/* ═══════════════════════════════════════════════════════════════════════
   SIVNSH7 — FIELD DOSSIER
   Design system: brutalist structure · clay tactility · paper skeuomorphism
   with a signature "redaction bar" motif.

   SYSTEM CONTRACT — read before adding a component
   ───────────────────────────────────────────────────────────────────────
   ELEVATION — 3 levels + a pressed state.
     --sh-1  secondary surfaces (chips, inner modules, log bodies, links)
     --sh-2  primary surfaces (cards, nav, hero coords, case files)
     --sh-hero for the single highest-priority proof block (hero__proof, .btn--clay:hover)
     --sh-press for active/pressed states.
   RADII    — --r-sm / --r-md / --r-lg / --r-pill only.
   BORDERS  — --border-w (primary) or --border-hair (secondary). Nothing else.
   BLUR     — budget: max 2 backdrop-filter surfaces (nav, sheet). Nowhere else.
   LABELS   — .lbl is the ONLY uppercase-mono label class. Do not create variants.
   STATUS   — use .stamp--{live,wip,confirmed,probable,hypothesis}. No inline style.
   PROOF    — .proof / .proof__n / .proof__l for any quantified claim.
   MOTION   — structural: reveal-on-scroll, section heading line draw, disclosure arrow,
              grade-bar fill, scroll-progress bar. Signature: hero 3D tilt + letter
              entrance. Informational: proof count-in. Nothing decorative.
   ═══════════════════════════════════════════════════════════════════════ */

/* ---------- 1. TOKENS ---------- */
:root{
  /* paper + ink — ivory linen over espresso, not brutalist cream/black */
  --paper:      #F1EBDC;
  --paper-2:    #E6DCC4;   /* recessed panel */
  --paper-3:    #F9F5EA;   /* raised card, lightest */
  --ink:        #211C15;
  --ink-soft:   #4F4738;
  --ink-mute:   #756A57;   /* AA on --paper */
  --line:       #211C15;

  /* accents — oxblood (primary), antique brass (support). Others status-only. */
  --red:        #7A3430;
  --red-dark:   #5B2521;
  --red-tint:   #E9DACE;
  --clay:       #9C7B3F;
  --clay-dark:  #715A26;   /* darkened → AA on light tints */
  --clay-light: #C2A05E;
  --clay-tint:  #EBE0C4;
  --clay-shade: #5C4720;   /* fixed bevel-shadow tone, does not swap with theme */
  --letter-outline: #211406; /* fixed dark outline, stays dark in both themes */
  --green:      #35513F;
  --green-dark: #223A2B;
  --green-tint: #DFE6DC;
  /* --green above is reserved for the literal "live" indicator (.dot, .rig__live)
     only. Every other status that used to borrow it (active/confirmed capsules)
     now runs on --red-active below, kept one step brighter than the base
     --red so a "confirmed/active" stamp still reads apart from a "hypothesis" one. */
  --red-active:      #B23A2C;
  --red-active-dark: #7C2318;
  --red-active-tint: #F1DBCF;
  --blue:       #33455E;
  --blue-light: #DEE2E9;

  /* elevation — TWO levels + one reserved hero level */
  --sh-1: 3px 3px 0 var(--ink);
  --sh-2: 6px 6px 0 var(--ink);
  --sh-hero: 9px 9px 0 var(--ink);
  --sh-press: 2px 2px 0 var(--ink);

  /* radii */
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 22px;
  --r-pill: 999px;

  /* type */
  --font-display: "Bricolage Grotesque", "Space Grotesk", system-ui, sans-serif;
  --font-body: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "Menlo", "Consolas", monospace;

  --border-w: 2.5px;
  --border-hair: 1.5px;
  --edge: clamp(20px, 6vw, 64px);

  /* surfaces that were backdrop-blurred — now opaque (perf budget) */
  --glass:      rgba(249,245,234,.92);
  --glass-hi:   rgba(249,245,234,.97);

  /* fixed lacquer-red button tones — deliberately NOT theme-swapped like
     --clay-light/--clay-dark. The CTA (and the nav logo mark) must read as
     a glossy red plate in both themes; if it borrowed the swapped tokens,
     dark mode would hand it a duller variant as the gradient's top edge and
     go muddy against the dark page. */
  --clay-btn-hi: #FF8267;
  --clay-btn-lo: #C93325;

  /* fixed phosphor tones for the hero-name matrix glitch — a deliberate
     special-moment accent, not part of the base palette, so it doesn't
     swap with theme either. Signal-red phosphor, tuned to stay legible
     and glow cleanly against a true AMOLED black rather than washing out. */
  --matrix-red:      #FF2E3F;
  --matrix-red-dark: #3D0007;
  --matrix-glow:      rgba(255,46,63,.55);
  --matrix-glow-soft: rgba(255,46,63,.26);
  --matrix-scan:       rgba(255,214,204,.95);

  color-scheme: light;
}

/* ---------- 1b. DARK THEME ---------- */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:      #000000;
    --paper-2:    #0A0908;
    --paper-3:    #131110;
    --ink:        #F1E9D8;
    --ink-soft:   #C9BFA9;
    --ink-mute:   #948870;
    --line:       #F1E9D8;

    --red:        #E8382D;
    --red-dark:   #FF9186;
    --red-tint:   #2C0C09;
    --clay:       #FF5B47;
    --clay-dark:  #FF8A76;
    --clay-light: #B32A1C;
    --clay-tint:  #2E0F0A;
    --clay-shade: #3A0C08;
    --letter-outline: #050403;
    --green:      #4FD8D8;
    --green-dark: #96EFE9;
    --green-tint: #0E2626;
    --red-active:      #FF5A45;
    --red-active-dark: #FFAE9C;
    --red-active-tint: #341008;
    --blue:       #8FA8E8;
    --blue-light: #1B2138;

    --glass:      rgba(0,0,0,.88);
    --glass-hi:   rgba(0,0,0,.95);

    color-scheme: dark;
  }
}
:root[data-theme="dark"]{
  --paper:      #000000;
  --paper-2:    #0A0908;
  --paper-3:    #131110;
  --ink:        #F1E9D8;
  --ink-soft:   #C9BFA9;
  --ink-mute:   #948870;
  --line:       #F1E9D8;

  --red:        #E8382D;
  --red-dark:   #FF9186;
  --red-tint:   #2C0C09;
  --clay:       #FF5B47;
  --clay-dark:  #FF8A76;
  --clay-light: #B32A1C;
  --clay-tint:  #2E0F0A;
  --clay-shade: #3A0C08;
  --letter-outline: #050403;
  --green:      #4FD8D8;
  --green-dark: #96EFE9;
  --green-tint: #0E2626;
  --red-active:      #FF5A45;
  --red-active-dark: #FFAE9C;
  --red-active-tint: #341008;
  --blue:       #8FA8E8;
  --blue-light: #1B2138;

  --glass:      rgba(23,20,15,.92);
  --glass-hi:   rgba(23,20,15,.97);

  color-scheme: dark;
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after{ box-sizing: border-box; margin:0; padding:0; }
html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; scroll-padding-top: var(--nav-offset, 78px); }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *, *::before, *::after{ animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important; scroll-behavior:auto !important; }
}
body{
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  overflow-x: hidden;
  position: relative;
  transition: background .3s ease, color .3s ease;
}
img,svg{ display:block; max-width:100%; }
img{ height:auto; }
a{ color:inherit; text-decoration:none; }
ul,ol{ list-style:none; }
button{ font:inherit; color:inherit; background:none; border:none; cursor:pointer; }
h1,h2,h3,h4{ font-family:var(--font-display); font-weight:700; text-wrap:balance; line-height:1.02; letter-spacing:-0.01em; }
/* Subheads use body font at weight 700 — display face reserved for h1/h2 (typography fix) */
h3,h4{ font-family:var(--font-body); font-weight:700; line-height:1.2; letter-spacing:-.005em; }
::selection{ background: var(--ink); color: var(--paper); }
:focus-visible{ outline: 3px solid var(--blue); outline-offset: 3px; border-radius: 4px; }

