/* Ziltch theme — the MARKETING / CMS front-end chrome, on the ONE Ziltch design system (Erin-directed: design
   enforcement everywhere). A clean light surface carrying the shared AMBER brand + the same nav structure as the dark
   gateway app surfaces (ziltch-terminal.css), so the platform reads as one designed product. The Blog shape templates
   (BaseTheme = TheBlogTheme) render into .ziltch-main; this file owns the outer frame. */
/* The design TOKENS (:root light + the prefers-color-scheme:dark flip) were RELOCATED to ziltch-chrome.css (Erin
   2026-07-17 "share, not duplicate, between site + admin") — the shared file is loaded BEFORE this one by both the site
   Layout and Ziltch.Theme.Admin, so every var(--zt-*) below still resolves. Kept out of this file so there is one
   definition of the palette, not a site copy and an admin copy that drift. */

/* Bootstrap's `body { background: var(--bs-body-bg) }` loads AFTER ours and won by load order — so in dark mode only the
   header/footer (which set --zt-surface explicitly) went dark while the page body stayed white (measured: bodyBg was
   rgb(255,255,255) with --zt-surface already #0b1020). Pin the body to the theme with a higher-specificity selector, and
   map bootstrap's body tokens to the theme vars so BS components follow light/dark too. */
/* ── UNIFIED DARK OBSERVATORY (Erin: "UI design needs a lot of work" — cohesion pass) ──────────────────────────────
   The surface islands commit to the dark "sea of stars" identity (ziltch-terminal.css forces --zt-bg #070b1a
   unconditionally), so the CHROME must match or the page reads as a light Bootstrap shell wrapping a dark blob (the exact
   disconnect that made it look unfinished). Point the whole frame at the SURFACE tokens (--zt-bg / --zt-fg / --zt-panel /
   --zt-grid — which the terminal stylesheet keeps dark) so header, body, content and footer read as ONE instrument. A
   faint amber top-glow + a deep vignette give the near-black real depth instead of flatness. */
html body { background: var(--zt-bg); color: var(--zt-fg); }
:root { --bs-body-bg: var(--zt-bg); --bs-body-color: var(--zt-fg); }

body { min-height: 100vh; display: flex; flex-direction: column; color: var(--zt-fg);
    font-family: var(--zt-font-ui); background: var(--zt-bg);
    background-image:
        radial-gradient(1100px 520px at 50% -8%, color-mix(in srgb, var(--zt-accent) 7%, transparent), transparent 70%),
        radial-gradient(900px 900px at 100% 100%, color-mix(in srgb, var(--zt-accent-2) 6%, transparent), transparent 60%);
    background-attachment: fixed; }

/* ── header ──────────────────────────────────────────────────────────────────────
   RELOCATED to ziltch-chrome.css (Erin 2026-07-17 "share, not duplicate, between site + admin"): the tokens + the
   .ziltch-header / .navbar-brand / .ziltch-logo / .ziltch-app-nav / toggler chrome now live there and are loaded by BOTH
   this site theme and Ziltch.Theme.Admin. The site Layout links ziltch-chrome.css BEFORE this file. Only site-LAYOUT
   rules (the flex body frame, front-door, content) remain here — they must NOT reach the admin layout. */

.ziltch-gateway-badge {
    font-size: .7rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--zt-accent); background: color-mix(in srgb, var(--zt-accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--zt-accent) 35%, transparent);
    padding: .22rem .7rem; border-radius: 999px; white-space: nowrap;
}

/* ── main + footer ──────────────────────────────────────────────────────────── */
/* 🔴 THE BRAND DID NOT SURVIVE THE THEME CONSOLIDATION — MEASURED 2026-09-12.
   These rules were written for Ziltch.Theme, whose layout renders `<main class="container ziltch-main">`.
   The SERVED theme is Ziltch.Theme.SiteAndAdmin ("no base theme, one chrome"), whose layout renders
   `ziltch-site-main` (Layout.cshtml:305) and `ziltch-admin-main` (:286). It LOADS this stylesheet
   (Layout.cshtml:183) — so the file ships, and nine of its rules match nothing.
   🩸 Measured in a static harness serving the three sheets the layout loads, identical markup in both
   containers: EVERY declaration below differed. Content links, form fields, selects and the gold primary
   variant reached `.ziltch-main` and reached NOTHING in `.ziltch-site-main`.
   ⚖️ THE IMPACT IS BRAND, NOT BLANK: Bootstrap is loaded (Layout.cshtml:179) and `.btn-primary` is also
   styled unscoped (line ~74 here, and ziltch-chrome.css:413 at doubled specificity), so controls render as
   BOOTSTRAP's palette rather than Ziltch's — not as unstyled HTML. The login form is separately covered by
   `.auth-form` rules in ziltch-chrome.css. What is lost is every form field and content link OUTSIDE that.
   📌 `:is(.ziltch-main, .ziltch-site-main)` carries the specificity of a single class, so nothing else in
   the cascade moves — this widens WHERE the rules apply and changes no value. */
