@tailwind base; @tailwind components; @tailwind utilities; /* Accessibility utilities */ @layer utilities { .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .skip-link { @apply absolute -top-full left-0 z-50 bg-primary-600 text-white px-4 py-2; } .skip-link:focus { @apply top-0; } } /* Reduce motion for accessibility */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } /* Dark mode body background */ @layer base { body { @apply bg-white dark:bg-surface-950 text-surface-900 dark:text-surface-100; } } /* Layout styles */ @layer components { /* Site header */ .site-header { @apply bg-white dark:bg-surface-900 border-b border-surface-200 dark:border-surface-700 py-4 sticky top-0 z-50; } .header-container { @apply flex items-center justify-between; } .site-title { @apply text-xl font-bold text-surface-900 dark:text-white no-underline hover:text-primary-600 dark:hover:text-primary-400 transition-colors; } /* Header actions (nav + theme toggle) */ .header-actions { @apply hidden md:flex items-center gap-4; } .site-nav { @apply flex items-center gap-4; } .site-nav > a, .site-nav .nav-dropdown-trigger { @apply text-surface-600 dark:text-surface-400 hover:text-primary-600 dark:hover:text-primary-400 no-underline transition-colors py-2; } /* Navigation dropdown */ .nav-dropdown { @apply relative; } .nav-dropdown-trigger { @apply flex items-center gap-1 cursor-pointer bg-transparent border-none text-base; } .nav-dropdown-menu { @apply absolute top-full left-0 mt-1 py-2 bg-white dark:bg-surface-800 border border-surface-200 dark:border-surface-700 rounded-lg shadow-lg min-w-[160px] z-50 overflow-y-auto; max-height: calc(100vh - 5rem); max-height: calc(100dvh - 5rem); } .nav-dropdown-menu a { @apply block px-4 py-2 text-sm text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-700 hover:text-primary-600 dark:hover:text-primary-400 no-underline; } .nav-dropdown-divider { @apply my-2 border-t border-surface-200 dark:border-surface-700; } /* Mobile menu toggle button */ .menu-toggle { @apply md:hidden p-2 rounded-lg text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors; } /* Mobile navigation dropdown */ .mobile-nav { @apply md:hidden border-t border-surface-200 dark:border-surface-700 bg-white dark:bg-surface-900 overflow-y-auto; max-height: calc(100vh - 4rem); max-height: calc(100dvh - 4rem); } .mobile-nav a { @apply block px-4 py-3 text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 hover:text-primary-600 dark:hover:text-primary-400 no-underline transition-colors border-b border-surface-100 dark:border-surface-800 last:border-b-0; } /* Mobile nav collapsible sections */ .mobile-nav-section { @apply border-b border-surface-100 dark:border-surface-800; } .mobile-nav-toggle { @apply flex items-center justify-between w-full px-4 py-3 text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 hover:text-primary-600 dark:hover:text-primary-400 transition-colors bg-transparent border-none text-base text-left cursor-pointer; } .mobile-nav-submenu { @apply bg-surface-50 dark:bg-surface-800; } .mobile-nav-submenu a { @apply pl-8 py-2 text-sm border-b-0; } .mobile-nav-divider { @apply my-2 mx-4 border-t border-surface-200 dark:border-surface-700; } /* Theme toggle button */ .theme-toggle { @apply p-2 rounded-lg text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors; } .theme-toggle .sun-icon { @apply hidden; } .theme-toggle .moon-icon { @apply block; } .dark .theme-toggle .sun-icon { @apply block; } .dark .theme-toggle .moon-icon { @apply hidden; } /* Mobile theme toggle */ .mobile-theme-toggle { @apply flex items-center justify-between w-full px-4 py-3 text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 hover:text-primary-600 dark:hover:text-primary-400 transition-colors bg-transparent border-none text-base text-left cursor-pointer border-t border-surface-200 dark:border-surface-700; } .mobile-theme-toggle .theme-label { @apply font-normal; } .mobile-theme-toggle .theme-icons { @apply flex items-center; } .mobile-theme-toggle .sun-icon { @apply hidden; } .mobile-theme-toggle .moon-icon { @apply block; } .dark .mobile-theme-toggle .sun-icon { @apply block; } .dark .mobile-theme-toggle .moon-icon { @apply hidden; } /* Container */ .container { @apply max-w-5xl mx-auto px-4; } /* Site footer */ .site-footer { @apply mt-12 py-8 border-t border-surface-200 dark:border-surface-700 text-center text-sm text-surface-500; } .site-footer a { @apply text-primary-600 dark:text-primary-400 hover:underline; } /* Layout with sidebar - mobile-first with responsive grid */ .layout-with-sidebar { @apply grid grid-cols-1 gap-6 md:gap-8 lg:grid-cols-3; } .main-content { @apply lg:col-span-2 min-w-0 overflow-x-hidden; /* min-w-0 + overflow-x-hidden prevents layout breaking */ } .sidebar { @apply space-y-6 lg:sticky lg:top-24 lg:self-start overflow-hidden; } /* Main content area - adjust padding for mobile */ main.container { @apply py-6 md:py-8; } } /* Custom component styles */ @layer components { /* Post list */ .post-list { @apply list-none p-0 m-0 space-y-6; } .post-list li { @apply pb-6 border-b border-b-surface-200 dark:border-b-surface-700 last:border-0; } /* Post meta */ .post-meta { @apply text-sm text-surface-600 dark:text-surface-400 flex flex-wrap gap-2 items-center; } /* Category tags */ .p-category { @apply inline-block px-2 py-0.5 text-xs bg-primary-100 dark:bg-primary-900 text-primary-800 dark:text-primary-200 rounded; } /* Webmention facepile - overlapping avatar display */ .facepile { @apply flex flex-wrap items-center; } .facepile-avatar { @apply inline-block -ml-2 first:ml-0 transition-transform hover:z-10 hover:scale-110; } .facepile-avatar img { @apply w-8 h-8 rounded-full; } /* GitHub components */ .repo-card { @apply p-4 border border-surface-200 dark:border-surface-700 rounded-lg; } .repo-meta { @apply flex gap-4 text-sm text-surface-600 dark:text-surface-400 mt-2; } /* Timeline for CV */ .timeline { @apply relative pl-6 border-l-2 border-primary-500; } .timeline-item { @apply relative pb-6 last:pb-0; } .timeline-item::before { content: ''; @apply absolute -left-[calc(1.5rem+5px)] top-1.5 w-3 h-3 bg-primary-500 rounded-full; } /* Skills badges */ .skill-badge { @apply inline-block px-3 py-1 text-sm bg-surface-100 dark:bg-surface-800 rounded-full; } /* Ensure is-land custom elements don't break block layout flow */ is-land { @apply block; } /* Widget cards */ .widget { @apply p-4 mb-4 bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden; } .widget-title { @apply font-bold text-lg mb-4; } /* Collapsible widget wrapper */ .widget-header { @apply flex items-center justify-between cursor-pointer; } .widget-header .widget-title { @apply mb-0; } .widget-chevron { @apply w-4 h-4 text-surface-400 transition-transform duration-200 shrink-0; } /* Hide inner widget titles when the collapsible wrapper provides one */ .widget-collapsible .widget .widget-title { @apply hidden; } /* Hide FeedLand's custom title in collapsible wrapper */ .widget-collapsible .widget .fl-title { @apply hidden; } /* Neutralize inner widget card styling when inside collapsible wrapper */ .widget-collapsible .widget { @apply border-0 shadow-none rounded-none mb-0 bg-transparent; } /* Post cards */ .post-card { @apply p-5 bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden; } .post-header { @apply flex flex-wrap items-center gap-2; } .post-footer { @apply pt-3 border-t border-surface-100 dark:border-surface-700; } /* Photo gallery on listing pages */ .photo-list li { @apply pb-8; } .photo-gallery { @apply my-4 grid gap-2; } .photo-gallery img { @apply w-full max-h-[500px] object-cover rounded-lg; } .photo-link { @apply block; } .photo-caption { @apply mt-3 text-surface-600 dark:text-surface-400; } /* Multi-photo grid */ .photo-gallery:has(img:nth-child(2)) { @apply grid-cols-2; } .photo-gallery:has(img:nth-child(3)) { @apply grid-cols-2; } .photo-gallery:has(img:nth-child(4)) { @apply grid-cols-2; } /* Pagination */ .pagination { @apply mt-12 pt-8 border-t border-surface-200 dark:border-surface-700 flex flex-col sm:flex-row items-center justify-between gap-4; } .pagination-info { @apply text-sm text-surface-600 dark:text-surface-400; } .pagination-links { @apply flex items-center gap-2; } .pagination-link { @apply inline-flex items-center gap-1 px-4 py-2 text-sm font-medium bg-surface-100 dark:bg-surface-800 rounded-lg hover:bg-surface-200 dark:hover:bg-surface-700 transition-colors; } .pagination-link.disabled { @apply opacity-50 cursor-not-allowed hover:bg-surface-100 dark:hover:bg-surface-800; } } /* Focus states */ @layer base { a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible { @apply outline-2 outline-offset-2 outline-primary-500; } } /* Video embeds */ @layer components { .video-embed { @apply relative w-full aspect-video my-4; } .video-embed iframe { @apply absolute inset-0 w-full h-full rounded-lg; } } /* Admin UI - FAB and dashboard link */ @layer components { .fab-container { @apply fixed bottom-6 right-6 z-50 flex flex-col items-end; } .fab-backdrop { @apply fixed inset-0 bg-black/20 dark:bg-black/40 z-40; } .fab-button { @apply relative z-50 w-14 h-14 rounded-full bg-primary-600 hover:bg-primary-700 dark:bg-primary-500 dark:hover:bg-primary-600 text-white shadow-lg hover:shadow-xl transition-all duration-200 flex items-center justify-center; } .fab-button:focus-visible { @apply outline-2 outline-offset-2 outline-primary-500; } .fab-menu { @apply relative z-50 mb-3 flex flex-col gap-2 items-end; } .fab-menu-item { @apply flex items-center gap-3 px-4 py-3 rounded-xl bg-white dark:bg-surface-800 shadow-md hover:shadow-lg border border-surface-200 dark:border-surface-700 text-surface-700 dark:text-surface-200 hover:text-primary-600 dark:hover:text-primary-400 no-underline transition-all duration-150 text-sm font-medium; } .fab-menu-divider { @apply border-t border-surface-200 dark:border-surface-700 my-1 w-full; } .admin-nav-link { @apply text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 no-underline transition-colors py-2 inline-flex items-center gap-1; } } /* Performance: content-visibility for off-screen rendering optimization */ @layer utilities { .content-auto { content-visibility: auto; contain-intrinsic-size: auto 500px; } } /* Apply content-visibility to images and post items for performance */ @layer base { /* Responsive typography */ html { @apply text-base md:text-lg; } /* Prevent horizontal overflow */ body { @apply overflow-x-hidden; } /* Images - prevent overflow and add content-visibility */ img { @apply max-w-full h-auto; content-visibility: auto; } /* Pre/code blocks - prevent overflow on mobile */ pre { @apply overflow-x-auto max-w-full; -webkit-overflow-scrolling: touch; } code { @apply break-words; } pre code { word-break: normal; overflow-wrap: normal; } /* Links in content - break long URLs */ .e-content a, .prose a { @apply break-words; word-break: break-word; } /* Content containers - clip horizontal overflow but allow pre blocks to scroll */ .e-content, .prose { overflow-x: clip; max-width: 100%; } article { scroll-margin-top: 80px; /* Prevent header overlap when scrolling to anchors */ } /* Heading anchors — generated by markdown-it-anchor */ .prose h2[id], .prose h3[id], .prose h4[id] { scroll-margin-top: 80px; } .prose :is(h2, h3, h4) > a.header-anchor { color: inherit; text-decoration: none; } .prose :is(h2, h3, h4) > a.header-anchor:hover { text-decoration: underline; text-decoration-color: var(--tw-prose-links, currentColor); text-underline-offset: 4px; } .prose :is(h2, h3, h4) > a.header-anchor::after { content: " #"; opacity: 0; font-weight: normal; transition: opacity 0.15s; } .prose :is(h2, h3, h4):hover > a.header-anchor::after { opacity: 0.4; } .post-list li { content-visibility: auto; contain-intrinsic-size: auto 200px; } /* Tables - responsive handling */ table { @apply w-full; display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; } /* Ensure truncate works properly in flex containers */ .truncate { @apply overflow-hidden text-ellipsis whitespace-nowrap; } /* Video embeds - maintain aspect ratio */ lite-youtube, iframe[src*="youtube"], iframe[src*="vimeo"] { @apply max-w-full; } } /* Pagefind UI theme overrides — outside @layer for higher specificity over Pagefind's :root defaults */ #search .pagefind-ui { --pagefind-ui-scale: 1; --pagefind-ui-primary: #2563eb; --pagefind-ui-text: #18181b; --pagefind-ui-background: #ffffff; --pagefind-ui-border: #e4e4e7; --pagefind-ui-tag: #f4f4f5; --pagefind-ui-border-width: 1px; --pagefind-ui-border-radius: 8px; --pagefind-ui-image-border-radius: 8px; --pagefind-ui-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } .dark #search .pagefind-ui { --pagefind-ui-primary: #60a5fa; --pagefind-ui-text: #f4f4f5; --pagefind-ui-background: #09090b; --pagefind-ui-border: #3f3f46; --pagefind-ui-tag: #27272a; } /* Search input */ #search .pagefind-ui__search-input { background-color: #ffffff; color: #18181b; border-color: #e4e4e7; font-weight: 400; } .dark #search .pagefind-ui__search-input { background-color: #18181b; color: #f4f4f5; border-color: #3f3f46; } #search .pagefind-ui__search-input:focus { outline: 2px solid #3b82f6; outline-offset: 2px; border-color: #3b82f6; } .dark #search .pagefind-ui__search-input:focus { outline-color: #60a5fa; border-color: #60a5fa; } /* Search clear button */ #search .pagefind-ui__search-clear { color: #52525b; background-color: #ffffff; } .dark #search .pagefind-ui__search-clear { color: #a1a1aa; background-color: #18181b; } #search .pagefind-ui__search-clear:hover { color: #18181b; } .dark #search .pagefind-ui__search-clear:hover { color: #f4f4f5; } /* Result links */ #search .pagefind-ui__result-link { color: #2563eb; } #search .pagefind-ui__result-link:hover { text-decoration: underline; } .dark #search .pagefind-ui__result-link { color: #60a5fa; } /* Result excerpts */ #search .pagefind-ui__result-excerpt { color: #52525b; } .dark #search .pagefind-ui__result-excerpt { color: #a1a1aa; } /* Highlighted search terms in results */ #search .pagefind-ui__result-excerpt mark, #search mark { background-color: #dbeafe; color: #1e40af; padding: 0.1em 0.2em; border-radius: 2px; } .dark #search .pagefind-ui__result-excerpt mark, .dark #search mark { background-color: #1e3a8a; color: #bfdbfe; } /* Message (result count) */ #search .pagefind-ui__message { color: #52525b; } .dark #search .pagefind-ui__message { color: #a1a1aa; } /* "Load more" button */ #search .pagefind-ui__button { color: #2563eb; background-color: #ffffff; border-color: #e4e4e7; cursor: pointer; } #search .pagefind-ui__button:hover { background-color: #eff6ff; border-color: #2563eb; } .dark #search .pagefind-ui__button { color: #60a5fa; background-color: #09090b; border-color: #3f3f46; } .dark #search .pagefind-ui__button:hover { background-color: #18181b; border-color: #60a5fa; } /* Filter panel labels */ #search .pagefind-ui__filter-name, #search .pagefind-ui__filter-label { color: #18181b; } .dark #search .pagefind-ui__filter-name, .dark #search .pagefind-ui__filter-label { color: #f4f4f5; } /* Result tags */ #search .pagefind-ui__result-tag { background-color: #f4f4f5; color: #52525b; } .dark #search .pagefind-ui__result-tag { background-color: #27272a; color: #a1a1aa; } /* Sub-result nested links */ #search .pagefind-ui__result-nested .pagefind-ui__result-link { color: #2563eb; font-weight: 400; } .dark #search .pagefind-ui__result-nested .pagefind-ui__result-link { color: #60a5fa; } /* Mobile-specific improvements */ @layer utilities { /* Ensure proper touch scrolling on overflow containers */ .overflow-x-auto { -webkit-overflow-scrolling: touch; } /* Hide scrollbar but allow scrolling */ .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } .scrollbar-hide::-webkit-scrollbar { display: none; } } /* Save for Later buttons — hidden until auth confirmed */ .save-later-btn { display: none; } body[data-indiekit-auth="true"] .save-later-btn { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; background: none; border: 1px solid transparent; border-radius: 6px; padding: 2px 8px; font-size: 0.75rem; color: #6b7280; transition: all 0.2s ease; } body[data-indiekit-auth="true"] .save-later-btn:hover { border-color: #d1d5db; color: #4a9eff; } .save-later--saved { color: #4a9eff !important; opacity: 0.6; pointer-events: none; }