/* paper grain — subtle, no images */
body::before{
  content:"";
  position:fixed; inset:0; z-index:0; pointer-events:none;
  opacity:.5; mix-blend-mode:multiply;
  background-image:
    radial-gradient(rgba(20,18,15,.05) .6px, transparent .6px),
    radial-gradient(rgba(20,18,15,.04) .6px, transparent .6px);
  background-size: 3px 3px, 5px 5px;
  background-position: 0 0, 1.5px 1.5px;
}
:root[data-theme="dark"] body::before{ mix-blend-mode:screen; opacity:.32; }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) body::before{ mix-blend-mode:screen; opacity:.32; }
}

.wrap{ position:relative; z-index:1; }
.vh{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

/* ---------- 3. UTILITIES ---------- */
/* .lbl — THE single uppercase-mono label class. No variants. */
.lbl{
  font-family:var(--font-mono); font-size:.7rem; text-transform:uppercase;
  letter-spacing:.06em; color:var(--ink-mute); display:block;
}
.lbl--accent{ color:var(--red); }

.eyebrow{
  display:inline-flex; align-items:center; gap:.55em;
  font-family:var(--font-mono); font-size:.78rem; letter-spacing:.06em; text-transform:uppercase;
  color: var(--ink-soft);
}
.dot{ width:7px; height:7px; border-radius:50%; background:var(--green); box-shadow:0 0 0 3px rgba(30,122,76,.18); flex:none; }
.dot--live{ animation: pulse 2.2s ease-in-out infinite; }
@keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }

.chips{ display:flex; flex-wrap:wrap; gap:.5rem; list-style:none; }
.chip{
  font-family:var(--font-mono); font-size:.72rem; letter-spacing:.02em;
  padding:.4em .8em; border:var(--border-hair) solid var(--ink); border-radius:var(--r-pill);
  background:var(--paper-3);
  transition: border-color .18s ease, transform .18s ease, background .18s ease;
}
@media (hover:hover){
  .chip:hover{
    border-color: color-mix(in srgb, var(--clay) 55%, var(--ink));
    background: var(--clay-tint);
    transform: translateY(-1px);
  }
}

.stamp{
  font-family:var(--font-mono); font-weight:700; font-size:.68rem; letter-spacing:.08em; text-transform:uppercase;
  padding:.32em .75em; border:var(--border-w) solid currentColor; border-radius:var(--r-sm);
  display:inline-block;
}
.stamp--live       { color:var(--red-active-dark); background:var(--red-active-tint); }
.stamp--wip        { color:var(--clay-dark);  background:var(--clay-tint); }
.stamp--confirmed  { color:var(--red-active-dark); background:var(--red-active-tint); }
.stamp--probable   { color:var(--clay-dark);  background:var(--clay-tint); }
.stamp--hypothesis { color:var(--red-dark);   background:var(--red-tint); }

/* ---------- 3b. SIGNATURE MOTIF — redaction bar ----------
   The one visual device unique to this site: a disclosure portfolio that
   cannot name targets. Redaction becomes the brand mark. */
.redact{
  display:inline-block; position:relative;
  background:var(--ink); color:transparent;
  padding:0 .35em; border-radius:2px;
  user-select:none;
}
.redact::after{
  content:attr(data-note); position:absolute; inset:0;
  display:grid; place-items:center;
  font-family:var(--font-mono); font-size:.62em; letter-spacing:.1em;
  color:var(--paper); text-transform:uppercase;
}
.rule-redact{
  height:10px; border:none; border-radius:2px;
  background: repeating-linear-gradient(90deg, var(--ink) 0 42px, transparent 42px 52px);
  opacity:.9;
}

/* ---------- 3c. PROOF PRIMITIVE ---------- */
.proof{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border:var(--border-w) solid var(--ink); border-radius:var(--r-md);
  background:var(--paper-3); box-shadow:var(--sh-2); overflow:hidden;
}
.proof > div{ padding:1.15rem 1.2rem; border-left:var(--border-w) solid var(--ink); }
.proof > div:first-child{ border-left:none; }
.proof__n{
  font-family:var(--font-display); font-size:clamp(1.5rem,3.4vw,2.1rem);
  line-height:1; letter-spacing:-.02em; color:var(--ink); display:block;
}
.proof__n[data-pending]{ color:var(--ink-mute); }
.proof__l{ font-family:var(--font-mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-mute); margin-top:.45em; display:block; }
@media (max-width:720px){
  .proof > div{ border-left:none; border-top:var(--border-w) solid var(--ink); }
  .proof > div:first-child{ border-top:none; }
}

/* evidence slot — visible placeholder for artifacts not yet added */
.ev{
  margin-top:1rem; border:var(--border-w) dashed var(--ink-mute); border-radius:var(--r-md);
  background:var(--paper-2); padding:1.1rem 1.2rem;
}
.ev figure{ margin:0; }
.ev img{ width:100%; border:var(--border-hair) solid var(--ink); border-radius:var(--r-sm); }
.ev figcaption{ font-family:var(--font-mono); font-size:.72rem; color:var(--ink-mute); margin-top:.6rem; }
.ev__empty{ font-family:var(--font-mono); font-size:.76rem; color:var(--ink-mute); }
.ev__empty b{ color:var(--ink-soft); font-weight:500; }