:is(.ziltch-main,.ziltch-site-main) { flex: 1 0 auto; padding-top: 1.5rem; padding-bottom: 2.5rem; }
:is(.ziltch-main,.ziltch-site-main) a { color: var(--zt-accent-2); text-underline-offset: 2px; }
/* 🔴 HOVERING A LINK MADE IT HARDER TO READ — AND ONLY IN THE LIGHT ARM.
   This was `color: var(--zt-accent)`, which resolves through --zt-gold to #c79a3a in light and
   #e9c46a in dark. Measured 2026-09-12 against --zt-bg (= --zt-surface), which is what .ziltch-main
   actually sits on since it declares no background of its own:
       light   rest #472c54  11.96:1   ->  HOVER #c79a3a   2.59:1   *** FAILS WCAG 1.4.3 (4.5)
       dark    rest #b79bd6   8.09:1   ->  HOVER #e9c46a  11.73:1   PASS
   Grounds are the LIVE computed values (#ffffff / #070b1a), read off the running cell rather than
   resolved from the stylesheet by hand — the hand pass had the dark ground as #0b1020
   (--p-dark-surface) and was wrong by one token hop. It moved the dark numbers and changed nothing
   about the verdict, because the failure is in the arm whose ground was never in doubt.
   A 4.6x LOSS on the light arm, on the one interaction whose whole job is to say "this is
   actionable". Dark improves on hover, which is exactly why this survived: whichever arm you test,
   you see the opposite conclusion. (The togglePassword defect fixed the same day ran the other way
   — dead in dark, fine in light. One-arm testing misses these in BOTH directions.)
   ⚖️ THE THEME ALREADY HAD THE RIGHT ANSWER AND THIS RULE WAS OVERRIDING IT. --ztc-link-hover is
   defined in all four arms and feeds --bs-link-hover-color, i.e. it IS this theme's link-hover
   colour for every Bootstrap link on the page. Gold is an ACCENT — a fill and a highlight — and was
   never the link colour; reaching for it here overrode a correct, theme-aware system with a value
   that only works in one arm. Light 7.00:1, dark 11.64:1.
   📌 Rest state is left alone: --zt-accent-2 passes both arms (11.96 / 8.09) and is unrelated. */
:is(.ziltch-main,.ziltch-site-main) a:hover { color: var(--ztc-link-hover); }

.ziltch-footer { flex-shrink: 0; border-top: 1px solid var(--zt-grid); padding: 1.1rem 0;
    background: color-mix(in srgb, var(--zt-panel) 60%, var(--zt-bg)); color: var(--zt-muted); font-size: .82rem; }
.ziltch-island-slot { margin-bottom: .75rem; }
.ziltch-copyright { color: var(--zt-muted); font-size: .76rem; letter-spacing: .04em; margin: 0; opacity: .8; }

/* on-brand primary buttons across CMS content (Bootstrap variable override) */
.btn-primary {
    --bs-btn-bg: var(--zt-brand-deep); --bs-btn-border-color: var(--zt-brand-deep);
    --bs-btn-hover-bg: #946100; --bs-btn-hover-border-color: #946100;
    --bs-btn-active-bg: #7d5200; --bs-btn-active-border-color: #7d5200;
}

/* ── DESIGNED-PRODUCT POLISH (whole-page craft signals) ───────────────────────────────────────────────────────────
   The small details that separate "a dark app" from "an instrument": a thin dark scrollbar that belongs to the surface
   (not the OS default light bar), amber text-selection + focus rings that echo the accent, and smooth in-surface scroll.
   All global, CSS-only, zero markup change. */
html { scroll-behavior: smooth; }

::selection { background: color-mix(in srgb, var(--zt-accent) 32%, transparent); color: var(--zt-fg); }

/* Firefox */
* { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--zt-accent) 30%, var(--zt-grid)) transparent; }
/* WebKit/Chromium */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--zt-grid) 85%, var(--zt-accent) 15%);
    border-radius: 999px; border: 2px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--zt-accent) 45%, var(--zt-grid)); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Keyboard focus — an amber ring that matches the accent, only on keyboard nav (never a mouse-click halo). */
:focus-visible { outline: 2px solid color-mix(in srgb, var(--zt-accent) 70%, transparent); outline-offset: 2px; border-radius: 4px; }
a, button, [role="button"] { -webkit-tap-highlight-color: transparent; }

