/* ════════════════════════════════════════════════════════════════════
   CELL 4 — THE RESURRECTIONS ★ SIGNATURE MOMENT ★
   ALL selectors scoped under #cell-4 (no leak into siblings).
   Authority: WOW_CONTRACTS cell:4 + picks.json cell:4 (G001 seam · G002
   timeline+spec-plates · G003 GYR case-number in STEEL) + board slice + DESIGN.md.
   Palette from tokens.css ONLY (base #222222 · accent #C2231B Signal Red ·
   support #B7BCC1 Polished Steel · breath #E9E6E1 · ink-deep #141414).
   Radius 0 = machined edge everywhere. Big Shoulders display / Plex Mono labels.

   THE DRIVING VARIABLE: --resto (0%..100%). Set at rest to the static "mid-
   resurrection" value by CSS; driven by js/cells/cell-4.js on the pinned scrub.
   Everything (seam position, before-clip, gauge fill, node highlight) reads it,
   so a captured/reduced-motion/solo frame is content-complete on its own.
   ════════════════════════════════════════════════════════════════════ */

#cell-4 {
  /* rest state = a composed mid-resurrection frame (WOW contract: --resto:62%,
     gauge 62%, label REBUILT) so the section is content-complete before the pin
     ever engages and in reduced-motion / ?solo. The JS overrides this live. */
  --resto: 62%;
  /* P3 row 5 — SHIFT-DOWN LOCK: how much viewport to reserve ABOVE the pinned
     stage so "THE RESURRECTIONS" title + kicker stay framed at the top of the
     scroll-lock arrest (David: title fully visible up top, a handful of px pad,
     equal pad below). Default 1rem = the no-JS floor (unchanged); cell-4.js
     measures the real header block (title + gap) and raises this so the header
     lands under the nav and the wasted bottom space is absorbed. */
  --rez-lock-reserve: 1rem;
  /* derived: the active timeline node 0..3 = floor(--resto / 25%). CSS can't do
     that math for the highlight, so the JS toggles .is-active; but the seam,
     clip and gauge below are pure --resto so they never need JS to be correct. */
  overflow: clip;
  isolation: isolate;
}

/* the section head + stage + roster stack with composed rhythm (interior gaps
   < the section break above/below — T2.20) */
#cell-4 .rez {
  display: flex;
  flex-direction: column;
  /* P3 row 5 — tighter title↔film gap so the arrest reads as "a handful of px"
     of padding above the film, not a wide band (was clamp(2.5,5vw,4.5)). */
  gap: clamp(1.4rem, 3vw, 2.4rem);
}

/* ── SECTION HEAD ─────────────────────────────────────────────────────
   H2 display caps left; eyebrow-rule + lede right — matches the board. */
#cell-4 .rez__head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: clamp(1.25rem, 3vw, 3rem);
  /* P3 row 5 + R89 pin fix — the title holds framed above the stage for the
     scrub via its OWN GSAP pin in cell-4.js, sharing the stage's exact pin
     window (CSS sticky's containment spanned the roster too, so the title
     rode down over the cards after release — R20's disease at every width).
     Pinned by JS = it releases WITH the stage. No sticky here anymore. */
  position: relative;
  z-index: 5;
}
#cell-4 .rez__title {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: var(--step-section);
  line-height: 0.9;
  letter-spacing: 0.004em;
  color: var(--breath);
  text-wrap: balance;
}
/* H2A-red — the single Signal-Red word (the resurrection word) */
#cell-4 .rez__title-accent { color: var(--accent); }

#cell-4 .rez__intro {
  max-width: 34rem;
  padding-bottom: 0.35rem;    /* optical baseline seat against the big title */
}
#cell-4 .rez__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-family: var(--font-mono);
  color: var(--support);
  margin-bottom: var(--space-s);
}
#cell-4 .rez__eyebrow-rule {
  display: inline-block;
  width: clamp(1.75rem, 4vw, 3rem);
  height: 1px;
  background: var(--support);
  flex: none;
}
#cell-4 .rez__lede {
  font-size: var(--step-mini);
  line-height: 1.55;
  color: var(--text-on-dark);
}

