diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-22 12:43:22 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-22 12:43:22 +0200 |
| commit | 5b476f8905f411768e23cb01d577a60e5a5fd725 (patch) | |
| tree | 0a08cc83d809dbea714f52826e822501ee7c0165 /themes/danix-xyz-hacker/assets/css/main.css | |
| parent | 082e9246ffe453031894d32d3cee9d5d1bf2b67a (diff) | |
| download | danixxyz-5b476f8905f411768e23cb01d577a60e5a5fd725.tar.gz danixxyz-5b476f8905f411768e23cb01d577a60e5a5fd725.zip | |
chore: extract theme into git submodule (danix2-hugo-theme)
Diffstat (limited to 'themes/danix-xyz-hacker/assets/css/main.css')
| -rw-r--r-- | themes/danix-xyz-hacker/assets/css/main.css | 1709 |
1 files changed, 0 insertions, 1709 deletions
diff --git a/themes/danix-xyz-hacker/assets/css/main.css b/themes/danix-xyz-hacker/assets/css/main.css deleted file mode 100644 index ab41a7d..0000000 --- a/themes/danix-xyz-hacker/assets/css/main.css +++ /dev/null @@ -1,1709 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* Dark theme (default) - CSS custom properties */ -:root { - --bg: #060b10; - --bg2: #0c1520; - --bg2-rgb: 12, 21, 32; - --surface: #101e2d; - --surface-rgb: 16, 30, 45; - --border: #182840; - --accent: #a855f7; - --accent-rgb: 168, 85, 247; - --accent2: #00ff88; - --accent-glow: rgba(168, 85, 247, 0.12); - --text: #c4d6e8; - --text-dim: #7a9bb8; - --muted: #304860; - /* Article type colors - dark */ - --type-tech: #a855f7; - --type-life: #f59e0b; - --type-quote: #00ff88; - --type-link: #38bdf8; - --type-photo: #ec4899; - /* Article type text colors - dark (all black for WCAG AA) */ - --type-tech-text: #000000; - --type-life-text: #000000; - --type-quote-text: #000000; - --type-link-text: #000000; - --type-photo-text: #000000; -} - -/* Light theme overrides */ -html.theme-light { - --bg: #ffffff; - --bg2: #f8f9fa; - --bg2-rgb: 248, 249, 250; - --surface: #f0f3f7; - --surface-rgb: 240, 243, 247; - --border: #d9dfe8; - --accent: #9333ea; - --accent-rgb: 147, 51, 234; - --accent2: #10b981; - --accent-glow: rgba(147, 51, 234, 0.1); - --text: #1f2937; - --text-dim: #374151; - --muted: #d1d5db; - /* Article type colors - light */ - --type-tech: #7c3aed; - --type-life: #d97706; - --type-quote: #008f5a; - --type-link: #0284c7; - --type-photo: #be185d; - /* Article type text colors - light (mixed for WCAG AA) */ - --type-tech-text: #ffffff; - --type-life-text: #000000; - --type-quote-text: #000000; - --type-link-text: #000000; - --type-photo-text: #ffffff; -} - -/* No-JS fallback: prefers-color-scheme light */ -@media (prefers-color-scheme: light) { - html:not(.theme-dark) { - --bg: #ffffff; - --bg2: #f8f9fa; - --bg2-rgb: 248, 249, 250; - --surface: #f0f3f7; - --surface-rgb: 240, 243, 247; - --border: #d9dfe8; - --accent: #9333ea; - --accent-rgb: 147, 51, 234; - --accent2: #10b981; - --accent-glow: rgba(147, 51, 234, 0.1); - --text: #1f2937; - --text-dim: #374151; - --muted: #d1d5db; - --type-tech: #7c3aed; - --type-life: #d97706; - --type-quote: #008f5a; - --type-link: #0284c7; - --type-photo: #be185d; - --type-tech-text: #ffffff; - --type-life-text: #000000; - --type-quote-text: #000000; - --type-link-text: #000000; - --type-photo-text: #ffffff; - } -} - -/* Theme-aware picture element for default thumbnails */ -html.theme-light picture img[src="/images/default_thumbnail_dark.png"] { - content: url('/images/default_thumbnail_light.png'); -} - -@layer base { - html { - @apply overflow-x-hidden; - } - - body { - @apply bg-bg text-text font-body overflow-x-hidden; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - @apply font-bold; - font-family: 'Oxanium', monospace; - } - - h1 { - @apply text-3xl md:text-4xl; - } - - h2 { - @apply text-2xl md:text-3xl; - } - - h3 { - @apply text-xl md:text-2xl; - } - - .heading-prefix { - font-family: 'JetBrains Mono', monospace; - font-weight: 400; - font-size: 0.8em; - color: var(--accent); - opacity: 0.7; - margin-right: 0.35em; - user-select: none; - } - - a { - @apply text-accent hover:opacity-80 transition-opacity; - } - - code { - @apply font-mono bg-surface border border-border px-1.5 py-0.5 rounded text-accent2; - } - - pre { - background-color: rgba(var(--surface-rgb), 0.8); - @apply p-4 rounded border border-border overflow-x-auto; - } - - pre code { - @apply bg-transparent border-0 p-0 text-text; - } - - *:focus-visible { - @apply ring-2 ring-accent ring-offset-2; - ring-offset-color: var(--bg); - } - - button, - input, - textarea, - select { - @apply transition-colors duration-200; - } -} - -@layer components { - .container { - @apply max-w-4xl mx-auto; - } - - /* Background utilities */ - .bg-bg { - background-color: var(--bg); - } - - .bg-bg2 { - background-color: var(--bg2); - } - - .bg-surface { - background-color: var(--surface); - } - - /* Border utilities */ - .border-border { - border-color: var(--border); - } - - /* Text color utilities */ - .text-accent { - color: var(--accent); - } - - .text-accent2 { - color: var(--accent2); - } - - .text-text { - color: var(--text); - } - - .text-text-dim { - color: var(--text-dim); - } - - /* Additional semantic utilities */ - .text-muted { - color: var(--muted); - } - - .bg-muted { - background-color: var(--muted); - } - - /* Glow effect utility */ - .glow-accent { - box-shadow: 0 0 20px var(--accent-glow); - } - - /* Frosted glass bar (header/footer) */ - .frosted-bar { - background-color: rgba(var(--bg2-rgb), 0.75); - backdrop-filter: blur(10px); - box-shadow: 0 0 20px var(--accent-glow); - /* border applied via utility classes in templates */ - } - - /* Border utilities for frosted-bar component */ - .frosted-bar.border-b, - .frosted-bar.border-t { - border-color: var(--border); - } - - /* Button component styles */ - .btn { - @apply inline-flex items-center justify-center px-4 py-2 rounded font-bold transition-all duration-200 cursor-pointer; - background-color: var(--accent); - color: #ffffff; - border: none; - outline: none; - } - - .btn:hover:not(:disabled) { - opacity: 0.85; - transform: translateY(-1px); - } - - .btn:focus-visible { - @apply ring-2 ring-offset-2; - ring-color: var(--accent); - ring-offset-color: var(--bg); - } - - .btn:active:not(:disabled) { - transform: translateY(0); - opacity: 0.75; - } - - .btn:disabled { - opacity: 0.5; - cursor: not-allowed; - } - - /* Button variants */ - .btn-primary { - background-color: var(--accent); - color: #ffffff; - } - - .btn-primary:hover:not(:disabled) { - background-color: var(--accent); - } - - .btn-secondary { - background-color: var(--accent2); - color: var(--bg); - font-weight: 600; - } - - .btn-secondary:hover:not(:disabled) { - background-color: var(--accent2); - } - - .btn-outline { - background-color: transparent; - color: var(--accent); - border: 2px solid var(--accent); - } - - .btn-outline:hover:not(:disabled) { - background-color: var(--accent); - color: #ffffff; - } - - /* Button sizes */ - .btn-sm { - @apply px-3 py-1 text-sm; - } - - .btn-lg { - @apply px-6 py-3 text-lg; - } - - /* Icon button (for icons without text) */ - .btn-icon { - @apply rounded-full inline-flex items-center justify-center; - width: auto; - height: auto; - padding: 0.5rem; - } - - .btn-icon svg, - .btn-icon i { - width: auto !important; - height: auto !important; - } - - /* Force Feather icons to match size */ - .btn-icon [data-feather] { - width: 50px !important; - height: 50px !important; - } - - .btn-icon [data-feather] svg { - width: 50px !important; - height: 50px !important; - } - - /* Sidebar widget — no box, no border */ - .sidebar-widget { - margin-bottom: 1.5rem; - } - - /* Sidebar widget title — bash comment style */ - .sidebar-widget-label { - font-family: var(--font-mono, monospace); - font-size: 1rem; - font-weight: bold; - color: var(--accent); - letter-spacing: 0.08em; - margin-bottom: 0.5rem; - } - - /* Sidebar separator */ - .sidebar-hr { - border: none; - border-top: 1px solid var(--border); - margin-bottom: 1.5rem; - } - - /* ===================== - Tag Cloud Component - ===================== */ - - .tag-cloud { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 0.75rem; - align-items: baseline; - overflow: visible; - } - - .tag-cloud-link { - display: inline-flex; - align-items: center; - gap: 0.375rem; - padding: 0.25rem 0.625rem; - border: 1px solid var(--border); - border-radius: 0.25rem; - font-family: var(--font-mono, 'JetBrains Mono', monospace); - color: var(--text-dim); - text-decoration: none; - background-color: var(--bg2); - transition: border-color 150ms ease-out, color 150ms ease-out, background-color 150ms ease-out, opacity 150ms ease-out; - white-space: nowrap; - line-height: 1.4; - } - - .tag-cloud-link:hover { - border-color: rgba(var(--accent-rgb), 0.5); - color: var(--accent); - background-color: rgba(var(--accent-rgb), 0.1); - } - - .tag-cloud-link:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - border-radius: 0.25rem; - } - - .tag-cloud-count { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0 0.375rem; - border-radius: 9999px; - font-size: 0.65em; - font-weight: 600; - background-color: rgba(var(--accent-rgb), 0.12); - color: var(--accent); - line-height: 1.6; - min-width: 1.2em; - } - - @media (prefers-reduced-motion: reduce) { - .tag-cloud-link { - transition: none; - } - } - - .share-grid { - display: grid; - grid-template-columns: repeat(3, 50px); - justify-content: space-evenly; - justify-items: center; - align-content: space-evenly; - align-items: center; - } - - .btn-share { - display: inline-flex; - align-items: center; - justify-content: center; - width: 50px; - height: 50px; - border-radius: 4px; - border: 1px solid var(--border); - background: var(--surface); - color: var(--text-dim); - cursor: pointer; - transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease; - text-decoration: none; - } - - .btn-share svg, - .btn-share i, - .btn-share [data-feather] { - width: 22px !important; - height: 22px !important; - flex-shrink: 0; - } - - .btn-share:hover { - color: var(--accent); - border-color: rgba(var(--accent-rgb), 0.5); - background: rgba(var(--accent-rgb), 0.06); - box-shadow: 0 0 10px var(--accent-glow); - } - - .btn-share:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - color: var(--accent); - border-color: var(--accent); - } - - .btn-share--copied { - color: var(--accent2); - border-color: var(--accent2); - background: var(--surface); - } - - @media (prefers-reduced-motion: reduce) { - .btn-share { - transition: none; - } - } - - /* Badge base style */ - .badge { - @apply inline-flex items-center px-2.5 py-1 rounded text-sm font-mono font-semibold whitespace-nowrap transition-all duration-200; - border: 1px solid; - } - - /* Article type badge styles */ - .badge-tech { - color: var(--type-tech); - background-color: rgba(168, 85, 247, 0.1); - border-color: rgba(168, 85, 247, 0.3); - } - - .badge-tech:hover { - background-color: rgba(168, 85, 247, 0.2); - } - - .badge-life { - color: var(--type-life); - background-color: rgba(245, 158, 11, 0.1); - border-color: rgba(245, 158, 11, 0.3); - } - - .badge-life:hover { - background-color: rgba(245, 158, 11, 0.2); - } - - .badge-quote { - color: var(--type-quote); - background-color: rgba(0, 255, 136, 0.1); - border-color: rgba(0, 255, 136, 0.3); - } - - .badge-quote:hover { - background-color: rgba(0, 255, 136, 0.2); - } - - .badge-link { - color: var(--type-link); - background-color: rgba(56, 189, 248, 0.1); - border-color: rgba(56, 189, 248, 0.3); - } - - .badge-link:hover { - background-color: rgba(56, 189, 248, 0.2); - } - - .badge-photo { - color: var(--type-photo); - background-color: rgba(236, 72, 153, 0.1); - border-color: rgba(236, 72, 153, 0.3); - } - - .badge-photo:hover { - background-color: rgba(236, 72, 153, 0.2); - } - - /* Legacy type-* classes for compatibility (with badge styling) */ - .type-tech { - color: var(--type-tech); - background-color: rgba(168, 85, 247, 0.1); - } - - .type-life { - color: var(--type-life); - background-color: rgba(245, 158, 11, 0.1); - } - - .type-quote { - color: var(--type-quote); - background-color: rgba(0, 255, 136, 0.1); - } - - .type-link { - color: var(--type-link); - background-color: rgba(56, 189, 248, 0.1); - } - - .type-photo { - color: var(--type-photo); - background-color: rgba(236, 72, 153, 0.1); - } - - /* Card component */ - .card { - @apply border border-border rounded-lg overflow-hidden transition-all duration-200; - box-shadow: 0 0 20px var(--accent-glow); - } - - .card:hover { - transform: translateY(-2px); - box-shadow: 0 0 30px var(--accent-glow); - } - - .card-image { - @apply aspect-video object-cover w-full; - } - - .card-body { - @apply p-5 md:p-6 space-y-3; - } - - .card-title { - @apply text-xl font-semibold; - } - - .card-excerpt { - @apply text-text-dim text-sm line-clamp-3; - } - - .card-footer { - @apply flex items-center justify-between gap-4; - } - - /* ===================== - Timeline Layout - ===================== */ - - .timeline { - @apply relative mx-auto max-w-5xl px-4 py-12; - } - - /* Vertical spine */ - .timeline::before { - content: ''; - @apply absolute top-0 bottom-0; - /* Mobile: fixed 20px from container left edge */ - left: 20px; - width: 2px; - background: linear-gradient(to bottom, var(--accent), var(--accent2, var(--accent))); - opacity: 0.7; - } - - @screen md { - .timeline::before { - left: 50%; - transform: translateX(-50%); - } - } - - /* Each timeline row — block, full width, positioned context for abs children */ - .timeline-item { - @apply relative mb-10; - /* - Mobile geometry (.timeline has px-4 = 16px padding): - spine left = 20px from <ol> border → 20-16 = 4px from item's containing block. - We want card to start ~8px right of spine right edge (22px from <ol> = 6px from block). - Use margin-left: 30px so card starts at 16+30=46px from <ol>, 24px right of spine right. - abs children: spine left relative to item = 4 - 30 = -26px. - */ - margin-left: 30px; - } - - @screen md { - .timeline-item { - margin-left: 0; - } - } - - /* ---- Connector line ---- */ - .timeline-connector { - @apply absolute; - top: 20px; - height: 2px; - /* - Mobile: .timeline px-4(16px) + item margin-left(30px) = 46px from <ol> border. - Spine right edge = 22px from <ol> border = 22-46 = -24px from item left. - Connector: left=-24px, width=24px → touches spine right and card left edge. - */ - left: -24px; - width: 24px; - } - - @screen md { - /* - spine center = 50% of item. Spine is 2px: left edge at 50%-1px, right at 50%+1px. - Cards occupy [0 .. 50%-24px] (left) or [50%+24px .. 100%] (right). - Left connector: left=50%-24px, width=23px → touches card right edge and spine left. - Right connector: left=50%+1px, width=23px → touches spine right and card left. - */ - .timeline-item--left .timeline-connector { - left: calc(50% - 24px); - width: 23px; - } - .timeline-item--right .timeline-connector { - left: calc(50% + 1px); - width: 23px; - } - } - - /* ---- Node on spine ---- */ - .timeline-node { - @apply absolute rounded-full z-10; - top: 14px; - /* - Mobile: spine center = 21px from <ol> border = 21-46 = -25px from item left. - Node (10px wide): left = -25 - 5 = -30px. - */ - left: -30px; - width: 10px; - height: 10px; - border: 2px solid var(--bg); - } - - @screen md { - .timeline-node { - width: 12px; - height: 12px; - top: 14px; - /* Desktop: spine center = 50% of item. Node center on spine: left = 50% - 6px */ - left: calc(50% - 6px); - } - } - - /* ---- Card wrapper ---- */ - .timeline-card { - @apply flex border rounded-lg overflow-hidden bg-surface; - /* Mobile: column (thumb on top) */ - flex-direction: column; - width: 100%; - transition: box-shadow 0.2s, transform 0.2s; - } - - .timeline-card:hover { - transform: translateY(-2px); - } - - @screen md { - /* Desktop: push card into left or right half via item padding */ - .timeline-item--left { - padding-right: calc(50% + 24px); - } - .timeline-item--right { - padding-left: calc(50% + 24px); - } - /* Left card: thumb outer-left, body inner-right */ - .timeline-item--left .timeline-card { - flex-direction: row; - } - /* Right card: body inner-left, thumb outer-right */ - .timeline-item--right .timeline-card { - flex-direction: row-reverse; - } - } - - /* ---- Thumbnail panel ---- */ - .timeline-thumb { - @apply flex-shrink-0 overflow-hidden; - /* Mobile: full-width banner */ - width: 100%; - height: 90px; - } - - @screen md { - .timeline-thumb { - /* 3:2 landscape: wider than tall */ - width: 40%; - height: auto; - aspect-ratio: 3 / 2; - } - } - - .timeline-thumb img { - @apply w-full h-full object-cover; - transition: transform 0.2s; - } - - .timeline-card:hover .timeline-thumb img { - transform: scale(1.03); - } - - /* ---- Text panel ---- */ - .timeline-body { - @apply flex flex-col gap-2 p-4 flex-1; - } - - /* ---- Meta row (TYPE · date) ---- */ - .timeline-meta { - @apply flex items-center gap-2 text-xs font-mono tracking-widest uppercase; - } - - .timeline-meta-sep { - @apply text-border; - } - - .timeline-date { - @apply text-text-dim normal-case tracking-normal; - } - - /* ---- Title ---- */ - .timeline-title { - @apply font-semibold text-base leading-snug; - } - - .timeline-title a { - @apply hover:text-accent transition-colors; - } - - /* ---- Excerpt ---- */ - .timeline-excerpt { - @apply text-text-dim text-sm line-clamp-3 leading-relaxed; - } - - /* ---- Pinned badge ---- */ - .timeline-pinned { - @apply inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-semibold; - } - - /* ---- Type-color variants (node, connector, card) ---- */ - - /* Tech (purple) */ - .timeline-node--tech { - background-color: var(--type-tech); - box-shadow: 0 0 12px color-mix(in srgb, var(--type-tech) 40%, transparent); - } - .timeline-connector--tech { - background-color: var(--type-tech); - } - .timeline-card--tech { - border-color: color-mix(in srgb, var(--type-tech) 25%, transparent); - box-shadow: 0 0 18px color-mix(in srgb, var(--type-tech) 10%, transparent); - } - - /* Life (amber) */ - .timeline-node--life { - background-color: var(--type-life); - box-shadow: 0 0 12px color-mix(in srgb, var(--type-life) 40%, transparent); - } - .timeline-connector--life { - background-color: var(--type-life); - } - .timeline-card--life { - border-color: color-mix(in srgb, var(--type-life) 25%, transparent); - box-shadow: 0 0 18px color-mix(in srgb, var(--type-life) 10%, transparent); - } - - /* Quote (green) */ - .timeline-node--quote { - background-color: var(--type-quote); - box-shadow: 0 0 12px color-mix(in srgb, var(--type-quote) 40%, transparent); - } - .timeline-connector--quote { - background-color: var(--type-quote); - } - .timeline-card--quote { - border-color: color-mix(in srgb, var(--type-quote) 25%, transparent); - box-shadow: 0 0 18px color-mix(in srgb, var(--type-quote) 10%, transparent); - } - - /* Link (cyan) */ - .timeline-node--link { - background-color: var(--type-link); - box-shadow: 0 0 12px color-mix(in srgb, var(--type-link) 40%, transparent); - } - .timeline-connector--link { - background-color: var(--type-link); - } - .timeline-card--link { - border-color: color-mix(in srgb, var(--type-link) 25%, transparent); - box-shadow: 0 0 18px color-mix(in srgb, var(--type-link) 10%, transparent); - } - - /* Photo (pink) */ - .timeline-node--photo { - background-color: var(--type-photo); - box-shadow: 0 0 12px color-mix(in srgb, var(--type-photo) 40%, transparent); - } - .timeline-connector--photo { - background-color: var(--type-photo); - } - .timeline-card--photo { - border-color: color-mix(in srgb, var(--type-photo) 25%, transparent); - box-shadow: 0 0 18px color-mix(in srgb, var(--type-photo) 10%, transparent); - } - - /* ---- Timeline lazy-reveal (scroll-triggered) ---- */ - .js-lazy-timeline > .timeline-item { - opacity: 0; - transform: translateX(-18px); - transition: opacity 320ms ease-out, transform 320ms ease-out; - } - - @screen md { - .js-lazy-timeline > .timeline-item--right { - transform: translateX(18px); - } - } - - .js-lazy-timeline > .timeline-item.is-visible { - opacity: 1; - transform: translateX(0); - } - - /* Header navigation styling */ - .header { - @apply fixed top-0 left-0 right-0 z-40; - } - - .header-nav { - @apply hidden md:flex items-center gap-6; - } - - .nav-link { - @apply text-text hover:text-accent transition-colors; - } - - .header-actions { - @apply flex items-center gap-4; - } - - /* Mobile menu overlay */ - .menu-overlay { - @apply fixed inset-0 bg-bg z-40 opacity-0 invisible transition-all duration-300; - } - - .menu-overlay.active { - @apply opacity-100 visible; - } - - .menu-nav { - @apply flex flex-col gap-4 p-6 text-lg font-semibold; - } - - .menu-nav a { - @apply text-text hover:text-accent transition-colors; - } - - /* Breadcrumb navigation */ - .breadcrumb { - @apply flex items-center gap-2 text-sm text-text-dim; - } - - .breadcrumb a { - @apply hover:text-accent transition-colors; - } - - .breadcrumb-separator { - @apply opacity-50; - } - - /* Article metadata styling (with icons) */ - .article-meta { - @apply flex flex-wrap items-center gap-4 text-sm text-text-dim; - } - - .article-meta-item { - @apply flex items-center gap-2; - } - - .article-meta-item i { - @apply w-4 h-4 flex-shrink-0; - color: var(--accent2); - } - - /* Hero typography with fluid sizing */ - .hero-title { - font-size: clamp(2rem, 5vw + 1rem, 4.5rem); - } - - .section-title { - font-size: clamp(1.5rem, 3vw + 0.5rem, 2.5rem); - } - - /* ---- Article prev/next navigation ---- */ - .article-nav { - @apply border-t border-border pt-6; - } - - .article-nav-prompt { - @apply font-mono text-sm mb-2; - color: var(--accent); - } - - .article-nav-links { - @apply flex flex-col md:flex-row md:justify-between md:items-center gap-4 md:gap-0 font-mono text-sm; - } - - .article-nav-link { - @apply hover:text-accent transition-colors text-text; - } - - .article-nav-placeholder { - @apply text-text-dim opacity-40; - } - - /* ---- Footer badge variants ---- */ - .badge-footer-accent { - @apply inline-flex items-center px-2.5 py-1 rounded text-xs font-mono font-semibold whitespace-nowrap; - border: 1px solid rgba(168, 85, 247, 0.35); - background: rgba(168, 85, 247, 0.1); - color: var(--accent); - } - - .badge-footer-accent2 { - @apply inline-flex items-center px-2.5 py-1 rounded text-xs font-mono font-semibold whitespace-nowrap; - border: 1px solid rgba(0, 255, 136, 0.35); - background: rgba(0, 255, 136, 0.1); - color: var(--accent2); - } - - /* Back to top button */ - .back-to-top { - @apply fixed bottom-6 right-6 z-40 w-11 h-11 rounded-full flex items-center justify-center; - background: var(--accent); - box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.4); - transition: background 200ms ease, box-shadow 200ms ease; - color: #fff; - } - .back-to-top:hover { - background: var(--accent); - filter: brightness(0.85); - box-shadow: 0 0 20px var(--accent); - } - .back-to-top:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -/* Prose overrides for light theme */ -html.theme-light .prose, -html.theme-light .prose-invert { - color: var(--text); -} - -html.theme-light .prose a, -html.theme-light .prose-invert a { - color: var(--accent); -} - -html.theme-light .prose strong, -html.theme-light .prose-invert strong { - color: var(--text); -} - -html.theme-light .prose code, -html.theme-light .prose-invert code { - color: var(--accent2); -} - -html.theme-light .prose pre, -html.theme-light .prose-invert pre { - background-color: var(--surface); - color: var(--text); -} - -html.theme-light .prose h1, -html.theme-light .prose h2, -html.theme-light .prose h3, -html.theme-light .prose h4, -html.theme-light .prose h5, -html.theme-light .prose h6, -html.theme-light .prose-invert h1, -html.theme-light .prose-invert h2, -html.theme-light .prose-invert h3, -html.theme-light .prose-invert h4, -html.theme-light .prose-invert h5, -html.theme-light .prose-invert h6 { - color: var(--text); -} - -html.theme-light .prose blockquote, -html.theme-light .prose-invert blockquote { - color: var(--text); - border-left-color: var(--accent); -} - -/* Responsive container utilities - mobile-first */ -.container { - @apply max-w-full px-4; -} - -@media (min-width: 768px) { - .container { - @apply max-w-4xl px-6; - } -} - -@media (min-width: 1060px) { - .container { - @apply max-w-5xl px-8; - } -} - -/* Alpine.js x-cloak - hide content until Alpine initializes */ -[x-cloak] { - display: none !important; -} - -/* Respect user's motion preferences */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } -} - -/* Matrix rain canvas background */ -#matrix-rain { - position: fixed; - inset: 0; - width: 100%; - height: 100%; - pointer-events: none; - z-index: 1; -} - -/* Dark theme: 13% opacity (inner pages) */ -html.theme-dark #matrix-rain { - opacity: 0.13; -} - -/* Light theme: 18% opacity (inner pages) */ -html.theme-light #matrix-rain { - opacity: 0.18; -} - -/* Homepage: more prominent background */ -html.theme-dark body[data-page-kind="home"] #matrix-rain { - opacity: 0.28; -} - -html.theme-light body[data-page-kind="home"] #matrix-rain { - opacity: 0.35; -} - -/* Reduced motion: hide canvas entirely */ -@media (prefers-reduced-motion: reduce) { - #matrix-rain { - display: none; - } -} - -/* Content grid background — blocks rain under text, visible in gutters (single pages only) */ -.content-grid { - position: relative; - z-index: 10; - background-color: var(--bg); - padding: 2px; - border: 1px solid var(--border); - box-shadow: 0 0 20px var(--accent-glow); -} - -@media (min-width: 768px) { - .content-grid { - padding: 2rem; - } -} - -/* Article list items — soft glow effect */ -article.border.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { - border-color: var(--border); - box-shadow: 0 0 20px var(--accent-glow); -} - -/* ============================================ - FORM COMPONENTS (Week 4) - ============================================ */ - -/* Form input base styles */ -.form-input, -.form-textarea, -.form-select { - @apply w-full px-4 py-2 rounded border border-border bg-bg2 text-text font-body transition-all duration-200; -} - -/* Input placeholder styling */ -.form-input::placeholder, -.form-textarea::placeholder { - color: var(--text-dim); - opacity: 0.7; -} - -/* Input focus state */ -.form-input:focus, -.form-textarea:focus, -.form-select:focus { - @apply outline-none border-accent ring-2 ring-accent ring-offset-2; - ring-offset-color: var(--bg); - border-color: var(--accent); -} - -/* Input invalid/error state */ -.form-input:invalid, -.form-textarea:invalid, -.form-select:invalid, -.form-input.error, -.form-textarea.error, -.form-select.error { - @apply border-red-500 ring-red-500; -} - -.form-input:invalid:focus, -.form-textarea:invalid:focus, -.form-select:invalid:focus { - @apply ring-red-500 border-red-500; - ring-offset-color: var(--bg); -} - -/* Input disabled state */ -.form-input:disabled, -.form-textarea:disabled, -.form-select:disabled { - @apply opacity-50 cursor-not-allowed bg-muted; -} - -/* Textarea specific */ -.form-textarea { - @apply min-h-32; - resize: vertical; -} - -.form-textarea.auto-expand { - resize: none; - overflow-y: hidden; -} - -/* Select dropdown */ -.form-select { - cursor: pointer; - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23a855f7' d='M6 9L1 4h10z'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: right 0.75rem center; - padding-right: 2.5rem; -} - -html.theme-light .form-select { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239333ea' d='M6 9L1 4h10z'/%3E%3C/svg%3E"); -} - -/* Checkbox and radio button base */ -.form-checkbox, -.form-radio { - @apply w-5 h-5 cursor-pointer accent-accent transition-all duration-200; - appearance: none; - border: 2px solid var(--border); - border-radius: 0.375rem; - flex-shrink: 0; -} - -.form-radio { - border-radius: 50%; -} - -/* Checkbox/radio focus state */ -.form-checkbox:focus-visible, -.form-radio:focus-visible { - @apply outline-none ring-2 ring-accent ring-offset-2; - ring-offset-color: var(--bg); -} - -/* Checkbox/radio checked state */ -.form-checkbox:checked, -.form-radio:checked { - background-color: var(--accent); - border-color: var(--accent); - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center; - background-size: 100%; -} - -.form-radio:checked { - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3.5'/%3E%3C/svg%3E"); -} - -/* Checkbox/radio disabled state */ -.form-checkbox:disabled, -.form-radio:disabled { - @apply opacity-50 cursor-not-allowed; - border-color: var(--muted); -} - -/* Form group layout */ -.form-group { - @apply space-y-2; -} - -.form-group label { - @apply block text-sm font-semibold text-text; -} - -.form-group.required label::after { - content: ' *'; - color: #ef4444; -} - -.form-group-input { - @apply relative; -} - -.form-group-help { - @apply text-xs text-text-dim; -} - -.form-group.error .form-group-help { - @apply text-red-500; -} - -.form-error { - @apply text-sm text-red-500 mt-1; -} - -/* Form layout utilities */ -.form-row { - @apply flex flex-col md:flex-row gap-4; -} - -.form-row > .form-group { - @apply flex-1; -} - -.form-inline { - @apply flex flex-col sm:flex-row items-end gap-4; -} - -.form-inline .form-group { - @apply flex-1; -} - -.form-inline .btn { - @apply h-10; -} - -/* Character count indicator */ -.form-char-count { - @apply text-xs text-text-dim text-right; -} - -.form-char-count.warning { - @apply text-amber-500; -} - -.form-char-count.error { - @apply text-red-500; -} - -/* ============================================ - FOCUS MANAGEMENT (Week 5) - ============================================ */ - -/* Enhanced :focus-visible with accent color styling */ -:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -/* Respect motion preferences for focus indicator */ -@media (prefers-reduced-motion: reduce) { - :focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -/* Button and link hover/focus transitions */ -button, -a.btn, -.btn { - transition: all 150ms ease-out; -} - -button:hover, -a.btn:hover, -.btn:hover { - opacity: 0.8; - transform: translateY(-1px); -} - -button:active, -a.btn:active, -.btn:active { - transform: translateY(0); -} - -/* Form input focus transitions with glow effect */ -input, -textarea, -select { - transition: all 200ms ease-out; -} - -input:focus, -textarea:focus, -select:focus, -input:focus-visible, -textarea:focus-visible, -select:focus-visible { - box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.1); -} - -/* ============================================ - MODAL COMPONENTS (Week 4) - ============================================ */ - -/* Modal backdrop */ -.modal-backdrop { - @apply fixed inset-0 bg-black/50 opacity-0 invisible transition-all duration-300 z-40; - backdrop-filter: blur(2px); -} - -.modal-backdrop.active { - @apply opacity-100 visible; -} - -/* Modal container */ -.modal { - @apply fixed inset-0 flex items-center justify-center opacity-0 invisible transition-all duration-300 z-50 p-4; - pointer-events: none; -} - -.modal.active { - @apply opacity-100 visible; - pointer-events: auto; -} - -.modal.active .modal-backdrop { - @apply opacity-100 visible; - pointer-events: auto; -} - -/* Modal content box */ -.modal-content { - @apply bg-bg2 border border-border rounded-lg shadow-2xl max-w-lg w-full max-h-[90vh] flex flex-col; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); - animation: modalSlideUp 0.3s ease-out; -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slideUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes modalSlideUp { - from { - opacity: 0; - transform: translateY(30px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Modal header */ -.modal-header { - @apply flex items-start justify-between gap-4 p-6 border-b border-border; -} - -.modal-title { - @apply text-xl font-bold text-text; -} - -.modal-close { - @apply flex items-center justify-center w-8 h-8 rounded hover:bg-surface cursor-pointer transition-colors; -} - -.modal-close::before, -.modal-close::after { - content: ''; - @apply absolute w-5 h-0.5 bg-text-dim; -} - -.modal-close::before { - transform: rotate(45deg); -} - -.modal-close::after { - transform: rotate(-45deg); -} - -.modal-close:hover::before, -.modal-close:hover::after { - @apply bg-accent; -} - -/* Modal body */ -.modal-body { - @apply flex-1 overflow-y-auto p-6 space-y-4; -} - -/* Modal footer */ -.modal-footer { - @apply flex items-center justify-end gap-3 p-6 border-t border-border; -} - -/* Modal sizes */ -.modal-content.modal-sm { - @apply max-w-sm; -} - -.modal-content.modal-md { - @apply max-w-md; -} - -.modal-content.modal-lg { - @apply max-w-2xl; -} - -/* Modal variants */ -.modal-content.modal-alert { - @apply max-w-sm; -} - -.modal-content.modal-confirm { - @apply max-w-sm; -} - -/* Modal button styling */ -.modal-footer .btn { - @apply min-w-[100px]; -} - -/* ============================================ - INTERACTIVE PATTERNS (Week 4) - ============================================ */ - -/* Loading spinner */ -.spinner { - @apply inline-block; - width: 1rem; - height: 1rem; - border: 2px solid var(--border); - border-top-color: var(--accent); - border-radius: 50%; - animation: spin 0.6s linear infinite; -} - -@keyframes spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -.spinner-sm { - width: 0.75rem; - height: 0.75rem; - border-width: 1.5px; -} - -.spinner-lg { - width: 1.5rem; - height: 1.5rem; - border-width: 3px; -} - -/* Button with spinner */ -.btn:disabled .spinner { - @apply inline-block mr-2; -} - -/* Toast notification container */ -.toast-container { - @apply fixed bottom-0 right-0 p-4 space-y-3 max-w-sm z-50; -} - -@media (max-width: 640px) { - .toast-container { - @apply left-0 right-0 px-4; - } -} - -/* Toast base */ -.toast { - @apply flex items-start gap-3 p-4 rounded-lg border border-border shadow-lg; - animation: slideInUp 0.3s ease-out; - background-color: var(--bg2); - color: var(--text); -} - -@keyframes slideInUp { - from { - transform: translateY(100%); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -/* Animation Utility Classes */ - -.animate-fade-in { - animation: fadeIn 300ms ease-out; -} - -.animate-slide-up { - animation: slideUp 300ms ease-out; -} - -.animate-spin-loader { - animation: spin 600ms linear infinite; -} - -/* Toast variants */ -.toast-success { - border-color: #10b981; - background-color: rgba(16, 185, 129, 0.1); -} - -.toast-success::before { - content: '✓'; - color: #10b981; - font-weight: bold; - flex-shrink: 0; -} - -.toast-error { - border-color: #ef4444; - background-color: rgba(239, 68, 68, 0.1); -} - -.toast-error::before { - content: '✕'; - color: #ef4444; - font-weight: bold; - flex-shrink: 0; -} - -.toast-info { - border-color: #3b82f6; - background-color: rgba(59, 130, 246, 0.1); -} - -.toast-info::before { - content: 'ℹ'; - color: #3b82f6; - flex-shrink: 0; -} - -.toast-warning { - border-color: #f59e0b; - background-color: rgba(245, 158, 11, 0.1); -} - -.toast-warning::before { - content: '⚠'; - color: #f59e0b; - flex-shrink: 0; -} - -.toast-close { - @apply ml-auto flex-shrink-0 w-6 h-6 flex items-center justify-center cursor-pointer hover:bg-surface rounded transition-colors; -} - -/* Tooltip */ -.tooltip { - @apply relative inline-block; -} - -.tooltip-text { - @apply absolute bg-bg2 text-text-dim text-xs rounded px-2 py-1 whitespace-nowrap pointer-events-none opacity-0 invisible transition-all duration-200; - z-index: 50; - bottom: 125%; - left: 50%; - transform: translateX(-50%); -} - -.tooltip:hover .tooltip-text { - @apply opacity-100 visible; -} - -.tooltip-text::after { - content: ''; - @apply absolute w-2 h-2 bg-bg2; - bottom: -4px; - left: 50%; - transform: translateX(-50%) rotate(45deg); -} - -/* Tooltip directions */ -.tooltip-bottom .tooltip-text { - @apply top-[125%] bottom-auto; -} - -.tooltip-bottom .tooltip-text::after { - @apply top-[-4px] bottom-auto; - transform: translateX(-50%) rotate(225deg); -} - -.tooltip-left .tooltip-text { - @apply left-auto right-[125%]; - transform: none; -} - -.tooltip-left .tooltip-text::after { - @apply left-auto right-[-4px]; - transform: rotate(135deg); -} - -.tooltip-right .tooltip-text { - @apply left-[125%]; - transform: none; -} - -.tooltip-right .tooltip-text::after { - @apply left-[-4px] right-auto; - transform: rotate(315deg); -} - -/* Motion Safety - Respect prefers-reduced-motion */ - -@media (prefers-reduced-motion: reduce) { - /* Remove all animations */ - *, - *::before, - *::after { - animation: none !important; - transition: none !important; - } - - /* Ensure focus-visible is still visible */ - :focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} |