/* Account pages (login / register / reset) now render in the SITE theme (LoginSettings.UseSiteTheme, Erin ask #2), but
   OC's form uses bare Bootstrap controls — white inputs + a blue button that read as unfinished on the dark chrome.
   Theme the OC form controls to the Ziltch palette so the FORM matches the header/footer. Scoped to .ziltch-main so it
   only touches the themed content area (every site form is consistent; the anon greeter uses its own .reply input). */
:is(.ziltch-main,.ziltch-site-main) .form-control, :is(.ziltch-main,.ziltch-site-main) .form-select {
    background: var(--zt-panel); color: var(--zt-fg); border-color: var(--zt-grid); }
:is(.ziltch-main,.ziltch-site-main) .form-control::placeholder { color: var(--zt-muted); }
:is(.ziltch-main,.ziltch-site-main) .form-control:focus, :is(.ziltch-main,.ziltch-site-main) .form-select:focus {
    background: var(--zt-panel); color: var(--zt-fg); border-color: var(--zt-accent);
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--zt-accent) 22%, transparent); }
/* ⚖️ THE INK AND THE HOVER BOTH FOLLOW THE ARM — measured 2026-09-12, both were frozen at the dark arm's
   values and both failed on light. --zt-accent is #8a6100 on light and #e9c46a on dark, so a literal ink can
   only be right in one of them: #0b1020 on the light accent read 3.42:1. var(--zt-bg) inverts with the ground
   (#ffffff light / #070b1a dark) and reads 5.54 / 11.73.
   🔑 AND THE HOVER WAS MIXING THE WRONG WAY, which the ink fix alone does NOT cure: mixing toward #ffffff
   lightens the fill TOWARD THE PAGE on a light theme, so hover read 4.33:1 — still under 4.5, and a weaker
   affordance than rest. Mixing toward var(--zt-fg) moves the fill AWAY from the ground in BOTH arms: darker on
   light (6.29:1), lighter on dark (12.08:1), so contrast IMPROVES on hover instead of degrading. */
/* ⚖️ THREE RULES DELIBERATELY LEFT SCOPED TO THE OLD THEME — THEY WOULD RE-DECIDE A COLOUR, NOT RESTORE ONE.
   `.ziltch-main .btn-primary` (+ :hover/:focus) and `.form-check-input:checked` paint var(--zt-accent) = GOLD.
   Widening them would change the served site's primary CTA from BRAND PURPLE to gold sitewide: measured on the
   live login button before this cell went down, the served primary is #472c54 with white ink at 11.96:1, and
   ziltch-chrome.css:413 styles it as `.btn-primary.btn-primary` — DOUBLED specificity, which is a deliberate
   "this override must win", not an accident. The new theme has decided its primary action is purple.
   📌 So the gap those three would fill is not a gap: the served theme already answers them. The other nine ARE
   a gap — nothing in the new theme styles a content link or a form field, so they fall back to Bootstrap.
   Gold-vs-purple for the primary CTA and the checked state is Erin's call, not a side effect of a scoping fix. */