/* ════════════════════════════════════════════════════════════════════
   THE RESURRECTION SCRUB — the signature stage.
   Layout: the film (before/after clip) fills the width; the instrument panel
   (timeline + gauge) sits below it, both riding --resto.
   ════════════════════════════════════════════════════════════════════ */
#cell-4 .rez__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: clamp(1rem, 2.2vw, 1.6rem);
  border: 1px solid var(--ink-700);
  background: linear-gradient(to bottom, #262626 0%, var(--ink-900) 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
  padding: clamp(0.9rem, 1.8vw, 1.35rem);
  /* T2.35 PINNED-FIT: once pinned, the whole composition (film + gap + instrument
     panel) must sit inside the below-nav viewport, so the name chip, red seam bar,
     FOUND→DELIVERED timeline and 1→100 gauge never drop below the fold at wide
     widths. Cap the stage to the available height; the film flex-shrinks
     (cover-crops the car) to give the leftover height to the panel, which keeps
     its natural height. The -1rem matches the breathing gap the pin start
     (top+=navPx) reserves under the nav. invalidateOnRefresh + the load refresh
     recompute the pin distance after this cap applies. P3 row 5: the reserve is
     now --rez-lock-reserve (JS raises it to header height + gap) so the pinned
     stage leaves room for the title above it. */
  max-height: calc(100svh - var(--nav-h) - var(--rez-lock-reserve));
  box-sizing: border-box;
}

/* ── THE FILM ─────────────────────────────────────────────────────────
   DELIVERED (after) image is the base; the SAME car AS FOUND (before) is clipped
   from the RIGHT by --resto (0% = full found-car, 100% = found-car fully wiped →
   all delivered). Both cover the same box. This is ONE car — the 1937 Imperial
   "Black Betty" — resurrected found→delivered (LAW-verified same car). AR locked
   so both frames read cleanly. */
#cell-4 .rez__film {
  position: relative;
  width: 100%;
  /* T2.35 PINNED-FIT: the whole pinned composition (film + gap + instrument panel)
     must sit below the nav once pinned. GSAP pins the STAGE by freezing its natural
     height inline (position:fixed), so a max-height on the stage alone is overridden
     once pinned — the lever that actually shrinks the frozen stage is capping the
     FILM here. max-height = svh minus the nav and a reserve for the panel + gap +
     stage padding, so the film's viewport cap keeps the stage's natural height ≤ the
     available box at every width; the pin then freezes a box that already fits.
     No hard aspect-ratio: object-fit:cover cover-crops a shorter film, cars stay
     seated via object-position. height (flex-basis) sets the ~16:9-tall preference
     when there's room; flex:1 1 auto + min-height:0 let it shrink; the max-height is
     the viewport ceiling. */
  flex: 1 1 auto;
  min-height: 0;
  height: min(56.25vw, 62vh);   /* ~16:9 preference at wide widths */
  /* reserve: header lock (row 5) + panel + gap + stage padding */
  max-height: calc(100svh - var(--nav-h) - var(--rez-lock-reserve) - 11.5rem);
  overflow: hidden;
  border: 1px solid var(--ink-700);
  background: var(--ink-deep);
  margin: 0;
}
#cell-4 .rez__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* THE ONE CONSISTENT GRADE (DESIGN.md photography treatment): slight desat +
     warm lift → honest tungsten shop light, never faked to studio gloss. Shared
     look across every cell. */
  filter: saturate(0.92) contrast(1.03) brightness(1.0) sepia(0.14) hue-rotate(-6deg);
}
/* P3 row 6 — David hand-built the BEFORE/AFTER pair (gen-expanded, aligned,
   cleaned, transformed 1:1 for the scroll-swipe seam), so the alignment is BAKED
   INTO THE FILES. CENTER both (50% 50%) and do NOT reposition or crop-fix — any
   per-image nudge would fight his baked 1:1 seam. */
#cell-4 .rez__img--after  { object-position: 50% 50%; }
#cell-4 .rez__img--before { object-position: 50% 50%; }
/* the BEFORE overlay clips off the RIGHT edge as --resto grows: at 0% it covers
   the whole frame; at 100% its right edge has swept fully left → all AFTER.
   inset() from the right by --resto. transform-free = compositor-cheap + the
   captured frame is exact. */
