/* =========================================================================
   LazyBlog — base
   Theme tokens, reset, typography, layout (header/main/footer), smooth scroll.
   ========================================================================= */

/* ---------- Theme tokens ---------- */
:root, [data-theme="amber"] {
    --bg: #100a04;
    --panel: #1a1208;
    --primary: #ffb700;
    --primary-dim: #7a5800;
    --primary-glow: rgba(255, 183, 0, 0.15);
    --primary-glow-strong: rgba(255, 183, 0, 0.30);
    /* Accent stays in the amber family — lifted/lighter sibling so it
       reads as warm phosphor wash, not a contrasting acid-green flash. */
    --accent: #ffd065;
    --accent-dim: #7a5c20;
    --text: #efe0c0;
    --text-dim: #7a6a55;
    --border: #3a2a1e;
    --scan: rgba(255, 183, 0, 0.03);
}

[data-theme="green"] {
    --bg: #0a0e0a;
    --panel: #0f1a0f;
    --primary: #39ff14;
    --primary-dim: #1a7a08;
    --primary-glow: rgba(57, 255, 20, 0.15);
    --primary-glow-strong: rgba(57, 255, 20, 0.30);
    /* Accent stays in the green family — mint-tinted lifted sibling
       instead of an amber contrast. */
    --accent: #8aff70;
    --accent-dim: #3a7a28;
    --text: #d8efd0;
    --text-dim: #5a7a55;
    --border: #1e3a1e;
    --scan: rgba(57, 255, 20, 0.03);
}

[data-theme="crypt"] {
    --bg: #0a0303;
    --panel: #1a0808;
    --primary: #ff2418;
    --primary-dim: #7a1008;
    --primary-glow: rgba(255, 36, 24, 0.15);
    --primary-glow-strong: rgba(255, 36, 24, 0.30);
    /* Accent stays in the red family — soft coral so it reads as a
       lifted/desaturated sibling of the blood-red primary instead of
       an orange/amber contrast. */
    --accent: #ff8a7a;
    --accent-dim: #7a3028;
    /* Pink-tinted text avoids the halation that pure white triggers against
       a blood-red primary; stays in the warm family so hierarchy reads. */
    --text: #efc8c0;
    --text-dim: #7a5a55;
    --border: #3a1e1e;
    --scan: rgba(255, 36, 24, 0.03);
}

[data-theme="brutalist"] {
    /* Cool-tinted near-black + bluish whites — not pure #000/#fff, which
       would read as flat OLED test pattern. The slight blue undertone
       matches the "intentional brutalist site" look (GitHub dark, Linear,
       Are.na). */
    --bg: #08090c;
    --panel: #0e1117;
    --primary: #e6edf3;
    --primary-dim: #6e7681;
    --primary-glow: rgba(230, 237, 243, 0.05);
    --primary-glow-strong: rgba(230, 237, 243, 0.10);
    --accent: #e6edf3;
    --accent-dim: #484f58;
    --text: #c9d1d9;
    --text-dim: #8b949e;
    --border: #21262d;
    /* Transparent --scan kills the repeating-gradient scanlines without
       needing to disable body::before — keeps the cascade simple. */
    --scan: transparent;
}

[data-theme="p7"] {
    /* P7 phosphor — blue-violet emission used on Cold War radar A-scopes
       and navigation displays. Pairs the operational/tradecraft mood from
       reference covert-ops infographics with the same phosphor-color
       naming axis as amber (P3) and green (P1). Bg leans cool navy so the
       primary violet reads as a sharp signal, not a flat fill.
       Text-shadow is fully stripped on this theme (see the rule below
       the per-theme heading overrides), so --primary-glow tokens here
       drive dropdown-panel box-shadow only — kept low-alpha for a
       barely-there violet aura that fits the flat clinical look. */
    --bg: #08081a;
    --panel: #15102a;
    --primary: #a060ff;
    --primary-dim: #5a3a7a;
    --primary-glow: rgba(160, 96, 255, 0.10);
    --primary-glow-strong: rgba(160, 96, 255, 0.20);
    /* Accent is a paler lavender — reads as a lifted/desaturated sibling
       of the violet primary instead of a contrasting hue, so hierarchy
       stays inside one color family. */
    --accent: #d4a8ff;
    --accent-dim: #7a5e9a;
    /* Cool off-white with a violet undertone — pure white halates against
       saturated violet and reads as glare. */
    --text: #e6daf5;
    --text-dim: #8a7fa5;
    --border: #2a1f4a;
    --scan: rgba(160, 96, 255, 0.03);
}

