/* ==========================================================================
   exp38 . the shipped theme: terminal (phosphor CRT), baked in statically.

   HISTORY. This file was the exp28 review-only theme switcher's stylesheet:
   eight data-theme forks applied at runtime by assets/review.js (deleted).
   The founder-ruled default -- terminal, "the tube is the front door" -- is
   now baked into the static markup instead: every page carries
   data-theme="terminal" data-font="grotesk" on <html>, so the selectors
   below match with no JavaScript at all, at the same specificity the
   runtime switcher produced. The seven other theme forks, the switcher
   chrome (.rvw pill, .field-hud) and the Game-of-Life field rules were
   removed with the switcher and the field (stage 6); theme-verified.css
   remains in the tree, inert, per the leave-theme-files ruling.
   Load order is unchanged: site.css -> themes.css -> section builders.
   ========================================================================== */

/* ==========================================================================
   THEME: terminal — phosphor CRT. Near-black glass, everything IBM Plex
   Mono, green light, scanlines, bracketed buttons, amber for failure.
   ========================================================================== */
html[data-theme="terminal"]{
  --paper:#050807;
  --card:#0A100C;
  /* READING TEXT is pale phosphor green-white. Saturated green at low alpha
     has poor luminance against near-black and fringes on LCD subpixels; a real
     tube renders prose bright and slightly desaturated and keeps the saturated
     hue for accents. --signal is re-asserted below on every accent role
     (headings, kicker, buttons, cursor, selection, line-work) and carries the
     tube's light, never the state hue. */
  --ink:#D2FFE2;
  --ink-rgb:210,255,226;
  --ink-60:rgba(210,255,226,.84);
  --ink-40:rgba(210,255,226,.66);
  --muted:rgba(210,255,226,.80);
  --hair:rgba(43,255,111,.22);
  --hair-strong:rgba(43,255,111,.45);
  /* THE AFFORDANCE IS THE TUBE'S OWN LIGHT, NOT A HUE. This theme borrows
     verified's limit-case solution: --signal is white — one step past the
     phosphor ink #D2FFE2, the shade a CRT turns where it burns brightest —
     so at the front door the only saturated green left is --pass:#2BFF6F.
     "Verified" and "clickable" can no longer be the same pixel: state keeps
     the only hue. Everything bright still blooms green (the glows in this
     block stay rgba(43,255,111,…)): a white-hot core with a phosphor halo
     is what a tube does with light, so scanlines, bloom and the field are
     untouched. Affordances read against body ink by brightness, geometry
     and bloom — the same ladder verified runs (#F1F3EF ink vs #FFFFFF). */
  --signal:#FFFFFF;
  --signal-rgb:255,255,255;
  --fail:#FFB000;
  --pass:#2BFF6F;
  --wash:rgba(5,8,7,.88);
  --radius:0;
  /* the big lever: every DISPLAY + CHROME "sans" role becomes mono. This is
     the tube's identity: wordmark, headings, buttons, nav, node-card titles,
     figure "big" text. It does NOT reach prose. */
  --sans:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  /* exp32 two-layer rule: sentences a visitor reads stay in a real sans, in
     the same pale phosphor colour. A CRT renders prose bright and slightly
     desaturated; a monospace column of body copy is what made the whole page
     read as one texture with no hierarchy. */
  --prose:"Space Grotesk",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
}
/* scanlines + a faint phosphor bloom at the top of the tube */
html[data-theme="terminal"] body::after{
  content:"";position:fixed;inset:0;z-index:40;pointer-events:none;
  background:
    repeating-linear-gradient(0deg,rgba(0,0,0,.3) 0 1px,transparent 1px 3px),
    radial-gradient(120% 90% at 50% 0%,rgba(43,255,111,.055),transparent 60%);
}
/* exp32: prose floor holds on the tube too (was 1rem) */
html[data-theme="terminal"] body{font-size:1.06rem;}
/* type: all caps headings, prompt prefixes, zero rounded tracking.
   .hero-sub was in this list; exp32 moved it to the prose layer. */