/* ---------- 4. NAV ---------- */
.nav{
  position:fixed; top:14px; left:50%; translate:-50% 0; z-index:100;
  width:min(1180px, calc(100% - 28px));
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
  padding:.55rem .6rem .55rem 1rem;
  border:var(--border-w) solid var(--ink);
  border-radius:var(--r-lg);
  background: var(--glass);
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  box-shadow: var(--sh-2);
  transition: box-shadow .3s ease, background .3s ease;
}
/* The bar must NOT move on scroll. `translate` and `transform` are separate
   properties that BOTH apply, so a `transform: translate(-50%, …)` here would
   stack with the `translate:-50% 0` above and shift the bar a full -100% —
   half its own width off-screen. Only paint properties change on scroll. */
.nav.is-scrolled{ box-shadow: var(--sh-1); background: var(--glass-hi); }

.brand{ display:flex; align-items:center; gap:.55rem; font-family:var(--font-display); font-size:1.02rem; letter-spacing:-.01em; position:relative; }
.brand__mark{ width:30px; height:30px; display:grid; place-items:center; border:var(--border-w) solid var(--ink); border-radius:8px; background:linear-gradient(180deg, var(--clay-btn-hi), var(--clay-btn-lo)); box-shadow:var(--sh-1); color:#14120F; }
.brand__mark svg{ width:16px; height:16px; }
.brand small{ display:block; font-family:var(--font-mono); font-size:.6rem; font-weight:400; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-soft); }

.nav__links{ display:flex; align-items:center; gap:.15rem; position:relative; }
.nav__links a{
  font-family:var(--font-mono); font-size:.78rem; letter-spacing:.02em; text-transform:uppercase;
  padding:.55em .85em; border-radius:var(--r-pill); position:relative;
  transition: background .2s ease, color .2s ease;
}
.nav__links a:hover{ background: color-mix(in srgb, var(--ink) 8%, transparent); }
.nav__links a[aria-current="true"]{ background:var(--ink); color:var(--paper); }

.nav__right{ display:flex; align-items:center; gap:.5rem; }

.nav__cta{
  font-family:var(--font-mono); font-size:.78rem; font-weight:500; letter-spacing:.02em;
  padding:.6em 1.05em; border:var(--border-w) solid var(--ink); border-radius:var(--r-pill);
  background:var(--clay); color:#14120F; box-shadow: var(--sh-1);
  transition: transform .15s ease, box-shadow .15s ease;
}
.nav__cta:hover{ transform: translate(-1px,-1px); box-shadow: var(--sh-2); }
.nav__cta:active{ transform: translate(1px,1px); box-shadow: var(--sh-press); }

.theme{
  width:38px; height:38px; flex:none; display:grid; place-items:center;
  border:var(--border-w) solid var(--ink); border-radius:9px;
  background:var(--paper-3); box-shadow:var(--sh-1);
  transition: transform .15s ease, box-shadow .15s ease;
}
.theme:hover{ transform:translate(-1px,-1px); box-shadow:var(--sh-2); }
.theme:active{ transform:translate(1px,1px); box-shadow:var(--sh-press); }
.theme svg{ width:17px; height:17px; }
/* The icon depicts the CURRENT state, matching the toggle-button pattern in
   main.js: the name is static ("Dark theme") and aria-pressed carries on/off,
   so the glyph shows what is active — sun while light, moon while dark. */
.theme .theme__sun{ display:block; }
.theme .theme__moon{ display:none; }
:root[data-theme="dark"] .theme .theme__sun{ display:none; }
:root[data-theme="dark"] .theme .theme__moon{ display:block; }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .theme .theme__sun{ display:none; }
  :root:not([data-theme="light"]) .theme .theme__moon{ display:block; }
}

.nav__burger{ display:none; width:38px; height:38px; border:var(--border-w) solid var(--ink); border-radius:9px; background:var(--paper-3); align-items:center; justify-content:center; box-shadow:var(--sh-1); }
.nav__burger span, .nav__burger span::before, .nav__burger span::after{
  content:""; display:block; width:18px; height:2.5px; background:var(--ink); position:relative; transition:.25s ease;
}
.nav__burger span::before{ position:absolute; top:-6px; }
.nav__burger span::after{ position:absolute; top:6px; }
.nav__burger[aria-expanded="true"] span{ background:transparent; }
.nav__burger[aria-expanded="true"] span::before{ top:0; transform:rotate(45deg); }
.nav__burger[aria-expanded="true"] span::after{ top:0; transform:rotate(-45deg); }

.nav__sheet{
  position:fixed; inset:0; z-index:99; display:none;
  background: color-mix(in srgb, var(--ink) 34%, transparent);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.nav__sheet.open{ display:block; }
.nav__sheet__panel{
  position:absolute; top:78px; left:14px; right:14px;
  background:var(--glass-hi);
  border:var(--border-w) solid var(--ink); border-radius:var(--r-lg); box-shadow:var(--sh-2);
  padding:.75rem; display:flex; flex-direction:column; gap:.15rem;
  max-height:calc(100dvh - 100px); overflow-y:auto;
}
.nav__sheet__panel a{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:.03em; padding:.95em 1em; border-radius:var(--r-md); font-size:.9rem; }
.nav__sheet__panel a:hover{ background: color-mix(in srgb, var(--ink) 7%, transparent); }
.nav__sheet__panel a[aria-current="true"]{ background:var(--ink); color:var(--paper); }

@media (max-width: 900px){
  .nav__links{ display:none; }
  .nav__burger{ display:flex; }
  .nav__cta{ display:none; }
}

/* ---------- 5. SECTION SCAFFOLD ---------- */
main{ padding-top: 96px; }
.section{ padding: clamp(52px, 8vw, 108px) var(--edge); position:relative; }
.section__in{ max-width:1180px; margin-inline:auto; }

.kicker{
  display:flex; align-items:flex-start; gap:1rem; margin-bottom: clamp(28px,4vw,44px);
}
.kicker__n{
  font-family:var(--font-mono); font-size:.85rem; font-weight:700; color:var(--paper);
  background:var(--ink); width:2.5em; height:2.5em; flex:none; display:grid; place-items:center;
  border-radius:var(--r-sm);
}
.kicker h2{ font-size:clamp(1.7rem, 3.4vw, 2.6rem); font-family:var(--font-display); }
.kicker p{ color:var(--ink-soft); font-size:.98rem; margin-top:.35rem; max-width:56ch; }

/* ---------- 6. HERO ---------- */
.hero{
  padding: clamp(28px,4vw,52px) var(--edge) clamp(56px,8vw,88px);
  position:relative;
}
.hero__badge{
  /* Bound to --red-active (not the general --red accent) on purpose: this
     badge and the project "Active" stamps both say the same thing —
     something is live right now — so they share the one brighter signal-red
     instead of two slightly different reds. */
  display:inline-flex; align-items:center; gap:.65em;
  font-family:var(--font-mono); font-size:.78rem; letter-spacing:.03em;
  background: var(--red-active-tint); color:var(--red-active-dark);
  padding:.6em 1.15em .6em .95em; border:var(--border-hair) solid color-mix(in srgb, var(--red-active) 40%, transparent);
  border-radius:var(--r-pill);
  box-shadow: 0 1px 2px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.25);
  margin-bottom: 1.6rem;
  transition: transform .2s ease, box-shadow .2s ease;
}
.hero__badge:hover{
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.1), inset 0 1px 0 rgba(255,255,255,.25);
}
.hero__badge .dot{ background: var(--red-active); box-shadow: 0 0 0 3px color-mix(in srgb, var(--red-active) 22%, transparent); }