#cell-4 .rez__before {
  position: absolute;
  inset: 0;
  z-index: 1;
  clip-path: inset(0 var(--resto) 0 0);
  will-change: clip-path;
}
/* slightly cooler + rawer grade on the FOUND half so the before→after reads as
   a real tonal lift (raw shop-yard light → finished concours light). Still one
   honest site grade underneath, no drama. */
#cell-4 .rez__img--before {
  filter: saturate(0.72) contrast(1.05) brightness(0.94) sepia(0.05) hue-rotate(2deg);
}

/* ── THE RED SEAM — the operating-table line, sitting at the wipe edge (== the
   right edge of the BEFORE clip == 100% - --resto from the left). A hard 2px
   Signal-Red rule with a faint glow, riding on the seam. Alive at rest: the
   line breathes a 2px terracotta hairline before the pin engages (§9). ── */
#cell-4 .rez__seam {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}
/* CLS-STABLE seam: the line is a FULL-WIDTH, full-height layer locked at inset:0
   (its box never moves → it contributes ZERO layout shift on init, even if the
   CSS-rest --resto and the JS animate-start differ). The position is driven by a
   compositor-only translateX — and transform-driven motion is EXCLUDED from CLS
   by spec — so the seam sweeps without ever registering as a layout shift.
   translateX % is relative to this element's OWN width (== the film width), so
   translateX(-(--resto)) lands the RIGHT edge at (100% - --resto) from the left,
   exactly where the BEFORE clip's right edge sits. The visible 2px Signal-Red
   rule is painted at that right edge via ::before. */
#cell-4 .rez__seam-line {
  position: absolute;
  inset: 0;
  transform: translateX(calc(-1 * var(--resto)));
  will-change: transform;
}
#cell-4 .rez__seam-line::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 2px;
  background: var(--accent);
  box-shadow: 0 0 10px 1px rgba(194,35,27,0.55),
              0 0 2px 0 rgba(194,35,27,0.9);
}
/* idle breath on the seam at rest (before the scrub owns it) — a slow opacity
   pulse so the section is alive at t0 even fully un-scrolled. The JS clears
   the breath (adds .rez-scrubbing) once the pin drives the seam. Opacity-only,
   so it never causes layout shift. */
#cell-4 .rez__seam-line {
  animation: rez-seam-breath 4.2s ease-in-out infinite;
}
@keyframes rez-seam-breath {
  0%, 100% { opacity: 0.82; }
  50%      { opacity: 1; }
}
#cell-4 .rez-scrubbing .rez__seam-line { animation: none; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  #cell-4 .rez__seam-line { animation: none; }
}

/* ── WARM TUNGSTEN GLOW — ambient worklight ABOVE the film, never on the honest
   cars. Shared @keyframes tungsten-idle (base.css) breathes its opacity. Kept
   in the upper corners (away from the car mass) so car luma stays honest. ── */
#cell-4 .rez__tungsten {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: screen;
  background:
    radial-gradient(46% 60% at 8% 12%,
      rgba(255,176,96,0.30) 0%, rgba(255,150,70,0.10) 42%, rgba(255,150,70,0) 66%),
    radial-gradient(42% 55% at 94% 10%,
      rgba(255,176,96,0.22) 0%, rgba(255,150,70,0.06) 44%, rgba(255,150,70,0) 68%);
}

/* ── CORNER STATE TAGS — the two STATES of the SAME car: "As found" (top-left,
   over the calm farm sky) / "As delivered" (bottom-right, over the concours
   ground). Mono, stamped-steel chips. They cross-fade at the seam
   (.rez-delivered) so the visible state always matches the dominant half. Only
   ONE element per corner (T2.8). ── */