[data-theme="p11"] {
    /* P11 phosphor — pure blue emission (peak ~460nm), historically used
       on oscilloscope CRTs for photographic recording and early B&W TV.
       Sits next to p7 on the phosphor naming axis but cooler and more
       saturated — reference is the "medical-ops / clinical telemetry"
       infographic look (electric cyan-blue on near-black). */
    --bg: #040810;
    --panel: #0e1722;
    --primary: #1ac8ff;
    --primary-dim: #0a5478;
    --primary-glow: rgba(26, 200, 255, 0.15);
    --primary-glow-strong: rgba(26, 200, 255, 0.30);
    /* Paler cyan sibling for accent — keeps hierarchy in one cool-blue
       family so callouts/series tags don't introduce a warm contrast. */
    --accent: #7ddcff;
    --accent-dim: #5a829a;
    /* Cool off-white with a blue undertone — pure white halates against
       saturated cyan. */
    --text: #d4e6f5;
    --text-dim: #7f95ad;
    --border: #1a3050;
    --scan: rgba(26, 200, 255, 0.03);
}

/* ---------- Reset ---------- */
* { box-sizing: border-box; margin: 0; padding: 0; }

::selection { background: var(--primary); color: var(--bg); text-shadow: none; }
::-moz-selection { background: var(--primary); color: var(--bg); text-shadow: none; }

/* ---------- Mobile-first base ---------- */
html, body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Play', system-ui, sans-serif;
    font-size: 16px;
    line-height: 1.7;
    min-height: 100vh;
    /* `clip` (not `hidden`) so descendants can still use position: sticky.
       `hidden` implicitly sets overflow-y: auto on the html/body element,
       which creates a scroll container that breaks all inner sticky elements
       (e.g. the editor toolbar in admin). `clip` blocks overflow without
       establishing a scroll context. */
    overflow-x: clip;
    -webkit-text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
}

@media (min-width: 768px) {
    html, body { font-size: 17px; line-height: 1.75; }
}
@media (min-width: 1200px) {
    html, body { font-size: 18px; line-height: 1.8; }
}

/* ---------- Typography ----------
   Headings get a phosphor-glow stack PLUS a subtle chromatic-aberration
   RGB split (red shifted -1px, cyan shifted +1px). The split mimics a
   misaligned CRT shadow mask and reads as "glitchy retro" without being
   nausea-inducing — kept low alpha so it stays a flavor, not noise.
   On amber + green (the phosphor themes that actually keep this split)
   the fringe stacks against bright primary text, so alphas are tuned
   low enough that big headings stay legible at h1/h2 sizes. */