.hero h1{
  font-size: clamp(3rem, 11vw, 8rem);
  letter-spacing:-.02em;
  font-family:var(--font-display);
  font-weight:800;
}
.hero__sub{
  font-family:var(--font-mono); text-transform:uppercase; letter-spacing:.05em;
  font-size:clamp(.82rem,1.6vw,1rem); color:var(--ink-soft); margin-top:.9rem;
}
.hero__sub b{ color:var(--red); font-weight:600; }

.hero__lede{
  max-width:60ch; font-size:clamp(1.02rem,1.6vw,1.2rem); color:var(--ink-soft);
  margin-top:1.6rem;
}
.hero__lede strong{ color:var(--ink); font-weight:600; }

.hero__cta{ display:flex; flex-wrap:wrap; gap:.9rem; margin-top:2.2rem; }

.btn{
  display:inline-flex; align-items:center; gap:.6em;
  font-family:var(--font-mono); font-size:.9rem; font-weight:500; letter-spacing:.01em;
  padding:.95em 1.5em; border:var(--border-w) solid var(--ink); border-radius:var(--r-pill);
  transition: transform .15s cubic-bezier(.2,.8,.3,1.3), box-shadow .15s ease, background .2s ease;
  position:relative;
}
.btn svg{ width:16px; height:16px; transition:transform .2s ease; }
.btn--clay{
  background: linear-gradient(180deg, var(--clay-btn-hi), var(--clay-btn-lo)); color:#14120F;
  box-shadow: var(--sh-2), inset 0 1px 0 rgba(255,255,255,.6);
}
.btn--clay:hover{ transform: translate(-2px,-2px); box-shadow: var(--sh-hero), inset 0 1px 0 rgba(255,255,255,.6); }
.btn--clay:hover svg{ transform: translateX(3px); }
.btn--clay:active{ transform: translate(1px,1px); box-shadow: var(--sh-press), inset 0 1px 0 rgba(255,255,255,.4); }

.btn--glass{
  background: var(--paper-3);
  box-shadow: var(--sh-1);
}
.btn--glass:hover{ transform: translate(-2px,-2px); box-shadow: var(--sh-2); }
.btn--glass:active{ transform: translate(1px,1px); box-shadow: var(--sh-press); }

/* hero proof — the ONE element allowed --sh-hero */
.hero__proof{ margin-top: clamp(34px,5vw,52px); box-shadow: var(--sh-hero); }

.hero__coords{
  margin-top: 1.1rem;
  display:grid; grid-template-columns: repeat(4,1fr);
  border:var(--border-w) solid var(--ink); border-radius:var(--r-md);
  background:var(--paper-3); box-shadow: var(--sh-1);
  overflow:hidden;
}
.hero__coords div{ padding:1rem 1.1rem; border-left:var(--border-w) solid var(--ink); }
.hero__coords div:first-child{ border-left:none; }
.hero__coords dt{ font-family:var(--font-mono); font-size:.66rem; text-transform:uppercase; letter-spacing:.08em; color:var(--ink-mute); margin-bottom:.3em; }
.hero__coords dd{ font-family:var(--font-mono); font-size:.86rem; font-weight:500; }

@media (max-width: 720px){
  .hero__coords{ grid-template-columns: 1fr 1fr; }
  .hero__coords div:nth-child(3){ border-left:none; }
}

.hero__scroll{
  position:absolute; right:var(--edge); bottom:14px;
  font-family:var(--font-mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.1em; color:var(--ink-mute);
  display:flex; align-items:center; gap:.6em; writing-mode:vertical-rl;
}
.hero__scroll span{ width:1px; height:34px; background:var(--ink-mute); display:block; animation: scrollcue 1.8s ease-in-out infinite; }
@keyframes scrollcue{ 0%,100%{ transform:scaleY(1); opacity:.4; } 50%{ transform:scaleY(.5); opacity:1; } }
@media (max-width:900px){ .hero__scroll{ display:none; } }

/* ---------- 7. CARD PRIMITIVES ---------- */
.card{
  background: var(--paper-3);
  border: var(--border-w) solid var(--ink);
  border-radius: var(--r-md);
  box-shadow: var(--sh-2);
  position:relative;
}
.card--fold::before{ /* skeuomorphic folded corner */
  content:""; position:absolute; top:-1px; right:-1px; width:26px; height:26px;
  background: linear-gradient(135deg, transparent 50%, var(--paper) 50%);
  border-left:var(--border-w) solid var(--ink); border-bottom:var(--border-w) solid var(--ink);
  border-radius: 0 var(--r-md) 0 8px;
}
/* Reveal-on-scroll is opt-in via the `js` class that the head script adds
   before first paint. Without JavaScript the .in class is never applied, so
   scoping the hidden state this way is what keeps the page from rendering
   completely blank. Never move opacity:0 back onto the bare .reveal. */
:root.js .reveal{ opacity:0; transform: translateY(22px); transition: opacity .6s cubic-bezier(.2,.7,.2,1), transform .6s cubic-bezier(.2,.7,.2,1); }
:root.js .reveal.in{ opacity:1; transform: none; }

/* ---------- 8. ABOUT ---------- */
.about__grid{ display:grid; grid-template-columns: 1.5fr 1fr; gap: clamp(24px,4vw,40px); align-items:start; }
.about__main p{ margin-bottom:1.1rem; color:var(--ink-soft); font-size:1.02rem; max-width:66ch; }
.about__main p.first::first-letter{
  font-family:var(--font-display); font-size:3.6rem; float:left; line-height:.8; padding:.06em .12em 0 0; color:var(--red);
}
.about__main p:last-child{ margin-bottom:0; }
.about__main strong{ color:var(--ink); font-weight:600; }

.rig{ padding:1.3rem; }
.rig__head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:1rem; padding-bottom:.85rem; border-bottom: var(--border-w) dashed var(--ink-mute); }
.rig__live{ display:flex; align-items:center; gap:.4em; font-family:var(--font-mono); font-size:.7rem; color:var(--green-dark); }
.rig dl{ display:grid; gap:.65rem; }
.rig dl div{ display:flex; justify-content:space-between; gap:1rem; font-size:.86rem; }
.rig dl dt{ color:var(--ink-mute); font-family:var(--font-mono); font-size:.76rem; }
.rig dl dd{ text-align:right; font-weight:500; }
.rig dl div.on dd{ color:var(--red); }