html[data-theme="terminal"][data-font] h1,
html[data-theme="terminal"][data-font] h2,
html[data-theme="terminal"][data-font] h3,
html[data-theme="terminal"][data-font] .hero-2nd{font-family:var(--mono);}
html[data-theme="terminal"] h1,html[data-theme="terminal"] h2,html[data-theme="terminal"] h3,
html[data-theme="terminal"] .wordmark,html[data-theme="terminal"] .lead{letter-spacing:0;}
html[data-theme="terminal"] h1,html[data-theme="terminal"] h2,html[data-theme="terminal"] h3{
  text-transform:uppercase;font-weight:600;color:var(--signal);
}
html[data-theme="terminal"] h1{
  font-size:clamp(2rem,4.6vw,3.8rem);line-height:1.14;
  text-shadow:0 0 14px rgba(43,255,111,.4);
}
html[data-theme="terminal"] h2{font-size:clamp(1.3rem,2.4vw,1.9rem);text-shadow:0 0 12px rgba(43,255,111,.3);}
html[data-theme="terminal"] h3{font-size:1rem;}
html[data-theme="terminal"] h1::before,html[data-theme="terminal"] h2::before{content:"> ";color:rgba(43,255,111,.62);}
/* blinking block cursor after the H1 */
html[data-theme="terminal"] h1::after{
  content:"";display:inline-block;width:.5em;height:.85em;margin-left:.18em;
  background:var(--signal);vertical-align:baseline;transform:translateY(.1em);
  animation:t-blink 1.1s steps(1) infinite;
}
@keyframes t-blink{50%{opacity:0;}}
@media (prefers-reduced-motion: reduce){
  html[data-theme="terminal"] h1::after{animation:none;}
}
html[data-theme="terminal"] ::selection{background:var(--signal);color:#050807;}
html[data-theme="terminal"] a:hover{color:var(--signal);text-shadow:0 0 10px rgba(43,255,111,.6);}
/* no rounded corners anywhere on this tube */
html[data-theme="terminal"] .tiles,html[data-theme="terminal"] .tile,
html[data-theme="terminal"] .frame,html[data-theme="terminal"] .stage,
html[data-theme="terminal"] .rows,html[data-theme="terminal"] .persona,
html[data-theme="terminal"] .lead-form,html[data-theme="terminal"] .nav-menu nav,
html[data-theme="terminal"] .nav-menu summary,html[data-theme="terminal"] .legend i,
html[data-theme="terminal"] .lp-facts,html[data-theme="terminal"] .lp-pe,
html[data-theme="terminal"] .stop::before{border-radius:0;}
/* nav: thin green rule, caps */
/* the tube keeps square corners: a rounded CRT bar would be wrong */
html[data-theme="terminal"]{--nav-r:0;}
html[data-theme="terminal"] .site-header .nav{border:1px solid var(--hair-strong);background:rgba(5,8,7,.9);}
html[data-theme="terminal"] .site-header.is-stuck .nav{box-shadow:0 0 26px rgba(43,255,111,.16);}
/* emphasis rides the same light as its line: #D9FFE6 under a brighter h1
   would invert the emphasis. The weight split carries it, never a second
   colour (verified's ruling); the stronger bloom stays phosphor. */
html[data-theme="terminal"] .h1-em{color:var(--signal);text-shadow:0 0 20px rgba(43,255,111,.55);}
html[data-theme="terminal"] .wordmark{text-transform:uppercase;font-weight:600;}
/* nav floor: this fork outranks s35-craft's `.nav-links a{max(13px,.82rem)}`
   on specificity, so it must carry the 13px founder floor itself — bare
   .76rem computed 12.16px site-wide. max() keeps the tighter terminal caps
   at exactly the floor. */
html[data-theme="terminal"] .nav-links a{text-transform:uppercase;font-size:max(13px,.76rem);letter-spacing:.08em;}
html[data-theme="terminal"] .nav-links a[aria-current="page"]{border-bottom-color:var(--signal);color:var(--ink);}
/* buttons: bracketed commands, transparent, caps */
html[data-theme="terminal"] .btn{
  background:transparent;border:1px solid transparent;color:var(--signal);
  text-transform:uppercase;letter-spacing:.06em;font-weight:600;
  border-radius:0;padding:0 .6rem;
}
html[data-theme="terminal"] .btn::before{content:"[";margin-right:.15em;color:rgba(43,255,111,.55);}
html[data-theme="terminal"] .btn::after{content:"]";margin-left:.15em;color:rgba(43,255,111,.55);}
html[data-theme="terminal"] .btn:hover{background:rgba(43,255,111,.12);border-color:rgba(43,255,111,.4);color:var(--signal);text-shadow:0 0 10px rgba(43,255,111,.7);}
html[data-theme="terminal"] .btn:disabled:hover{background:transparent;border-color:transparent;}
html[data-theme="terminal"] .cta-quiet{color:var(--ink-60);}
/* cards: 1px green line-work, flat, faint inner glow */
html[data-theme="terminal"] .tile,html[data-theme="terminal"] .persona,
html[data-theme="terminal"] .rows,html[data-theme="terminal"] .lead-form,
html[data-theme="terminal"] .lp-facts,html[data-theme="terminal"] .lp-pe{
  border-color:var(--hair);box-shadow:inset 0 0 32px rgba(43,255,111,.04);
}
html[data-theme="terminal"] .frame{border:1px solid var(--hair-strong);box-shadow:0 0 28px rgba(43,255,111,.1);}
html[data-theme="terminal"] .frame-bar{background:#050807;}
/* SCREENSHOTS RENDER NATURAL (founder ruling 2026-08-27). The tube used to
   phosphor-tint every .frame img with a grayscale/invert/sepia/hue-rotate
   chain. Ruled out: a portal capture is evidence, and evidence keeps the
   product's own colours on every page. The mount keeps the phosphor chrome
   (border + glow above); only the pixels inside it stopped being repainted. */
html[data-theme="terminal"] .stage{border:1px solid var(--hair-strong);box-shadow:inset 0 0 60px rgba(43,255,111,.05);}
html[data-theme="terminal"] .kicker{color:var(--signal);}
html[data-theme="terminal"] .kicker::before{box-shadow:0 0 8px rgba(43,255,111,.8);}
/* form: dark wells, green carets */
html[data-theme="terminal"] .lead-form input:not(.hp),
html[data-theme="terminal"] .lead-form select,
html[data-theme="terminal"] .lead-form textarea{border-radius:0;border-color:rgba(43,255,111,.4);background:#050807;}
html[data-theme="terminal"] .lead-form select{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23FFFFFF' stroke-width='1.5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .8rem center;}
html[data-theme="terminal"] .lead-form input[readonly]{background:var(--card);}
html[data-theme="terminal"] .skip{color:#050807;}

/* ---------- terminal: LEFT-ALIGNED hero ----------
   A prompt only reads at a fixed left column. Centred, the "> " inflates the
   first line so "PROVE" starts further right than the line under it. Here the
   prompt participates in the flow at column 0 and every wrapped line returns to
   that same column, exactly like a shell; the kicker, sub, CTA row and facts
   line all share it. The measure is set so the two lines nearly fill it, so the
   block reads as a deliberate paragraph of shell output rather than a stub. */
html[data-theme="terminal"] .hero{padding:clamp(2.2rem,4.6vw,3.6rem) 0 clamp(1.7rem,3.5vw,2.5rem);}
html[data-theme="terminal"] .hero-copy{text-align:left;}
html[data-theme="terminal"] .hero-copy > *{margin-inline:0;}
html[data-theme="terminal"] .hero-copy h1{
  font-size:clamp(2.2rem,5.4vw,4.6rem);
  max-width:26ch;
}
/* the sub's measure is the craft token (2026-08-27 ruling): this (0,2,1) rule
   reaches the heroes the craft layer's `main .hero .hero-sub` does not
   (pc-hero, mp-hero), so it must carry the same token, not its own number. */
html[data-theme="terminal"] .hero-sub{max-width:var(--measure-hero,62ch);margin-left:0;margin-right:0;}
html[data-theme="terminal"] .hero .cta-row{justify-content:flex-start;}
html[data-theme="terminal"] .hero .facts{justify-content:flex-start;}
/* the tube keeps its left column on mobile too: bracketed CTAs are text, so a
   full-width block button would centre them away from the prompt column */
@media (max-width:640px){
  html[data-theme="terminal"] .hero .cta-row{align-items:flex-start;}
  html[data-theme="terminal"] .hero .cta-row .btn,
  html[data-theme="terminal"] .hero .cta-row .btn-video{width:auto;justify-content:flex-start;padding-left:0;}
}

/* line-work is not prose: strokes, node cards and figure ink take the
   affordance light (they used to take the saturated hue, which is now
   reserved for --pass). State classes keep their own colours below —
   amber failures, cyan code, green only where a state class puts it. */
html[data-theme="terminal"] .stage text,
html[data-theme="terminal"] .stage .ttl{fill:var(--signal);}
html[data-theme="terminal"] .stage .n,
html[data-theme="terminal"] .stage .hm-lg{stroke:var(--signal);}
html[data-theme="terminal"] .stage .hm-reg rect{fill:var(--signal);}
/* FIGURE INK IS STRUCTURE, NOT A STATE.
   This used to be  .fig .st{stroke:var(--signal)}  which did two bad things at
   once: it painted every structural stroke the verified green, so "green means
   proven knowledge" stopped meaning anything in this theme, and — at (0,3,1) —
   it out-ranked the semantic state classes .st.gs-ok / .st.gs-bad / .st.good /
   .st.stale-s, so hazards drew green too. Re-keying the variable instead leaves
   every state class in charge of its own hue. */
html[data-theme="terminal"] .fig{--fig-st:var(--unknown,var(--hair-strong));}
html[data-theme="terminal"] .facts b{color:var(--signal);}

/* ---------- terminal: multi-hue phosphor for the maps ----------
   promises take the affordance light (was the saturated hue); code +
   implemented-by = cyan; tests keep white-green titles; known issue +
   affects + failing test = amber; the commit dot burns white (HDR asset
   when available). */
html[data-theme="terminal"] .stage [data-node^="c-"] .n,
html[data-theme="terminal"] .stage [data-node^="c_"] .n{stroke:#3DE8FF;}
html[data-theme="terminal"] .stage [data-node^="c-"] .lbl,
html[data-theme="terminal"] .stage [data-node^="c_"] .lbl{fill:rgba(61,232,255,.6);}
html[data-theme="terminal"] .stage [data-node^="c-"] .ttl,
html[data-theme="terminal"] .stage [data-node^="c_"] .ttl{fill:#3DE8FF;}
html[data-theme="terminal"] .stage .edge[data-edge*=">c"],
html[data-theme="terminal"] .stage [data-edge*=">c"] .edge{stroke:rgba(61,232,255,.5);}
html[data-theme="terminal"] .stage [data-node^="t"] .ttl{fill:#D9FFE6;}
html[data-theme="terminal"] .stage [data-node^="k"] .ttl{fill:#FFB000;}
/* edge labels: dimmer, hue-matched */
html[data-theme="terminal"] .heromap .stage .hm-el{fill:rgba(43,255,111,.4);}
html[data-theme="terminal"] .heromap .stage .hm-el[data-of^="c"]{fill:rgba(61,232,255,.42);}
html[data-theme="terminal"] .heromap .stage .hm-aff-l{fill:rgba(255,176,0,.55);}
/* heromap state + hover mechanics keep their hue */
html[data-theme="terminal"] .heromap .stage .hm-hi-sig{stroke:#3DE8FF;}
html[data-theme="terminal"] .heromap .stage .edge[data-edge*=">c"].hm-lit{stroke:rgba(61,232,255,.9);}
html[data-theme="terminal"] .heromap .stage .hm-el[data-of^="c"].hm-lit{fill:#3DE8FF;}
html[data-theme="terminal"] .heromap .stage .hm-c.act .lbl{fill:#3DE8FF;}
html[data-theme="terminal"] .heromap .stage .fail .ttl{fill:#FFB000;}
html[data-theme="terminal"] .heromap .stage .hm-lg-ink{stroke:#3DE8FF;}
html[data-theme="terminal"] .heromap .stage .hm-ping{stroke:#FFFFFF;}
html[data-theme="terminal"] .heromap .stage .hm-dot{fill:url(#hdrdotpat) #FFFFFF;}
/* graph plate: its inline styles hardcode dark ink; re-key them to phosphor */
html[data-theme="terminal"] .gp-plate .edge{stroke:rgba(43,255,111,.36);}
html[data-theme="terminal"] .gp-plate .elbl{fill:rgba(43,255,111,.4);}
html[data-theme="terminal"] .gp-plate .ptitle{fill:rgba(43,255,111,.5);}
html[data-theme="terminal"] .gp-plate [data-edge*=">c"] .elbl{fill:rgba(61,232,255,.42);}
html[data-theme="terminal"] .gp-plate [data-edge^="k"] .elbl{fill:rgba(255,176,0,.55);}
html[data-theme="terminal"] .stage [data-edge*=">c"].lit .edge{stroke:#3DE8FF;}
html[data-theme="terminal"] .gp-plate [data-edge*=">c"].lit .elbl{fill:#3DE8FF;}
html[data-theme="terminal"] .gp-plate .lit .n{filter:drop-shadow(0 0 10px rgba(43,255,111,.3));}

/* ---------- terminal: HDR accents (assets/hdr, BT.2100 PQ tagged) ----------
   NO RESTING EMITTER HERE. The primary CTA used to carry hdr/hdr-glow.png at
   rest: an 86% x 5px PQ strip under the button, live on graph.html and
   audit.html, and the brightest thing on either page before a visitor did
   anything. HDR is an event, not a palette, and nothing is HDR at rest, so the
   resting declaration is gone. The hover below is transient and stays; it sets
   the whole background shorthand itself, so it never depended on the resting
   rule for its position, size or repeat. */
html[data-theme="terminal"] .hero .cta-row .btn-primary:hover{
  background:rgba(43,255,111,.12) url("hdr/hdr-glow.png") 50% 100% / 86% 5px no-repeat;
}

/* ---------- data-hdr="off": the kill switch reaches this file too ----------
   hdr-event.css owns the off-list, but it can only name the carriers it
   declares. The terminal CTA hover above paints hdr/hdr-glow.png, which is
   declared here and so is switched off here. The hover keeps its SDR tell
   (the rgba(43,255,111,.12) wash) and loses only the HDR layer.
   !important because the carrier is re-declared at equal specificity. */
html[data-hdr="off"] .hero .cta-row .btn-primary:hover{background-image:none !important;}

/* ==========================================================================
   SCREENSHOT CAPTIONS READ AS SENTENCES (founder ruling 2026-08-27).
   .frame-cap blocks are 300-470-character explanations under the portal
   captures, and they rendered at the 13px machine floor on a 58ch mono
   measure -- a narrow ragged column filling barely half of its own plate.
   They are reading prose that happens to wear mono, so they take one step
   up in size and a 70ch cap that uses the plate's width sensibly.

   THIS LIVES HERE, NOT IN s35-craft.css: the craft floor sets these from
   `main :is(...)` (0,1,1) with !important, and that file is owned by the
   measure pass. (0,2,1) + !important out-cascades it from any sheet, and
   this one loads on every page that mounts a .frame. .count-note is the
   deliberate fine-print aside inside one caption; it follows the caption
   instead of staying a floor-pinned 13px island inside 14px prose. */
main .frame .frame-cap{
  font-size:14px !important;
  line-height:1.6;
  max-width:70ch;
}
main .frame .frame-cap .count-note{font-size:inherit !important;}
/* the branch-disclosure note under the product shots is the same reading
   role at the same old floor; it steps up with the captions. */
main .pr-body .pr-shotnote{font-size:14px !important;max-width:70ch;}

/* Second pass on the same ruling: the copy is compressed in the HTML, and a
   caption that still runs past four lines takes .cap-cols and flows as two
   balanced columns on wide viewports, so the plate's width carries text
   instead of an empty right field. Applied per block; captions of four lines
   or fewer keep the single 70ch column. Below 1100px (and on phones) the
   columns collapse back to the single column above. */
@media (min-width:1100px){
  main .frame .frame-cap.cap-cols,
  main .pr-body .pr-shotnote.cap-cols{
    max-width:none;
    columns:2;
    column-gap:3rem;
    text-wrap:pretty;
  }
}