h1, h2, h3, .story-title, .post-title, .site-brand {
    font-family: 'VT323', monospace;
    color: var(--primary);
    text-shadow:
        -1px 0 0 rgba(255, 0, 80, 0.28),
        1px 0 0 rgba(0, 220, 255, 0.22),
        0 0 6px var(--primary),
        0 0 22px var(--primary-glow-strong),
        0 0 56px var(--primary-glow);
    letter-spacing: 3px;
    line-height: 1.1;
    /* Long unbreakable tokens (snake_case identifiers, URLs, hashes)
       must wrap mid-string on narrow viewports — without this the title
       overflows the column and the tail gets clipped off-screen on
       mobile. Scoped to every heading so post-page-title (h1) on
       /posts/{slug} and section headings inside post bodies both honor
       it, not just the home list. */
    overflow-wrap: anywhere;
    word-break: break-word;
}
/* Reduced motion users get clean text — no chromatic split, just the glow. */
@media (prefers-reduced-motion: reduce) {
    h1, h2, h3, .story-title, .post-title, .site-brand {
        text-shadow:
            0 0 6px var(--primary),
            0 0 22px var(--primary-glow-strong),
            0 0 56px var(--primary-glow);
    }
}
/* Mobile: drop the chromatic RGB split AND collapse the phosphor halo
   to a single tight bloom. The desktop 6+22+56px stack was tuned for
   the larger title scale and a relaxed viewing distance; on a phone the
   22+56 outer halos overlap with neighbouring letters and burn the
   whole word. A tight 3px + soft 10px stack reads as "the type has a
   slight CRT bloom" instead of "the type is on fire". */
@media (max-width: 600px) {
    h1, h2, h3, .story-title, .post-title, .site-brand {
        text-shadow:
            0 0 3px var(--primary),
            0 0 10px var(--primary-glow-strong);
    }
}

/* Crypt + Brutalist heading overrides — drop the chromatic RGB split
   while keeping the phosphor halo. Crypt's primary is already red so
   the red shift stacks into a jagged outline; brutalist's flat palette
   clashes with colored fringes. Scope is limited to hero-scale headings
   (h1/h2/h3 + site-brand) on purpose. `.post-title` and `.story-title`
   are list-item titles whose at-rest shadow is tuned softer in post.css
   / components.css; pulling them into this override re-imposes the
   22/56px halo via attribute+class specificity and they read as
   always-hovered.
   Wrapped in min-width:601px so the universal mobile heading rule
   below (smaller blur stack) takes over on phones — otherwise these
   higher-specificity overrides win on mobile and the title burns. */
@media (min-width: 601px) {
    [data-theme="crypt"] h1,
    [data-theme="crypt"] h2,
    [data-theme="crypt"] h3,
    [data-theme="crypt"] .site-brand,
    [data-theme="brutalist"] h1,
    [data-theme="brutalist"] h2,
    [data-theme="brutalist"] h3,
    [data-theme="brutalist"] .site-brand {
        text-shadow:
            0 0 6px var(--primary),
            0 0 22px var(--primary-glow-strong),
            0 0 56px var(--primary-glow);
    }
}

/* P7 + P11 themes: flat tradecraft / clinical-telemetry look —
   saturated colored text on near-black bg, no phosphor bloom. Reference
   infographics (covert ops + medical ops) use crisp colored type without
   halation; phosphor glow at the saturation level of violet (p7) and
   electric blue (p11) burns the whole page instead of reading as a
   subtle CRT cue. Strip text-shadow site-wide. Box-shadow and filter
   stay so card edges + vignette + flicker still play. */
[data-theme="p7"] *,
[data-theme="p7"] *::before,
[data-theme="p7"] *::after,
[data-theme="p11"] *,
[data-theme="p11"] *::before,
[data-theme="p11"] *::after {
    text-shadow: none !important;
}

h1, .site-brand { font-size: clamp(38px, 9vw, 68px); }
/* `<p class="site-brand">` is normal-weight by default; h1 is browser-bold.
   The weight mismatch makes the brand on non-home pages render thinner,
   so the phosphor text-shadow reads visibly dimmer than the same title
   on home. Pin to bold so every page shows the brand at identical glow. */
.site-brand { margin: 0; font-weight: bold; }
h1 .brand-link, .site-brand .brand-link { color: inherit; text-decoration: none; }
h1 .brand-link:hover,
.site-brand .brand-link:hover { text-shadow: 0 0 16px var(--primary), 0 0 48px var(--primary-glow-strong); }

h2 { font-size: clamp(28px, 5vw, 36px); margin: 28px 0 16px; }
h3 { font-size: clamp(22px, 4vw, 26px); margin: 24px 0 12px; }
h3 { color: var(--accent); text-shadow: 0 0 8px var(--accent-dim); }