.domains{ display:grid; grid-template-columns: repeat(2,1fr); gap: 1.1rem; margin-top: clamp(28px,4vw,44px); }
.dom{ padding: 1.4rem; box-shadow: var(--sh-1); }
.dom h3{ font-size:1.15rem; margin:.5rem 0 .55rem; }
.dom p{ color:var(--ink-soft); font-size:.92rem; }

@media (max-width: 920px){ .about__grid{ grid-template-columns:1fr; } .domains{ grid-template-columns:1fr; } }

/* ---------- 9. SKILLS ---------- */
.legend{ display:flex; flex-wrap:wrap; gap:1.4rem; margin-bottom:1.6rem; font-family:var(--font-mono); font-size:.76rem; color:var(--ink-soft); }
.legend span{ display:inline-flex; align-items:center; gap:.4em; }
.seg{ width:9px; height:9px; border:var(--border-hair) solid var(--ink); border-radius:2px; background:transparent; display:inline-block; }
.seg.on{ background:var(--blue); }

.sys{
  display:grid; grid-template-columns:repeat(3,1fr); gap:1.1rem;
  padding: 1.4rem; border:var(--border-w) solid var(--ink); border-radius:var(--r-lg);
  background:
    linear-gradient(var(--blue-light) 1px, transparent 1px) 0 0 / 100% 28px,
    linear-gradient(90deg, var(--blue-light) 1px, transparent 1px) 0 0 / 28px 100%,
    var(--paper-3);
  box-shadow: var(--sh-2);
}
.mod{ background:var(--paper-3); border:var(--border-hair) solid var(--ink); border-radius:var(--r-sm); padding:1.05rem; }
.mod__head{ display:flex; align-items:baseline; justify-content:space-between; gap:.5rem; margin-bottom:.35rem; }
.mod .lbl{ font-size:.66rem; margin-bottom:.25rem; }
.mod h3{ font-size:1.02rem; }
.mod__lvl{ font-family:var(--font-mono); font-size:.68rem; color:var(--blue); white-space:nowrap; }
.meter{ display:flex; gap:4px; margin:.6rem 0 .8rem; }
.meter i{ height:6px; flex:1; border:var(--border-hair) solid var(--ink); border-radius:3px; background:transparent; }
.meter i.on{ background:var(--blue); }
.mod .chips{ gap:.4rem; }
.mod .chip{ font-size:.66rem; padding:.3em .6em; }

.sysnote{ margin-top:1.2rem; font-family:var(--font-mono); font-size:.8rem; color:var(--ink-mute); }

@media (max-width: 920px){ .sys{ grid-template-columns:1fr 1fr; } }
@media (max-width: 620px){ .sys{ grid-template-columns:1fr; } }

/* ---------- 10. PROJECTS — case files ---------- */
.files{ display:flex; flex-direction:column; gap:1rem; }
.file{
  border:var(--border-w) solid var(--ink); border-radius:var(--r-md);
  background:var(--paper-3); box-shadow: var(--sh-2);
  overflow:hidden;
}
.file summary{
  list-style:none; cursor:pointer; padding: 1.2rem 1.3rem;
  display:grid; grid-template-columns:auto 1fr auto; gap:1rem; align-items:flex-start;
  position:relative;
}
.file summary::-webkit-details-marker{ display:none; }
.file summary::marker{ content:""; }
.file__id{ font-family:var(--font-mono); font-weight:700; font-size:.82rem; color:var(--ink-mute); padding-top:.15em; }
.file__head{ display:flex; align-items:center; gap:.8rem; flex-wrap:wrap; margin-bottom:.4rem; }
.file__head h3{ font-size:1.18rem; }
/* The middle grid column of `.file summary`. Needs min-width:0 so a long
   unbroken summary line shrinks instead of pushing the chevron off the row. */