#cell-4 .rez__statetag {
  position: absolute;
  z-index: 3;
  font-family: var(--font-mono);
  font-size: clamp(0.6rem, 1vw, 0.72rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.4em 0.7em;
  color: var(--breath);
  background: color-mix(in srgb, var(--ink-deep) 78%, transparent);
  border: 1px solid var(--hairline-strong);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
/* BEFORE tag (top-left): "As found", stamped over the calm farm sky — the honest
   label for the LEFT (un-wiped) found half. It stays until the seam, then the JS
   adds .rez-delivered and it fades out so the delivered label takes over cleanly
   (T2.27 motion is semantic — a tag never lies). */
#cell-4 .rez__statetag--before {
  top: 0.7rem; left: 0.7rem;
  transition: opacity 200ms var(--ease-out);
}
/* AFTER tag (bottom-right): "As delivered" — asserted once the delivered half
   dominates (at the seam). Hidden until the JS adds .rez-delivered so it never
   sits over the found car. */
#cell-4 .rez__statetag--after {
  right: 0.7rem; bottom: 0.7rem;
  color: #fff; border-color: rgba(194,35,27,0.55);
  opacity: 0;
  transition: opacity 200ms var(--ease-out);
}
#cell-4.rez-delivered .rez__statetag--before { opacity: 0; }
#cell-4.rez-delivered .rez__statetag--after  { opacity: 1; }
/* static/reduced-motion/solo floor (rest 62% — past the seam, delivered half
   dominates): show BOTH tags, each honestly over its OWN half (found upper-left,
   delivered lower-right). The composed mid-resurrection frame reads true without
   JS: "As found" over the found corner, "As delivered" over the red car. */
html:not(.js) #cell-4 .rez__statetag--before,
#cell-4.rez-nojs .rez__statetag--before,
html:not(.js) #cell-4 .rez__statetag--after,
#cell-4.rez-nojs .rez__statetag--after { opacity: 1; }

/* ── THE IDENTITY PLATE — names the car CONSISTENTLY (bottom-left): this IS the
   same car, so the plate reads "1937 Imperial · Black Betty" the whole sweep;
   only its STATE line swaps AS IT ARRIVED→AS DELIVERED at the seam. The plate
   never contradicts the visible car. Stamped in STEEL (the G003 graft). ── */
#cell-4 .rez__plate {
  position: absolute;
  z-index: 3;
  left: 0.7rem;
  bottom: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.5rem 0.75rem;
  background: linear-gradient(to bottom, #2f2f2f 0%, #1c1c1c 100%);
  border: 1px solid #3f3f3f;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08),
              0 2px 6px rgba(0,0,0,0.5);
  max-width: min(62%, 22rem);
}
#cell-4 .rez__plate-state {
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 1vw, 0.74rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}
#cell-4 .rez__plate-car {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(0.9rem, 1.6vw, 1.15rem);
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--breath);
}
/* the plate + chips carry their own bg scrims, so they stay legible over either
   half of the car at any seam position. */

/* ── THE INSTRUMENT PANEL ─────────────────────────────────────────────
   timeline (left) + gauge (right), both reading --resto. On narrow widths they
   stack. ── */
#cell-4 .rez__panel {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: clamp(1rem, 2.4vw, 2rem);
  align-items: center;
}
/* the timeline column carries a small "found to finished" eyebrow above the
   nodes: the four stages read as THIS car's real restoration (it is the same car,
   found→delivered) — the honest framing of the resurrection. */
#cell-4 .rez__timeline-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
#cell-4 .rez__panel-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin: 0;
  font-family: var(--font-mono);
  color: var(--support);
}

/* ── FOUND → STRIPPED → REBUILT → DELIVERED — numbered stamped-steel nodes on
   a red rail (G002 graft) — this car's four real restoration stages. The rail
   runs behind; the active node lights (JS toggles .is-active on floor(--resto/25)).
   Alive at t0: node 03 (rest 62% → node index 2 = REBUILT) is active by the
   static default; JS confirms it. ── */