/* All underlines are dashed across the site (1px thin dashes) to soften the
   look vs. the default solid bar — fits the CRT terminal aesthetic. */
a {
    color: var(--primary);
    text-decoration: underline;
    text-decoration-style: dashed;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
a:hover { text-shadow: 0 0 8px var(--primary-glow-strong); }

p { margin: 12px 0; }
ul, ol { margin: 12px 0 12px 24px; }
li { margin: 6px 0; }

/* Horizontal rule — themed thin line with soft phosphor glow. */
hr {
    border: 0;
    height: 1px;
    background: var(--primary-dim);
    box-shadow: 0 0 6px var(--primary-glow);
    margin: 28px 0;
}

code, pre {
    font-family: 'Share Tech Mono', monospace;
    background: var(--panel);
    border: 1px solid var(--border);
    padding: 1px 6px;
    border-radius: 2px;
}
pre { padding: 12px 14px; overflow-x: auto; margin: 12px 0; }
pre code { border: none; padding: 0; background: transparent; }

strong { color: var(--primary); }
em { color: var(--accent); font-style: italic; }

blockquote {
    border-left: 3px solid var(--primary-dim);
    padding: 8px 16px;
    margin: 16px 0;
    color: var(--text-dim);
    background: var(--panel);
}

/* ---------- Header (centered) ---------- */
header {
    border-bottom: 1px solid var(--border);
    padding: 28px 20px 24px;
    text-align: center;
}
@media (min-width: 768px) {
    header { padding: 40px 40px 28px; }
}

.callsign {
    font-family: 'Share Tech Mono', monospace;
    color: var(--primary-dim);
    letter-spacing: 3px;
    text-transform: uppercase;
    font-size: 11px;
    margin-bottom: 6px;
}

.subtitle {
    font-family: 'Share Tech Mono', monospace;
    color: var(--text-dim);
    font-size: 12px;
    margin-top: 12px;
    letter-spacing: 1px;
}

.header-actions {
    margin-top: 18px;
    display: inline-flex;
    gap: 10px;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
}
.header-btn {
    /* inline-flex + center alignment normalises content positioning so
       <a>.header-btn (text node child) and <button>.header-btn (span
       child) render at identical metrics. Pure inline-block left a 1-2px
       baseline drift on the picker toggle. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Reset UA button widget metrics (Chrome adds implicit padding to
       native <button> via `appearance: auto`). */
    appearance: none;
    -webkit-appearance: none;
    font-family: 'Share Tech Mono', monospace;
    font-size: 11px;
    line-height: 1.4;
    background: transparent;
    border: 1px solid var(--accent-dim);
    color: var(--accent);
    padding: 6px 14px;
    letter-spacing: 2px;
    cursor: pointer;
    border-radius: 2px;
    text-decoration: none;
    transition: background 0.18s ease, border-color 0.18s ease;
}
.header-btn:hover { background: var(--primary-glow); border-color: var(--accent); text-shadow: 0 0 6px var(--accent-dim); }
.header-btn[aria-current="page"] {
    border-color: var(--primary);
    color: var(--primary);
}

/* Theme picker dropdown: triggers like a .header-btn, opens a panel of
   theme options anchored below it. Menu is absolute-positioned and uses
   themed tokens so it re-skins with whatever theme is active. */
.theme-picker {
    position: relative;
    /* inline-flex with stretch makes the button child take wrapper height
       1-to-1 — eliminates baseline drift introduced by an inline-block
       wrapper around an inline-block toggle. */
    display: inline-flex;
    align-items: stretch;
}
.theme-picker-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    min-width: 140px;
    background: var(--panel);
    border: 1px solid var(--accent-dim);
    border-radius: 2px;
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    z-index: 50;
    box-shadow: 0 0 12px var(--primary-glow);
}
.theme-picker-menu[hidden] { display: none; }
.theme-picker-menu button {
    font-family: 'Share Tech Mono', monospace;
    font-size: 11px;
    letter-spacing: 2px;
    background: transparent;
    border: 0;
    color: var(--accent);
    padding: 6px 12px;
    text-align: left;
    cursor: pointer;
    border-radius: 2px;
}
.theme-picker-menu button:hover { background: var(--primary-glow); }
.theme-picker-menu button[aria-current="true"] {
    color: var(--primary);
    text-shadow: 0 0 6px var(--primary-glow-strong);
}