.file__body-sum{ display:block; min-width:0; }
.file__sum{ display:block; color:var(--ink-soft); font-size:.92rem; margin-bottom:.65rem; max-width:70ch; }
.file__stats{ display:flex; flex-wrap:wrap; gap:1.4rem; font-family:var(--font-mono); font-size:.72rem; color:var(--ink-mute); }
.file__stats em{ display:block; font-style:normal; color:var(--ink-mute); font-size:.65rem; text-transform:uppercase; letter-spacing:.05em; }
.file__stats b{ display:block; color:var(--ink); font-weight:500; font-size:.78rem; margin-top:.15em; }
.file__x{ width:34px; height:34px; border:var(--border-hair) solid var(--ink); border-radius:50%; display:grid; place-items:center; transition: transform .3s ease, background .2s ease; flex:none; }
.file[open] .file__x{ background:var(--clay); color:#14120F; transform:rotate(180deg); }
.file__x svg{ width:15px; height:15px; }

.file__body{ padding: 0 1.3rem 1.4rem; border-top: var(--border-w) dashed var(--ink-mute); }
.blk{ padding-top:1.1rem; }
.blk h4{ font-family:var(--font-mono); font-weight:600; font-size:.72rem; text-transform:uppercase; letter-spacing:.06em; color:var(--red); margin-bottom:.4rem; }
.blk p{ color:var(--ink-soft); font-size:.92rem; max-width:75ch; }
.blk .chips{ margin-top:.2rem; }

.files__tools{ display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1rem; }
.files__filters{ display:flex; flex-wrap:wrap; gap:.45rem; }
.filter{
  font-family:var(--font-mono); font-size:.72rem; letter-spacing:.02em;
  padding:.45em .9em; border:var(--border-hair) solid var(--ink); border-radius:var(--r-pill);
  background:var(--paper-3); transition:background .2s ease, color .2s ease;
}
.filter[aria-pressed="true"]{ background:var(--ink); color:var(--paper); }
.file[hidden]{ display:none; }
.expand-all{
  font-family:var(--font-mono); font-size:.72rem;
  padding:.45em .9em; border:var(--border-hair) solid var(--ink); border-radius:var(--r-pill);
  background:var(--paper-3);
}

@media (max-width: 640px){
  .file summary{ grid-template-columns:1fr auto; }
  .file__id{ display:none; }
}

/* ---------- 11. EXPERIENCE — mission log ---------- */
.log{ position:relative; padding-left: 2.2rem; }
.log::before{ content:""; position:absolute; left:.5rem; top:.4rem; bottom:.4rem; width:var(--border-w); background: repeating-linear-gradient(var(--ink),var(--ink) 6px, transparent 6px, transparent 12px); }
.log__i{ position:relative; padding-bottom:2.1rem; }
.log__i:last-child{ padding-bottom:0; }
.log__mark{ position:absolute; left:-2.2rem; top:.25rem; width:16px; height:16px; border-radius:50%; background:var(--paper-3); border:var(--border-w) solid var(--ink); }
.log__meta{ font-family:var(--font-mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-mute); margin-bottom:.4rem; display:flex; gap:.6rem; flex-wrap:wrap; align-items:center; }
.log__body{ background:var(--paper-3); border:var(--border-hair) solid var(--ink); border-radius:var(--r-md); padding:1.1rem 1.3rem; box-shadow:var(--sh-1); }
.log__body h3{ font-size:1.05rem; margin-bottom:.5rem; }
.log__body p{ color:var(--ink-soft); font-size:.9rem; margin-bottom:.75rem; max-width:72ch; }

/* ---------- 12. RESEARCH ETHIC ---------- */
.ethic{ display:grid; grid-template-columns:1.4fr 1fr; gap:2rem; align-items:start; }
.ethic__txt p{ color:var(--ink-soft); margin-bottom:1rem; font-size:1rem; max-width:66ch; }
.ethic__txt strong{ color:var(--ink); }

.grades{ display:flex; flex-direction:column; gap:.85rem; }
.grade{ padding:1rem 1.1rem; border:var(--border-hair) solid var(--ink); border-radius:var(--r-sm); background:var(--paper-3); }
.grade__top{ display:flex; align-items:center; justify-content:space-between; gap:.6rem; margin-bottom:.5rem; }
.grade__pct{ font-family:var(--font-mono); font-size:.72rem; color:var(--ink-mute); }
.grade__d{ font-size:.8rem; color:var(--ink-mute); }
.grade__bar{ height:7px; border:var(--border-hair) solid var(--ink); border-radius:4px; overflow:hidden; background:var(--paper-2); margin-top:.5rem; }
.grade__bar i{ display:block; height:100%; background:var(--red-active); transition:width 1s cubic-bezier(.2,.7,.2,1); }
.grade--p .grade__bar i{ background:var(--clay-dark); }
.grade--h .grade__bar i{ background:var(--red); }
/* Fill widths live here, not in a style attribute — inline styles are blocked
   by style-src 'self' in the CSP. Bars are filled by default so they still
   read correctly with JavaScript off; :root.js zeroes them so they can
   animate in on scroll. */
.grade--c .grade__bar i{ width:100%; }
.grade--p .grade__bar i{ width:62%; }
.grade--h .grade__bar i{ width:28%; }
:root.js .grade__bar i{ width:0; }
:root.js .grade--c.in .grade__bar i{ width:100%; }
:root.js .grade--p.in .grade__bar i{ width:62%; }
:root.js .grade--h.in .grade__bar i{ width:28%; }

.notes{ display:grid; grid-template-columns:1fr 1fr; gap:1rem; margin-top:2rem; }
.note{ padding:1.1rem 1.2rem; box-shadow:var(--sh-1); }
.note .lbl{ margin-bottom:.5rem; }
.note p{ font-size:.88rem; color:var(--ink-soft); }

.exploring{ margin-top:2rem; }
.exploring .lbl{ margin-bottom:.7rem; }

@media (max-width:920px){ .ethic{ grid-template-columns:1fr; } .notes{ grid-template-columns:1fr; } }

/* ---------- 13. CONTACT ---------- */
.contact-close{ font-family:var(--font-display); font-size:clamp(2rem,5.4vw,3.6rem); margin-bottom:1.4rem; line-height:1.02; }
.contact-close span{ color:var(--red); }

.out{ display:grid; grid-template-columns:1.2fr 1fr; gap:1.4rem; align-items:stretch; }
.out__main{ padding:1.6rem; display:flex; flex-direction:column; gap:1rem; }
.badge-open{ display:inline-flex; align-items:center; gap:.5em; font-family:var(--font-mono); font-size:.76rem; padding:.4em .85em; border:var(--border-hair) solid var(--ink); border-radius:var(--r-pill); width:fit-content; }
.out__mail{ display:flex; align-items:center; gap:.8rem; flex-wrap:wrap; }
.out__mail a{ font-family:var(--font-mono); font-size:clamp(1rem,2.4vw,1.3rem); font-weight:500; border-bottom:var(--border-w) solid var(--ink); padding-bottom:.15em; overflow-wrap:anywhere; }
.copy-btn{ display:inline-flex; align-items:center; justify-content:center; gap:.4em; font-family:var(--font-mono); font-size:.76rem; padding:.5em .9em; min-height:44px; min-width:44px; border:var(--border-hair) solid var(--ink); border-radius:var(--r-pill); background:var(--paper-2); transition:transform .15s ease, background .2s ease; }
.copy-btn:hover{ background:var(--clay-btn-hi); color:#14120F; transform:translateY(-1px); }
.copy-btn svg{ width:13px; height:13px; }
.out__note{ font-size:.82rem; color:var(--ink-mute); }
.out__fallback{ display:flex; gap:.5rem; align-items:center; }
.out__fallback input{
  font-family:var(--font-mono); font-size:.82rem; padding:.5em .7em; flex:1; min-width:0;
  border:var(--border-hair) solid var(--ink); border-radius:var(--r-sm);
  background:var(--paper-2); color:var(--ink);
}

.links{ display:grid; gap: .7rem; }
.links a{
  display:flex; align-items:center; gap:.9rem; padding:1rem 1.1rem;
  border:var(--border-hair) solid var(--ink); border-radius:var(--r-md);
  background: var(--paper-3);
  transition: transform .18s ease, box-shadow .18s ease;
}
.links a:hover{ transform: translate(-2px,-2px); box-shadow: var(--sh-1); }
.links__i{ width:34px; height:34px; border-radius:50%; border:var(--border-hair) solid var(--ink); display:grid; place-items:center; flex:none; background:var(--paper-2); }
.links__i svg{ width:16px; height:16px; }
.links__t{ flex:1; display:flex; flex-direction:column; }
.links__t b{ font-size:.92rem; }
.links__t i{ font-style:normal; font-family:var(--font-mono); font-size:.72rem; color:var(--ink-mute); }
.links__a svg{ width:15px; height:15px; opacity:.55; }

@media (max-width:860px){ .out{ grid-template-columns:1fr; } }

.foot{ margin-top: clamp(48px,7vw,72px); padding-top:1.6rem; border-top:var(--border-w) dashed var(--ink-mute); display:flex; justify-content:space-between; flex-wrap:wrap; gap:.6rem; align-items:center; }
.foot p{ font-size:.8rem; color:var(--ink-mute); font-family:var(--font-mono); }
.foot b{ color:var(--ink); }

/* ---------- 14. TOAST ---------- */
.toast{
  position:fixed; left:50%; bottom:24px; translate:-50% 12px;
  font-family:var(--font-mono); font-size:.82rem;
  background:var(--ink); color:var(--paper); padding:.7em 1.2em;
  border-radius:var(--r-pill); box-shadow:var(--sh-1);
  opacity:0; pointer-events:none; transition:opacity .3s ease, translate .3s ease; z-index:200;
  max-width:calc(100% - 32px); text-align:center;
}
.toast.show{ opacity:1; translate:-50% 0; }

/* ---------- 15. MISC ---------- */
.skip{ position:absolute; left:-999px; top:0; background:var(--ink); color:var(--paper); padding:.8em 1.2em; z-index:999; border-radius:0 0 var(--r-sm) 0; }
.skip:focus{ left:0; top:0; }

/* ---------- 16. PRINT ---------- */
@media print{
  .nav,.nav__sheet,.hero__scroll,.theme,.toast,.files__tools,.skip{ display:none !important; }
  body::before{ display:none; }
  body{ background:#fff; color:#000; }
  main{ padding-top:0; }
  .card,.file,.log__body,.proof,.hero__coords{ box-shadow:none !important; break-inside:avoid; }
  .file details{ display:block; }
  .file__body{ display:block !important; }
  .reveal{ opacity:1 !important; transform:none !important; }
  a[href^="http"]::after{ content:" (" attr(href) ")"; font-size:.7em; word-break:break-all; }
}

/* ══════════════════════════════════════════════════════════════════════════
   PRELOADER — brand mark + progress line, hidden entirely without JS.
   ══════════════════════════════════════════════════════════════════════════ */
.pre{ display:none; }
:root.js .pre{
  display:grid; place-items:center;
  position:fixed; inset:0; z-index:200;
  background:var(--paper);
  transition: opacity .5s ease, visibility .5s ease;
}
:root.js .pre.is-done{ opacity:0; visibility:hidden; pointer-events:none; }
.pre__inner{ display:grid; justify-items:center; gap:22px; }

.pre__txt{
  font-family:var(--font-mono); font-size:.74rem; letter-spacing:.42em;
  text-indent:.42em; color:var(--ink-mute); text-transform:uppercase;
}
.pre__track{
  width:170px; height:2px; background:var(--line); overflow:hidden; border-radius:2px;
}
.pre__track i{
  display:block; height:100%; width:0; background:var(--ink);
  transition: width .28s ease;
}

/* ══════════════════════════════════════════════════════════════════════════
   3D NAME — extrusion is built from stacked text-shadows (cheap, no WebGL);
   the stage tilts with the pointer via --rx/--ry set in JS.
   ══════════════════════════════════════════════════════════════════════════ */
.hero__name{ perspective: 900px; margin:0; }
.hero__name__stage{
  /* inline-block, not block: the stage must shrink to the width of the word.
     A full-bleed stage rotates about the viewport centre and swings its near
     edge off-screen, where overflow-x:hidden silently guillotines the S. */
  display:inline-block; max-width:100%;
  transform-style:preserve-3d;
  transform: rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transition: transform .35s cubic-bezier(.2,.7,.3,1);
  will-change: transform;
}
.hero__name__3d{
  display:inline-flex; flex-wrap:wrap; gap:0;
  font-family:var(--font-display);
  font-weight:800;
  font-size: clamp(3rem, 11vw, 8rem);
  line-height:1.02; letter-spacing:-.02em;
  transform-style:preserve-3d;
}
.hero__name__3d .ltr{
  display:inline-block;
  transform-style:preserve-3d;
  /* --clay-dark is the theme-aware "readable" brass — darker brass on the
     light-mode cream paper, lighter brass on the dark-mode espresso paper.
     (--clay-light is the opposite: it's tuned for button gradients, so on
     dark mode it goes darker — which is why the name was going murky
     against the dark background before.) */
  color: var(--clay-dark);
  /* Thin dark border on both the outer silhouette and the inner counters
     ("holes") — text-stroke traces the full glyph outline, not just the
     perimeter, so A/S/V/N get an inner ring too. Fixed tone, not themed,
     so it reads as a dark border in both light and dark mode. */
  -webkit-text-stroke: 1.3px var(--letter-outline);
  paint-order: stroke fill;
  /* Extruded side: 4 offset copies stepping back-right in a fixed bevel
     tone, then a soft contact shadow — reads as a struck brass plate. */
  text-shadow:
    .010em .010em 0 var(--clay-shade), .020em .020em 0 var(--clay-shade),
    .030em .030em 0 var(--clay-shade), .040em .040em 0 var(--clay-shade),
    .055em .055em .12em rgba(0,0,0,.28);
}
/* Letters drop in on load, each one a beat after the last. */
:root.js .hero__name__3d .ltr{
  animation: ltrIn .72s cubic-bezier(.2,.8,.25,1) both;
}
.hero__name__3d .ltr:nth-child(1){ animation-delay:.05s }
.hero__name__3d .ltr:nth-child(2){ animation-delay:.11s }
.hero__name__3d .ltr:nth-child(3){ animation-delay:.17s }
.hero__name__3d .ltr:nth-child(4){ animation-delay:.23s }
.hero__name__3d .ltr:nth-child(5){ animation-delay:.29s }
.hero__name__3d .ltr:nth-child(6){ animation-delay:.35s }
.hero__name__3d .ltr:nth-child(7){ animation-delay:.41s }
.hero__name__3d .ltr:nth-child(8){ animation-delay:.47s }
@keyframes ltrIn{
  from{ opacity:0; transform: translate3d(0,-.42em,-220px) rotateX(-62deg); }
  to  { opacity:1; transform: none; }
}
/* Pointer-driven per-letter lift, set by JS on the nearest letters. */
.hero__name__3d .ltr{ transition: translate .3s ease, color .3s ease; }
.hero__name__3d .ltr.is-near{ translate: 0 -.045em; color: var(--clay); }

/* ---------- Matrix decode glitch ----------
   JS scrambles the letter's actual text through katakana/code glyphs for a
   few frames (classic "decrypting" effect), while this CSS just handles the
   look on top: phosphor-red colour + glow while .matrix-strike is on, and
   a bright scanline sweeping down through the glyph via ::before. JS adds/
   removes the class and swaps the character; it owns no visual styling. */
.hero__name__3d .ltr{ position:relative; }
.hero__name__3d .ltr.matrix-strike{
  color: var(--matrix-red);
  -webkit-text-stroke: 1.3px var(--matrix-red-dark);
  text-shadow:
    0 0 3px var(--matrix-red),
    0 0 10px var(--matrix-glow),
    0 0 24px var(--matrix-glow),
    0 0 46px var(--matrix-glow-soft);
}
.hero__name__3d .ltr.matrix-strike::before{
  content:"";
  position:absolute; left:-8%; right:-8%; top:-14%; height:30%;
  background: linear-gradient(180deg, transparent, var(--matrix-scan), transparent);
  filter: blur(1px);
  mix-blend-mode: screen;
  pointer-events:none;
  animation: matrixScan .68s linear;
}
@keyframes matrixScan{
  0%   { transform:translateY(-20%); opacity:0; }
  12%  { opacity:1; }
  100% { transform:translateY(440%); opacity:0; }
}
@media (prefers-reduced-motion: reduce){
  .hero__name__3d .ltr.matrix-strike,
  .hero__name__3d .ltr.matrix-strike::before{ animation:none; text-shadow:none; }
}

/* Touch devices get a fixed tilt rather than the old infinite sway. The
   extrusion already reads as a solid object from a static angle; a permanent
   ambient animation on a phone costs battery and adds nothing. */
@media (hover: none), (pointer: coarse){
  :root.js .hero__name__stage{ transform: rotateX(1.5deg) rotateY(-6deg); }
}

/* ══════════════════════════════════════════════════════════════════════════
   TICKER — the "I'm a security researcher" bar. Two identical groups scroll
   as one row; translating the row -50% lands group 2 exactly where group 1
   started, so the loop has no seam. The real sentence is in .vh above it;
   the strip itself is aria-hidden so a screen reader hears it once.
   ══════════════════════════════════════════════════════════════════════════ */
.tick{
  border-block: var(--border-w) solid var(--line);
  background: var(--clay-tint);
  overflow:hidden;
  position:relative;
}
.tick__vp{ display:flex; width:max-content; }
.tick__row{
  display:flex; flex:none;
  animation: tickRun 34s linear infinite;
}
.tick:hover .tick__row, .tick:focus-within .tick__row{ animation-play-state:paused; }
@keyframes tickRun{ from{ transform:none; } to{ transform: translateX(-50%); } }
.tick__g{
  display:flex; align-items:center; gap:1.1rem; flex:none;
  padding:.72rem 1.1rem;
  font-family:var(--font-mono); font-size:.76rem; letter-spacing:.1em;
  white-space:nowrap; color:var(--ink-soft);
}
.tick__g b{ font-weight:700; color:var(--ink); letter-spacing:.12em; }
.tick__g i{ font-style:normal; color:var(--red); font-size:.6rem; }
/* No JS → no animation is fine; the row still reads as a static strip. */
:root:not(.js) .tick__row{ animation:none; }

/* ══════════════════════════════════════════════════════════════════════════
   COLOPHON — closing footer + copyright.
   ══════════════════════════════════════════════════════════════════════════ */
.colo{
  border-top: var(--border-w) solid var(--line);
  background: var(--paper-2);
  padding: clamp(2rem, 5vw, 3.4rem) 0 clamp(1.6rem, 4vw, 2.4rem);
}
.colo__in{
  padding-inline: var(--edge);
  display:grid; gap:1.5rem;
  grid-template-columns: 1fr auto;
  align-items:start;
}
.colo__brand{
  display:inline-flex; align-items:center; gap:.6rem;
  font-family:var(--font-display); font-size:1.05rem; letter-spacing:.02em;
}
.colo__brand .brand__mark svg{ width:22px; height:22px; }
.colo__brand:hover{ color:var(--red); }

.colo__nav{ display:flex; flex-wrap:wrap; gap:.5rem 1.15rem; justify-content:flex-end; }
.colo__nav a{
  font-family:var(--font-mono); font-size:.74rem; letter-spacing:.04em;
  color:var(--ink-soft); padding-bottom:2px;
  border-bottom:var(--border-hair) solid transparent;
}
.colo__nav a:hover{ color:var(--ink); border-bottom-color:var(--red); }

.colo__cr{
  grid-column:1 / -1;
  padding-top:1.3rem;
  border-top: var(--border-hair) solid var(--ink-mute);
  font-family:var(--font-mono); font-size:.72rem; line-height:1.7;
  color:var(--ink-mute);
}
.colo__sep{ padding-inline:.45em; }

@media (max-width: 720px){
  .colo__in{ grid-template-columns:1fr; }
  .colo__nav{ justify-content:flex-start; }
}

/* Preloader must actually leave once it is hidden — [hidden] loses to the
   display:grid above it on specificity, so state it explicitly. */
:root.js .pre[hidden]{ display:none; }

/* ---------- Scroll progress: paints the nav's existing bottom edge ---------- */
.nav__prog{
  position:absolute; left:0; right:0; bottom:calc(var(--border-w) * -1);
  height:var(--border-w); pointer-events:none; overflow:hidden;
}
.nav__prog i{ display:block; height:100%; width:0; background:var(--red); }

/* ══════════════════════════════════════════════════════════════════════════
   MOTION — reveal system. One entrance transition, staggered by depth in JS.
   Directional variants (.reveal--l/--r/--s) were removed: nothing used them,
   and a single entrance direction is what keeps a section arriving as one
   group rather than a scatter.
   ══════════════════════════════════════════════════════════════════════════ */

/* Stagger lives in JS (the observer's setTimeout on data-delay-index).
   Deliberately NOT duplicated as transition-delay here — the two would
   compound and the last card in a group would arrive half a second late. */

/* Section headings draw their rule in as they arrive. */
.kicker__n{ position:relative; }
:root.js .kicker .kicker__n::after{
  content:""; position:absolute; left:0; right:0; bottom:-6px; height:var(--border-hair);
  background:var(--red); transform:scaleX(0); transform-origin:left;
  transition: transform .7s cubic-bezier(.2,.7,.2,1) .15s;
}
:root.js .kicker.in .kicker__n::after{ transform:scaleX(1); }

/* Cards lift toward the reader on hover. The shadow does NOT change — both
   already sit at --sh-2, and stepping to --sh-hero would break the two-level
   elevation contract. The lift alone reads as depth. */
.card, .file{ transition: translate .25s ease; }
@media (hover: hover) and (pointer: fine){
  .card:hover, .file:hover{ translate: 0 -3px; }
}

/* Live pulse on the hero status dot already exists; give the proof numbers a
   count-in so the strip reads as instrumentation rather than decoration. */
:root.js .proof.in .proof__n{ animation: proofIn .55s cubic-bezier(.2,.8,.25,1) both; }
@keyframes proofIn{ from{ opacity:0; translate:0 .3em; } to{ opacity:1; translate:0 0; } }