#cell-4 .rez__timeline {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  list-style: none;
  padding: 0;
  margin: 0;
}
/* the red rail — a thin Signal-Red line behind the node centers */
#cell-4 .rez__timeline::before {
  content: "";
  position: absolute;
  top: 1.35rem;                 /* aligns to the node-num vertical center */
  left: 12.5%;
  right: 12.5%;                 /* stop the rail at the first/last node centers */
  height: 2px;
  background: linear-gradient(to right,
    var(--terracotta-deep), var(--accent), var(--terracotta-deep));
  opacity: 0.55;
  z-index: 0;
}
#cell-4 .rez__node {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
}
#cell-4 .rez__node-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.7rem;
  height: 2.7rem;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--slate-400);
  background: linear-gradient(to bottom, #2c2c2c 0%, #1a1a1a 100%);
  border: 1px solid #3a3a3a;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06),
              inset 0 -2px 3px rgba(0,0,0,0.45);
  transition: color 150ms var(--ease-out),
              border-color 150ms var(--ease-out),
              box-shadow 150ms var(--ease-out),
              background 150ms var(--ease-out);
}
#cell-4 .rez__node-label {
  font-family: var(--font-mono);
  font-size: clamp(0.6rem, 1vw, 0.72rem);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate-400);
  transition: color 150ms var(--ease-out);
}
/* the active stage — red-hot stamped plate, white number, its label lit */
#cell-4 .rez__node.is-active .rez__node-num {
  color: #fff;
  background: linear-gradient(to bottom, #d1291f 0%, #a51a12 100%);
  border-color: #7d140e;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14),
              0 0 12px 0 rgba(194,35,27,0.45);
}
#cell-4 .rez__node.is-active .rez__node-label { color: var(--breath); }
/* passed stages — quietly seated (dimmer than active, brighter than upcoming) */
#cell-4 .rez__node.is-passed .rez__node-num { color: var(--support); border-color: #4a4a4a; }
#cell-4 .rez__node.is-passed .rez__node-label { color: var(--support); }

/* ── THE RESTORATION GAUGE — 0→100% fill on the same beat; the number
   odometer-flips (JS) and lands crisp. Fill width == --resto directly. ── */
#cell-4 .rez__gauge {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
#cell-4 .rez__gauge-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
#cell-4 .rez__gauge-label {
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 1vw, 0.74rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--support);
}
#cell-4 .rez__gauge-pct {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.6rem, 3.2vw, 2.4rem);
  line-height: 1;
  color: var(--breath);
  font-variant-numeric: tabular-nums;
}
#cell-4 .rez__gauge-unit {
  font-size: 0.5em;
  color: var(--accent);
  margin-left: 0.05em;
}
#cell-4 .rez__gauge-track {
  position: relative;
  height: 0.7rem;
  background: linear-gradient(to bottom, #1a1a1a, #262626);
  border: 1px solid #3a3a3a;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.6);
  overflow: hidden;
}
#cell-4 .rez__gauge-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--resto);          /* == the same driving var */
  background: linear-gradient(to right, var(--terracotta-deep), var(--accent));
  box-shadow: 0 0 8px 0 rgba(194,35,27,0.5);
  will-change: width;
}
/* fine tick marks across the gauge track (a real instrument, not a plain bar) */
#cell-4 .rez__gauge-track::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(to right,
    transparent 0, transparent calc(10% - 1px),
    rgba(0,0,0,0.4) calc(10% - 1px), rgba(0,0,0,0.4) 10%);
}

/* ════════════════════════════════════════════════════════════════════
   THE COMPLETED-WORK ROSTER — GYR case-file cards → project pages.
   (The mockup's 2nd before/after row, re-cast per T2.1: one wow, not two.)
   Repeated units identical by default (T2.2): same height, padding, meta slots.
   ════════════════════════════════════════════════════════════════════ */
#cell-4 .rez__roster {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 2.6vw, 2rem);
}
#cell-4 .rez__roster-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-family: var(--font-mono);
  color: var(--support);
}
#cell-4 .rez__cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(0.9rem, 1.8vw, 1.4rem);
}
#cell-4 .rez__card {
  display: flex;
}
#cell-4 .rez__card-link {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: linear-gradient(to bottom, #262626 0%, var(--ink-850) 100%);
  border: 1px solid var(--ink-700);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
  transition: transform 150ms var(--ease-out),
              border-color 150ms var(--ease-out),
              box-shadow 150ms var(--ease-out);
}
/* pre-rendered hover shadow layer (opacity-only transition — never animate
   box-shadow blur; motion lib §1.2) */