/* Nav drawer — button + dropdown panel, mirrors .theme-picker shape.
   Tried <details>/<summary> first but Chromium's UA stylesheet for
   <details> hides non-summary children through a path that `display:
   contents` doesn't reliably override on desktop. A plain button +
   aria-expanded toggle is robust across browsers and reuses the same
   click-outside / Escape JS that .theme-picker already ships. */
.header-nav-toggle { display: none; }

@media (min-width: 601px) {
    /* Make the drawer transparent to layout — nav buttons participate in
       .header-actions flex layout exactly like before the drawer existed. */
    .header-nav-drawer { display: contents; }
    .header-nav-drawer > .header-nav-list { display: contents; }
}

/* Mobile header compaction. The subtitle is "first-visit" copy — returning
   visitors don't need it on every page and it ate ~3 lines on phones.
   Buttons get tighter padding + letter-spacing. Nav collapses into the
   drawer; row 1 is just [ ≡ MENU ] + [ THEME ]. Theme toggle drops its
   current value via site.js so the row stays under one line wide; active
   theme is still indicated by aria-current in the dropdown. */
@media (max-width: 600px) {
    .subtitle { display: none; }
    .header-actions { gap: 6px; }
    .header-btn {
        font-size: 12px;
        padding: 4px 10px;
        letter-spacing: 1px;
    }
    .header-nav-drawer {
        /* Anchor for the dropdown panel — must establish a positioning
           context so the absolute-positioned list overlays content below
           the toggle without pushing surrounding flex items.
           inline-flex + align-items:stretch mirrors .theme-picker so the
           wrapper sizes to the toggle button exactly. A default block
           wrapper introduces line-box leading from body's line-height
           and renders ~4px taller than the button — causes a visible
           baseline mismatch against the theme picker sibling. */
        position: relative;
        display: inline-flex;
        align-items: stretch;
    }
    .header-nav-toggle { display: inline-flex; }
    /* List hidden by default on mobile; shown when toggle is expanded. */
    .header-nav-drawer .header-nav-list { display: none; }
    /* Nav list opens as a dropdown panel anchored under the toggle —
       mirrors the theme-picker dropdown so the two header controls feel
       like siblings. Theme picker stays inline at row 1; pushing it down
       (the earlier wrap approach) made the menu+theme controls feel
       disconnected. Vertical column = easier 1-tap targets on phones. */
    .header-nav-toggle[aria-expanded="true"] + .header-nav-list {
        position: absolute;
        top: calc(100% + 4px);
        /* Left-align the panel's left edge with the toggle's left edge
           so the dropdown drops straight down beneath [ ≡ MENU ] instead
           of centering under it and overflowing to the right. */
        left: 0;
        min-width: 200px;
        background: var(--panel);
        border: 1px solid var(--accent-dim);
        border-radius: 2px;
        padding: 6px;
        display: flex;
        flex-direction: column;
        gap: 4px;
        z-index: 50;
        box-shadow: 0 0 12px var(--primary-glow);
    }
    /* Theme picker dropdown on mobile: match the nav dropdown anchor —
       drop down from the [ THEME ] button's left edge. The desktop rule
       above keeps right:0 so the menu stays clear of the viewport edge
       on wide layouts. */
    .theme-picker-menu {
        left: 0;
        right: auto;
        min-width: 200px;
        padding: 6px;
        gap: 4px;
    }
    /* Theme buttons on mobile: borrow the bordered chip language from
       .header-btn so the [ THEME ] dropdown stops reading as a different
       widget family than the sibling [ ≡ MENU ] dropdown. Brackets in
       the markup (`[ AMBER ]`) carry the same chip glyph as nav items. */
    .theme-picker-menu button {
        border: 1px solid var(--accent-dim);
        border-radius: 2px;
        padding: 6px 14px;
        font-size: 12px;
        letter-spacing: 1px;
    }
    .theme-picker-menu button[aria-current="true"] {
        border-color: var(--primary);
    }
    /* Inside the dropdown, buttons fill the panel width — gives a calm
       vertical stack instead of jagged auto-widths. */
    .header-nav-toggle[aria-expanded="true"] + .header-nav-list > .header-btn {
        justify-content: flex-start;
        text-align: left;
    }
}

