commit a805fadc7a84306cbf1f390d0c5ff8c0512e30c0 Author: aggie Date: Thu Jun 25 00:57:39 2026 +0000 first ;3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a529fd4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +deploy-to-neocities.json diff --git a/_data/site.json b/_data/site.json new file mode 100644 index 0000000..493da50 --- /dev/null +++ b/_data/site.json @@ -0,0 +1,68 @@ +{ + "name": "Agnes the Alien", + "description": "Personal website and blog of Agnes the Alien.", + "url": "https://agnes.love", + "author": "Agnes the Alien", + "email": "alienhospitals@gmail.com", + "social": { + + "mastodon": "https://lesbian.alien.dentist/@alien" + + }, + "repo": { + "url": "https://treasurechest.alien.town/agnes/agnes-love", + "branch": "main" + }, + "bio": { + "short": "Agnes the Alien, a writer, artist, and hobbyist computerperson.", + "long": "I'm Agnes the Alien. I write about fandom, tech, disability and mental health, alterhumanity, and pretty much anything." + }, + "location": "Michigan, USA", + "timezone": "America/Detroit", + "newsletter": { + "enabled": true, + "provider": "buttondown", + "action": "https://buttondown.email/api/emails/embed-subscribe/agnesthealien", + "title": "Subscribe", + "description": "Subscribe to get new posts delivered directly to your email." + }, + "donate": { + "enabled": true, + "kofi": "agnesthealien", + "message": "If you like what I do and are interested in supporting me, that'd be cool." + }, + "analytics": { + "enabled": false, + "provider": "plausible", + "domain": "", + "siteId": "" + }, + "webmentions": { + "enabled": true, + "domain": "agnes.love" + }, + "webring": { + "enabled": false, + "url": "https://indieweb.org/webring" + }, + "lighthouse": { + "enabled": false, + "url": "https://pagespeed.web.dev/" + }, + "indieweb": { + "h_card": true, + "rel_me": true, + "microformats": true + }, + "sections": { + "notes": { "enabled": false, "title": "Notes", "path": "/notes/" }, + "journal": { "enabled": false, "title": "Journal", "path": "/journal/" }, + "poetry": { "enabled": true, "title": "Poetry and Writing", "path": "/poetry/" }, + "portfolio": { "enabled": false, "title": "Portfolio", "path": "/portfolio/" }, + "projects": { "enabled": true, "title": "Projects", "path": "/projects/" }, + "resume": { "enabled": false, "title": "Rรฉsumรฉ", "path": "/resume/" }, + "type": { "enabled": false, "title": "Type", "path": "/type/" }, + "links": { "enabled": true, "title": "Links", "path": "/links/" }, + "bookshelf": { "enabled": false, "title": "Bookshelf", "path": "/bookshelf/" } + } +} diff --git a/_data/tagColors.json b/_data/tagColors.json new file mode 100644 index 0000000..67906a6 --- /dev/null +++ b/_data/tagColors.json @@ -0,0 +1,22 @@ +{ + "intro": "#3b82f6", + "meta": "#8b5cf6", + "javascript": "#f59e0b", + "css": "#06b6d4", + "html": "#ef4444", + "eleventy": "#10b981", + "tailwind": "#06b6d4", + "tutorial": "#f97316", + "guide": "#84cc16", + "tips": "#eab308", + "review": "#6366f1", + "opinion": "#ec4899", + "personal": "#14b8a6", + "tech": "#6b7280", + "web": "#3b82f6", + "design": "#8b5cf6", + "accessibility": "#10b981", + "performance": "#f59e0b", + "seo": "#ef4444", + "indieweb": "#06b6d4" +} diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk new file mode 100644 index 0000000..da77a37 --- /dev/null +++ b/_includes/layouts/base.njk @@ -0,0 +1,345 @@ + + + + + + {% if title %} + {{ title }} โ€” {{ site.name }} + {% else %} + {{ site.name }} + {% endif %} + + + {# Canonical URL #} + {% if site.url %} + + {% endif %} + + {# Open Graph (Facebook, LinkedIn, etc.) #} + {% set ogTitle = title or site.name %} + {% set ogDescription = description or site.description %} + {% set ogUrl = (site.url and (site.url + (page.url or '/'))) or '' %} + {# Resolve image: allow per-page front matter `image` or default to /screenshot.png #} + {% set rawImage = image or '/screenshot.png' %} + {% if site.url %} + {% if rawImage | slice(0,4) == 'http' %} + {% set ogImage = rawImage %} + {% elseif rawImage | slice(0,1) == '/' %} + {% set ogImage = site.url + rawImage %} + {% else %} + {% set ogImage = site.url + '/' + rawImage %} + {% endif %} + {% else %} + {% set ogImage = rawImage %} + {% endif %} + + + {% if ogUrl %}{% endif %} + + + + + + {# Twitter Card #} + + {% if site.social and site.social.twitter %} + + + {% endif %} + + + + + + + + + {# Favicon and theme color #} + + + + + + + + + {# Syntax highlighting via Highlight.js CDN - vivid color scheme #} + + + + + + {% include "partials/analytics.njk" %} + + {# SEO: Structured Data (JSON-LD) #} + {% if site.url %} + + + {# Breadcrumbs: Home > Current #} + {% set isHome = (page.url or '/') == '/' %} + + + {# BlogPosting for content pages (#blog, #notes, #poetry, #journal) #} + {% set url = page.url or '/' %} + {% set isPostLike = (url | slice(0,6) == '/blog/' ) or (url | slice(0,7) == '/notes/' ) or (url | slice(0,8) == '/poetry/' ) or (url | slice(0,9) == '/journal/' ) %} + {% if isPostLike %} + + {% endif %} + {% endif %} + + + +
+
+ + {{ site.name }} + + + +
+ +
+ + +
+
+
+
+ + + +
+
+ {{ content | safe }} +
+
+ + + + + + + + + diff --git a/_includes/layouts/journal.njk b/_includes/layouts/journal.njk new file mode 100644 index 0000000..96c1a43 --- /dev/null +++ b/_includes/layouts/journal.njk @@ -0,0 +1,27 @@ +--- +layout: layouts/base.njk +--- +โ† Back to Journal + + + +
+
+

{{ title }}

+
+ + +
+
+
+ {{ content | safe }} +
+
diff --git a/_includes/layouts/note.njk b/_includes/layouts/note.njk new file mode 100644 index 0000000..acd0e8e --- /dev/null +++ b/_includes/layouts/note.njk @@ -0,0 +1,27 @@ +--- +layout: layouts/base.njk +--- +โ† Back to Notes + + + +
+
+

{{ title }}

+
+ + +
+
+
+ {{ content | safe }} +
+
diff --git a/_includes/layouts/poem.njk b/_includes/layouts/poem.njk new file mode 100644 index 0000000..cc406a5 --- /dev/null +++ b/_includes/layouts/poem.njk @@ -0,0 +1,27 @@ +--- +layout: layouts/base.njk +--- +โ† Back to Poetry + + + +
+
+

{{ title }}

+
+ + +
+
+
+ {{ content | safe }} +
+
diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk new file mode 100644 index 0000000..c719789 --- /dev/null +++ b/_includes/layouts/post.njk @@ -0,0 +1,103 @@ +--- +layout: layouts/base.njk +--- + + โ† Back to Blog + + + + +
+ {% if featuredImage %} + Featured image for {{ title }} + {% endif %} + +
+

{{ title }}

+ {% if subtitle %} +

{{ subtitle }}

+ {% endif %} +
+ Published on + by {{ author or site.author }} + โ€ข {{ content | readingTime }} min read +
+ +
+ +
+ {{ content | safe }} +
+ + {% if tags %} + + {% endif %} + +
+ {% include "partials/share-links.njk" %} +
+ +
+
+
+ {{ site.author }} +
+

{{ site.author }}

+

+ +
+
+
+
+ +
+ {% if site.bio.long %} +
+

About {{ site.author }}

+

+ {{ site.bio.long }} +

+
+ {% endif %} + {% if site.newsletter.enabled %} +
+

{{ site.newsletter.title }}

+

{{ site.newsletter.description }}

+
+ + +
+
+ {% endif %} +
+ + {% include "partials/related-posts.njk" %} + +
+

Responses

+
+
+
Loading webmentions...
+
+
+
+
diff --git a/_includes/partials/analytics.njk b/_includes/partials/analytics.njk new file mode 100644 index 0000000..7506861 --- /dev/null +++ b/_includes/partials/analytics.njk @@ -0,0 +1,29 @@ +{# +Analytics integration - Choose one: +1. Plausible Analytics (privacy-friendly) +2. Fathom Analytics (privacy-friendly) +3. Simple Analytics (privacy-friendly) + +To enable, uncomment one of the sections below and configure in site.json +#} + +{% if site.analytics and site.analytics.enabled %} + {% if site.analytics.provider == 'plausible' %} + + + {% elif site.analytics.provider == 'fathom' %} + + + {% elif site.analytics.provider == 'simple' %} + + + + {% endif %} + + {# + Privacy notice: Add this to your privacy policy + - We use privacy-friendly analytics that don't track personal information + - No cookies are stored + - Data is aggregated and anonymous + #} +{% endif %} diff --git a/_includes/partials/icons.njk b/_includes/partials/icons.njk new file mode 100644 index 0000000..6d47b75 --- /dev/null +++ b/_includes/partials/icons.njk @@ -0,0 +1,24 @@ +{% macro icon(name, class="w-4 h-4", title="") %} + {% set t = title or name %} + {% if name == 'github' %} + + {% elseif name == 'mastodon' %} + + {% elseif name == 'linkedin' %} + + {% elseif name == 'x' or name == 'twitter' %} + + {% elseif name == 'rss' %} + + {% elseif name == 'mail' %} + + {% elseif name == 'link' %} + + {% elseif name == 'copy' %} + + {% elseif name == 'share' %} + + {% else %} + + {% endif %} +{% endmacro %} diff --git a/_includes/partials/related-posts.njk b/_includes/partials/related-posts.njk new file mode 100644 index 0000000..f4e6dc6 --- /dev/null +++ b/_includes/partials/related-posts.njk @@ -0,0 +1,47 @@ +{% set relatedPosts = [] %} +{% if tags %} + {% for post in collections.posts %} + {% if post.url != page.url %} + {% set commonTags = 0 %} + {% for tag in tags %} + {% if post.data.tags and post.data.tags.includes(tag) %} + {% set commonTags = commonTags + 1 %} + {% endif %} + {% endfor %} + {% if commonTags > 0 %} + {% set relatedPosts = (relatedPosts.push({post: post, score: commonTags}), relatedPosts) %} + {% endif %} + {% endif %} + {% endfor %} +{% endif %} + +{% if relatedPosts.length > 0 %} + {% set sortedPosts = relatedPosts | sort(false, false, 'score') | reverse %} +
+

Related Posts

+
+ {% for item in sortedPosts | slice(0, 3) %} + {% set post = item.post %} +
+

+ {{ post.data.title }} +

+ +

+ {{ post.data.description or (post.templateContent | striptags | truncate(100)) }} +

+ {% if post.data.tags %} +
+ {% for tag in post.data.tags | slice(0, 2) %} + #{{ tag }} + {% endfor %} +
+ {% endif %} +
+ {% endfor %} +
+
+{% endif %} diff --git a/_includes/partials/share-links.njk b/_includes/partials/share-links.njk new file mode 100644 index 0000000..80385eb --- /dev/null +++ b/_includes/partials/share-links.njk @@ -0,0 +1,24 @@ +
+ Share: + {% from "partials/icons.njk" import icon %} + + {{ icon('x', 'w-4 h-4') }} Twitter + + + {{ icon('linkedin', 'w-4 h-4') }} LinkedIn + + + {{ icon('mastodon', 'w-4 h-4') }} Mastodon + + +
+ diff --git a/_includes/partials/webmentions.njk b/_includes/partials/webmentions.njk new file mode 100644 index 0000000..37f99d0 --- /dev/null +++ b/_includes/partials/webmentions.njk @@ -0,0 +1,59 @@ +{% if webmentions and webmentions.length > 0 %} +
+ {% for mention in webmentions %} +
+
+ {% if mention.author.photo %} + {{ mention.author.name }} + {% else %} +
+ {{ mention.author.name | first }} +
+ {% endif %} +
+
+ + {{ mention.author.name }} + + + {% if mention['wm-property'] == 'like-of' %} + liked this + {% elif mention['wm-property'] == 'repost-of' %} + reposted this + {% elif mention['wm-property'] == 'bookmark-of' %} + bookmarked this + {% elif mention['wm-property'] == 'mention-of' %} + mentioned this + {% else %} + replied + {% endif %} + + +
+ {% if mention.content and mention.content.text %} +
+ {{ mention.content.text | truncate(280) | safe }} +
+ {% endif %} + +
+
+
+ {% endfor %} +
+{% else %} +
+

No webmentions yet. Be the first to respond!

+

+ + Learn about webmentions + +

+
+{% endif %} diff --git a/_site/about/index.html b/_site/about/index.html new file mode 100644 index 0000000..232f7e4 --- /dev/null +++ b/_site/about/index.html @@ -0,0 +1,335 @@ + + + + + + + About โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+
+ Agnes the Alien +

Agnes the Alien

+

Your bio goes here. Describe yourself, your interests, and what you write about.

+ +

Your City

+

Your Country

+
+ +
+
+ + + + + + + + + diff --git a/_site/accessibility/index.html b/_site/accessibility/index.html new file mode 100644 index 0000000..5b75d8c --- /dev/null +++ b/_site/accessibility/index.html @@ -0,0 +1,299 @@ + + + + + + + Accessibility โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Accessibility

+

This site aims for WCAG 2.1 AA. Use the A11y menu in the header to adjust font size, contrast, and motion preferences. Preferences are saved in your browser.

+ +
+
+ + + + + + + + + diff --git a/_site/archive/index.html b/_site/archive/index.html new file mode 100644 index 0000000..61bc6f3 --- /dev/null +++ b/_site/archive/index.html @@ -0,0 +1,311 @@ + + + + + + + Archive โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Archive

+ +
+

A chronological archive of all posts, organized by year and month.

+
+ + + + + +
+

No posts found.

+
+ + +
+
+ + + + + + + + + diff --git a/_site/blogroll/index.html b/_site/blogroll/index.html new file mode 100644 index 0000000..2ac3f97 --- /dev/null +++ b/_site/blogroll/index.html @@ -0,0 +1,348 @@ + + + + + + + Blogroll โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Blogroll

+ +
+

Here are some blogs and websites I follow and recommend. This is a curated list of quality content creators in the web development, design, and IndieWeb communities.

+
+ +
+
+

Web Development

+
+
+

+ Example Blog +

+

Description of the blog and why you recommend it.

+
+ +
+
+ +
+

Design & UX

+
+
+

+ Design Blog +

+

Great insights on design and user experience.

+
+
+
+ +
+

IndieWeb & Personal Sites

+
+
+

+ Personal Site +

+

Excellent example of IndieWeb principles in action.

+
+
+
+
+ +
+

+ Want to be added? If you have a blog that fits these categories, feel free to + reach out and let me know! +

+
+ +
+
+ + + + + + + + + diff --git a/_site/bookshelf/index.html b/_site/bookshelf/index.html new file mode 100644 index 0000000..fe8df7d --- /dev/null +++ b/_site/bookshelf/index.html @@ -0,0 +1,338 @@ + + + + + + + Bookshelf โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Bookshelf

+

A living reading list. Track what you're reading, want to read, and your notes/reviews.

+ +
+
+

Reading

+
    +
  • + Designing for Accessibility +
    Notes: practical patterns for forms and focus
    +
  • +
  • + The Pragmatic Programmer +
    Notes: small steps, continuous improvement
    +
  • +
+
+ +
+

Finished

+
    +
  • + Atomic Habits +
    Takeaway: environment design beats willpower
    +
  • +
  • + Refactoring UI +
    Takeaway: spacing & contrast are the 80/20
    +
  • +
+
+ +
+

Want to Read

+
    +
  • Inclusive Components
  • +
  • Every Layout
  • +
+
+
+ +
+
+ + + + + + + + + diff --git a/_site/categories/index.html b/_site/categories/index.html new file mode 100644 index 0000000..c79948f --- /dev/null +++ b/_site/categories/index.html @@ -0,0 +1,302 @@ + + + + + + + Categories โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Categories

+ + +

No categories yet.

+ + +
+
+ + + + + + + + + diff --git a/_site/contact/index.html b/_site/contact/index.html new file mode 100644 index 0000000..1c2cfe1 --- /dev/null +++ b/_site/contact/index.html @@ -0,0 +1,344 @@ + + + + + + + Contact โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Get in Touch

+ +

I'd love to hear from you! Whether you have questions, feedback, or just want to say hello, + feel free to reach out through any of the channels below.

+ +
+
+

Get in Touch

+ +
+ +
+

Quick Message

+
+
+ + +
+
+ + +
+
+ + +
+ +
+

+ Note: Configure with Netlify Forms or similar service for functionality. +

+
+
+ +
+
+ + + + + + + + + diff --git a/_site/donate/index.html b/_site/donate/index.html new file mode 100644 index 0000000..e12e8c8 --- /dev/null +++ b/_site/donate/index.html @@ -0,0 +1,334 @@ + + + + + + + Support My Work โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Support My Work

+ +
+ +

If you like what I do and are interested in supporting me, that'd be cool.

+ + + +

One-time Support

+

Buy me a coffee or make a one-time contribution to help fuel my writing:

+ + + + + + +

Other Ways to Help

+
    +
  • Share my posts with others who might find them valuable
  • +
  • Subscribe to my newsletter to stay updated on new content
  • +
  • Follow me on social media and engage with my content
  • +
  • Send feedback via email or webmentions
  • +
+ +

+ Every contribution, no matter how small, helps me continue creating thoughtful content + and maintaining this blog. Thank you for your support! ๐Ÿ™ +

+
+ +
+
+ + + + + + + + + diff --git a/_site/index.html b/_site/index.html new file mode 100644 index 0000000..86bf7fe --- /dev/null +++ b/_site/index.html @@ -0,0 +1,369 @@ + + + + + + + Indieweb Starter Blog โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+
+ +
+

Agnes the Alien

+

Personal website and blog of Agnes the Alien.

+ + +
+

+ Welcome to my corner of the independent web! This is where I share thoughts, discoveries, and conversations + away from the noise of social media algorithms. +

+ +
+ + ๐ŸŒฑ IndieWeb + + + ๐Ÿ“ก RSS Ready + + + ๐Ÿ”’ Privacy First + + + โ™ฟ Accessible + +
+
+ + +
+ + +
+

+ โœ๏ธ Recent Posts +

+ + + + + + + +
+

No posts yet!

+

This is where thoughtful writing will appear. Stay tuned! ๐Ÿ“

+
+ +
+ + + +
+ +
+
+ + + + + + + + + diff --git a/_site/links/index.html b/_site/links/index.html new file mode 100644 index 0000000..99e2f8e --- /dev/null +++ b/_site/links/index.html @@ -0,0 +1,329 @@ + + + + + + + Links โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Links

+

A curated index of sites, references, and tools. Replace these with your own favorites or wire up a bookmarks feed.

+ +
+
+

Web Development

+
    +
  • Eleventy โ€” Static site generator with a small, flexible core.
  • +
  • Playwright โ€” Reliable endโ€‘toโ€‘end testing across browsers.
  • +
  • web.dev โ€” Guides on performance and modern web APIs.
  • +
+
+ +
+

IndieWeb & Publishing

+ +
+ +
+

Design & Accessibility

+ +
+
+ +
+
+ + + + + + + + + diff --git a/_site/now/index.html b/_site/now/index.html new file mode 100644 index 0000000..a33eba7 --- /dev/null +++ b/_site/now/index.html @@ -0,0 +1,317 @@ + + + + + + + Now โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

What I'm Doing Now

+ +
+

This is a /now page, inspired by Derek Sivers. It's a snapshot of what I'm focused on right now.

+ +

Current Focus

+
    +
  • Add your current projects
  • +
  • What you're learning
  • +
  • Books you're reading
  • +
  • Goals you're working toward
  • +
+ +

Location

+

Currently based in: Your Location

+ +

+ Last updated: +

+
+ +
+
+ + + + + + + + + diff --git a/_site/portfolio/index.html b/_site/portfolio/index.html new file mode 100644 index 0000000..9714f52 --- /dev/null +++ b/_site/portfolio/index.html @@ -0,0 +1,322 @@ + + + + + + + Portfolio โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Portfolio

+

Showcase selected work. Replace with your own projects and case studies.

+ +
+
+

Static Blog Template

+

An Eleventy starter focused on accessibility, IndieWeb features, and reliable E2E tests.

+
    +
  • Accessible navigation and skip links
  • +
  • Open Graph/Twitter meta defaults
  • +
  • Playwright tests (responsive, a11y flows, search)
  • +
+
+ +
+

Design System Pages

+

A living style guide to keep typography and components consistent.

+
+ +
+

Interested in working together?

+

Add your services and contact details here.

+
+
+ +
+
+ + + + + + + + + diff --git a/_site/projects/index.html b/_site/projects/index.html new file mode 100644 index 0000000..c215026 --- /dev/null +++ b/_site/projects/index.html @@ -0,0 +1,317 @@ + + + + + + + Projects โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Projects

+

Open-source and personal experiments. Replace with your own projects or migrate to a projects collection.

+ +
    +
  • +

    Eleventy Blog Starter

    +

    Accessible, IndieWeb-friendly, and tested with Playwright.

    +
    + eleventy + a11y + testing +
    +
  • + +
  • +

    Minimal Style Guide

    +

    A living page to document typography and components.

    +
  • +
+ +
+
+ + + + + + + + + diff --git a/_site/resume/index.html b/_site/resume/index.html new file mode 100644 index 0000000..4a87172 --- /dev/null +++ b/_site/resume/index.html @@ -0,0 +1,337 @@ + + + + + + + Rรฉsumรฉ โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Rรฉsumรฉ

+

A template CV you can adapt. Replace section content with your details or link to a PDF.

+ +
+ Download PDF + Add your static PDF at src/assets/ and update this link. +
+ +
+

Summary

+

Front-end oriented web developer focused on accessibility, performance, and maintainable static sites. Comfortable with modern tooling and progressive enhancement.

+ +

Experience

+

Senior Web Developer ยท Company Name

+

2023 โ€” Present

+
    +
  • Built static-first sites with Eleventy and automated deployments.
  • +
  • Established a11y testing and CI checks.
  • +
  • Collaborated with design on a living style guide.
  • +
+ +

Front-end Engineer ยท Organization

+

2020 โ€” 2023

+
    +
  • Implemented component libraries with semantic HTML and utility CSS.
  • +
  • Optimized web vitals via preloading and code-splitting.
  • +
+ +

Skills

+
    +
  • HTML, CSS (Tailwind), JavaScript
  • +
  • Eleventy, Nunjucks, Markdown
  • +
  • Accessibility, Testing (Playwright)
  • +
  • SEO, Open Graph, microformats2
  • +
+ +

Education

+

Degree / Program โ€” School Name

+
+ +
+
+ + + + + + + + + diff --git a/_site/search.json b/_site/search.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/_site/search.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/_site/search/index.html b/_site/search/index.html new file mode 100644 index 0000000..3aa71f3 --- /dev/null +++ b/_site/search/index.html @@ -0,0 +1,551 @@ + + + + + + + Search Results โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+
+

+ ๐Ÿ” Search Results +

+ + + + + + + + + + + + + + +
+
+
๐Ÿ”
+

Search the site

+

+ Find posts, pages, and content across the entire site. +

+
+ + +
+
+

๐Ÿ“ Recent Posts

+ +

No posts yet.

+ +
+ +
+

๐Ÿท๏ธ Popular Tags

+ +

No tags yet.

+ +
+
+ + +
+

๐Ÿ’ก Search Tips

+
    +
  • โ€ข Use specific keywords for better results
  • +
  • โ€ข Search works across post titles, content, and tags
  • +
  • โ€ข Try different variations of your search terms
  • +
  • โ€ข Browse by tags or the archive for discovery
  • +
+
+
+
+ + + +
+
+ + + + + + + + + diff --git a/_site/sitemap/index.html b/_site/sitemap/index.html new file mode 100644 index 0000000..2087391 --- /dev/null +++ b/_site/sitemap/index.html @@ -0,0 +1,398 @@ + + + + + + + Site Directory โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+
+

+ ๐Ÿ—บ๏ธ Site Directory +

+

+ A complete map of everything on this site. Explore and discover! +

+ +
+ + + + + + + + + + + + + + + + +
+

๐Ÿ“ Recent Posts

+ + + + + + + + +

No posts yet. Start writing!

+ +
+ + +
+

๐ŸŽช Fun Stuff

+
    +
  • ๐ŸŽฎ Try the Konami code
  • +
  • ๐Ÿ–ฑ๏ธ Click the logo 7 times
  • +
  • โŒจ๏ธ Type "blog" anywhere
  • +
  • ๐ŸŒ™ Toggle dark mode
  • +
+
+
+ +
+

๐Ÿงญ Lost?

+

+ This site is built with Eleventy + and follows IndieWeb principles. + It's designed to be a calm, thoughtful space for writing and connecting. +

+
+
+ +
+
+ + + + + + + + + diff --git a/_site/style/index.html b/_site/style/index.html new file mode 100644 index 0000000..5114e8b --- /dev/null +++ b/_site/style/index.html @@ -0,0 +1,397 @@ + + + + + + + Style Guide โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Style Guide

+ +
+
+

Typography

+
+
+

Heading 1

+

Heading 2

+

Heading 3

+

Heading 4

+
+

This is regular paragraph text. It should be readable and comfortable for extended reading sessions.

+

This is smaller text used for metadata and secondary information.

+
+
+ +
+

Colors

+
+
+
+

Primary Blue

+
+
+
+

Gray

+
+
+
+

Success Green

+
+
+
+

Error Red

+
+
+
+ +
+

Components

+ +
+
+

Buttons

+
+ + +
+
+ +
+

Tags

+
+ #example + #tag + #demo +
+
+ +
+

Cards

+
+

Card Title

+

This is an example card component with some content.

+
+
+
+
+ +
+

Prose Styles

+
+

This section demonstrates the prose styling used for blog content.

+ +
+

This is a blockquote. It should stand out from regular text and be easily identifiable.

+
+ +
    +
  • Unordered list item one
  • +
  • Unordered list item two
  • +
  • Unordered list item three
  • +
+ +
    +
  1. Ordered list item one
  2. +
  3. Ordered list item two
  4. +
  5. Ordered list item three
  6. +
+ +
// Code block example
+function example() {
+  return "Hello, world!";
+}
+ +

Here's some text with inline code and a link example.

+
+
+
+ +
+
+ + + + + + + + + diff --git a/_site/tags/index.html b/_site/tags/index.html new file mode 100644 index 0000000..5c5b583 --- /dev/null +++ b/_site/tags/index.html @@ -0,0 +1,302 @@ + + + + + + + Tags โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

Tags

+ + +

No tags yet.

+ + +
+
+ + + + + + + + + diff --git a/_site/type/index.html b/_site/type/index.html new file mode 100644 index 0000000..96c8859 --- /dev/null +++ b/_site/type/index.html @@ -0,0 +1,358 @@ + + + + + + + Type โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+ +

Type Scale & Components

+

A living typography page for quick visual checks. Tweak sizes in tailwind.config.cjs or override via utilities.

+ +
+

Fonts Used

+

This template uses the system UI font stack by default for speed and readability, and a system monospace stack for code.

+
    +
  • Body/UI: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
  • +
  • Monospace: the browser's default monospace stack via Tailwind's font-mono utility
  • +
+

Defined in src/assets/css/tailwind.css:

+
/* src/assets/css/tailwind.css */
+body {
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
+.system-fonts {
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
+}
+
+

To change fonts, you can:

+
    +
  1. Swap the body { font-family: ... } in src/assets/css/tailwind.css.
  2. +
  3. Optionally add fontFamily under theme.extend in tailwind.config.cjs and use Tailwind utilities (e.g., font-sans, font-mono).
  4. +
+
+ +
+

Heading 1

+

Heading 2

+

Heading 3

+

Heading 4

+

+ Body copy with bold and emphasis. Links look like + this inline link. Small text appears as + supporting detail. +

+ +

Lists

+
    +
  • Unordered list item
  • +
  • With sufficient spacing
  • +
+
    +
  1. Ordered list item
  2. +
  3. Use lists for steps
  4. +
+ +

Blockquote

+
+ Ship small improvements often. The garden grows one commit at a time. +
+ +

Code

+
// Syntax highlighting is provided client-side via Highlight.js
+function greet(name) {
+  return `Hello, ${name}!`;
+}
+console.log(greet('world'));
+
+
+ +
+
+ + + + + + + + + diff --git a/_site/uses/index.html b/_site/uses/index.html new file mode 100644 index 0000000..2011a73 --- /dev/null +++ b/_site/uses/index.html @@ -0,0 +1,334 @@ + + + + + + + Uses โ€” Agnes the Alien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Agnes the Alien + +
+ +
+ + +
+
+
+
+ + + +
+
+

What I Use

+ +
+
+

Development

+
    +
  • Editor: Your preferred code editor
  • +
  • Terminal: Your terminal setup
  • +
  • Browser: Your development browser
  • +
  • Version Control: Git + GitHub
  • +
+
+ +
+

Hardware

+
    +
  • Computer: Your computer specs
  • +
  • Monitor: Your monitor setup
  • +
  • Keyboard: Your keyboard
  • +
  • Mouse: Your mouse/trackpad
  • +
+
+ +
+

Software

+
    +
  • OS: Your operating system
  • +
  • Notes: Your note-taking app
  • +
  • Design: Your design tools
  • +
  • Productivity: Your productivity apps
  • +
+
+
+ +

+ This page is inspired by uses.tech +

+ +
+
+ + + + + + + + + diff --git a/about.njk b/about.njk new file mode 100755 index 0000000..e2dafe2 --- /dev/null +++ b/about.njk @@ -0,0 +1,45 @@ +--- +layout: layouts/base.njk +permalink: "/about/" +title: About +--- +
+ {{ site.author }} +

{{ site.author }}

+

+My site button, a very small drawing of myself (a white feminine individual with pink and green hair) that says Agnes on the side.
+Fediverse | Ko-Fi | Bluesky | AO3 | Dreamwidth
+


+ Hi! I'm Agnes the Alien (it/zhe). I also go by Holiday and a bunch of other names sometimes too :-P I'm a disabled nonbinary extraterrestrial lesbian and I live in the Midwestern USA, unfortunately. I'm not very good at writing about myself, but I'll try.

+ The main love of my life is creative writing. I've been writing since I was about four years old and I learned how to open Microsoft Word on our dinosaur desktop PC. I write pretty much everything - poetry, fanfiction, short stories, video games, scripts, things that can't be described very well. I love to write horror, sci-fi, and sci-fi horror, and I love to write about dissociation and bad people and aliens and healing in nontraditional ways. I just love writing.

Because of that a lot of my internet activity is focused around writing, usually fanfiction. I run a fork of OTW-Archive, the software behind Archive of Our Own, the largest fanfiction site in the world (and mine has status updates!), dedicated to fan and original works centered around F/F, NB/F and NB/NB sapphic relationships. I run a lot of fandom events on Dreamwidth, like Rarest of Rarepairs and (as of 2025) Sapphic Summer. I also participate in a lot of fandom events.

+I'm Quaker and currently in my freshman year of college studying theology. I'm about to start taking, for this upcoming semester: African American Literature, Intro to Ethics, and Intro to World Religions. I was originally going to be an English major, but. I think I should keep writing a hobby. +

+I have three cats, a dog, and a pet Goffin Cockatoo named Saira who I adore with my entire soul. I have a serious passion for the natural world and animals (I have a devil's hole pupfish/white spotted pufferfish tattoo on my chest...) I'm in love with the world and with love and I try to be the best and most pleasant person I can be.

+I'm a bit "cringe", but I don't care; I'm alterhuman and semi-fictosexual, and these things are major aspects of my identity! I'm an alien and that is very important to me. My fictional others are Caleb Mir from Starfleet Academy and the Negative Spirit from Doom Patrol TV, among other less serious beloveds. If you'd ever like to talk about it, hit me up at the contact information provided above. I'm very open about my identity and the things that make me who I am, so if you're respectfully curious, just ask!! +

+Iโ€™m multiply disabledโ€“physically, intellectually, mentally. I have dissociative identity disorder. These aspects of me impact pretty much every area of my life; outside of creativity and computer stuff, I really donโ€™t have the ability to do much at all, and am pretty limited. So, Iโ€™m housebound and often bedbound, and I talk about this a lot and how it shapes my relationship with the world, internet, technology, and fandom.

+Anyway, that's me. It's nice to meet you. +

+ +

Michigan

+

USA

+
diff --git a/accessibility.njk b/accessibility.njk new file mode 100755 index 0000000..7549983 --- /dev/null +++ b/accessibility.njk @@ -0,0 +1,7 @@ +--- +layout: layouts/base.njk +permalink: "/accessibility/" +title: Accessibility +--- +

Accessibility

+

This site aims for WCAG 2.1 AA. Use the A11y menu in the header to adjust font size, contrast, and motion preferences. Preferences are saved in your browser.

diff --git a/archive.njk b/archive.njk new file mode 100755 index 0000000..2e27f8c --- /dev/null +++ b/archive.njk @@ -0,0 +1,62 @@ +--- +layout: layouts/base.njk +permalink: "/archive/" +title: Archive +--- +

Archive

+ +
+

A chronological archive of all posts, organized by year and month.

+
+ +{% set postsByYear = collections.posts | groupby("date.getFullYear()") %} +{% for year, posts in postsByYear %} +
+

{{ year }}

+ + {% set postsByMonth = posts | groupby("date.getMonth()") %} + {% for month, monthPosts in postsByMonth %} +
+

+ {{ monthPosts[0].date | readableDate("MMMM") }} +

+ +
+ {% for post in monthPosts %} +
+ +
+

+ + {{ post.data.title }} + +

+ {% if post.data.description %} +

{{ post.data.description }}

+ {% endif %} + {% if post.data.tags %} +
+ {% for tag in post.data.tags %} + + {{ tag }} + + {% endfor %} +
+ {% endif %} +
+
+ {% endfor %} +
+
+ {% endfor %} +
+{% endfor %} + +{% if collections.posts.length == 0 %} +
+

No posts found.

+
+{% endif %} diff --git a/assets/apple-touch-icon.png b/assets/apple-touch-icon.png new file mode 100755 index 0000000..79c99b2 Binary files /dev/null and b/assets/apple-touch-icon.png differ diff --git a/assets/css/build.css b/assets/css/build.css new file mode 100755 index 0000000..5e25ec5 --- /dev/null +++ b/assets/css/build.css @@ -0,0 +1 @@ +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}a{cursor:pointer;text-decoration:none}a:focus-visible{outline:2px solid #7c3aed;outline-offset:2px;border-radius:2px}a:hover{text-decoration:underline;text-underline-offset:2px}a:active{text-decoration-thickness:2px}a:hover:not(.nav-item){color:var(--accent);transition:color .15s ease-in-out}.dark a:hover:not(.nav-item){color:var(--accent-light)}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.prose,.prose h1,.prose h2,.prose h3,.prose h4,.prose h5,.prose h6{color:var(--text)}.prose a{color:#2563eb;text-decoration:underline;text-underline-offset:2px;text-decoration-thickness:1.5px;transition:color .15s ease-in-out}.prose a:hover{color:#1d4ed8}.prose a:active{text-decoration-thickness:2px}.prose a:focus-visible{outline:2px solid #7c3aed;outline-offset:2px;border-radius:2px}.dark .prose a{color:#60a5fa}.dark .prose a:hover{color:#93c5fd}.dark .prose a:focus-visible{outline-color:#a855f7}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.static{position:static}.absolute{position:absolute}.relative{position:relative}.right-0{right:0}.mx-auto{margin-left:auto;margin-right:auto}.my-6{margin-top:1.5rem;margin-bottom:1.5rem}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-1{margin-top:.25rem}.mt-12{margin-top:3rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-0\.5{height:.125rem}.h-10{height:2.5rem}.h-16{height:4rem}.h-24{height:6rem}.h-4{height:1rem}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-24{width:6rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-64{width:16rem}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[4rem\]{min-width:4rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.flex-1{flex:1 1 0%}.animate-\[marquee_18s_linear_infinite\]{animation:marquee 18s linear infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-12>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(3rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(3rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.scroll-smooth{scroll-behavior:smooth}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.border-indigo-200{--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity,1))}.border-orange-200{--tw-border-opacity:1;border-color:rgb(254 215 170/var(--tw-border-opacity,1))}.border-pink-200{--tw-border-opacity:1;border-color:rgb(251 207 232/var(--tw-border-opacity,1))}.border-purple-200{--tw-border-opacity:1;border-color:rgb(233 213 255/var(--tw-border-opacity,1))}.border-purple-600{--tw-border-opacity:1;border-color:rgb(147 51 234/var(--tw-border-opacity,1))}.border-teal-200{--tw-border-opacity:1;border-color:rgb(153 246 228/var(--tw-border-opacity,1))}.bg-\[var\(--bg\)\]{background-color:var(--bg)}.bg-\[var\(--surface\)\]{background-color:var(--surface)}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity,1))}.bg-orange-100{--tw-bg-opacity:1;background-color:rgb(255 237 213/var(--tw-bg-opacity,1))}.bg-pink-600{--tw-bg-opacity:1;background-color:rgb(219 39 119/var(--tw-bg-opacity,1))}.bg-purple-100{--tw-bg-opacity:1;background-color:rgb(243 232 255/var(--tw-bg-opacity,1))}.bg-purple-50{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity,1))}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity,1))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-purple-100{--tw-gradient-from:#f3e8ff var(--tw-gradient-from-position);--tw-gradient-to:rgba(243,232,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-pink-100{--tw-gradient-to:#fce7f3 var(--tw-gradient-to-position)}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pl-5{padding-left:1.25rem}.pl-6{padding-left:1.5rem}.pt-6{padding-top:1.5rem}.pt-8{padding-top:2rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-6xl{font-size:3.75rem;line-height:1}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wide{letter-spacing:.025em}.text-\[var\(--text\)\]{color:var(--text)}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.text-blue-800{--tw-text-opacity:1;color:rgb(30 64 175/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-green-700{--tw-text-opacity:1;color:rgb(21 128 61/var(--tw-text-opacity,1))}.text-green-800{--tw-text-opacity:1;color:rgb(22 101 52/var(--tw-text-opacity,1))}.text-indigo-700{--tw-text-opacity:1;color:rgb(67 56 202/var(--tw-text-opacity,1))}.text-orange-700{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity,1))}.text-pink-700{--tw-text-opacity:1;color:rgb(190 24 93/var(--tw-text-opacity,1))}.text-purple-600{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.text-purple-700{--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.text-purple-800{--tw-text-opacity:1;color:rgb(107 33 168/var(--tw-text-opacity,1))}.text-teal-700{--tw-text-opacity:1;color:rgb(15 118 110/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes marquee{0%{transform:translateX(100%)}to{transform:translateX(-100%)}}.currently{float:right;height:190px;width:190px;overflow:scroll;position:absolute}.webring{margin:0 auto;width:400px;height:220px;border:1px solid #000;overflow:scroll}.prose{max-width:none;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose p{margin-bottom:1.5rem;line-height:1.625}.prose h1{margin-bottom:1.5rem;margin-top:2rem;font-size:1.875rem;line-height:2.25rem;font-weight:700;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h1:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose h2{margin-bottom:1rem;margin-top:2rem;font-size:1.5rem;line-height:2rem;font-weight:700;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h2:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose h3{margin-bottom:.75rem;margin-top:1.5rem;font-size:1.25rem;line-height:1.75rem;font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h3:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose h4{margin-bottom:.5rem;margin-top:1rem;font-size:1.125rem;line-height:1.75rem;font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h4:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose h5{margin-bottom:.5rem;margin-top:1rem;font-size:1rem;line-height:1.5rem;font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h5:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose h6{margin-bottom:.5rem;margin-top:1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose h6:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose ol,.prose ul{margin-bottom:1.5rem;padding-left:1.5rem}.prose li{margin-bottom:.5rem}.prose ul li{list-style-type:disc}.prose ol li{list-style-type:decimal}.prose blockquote{margin-bottom:1.5rem;border-left-width:4px;--tw-border-opacity:1;border-color:rgb(168 85 247/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1));padding-top:.5rem;padding-bottom:.5rem;padding-left:1.5rem;font-style:italic;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.prose blockquote:is(.dark *){background-color:rgba(31,41,55,.5);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.prose code{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1));padding:.25rem .5rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.prose code:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.prose pre{margin-bottom:1.5rem;overflow-x:auto;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1));padding:1rem;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose pre:is(.dark *){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose pre code{background-color:transparent;padding:0;color:inherit}.prose code.hljs,.prose pre .hljs,.prose pre code.hljs{background:transparent!important;color:inherit}#hamburger .bar-1,#hamburger .bar-3{transition:transform .2s ease}#hamburger .bar-2{transition:opacity .15s ease}#hamburger.open .bar-1{transform:translateY(6px) rotate(45deg)}#hamburger.open .bar-2{opacity:0}#hamburger.open .bar-3{transform:translateY(-6px) rotate(-45deg)}.prose a{overflow-wrap:anywhere;word-break:break-word;white-space:normal}.prose img{margin-bottom:1.5rem;border-radius:.5rem;--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.prose table{margin-bottom:1.5rem;width:100%;border-collapse:collapse}.prose th{border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1));padding:.5rem 1rem;text-align:left;font-weight:600}.prose th:is(.dark *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.prose td{border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1));padding:.5rem 1rem}.prose td:is(.dark *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.prose hr{margin-top:2rem;margin-bottom:2rem;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.prose hr:is(.dark *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.prose strong{font-weight:700;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.prose strong:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.prose em{font-style:italic}.prose del{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1));text-decoration-line:line-through}.prose del:is(.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.prose .header-anchor{margin-left:.5rem;--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1));text-decoration-line:none;opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.prose .header-anchor:hover{--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.prose .header-anchor:is(.dark *){--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.prose .header-anchor:hover:is(.dark *){--tw-text-opacity:1;color:rgb(233 213 255/var(--tw-text-opacity,1))}.prose h1:hover .header-anchor,.prose h2:hover .header-anchor,.prose h3:hover .header-anchor,.prose h4:hover .header-anchor{opacity:1}:root{--bg:#dcfcf4;--text:#1a1625;--surface:#f7f2fa;--accent:#ffd1f0;--accent-light:#ffd1f0;--border:hotpink}.dark{--bg:#0f0a1a;--text:#f1e8ff;--surface:#1a0f2e;--accent:#a855f7;--accent-light:#c084fc;--border:#4c1d95}#progress-bar{position:fixed;top:0;left:0;height:3px;background:linear-gradient(90deg,#7c3aed,#ec4899,#f59e0b);z-index:9999;transition:width .3s ease}.nav-item{color:inherit}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.float-animation{animation:float 3s ease-in-out infinite}.system-fonts{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif}html{scroll-behavior:smooth;overflow-y:scroll;width:100vw;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;line-height:1.6}.last\:border-b-0:last-child{border-bottom-width:0}.hover\:bg-blue-100:hover{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.hover\:bg-blue-200:hover{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.hover\:bg-gray-50:hover{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.hover\:bg-gray-900:hover{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.hover\:bg-green-200:hover{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.hover\:bg-purple-100:hover{--tw-bg-opacity:1;background-color:rgb(243 232 255/var(--tw-bg-opacity,1))}.hover\:bg-purple-200:hover{--tw-bg-opacity:1;background-color:rgb(233 213 255/var(--tw-bg-opacity,1))}.hover\:bg-purple-50:hover{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity,1))}.hover\:bg-purple-700:hover{--tw-bg-opacity:1;background-color:rgb(126 34 206/var(--tw-bg-opacity,1))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.hover\:text-blue-700:hover{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.hover\:text-blue-800:hover{--tw-text-opacity:1;color:rgb(30 64 175/var(--tw-text-opacity,1))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.hover\:text-green-600:hover{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.hover\:text-orange-600:hover{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.hover\:text-pink-600:hover{--tw-text-opacity:1;color:rgb(219 39 119/var(--tw-text-opacity,1))}.hover\:text-purple-600:hover{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.hover\:text-purple-800:hover{--tw-text-opacity:1;color:rgb(107 33 168/var(--tw-text-opacity,1))}.hover\:text-teal-600:hover{--tw-text-opacity:1;color:rgb(13 148 136/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.focus\:ring-purple-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(168 85 247/var(--tw-ring-opacity,1))}.dark\:border-blue-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(30 64 175/var(--tw-border-opacity,1))}.dark\:border-gray-600:is(.dark *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.dark\:border-gray-700:is(.dark *){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.dark\:border-green-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(22 101 52/var(--tw-border-opacity,1))}.dark\:border-indigo-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(55 48 163/var(--tw-border-opacity,1))}.dark\:border-orange-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(154 52 18/var(--tw-border-opacity,1))}.dark\:border-pink-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(157 23 77/var(--tw-border-opacity,1))}.dark\:border-purple-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(107 33 168/var(--tw-border-opacity,1))}.dark\:border-teal-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(17 94 89/var(--tw-border-opacity,1))}.dark\:bg-blue-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity,1))}.dark\:bg-blue-900\/20:is(.dark *){background-color:rgba(30,58,138,.2)}.dark\:bg-blue-900\/30:is(.dark *){background-color:rgba(30,58,138,.3)}.dark\:bg-gray-200:is(.dark *){--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.dark\:bg-gray-600:is(.dark *){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:bg-gray-800\/50:is(.dark *){background-color:rgba(31,41,55,.5)}.dark\:bg-green-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(20 83 45/var(--tw-bg-opacity,1))}.dark\:bg-green-900\/20:is(.dark *){background-color:rgba(20,83,45,.2)}.dark\:bg-green-900\/30:is(.dark *){background-color:rgba(20,83,45,.3)}.dark\:bg-orange-900\/30:is(.dark *){background-color:rgba(124,45,18,.3)}.dark\:bg-purple-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(88 28 135/var(--tw-bg-opacity,1))}.dark\:bg-purple-900\/20:is(.dark *){background-color:rgba(88,28,135,.2)}.dark\:bg-purple-900\/30:is(.dark *){background-color:rgba(88,28,135,.3)}.dark\:bg-yellow-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(133 77 14/var(--tw-bg-opacity,1))}.dark\:from-purple-900\/20:is(.dark *){--tw-gradient-from:rgba(88,28,135,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(88,28,135,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.dark\:to-pink-900\/20:is(.dark *){--tw-gradient-to:rgba(131,24,67,.2) var(--tw-gradient-to-position)}.dark\:text-blue-200:is(.dark *){--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.dark\:text-blue-300:is(.dark *){--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.dark\:text-blue-400:is(.dark *){--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.dark\:text-gray-100:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.dark\:text-green-200:is(.dark *){--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.dark\:text-green-300:is(.dark *){--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.dark\:text-indigo-300:is(.dark *){--tw-text-opacity:1;color:rgb(165 180 252/var(--tw-text-opacity,1))}.dark\:text-orange-200:is(.dark *){--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.dark\:text-orange-300:is(.dark *){--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.dark\:text-pink-300:is(.dark *){--tw-text-opacity:1;color:rgb(249 168 212/var(--tw-text-opacity,1))}.dark\:text-purple-200:is(.dark *){--tw-text-opacity:1;color:rgb(233 213 255/var(--tw-text-opacity,1))}.dark\:text-purple-300:is(.dark *){--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.dark\:text-teal-300:is(.dark *){--tw-text-opacity:1;color:rgb(94 234 212/var(--tw-text-opacity,1))}.dark\:hover\:bg-blue-900\/30:hover:is(.dark *){background-color:rgba(30,58,138,.3)}.dark\:hover\:bg-blue-900\/50:hover:is(.dark *){background-color:rgba(30,58,138,.5)}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:hover\:bg-gray-800:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:hover\:bg-green-900\/30:hover:is(.dark *){background-color:rgba(20,83,45,.3)}.dark\:hover\:bg-green-900\/50:hover:is(.dark *){background-color:rgba(20,83,45,.5)}.dark\:hover\:bg-purple-900\/20:hover:is(.dark *){background-color:rgba(88,28,135,.2)}.dark\:hover\:bg-purple-900\/30:hover:is(.dark *){background-color:rgba(88,28,135,.3)}.dark\:hover\:bg-purple-900\/50:hover:is(.dark *){background-color:rgba(88,28,135,.5)}.dark\:hover\:text-blue-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.dark\:hover\:text-gray-200:hover:is(.dark *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.dark\:hover\:text-green-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.dark\:hover\:text-orange-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.dark\:hover\:text-pink-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(244 114 182/var(--tw-text-opacity,1))}.dark\:hover\:text-purple-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.dark\:hover\:text-teal-400:hover:is(.dark *){--tw-text-opacity:1;color:rgb(45 212 191/var(--tw-text-opacity,1))}@media (min-width:640px){.sm\:block{display:block}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}}@media (min-width:768px){.md\:col-span-2{grid-column:span 2/span 2}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.5rem*var(--tw-space-x-reverse));margin-left:calc(1.5rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}} \ No newline at end of file diff --git a/assets/css/tailwind.css b/assets/css/tailwind.css new file mode 100755 index 0000000..a4b0a3e --- /dev/null +++ b/assets/css/tailwind.css @@ -0,0 +1,286 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; +@keyframes marquee { + 0% { transform: translateX(100%); } + 100% { transform: translateX(-100%); } +} + +.currently { +float: right; +height: 190px; +width: 190px; +overflow: scroll; +position: absolute;} +.webring { +margin: 0 auto; +width: 400px; +height: 220px; +border: 1px #000 solid; +overflow: scroll; +} +/* Blog post typography styles */ +.prose { + @apply max-w-none text-gray-900 dark:text-gray-100; +} + +.prose p { + @apply mb-6 leading-relaxed; +} + +.prose h1 { + @apply text-3xl font-bold mb-6 mt-8 text-gray-900 dark:text-gray-100; +} + +.prose h2 { + @apply text-2xl font-bold mb-4 mt-8 text-gray-900 dark:text-gray-100; +} + +.prose h3 { + @apply text-xl font-semibold mb-3 mt-6 text-gray-900 dark:text-gray-100; +} + +.prose h4 { + @apply text-lg font-semibold mb-2 mt-4 text-gray-900 dark:text-gray-100; +} + +.prose h5 { + @apply text-base font-semibold mb-2 mt-4 text-gray-900 dark:text-gray-100; +} + +.prose h6 { + @apply text-sm font-semibold mb-2 mt-4 text-gray-900 dark:text-gray-100; +} + +.prose ul { + @apply mb-6 pl-6; +} + +.prose ol { + @apply mb-6 pl-6; +} + +.prose li { + @apply mb-2; +} + +.prose ul li { + @apply list-disc; +} + +.prose ol li { + @apply list-decimal; +} + +.prose blockquote { + @apply border-l-4 border-purple-500 pl-6 py-2 mb-6 italic text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-gray-800/50; +} + +.prose code { + @apply bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded text-sm font-mono text-purple-700 dark:text-purple-300; +} + +.prose pre { + @apply bg-gray-100 text-gray-900 dark:bg-gray-900 dark:text-gray-100 p-4 rounded-lg mb-6 overflow-x-auto; +} + +.prose pre code { + @apply bg-transparent p-0; + color: inherit; +} + +/* Ensure HLJS themes don't override background/text inside prose blocks */ +.prose pre code.hljs, +.prose code.hljs, +.prose pre .hljs { + background: transparent !important; + color: inherit; +} + +/* Mobile hamburger animation */ +#hamburger .bar-1, +#hamburger .bar-3 { transition: transform 200ms ease; } +#hamburger .bar-2 { transition: opacity 150ms ease; } +#hamburger.open .bar-1 { transform: translateY(6px) rotate(45deg); } +#hamburger.open .bar-2 { opacity: 0; } +#hamburger.open .bar-3 { transform: translateY(-6px) rotate(-45deg); } + +/* Wrap long links in blog posts to prevent overflow */ +.prose a { + overflow-wrap: anywhere; + word-break: break-word; + white-space: normal; +} + + + +.prose img { + @apply rounded-lg mb-6 shadow-md; +} + +.prose table { + @apply w-full mb-6 border-collapse; +} + +.prose th { + @apply bg-gray-100 dark:bg-gray-800 px-4 py-2 text-left font-semibold border border-gray-300 dark:border-gray-600; +} + +.prose td { + @apply px-4 py-2 border border-gray-300 dark:border-gray-600; +} + +.prose hr { + @apply my-8 border-gray-300 dark:border-gray-600; +} + +.prose strong { + @apply font-bold text-gray-900 dark:text-gray-100; +} + +.prose em { + @apply italic; +} + +.prose del { + @apply line-through text-gray-500 dark:text-gray-400; +} + +/* Header anchors */ +.prose .header-anchor { + @apply text-purple-500 hover:text-purple-700 dark:text-purple-400 dark:hover:text-purple-200 no-underline ml-2 opacity-0 transition-opacity; +} + +.prose h1:hover .header-anchor, +.prose h2:hover .header-anchor, +.prose h3:hover .header-anchor, +.prose h4:hover .header-anchor { + @apply opacity-100; +} + +:root { + --bg: #dcfcf4; + --text: #1a1625; + --surface: #f7f2fa; + --accent: #ffd1f0; + --accent-light:#ffd1f0; + --border: hotpink; +} + +.dark { + --bg: #0f0a1a; + --text: #f1e8ff; + --surface: #1a0f2e; + --accent: #a855f7; + --accent-light: #c084fc; + --border: #4c1d95; +} + +#progress-bar { + position: fixed; + top: 0; + left: 0; + height: 3px; + background: linear-gradient(90deg, #7c3aed, #ec4899, #f59e0b); + z-index: 9999; + transition: width 0.3s ease; +} + +/* Nav items - no hover effects to prevent jitter */ +.nav-item { + color: inherit; +} + +/* Remove hover transform that could cause layout shifts */ + +/* Subtle animations */ +@keyframes float { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-3px); } +} + +.float-animation { + animation: float 3s ease-in-out infinite; +} + +/* System fonts toggle */ +.system-fonts { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; +} + +html { + scroll-behavior: smooth; + overflow-y: scroll; + width: 100vw; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + line-height: 1.6; +} + +/* Base accessibility improvements */ +@layer base { + a { + cursor: pointer; + text-decoration: none; + } + a:focus-visible { + outline: 2px solid #7c3aed; /* purple accent focus ring */ + outline-offset: 2px; + border-radius: 2px; + } + /* Global link hover/active behavior (non-prose, non-nav links) */ + a:hover { + text-decoration: underline; + text-underline-offset: 2px; + } + a:active { + text-decoration-thickness: 2px; + } + a:hover:not(.nav-item) { + color: var(--accent); + transition: color 150ms ease-in-out; + } + .dark a:hover:not(.nav-item) { + color: var(--accent-light); + } +} + +/* Prose improvements */ +@layer components { + .prose { + color: var(--text); + } + .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 { + color: var(--text); + } + .prose a { + color: #2563eb; /* readable blue on light */ + text-decoration: underline; + text-underline-offset: 2px; + text-decoration-thickness: 1.5px; + transition: color 150ms ease-in-out; /* color-only to avoid layout shift */ + } + .prose a:hover { + color: #1d4ed8; + } + .prose a:active { + text-decoration-thickness: 2px; + } + .prose a:focus-visible { + outline: 2px solid #7c3aed; + outline-offset: 2px; + border-radius: 2px; + } + .dark .prose a { + color: #60a5fa; + } + .dark .prose a:hover { + color: #93c5fd; + } + .dark .prose a:focus-visible { + outline-color: #a855f7; + } +} diff --git a/assets/favicon-16x16.png b/assets/favicon-16x16.png new file mode 100755 index 0000000..4847b55 Binary files /dev/null and b/assets/favicon-16x16.png differ diff --git a/assets/favicon-32x32.png b/assets/favicon-32x32.png new file mode 100755 index 0000000..83684a2 Binary files /dev/null and b/assets/favicon-32x32.png differ diff --git a/assets/favicon.svg b/assets/favicon.svg new file mode 100755 index 0000000..776af1d --- /dev/null +++ b/assets/favicon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/js/easter-eggs.js b/assets/js/easter-eggs.js new file mode 100644 index 0000000..bb9c9db --- /dev/null +++ b/assets/js/easter-eggs.js @@ -0,0 +1,238 @@ +// Easter eggs and fun interactions +class EasterEggs { + constructor() { + this.konamiCode = [ + 'ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', + 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', + 'KeyB', 'KeyA' + ]; + this.konamiIndex = 0; + this.init(); + } + + init() { + this.setupKonamiCode(); + this.setupClickEasterEgg(); + this.setupTypingEasterEgg(); + } + + setupKonamiCode() { + document.addEventListener('keydown', (e) => { + if (e.code === this.konamiCode[this.konamiIndex]) { + this.konamiIndex++; + if (this.konamiIndex === this.konamiCode.length) { + this.triggerKonamiEasterEgg(); + this.konamiIndex = 0; + } + } else { + this.konamiIndex = 0; + } + }); + } + + triggerKonamiEasterEgg() { + // Create rainbow effect + document.body.style.animation = 'rainbow 2s infinite'; + + // Add rainbow keyframes if not already present + if (!document.querySelector('#rainbow-styles')) { + const style = document.createElement('style'); + style.id = 'rainbow-styles'; + style.textContent = ` + @keyframes rainbow { + 0% { filter: hue-rotate(0deg); } + 25% { filter: hue-rotate(90deg); } + 50% { filter: hue-rotate(180deg); } + 75% { filter: hue-rotate(270deg); } + 100% { filter: hue-rotate(360deg); } + } + .easter-egg-message { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3); + background-size: 400% 400%; + animation: rainbow-bg 2s ease infinite; + color: white; + padding: 20px; + border-radius: 10px; + font-size: 24px; + font-weight: bold; + text-align: center; + z-index: 9999; + box-shadow: 0 10px 30px rgba(0,0,0,0.3); + } + @keyframes rainbow-bg { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } + } + `; + document.head.appendChild(style); + } + + // Show message + const message = document.createElement('div'); + message.className = 'easter-egg-message'; + message.innerHTML = '๐ŸŽ‰ Konami Code Activated! ๐ŸŽ‰
You found the secret!'; + document.body.appendChild(message); + + // Remove effects after 3 seconds + setTimeout(() => { + document.body.style.animation = ''; + message.remove(); + }, 3000); + } + + setupClickEasterEgg() { + let clickCount = 0; + let resetTimer; + + // Use a more specific selector that won't interfere with navigation + const logo = document.querySelector('header h1 a, header .site-title a'); + + if (logo) { + logo.addEventListener('click', (e) => { + // Only trigger easter egg if we're already on the home page + if (window.location.pathname === '/') { + clickCount++; + if (clickCount === 7) { + e.preventDefault(); + this.triggerClickEasterEgg(); + clickCount = 0; + } + + // Reset counter after 3 seconds of no clicks + clearTimeout(resetTimer); + resetTimer = setTimeout(() => { + clickCount = 0; + }, 3000); + } + }); + } + } + + triggerClickEasterEgg() { + // Make all images spin + const images = document.querySelectorAll('img'); + images.forEach(img => { + img.style.transition = 'transform 2s ease'; + img.style.transform = 'rotate(360deg)'; + setTimeout(() => { + img.style.transform = ''; + }, 2000); + }); + + // Show message + this.showTemporaryMessage('๐ŸŒŸ Images are spinning! ๐ŸŒŸ'); + } + + setupTypingEasterEgg() { + let typedSequence = ''; + const secretWord = 'nahleb'; + + document.addEventListener('keypress', (e) => { + typedSequence += e.key.toLowerCase(); + + if (typedSequence.length > secretWord.length) { + typedSequence = typedSequence.slice(-secretWord.length); + } + + if (typedSequence === secretWord) { + this.triggerTypingEasterEgg(); + typedSequence = ''; + } + }); + } + + triggerTypingEasterEgg() { + // Add floating hearts + for (let i = 0; i < 10; i++) { + setTimeout(() => { + this.createFloatingHeart(); + }, i * 200); + } + + this.showTemporaryMessage('๐Ÿ’– You typed the magic word! They are in love ๐Ÿ’–'); + } + + createFloatingHeart() { + const heart = document.createElement('div'); + heart.innerHTML = '๐Ÿ’–'; + heart.style.cssText = ` + position: fixed; + font-size: 24px; + pointer-events: none; + z-index: 9999; + left: ${Math.random() * window.innerWidth}px; + top: ${window.innerHeight}px; + animation: float-up 3s ease-out forwards; + `; + + // Add floating animation if not present + if (!document.querySelector('#float-styles')) { + const style = document.createElement('style'); + style.id = 'float-styles'; + style.textContent = ` + @keyframes float-up { + to { + transform: translateY(-${window.innerHeight + 100}px) rotate(360deg); + opacity: 0; + } + } + `; + document.head.appendChild(style); + } + + document.body.appendChild(heart); + + setTimeout(() => { + heart.remove(); + }, 3000); + } + + showTemporaryMessage(text) { + const message = document.createElement('div'); + message.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + background: rgba(0, 0, 0, 0.8); + color: white; + padding: 15px 20px; + border-radius: 8px; + font-size: 16px; + z-index: 9999; + animation: slideIn 0.3s ease; + `; + message.textContent = text; + + // Add slide animation if not present + if (!document.querySelector('#slide-styles')) { + const style = document.createElement('style'); + style.id = 'slide-styles'; + style.textContent = ` + @keyframes slideIn { + from { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } + } + `; + document.head.appendChild(style); + } + + document.body.appendChild(message); + + setTimeout(() => { + message.style.animation = 'slideIn 0.3s ease reverse'; + setTimeout(() => message.remove(), 300); + }, 2000); + } +} + +// Initialize easter eggs when DOM is loaded +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => new EasterEggs()); +} else { + new EasterEggs(); +} diff --git a/assets/js/flexsearch.min.js b/assets/js/flexsearch.min.js new file mode 100644 index 0000000..822e471 --- /dev/null +++ b/assets/js/flexsearch.min.js @@ -0,0 +1,48 @@ +/**! + * FlexSearch.js v0.7.41 (Es5) + * Author and Copyright: Thomas Wilkerling + * Licence: Apache-2.0 + * Hosted by Nextapps GmbH + * https://github.com/nextapps-de/flexsearch + */ +(function(self){'use strict';var t;function aa(a){var b=0;return function(){return b>>0)+"_",e=0;return b}); +y("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;cc&&(c=Math.max(c+e,0));c=this.C&&(f||!g[l])){var p=O(h,d,k),n="";switch(this.H){case "full":if(2p;q--)if(q-p>=this.C){var r=O(h,d,k,m,p);n=l.substring(p,q);P(this,g,n,r,a,c)}break}case "reverse":if(1=this.C&&P(this,g,n,O(h,d,k, +m,q),a,c);n=""}case "forward":if(1=this.C&&P(this,g,n,p,a,c);break}default:if(this.o&&(p=Math.min(p/this.o(b,l,k)|0,h-1)),P(this,g,l,p,a,c),f&&1=this.C&&!m[l]){m[l]=1;var u=this.l&&l>p;P(this,e,u?p:l,O(n+(d/2>n?0:1),d,k,q-1,r-1),a,c,u?l:p)}}}}this.s||(this.register[a]=1)}}return this}; +function O(a,b,c,d,e){return c&&1=this.C&&!c[p])if(this.B||f||this.map[p])k[m++]=p,c[p]=1;else return d;a=k;h=a.length}}if(!h)return d;b||(b=100);g=this.depth&&1=d)))break;if(m){if(g)return ya(k,d,0);b[b.length]=k;return}}return!c&&k}function ya(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function za(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)}; +t.remove=function(a,b){var c=this.register[a];if(c){if(this.s)for(var d=0,e;db||c)e=e.slice(c,c+b);d&&(e=Ea.call(this,e));return{tag:a,result:e}}}function Ea(a){for(var b=Array(a.length),c=0,d;c { + if (!bar) return; + clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(() => { + const scrollTop = window.scrollY; + const docHeight = document.documentElement.scrollHeight - window.innerHeight; + const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0; + bar.style.width = progress + '%'; + }, 10); + }; + window.addEventListener('scroll', onScroll, { passive: true }); + onScroll(); + + // Dark mode toggle + const darkToggle = document.getElementById('dark-toggle'); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)'); + const setToggleUI = (isDark) => { + if (!darkToggle) return; + darkToggle.textContent = isDark ? 'โ˜€๏ธ' : '๐ŸŒ™'; + darkToggle.setAttribute('aria-pressed', isDark ? 'true' : 'false'); + darkToggle.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode'); + }; + const applyTheme = (isDark) => { + document.documentElement.classList.toggle('dark', isDark); + localStorage.setItem('theme', isDark ? 'dark' : 'light'); + setToggleUI(isDark); + }; + const savedTheme = localStorage.getItem('theme'); + const initialDark = savedTheme ? savedTheme === 'dark' : prefersDark.matches; + applyTheme(initialDark); + if (darkToggle) { + darkToggle.addEventListener('click', () => applyTheme(!document.documentElement.classList.contains('dark'))); + } + + // Accessibility controls + const fontInc = document.getElementById('font-inc'); + const fontDec = document.getElementById('font-dec'); + const contrastToggle = document.getElementById('contrast-toggle'); + const motionToggle = document.getElementById('motion-toggle'); + + const applyA11y = () => { + const size = parseFloat(localStorage.getItem('fontScale') || '1'); + const highContrast = localStorage.getItem('highContrast') === '1'; + const reduceMotion = localStorage.getItem('reduceMotion') === '1'; + + // Apply all changes in a single batch to prevent layout thrashing + requestAnimationFrame(() => { + document.documentElement.style.setProperty('font-size', (size * 100) + '%'); + document.documentElement.classList.toggle('contrast', highContrast); + document.documentElement.classList.toggle('reduce-motion', reduceMotion); + }); + }; + applyA11y(); + + if (fontInc) fontInc.addEventListener('click', () => { + const size = Math.min(1.5, (parseFloat(localStorage.getItem('fontScale') || '1') + 0.1)); + localStorage.setItem('fontScale', String(size)); + applyA11y(); + }); + if (fontDec) fontDec.addEventListener('click', () => { + const size = Math.max(0.8, (parseFloat(localStorage.getItem('fontScale') || '1') - 0.1)); + localStorage.setItem('fontScale', String(size)); + applyA11y(); + }); + if (contrastToggle) contrastToggle.addEventListener('click', () => { + const v = localStorage.getItem('highContrast') === '1' ? '0' : '1'; + localStorage.setItem('highContrast', v); + applyA11y(); + }); + if (motionToggle) motionToggle.addEventListener('click', () => { + const v = localStorage.getItem('reduceMotion') === '1' ? '0' : '1'; + localStorage.setItem('reduceMotion', v); + applyA11y(); + }); + + // Mobile navigation toggle + const hamburger = document.getElementById('hamburger'); + const primaryNav = document.getElementById('primary-nav'); + if (hamburger && primaryNav) { + // Ensure initial aria state + hamburger.setAttribute('aria-expanded', primaryNav.classList.contains('hidden') ? 'false' : 'true'); + hamburger.addEventListener('click', () => { + const isHidden = primaryNav.classList.toggle('hidden'); + hamburger.classList.toggle('open', !isHidden); + hamburger.setAttribute('aria-expanded', isHidden ? 'false' : 'true'); + }); + } + + // A11y popover (button + menu) + const a11yToggle = document.getElementById('a11y-toggle'); + const a11yMenu = document.getElementById('a11y-menu'); + if (a11yToggle && a11yMenu) { + const closeMenu = () => { + a11yMenu.classList.add('hidden'); + a11yToggle.setAttribute('aria-expanded', 'false'); + }; + const openMenu = () => { + a11yMenu.classList.remove('hidden'); + a11yToggle.setAttribute('aria-expanded', 'true'); + }; + a11yToggle.addEventListener('click', (e) => { + e.stopPropagation(); + const isHidden = a11yMenu.classList.contains('hidden'); + if (isHidden) openMenu(); else closeMenu(); + }); + document.addEventListener('click', (e) => { + if (!a11yMenu.classList.contains('hidden')) { + const within = a11yMenu.contains(e.target) || a11yToggle.contains(e.target); + if (!within) closeMenu(); + } + }); + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') closeMenu(); + }); + } + + // Font toggle for footer + const fontToggle = document.getElementById('font-toggle'); + if (fontToggle) { + const applyFontPref = (enabled) => { + document.documentElement.classList.toggle('system-fonts', enabled); + fontToggle.textContent = enabled ? 'Web Fonts' : 'System Fonts'; + fontToggle.setAttribute('aria-pressed', enabled ? 'true' : 'false'); + }; + + fontToggle.addEventListener('click', () => { + const currentlyEnabled = document.documentElement.classList.contains('system-fonts'); + const next = !currentlyEnabled; + applyFontPref(next); + localStorage.setItem('systemFonts', next ? '1' : '0'); + }); + + // Apply saved font preference + const savedFontPref = localStorage.getItem('systemFonts'); + applyFontPref(savedFontPref === '1'); + } +})(); diff --git a/assets/js/search.js b/assets/js/search.js new file mode 100644 index 0000000..ce4baf7 --- /dev/null +++ b/assets/js/search.js @@ -0,0 +1,195 @@ +(function() { + let searchIndex = null; + let flexSearch = null; + + // Initialize search when DOM is ready + document.addEventListener('DOMContentLoaded', initializeSearch); + + async function initializeSearch() { + const searchInput = document.getElementById('q'); + const searchResults = document.getElementById('search-results'); + + if (!searchInput) return; + + try { + // FlexSearch should already be loaded via script tag + if (typeof FlexSearch === 'undefined') { + throw new Error('FlexSearch library not found. Make sure flexsearch.min.js is loaded.'); + } + + // Load search index + const response = await fetch('/search.json'); + if (!response.ok) { + throw new Error(`Failed to load search index: ${response.status}`); + } + + searchIndex = await response.json(); + + if (!Array.isArray(searchIndex) || searchIndex.length === 0) { + console.warn('Search index is empty or invalid'); + return; + } + + // Initialize FlexSearch + flexSearch = new FlexSearch.Index({ + tokenize: 'forward', + cache: true, + resolution: 9 + }); + + // Add documents to search index + searchIndex.forEach((item, index) => { + if (item && item.title) { + const searchText = `${item.title} ${item.description || ''} ${item.content || ''} ${(item.tags || []).join(' ')}`; + flexSearch.add(index, searchText); + } + }); + + // Set up search event listeners + setupSearchListeners(searchInput, searchResults); + + console.log(`Search initialized with ${searchIndex.length} items`); + + } catch (error) { + console.error('Search initialization failed:', error); + } + } + + function setupSearchListeners(searchInput, searchResults) { + let searchTimeout; + + searchInput.addEventListener('input', (e) => { + clearTimeout(searchTimeout); + const query = e.target.value.trim(); + + if (query.length < 2) { + hideSearchResults(searchResults); + return; + } + + searchTimeout = setTimeout(() => { + performSearch(query, searchResults); + }, 300); + }); + + searchInput.addEventListener('focus', (e) => { + if (e.target.value.trim().length >= 2) { + performSearch(e.target.value.trim(), searchResults); + } + }); + + // Hide results when clicking outside + document.addEventListener('click', (e) => { + if (!searchInput.contains(e.target) && !searchResults?.contains(e.target)) { + hideSearchResults(searchResults); + } + }); + + // Keyboard navigation + searchInput.addEventListener('keydown', (e) => { + if (!searchResults) return; + + const items = searchResults.querySelectorAll('a'); + const currentFocus = document.activeElement; + let currentIndex = Array.from(items).indexOf(currentFocus); + + if (e.key === 'ArrowDown') { + e.preventDefault(); + currentIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0; + items[currentIndex]?.focus(); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + currentIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1; + items[currentIndex]?.focus(); + } else if (e.key === 'Escape') { + hideSearchResults(searchResults); + searchInput.blur(); + } + }); + } + + function performSearch(query, searchResults) { + if (!flexSearch || !searchIndex) return; + + try { + const results = flexSearch.search(query, { limit: 8 }); + const items = results.map(index => searchIndex[index]); + + displaySearchResults(items, query, searchResults); + } catch (error) { + console.warn('Search failed:', error); + } + } + + function displaySearchResults(items, query, searchResults) { + if (!searchResults) { + // Create search results container if it doesn't exist + searchResults = createSearchResultsContainer(); + } + + if (items.length === 0) { + searchResults.innerHTML = ` +
+ No results found for "${query}" +
+ `; + } else { + searchResults.innerHTML = items.map(item => ` + +
${highlightMatch(item.title, query)}
+
${highlightMatch(item.description || item.content, query)}
+ ${item.tags.length > 0 ? ` +
+ ${item.tags.slice(0, 3).map(tag => `#${tag}`).join('')} +
+ ` : ''} +
+ `).join(''); + } + + searchResults.classList.remove('hidden'); + } + + function createSearchResultsContainer() { + const searchForm = document.querySelector('form[role="search"]'); + if (!searchForm) return null; + + const container = document.createElement('div'); + container.id = 'search-results'; + container.className = 'absolute top-full left-0 right-0 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-b-md shadow-lg z-50 max-h-96 overflow-y-auto hidden'; + + searchForm.style.position = 'relative'; + searchForm.appendChild(container); + + return container; + } + + function hideSearchResults(searchResults) { + if (searchResults) { + searchResults.classList.add('hidden'); + } + } + + function highlightMatch(text, query) { + if (!text || !query) return text || ''; + + const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); + return text.replace(regex, '$1'); + } + + function loadScript(src) { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.src = src; + script.onload = () => { + console.log('Script loaded successfully:', src); + resolve(); + }; + script.onerror = (error) => { + console.error('Script failed to load:', src, error); + reject(error); + }; + document.head.appendChild(script); + }); + } +})(); diff --git a/assets/js/webmentions.js b/assets/js/webmentions.js new file mode 100644 index 0000000..ac6c2c4 --- /dev/null +++ b/assets/js/webmentions.js @@ -0,0 +1,117 @@ +(function() { + // Webmentions functionality + async function loadWebmentions() { + const webmentionsContainer = document.getElementById('webmentions-list'); + if (!webmentionsContainer) return; + + const currentUrl = window.location.href; + const domain = window.location.hostname; + + try { + // Fetch webmentions from webmention.io + const response = await fetch(`https://webmention.io/api/mentions.jf2?target=${encodeURIComponent(currentUrl)}&per-page=50`); + const data = await response.json(); + + if (data.children && data.children.length > 0) { + displayWebmentions(data.children, webmentionsContainer); + } else { + showEmptyState(webmentionsContainer); + } + } catch (error) { + console.warn('Failed to load webmentions:', error); + showEmptyState(webmentionsContainer); + } + } + + function displayWebmentions(mentions, container) { + const likes = mentions.filter(m => m['wm-property'] === 'like-of'); + const reposts = mentions.filter(m => m['wm-property'] === 'repost-of'); + const replies = mentions.filter(m => m['wm-property'] === 'in-reply-to'); + const bookmarks = mentions.filter(m => m['wm-property'] === 'bookmark-of'); + const general = mentions.filter(m => m['wm-property'] === 'mention-of'); + + let html = ''; + + // Show counts + if (likes.length > 0 || reposts.length > 0 || bookmarks.length > 0) { + html += '
'; + if (likes.length > 0) html += `โค๏ธ ${likes.length} like${likes.length !== 1 ? 's' : ''}`; + if (reposts.length > 0) html += `๐Ÿ”„ ${reposts.length} repost${reposts.length !== 1 ? 's' : ''}`; + if (bookmarks.length > 0) html += `๐Ÿ”– ${bookmarks.length} bookmark${bookmarks.length !== 1 ? 's' : ''}`; + html += '
'; + } + + // Show replies and mentions + const conversationMentions = [...replies, ...general].sort((a, b) => new Date(a.published) - new Date(b.published)); + + if (conversationMentions.length > 0) { + html += '
'; + conversationMentions.forEach(mention => { + html += renderMention(mention); + }); + html += '
'; + } + + container.innerHTML = html; + } + + function renderMention(mention) { + const author = mention.author || {}; + const content = mention.content || {}; + const published = mention.published ? new Date(mention.published).toLocaleDateString() : ''; + + return ` +
+
+ ${author.photo ? + `${author.name || 'Anonymous'}` : + `
+ ${(author.name || 'A')[0].toUpperCase()} +
` + } +
+
+ + ${author.name || 'Anonymous'} + + + ${mention['wm-property'] === 'in-reply-to' ? 'replied' : 'mentioned this'} + + ${published ? `` : ''} +
+ ${content.text ? + `
+ ${content.text.length > 280 ? content.text.substring(0, 280) + '...' : content.text} +
` : '' + } + +
+
+
+ `; + } + + function showEmptyState(container) { + container.innerHTML = ` +
+

No webmentions yet. Be the first to respond!

+

+ + Learn about webmentions + +

+
+ `; + } + + // Initialize webmentions when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', loadWebmentions); + } else { + loadWebmentions(); + } +})(); diff --git a/assets/og-default.png b/assets/og-default.png new file mode 100755 index 0000000..d3ef41d Binary files /dev/null and b/assets/og-default.png differ diff --git a/assets/profile.jpg b/assets/profile.jpg new file mode 100755 index 0000000..1e07966 Binary files /dev/null and b/assets/profile.jpg differ diff --git a/assets/retro-stars.png b/assets/retro-stars.png new file mode 100755 index 0000000..d1ee1dc Binary files /dev/null and b/assets/retro-stars.png differ diff --git a/blog.njk b/blog.njk new file mode 100755 index 0000000..81ae9c6 --- /dev/null +++ b/blog.njk @@ -0,0 +1,39 @@ +--- +layout: layouts/base.njk +pagination: + data: collections.posts + size: 10 + alias: posts +permalink: "/blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber + 1 }}/{% endif %}" +title: Blog +--- +
+

Blog

+ + +
+ {% for post in posts %} +
+

{{ post.data.title }}

+ +
{{ post.data.description or (post.templateContent | striptags | truncate(160)) }}
+
+ {% for tag in post.data.tags %} + #{{ tag }} + {% endfor %} +
+
+ {% endfor %} +
+ + +
diff --git a/blog/fandom-sucks.md b/blog/fandom-sucks.md new file mode 100644 index 0000000..b59eddd --- /dev/null +++ b/blog/fandom-sucks.md @@ -0,0 +1,58 @@ +--- +layout: layouts/post.njk +title: Fandom Sucks Now, and Other Laments +author: Agnes the Alien +date: 2026-03-14 +description: You know, these days, I am getting sort of tired. I donโ€™t really know how else to describe it, so weโ€™ll just go with the simplicity of Iโ€™m really just kind of tired. And the worst, most unsightly aspect of it all is this - I donโ€™t really know what Iโ€™m tired of. I can give you a list of reasons without hesitation - 1) I spend my entire time in fandom.... +tags: [fandom, essays, media] +category: fandom +--- +Content warnings: child sex trafficking/PTSD. + + +You know, these days, I am getting sort of tired. + +I donโ€™t really know how else to describe it, so weโ€™ll just go with the simplicity of *Iโ€™m really just kind of tired.* And the worst, most unsightly aspect of it all is this: I donโ€™t really know what Iโ€™m tired _of._ + +I can give you a list of reasons without hesitation: + +1) I spend my entire time in fandom, because fandom is my passion. I run a fanfiction archive with ~360 users and around 500 different fandoms. Fandom is, quite literally, what I have dedicated my life to for the past fifteen years. And fandom, apparently, fucking hates me. Yeah, so it turns out that if youโ€™re different from what is considered Normal and Acceptable in any way, you deserve to die and are subhuman, according to others. This widespread harassment is reminiscent of my days being beaten up and nearly murdered as a child at my Waldorf elementary schoolโ€”unfathomable, needless cruelty fueled by a hatred of anything they donโ€™t want to understand. So what if I like to cope by writing dark fanfiction? So what if I just fucking like dark fanfiction? What are you going to do about it? Stop me? + +But unfortunately, there are actual repercussions for openly liking dark content. People can and will try to ruin your life, your source of income, your relationships, your safety. And Iโ€™m a sensitive alien, okay! Iโ€™m a goddamn child trafficking survivor and to be called a pedophile over fictional aliens shatters my soul in ways no one can even begin to comprehend unless theyโ€™re in the same situation. + +I shouldnโ€™t say that, probably. I shouldnโ€™t let people know about that weakness. Itโ€™s like a KICK ME sign taped to my back, a big red arrow pointing right to my Achilles heel. Come and cut me. But I am in a human body in this life, and so I am human. And as a human thing, the comparison still will never leave me. It haunts, vivisects. I know who I am, and I cannot control how others perceive me, and I cannot handle being seen as a being of the same depravity of the people who hurt me. I just canโ€™t. + +I think this is a valid reason to be tired. It is still only one facet of the crystal. + +I do so much for fandom. What does fandom do for me? It brought me my beloved. My amazing friends. But what else? What lately? + +2) I just do nothing. I have nothing to do all day. Oh, sure, I have tons to do, actually. I have ideas and I have projects and I have embroidery supplies and music software and cute little $5 kits from the store where you knit an ugly ass ladybug. I simply never have the wherewithal to actually do any of them. Is it the fatigue and pain I am constantly in? Am I just depressed and unmotivated because everything seems worthless? Is my psychosis acting up again? Do I need to have my meds adjusted, is what my family will say, if I tell them Iโ€™m struggling with motivation, so of course I donโ€™t tell them. + +I canโ€™t ever get the spark going. Like a wind-up toy that just gets tighter and tigher until it snaps, never moving forward. And I have no goddamn idea why. + +Iโ€™m tired of being so tired. + +3) My family is aging and ill and my mother will not go to the doctor because she is scared. Sheโ€™s sixty one, her thyroid is dead, she needs to be on medication for it (hypocritical of me perhaps, since my thyroid is also dead and I donโ€™t take _my_ synthroid, but Iโ€™m going to start!!!), but she refuses to get a perscription. Iโ€™m terrified about what will happen when her body canโ€™t take it anymore. + +My nana has anxiety worse than mine. Itโ€™s so bad she stays up multiple nights having intrusive thoughts. She refuses to take any sort of medication for this or bring it up to her doctor. Iโ€™m terrified about what will happen when she gets too terrified. + +Iโ€™m tired of being so scared. + +4) Oh, yeah, and thereโ€™s that whole I-have-dissociative-identity-disorder-and-CPTSD thing. Iโ€™ve been having flashbacks almost every day lately. Iโ€™m tired of feeling broken. Iโ€™m tired of letting it break me, but I just donโ€™t know how to stop thinking about it, writing about it, recreating it in fiction, thinking about it, throwing up about it, obsessing over it, thinking about it. Iโ€™m obsessed with it all, the pain that I went through and the siphoning of my innocence and the portioning of my body and so on. Itโ€™s all I ever think about. When will it stop? When will I stop feeling it? + +Torturing fictional characters in the same way makes it feel better for a little while. Like a band-aid over an autopsy incison. + +I guess maybe Iโ€™m just tired of all of it. Of this frozen life Iโ€™m living. I keep thinking something needs to change, and I keep trying to make small changes to my daily routine, you know, build new habits, start a schedule, but itโ€™s all futile, I fall out of everything eventually. I really need to start preparing for my future, because I guess Iโ€™m going to have one? And preparing for my future is not sitting here writing toxic yuri fanfiction all day, as fun as it is. I donโ€™t know. I keep clawing at the walls of my brain, trying to find a solution. + +I see a lot of my friends taking steps back from fandom these days. A lot of them are also creatives, and theyโ€™re choosing to focus more on original works instead. I find that option more and more appealing with each cruel post I see pass my Tumblr dashboard. I canโ€™t decide if I really want to step back from fandom, or if I only feel a need to do so because still being so deeply entrenched in fandom when everyone else I know has moved on makes me feel a little self-conscious, and I feel like I have to follow suit or I will be left behind. But I suspect that while my insecurities are probably a factor, it has more to do with the harassment Iโ€™ve been facing over being a Nahla/Caleb(/Anisha) shipper, and the terrible things people have said about me because of it. + +I donโ€™t want to enjoy things in fear. I have my own personal archive using the AO3 software now; I rarely post to AO3 outside of exchanges. I keep my fics locked down to my friends and people I trust not to judge me. Andโ€ฆ Iโ€™m someone who loves attention! I kind of need it to survive, clinically. But I just struggle to stay sane when horrible accusation after horrible accusation is thrown at me, and all Iโ€™m trying to do is enjoy myself in peace. I donโ€™t want to have to hide or water myself down to be accepted, but unfortunately that is the reality of the world. Weโ€™re all paranoid, weโ€™re all pointing fingers and pointing fingers and gnawing off fingers, weโ€™re all cruel. I just canโ€™t take it anymore. + +The issue is that I run that aforementioned somewhat-popular fanfiction archive. And I enjoy running this archive! I want to do so much more with it! And the people I have met through it are absolutely wonderful. I donโ€™t want to step back from Sunset and I donโ€™t see myself doing so in the future. At the same time, though, I think Sunset and Dreamwidth and my tiny little Discord server will be the extent of my fandom participation for a while. + +I want to focus on my original works and build a real career in writing. I want to make video games and finish my novella Iโ€™ve been working on for a year now that is still only at 4,400 words and I want to make music and I want to learn how to hand quilt and I want to have more things in my life than just television and fictional characters, but itโ€™s kind of hard for me to focus on anything besides them. Or โ€“ it has been in the past. Maybe Iโ€™m finally so disillusioned with fandom that Iโ€™ll be able to focus on something else for a change. I donโ€™t know. + +I donโ€™t really know how to talk to people outside of fandom, and in all honesty, I donโ€™t know a lot about myself outside of it just in general. I donโ€™t have much of an identity beyond that, at least in my own perception of myself, and thatโ€™sโ€ฆ well, obviously unhealthy. I want to go back to school and go to writerโ€™s groups in the city and I want a life worth living. I want to make websites that arenโ€™t AO3-based or shoddy things I threw together based on outdated Rails guides; I want to actually _know_ what Iโ€™m doing with web development, because itโ€™s something I find very fun and rewarding. + +I just so desperately want things to change, but I donโ€™t know how to change them. The only thing I can think of for now is that I must focus on building a life for myself that isnโ€™t attached to a fictional character. Itโ€™s long overdue. + diff --git a/blog/traumaloop.md b/blog/traumaloop.md new file mode 100644 index 0000000..0e07d22 --- /dev/null +++ b/blog/traumaloop.md @@ -0,0 +1,39 @@ +--- +layout: layouts/post.njk +title: (Nus Braka Voice) how's that for a trauma loop? +author: Agnes the Alien +date: 2026-03-03 +description: Iโ€™ve been thinking a lot lately about my creativity. I donโ€™t do a lot of original work โ€“ Ice Dancer was my first poem inโ€ฆ way too long, maybe a YEAR? โ€“ Iโ€™ve only been focusing on fanworks. I do have ideas for original works! Many, in fact! But every time I sit down to write, thereโ€™s a block. I donโ€™t really know why. +tags: [personal, creativity] +category: personal +--- +Content warning: childhood sexual abuse & trafficking. + +Iโ€™ve been thinking a lot lately about my creativity. I donโ€™t do a lot of original work โ€“ [Ice Dancer](https://kissing.computer/2026/02/27/poem-ice-dancer/) was my first poem inโ€ฆ way too long, maybe a YEAR? โ€“ Iโ€™ve only been focusing on fanworks. I do have ideas for original works! Many, in fact! But every time I sit down to write, thereโ€™s a block. I donโ€™t really know why. + +Maybe itโ€™s that I feel like my original writing is futile. + +Iโ€™ve been published before. But because I was suicidal for so long and genuinely didnโ€™t plan on being alive for it to matter, I never really learned how to separate my fandom persona from my professional writing self. And that was a bad idea. When I started to finally heal โ€“ around the time I started using dark fiction to cope with past trauma โ€“ I realized that the people I surrounded myself with would try to ruin my career and life if they could tie me to that pen name. So I had to rebuild, and none of my previously published works could be tied to my current pen name. I had to remake everything โ€“ my author site, my itch.io, etc. Some of my favorite creations can no longer be tied to me because of this, including a piece of interactive art that meansโ€ฆ wellโ€ฆ just about everything to me. I had about 2k followers on those accounts; now I barely have 200. It all just feels utterly useless. + +I also feel like a lot of my original work is just horribly repetitive these days. I use the same metaphors and the same pains and the same words and the same events, over and over and over again. + +Iโ€™m stuck. And not just creatively. + +Iโ€™m chained to these things. Iโ€™m living a time loop where Iโ€™m forced to re-experience them over and over again every day of my pitiful damn existence. Iโ€™m being buried alive and when I suffocate Iโ€™ll wake up in a television show but for me I really have run out of time!!! Or at least it feels that way. I try not to let fiction write my story for me but it is a little bit easier that way. + +Even my fanworks, honestly, to a lesser extent. I find myself hyperfixated on portrayals of childhood sexual abuse in fiction, and finding ways to project my experiences with it onto characters who havenโ€™t explicitly been through it but also have backstories that would realistically involve it. Take Caleb Mir from Star Trek: SFA for example; heโ€™s been on his own, on the run, and in and out of prison since age six. You donโ€™t escape that unmolested. + +I find myself projecting onto him deeply. I find myself getting unhealthily attached to him. I think about this stuff way way too much. I see myself in him, even if I shouldnโ€™t, even if my life has been paradise compared to his. Thinking about characters having the same pain I have, and overcoming it, gives me some illusion of hopeโ€™s tangibility. Illusion, delusion? I donโ€™t know. It just makes me feel like healing can be in reach for me if I try really hard enough โ€“ like maybe if I squint really hard and believe and click my heels together I can imagine up a portal into a world where Iโ€™m not in this much agony. + +I love SFA because itโ€™s the first time Iโ€™ve seen a show with a cast of characters that I feel like would genuinely accept me as a person if they knew me. I relate to SAM so deeply; to see her accepted by everyone โ€“ loved by everyone โ€“ makes me soar. Caleb comforts fat anxious cadets (even if I have beef with Pickford now.) People are given space to deal with their traumas, given empathy. Iโ€™ve never wanted to live in a show more than this (except maybe Doom Patrol, for ficto reasons.) + +But as I go deeper and deeper into escapism here, I find myself just ouroborosing my trauma. Like I just keep throwing it up and then eating the vomit and then throwing it back up and eating it again and so on and so forth, like my dog did when my dad died. The projection helps me cope, but it also keeps me trapped there, in a way. + +And then I wonder if there is a key to release the trap anywhere when youโ€™re a trafficking survivor, or if itโ€™s sort of like how sometimes when people get shot they have to leave bullet fragments in the body because itโ€™s too dangerous to try and remove them. You know? Like, maybe itโ€™s just something you have to carry inside of you as you try to move forward, because going back through it would just make things worse. Maybe coping with fiction is as far as Iโ€™m going to get. + +I am in therapy. I see two therapists! I do ketamine therapy twice a week. I literally have appointments 4/5 days a week. Yet here I remain, just barely hanging on, handcuffed to the pole. + +Sometimes I find myself getting confused. I forget that Star Trek technology โ€“ and Star Trek peace โ€“ isnโ€™t real. I forget that it isnโ€™t that easy. I forget that the peace in Star Trek is just as precarious and blood-soaked as it would be in real life. But itโ€™s easier to live somewhere I feel accepted than live in this universe where the only hobby Iโ€™m truly capable of having is retraumatizing myself. + +I want to write about something else now. + diff --git a/blogroll.njk b/blogroll.njk new file mode 100755 index 0000000..c4f98bc --- /dev/null +++ b/blogroll.njk @@ -0,0 +1,56 @@ +--- +layout: layouts/base.njk +permalink: "/blogroll/" +title: Blogroll +--- +

Blogroll

+ +
+

Here are some blogs and websites I follow and recommend. This is a curated list of quality content creators in the web development, design, and IndieWeb communities.

+
+ +
+
+

Web Development

+
+
+

+ Example Blog +

+

Description of the blog and why you recommend it.

+
+ +
+
+ +
+

Design & UX

+
+
+

+ Design Blog +

+

Great insights on design and user experience.

+
+
+
+ +
+

IndieWeb & Personal Sites

+
+
+

+ Personal Site +

+

Excellent example of IndieWeb principles in action.

+
+
+
+
+ +
+

+ Want to be added? If you have a blog that fits these categories, feel free to + reach out and let me know! +

+
diff --git a/bookshelf.njk b/bookshelf.njk new file mode 100755 index 0000000..b2a60b1 --- /dev/null +++ b/bookshelf.njk @@ -0,0 +1,46 @@ +--- +layout: layouts/base.njk +title: Bookshelf +permalink: /bookshelf/ +--- + +

Bookshelf

+

A living reading list. Track what you're reading, want to read, and your notes/reviews.

+ +
+
+

Reading

+
    +
  • + Designing for Accessibility +
    Notes: practical patterns for forms and focus
    +
  • +
  • + The Pragmatic Programmer +
    Notes: small steps, continuous improvement
    +
  • +
+
+ +
+

Finished

+
    +
  • + Atomic Habits +
    Takeaway: environment design beats willpower
    +
  • +
  • + Refactoring UI +
    Takeaway: spacing & contrast are the 80/20
    +
  • +
+
+ +
+

Want to Read

+
    +
  • Inclusive Components
  • +
  • Every Layout
  • +
+
+
diff --git a/buttonwall.md b/buttonwall.md new file mode 100644 index 0000000..ce75302 --- /dev/null +++ b/buttonwall.md @@ -0,0 +1,13 @@ +--- +layout: layouts/base.njk +permalink: "/buttonwall/" +title: Button Wall +--- + +

Button Wall

+Would you like to add my button? + +button for the site agnes.love + + +friends, mutuals, cool internet people i like:

button for serpentinemalignbutton for euonoiabutton for linkybutton for hellomeibutton for maevedarcybutton for overmorebutton for herewithin diff --git a/categories.njk b/categories.njk new file mode 100755 index 0000000..4f4e454 --- /dev/null +++ b/categories.njk @@ -0,0 +1,50 @@ +--- +layout: layouts/base.njk +pagination: + data: collections.categoryList + size: 1 + alias: category + addAllPagesToCollections: true +permalink: /categories/{{ category | slug }}/ +eleventyComputed: + title: "Posts in '{{ category }}'" +--- +

Posts in + {{ category }} +

+ +{% set catPosts = [] %} +{% for post in collections.posts %} + {% if post.data.category and post.data.category == category %} + {% set catPosts = (catPosts.push(post), catPosts) %} + {% endif %} +{% endfor %} + +{% if catPosts.length > 0 %} +
+ {% for post in catPosts %} +
+

+ {{ post.data.title }} +

+ +

+ {{ post.data.description or (post.templateContent | striptags | truncate(160)) }} +

+
+ {% if post.data.tags %} + {% for postTag in post.data.tags %} + #{{ postTag }} + {% endfor %} + {% endif %} +
+
+ {% endfor %} +
+{% else %} +

No posts found in this category.

+{% endif %} diff --git a/categories/index.njk b/categories/index.njk new file mode 100644 index 0000000..ace4ec6 --- /dev/null +++ b/categories/index.njk @@ -0,0 +1,25 @@ +--- +layout: layouts/base.njk +title: Categories +permalink: /categories/ +--- +

Categories

+ +{% if collections.categoryList and collections.categoryList.length %} +
    + {% for cat in collections.categoryList %} + {% set count = 0 %} + {% for post in collections.posts %} + {% if post.data.category and post.data.category == cat %} + {% set count = count + 1 %} + {% endif %} + {% endfor %} +
  • + {{ cat }} + {{ count }} post{% if count != 1 %}s{% endif %} +
  • + {% endfor %} +
+{% else %} +

No categories yet.

+{% endif %} diff --git a/category.njk b/category.njk new file mode 100755 index 0000000..05b456c --- /dev/null +++ b/category.njk @@ -0,0 +1,8 @@ +--- +permalink: false +eleventyExcludeFromCollections: true +--- +{# + This file is intentionally disabled to avoid output conflicts. + Per-category pages are generated by `src/categories.njk`. +#} diff --git a/contact.njk b/contact.njk new file mode 100755 index 0000000..65cfd59 --- /dev/null +++ b/contact.njk @@ -0,0 +1,36 @@ +--- +layout: layouts/base.njk +permalink: "/contact/" +title: Contact +--- +

Get in Touch

+ +

Feel free to reach out to me about pretty much anything. +

+
+

Get in Touch

+ +
+ + +
diff --git a/donate.njk b/donate.njk new file mode 100755 index 0000000..46271d6 --- /dev/null +++ b/donate.njk @@ -0,0 +1,29 @@ +--- +layout: layouts/base.njk +permalink: "/donate/" +title: Support My Work +--- +

Support My Work

+ +
+ {% if site.donate.message %} +

{{ site.donate.message }}

+ {% else %} +

If you like what I do or any of the sites I host, and you'd like to support me, you can do so here:

+ {% endif %} + + Buy Me a Coffee at ko-fi.com + {% if site.donate.github %} +

Ongoing Support

+

For ongoing support, consider sponsoring me on GitHub:

+ + + + {% endif %} + +
diff --git a/feed.xml b/feed.xml new file mode 100755 index 0000000..7f7af74 --- /dev/null +++ b/feed.xml @@ -0,0 +1,38 @@ +--- +permalink: /feed.xml +eleventyExcludeFromCollections: true +templateEngine: njk +--- + + + {{ site.name }} + {{ site.description }} + + + {% if collections.posts and (collections.posts | length) %} + {{ collections.posts[0].date | htmlDateString }}T00:00:00Z + {% else %} + {{ '1970-01-01' }} + {% endif %} + {{ site.url }}/ + + {{ site.author }} + + {% if collections.posts and (collections.posts | length) %} + {% for post in collections.posts | slice(0, 20) %} + + {{ post.data.title }} + + {{ post.date | htmlDateString }}T00:00:00Z + {{ site.url }}{{ post.url }} + {{ post.templateContent | htmlToAbsoluteUrls(site.url) }} + {% if post.data.description %} + {{ post.data.description }} + {% endif %} + {% for tag in post.data.tags %} + + {% endfor %} + + {% endfor %} + {% endif %} + diff --git a/hosted.njk b/hosted.njk new file mode 100644 index 0000000..dffa83b --- /dev/null +++ b/hosted.njk @@ -0,0 +1,19 @@ +--- +layout: layouts/base.njk +permalink: "/hosted/" +title: Hosted +--- + +

SERVICES I HOST!!

+ +Here is a long list of all the things I do on the web.

+ +
  • Sillywordz, a fork of statuscafe that lets you embed your current word count into your site
  • +
  • Cheesy, food microblogging +
  • Status.cafe (regular)
  • +
  • Fandom.cooking, public multifandom cookbook
  • +
  • Sunset Archive, an archive running on the same code as AO3 dedicated to F/F, NB/F and NB/NB sapphic fanworks
  • +

    +
  • Personal fanart archive
  • +
  • Bookmarks and resources

  • +More coming soon.... diff --git a/index.njk b/index.njk new file mode 100755 index 0000000..77faca7 --- /dev/null +++ b/index.njk @@ -0,0 +1,113 @@ +--- +layout: layouts/base.njk +permalink: "/" +title: "AGNES THE ALIEN!" +--- +
    currently...
    reading: the orange eats creeps, +serious weakness
    watching:star trek: voyager, paradise
    listening to: bloc party, cupcakke
    + +
    A stylized bust-level drawing of me, a white feminine individual with heart shaped glasses, pink and green pigtails, and a teal halter top. I am saying WELCOME which is written in stylized pink text +

    {{ site.name }}

    +

    {{ site.description }}

    + + +
    +

    + Hey, I'm Agnes! I'm a writer, artist, hobbyist computerdyke, and real life alien from outer space. This is my personal site and weblog. Feel free to check out what I have here!

    + +
    +Current status:
    {% postGraph collections.posts %} +
    +webrings, cliques & more...
    Language Learning ๐Ÿ’š Japanese, Python & Welsh
    +unproblematic blorbo โฅ teleya
    +
    FEMSLASH FANS ONLINE WEBRING
    +MY femslash OTP is...
    +๐Ÿ’ž NAHLA X ANISHA ! ๐Ÿ’ž
    + previous | + random | + next
    +
    +
    + +
    + + ๐Ÿ“ก Subscribe via RSS + +
    +
    + + +
    +

    + ๐ŸŒŒ Recent Posts +

    + + {% set recent = collections.posts | default([]) %} + {% if (recent | length) == 0 %} + {% set recent = collections.searchIndex | default([]) %} + {% endif %} + + {% if recent | length > 0 %} +
    + {% for post in recent | head(5) %} + {% set url = post.url or post.id %} + {% set title = (post.data and post.data.title) or post.title %} + {% set dateVal = post.date %} + {% set desc = (post.data and post.data.description) or post.description or (post.templateContent | default('') | striptags | truncate(160)) %} + {% set tags = (post.data and post.data.tags) or post.tags or [] %} +
    +

    + + {{ title }} + +

    + {% if dateVal %} + + {% endif %} + {% if desc %} +

    + {{ desc }} +

    + {% endif %} + {% if tags %} +
    + {% for tag in tags %} + #{{ tag }} + {% endfor %} +
    + {% endif %} +
    + {% endfor %} +
    + + + {% else %} +
    +

    No posts yet!

    +

    This is where thoughtful writing will appear. Stay tuned! ๐Ÿ“

    +
    + {% endif %} +
    + + + + + +
    ๐ŸŒŒ
    +

    Explore the galaxy...

    +

    All pages on this site

    +
    + + diff --git a/journal/day-one.md b/journal/day-one.md new file mode 100644 index 0000000..6d67dad --- /dev/null +++ b/journal/day-one.md @@ -0,0 +1,7 @@ +--- +layout: layouts/journal.njk +title: Day One +description: Starting the journal as a collection. +--- + +Today I migrated the Journal section into a proper Eleventy collection. Each entry gets its own permalink and shows up on the listing page. diff --git a/journal/week-two.md b/journal/week-two.md new file mode 100644 index 0000000..b9df8a7 --- /dev/null +++ b/journal/week-two.md @@ -0,0 +1,7 @@ +--- +layout: layouts/journal.njk +title: Week Two +description: Settling into a rhythm. +--- + +Second week of writing. The collections pattern keeps things tidy and discoverable. Next up: pagination and tests. diff --git a/links.njk b/links.njk new file mode 100755 index 0000000..fc2abce --- /dev/null +++ b/links.njk @@ -0,0 +1,37 @@ +--- +layout: layouts/base.njk +title: Links +permalink: /links/ +--- + +

    Links

    +

    A curated index of sites, references, and tools. Replace these with your own favorites or wire up a bookmarks feed.

    + +
    +
    +

    Web Development

    +
      +
    • Eleventy โ€” Static site generator with a small, flexible core.
    • +
    • Playwright โ€” Reliable endโ€‘toโ€‘end testing across browsers.
    • +
    • web.dev โ€” Guides on performance and modern web APIs.
    • +
    +
    + +
    +

    IndieWeb & Publishing

    + +
    + +
    +

    Design & Accessibility

    + +
    +
    diff --git a/manifest.webmanifest b/manifest.webmanifest new file mode 100755 index 0000000..4c64541 --- /dev/null +++ b/manifest.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "Indieweb Starter Blog", + "short_name": "Indieweb Blog", + "start_url": "/", + "scope": "/", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#a78bfa", + "icons": [ + { "src": "/assets/favicon-16x16.png", "sizes": "16x16", "type": "image/png" }, + { "src": "/assets/favicon-32x32.png", "sizes": "32x32", "type": "image/png" }, + { "src": "/assets/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" } + ] +} diff --git a/notes.njk b/notes.njk new file mode 100755 index 0000000..95f6e5a --- /dev/null +++ b/notes.njk @@ -0,0 +1,48 @@ +--- +layout: layouts/base.njk +title: Notes +pagination: + data: collections.notes + size: 10 + alias: items + reverse: true +permalink: "/notes/{% if pagination.pageNumber > 0 %}page-{{ pagination.pageNumber + 1 }}/{% endif %}" +--- + +

    Notes

    +

    Short, linkable thoughts. Each note has its own permalink.

    + +{% set items = items | default([]) %} +{% if (items | length) == 0 %} +

    No notes yet. Add files under src/notes/.

    +{% else %} +
    + {% for item in items %} +
    +

    {{ item.data.title or 'Untitled' }}

    + {% if item.date %} + + {% endif %} + {% if item.data.description %} +

    {{ item.data.description }}

    + {% endif %} +
    + {% endfor %} +
    + + +{% endif %} diff --git a/notes/first-note.md b/notes/first-note.md new file mode 100644 index 0000000..d89c496 --- /dev/null +++ b/notes/first-note.md @@ -0,0 +1,7 @@ +--- +layout: layouts/note.njk +title: First Note +description: A tiny note to kick off the notes collection. +--- + +A small thought to test the notes collection. Links, ideas, and references belong here. diff --git a/notes/second-note.md b/notes/second-note.md new file mode 100644 index 0000000..2a1370b --- /dev/null +++ b/notes/second-note.md @@ -0,0 +1,7 @@ +--- +layout: layouts/note.njk +title: Second Note +description: Another brief thought to test pagination and listing. +--- + +Design with constraints: a short page title, a clear hierarchy, and readable line length go a long way. diff --git a/notes/third-note.md b/notes/third-note.md new file mode 100644 index 0000000..3c18a5b --- /dev/null +++ b/notes/third-note.md @@ -0,0 +1,7 @@ +--- +layout: layouts/note.njk +title: Third Note +description: Shortcuts make habits stick. +--- + +Create keyboard shortcuts for frequent tasks. Friction is the enemy of consistency. diff --git a/now.njk b/now.njk new file mode 100755 index 0000000..21ded5d --- /dev/null +++ b/now.njk @@ -0,0 +1,46 @@ +--- +layout: layouts/base.njk +permalink: "/now/" +title: Now +--- +

    What I'm Doing Now

    + + +inspired by nownownow.com +
    +Life...

    +Currently finally moving on from 20 years of treatment resistant depression, which is nice, and finally getting treatment for my lifelong PMDD, which will hopefully take care of the rest of my suffering. I'm writing this on June 20, 2026, which means I'm turning 25 in exactly a week. That's pretty wild, considering I never planned to make it past the age of eighteen.

    +I'm at peace with my life currently. I'm frightened by the current state of the world, but I have hope. I love my friends and family and partner and pets. I finally feel like I have some sort of tangible, beautiful future? AGAIN: crazy, because I've never known this kind of contentment and hope. I'm squeezing all the juice I can out of every second of my life; I'm not going to let it go to waste. +

    + +Something a lot of people don't talk about is the post-suicidal phase of life. You know, what happens when you've been suicidal since the single digits and it's all you know how to be, and now you have to learn what it's like to want to be around. It might not sound like it, but it's a real adjustment! For so long I have felt like my life is ephemeral, but it isn't. I can make something of it. I just need to figure out how. +

    +My life is relatively limited by my health issues, but I want to do as much as I possibly can, both inside and outside of the home. I'm about to start college this August, where I'll be a religious studies major with the goal of volunteering in medical chaplaincy. The one field I can do that I do not think will be replaced by AI any time soon...

    +I'm excited for what comes next. + +
    + +Projects...

    + +In October 2025, I launched Sunset Archive, a fanfiction archive using AO3's code dedicated to F/F, F/NB and NB/NB sapphic fanworks. It was rocky at the start, but it has ended up being incredibly rewarding. Now, as I move forward with my mental health and continue to improve, I'm thinking of launching an entire "femslash web"; a cluster of social services and tools made by and for femslash fans, where we come first, and where femslash is freely accessible to those who are looking as opposed to being a needle in a haystack. +I'm very passionate about fandom and sapphic works. I don't know if this will come to fruition, but it is my dream... +

    +I'm currently working on a cluster of short stories and am brainstorming a novel, and I recently got a v-gen artist account and plan to open writing commissions soon. +As I write this, it is late June, so ArtFight will be starting soon! This year I'm getting into making jewelry so I can do craft attacks, and just because I want to make jewelry in general, since so many people in my family work with it. +

    In fact, here's a practice necklace I made:
    +A necklace composed of red heart shaped gems. It has a blue UFO pendant. +

    I'm pretty proud of it :-) +
    +Goals... +

    +
  • To successfully use my DBT skills when necessary to avoid having a breakdown
  • +
  • To finish a novel by June 2027
  • +
  • To write at least 150k by the end of the year
  • +
  • To get a short story professionally published
  • +
  • To continue to improve with my digital art and my crafts
  • +
  • To learn music theory
  • +
  • To finish my freshman year of college with at least a 3.8 GPA.
  • +

    + Last updated: +

    + diff --git a/poetry.njk b/poetry.njk new file mode 100755 index 0000000..e7c9e6d --- /dev/null +++ b/poetry.njk @@ -0,0 +1,44 @@ +--- +layout: layouts/base.njk +title: Poetry +pagination: + data: collections.poetry + size: 10 + alias: items + reverse: true +permalink: "/poetry/{% if pagination.pageNumber > 0 %}page-{{ pagination.pageNumber + 1 }}/{% endif %}" +--- + +

    Poetry

    +

    Collected poems with their own pages.

    + +{% set items = items | default([]) %} +{% if items | length == 0 %} +

    No poems yet. Add files under src/poetry/.

    +{% else %} +
    + {% for item in items %} + + {% endfor %} +
    + +{% endif %} diff --git a/poetry/build-logs.md b/poetry/build-logs.md new file mode 100644 index 0000000..0f2a3be --- /dev/null +++ b/poetry/build-logs.md @@ -0,0 +1,12 @@ +--- +layout: layouts/poem.njk +title: Build Logs +description: On learning by walking the meadow of errors. +--- + +``` +Errors bloom +like wildflowers โ€” +you learn the meadow +by walking it. +``` diff --git a/poetry/night-shift.md b/poetry/night-shift.md new file mode 100644 index 0000000..1dd69b1 --- /dev/null +++ b/poetry/night-shift.md @@ -0,0 +1,12 @@ +--- +layout: layouts/poem.njk +title: Night Shift +description: A late session at the keyboard. +--- + +``` +Cursor blinks โ€” +the room hums low โ€” +ideas compile +into morning. +``` diff --git a/poetry/static-garden.md b/poetry/static-garden.md new file mode 100644 index 0000000..1cc522e --- /dev/null +++ b/poetry/static-garden.md @@ -0,0 +1,13 @@ +--- +layout: layouts/poem.njk +title: Static Garden +description: A short poem about websites as gardens. +--- + +``` +I plant pages +in a quiet repo โ€” +permalinks +growing paths +to places worth returning. +``` diff --git a/portfolio.njk b/portfolio.njk new file mode 100755 index 0000000..d972bd9 --- /dev/null +++ b/portfolio.njk @@ -0,0 +1,30 @@ +--- +layout: layouts/base.njk +title: Portfolio +permalink: /portfolio/ +--- + +

    Portfolio

    +

    Showcase selected work. Replace with your own projects and case studies.

    + +
    +
    +

    Static Blog Template

    +

    An Eleventy starter focused on accessibility, IndieWeb features, and reliable E2E tests.

    +
      +
    • Accessible navigation and skip links
    • +
    • Open Graph/Twitter meta defaults
    • +
    • Playwright tests (responsive, a11y flows, search)
    • +
    +
    + +
    +

    Design System Pages

    +

    A living style guide to keep typography and components consistent.

    +
    + +
    +

    Interested in working together?

    +

    Add your services and contact details here.

    +
    +
    diff --git a/projects.njk b/projects.njk new file mode 100755 index 0000000..72b4c3f --- /dev/null +++ b/projects.njk @@ -0,0 +1,25 @@ +--- +layout: layouts/base.njk +title: Projects +permalink: /projects/ +--- + +

    Projects

    +

    Open-source and personal experiments. Replace with your own projects or migrate to a projects collection.

    + +
      +
    • +

      Eleventy Blog Starter

      +

      Accessible, IndieWeb-friendly, and tested with Playwright.

      +
      + eleventy + a11y + testing +
      +
    • + +
    • +

      Minimal Style Guide

      +

      A living page to document typography and components.

      +
    • +
    diff --git a/resume.njk b/resume.njk new file mode 100755 index 0000000..679eb69 --- /dev/null +++ b/resume.njk @@ -0,0 +1,45 @@ +--- +layout: layouts/base.njk +title: Rรฉsumรฉ +permalink: /resume/ +--- + +

    Rรฉsumรฉ

    +

    A template CV you can adapt. Replace section content with your details or link to a PDF.

    + +
    + Download PDF + Add your static PDF at src/assets/ and update this link. +
    + +
    +

    Summary

    +

    Front-end oriented web developer focused on accessibility, performance, and maintainable static sites. Comfortable with modern tooling and progressive enhancement.

    + +

    Experience

    +

    Senior Web Developer ยท Company Name

    +

    2023 โ€” Present

    +
      +
    • Built static-first sites with Eleventy and automated deployments.
    • +
    • Established a11y testing and CI checks.
    • +
    • Collaborated with design on a living style guide.
    • +
    + +

    Front-end Engineer ยท Organization

    +

    2020 โ€” 2023

    +
      +
    • Implemented component libraries with semantic HTML and utility CSS.
    • +
    • Optimized web vitals via preloading and code-splitting.
    • +
    + +

    Skills

    +
      +
    • HTML, CSS (Tailwind), JavaScript
    • +
    • Eleventy, Nunjucks, Markdown
    • +
    • Accessibility, Testing (Playwright)
    • +
    • SEO, Open Graph, microformats2
    • +
    + +

    Education

    +

    Degree / Program โ€” School Name

    +
    diff --git a/search-results.njk b/search-results.njk new file mode 100755 index 0000000..5add0e2 --- /dev/null +++ b/search-results.njk @@ -0,0 +1,278 @@ +--- +layout: layouts/base.njk +permalink: "/search/" +title: "Search Results" +--- +
    +

    + ๐Ÿ” Search Results +

    + + + + + + + + + + + + + + +
    +
    +
    ๐Ÿ”
    +

    Search the site

    +

    + Find posts, pages, and content across the entire site. +

    +
    + + +
    +
    +

    ๐Ÿ“ Recent Posts

    + {% if collections.posts.length > 0 %} + + {% else %} +

    No posts yet.

    + {% endif %} +
    + +
    +

    ๐Ÿท๏ธ Popular Tags

    + {% if collections.tagList.length > 0 %} +
    + {% for tag in collections.tagList | slice(0, 10) %} + + #{{ tag }} + + {% endfor %} +
    + {% else %} +

    No tags yet.

    + {% endif %} +
    +
    + + +
    +

    ๐Ÿ’ก Search Tips

    +
      +
    • โ€ข Use specific keywords for better results
    • +
    • โ€ข Search works across post titles, content, and tags
    • +
    • โ€ข Try different variations of your search terms
    • +
    • โ€ข Browse by tags or the archive for discovery
    • +
    +
    +
    +
    + + diff --git a/search.json b/search.json new file mode 100755 index 0000000..e69de29 diff --git a/search.njk b/search.njk new file mode 100755 index 0000000..b8cd4ba --- /dev/null +++ b/search.njk @@ -0,0 +1,9 @@ +--- +permalink: /search.json +eleventyExcludeFromCollections: true +--- +{%- if collections.searchIndex -%} +{{ collections.searchIndex | json | safe }} +{%- else -%} +[] +{%- endif -%} diff --git a/sitemap.njk b/sitemap.njk new file mode 100755 index 0000000..7c3b96b --- /dev/null +++ b/sitemap.njk @@ -0,0 +1,92 @@ +--- +layout: layouts/base.njk +permalink: "/sitemap/" +title: Site Directory +--- +
    +

    + ๐ŸŒŒ Sitemap

    +

    + All pages in the galaxy.

    + +
    + +
    +

    ๐ŸŒŒ Main Pages

    + +
    + + + + + + + + + +
    +

    ๐Ÿ“ Recent Posts

    + + {# Fallback to searchIndex like homepage if posts collection is empty #} + {% set recent = collections.posts | default([]) %} + {% if (recent | length) == 0 %} + {% set recent = collections.searchIndex | default([]) %} + {% endif %} + + {% if recent | length > 0 %} + + {% else %} +

    No posts yet. Start writing!

    + {% endif %} +
    + + +
    +

    ๐ŸŽช Fun Stuff

    +
      +
    • ๐ŸŽฎ Try the Konami code
    • +
    • ๐Ÿ–ฑ๏ธ Click the logo 7 times
    • +
    • โŒจ๏ธ Type nahleb anywhere
    • +
    • ๐ŸŒ™ Toggle dark mode
    • +
    +
    +
    + + +
    diff --git a/style.njk b/style.njk new file mode 100755 index 0000000..a5ea703 --- /dev/null +++ b/style.njk @@ -0,0 +1,105 @@ +--- +layout: layouts/base.njk +permalink: "/style/" +title: Style Guide +--- +

    Style Guide

    + +
    +
    +

    Typography

    +
    +
    +

    Heading 1

    +

    Heading 2

    +

    Heading 3

    +

    Heading 4

    +
    +

    This is regular paragraph text. It should be readable and comfortable for extended reading sessions.

    +

    This is smaller text used for metadata and secondary information.

    +
    +
    + +
    +

    Colors

    +
    +
    +
    +

    Primary Blue

    +
    +
    +
    +

    Gray

    +
    +
    +
    +

    Success Green

    +
    +
    +
    +

    Error Red

    +
    +
    +
    + +
    +

    Components

    + +
    +
    +

    Buttons

    +
    + + +
    +
    + +
    +

    Tags

    +
    + #example + #tag + #demo +
    +
    + +
    +

    Cards

    +
    +

    Card Title

    +

    This is an example card component with some content.

    +
    +
    +
    +
    + +
    +

    Prose Styles

    +
    +

    This section demonstrates the prose styling used for blog content.

    + +
    +

    This is a blockquote. It should stand out from regular text and be easily identifiable.

    +
    + +
      +
    • Unordered list item one
    • +
    • Unordered list item two
    • +
    • Unordered list item three
    • +
    + +
      +
    1. Ordered list item one
    2. +
    3. Ordered list item two
    4. +
    5. Ordered list item three
    6. +
    + +
    // Code block example
    +function example() {
    +  return "Hello, world!";
    +}
    + +

    Here's some text with inline code and a link example.

    +
    +
    +
    diff --git a/sw.js b/sw.js new file mode 100755 index 0000000..3f240be --- /dev/null +++ b/sw.js @@ -0,0 +1,35 @@ +/* Basic offline-first service worker */ +const CACHE_NAME = 'indieweb-blog-v1'; +const OFFLINE_URLS = [ + '/', + '/assets/css/build.css', + '/assets/js/main.js', + '/assets/favicon-32x32.png', + '/assets/apple-touch-icon.png' +]; + +self.addEventListener('install', (event) => { + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => cache.addAll(OFFLINE_URLS)).then(() => self.skipWaiting()) + ); +}); + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((keys) => Promise.all(keys.map((k) => (k === CACHE_NAME ? null : caches.delete(k))))).then(() => self.clients.claim()) + ); +}); + +self.addEventListener('fetch', (event) => { + const { request } = event; + if (request.method !== 'GET') return; + event.respondWith( + caches.match(request).then((cached) => + cached || fetch(request).then((resp) => { + const respClone = resp.clone(); + caches.open(CACHE_NAME).then((cache) => cache.put(request, respClone)); + return resp; + }).catch(() => caches.match('/')) + ) + ); +}); diff --git a/tags.njk b/tags.njk new file mode 100755 index 0000000..e55cadf --- /dev/null +++ b/tags.njk @@ -0,0 +1,58 @@ +--- +layout: layouts/base.njk +pagination: + data: collections.tagList + size: 1 + alias: tag + addAllPagesToCollections: true +permalink: /tags/{{ tag | slug }}/ +eleventyComputed: + title: "Posts tagged '{{ tag }}'" +--- +

    Posts tagged + #{{ tag }} +

    + +{% set currentSlug = (tag | slug) %} +{% set taggedPosts = [] %} +{% for post in collections.posts %} + {% set matched = false %} + {% if post.data.tags %} + {% for t in post.data.tags %} + {% if (t | slug) == currentSlug %} + {% set matched = true %} + {% endif %} + {% endfor %} + {% endif %} + {% if matched %} + {% set taggedPosts = (taggedPosts.push(post), taggedPosts) %} + {% endif %} +{% endfor %} + +{% if taggedPosts.length > 0 %} +
    + {% for post in taggedPosts %} +
    +

    + {{ post.data.title }} +

    + +

    + {{ post.data.description or (post.templateContent | striptags | truncate(160)) }} +

    +
    + {% for postTag in post.data.tags %} + #{{ postTag }} + {% endfor %} +
    +
    + {% endfor %} +
    +{% else %} +

    No posts found with this tag.

    +{% endif %} diff --git a/tags/index.njk b/tags/index.njk new file mode 100644 index 0000000..fd97594 --- /dev/null +++ b/tags/index.njk @@ -0,0 +1,25 @@ +--- +layout: layouts/base.njk +title: Tags +permalink: /tags/ +--- +

    Tags

    + +{% if collections.tagList and collections.tagList.length %} +
      + {% for t in collections.tagList %} + {% set count = 0 %} + {% for post in collections.posts %} + {% if post.data.tags and (t in post.data.tags) %} + {% set count = count + 1 %} + {% endif %} + {% endfor %} +
    • + #{{ t }} + {{ count }} post{% if count != 1 %}s{% endif %} +
    • + {% endfor %} +
    +{% else %} +

    No tags yet.

    +{% endif %} diff --git a/type.njk b/type.njk new file mode 100755 index 0000000..a2fbdd1 --- /dev/null +++ b/type.njk @@ -0,0 +1,66 @@ +--- +layout: layouts/base.njk +title: Type +permalink: /type/ +--- + +

    Type Scale & Components

    +

    A living typography page for quick visual checks. Tweak sizes in tailwind.config.cjs or override via utilities.

    + +
    +

    Fonts Used

    +

    This template uses the system UI font stack by default for speed and readability, and a system monospace stack for code.

    +
      +
    • Body/UI: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
    • +
    • Monospace: the browser's default monospace stack via Tailwind's font-mono utility
    • +
    +

    Defined in src/assets/css/tailwind.css:

    +
    /* src/assets/css/tailwind.css */
    +body {
    +  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    +}
    +.system-fonts {
    +  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    +}
    +
    +

    To change fonts, you can:

    +
      +
    1. Swap the body { font-family: ... } in src/assets/css/tailwind.css.
    2. +
    3. Optionally add fontFamily under theme.extend in tailwind.config.cjs and use Tailwind utilities (e.g., font-sans, font-mono).
    4. +
    +
    + +
    +

    Heading 1

    +

    Heading 2

    +

    Heading 3

    +

    Heading 4

    +

    + Body copy with bold and emphasis. Links look like + this inline link. Small text appears as + supporting detail. +

    + +

    Lists

    +
      +
    • Unordered list item
    • +
    • With sufficient spacing
    • +
    +
      +
    1. Ordered list item
    2. +
    3. Use lists for steps
    4. +
    + +

    Blockquote

    +
    + Ship small improvements often. The garden grows one commit at a time. +
    + +

    Code

    +
    // Syntax highlighting is provided client-side via Highlight.js
    +function greet(name) {
    +  return `Hello, ${name}!`;
    +}
    +console.log(greet('world'));
    +
    +
    diff --git a/uses.njk b/uses.njk new file mode 100755 index 0000000..029f790 --- /dev/null +++ b/uses.njk @@ -0,0 +1,33 @@ +--- +layout: layouts/base.njk +permalink: "/uses/" +title: Uses +--- +

    Things I Use

    + +
    +
    + What I Use For... a personal laptop: HP 15.6" touchscreen business & home laptop, 8GB RAM, 512GB SSD, Windows 10 + What I Use For... an MP3 player: AiMoonsa MP3 player, 64GB, Black
    + What I Use For... a digital calendar: Anyuse 10.1" digital calendar chore chart
    + What I Use For... TV and Media: 40" onn. Roku TV, Panasonic DVD Bluray player, YOTON portable 9" DVD player
    + What I Use For... a digital typewriter: Freewrite Alpha
    +What I Use For... a smart watch Tesky smart watch
    +What I Use For.. drawing: Samsung Galaxy Tab A7, IbispaintX
    +What I Use For... e-books: XTE Ink X4
    +What I Use For... gaming: Nintendo Switch

    + What I Use For... this site: Eleventy with CLI deployment to Neocities, using this blog theme (thank you Brennan!)
    + What I Use For... servers: + +
  • 2x HP ProBooks, 8GB RAM, 512GB/EA SSD || Runs: personal fediverse, piefed, beszel
  • +
  • HP Envy, 12GB RAM, 1TB SSD || Runs: Sunset
  • +
  • 2x HP Pavilion, 16GB RAM, 1TB SSD || Runs: Cheesy, Rails sites, Fandom.Cooking, UptimeKuma, fanart archive
  • +
  • Dell Inspiron All in one desktop, 64GB RAM, 4TB SSD || Runs: Dreamwidth clone, PHPbb forums, forgejo, BookWyrm, FreshRSS, LinkDing, SillyWordz, Status.cafe, personal archive, Ovumcy
    +
  • HP 255 G10 Professional Business Laptop, 64GB RAM, 2TB SSD || Runs: nothing yet...
  • + + +
    + +

    + This page is inspired by uses.tech +