#cell-4 .rez__card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  box-shadow: 0 24px 46px -30px rgba(0,0,0,0.7), 0 8px 20px -16px rgba(0,0,0,0.5);
  transition: opacity 150ms var(--ease-out);
}
#cell-4 .rez__card-media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-bottom: 1px solid var(--ink-700);
}
#cell-4 .rez__card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.92) contrast(1.03) brightness(1.0) sepia(0.14) hue-rotate(-6deg);
  transition: transform 400ms var(--ease-out);
}
#cell-4 .rez__card-body {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: clamp(0.9rem, 1.6vw, 1.2rem);
  flex: 1;
}
#cell-4 .rez__card-case {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  color: var(--accent);
}
#cell-4 .rez__card-name {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(1.1rem, 1.7vw, 1.3rem);
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--breath);
}
#cell-4 .rez__card-spec {
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--slate-400);
}
#cell-4 .rez__card-award {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--support);
  margin-top: 0.1rem;
}
#cell-4 .rez__card-cta {
  margin-top: auto;
  padding-top: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}
#cell-4 .rez__card-arrow { transition: transform 150ms var(--ease-out); }

/* plate-press hover — scale-not-shift, ≤150ms, hover-capable ONLY (T2.27/T2.30) */
@media (hover: hover) {
  #cell-4 .rez__card-link:hover {
    transform: translateY(-0.28rem) scale(1.012);
    border-color: #4a4a4a;
  }
  #cell-4 .rez__card-link:hover::after { opacity: 1; }
  #cell-4 .rez__card-link:hover .rez__card-media img { transform: scale(1.04); }
  #cell-4 .rez__card-link:hover .rez__card-arrow { transform: translateX(3px); }
}

/* ── THE STAMPED "OPEN THE PROJECT FILES" BUTTON — a machined steel plate with
   corner rivets, exactly the board's element, done in steel. Centered. ── */
#cell-4 .rez__filesbtn {
  position: relative;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: clamp(16rem, 34vw, 24rem);
  padding: 1.05rem 2.2rem;
  background: linear-gradient(to bottom, #2c2c2c 0%, #1c1c1c 52%, #232323 100%);
  border: 1px solid var(--support);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08),
              0 3px 0 rgba(0,0,0,0.45);
  transition: transform 140ms var(--ease-out),
              box-shadow 140ms var(--ease-out),
              border-color 140ms var(--ease-out),
              background 140ms var(--ease-out);
}
#cell-4 .rez__filesbtn-label {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--breath);
}
/* the four corner rivets — steel bolt heads */
#cell-4 .rez__filesbtn-rivet {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;                 /* rivets ARE round — an intentional
                                         exception to the machined 0px edge */
  background: radial-gradient(circle at 35% 30%, #6a6d70, #2a2b2c 70%);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5);
}
#cell-4 .rez__filesbtn-rivet--tl { top: 7px;  left: 9px; }
#cell-4 .rez__filesbtn-rivet--tr { top: 7px;  right: 9px; }
#cell-4 .rez__filesbtn-rivet--bl { bottom: 7px; left: 9px; }
#cell-4 .rez__filesbtn-rivet--br { bottom: 7px; right: 9px; }
@media (hover: hover) {
  #cell-4 .rez__filesbtn:hover {
    transform: translateY(2px);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 1px 0 rgba(0,0,0,0.45);
    border-color: var(--breath);
    background: linear-gradient(to bottom, #333 0%, #202020 52%, #282828 100%);
  }
}

/* ════════════════════════════════════════════════════════════════════
   RESPONSIVE — mobile is desktop RECOMPOSED, not squished (T2.31).
   One-viewport density per beat; grids re-grid rather than endlessly stack.
   ════════════════════════════════════════════════════════════════════ */

/* tablet: head stacks, roster → 2-up, panel stays 2-col until it's tight */
@media (max-width: 900px) {
  #cell-4 .rez__head {
    grid-template-columns: 1fr;
    align-items: start;
    gap: var(--space-s);
  }
  #cell-4 .rez__intro { padding-bottom: 0; max-width: 42rem; }
  #cell-4 .rez__cards { grid-template-columns: repeat(2, 1fr); }
}