/* ---------- Main layout ---------- */
main {
    width: 100%;
    max-width: 960px;
    margin: 0 auto;
    /* Tighter bottom padding — footer's own top padding (and the rule)
       already provides separation, so we don't need to double-stack
       breathing room here. */
    padding: 16px 20px 18px;
}
@media (min-width: 768px) {
    main { padding: 20px 40px 22px; }
}
@media (min-width: 1200px) {
    main { max-width: 1020px; padding: 24px 48px 24px; }
}

/* Admin canvas widths + admin styles live in /assets/admin.css and are
   only loaded on /admin paths (see layout.php). */

/* The first heading in main shouldn't have a big top margin — header border
   already separates it from the brand area. */
main > section:first-child > h2:first-child,
main > article:first-child > .post-page-title:first-of-type,
main > article:first-child > .section-tag:first-child {
    margin-top: 4px;
}

/* ---------- Footer (site-wide metadata) ---------- */
footer {
    border-top: 1px solid var(--border);
    padding: 20px 20px 24px;
    font-family: 'Share Tech Mono', monospace;
    font-size: 11px;
    color: var(--text-dim);
    letter-spacing: 2px;
    text-align: left;
}
@media (min-width: 768px) {
    footer { padding: 24px 40px 28px; }
}

.footer-block {
    margin-bottom: 22px;
    max-width: 960px;
    margin-left: auto;
    margin-right: auto;
}
.footer-block:last-child { margin-bottom: 0; }

.footer-label {
    color: var(--primary-dim);
    letter-spacing: 3px;
    margin-bottom: 10px;
    text-transform: uppercase;
}

.footer-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.footer-ai a { color: var(--accent); text-decoration: underline; }

/* Source / "Powered by" link — sits at the very bottom of the footer
   below the copyright. Single centered line, dim by default, glows on
   hover. Reads as a subtle brand mark, not an ad. */
.footer-source {
    text-align: center;
    margin-top: 14px;
    letter-spacing: 2px;
}
.footer-source-link {
    color: var(--text-dim);
    text-decoration: none;
    font-family: 'Share Tech Mono', monospace;
    font-size: 11px;
    transition: color 0.18s ease, text-shadow 0.18s ease;
}
.footer-source-link:hover {
    color: var(--accent);
    text-shadow: 0 0 6px var(--accent-dim);
}

/* Tiny version stamp directly below the GitHub link. Operators see at a
   glance which build is serving. Dim by design — informational, not
   decorative. Source of truth: /VERSION file, surfaced via App\Version. */
.footer-version {
    text-align: center;
    color: var(--text-dim);
    opacity: 0.6;
    font-family: 'Share Tech Mono', monospace;
    font-size: 10px;
    letter-spacing: 2px;
    margin-top: 6px;
}

.footer-copyright {
    text-align: center;
    color: var(--text-dim);
    padding-top: 18px;
    border-top: 1px dashed var(--border);
    margin-top: 8px;
    letter-spacing: 3px;
}
/* No separator needed when copyright is the very first footer line
   (i.e. no § EXTENSIONS plugin block above) — the <footer> border-top
   already provides the visual break. */
footer > .footer-copyright:first-child {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

/* Smooth scroll for anchor jumps */
html { scroll-behavior: smooth; }
.post-body h1, .post-body h2, .post-body h3 { scroll-margin-top: 24px; }
