mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-04-02 16:44:56 +02:00
a11y: comprehensive WCAG 2.1 Level AA accessibility audit
- Add skip-to-main-content link and main content ID target - Add prefers-reduced-motion media queries for all animations - Enhance visible focus indicators (2px offset, high-contrast ring) - Replace ~160 text-surface-500 instances with text-surface-600/dark:text-surface-400 for 4.5:1+ contrast ratio compliance - Add aria-hidden="true" to ~30+ decorative SVG icons across sidebars/widgets - Convert facepile containers from div to semantic ul/li with role="list" - Add aria-label to icon-only buttons (share, sort controls) - Add sr-only labels to form inputs (webmention, search) - Add aria-live="polite" to dynamically loaded webmentions - Add aria-label with relative+absolute date to time-difference component - Add keyboard handlers (Enter/Space) to custom interactive elements - Add aria-label to nav landmarks (table of contents) - Fix modal focus trap and dialog accessibility - Fix lightbox keyboard navigation and screen reader announcements Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88
This commit is contained in:
@@ -46,23 +46,23 @@
|
||||
{% elif widget.type == "fediverse-follow" %}
|
||||
{% set widgetIcon = "user-plus" %}{% set widgetIconClass = "w-5 h-5 text-[#a730b8]" %}{% set widgetBorder = "border-l-[3px] border-l-[#a730b8]" %}
|
||||
{% elif widget.type == "author-card" or widget.type == "author-card-compact" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-posts" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "categories" or widget.type == "post-categories" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-comments" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "search" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "webmentions" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "ai-usage" %}
|
||||
{% set widgetIcon = "zap" %}{% set widgetIconClass = "w-5 h-5 text-amber-500" %}{% set widgetBorder = "border-l-[3px] border-l-amber-400 dark:border-l-amber-500" %}
|
||||
{% elif widget.type == "toc" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "share" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% else %}
|
||||
{% set widgetIcon = "" %}{% set widgetIconClass = "" %}{% set widgetBorder = "" %}
|
||||
{% endif %}
|
||||
@@ -89,6 +89,7 @@
|
||||
class="widget-chevron"
|
||||
:class="open && 'rotate-180'"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
@@ -169,8 +170,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : true }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("user", "w-5 h-5 text-surface-500") }} Author</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("user", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Author</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/author-card-compact.njk" %}
|
||||
@@ -183,8 +184,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : true }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-500") }} Table of Contents</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Table of Contents</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/toc.njk" %}
|
||||
@@ -197,8 +198,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : true }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("tag", "w-5 h-5 text-surface-500") }} Categories</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("tag", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Categories</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/post-categories.njk" %}
|
||||
@@ -211,8 +212,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-500") }} Recent Posts</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Recent Posts</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/recent-posts-blog.njk" %}
|
||||
@@ -225,8 +226,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("share", "w-5 h-5 text-surface-500") }} Webmentions</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("share", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Webmentions</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/webmentions.njk" %}
|
||||
@@ -239,8 +240,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("share", "w-5 h-5 text-surface-500") }} Share</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("share", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Share</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/share.njk" %}
|
||||
@@ -254,7 +255,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-orange-400 dark:border-l-orange-500">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("rss", "w-5 h-5 text-orange-500") }} Subscribe</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/subscribe.njk" %}
|
||||
@@ -267,8 +268,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("chat", "w-5 h-5 text-surface-500") }} Recent Comments</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("chat", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Recent Comments</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/recent-comments.njk" %}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<div class="mt-4">
|
||||
{# Status messages #}
|
||||
<div x-show="statusMessage" x-cloak
|
||||
role="alert"
|
||||
x-bind:class="statusType === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400' :
|
||||
statusType === 'success' ? 'bg-green-50 text-green-700 dark:bg-green-900/20 dark:text-green-400' :
|
||||
'bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:text-blue-400'"
|
||||
@@ -54,12 +55,13 @@
|
||||
</div>
|
||||
|
||||
<form x-on:submit.prevent="submitComment()">
|
||||
<textarea x-model="commentText" rows="4" required
|
||||
<label for="comment-text" class="sr-only">Your comment</label>
|
||||
<textarea id="comment-text" x-model="commentText" rows="4" required
|
||||
placeholder="Share your thoughts... (supports **bold**, *italic*, and [links](url))"
|
||||
class="w-full px-3 py-2 border rounded-lg mb-2 dark:bg-surface-800 dark:border-surface-700 dark:text-surface-100"
|
||||
x-bind:maxlength="maxLength"></textarea>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-surface-500" x-text="commentText.length + '/' + maxLength"></span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400" x-text="commentText.length + '/' + maxLength"></span>
|
||||
<button type="submit" class="button" x-bind:disabled="submitting">
|
||||
<span x-show="!submitting">Post Comment</span>
|
||||
<span x-show="submitting" x-cloak>Posting...</span>
|
||||
@@ -71,7 +73,7 @@
|
||||
{# Comment list #}
|
||||
<div class="mt-6 space-y-4">
|
||||
<template x-if="loading">
|
||||
<p class="text-sm text-surface-500">Loading comments...</p>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400">Loading comments...</p>
|
||||
</template>
|
||||
|
||||
<template x-for="comment in comments" x-bind:key="comment.published">
|
||||
@@ -90,7 +92,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<a x-bind:href="comment.author?.url" class="font-medium text-sm hover:underline" target="_blank" rel="noopener"
|
||||
x-text="comment.author?.name || comment.author?.url"></a>
|
||||
<time class="text-xs text-surface-500 font-mono" x-bind:datetime="comment.published"
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 font-mono" x-bind:datetime="comment.published"
|
||||
x-text="new Date(comment.published).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })"></time>
|
||||
</div>
|
||||
<div class="mt-1 text-sm prose dark:prose-invert" x-html="comment.content?.html || comment.content?.text"></div>
|
||||
@@ -100,7 +102,7 @@
|
||||
</template>
|
||||
|
||||
<template x-if="!loading && comments.length === 0">
|
||||
<p class="text-sm text-surface-500">No comments yet. Be the first to share your thoughts!</p>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400">No comments yet. Be the first to share your thoughts!</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
{% endif %}
|
||||
{# Contact details — location, organization, website, email, PGP #}
|
||||
{% if cvLocality or cvCountry or cvOrg or cvUrl or cvEmail or cvKeyUrl %}
|
||||
<div class="flex flex-wrap gap-x-4 gap-y-1 mt-4 text-sm text-surface-500 dark:text-surface-400">
|
||||
<div class="flex flex-wrap gap-x-4 gap-y-1 mt-4 text-sm text-surface-600 dark:text-surface-400">
|
||||
{% if cvLocality or cvCountry %}
|
||||
<span>{% if cvLocality %}{{ cvLocality }}{% endif %}{% if cvLocality and cvCountry %}, {% endif %}{% if cvCountry %}{{ cvCountry }}{% endif %}</span>
|
||||
{% endif %}
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
{# Last Updated #}
|
||||
{% if cv.lastUpdated %}
|
||||
<p class="text-sm text-surface-500 text-center mt-8">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 text-center mt-8">
|
||||
Last updated: <time class="font-mono text-sm" datetime="{{ cv.lastUpdated }}">{{ cv.lastUpdated | date("PPP") }}</time>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<h2 class="text-lg font-semibold text-surface-700 dark:text-surface-300 mb-2">No {{ title | lower }} yet</h2>
|
||||
<p class="text-surface-500 dark:text-surface-400 mb-6 max-w-md mx-auto">
|
||||
<p class="text-surface-600 dark:text-surface-400 mb-6 max-w-md mx-auto">
|
||||
This is where your {{ title | lower }} will appear once you start creating content.
|
||||
</p>
|
||||
{% if typeInfo %}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
@click="showModal = false"></div>
|
||||
{# Panel #}
|
||||
<div class="relative bg-surface-50 dark:bg-surface-800 rounded-xl shadow-xl w-full max-w-sm p-6"
|
||||
role="dialog" aria-modal="true" aria-labelledby="fediverse-modal-title"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
@@ -21,8 +22,8 @@
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.stop>
|
||||
<h3 class="text-lg font-semibold text-surface-900 dark:text-surface-100 mb-1">{{ modalTitle }}</h3>
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-4">{{ modalDescription }}</p>
|
||||
<h3 id="fediverse-modal-title" class="text-lg font-semibold text-surface-900 dark:text-surface-100 mb-1">{{ modalTitle }}</h3>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-4">{{ modalDescription }}</p>
|
||||
|
||||
{# Saved domains list #}
|
||||
<template x-if="savedDomains.length > 0 && !showInput">
|
||||
@@ -35,8 +36,8 @@
|
||||
x-text="item.domain"></button>
|
||||
<button class="px-2 py-2.5 text-surface-400 hover:text-red-500 transition-colors cursor-pointer"
|
||||
@click="deleteSaved(item.domain)"
|
||||
title="Remove">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
:aria-label="'Remove ' + item.domain">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -55,14 +56,16 @@
|
||||
{# New domain input #}
|
||||
<template x-if="savedDomains.length === 0 || showInput">
|
||||
<div>
|
||||
<input x-ref="instanceInput"
|
||||
<label for="fediverse-instance-input" class="sr-only">Fediverse instance domain</label>
|
||||
<input id="fediverse-instance-input"
|
||||
x-ref="instanceInput"
|
||||
x-model="instance"
|
||||
@keydown.enter.prevent="confirm()"
|
||||
type="text"
|
||||
placeholder="mastodon.social"
|
||||
class="w-full px-3 py-2 border border-surface-300 dark:border-surface-600 rounded-lg bg-surface-50 dark:bg-surface-800 text-surface-900 dark:text-surface-100 placeholder-surface-400 text-sm">
|
||||
<template x-if="error">
|
||||
<p class="text-xs text-red-500 mt-1" x-text="error"></p>
|
||||
<p class="text-xs text-red-500 mt-1" x-text="error" role="alert"></p>
|
||||
</template>
|
||||
<div class="flex gap-3 mt-4">
|
||||
<button @click="showInput ? (showInput = false) : (showModal = false)"
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4 mb-6 sm:mb-8">
|
||||
<div class="p-4 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm text-center">
|
||||
<span class="text-2xl font-bold font-mono text-purple-600 dark:text-purple-400 block">{{ summary.totalPlays or 0 }}</span>
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide">Plays</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide">Plays</span>
|
||||
</div>
|
||||
<div class="p-4 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm text-center">
|
||||
<span class="text-2xl font-bold font-mono text-purple-600 dark:text-purple-400 block">{{ summary.uniqueTracks or 0 }}</span>
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide">Tracks</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide">Tracks</span>
|
||||
</div>
|
||||
<div class="p-4 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm text-center">
|
||||
<span class="text-2xl font-bold font-mono text-purple-600 dark:text-purple-400 block">{{ summary.uniqueArtists or 0 }}</span>
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide">Artists</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide">Artists</span>
|
||||
</div>
|
||||
<div class="p-4 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm text-center">
|
||||
<span class="text-2xl font-bold font-mono text-purple-600 dark:text-purple-400 block">{{ summary.totalDurationFormatted or '0m' }}</span>
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide">Listened</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide">Listened</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="flex items-center gap-3 p-3 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<span class="w-6 h-6 flex items-center justify-center text-sm font-bold text-surface-400 bg-surface-100 dark:bg-surface-700 rounded-full">{{ loop.index }}</span>
|
||||
<span class="flex-1 font-medium text-surface-900 dark:text-surface-100">{{ artist.name }}</span>
|
||||
<span class="text-sm text-surface-500">{{ artist.playCount }} plays</span>
|
||||
<span class="text-sm text-surface-600 dark:text-surface-400">{{ artist.playCount }} plays</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<p class="text-sm font-medium text-surface-900 dark:text-surface-100 truncate">{{ album.title }}</p>
|
||||
<p class="text-xs text-surface-500 truncate">{{ album.artist }}</p>
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 truncate">{{ album.artist }}</p>
|
||||
<p class="text-xs text-surface-400">{{ album.playCount }} plays</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
{{ authorName }}
|
||||
</a>
|
||||
{% if authorPronoun %}
|
||||
<span class="p-pronoun text-xs text-surface-500">({{ authorPronoun }})</span>
|
||||
<span class="p-pronoun text-xs text-surface-600 dark:text-surface-400">({{ authorPronoun }})</span>
|
||||
{% endif %}
|
||||
<p class="p-job-title text-sm text-surface-600 dark:text-surface-400" itemprop="jobTitle">{{ authorTitle }}</p>
|
||||
{# Structured address #}
|
||||
<p class="p-adr h-adr text-sm text-surface-500 dark:text-surface-500" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
|
||||
<p class="p-adr h-adr text-sm text-surface-600 dark:text-surface-400" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
|
||||
{% if authorLocality %}
|
||||
<span class="p-locality" itemprop="addressLocality">{{ authorLocality }}</span>{% if authorCountry %}, {% endif %}
|
||||
{% endif %}
|
||||
@@ -79,7 +79,7 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if authorKeyUrl %}
|
||||
<a href="{{ authorKeyUrl }}" class="u-key text-surface-500 dark:text-surface-400 hover:underline" rel="pgpkey">
|
||||
<a href="{{ authorKeyUrl }}" class="u-key text-surface-600 dark:text-surface-400 hover:underline" rel="pgpkey">
|
||||
🔐 PGP Key
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -87,11 +87,11 @@
|
||||
|
||||
{# Categories / Skills #}
|
||||
{% if authorCategories and authorCategories.length %}
|
||||
<div class="mt-3 flex flex-wrap gap-1">
|
||||
<ul class="mt-3 flex flex-wrap gap-1 list-none p-0 m-0" role="list" aria-label="Skills and interests">
|
||||
{% for category in authorCategories %}
|
||||
<span class="p-category text-xs px-2 py-0.5 bg-surface-100 dark:bg-surface-800 rounded-full">{{ category }}</span>
|
||||
<li class="p-category text-xs px-2 py-0.5 bg-surface-100 dark:bg-surface-800 rounded-full">{{ category }}</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Social links with rel="me" - critical for IndieWeb identity verification #}
|
||||
@@ -102,8 +102,8 @@
|
||||
<a
|
||||
href="{{ link.url }}"
|
||||
rel="{{ link.rel }} noopener"
|
||||
class="u-url text-surface-500 hover:text-accent-600 dark:hover:text-accent-400 transition-colors"
|
||||
aria-label="{{ link.name }}"
|
||||
class="u-url text-surface-600 dark:text-surface-400 hover:text-accent-600 dark:hover:text-accent-400 transition-colors"
|
||||
aria-label="{{ link.name }} (opens in new tab)"
|
||||
target="_blank">
|
||||
{{ socialIcon(link.icon, "w-5 h-5") }}
|
||||
</a>
|
||||
|
||||
@@ -39,17 +39,17 @@
|
||||
{% elif widget.type == "fediverse-follow" %}
|
||||
{% set widgetIcon = "user-plus" %}{% set widgetIconClass = "w-5 h-5 text-[#a730b8]" %}{% set widgetBorder = "border-l-[3px] border-l-[#a730b8]" %}
|
||||
{% elif widget.type == "author-card" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-posts" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "categories" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-comments" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "search" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "webmentions" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "ai-usage" %}
|
||||
{% set widgetIcon = "zap" %}{% set widgetIconClass = "w-5 h-5 text-amber-500" %}{% set widgetBorder = "border-l-[3px] border-l-amber-400 dark:border-l-amber-500" %}
|
||||
{% else %}
|
||||
@@ -78,6 +78,7 @@
|
||||
class="widget-chevron"
|
||||
:class="open && 'rotate-180'"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
|
||||
@@ -39,17 +39,17 @@
|
||||
</span>
|
||||
{% else %}
|
||||
<div class="p-4 sm:p-5">
|
||||
<span class="text-[10px] sm:text-xs font-semibold uppercase tracking-wide text-surface-500 block mb-2">← Previous</span>
|
||||
<span class="text-[10px] sm:text-xs font-semibold uppercase tracking-wide text-surface-600 dark:text-surface-400 block mb-2">← Previous</span>
|
||||
<span class="text-sm sm:text-base font-medium text-surface-900 dark:text-surface-100 group-hover:text-accent-600 dark:group-hover:text-accent-400 line-clamp-2 transition-colors">
|
||||
{{ _prevTitle }}
|
||||
</span>
|
||||
<time class="text-xs text-surface-500 mt-1 block font-mono" datetime="{{ _prevPost.date | isoDate }}">{{ _prevPost.date | dateDisplay }}</time>
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 mt-1 block font-mono" datetime="{{ _prevPost.date | isoDate }}">{{ _prevPost.date | dateDisplay }}</time>
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<div class="rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200/50 dark:border-surface-700/50"></div>
|
||||
<div class="rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200/50 dark:border-surface-700/50" aria-hidden="true"></div>
|
||||
{% endif %}
|
||||
|
||||
{# ── Next Post ── #}
|
||||
@@ -85,17 +85,17 @@
|
||||
</span>
|
||||
{% else %}
|
||||
<div class="p-4 sm:p-5 text-right">
|
||||
<span class="text-[10px] sm:text-xs font-semibold uppercase tracking-wide text-surface-500 block mb-2">Next →</span>
|
||||
<span class="text-[10px] sm:text-xs font-semibold uppercase tracking-wide text-surface-600 dark:text-surface-400 block mb-2">Next →</span>
|
||||
<span class="text-sm sm:text-base font-medium text-surface-900 dark:text-surface-100 group-hover:text-accent-600 dark:group-hover:text-accent-400 line-clamp-2 transition-colors">
|
||||
{{ _nextTitle }}
|
||||
</span>
|
||||
<time class="text-xs text-surface-500 mt-1 block font-mono" datetime="{{ _nextPost.date | isoDate }}">{{ _nextPost.date | dateDisplay }}</time>
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 mt-1 block font-mono" datetime="{{ _nextPost.date | isoDate }}">{{ _nextPost.date | dateDisplay }}</time>
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<div class="rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200/50 dark:border-surface-700/50"></div>
|
||||
<div class="rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200/50 dark:border-surface-700/50" aria-hidden="true"></div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
<aside class="reply-context mb-6">
|
||||
{% if replyTo %}
|
||||
<div class="u-in-reply-to h-cite">
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/>
|
||||
</svg>
|
||||
<span>In reply to:</span>
|
||||
</p>
|
||||
{% unfurl replyTo %}
|
||||
<a class="u-url text-xs text-surface-400 dark:text-surface-500 hover:underline break-all" href="{{ replyTo }}">
|
||||
<a class="u-url text-xs text-surface-600 dark:text-surface-400 hover:underline break-all" href="{{ replyTo }}">
|
||||
{{ replyTo }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -28,14 +28,14 @@
|
||||
|
||||
{% if likedUrl %}
|
||||
<div class="u-like-of h-cite">
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-red-500" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
|
||||
</svg>
|
||||
<span>Liked:</span>
|
||||
</p>
|
||||
{% unfurl likedUrl %}
|
||||
<a class="u-url text-xs text-surface-400 dark:text-surface-500 hover:underline break-all" href="{{ likedUrl }}">
|
||||
<a class="u-url text-xs text-surface-600 dark:text-surface-400 hover:underline break-all" href="{{ likedUrl }}">
|
||||
{{ likedUrl }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -43,14 +43,14 @@
|
||||
|
||||
{% if repostedUrl %}
|
||||
<div class="u-repost-of h-cite">
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
||||
</svg>
|
||||
<span>Reposted:</span>
|
||||
</p>
|
||||
{% unfurl repostedUrl %}
|
||||
<a class="u-url text-xs text-surface-400 dark:text-surface-500 hover:underline break-all" href="{{ repostedUrl }}">
|
||||
<a class="u-url text-xs text-surface-600 dark:text-surface-400 hover:underline break-all" href="{{ repostedUrl }}">
|
||||
{{ repostedUrl }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -58,14 +58,14 @@
|
||||
|
||||
{% if bookmarkedUrl %}
|
||||
<div class="u-bookmark-of h-cite">
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-2 flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2z"/>
|
||||
</svg>
|
||||
<span>Bookmarked:</span>
|
||||
</p>
|
||||
{% unfurl bookmarkedUrl %}
|
||||
<a class="u-url text-xs text-surface-400 dark:text-surface-500 hover:underline break-all" href="{{ bookmarkedUrl }}">
|
||||
<a class="u-url text-xs text-surface-600 dark:text-surface-400 hover:underline break-all" href="{{ bookmarkedUrl }}">
|
||||
{{ bookmarkedUrl }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
<div class="grid gap-4 sm:grid-cols-4 mb-6">
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold font-mono text-surface-900 dark:text-surface-100">{{ stats.total }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">Total posts</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">Total posts</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold font-mono text-amber-600 dark:text-amber-400">{{ stats.aiCount }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">AI-involved</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">AI-involved</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold font-mono text-emerald-600 dark:text-emerald-400">{{ stats.total - stats.aiCount }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">Human-only</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">Human-only</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold font-mono text-surface-900 dark:text-surface-100">{{ stats.percentage }}%</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">AI ratio</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">AI ratio</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
{# Post graph — AI-involved posts highlighted #}
|
||||
{% if aiPostsList and aiPostsList.length %}
|
||||
<h3 class="text-lg font-semibold text-surface-900 dark:text-surface-100 mb-3">AI-Involved Posts Over Time</h3>
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-4">Highlighted days had posts with AI involvement (level 1+). Empty boxes represent days with no AI-involved posts.</p>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-4">Highlighted days had posts with AI involvement (level 1+). Empty boxes represent days with no AI-involved posts.</p>
|
||||
{% set graphLimit = sectionConfig.limit or 1 %}
|
||||
{% postGraph aiPostsList, { prefix: "ai-section", limit: graphLimit, boxColorDark: "#44403c", highlightColorLight: "#d97706", highlightColorDark: "#fbbf24" } %}
|
||||
{% endif %}
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
{% if item.startDate %}
|
||||
<span class="text-xs text-surface-500 hidden sm:inline font-mono">
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 hidden sm:inline font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</span>
|
||||
{% elif item.year %}
|
||||
<span class="text-xs text-surface-500 hidden sm:inline font-mono">{{ item.year }}</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 hidden sm:inline font-mono">{{ item.year }}</span>
|
||||
{% endif %}
|
||||
<svg
|
||||
class="w-4 h-4 text-surface-400 transition-transform duration-200"
|
||||
@@ -69,11 +69,11 @@
|
||||
class="px-4 pb-4"
|
||||
>
|
||||
{% if item.startDate %}
|
||||
<p class="text-xs text-surface-500 mb-1 sm:hidden font-mono">
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-1 sm:hidden font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</p>
|
||||
{% elif item.year %}
|
||||
<p class="text-xs text-surface-500 mb-1 sm:hidden font-mono">{{ item.year }}</p>
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-1 sm:hidden font-mono">{{ item.year }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if item.description %}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
{% if item.type %} · <span class="capitalize">{{ item.type }}</span>{% endif %}
|
||||
</p>
|
||||
{% if item.startDate %}
|
||||
<p class="text-xs text-surface-500 mt-0.5 font-mono">
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mt-0.5 font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
{% for lang in cv.languages %}
|
||||
<div class="flex items-center gap-2 px-3 py-1.5 bg-surface-50 dark:bg-surface-800 rounded-full border border-surface-200 dark:border-surface-700">
|
||||
<span class="font-medium text-sm text-surface-900 dark:text-surface-100">{{ lang.name }}</span>
|
||||
<span class="text-xs text-surface-500 capitalize">{{ lang.level }}</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 capitalize">{{ lang.level }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
{% if item.startDate %}
|
||||
<span class="text-xs text-surface-500 hidden sm:inline font-mono">
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 hidden sm:inline font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -89,7 +89,7 @@
|
||||
class="px-4 pb-4"
|
||||
>
|
||||
{% if item.startDate %}
|
||||
<p class="text-xs text-surface-500 mb-1 sm:hidden font-mono">
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-1 sm:hidden font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
{% if item.startDate %}
|
||||
<span class="text-xs text-surface-500 hidden sm:inline font-mono">
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 hidden sm:inline font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -89,7 +89,7 @@
|
||||
class="px-4 pb-4"
|
||||
>
|
||||
{% if item.startDate %}
|
||||
<p class="text-xs text-surface-500 mb-1 sm:hidden font-mono">
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-1 sm:hidden font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
{% if item.startDate %}
|
||||
<span class="text-xs text-surface-500 hidden sm:inline font-mono">
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 hidden sm:inline font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -79,7 +79,7 @@
|
||||
class="px-4 pb-4"
|
||||
>
|
||||
{% if item.startDate %}
|
||||
<p class="text-xs text-surface-500 mb-1 sm:hidden font-mono">
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-1 sm:hidden font-mono">
|
||||
{{ item.startDate }}{% if item.endDate %} – {{ item.endDate }}{% else %} – Present{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -53,14 +53,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-red-600 dark:text-red-400">Liked</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ likedUrl | unfurlCard | safe }}
|
||||
<a class="u-like-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ likedUrl }}">
|
||||
<a class="u-like-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ likedUrl }}">
|
||||
{{ likedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -81,7 +81,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-amber-600 dark:text-amber-400">Bookmarked</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
@@ -93,7 +93,7 @@
|
||||
</h3>
|
||||
{% endif %}
|
||||
{{ bookmarkedUrl | unfurlCard | safe }}
|
||||
<a class="u-bookmark-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ bookmarkedUrl }}">
|
||||
<a class="u-bookmark-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ bookmarkedUrl }}">
|
||||
{{ bookmarkedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -114,14 +114,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-green-600 dark:text-green-400">Reposted</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ repostedUrl | unfurlCard | safe }}
|
||||
<a class="u-repost-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ repostedUrl }}">
|
||||
<a class="u-repost-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ repostedUrl }}">
|
||||
{{ repostedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -142,14 +142,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-sky-600 dark:text-sky-400">In reply to</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ replyToUrl | unfurlCard | safe }}
|
||||
<a class="u-in-reply-to text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ replyToUrl }}">
|
||||
<a class="u-in-reply-to text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ replyToUrl }}">
|
||||
{{ replyToUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -171,7 +171,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-purple-600 dark:text-purple-400">Photo</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
@@ -209,7 +209,7 @@
|
||||
{{ post.templateContent | striptags | truncate(250) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
@@ -222,9 +222,9 @@
|
||||
|
||||
{% else %}
|
||||
{# ── Note card ── #}
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500 mb-2">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400 mb-2">
|
||||
<a class="u-url" href="{{ post.url }}">
|
||||
<time class="dt-published font-medium font-mono text-surface-500 dark:text-surface-400" datetime="{{ post.date | isoDate }}">
|
||||
<time class="dt-published font-medium font-mono text-surface-600 dark:text-surface-400" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</a>
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-red-600 dark:text-red-400">Liked</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ likedUrl | unfurlCard | safe }}
|
||||
<a class="u-like-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ likedUrl }}">
|
||||
<a class="u-like-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ likedUrl }}">
|
||||
{{ likedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -78,7 +78,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-amber-600 dark:text-amber-400">Bookmarked</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
@@ -90,7 +90,7 @@
|
||||
</h3>
|
||||
{% endif %}
|
||||
{{ bookmarkedUrl | unfurlCard | safe }}
|
||||
<a class="u-bookmark-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ bookmarkedUrl }}">
|
||||
<a class="u-bookmark-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ bookmarkedUrl }}">
|
||||
{{ bookmarkedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -111,14 +111,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-green-600 dark:text-green-400">Reposted</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ repostedUrl | unfurlCard | safe }}
|
||||
<a class="u-repost-of text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ repostedUrl }}">
|
||||
<a class="u-repost-of text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ repostedUrl }}">
|
||||
{{ repostedUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -139,14 +139,14 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-sky-600 dark:text-sky-400">In reply to</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
{{ replyToUrl | unfurlCard | safe }}
|
||||
<a class="u-in-reply-to text-xs text-surface-400 dark:text-surface-500 hover:underline break-all mt-1 inline-block" href="{{ replyToUrl }}">
|
||||
<a class="u-in-reply-to text-xs text-surface-400 dark:text-surface-400 hover:underline break-all mt-1 inline-block" href="{{ replyToUrl }}">
|
||||
{{ replyToUrl }}
|
||||
</a>
|
||||
{% if post.templateContent %}
|
||||
@@ -168,7 +168,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span class="font-medium text-purple-600 dark:text-purple-400">Photo</span>
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
@@ -206,7 +206,7 @@
|
||||
{{ post.templateContent | striptags | truncate(250) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<time class="dt-published font-mono" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
@@ -219,9 +219,9 @@
|
||||
|
||||
{% else %}
|
||||
{# ── Note card ── #}
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500 mb-2">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400 mb-2">
|
||||
<a class="u-url" href="{{ post.url }}">
|
||||
<time class="dt-published font-medium font-mono text-surface-500 dark:text-surface-400" datetime="{{ post.date | isoDate }}">
|
||||
<time class="dt-published font-medium font-mono text-surface-600 dark:text-surface-400" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</a>
|
||||
|
||||
@@ -43,17 +43,17 @@
|
||||
{% elif widget.type == "fediverse-follow" %}
|
||||
{% set widgetIcon = "user-plus" %}{% set widgetIconClass = "w-5 h-5 text-[#a730b8]" %}{% set widgetBorder = "border-l-[3px] border-l-[#a730b8]" %}
|
||||
{% elif widget.type == "author-card" or widget.type == "author-card-compact" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "user" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-posts" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "list" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "categories" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "tag" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "recent-comments" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "chat" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "search" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "search" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "webmentions" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-500" %}{% set widgetBorder = "" %}
|
||||
{% set widgetIcon = "share" %}{% set widgetIconClass = "w-5 h-5 text-surface-600 dark:text-surface-400" %}{% set widgetBorder = "" %}
|
||||
{% elif widget.type == "ai-usage" %}
|
||||
{% set widgetIcon = "zap" %}{% set widgetIconClass = "w-5 h-5 text-amber-500" %}{% set widgetBorder = "border-l-[3px] border-l-amber-400 dark:border-l-amber-500" %}
|
||||
{% else %}
|
||||
@@ -82,6 +82,7 @@
|
||||
class="widget-chevron"
|
||||
:class="open && 'rotate-180'"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
@@ -158,8 +159,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : true }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("user", "w-5 h-5 text-surface-500") }} Author</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("user", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Author</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/author-card.njk" %}
|
||||
@@ -173,7 +174,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-[#0085ff]">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("globe", "w-5 h-5 text-[#0085ff]") }} Social Activity</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/social-activity.njk" %}
|
||||
@@ -187,7 +188,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-surface-400 dark:border-l-surface-500">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("github", "w-5 h-5 text-surface-800 dark:text-surface-200") }} GitHub</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/github-repos.njk" %}
|
||||
@@ -201,7 +202,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-purple-400 dark:border-l-purple-500">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("headphones", "w-5 h-5 text-purple-500") }} Listening</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/funkwhale.njk" %}
|
||||
@@ -214,8 +215,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-500") }} Recent Posts</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("list", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Recent Posts</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/recent-posts.njk" %}
|
||||
@@ -230,7 +231,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-amber-400 dark:border-l-amber-500">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("book-open", "w-5 h-5 text-amber-500") }} Blogroll</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/blogroll.njk" %}
|
||||
@@ -246,7 +247,7 @@
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden border-l-[3px] border-l-amber-400 dark:border-l-amber-500">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("rss", "w-5 h-5 text-amber-500") }} FeedLand</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/feedland.njk" %}
|
||||
@@ -260,8 +261,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("chat", "w-5 h-5 text-surface-500") }} Recent Comments</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("chat", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Recent Comments</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/recent-comments.njk" %}
|
||||
@@ -274,8 +275,8 @@
|
||||
<div class="widget-collapsible mb-4" x-data="{ open: localStorage.getItem('{{ widgetKey }}') !== null ? localStorage.getItem('{{ widgetKey }}') === 'true' : false }">
|
||||
<div class="bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
|
||||
<button class="widget-header w-full p-4" @click="open = !open; localStorage.setItem('{{ widgetKey }}', open)" :aria-expanded="open ? 'true' : 'false'">
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("tag", "w-5 h-5 text-surface-500") }} Categories</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
<h3 class="widget-title font-bold text-lg flex items-center gap-2">{{ icon("tag", "w-5 h-5 text-surface-600 dark:text-surface-400") }} Categories</h3>
|
||||
<svg class="widget-chevron" :class="open && 'rotate-180'" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
||||
</button>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" x-cloak>
|
||||
{% include "components/widgets/categories.njk" %}
|
||||
|
||||
@@ -28,22 +28,24 @@
|
||||
{{ likes.length }} Like{% if likes.length != 1 %}s{% endif %}
|
||||
</h3>
|
||||
<is-land on:visible>
|
||||
<div class="facepile">
|
||||
<ul class="facepile" role="list">
|
||||
{% for like in likes %}
|
||||
<a href="{{ like.author.url }}"
|
||||
class="facepile-avatar"
|
||||
title="{{ like.author.name }}"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ like.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt="{{ like.author.name }}"
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
<li class="inline">
|
||||
<a href="{{ like.author.url }}"
|
||||
class="facepile-avatar"
|
||||
aria-label="{{ like.author.name }} (opens in new tab)"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ like.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt=""
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</is-land>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -56,22 +58,24 @@
|
||||
{{ reposts.length }} Repost{% if reposts.length != 1 %}s{% endif %}
|
||||
</h3>
|
||||
<is-land on:visible>
|
||||
<div class="facepile">
|
||||
<ul class="facepile" role="list">
|
||||
{% for repost in reposts %}
|
||||
<a href="{{ repost.author.url }}"
|
||||
class="facepile-avatar"
|
||||
title="{{ repost.author.name }}"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ repost.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt="{{ repost.author.name }}"
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
<li class="inline">
|
||||
<a href="{{ repost.author.url }}"
|
||||
class="facepile-avatar"
|
||||
aria-label="{{ repost.author.name }} (opens in new tab)"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ repost.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt=""
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</is-land>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -84,22 +88,24 @@
|
||||
{{ bookmarks.length }} Bookmark{% if bookmarks.length != 1 %}s{% endif %}
|
||||
</h3>
|
||||
<is-land on:visible>
|
||||
<div class="facepile">
|
||||
<ul class="facepile" role="list">
|
||||
{% for bookmark in bookmarks %}
|
||||
<a href="{{ bookmark.author.url }}"
|
||||
class="facepile-avatar"
|
||||
title="{{ bookmark.author.name }}"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ bookmark.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt="{{ bookmark.author.name }}"
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
<li class="inline">
|
||||
<a href="{{ bookmark.author.url }}"
|
||||
class="facepile-avatar"
|
||||
aria-label="{{ bookmark.author.name }} (opens in new tab)"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<img
|
||||
src="{{ bookmark.author.photo or '/images/default-avatar.svg' }}"
|
||||
alt=""
|
||||
class="w-8 h-8 rounded-full ring-2 ring-white dark:ring-surface-900"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</is-land>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -132,7 +138,7 @@
|
||||
{{ reply.author.name }}
|
||||
</a>
|
||||
<a href="{{ reply.url }}"
|
||||
class="text-xs text-surface-500 hover:underline"
|
||||
class="text-xs text-surface-600 dark:text-surface-400 hover:underline"
|
||||
target="_blank"
|
||||
rel="noopener">
|
||||
<time class="font-mono" datetime="{{ reply.published }}">
|
||||
@@ -189,7 +195,9 @@
|
||||
</p>
|
||||
<form action="https://webmention.io/{{ site.webmentions.domain }}/webmention" method="post" class="flex gap-2">
|
||||
<input type="hidden" name="target" value="{{ site.url }}{{ page.url }}">
|
||||
<label for="webmention-source" class="sr-only">Your post URL</label>
|
||||
<input
|
||||
id="webmention-source"
|
||||
type="url"
|
||||
name="source"
|
||||
placeholder="https://your-site.com/response"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<is-land on:visible>
|
||||
<div class="widget">
|
||||
<h3 class="widget-title flex items-center gap-2">
|
||||
<svg class="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
|
||||
</svg>
|
||||
AI Transparency
|
||||
@@ -15,19 +15,19 @@
|
||||
<div class="grid grid-cols-2 gap-2 mb-3">
|
||||
<div class="text-center p-2 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700">
|
||||
<div class="text-lg font-bold text-surface-900 dark:text-surface-100">{{ stats.total }}</div>
|
||||
<div class="text-[10px] text-surface-500 dark:text-surface-400">Total</div>
|
||||
<div class="text-[10px] text-surface-600 dark:text-surface-400">Total</div>
|
||||
</div>
|
||||
<div class="text-center p-2 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700">
|
||||
<div class="text-lg font-bold text-amber-600 dark:text-amber-400">{{ stats.aiCount }}</div>
|
||||
<div class="text-[10px] text-surface-500 dark:text-surface-400">AI-involved</div>
|
||||
<div class="text-[10px] text-surface-600 dark:text-surface-400">AI-involved</div>
|
||||
</div>
|
||||
<div class="text-center p-2 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700">
|
||||
<div class="text-lg font-bold text-emerald-600 dark:text-emerald-400">{{ stats.total - stats.aiCount }}</div>
|
||||
<div class="text-[10px] text-surface-500 dark:text-surface-400">Human-only</div>
|
||||
<div class="text-[10px] text-surface-600 dark:text-surface-400">Human-only</div>
|
||||
</div>
|
||||
<div class="text-center p-2 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700">
|
||||
<div class="text-lg font-bold text-surface-900 dark:text-surface-100">{{ stats.percentage }}%</div>
|
||||
<div class="text-[10px] text-surface-500 dark:text-surface-400">AI ratio</div>
|
||||
<div class="text-[10px] text-surface-600 dark:text-surface-400">AI ratio</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -49,13 +49,13 @@
|
||||
|
||||
{# Compact post-graph — current year only, AI posts highlighted #}
|
||||
{% if aiPostsList and aiPostsList.length %}
|
||||
<div class="text-[10px] text-surface-500 dark:text-surface-400 mb-2">AI-involved posts this year</div>
|
||||
<div class="text-[10px] text-surface-600 dark:text-surface-400 mb-2">AI-involved posts this year</div>
|
||||
{% postGraph aiPostsList, { prefix: "ai-widget", limit: 1, noLabels: true, boxColorDark: "#44403c", highlightColorLight: "#d97706", highlightColorDark: "#fbbf24" } %}
|
||||
{% endif %}
|
||||
|
||||
<a href="/ai/" class="text-sm text-amber-600 dark:text-amber-400 hover:underline flex items-center gap-1 mt-3">
|
||||
View full AI report
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</is-land>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<div class="h-card p-author flex items-center gap-3">
|
||||
{# Hidden u-photo for reliable microformat parsing #}
|
||||
<data class="u-photo hidden" value="{{ site.author.avatar }}"></data>
|
||||
<a href="{{ site.author.url }}" class="u-url u-uid" rel="me" itemprop="url">
|
||||
<a href="{{ site.author.url }}" class="u-url u-uid" rel="me" itemprop="url" aria-label="{{ site.author.name }}">
|
||||
<img
|
||||
src="{{ site.author.avatar }}"
|
||||
alt="{{ site.author.name }}"
|
||||
alt=""
|
||||
class="w-12 h-12 rounded-full object-cover shadow-lg"
|
||||
loading="lazy"
|
||||
>
|
||||
@@ -16,9 +16,9 @@
|
||||
<a href="{{ site.author.url }}" class="u-url p-name font-medium text-surface-900 dark:text-surface-100 hover:text-accent-600 dark:hover:text-accent-400 transition-colors">
|
||||
{{ site.author.name }}
|
||||
</a>
|
||||
<p class="p-job-title text-xs text-surface-500">{{ site.author.title }}</p>
|
||||
<p class="p-job-title text-xs text-surface-600 dark:text-surface-400">{{ site.author.title }}</p>
|
||||
{% if site.author.locality %}
|
||||
<p class="p-locality text-xs text-surface-500">{{ site.author.locality }}{% if site.author.country %}, <span class="p-country-name">{{ site.author.country }}</span>{% endif %}</p>
|
||||
<p class="p-locality text-xs text-surface-600 dark:text-surface-400">{{ site.author.locality }}{% if site.author.country %}, <span class="p-country-name">{{ site.author.country }}</span>{% endif %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
@click="activeTab = tab.key"
|
||||
:class="activeTab === tab.key
|
||||
? 'border-b-2 border-accent-600 text-accent-600 dark:text-accent-400 dark:border-accent-400'
|
||||
: 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
: 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="px-2 py-1 text-xs font-medium transition-colors -mb-px"
|
||||
x-text="tab.label + ' (' + tab.count + ')'"
|
||||
></button>
|
||||
@@ -40,7 +40,7 @@
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
<div x-show="filteredBlogs.length === 0 && !loading" class="text-sm text-surface-500 py-2">
|
||||
<div x-show="filteredBlogs.length === 0 && !loading" class="text-sm text-surface-600 dark:text-surface-400 py-2">
|
||||
No blogs loaded yet.
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<is-land on:visible>
|
||||
<div class="widget" x-data="fediverseInteract('{{ actorUrl }}', 'interact')">
|
||||
<h3 class="widget-title">Follow Me</h3>
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-3">Follow me from your fediverse instance.</p>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-3">Follow me from your fediverse instance.</p>
|
||||
<a href="{{ actorUrl }}"
|
||||
@click="handleClick($event)"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[#a730b8]/10 text-[#a730b8] hover:bg-[#a730b8]/20 transition-colors text-sm font-medium cursor-pointer"
|
||||
|
||||
@@ -240,8 +240,8 @@
|
||||
|
||||
{# Sort links #}
|
||||
<div class="fl-sort">
|
||||
<span :class="sortBy === 'title' ? 'selected' : ''" @click="sortBy = 'title'">Title</span>
|
||||
<span :class="sortBy === 'when' ? 'selected' : ''" @click="sortBy = 'when'">When</span>
|
||||
<span :class="sortBy === 'title' ? 'selected' : ''" @click="sortBy = 'title'" @keydown.enter="sortBy = 'title'" @keydown.space.prevent="sortBy = 'title'" tabindex="0" role="button" :aria-pressed="sortBy === 'title'">Title</span>
|
||||
<span :class="sortBy === 'when' ? 'selected' : ''" @click="sortBy = 'when'" @keydown.enter="sortBy = 'when'" @keydown.space.prevent="sortBy = 'when'" tabindex="0" role="button" :aria-pressed="sortBy === 'when'">When</span>
|
||||
</div>
|
||||
|
||||
{# Feed list — pure divs, no table #}
|
||||
@@ -253,7 +253,13 @@
|
||||
<span class="fl-caret"
|
||||
:class="expandedId === blog.id ? 'fl-caret-dark' : (selectedId === blog.id ? 'fl-caret-dark' : 'fl-caret-light')"
|
||||
x-text="expandedId === blog.id ? '\u25BC' : '\u25B6'"
|
||||
@click.stop="toggleExpand(blog)"></span>
|
||||
@click.stop="toggleExpand(blog)"
|
||||
@keydown.enter.stop="toggleExpand(blog)"
|
||||
@keydown.space.prevent.stop="toggleExpand(blog)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-label="expandedId === blog.id ? 'Collapse ' + blog.title : 'Expand ' + blog.title"
|
||||
:aria-expanded="expandedId === blog.id"></span>
|
||||
<span class="fl-name">
|
||||
<a :href="blog.siteUrl || blog.feedUrl" target="_blank" rel="noopener"
|
||||
x-text="blog.title" @click.stop></a>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
{{ listening.track }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<p class="text-xs text-surface-500 truncate">{{ listening.artist }}
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 truncate">{{ listening.artist }}
|
||||
<span class="text-purple-500 ml-1">Funkwhale</span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -97,7 +97,7 @@
|
||||
{% endif %}
|
||||
{% if scrobble.loved %}<span class="text-red-500 ml-0.5">♥</span>{% endif %}
|
||||
</p>
|
||||
<p class="text-xs text-surface-500 truncate">{{ scrobble.artist }}
|
||||
<p class="text-xs text-surface-600 dark:text-surface-400 truncate">{{ scrobble.artist }}
|
||||
<span class="text-red-500 ml-1">Last.fm</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -9,31 +9,39 @@
|
||||
</h3>
|
||||
|
||||
{# Tab buttons — order: Commits, Repos, Featured, PRs #}
|
||||
<div class="flex gap-1 mb-4 border-b border-surface-200 dark:border-surface-700">
|
||||
<div class="flex gap-1 mb-4 border-b border-surface-200 dark:border-surface-700" role="tablist" aria-label="GitHub activity">
|
||||
<button
|
||||
@click="activeTab = 'commits'"
|
||||
:class="activeTab === 'commits' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'commits' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'commits').toString()"
|
||||
role="tab" id="gh-tab-commits" aria-controls="gh-panel-commits"
|
||||
class="flex items-center gap-1.5 px-2 py-2 text-xs font-medium transition-colors -mb-px"
|
||||
>
|
||||
Commits
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'repos'"
|
||||
:class="activeTab === 'repos' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'repos' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'repos').toString()"
|
||||
role="tab" id="gh-tab-repos" aria-controls="gh-panel-repos"
|
||||
class="flex items-center gap-1.5 px-2 py-2 text-xs font-medium transition-colors -mb-px"
|
||||
>
|
||||
Repos
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'featured'"
|
||||
:class="activeTab === 'featured' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'featured' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'featured').toString()"
|
||||
role="tab" id="gh-tab-featured" aria-controls="gh-panel-featured"
|
||||
class="flex items-center gap-1.5 px-2 py-2 text-xs font-medium transition-colors -mb-px"
|
||||
>
|
||||
Featured
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'prs'"
|
||||
:class="activeTab === 'prs' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'prs' ? 'border-b-2 border-accent-500 text-accent-600 dark:text-accent-400' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'prs').toString()"
|
||||
role="tab" id="gh-tab-prs" aria-controls="gh-panel-prs"
|
||||
class="flex items-center gap-1.5 px-2 py-2 text-xs font-medium transition-colors -mb-px"
|
||||
>
|
||||
PRs
|
||||
@@ -44,18 +52,18 @@
|
||||
<div class="h-[420px] overflow-y-auto">
|
||||
|
||||
{# Loading state #}
|
||||
<div x-show="loading" class="text-sm text-surface-500 py-4 text-center">
|
||||
<div x-show="loading" class="text-sm text-surface-600 dark:text-surface-400 py-4 text-center">
|
||||
Loading...
|
||||
</div>
|
||||
|
||||
{# Commits Tab #}
|
||||
<div x-show="activeTab === 'commits' && !loading" x-cloak>
|
||||
<div x-show="activeTab === 'commits' && !loading" x-cloak role="tabpanel" id="gh-panel-commits" aria-labelledby="gh-tab-commits">
|
||||
<ul x-show="commits.length > 0" class="space-y-3">
|
||||
<template x-for="commit in commits.slice(0, 5)" :key="commit.sha">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
<a :href="commit.url" target="_blank" rel="noopener" class="block group">
|
||||
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-surface-900 dark:group-hover:text-surface-100 transition-colors line-clamp-2" x-text="commit.message"></p>
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-600 dark:text-surface-400">
|
||||
<code class="text-xs font-mono bg-surface-100 dark:bg-surface-800 px-1 py-0.5 rounded" x-text="commit.sha"></code>
|
||||
<span class="truncate" x-text="commit.repo?.split('/')[1] || commit.repo"></span>
|
||||
<span class="font-mono" x-text="formatDate(commit.date)"></span>
|
||||
@@ -64,11 +72,11 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="commits.length === 0" class="text-sm text-surface-500 py-2">No recent commits.</div>
|
||||
<div x-show="commits.length === 0" class="text-sm text-surface-600 dark:text-surface-400 py-2">No recent commits.</div>
|
||||
</div>
|
||||
|
||||
{# Repos Tab #}
|
||||
<div x-show="activeTab === 'repos' && !loading" x-cloak>
|
||||
<div x-show="activeTab === 'repos' && !loading" x-cloak role="tabpanel" id="gh-panel-repos" aria-labelledby="gh-tab-repos">
|
||||
<ul x-show="repos.length > 0" class="space-y-3">
|
||||
<template x-for="repo in repos.slice(0, 5)" :key="repo.name">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
@@ -78,7 +86,7 @@
|
||||
<span x-show="repo.language" class="text-xs px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-400 flex-shrink-0" x-text="repo.language"></span>
|
||||
</div>
|
||||
<p x-show="repo.description" class="text-xs text-surface-600 dark:text-surface-400 mt-1 line-clamp-2" x-text="repo.description"></p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span x-show="repo.stargazers_count > 0" class="flex items-center gap-1">
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
|
||||
<span x-text="repo.stargazers_count"></span>
|
||||
@@ -89,11 +97,11 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="repos.length === 0" class="text-sm text-surface-500 py-2">No repositories found.</div>
|
||||
<div x-show="repos.length === 0" class="text-sm text-surface-600 dark:text-surface-400 py-2">No repositories found.</div>
|
||||
</div>
|
||||
|
||||
{# Featured Tab #}
|
||||
<div x-show="activeTab === 'featured' && !loading" x-cloak>
|
||||
<div x-show="activeTab === 'featured' && !loading" x-cloak role="tabpanel" id="gh-panel-featured" aria-labelledby="gh-tab-featured">
|
||||
<ul x-show="featured.length > 0" class="space-y-3">
|
||||
<template x-for="repo in featured.slice(0, 5)" :key="repo.fullName || repo.name">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
@@ -103,7 +111,7 @@
|
||||
<span x-show="repo.language" class="text-xs px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-400 flex-shrink-0" x-text="repo.language"></span>
|
||||
</div>
|
||||
<p x-show="repo.description" class="text-xs text-surface-600 dark:text-surface-400 mt-1 line-clamp-2" x-text="repo.description"></p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-surface-600 dark:text-surface-400">
|
||||
<span x-show="repo.stars > 0" class="flex items-center gap-1">
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
|
||||
<span x-text="repo.stars"></span>
|
||||
@@ -117,11 +125,11 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="featured.length === 0" class="text-sm text-surface-500 py-2">No featured projects.</div>
|
||||
<div x-show="featured.length === 0" class="text-sm text-surface-600 dark:text-surface-400 py-2">No featured projects.</div>
|
||||
</div>
|
||||
|
||||
{# PRs Tab #}
|
||||
<div x-show="activeTab === 'prs' && !loading" x-cloak>
|
||||
<div x-show="activeTab === 'prs' && !loading" x-cloak role="tabpanel" id="gh-panel-prs" aria-labelledby="gh-tab-prs">
|
||||
<ul x-show="contributions.length > 0" class="space-y-3">
|
||||
<template x-for="item in contributions.slice(0, 5)" :key="item.url">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
@@ -136,7 +144,7 @@
|
||||
</span>
|
||||
<span class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-surface-900 dark:group-hover:text-surface-100 transition-colors truncate" x-text="item.title"></span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-500 pl-6">
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-600 dark:text-surface-400 pl-6">
|
||||
<span x-text="item.repo?.split('/')[1] || item.repo"></span>
|
||||
<span x-show="item.number" x-text="'#' + item.number"></span>
|
||||
<span class="font-mono" x-text="formatDate(item.date)"></span>
|
||||
@@ -145,7 +153,7 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="contributions.length === 0" class="text-sm text-surface-500 py-2">No recent PRs or issues.</div>
|
||||
<div x-show="contributions.length === 0" class="text-sm text-surface-600 dark:text-surface-400 py-2">No recent PRs or issues.</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="space-y-3">
|
||||
{% if _prevPost %}
|
||||
<div class="border-b border-surface-200 dark:border-surface-700 pb-3">
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide block mb-1">Previous</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide block mb-1">Previous</span>
|
||||
{% set _likedUrl = _prevPost.data.likeOf or _prevPost.data.like_of %}
|
||||
{% set _bookmarkedUrl = _prevPost.data.bookmarkOf or _prevPost.data.bookmark_of %}
|
||||
{% set _repostedUrl = _prevPost.data.repostOf or _prevPost.data.repost_of %}
|
||||
@@ -36,7 +36,7 @@
|
||||
{% endif %}
|
||||
{% if _nextPost %}
|
||||
<div>
|
||||
<span class="text-xs text-surface-500 uppercase tracking-wide block mb-1">Next</span>
|
||||
<span class="text-xs text-surface-600 dark:text-surface-400 uppercase tracking-wide block mb-1">Next</span>
|
||||
{% set _likedUrl = _nextPost.data.likeOf or _nextPost.data.like_of %}
|
||||
{% set _bookmarkedUrl = _nextPost.data.bookmarkOf or _nextPost.data.bookmark_of %}
|
||||
{% set _repostedUrl = _nextPost.data.repostOf or _nextPost.data.repost_of %}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-accent-600 dark:text-accent-400 hover:underline line-clamp-1">
|
||||
Liked {{ _likedUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-accent-600 dark:text-accent-400 hover:underline line-clamp-1">
|
||||
{{ post.data.title or ("Bookmarked " + (_bookmarkedUrl | replace("https://", "") | truncate(35))) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-accent-600 dark:text-accent-400 hover:underline line-clamp-1">
|
||||
Reposted {{ _repostedUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-sky-600 dark:text-sky-400 hover:underline line-clamp-1">
|
||||
Reply to {{ _replyToUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -69,7 +69,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-accent-600 dark:text-accent-400 hover:underline line-clamp-2">
|
||||
{{ post.data.title or post.data.name or (post.templateContent | striptags | truncate(50)) or "Note" }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
{% endif %}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-red-600 dark:text-red-400 hover:underline break-all line-clamp-1">
|
||||
Liked {{ likedUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -37,7 +37,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-amber-600 dark:text-amber-400 hover:underline line-clamp-1">
|
||||
{{ post.data.title or ("Bookmarked " + (bookmarkedUrl | replace("https://", "") | truncate(35))) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -52,7 +52,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-green-600 dark:text-green-400 hover:underline break-all line-clamp-1">
|
||||
Reposted {{ repostedUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -67,7 +67,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-sky-600 dark:text-sky-400 hover:underline break-all line-clamp-1">
|
||||
Reply to {{ replyToUrl | replace("https://", "") | truncate(40) }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -83,7 +83,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline line-clamp-1">
|
||||
{{ post.data.title }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@
|
||||
<a href="{{ post.url }}" class="text-sm text-teal-600 dark:text-teal-400 hover:underline line-clamp-1">
|
||||
{{ post.templateContent | striptags | truncate(50) or "Note" }}
|
||||
</a>
|
||||
<time class="text-xs text-surface-500 block font-mono" datetime="{{ post.data.published }}">
|
||||
<time class="text-xs text-surface-600 dark:text-surface-400 block font-mono" datetime="{{ post.data.published }}">
|
||||
{{ (post.data.published or post.date) | dateDisplay }}
|
||||
</time>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="flex-1 inline-flex items-center justify-center gap-2 px-3 py-2 rounded-lg bg-[#0085ff]/10 text-[#0085ff] hover:bg-[#0085ff]/20 transition-colors text-sm font-medium"
|
||||
title="Share on Bluesky">
|
||||
title="Share on Bluesky"
|
||||
aria-label="Share on Bluesky">
|
||||
<svg class="w-4 h-4" viewBox="0 0 568 501" fill="currentColor" aria-hidden="true">
|
||||
<path d="M123.121 33.664C188.241 82.553 258.281 181.68 284 234.873c25.719-53.192 95.759-152.32 160.879-201.21C491.866-1.611 568-28.906 568 57.947c0 17.346-9.945 145.713-15.778 166.555-20.275 72.453-94.155 90.933-159.875 79.748C507.222 323.8 536.444 388.56 473.333 453.32c-119.86 122.992-172.272-30.859-185.702-70.281-2.462-7.227-3.614-10.608-3.631-7.733-.017-2.875-1.169.506-3.631 7.733-13.43 39.422-65.842 193.273-185.702 70.281-63.111-64.76-33.89-129.52 80.986-149.071-65.72 11.185-139.6-7.295-159.875-79.748C9.945 203.659 0 75.291 0 57.946 0-28.906 76.135-1.612 123.121 33.664Z"/>
|
||||
</svg>
|
||||
@@ -17,7 +18,8 @@
|
||||
<a href="https://share.joinmastodon.org/#text={{ shareText | urlencode }}"
|
||||
@click="handleClick($event)"
|
||||
class="w-full inline-flex items-center justify-center gap-2 px-3 py-2 rounded-lg bg-[#a730b8]/10 text-[#a730b8] hover:bg-[#a730b8]/20 transition-colors text-sm font-medium cursor-pointer"
|
||||
title="Share on the Fediverse (Shift+click to change instance)">
|
||||
title="Share on the Fediverse (Shift+click to change instance)"
|
||||
aria-label="Share on the Fediverse">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M13.09 4.43L24 10.73v2.51L13.09 19.58v-2.51L21.83 12 13.09 6.98v-2.55zM13.09 9.49L17.44 12l-4.35 2.51V9.49z"/><path d="M10.91 4.43L0 10.73v2.51l8.74-5.03v10.09l2.18 1.28V4.43zM6.56 12L2.18 14.51l4.35 2.51V12z"/>
|
||||
</svg>
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
<h3 class="widget-title">Social Activity</h3>
|
||||
|
||||
{# Tab buttons #}
|
||||
<div class="flex gap-1 mb-4 border-b border-surface-200 dark:border-surface-700">
|
||||
<div class="flex gap-1 mb-4 border-b border-surface-200 dark:border-surface-700" role="tablist" aria-label="Social feeds">
|
||||
{% if blueskyFeed and blueskyFeed.length %}
|
||||
<button
|
||||
@click="activeTab = 'bluesky'"
|
||||
:class="activeTab === 'bluesky' ? 'border-b-2 border-[#0085ff] text-[#0085ff]' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'bluesky' ? 'border-b-2 border-[#0085ff] text-[#0085ff]' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'bluesky').toString()"
|
||||
role="tab" id="social-tab-bluesky" aria-controls="social-panel-bluesky"
|
||||
class="flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors -mb-px"
|
||||
>
|
||||
<svg class="w-4 h-4 text-[#0085ff]" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
@@ -21,7 +23,9 @@
|
||||
{% if mastodonFeed and mastodonFeed.length %}
|
||||
<button
|
||||
@click="activeTab = 'mastodon'"
|
||||
:class="activeTab === 'mastodon' ? 'border-b-2 border-[#a730b8] text-[#a730b8]' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="activeTab === 'mastodon' ? 'border-b-2 border-[#a730b8] text-[#a730b8]' : 'text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:aria-selected="(activeTab === 'mastodon').toString()"
|
||||
role="tab" id="social-tab-mastodon" aria-controls="social-panel-mastodon"
|
||||
class="flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors -mb-px"
|
||||
>
|
||||
<svg class="w-4 h-4 text-[#6364ff]" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
@@ -34,7 +38,7 @@
|
||||
|
||||
{# Bluesky Tab Content #}
|
||||
{% if blueskyFeed and blueskyFeed.length %}
|
||||
<div x-show="activeTab === 'bluesky'" x-cloak>
|
||||
<div x-show="activeTab === 'bluesky'" x-cloak role="tabpanel" id="social-panel-bluesky" aria-labelledby="social-tab-bluesky">
|
||||
<ul class="space-y-3">
|
||||
{% for post in blueskyFeed | head(5) %}
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
@@ -42,7 +46,7 @@
|
||||
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-[#0085ff] transition-colors">
|
||||
{{ post.text | truncate(140) }}
|
||||
</p>
|
||||
<div class="flex items-center gap-3 mt-2 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 mt-2 text-xs text-surface-600 dark:text-surface-400">
|
||||
<time class="font-mono" datetime="{{ post.createdAt }}">{{ post.createdAt | date("MMM d, yyyy") }}</time>
|
||||
{% if post.likeCount > 0 %}
|
||||
<span class="flex items-center gap-1">
|
||||
@@ -64,7 +68,7 @@
|
||||
|
||||
{# Mastodon Tab Content #}
|
||||
{% if mastodonFeed and mastodonFeed.length %}
|
||||
<div x-show="activeTab === 'mastodon'" x-cloak>
|
||||
<div x-show="activeTab === 'mastodon'" x-cloak role="tabpanel" id="social-panel-mastodon" aria-labelledby="social-tab-mastodon">
|
||||
<ul class="space-y-3">
|
||||
{% for post in mastodonFeed | head(5) %}
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
@@ -72,7 +76,7 @@
|
||||
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-[#a730b8] transition-colors">
|
||||
{{ post.text | truncate(140) }}
|
||||
</p>
|
||||
<div class="flex items-center gap-3 mt-2 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 mt-2 text-xs text-surface-600 dark:text-surface-400">
|
||||
<time class="font-mono" datetime="{{ post.createdAt }}">{{ post.createdAt | date("MMM d, yyyy") }}</time>
|
||||
{% if post.favouritesCount > 0 %}
|
||||
<span class="flex items-center gap-1">
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<h3 class="widget-title">Subscribe</h3>
|
||||
<div class="space-y-2">
|
||||
<a href="/feed.xml" class="flex items-center gap-2 text-sm text-surface-600 dark:text-surface-400 hover:text-orange-600 dark:hover:text-orange-400 hover:underline transition-colors">
|
||||
<svg class="w-4 h-4 text-orange-500" fill="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-4 h-4 text-orange-500" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20C5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27V4.44m0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93V10.1Z"/>
|
||||
</svg>
|
||||
RSS Feed
|
||||
</a>
|
||||
<a href="/feed.json" class="flex items-center gap-2 text-sm text-surface-600 dark:text-surface-400 hover:text-orange-600 dark:hover:text-orange-400 hover:underline transition-colors">
|
||||
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2m3 12h2v2H8v-2m4-8h2v10h-2V7m4 4h2v6h-2v-6Z"/>
|
||||
</svg>
|
||||
JSON Feed
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<is-land on:visible>
|
||||
<div class="widget">
|
||||
<h3 class="widget-title">Contents</h3>
|
||||
<nav class="toc">
|
||||
<nav class="toc" aria-label="Table of contents">
|
||||
<ul class="space-y-1 text-sm">
|
||||
{% for item in toc %}
|
||||
<li class="{% if item.level > 2 %}ml-{{ (item.level - 2) * 3 }}{% endif %}">
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
<div class="flex border-b border-surface-200 dark:border-surface-700 mb-3">
|
||||
<button
|
||||
@click="tab = 'inbound'"
|
||||
:class="tab === 'inbound' ? 'border-accent-500 text-accent-600 dark:text-accent-400' : 'border-transparent text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="tab === 'inbound' ? 'border-accent-500 text-accent-600 dark:text-accent-400' : 'border-transparent text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="px-2 py-1.5 text-xs font-medium border-b-2 -mb-px transition-colors">
|
||||
Received
|
||||
<span x-show="mentions.length" x-text="mentions.length" class="ml-0.5 text-xs opacity-75"></span>
|
||||
</button>
|
||||
<button
|
||||
@click="tab = 'outbound'"
|
||||
:class="tab === 'outbound' ? 'border-accent-500 text-accent-600 dark:text-accent-400' : 'border-transparent text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
:class="tab === 'outbound' ? 'border-accent-500 text-accent-600 dark:text-accent-400' : 'border-transparent text-surface-600 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="px-2 py-1.5 text-xs font-medium border-b-2 -mb-px transition-colors">
|
||||
Sent
|
||||
</button>
|
||||
@@ -52,14 +52,14 @@
|
||||
<span x-show="wm['wm-property'] === 'in-reply-to'" class="text-sky-500"> replied to</span>
|
||||
<span x-show="wm['wm-property'] === 'mention-of'" class="text-amber-500"> mentioned</span>
|
||||
<span x-show="wm['wm-property'] === 'bookmark-of'" class="text-purple-500"> bookmarked</span>
|
||||
<a :href="wm['wm-target']" class="text-surface-500 hover:underline block truncate" x-text="formatPath(wm['wm-target'])"></a>
|
||||
<a :href="wm['wm-target']" class="text-surface-600 dark:text-surface-400 hover:underline block truncate" x-text="formatPath(wm['wm-target'])"></a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
{# Empty #}
|
||||
<p x-show="!loading && !mentions.length && !error" class="text-xs text-surface-500 py-2">No webmentions received yet.</p>
|
||||
<p x-show="!loading && !mentions.length && !error" class="text-xs text-surface-600 dark:text-surface-400 py-2">No webmentions received yet.</p>
|
||||
|
||||
{# Error #}
|
||||
<p x-show="error" class="text-xs text-red-500 py-2" x-text="error"></p>
|
||||
|
||||
@@ -135,18 +135,19 @@
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||
<header class="site-header">
|
||||
<div class="container header-container">
|
||||
<a href="/" class="site-title">{{ site.name }}</a>
|
||||
|
||||
{# Mobile menu button #}
|
||||
<button id="menu-toggle" type="button" class="menu-toggle" aria-label="Toggle menu" aria-expanded="false">
|
||||
<svg class="menu-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<svg class="menu-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
|
||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
||||
<line x1="3" y1="12" x2="21" y2="12"/>
|
||||
<line x1="3" y1="18" x2="21" y2="18"/>
|
||||
</svg>
|
||||
<svg class="close-icon hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<svg class="close-icon hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/>
|
||||
<line x1="6" y1="6" x2="18" y2="18"/>
|
||||
</svg>
|
||||
@@ -159,33 +160,33 @@
|
||||
<a href="/about/">About</a>
|
||||
<a href="/now/">Now</a>
|
||||
{# Blog dropdown #}
|
||||
<div class="nav-dropdown" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false">
|
||||
<a href="/blog/" class="nav-dropdown-trigger">
|
||||
<div class="nav-dropdown" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false" @focusin="open = true" @focusout="!$el.contains($event.relatedTarget) && (open = false)" @keydown.escape="open = false">
|
||||
<a href="/blog/" class="nav-dropdown-trigger" :aria-expanded="open.toString()" aria-haspopup="true">
|
||||
Blog
|
||||
<svg class="w-3 h-3 ml-1 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-3 h-3 ml-1 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="nav-dropdown-menu" x-show="open" x-transition x-cloak>
|
||||
<a href="/blog/">All Posts</a>
|
||||
<div class="nav-dropdown-menu" x-show="open" x-transition x-cloak role="menu">
|
||||
<a href="/blog/" role="menuitem">All Posts</a>
|
||||
{% for pt in enabledPostTypes %}
|
||||
<a href="{{ pt.path }}">{{ pt.label }}</a>
|
||||
<a href="{{ pt.path }}" role="menuitem">{{ pt.label }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{# Pages dropdown #}
|
||||
<div class="nav-dropdown" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false">
|
||||
<a href="/slashes/" class="nav-dropdown-trigger">
|
||||
<div class="nav-dropdown" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false" @focusin="open = true" @focusout="!$el.contains($event.relatedTarget) && (open = false)" @keydown.escape="open = false">
|
||||
<a href="/slashes/" class="nav-dropdown-trigger" :aria-expanded="open.toString()" aria-haspopup="true">
|
||||
Pages
|
||||
<svg class="w-3 h-3 ml-1 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-3 h-3 ml-1 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="nav-dropdown-menu" x-show="open" x-transition x-cloak>
|
||||
{% if blogrollStatus and blogrollStatus.source == "indiekit" %}<a href="/blogroll/">Blogroll</a>{% endif %}
|
||||
{% if podrollStatus and podrollStatus.source == "indiekit" %}<a href="/podroll/">Podroll</a>{% endif %}
|
||||
{% if newsActivity and newsActivity.source == "indiekit" %}<a href="/news/">News</a>{% endif %}
|
||||
<a href="/slashes/">All Pages</a>
|
||||
<div class="nav-dropdown-menu" x-show="open" x-transition x-cloak role="menu">
|
||||
{% if blogrollStatus and blogrollStatus.source == "indiekit" %}<a href="/blogroll/" role="menuitem">Blogroll</a>{% endif %}
|
||||
{% if podrollStatus and podrollStatus.source == "indiekit" %}<a href="/podroll/" role="menuitem">Podroll</a>{% endif %}
|
||||
{% if newsActivity and newsActivity.source == "indiekit" %}<a href="/news/" role="menuitem">News</a>{% endif %}
|
||||
<a href="/slashes/" role="menuitem">All Pages</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/interactions/">Interactions</a>
|
||||
@@ -196,23 +197,23 @@
|
||||
x-transition
|
||||
@indiekit:auth.window="show = $event.detail.loggedIn"
|
||||
class="admin-nav-link">
|
||||
<svg class="w-4 h-4 inline -mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg class="w-4 h-4 inline -mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/>
|
||||
</svg>
|
||||
Dashboard
|
||||
</a>
|
||||
</nav>
|
||||
<a href="/search/" aria-label="Search" title="Search" class="p-2 rounded-lg text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/>
|
||||
</svg>
|
||||
</a>
|
||||
<button id="theme-toggle" type="button" class="theme-toggle" aria-label="Toggle dark mode" title="Toggle dark mode">
|
||||
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</button>
|
||||
@@ -226,13 +227,13 @@
|
||||
<a href="/now/">Now</a>
|
||||
{# Blog section #}
|
||||
<div class="mobile-nav-section">
|
||||
<button type="button" class="mobile-nav-toggle" @click="blogOpen = !blogOpen">
|
||||
<button type="button" class="mobile-nav-toggle" @click="blogOpen = !blogOpen" :aria-expanded="blogOpen.toString()" aria-controls="mobile-blog-submenu">
|
||||
Blog
|
||||
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-180': blogOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-180': blogOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="mobile-nav-submenu" x-show="blogOpen" x-collapse>
|
||||
<div id="mobile-blog-submenu" class="mobile-nav-submenu" x-show="blogOpen" x-collapse>
|
||||
<a href="/blog/">All Posts</a>
|
||||
{% for pt in enabledPostTypes %}
|
||||
<a href="{{ pt.path }}">{{ pt.label }}</a>
|
||||
@@ -241,13 +242,13 @@
|
||||
</div>
|
||||
{# Pages section #}
|
||||
<div class="mobile-nav-section">
|
||||
<button type="button" class="mobile-nav-toggle" @click="pagesOpen = !pagesOpen">
|
||||
<button type="button" class="mobile-nav-toggle" @click="pagesOpen = !pagesOpen" :aria-expanded="pagesOpen.toString()" aria-controls="mobile-pages-submenu">
|
||||
Pages
|
||||
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-180': pagesOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-180': pagesOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="mobile-nav-submenu" x-show="pagesOpen" x-collapse>
|
||||
<div id="mobile-pages-submenu" class="mobile-nav-submenu" x-show="pagesOpen" x-collapse>
|
||||
{% if blogrollStatus and blogrollStatus.source == "indiekit" %}<a href="/blogroll/">Blogroll</a>{% endif %}
|
||||
{% if podrollStatus and podrollStatus.source == "indiekit" %}<a href="/podroll/">Podroll</a>{% endif %}
|
||||
{% if newsActivity and newsActivity.source == "indiekit" %}<a href="/news/">News</a>{% endif %}
|
||||
@@ -267,11 +268,11 @@
|
||||
<button type="button" class="mobile-theme-toggle" aria-label="Toggle dark mode">
|
||||
<span class="theme-label">Theme</span>
|
||||
<span class="theme-icons">
|
||||
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</span>
|
||||
@@ -279,7 +280,7 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="container py-8" data-pagefind-body>
|
||||
<main class="container py-8" id="main-content" data-pagefind-body>
|
||||
{# Skeleton loader — shown until Tailwind stylesheet loads #}
|
||||
<div class="page-skeleton" aria-hidden="true">
|
||||
<div style="display:flex;gap:1.5rem;align-items:flex-start;margin-bottom:2rem">
|
||||
@@ -329,7 +330,7 @@
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 mb-8">
|
||||
{# Navigate #}
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400 mb-3">Navigate</h4>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-600 dark:text-surface-400 mb-3">Navigate</h4>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="/" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Home</a></li>
|
||||
<li><a href="/about/" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">About</a></li>
|
||||
@@ -339,7 +340,7 @@
|
||||
</div>
|
||||
{# Content #}
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400 mb-3">Content</h4>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-600 dark:text-surface-400 mb-3">Content</h4>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="/blog/" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Blog</a></li>
|
||||
{% for pt in enabledPostTypes %}
|
||||
@@ -350,7 +351,7 @@
|
||||
</div>
|
||||
{# Connect #}
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400 mb-3">Connect</h4>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-600 dark:text-surface-400 mb-3">Connect</h4>
|
||||
<ul class="space-y-2">
|
||||
{% for social in site.social %}
|
||||
<li><a href="{{ social.url }}" rel="{{ social.rel }}" target="_blank" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">{{ social.name }}</a></li>
|
||||
@@ -359,7 +360,7 @@
|
||||
</div>
|
||||
{# Meta #}
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400 mb-3">Meta</h4>
|
||||
<h4 class="text-sm font-semibold uppercase tracking-wider text-surface-600 dark:text-surface-400 mb-3">Meta</h4>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="/feed.xml" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">RSS Feed</a></li>
|
||||
<li><a href="/feed.json" class="text-sm text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-100 hover:underline">JSON Feed</a></li>
|
||||
@@ -367,7 +368,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center text-sm text-surface-500 dark:text-surface-400">Powered by <a href="https://getindiekit.com" class="hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Indiekit</a> + <a href="https://11ty.dev" class="hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Eleventy</a></p>
|
||||
<p class="text-center text-sm text-surface-600 dark:text-surface-400">Powered by <a href="https://getindiekit.com" class="hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Indiekit</a> + <a href="https://11ty.dev" class="hover:text-surface-900 dark:hover:text-surface-100 hover:underline">Eleventy</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
@@ -469,43 +470,43 @@
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100 translate-y-0"
|
||||
x-transition:leave-end="opacity-0 translate-y-4"
|
||||
class="fab-menu">
|
||||
class="fab-menu" role="menu" aria-label="Create new post">
|
||||
{% if mpUrl %}
|
||||
<a href="/posts/edit?url={{ mpUrl | urlencode }}" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-accent-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/edit?url={{ mpUrl | urlencode }}" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-accent-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
||||
</svg>
|
||||
<span>Edit this post</span>
|
||||
</a>
|
||||
<div class="fab-menu-divider"></div>
|
||||
<div class="fab-menu-divider" role="separator"></div>
|
||||
{% endif %}
|
||||
<a href="/posts/create?type=page" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/create?type=page" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>
|
||||
</svg>
|
||||
<span>Page</span>
|
||||
</a>
|
||||
<a href="/posts/create?type=bookmark" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/create?type=bookmark" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
|
||||
</svg>
|
||||
<span>Bookmark</span>
|
||||
</a>
|
||||
<a href="/posts/create?type=photo" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/create?type=photo" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/>
|
||||
</svg>
|
||||
<span>Photo</span>
|
||||
</a>
|
||||
<a href="/posts/create?type=article" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/create?type=article" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/>
|
||||
</svg>
|
||||
<span>Article</span>
|
||||
</a>
|
||||
<a href="/posts/create?type=note" @click="open = false" class="fab-menu-item" rel="nofollow">
|
||||
<svg class="w-5 h-5 text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<a href="/posts/create?type=note" @click="open = false" class="fab-menu-item" rel="nofollow" role="menuitem">
|
||||
<svg class="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
|
||||
</svg>
|
||||
<span>Note</span>
|
||||
@@ -515,8 +516,9 @@
|
||||
<button @click="open = !open"
|
||||
class="fab-button"
|
||||
:aria-expanded="open"
|
||||
aria-label="Create new post">
|
||||
<svg class="w-7 h-7 transition-transform duration-200" :class="{ 'rotate-45': open }" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5" stroke-linecap="round">
|
||||
aria-label="Create new post"
|
||||
aria-haspopup="menu">
|
||||
<svg class="w-7 h-7 transition-transform duration-200" :class="{ 'rotate-45': open }" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5" stroke-linecap="round" aria-hidden="true">
|
||||
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@@ -90,7 +90,7 @@ withSidebar: true
|
||||
{% if post.data.summary %}
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-2 line-clamp-2">{{ post.data.summary }}</p>
|
||||
{% endif %}
|
||||
<div class="flex items-center gap-3 text-xs text-surface-500">
|
||||
<div class="flex items-center gap-3 text-xs text-surface-600 dark:text-surface-400">
|
||||
<time class="font-mono" datetime="{{ post.data.published or post.date }}">
|
||||
{{ (post.data.published or post.date) | date("MMM d, yyyy") }}
|
||||
</time>
|
||||
|
||||
@@ -16,7 +16,7 @@ withSidebar: true
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if updated %}
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mt-2">
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mt-2">
|
||||
Last updated: <time class="dt-updated font-mono text-sm" datetime="{{ updated | isoDate }}">{{ updated | dateDisplay }}</time>
|
||||
</p>
|
||||
{% endif %}
|
||||
@@ -35,19 +35,19 @@ withSidebar: true
|
||||
<div class="grid gap-4 sm:grid-cols-4 mb-6">
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold text-surface-900 dark:text-surface-100">{{ stats.total }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">Total posts</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">Total posts</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold text-amber-600 dark:text-amber-400">{{ stats.aiCount }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">AI-involved</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">AI-involved</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold text-emerald-600 dark:text-emerald-400">{{ stats.total - stats.aiCount }}</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">Human-only</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">Human-only</div>
|
||||
</div>
|
||||
<div class="text-center p-3 rounded-lg bg-surface-50 dark:bg-surface-800 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="text-2xl font-bold text-surface-900 dark:text-surface-100">{{ stats.percentage }}%</div>
|
||||
<div class="text-xs text-surface-500 dark:text-surface-400">AI ratio</div>
|
||||
<div class="text-xs text-surface-600 dark:text-surface-400">AI ratio</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@ withSidebar: true
|
||||
|
||||
{# Post graph showing AI posts (highlighted) on the full year grid #}
|
||||
<h3 class="text-lg font-semibold text-surface-900 dark:text-surface-100 mb-3">AI-Involved Posts Over Time</h3>
|
||||
<p class="text-sm text-surface-500 dark:text-surface-400 mb-4">Highlighted days had posts with AI involvement (level 1+). Empty boxes represent days with no AI-involved posts.</p>
|
||||
<p class="text-sm text-surface-600 dark:text-surface-400 mb-4">Highlighted days had posts with AI involvement (level 1+). Empty boxes represent days with no AI-involved posts.</p>
|
||||
{% postGraph aiPostsList, { prefix: "ai", highlightColorLight: "#d97706", highlightColorDark: "#fbbf24" } %}
|
||||
</section>
|
||||
{% endif %}
|
||||
@@ -82,7 +82,7 @@ withSidebar: true
|
||||
{% if aiTextLevel or aiCodeLevel or aiTools %}
|
||||
<aside class="mt-6 p-4 rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200 dark:border-surface-700 shadow-sm">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<svg class="w-4 h-4 text-surface-500 dark:text-surface-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<svg class="w-4 h-4 text-surface-600 dark:text-surface-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714a2.25 2.25 0 00.659 1.591L19 14.5M14.25 3.104c.251.023.501.05.75.082M19 14.5l-2.47 2.47a2.25 2.25 0 01-1.59.659H9.06a2.25 2.25 0 01-1.591-.659L5 14.5m14 0V17a2 2 0 01-2 2H7a2 2 0 01-2-2v-2.5"/>
|
||||
</svg>
|
||||
<strong class="text-sm font-semibold text-surface-700 dark:text-surface-300">AI Usage</strong>
|
||||
@@ -105,7 +105,7 @@ withSidebar: true
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if aiDescription %}
|
||||
<p class="mt-2 text-xs text-surface-500 dark:text-surface-400">{{ aiDescription }}</p>
|
||||
<p class="mt-2 text-xs text-surface-600 dark:text-surface-400">{{ aiDescription }}</p>
|
||||
{% endif %}
|
||||
<p class="mt-2 text-xs"><a href="/ai/" class="text-accent-600 dark:text-accent-400 hover:underline">Learn more about AI usage on this site →</a></p>
|
||||
</aside>
|
||||
|
||||
@@ -13,7 +13,7 @@ withBlogSidebar: true
|
||||
<h1 class="p-name text-2xl sm:text-3xl font-bold text-surface-900 dark:text-surface-100 mb-3 sm:mb-4">{{ title }}</h1>
|
||||
{% else %}
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<span class="text-sm font-medium text-surface-500 dark:text-surface-400">
|
||||
<span class="text-sm font-medium text-surface-600 dark:text-surface-400">
|
||||
{% if replyTo %}↩ Reply{% elif likedUrl %}♥ Like{% elif repostedUrl %}♻ Repost{% elif bookmarkedUrl %}🔖 Bookmark{% else %}✎ Note{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
@@ -73,7 +73,7 @@ withBlogSidebar: true
|
||||
{% set aiCodeLevel = aiCodeLevel or ai_code_level %}
|
||||
{% set aiTools = aiTools or ai_tools %}
|
||||
{% set aiDescription = aiDescription or ai_description %}
|
||||
<details class="mt-4 text-xs text-surface-500 dark:text-surface-400">
|
||||
<details class="mt-4 text-xs text-surface-600 dark:text-surface-400">
|
||||
<summary class="cursor-pointer hover:text-surface-600 dark:hover:text-surface-300 list-none flex items-center gap-1.5 [&::-webkit-details-marker]:hidden">
|
||||
<svg class="w-3.5 h-3.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714a2.25 2.25 0 00.659 1.591L19 14.5M14.25 3.104c.251.023.501.05.75.082M19 14.5l-2.47 2.47a2.25 2.25 0 01-1.59.659H9.06a2.25 2.25 0 01-1.591-.659L5 14.5m14 0V17a2 2 0 01-2 2H7a2 2 0 01-2-2v-2.5"/>
|
||||
@@ -115,7 +115,7 @@ withBlogSidebar: true
|
||||
{% if externalSyndication.length or selfHostedApUrl %}
|
||||
<footer class="post-footer mt-8 pt-6 border-t border-surface-200 dark:border-surface-700">
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
<span class="text-sm text-surface-500 dark:text-surface-400">Also on:</span>
|
||||
<span class="text-sm text-surface-600 dark:text-surface-400">Also on:</span>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
{# Fediverse remote interaction button (self-hosted ActivityPub) #}
|
||||
{% if selfHostedApUrl %}
|
||||
@@ -269,9 +269,10 @@ withBlogSidebar: true
|
||||
{# Lightbox overlay for article images #}
|
||||
<template x-teleport="body">
|
||||
<div x-show="open" x-transition.opacity.duration.200ms
|
||||
role="dialog" aria-modal="true" aria-label="Image viewer"
|
||||
class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/90 backdrop-blur-sm"
|
||||
@click.self="close()">
|
||||
<button @click="close()" class="absolute top-4 right-4 text-white/70 hover:text-white text-3xl leading-none p-2 z-10" aria-label="Close">×</button>
|
||||
<button x-ref="closeBtn" @click="close()" class="absolute top-4 right-4 text-white/70 hover:text-white text-3xl leading-none p-2 z-10" aria-label="Close lightbox">×</button>
|
||||
<template x-if="images.length > 1">
|
||||
<button @click="prev()" class="absolute left-4 top-1/2 -translate-y-1/2 text-white/70 hover:text-white text-4xl leading-none p-2 z-10" aria-label="Previous">‹</button>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user