/* narrow: the instrument panel stacks (timeline over gauge) → taller, so the
   pinned stage must reserve MORE for the panel and give the film a shorter basis
   that flex-shrinks to fit 390×844 below the nav; film still reads the car mass
   via cover-crop; roster → 1-up */
@media (max-width: 620px) {
  #cell-4 .rez__panel { grid-template-columns: 1fr; gap: 1.4rem; }
  /* film basis for mobile: ~4:3-tall preference, but viewport-capped so the
     STACKED (taller) panel — timeline over gauge — stays above the fold at
     390×844. The stacked panel needs a bigger reserve than desktop, so the film
     max-height reserves ~19rem for panel + gap + padding. Keeping the flex model
     (not a hard aspect-ratio) is what lets it give height back to the panel. */
  #cell-4 .rez__film {
    height: min(75vw, 46vh);
    max-height: calc(100svh - var(--nav-h) - 19rem);
  }
  #cell-4 .rez__node-num { width: 2.3rem; height: 2.3rem; font-size: 0.78rem; }
  #cell-4 .rez__timeline::before { top: 1.15rem; }
  /* R98: all three cars on screen at once (David) — the roster compresses to
     thumb + case + name; spec/award/cta lines yield at this width and live on
     the detail pages the cards open */
  #cell-4 .rez__cards { grid-template-columns: repeat(3, 1fr); gap: 0.55rem; }
  #cell-4 .rez__card-body { padding: 0.55rem 0.55rem 0.6rem; gap: 0.18rem; }
  #cell-4 .rez__card-case { font-size: 0.5rem; }
  #cell-4 .rez__card-name { font-size: 0.66rem; line-height: 1.25; }
  #cell-4 .rez__card-spec,
  #cell-4 .rez__card-award,
  #cell-4 .rez__card-cta { display: none; }
  #cell-4 .rez__plate { max-width: min(80%, 20rem); }
  /* The identity plate owns the lower-left of the compact film.  Keeping the
     delivered state chip at lower-right made the two physical labels collide
     at 390px; move that chip to the remaining calm corner instead (T2.8). */
  #cell-4 .rez__statetag--after { top: 0.7rem; bottom: auto; }
  #cell-4 .rez__filesbtn { width: 100%; min-width: 0; }
}

/* ── STATIC / REDUCED-MOTION / SOLO FLOOR ─────────────────────────────
   With no JS-motion the section is already correct: --resto rests at 62% so the
   seam sits mid-frame, the gauge reads 62%, the BEFORE is half-wiped, and the
   roster + button are fully present. The JS only ADDS the scrub + node/word
   sync + the odometer flip. If JS never runs, we still want the REBUILT node
   lit to match the 62% rest — do it in pure CSS via :nth-child so the floor is
   content-complete without JS. (JS overrides with live .is-active as it scrubs.) */
html:not(.js) #cell-4 .rez__node:nth-child(3) .rez__node-num,
#cell-4.rez-nojs .rez__node:nth-child(3) .rez__node-num {
  color: #fff;
  background: linear-gradient(to bottom, #d1291f 0%, #a51a12 100%);
  border-color: #7d140e;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 0 12px 0 rgba(194,35,27,0.45);
}
html:not(.js) #cell-4 .rez__node:nth-child(3) .rez__node-label,
#cell-4.rez-nojs .rez__node:nth-child(3) .rez__node-label { color: var(--breath); }
html:not(.js) #cell-4 .rez__node:nth-child(-n+2) .rez__node-num,
#cell-4.rez-nojs .rez__node:nth-child(-n+2) .rez__node-num { color: var(--support); border-color: #4a4a4a; }
html:not(.js) #cell-4 .rez__node:nth-child(-n+2) .rez__node-label,
#cell-4.rez-nojs .rez__node:nth-child(-n+2) .rez__node-label { color: var(--support); }

/* H3 — ≤1100w: the sticky rez header (top: nav+0.55rem, z:5) rides over the
   stacked tile grid for the whole scroll at narrow widths (David's R20).
   R89: retired — the header is GSAP-pinned to the stage's exact scrub window
   in cell-4.js now (all widths), so it can never outlive the scrub. */