.ziltch-main .btn-primary {
    background: var(--zt-accent); border-color: var(--zt-accent); color: var(--zt-bg, #070b1a); font-weight: 600; }
.ziltch-main .btn-primary:hover, .ziltch-main .btn-primary:focus {
    background: color-mix(in srgb, var(--zt-accent) 88%, var(--zt-fg)); border-color: var(--zt-accent); color: var(--zt-bg, #070b1a); }
.ziltch-main .form-check-input:checked { background-color: var(--zt-accent); border-color: var(--zt-accent); }

/* ══ LIGHT-MODE TOKEN PAIRING ═══════════════════════════════════════════════════════════════════════════════════
   🔴 WITHOUT THIS, ziltch.io IS UNREADABLE IN LIGHT MODE AND HAS NO REACHABLE SIGN-IN. Measured on the live site
   2026-08-11 with an iPhone user-agent: `--zt-fg: #20232e` on `--zt-bg: #070b1a` — near-black on near-black, a
   contrast ratio of 1.3:1. The header controls are the only text on the front page, so they are the only casualty.

   THE MECHANISM IS A SPECIFICITY SPLIT ACROSS TWO STYLESHEETS, and the two halves of one token pair get two
   different winners:

     --zt-bg   ziltch-chrome.css `:root` (alias -> --zt-surface)   vs   ziltch-terminal.css `:root` (#070b1a)
               EQUAL specificity (0,1,0); terminal loads LATER  =>  TERMINAL WINS  =>  dark, in every mode
     --zt-ink  ziltch-chrome.css `@media (prefers-color-scheme: light) :root:not([data-bs-theme="dark"])`
               (0,2,0) beats a plain `:root`                    =>  CHROME WINS   =>  the LIGHT ink

   So the foreground follows the theme and the background does not.

   ⚠️ DARK MODE HIDES IT COMPLETELY — there the chrome light block does not apply, both tokens fall through to
   terminal.css's OWN self-consistent palette (#e8ecf8 on #070b1a) and read perfectly. THE DEFECT IS REACHABLE
   ONLY IN LIGHT MODE, which is the mode nobody here develops in, on a homepage that is a full-bleed image with
   almost no text. It looked fine from every seat.

   ⚖️ THIS LIVES HERE RATHER THAN IN ziltch-chrome.css BESIDE THE ALIASES IT REPAIRS, AND THAT IS A DELIBERATE
   TRADE, NOT A PREFERENCE: that file carried another agent's uncommitted work, and `git add <file>` takes a
   MOMENT rather than a change. Order is irrelevant to the cure — (0,2,0) beats (0,1,0) whichever file it sits
   in, which is empirically proven by the bug itself (chrome's light block already beats terminal's later
   `--zt-ink` from an EARLIER file). Fold it back beside the aliases when that file is quiet.

   ⏭️ ROOT CAUSE NAMED AND NOT FIXED: a COMPONENT stylesheet (the Gateway's terminal render-kit) declares global
   `:root` chrome tokens at all. Scoping those to the terminal is the real cure and is wider than a front-door
   outage should carry.

   BOTH light doors, deliberately — fixing only the media query leaves a user who picks light in the UI with the
   identical outage, reading as a different bug. */
@media (prefers-color-scheme: light) {
    :root:not([data-bs-theme="dark"]) {
        --zt-bg: var(--zt-surface);
        --zt-fg: var(--zt-ink);
        --zt-muted: var(--zt-ink-dim);
        --zt-accent: var(--zt-gold);
        --zt-accent-2: var(--zt-brand-text);
        --zt-grid: var(--zt-line);
        --zt-panel: var(--zt-surface-2);
    }
}

:root[data-bs-theme="light"] {
    --zt-bg: var(--zt-surface);
    --zt-fg: var(--zt-ink);
    --zt-muted: var(--zt-ink-dim);
    --zt-accent: var(--zt-gold);
    --zt-accent-2: var(--zt-brand-text);
    --zt-grid: var(--zt-line);
    --zt-panel: var(--zt-surface-2);
}

/* ─────────────────────────────────────────────────────────────────────────────
   REDUCED MOTION — an OS-level request the product answered only on the front door.

   MEASURED 2026-09-12: 47 files carry motion (9 INFINITE animations, 103 transitions) and
   exactly ONE — ziltch-frontdoor.css — honoured prefers-reduced-motion. Everything else ran
   regardless: pulse-live and pulse-sync on status indicators, cursor-blink and blink in the
   terminal, spin on every loading state. None of it is a parallax or an auto-playing carousel,
   which is why it was easy to leave: each animation is small, conventional and defensible on
   its own, and the sum is a page that never stops moving for someone who asked it to.

   This lives in ziltch.css because both the site and admin layouts serve it, so one block
   reaches every surface rather than each component remembering. It is the canonical form:
   0.01ms rather than 0, so a transitionend/animationend listener still fires and nothing that
   waits on one hangs. animation-iteration-count:1 is what actually stops an `infinite`.

   NOT a blanket kill: `reduce` is a user's explicit setting, not a default, and motion that
   CARRIES INFORMATION should survive it. Nothing here does — a pulse says "live", which the
   label beside it already says. If a future animation is the only carrier of some state, it
   belongs outside this block with a comment saying why.
   ───────────────────────────────────────────────────────────────────────────── */
@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;
    }
}

/* A GL block drawn through a render-kit lens (GlAnswerLens). */
.zt-gl-lens { margin: .25rem 0; }

/* An editable GL block (GlEditorBlock): the reader's program above its answer. */
.zt-gl-editor { display: flex; flex-direction: column; gap: .4rem; margin: .25rem 0 .5rem; }
.zt-gl-edit { width: 100%; font-family: ui-monospace, Consolas, "Cascadia Mono", monospace; font-size: .875rem;
    background: var(--zt-panel, #0f1626); color: inherit; border: 1px solid var(--zt-grid, #24314a); border-radius: .4rem; padding: .5rem; }
.zt-gl-editor-bar { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.zt-gl-editor-note { color: var(--zt-muted, #7e8aa3); font-size: .875rem; }
