/* ═══════════════════════════════════════════════════════════════
   אילן חוסיד · hub landing page
   Direction: cinematic editorial bleed.
   Dark brand ground, Heebo 300 display at viewport scale, colour
   fields cropped by the screen edge, asymmetry that reverses from
   section to section. No boxes. No uniform inset. No grid of tiles.
   BRAND-IDENTITY.md is law: #131319 ground, #2E8BFF accent,
   Heebo 300 display, Assistant body, never letter-space Hebrew,
   never italicise Hebrew, logical properties only.

   Tonal ladder (the page descends and comes back up):
     hero   #06070b  deep
     arg    #06070b → #0b0d13 → #131319
     gal    #131319  the bright plateau, where the work lives
     inc    #131319 → #0b0d13
     edge   #0b0d13 → #08090e, blue field rising underneath
     proc   #06070b + one hard cut to paper white
     cta    #06070b, shafts mirrored onto the opposite edge
   ═══════════════════════════════════════════════════════════════ */

/* ── tokens ─────────────────────────────────────────────────── */
:root {
  --deep:      #0B0E14;
  --bg:        #FFFFFF;
  --bg-cool:   #F5F7FA;
  --bg-lift:   #FFFFFF;
  --ink:       #0B0E14;
  --ink-dim:   rgba(11, 14, 20, .68);
  --ink-faint: rgba(11, 14, 20, .48);
  --ink-ghost: rgba(11, 14, 20, .14);

  --accent:      #2E8BFF;
  --accent-deep: #0E5FE8;
  --accent-soft: #7FB4FF;

  /* Depth washes. Named by job, not by hue, so they read as
     atmosphere rather than as a second accent. Under 12% they
     are structure - they never count against the accent budget. */
  --wash-core: color-mix(in srgb, var(--accent-deep) 24%, transparent);
  --wash-far:  color-mix(in srgb, var(--accent) 9%, transparent);

  /* the one light surface on the page */
  --paper:       #fbfbf9;
  --paper-ink:   #101116;
  --paper-dim:   rgba(16, 17, 22, .58);
  --paper-faint: rgba(16, 17, 22, .34);
  --paper-line:  rgba(16, 17, 22, .13);

  /* scrubbed by ScrollTrigger so the vignette breathes by section */
  --vig: .32;

  --font-d: "Heebo", "Assistant", system-ui, sans-serif;
  --font-b: "Assistant", "Heebo", system-ui, sans-serif;

  /* ── TYPE SCALE ────────────────────────────────────────────────
     One modular scale. Ratio 1.25 (major third) at the desktop end,
     1.115 at the phone end so display steps compress instead of
     exploding on a 375px screen. Both ladders are anchored on the
     body step (--f-3: 15px phone / 18px desktop) and interpolate
     linearly between 380px and 1680px of viewport.

     EVERY font-size on this page is one of these steps. If a size
     is not on the ladder it is a bug, not a decision. Editorial
     contrast is produced by SKIPPING steps (body f-3, display f-12),
     never by inventing a value between them.

       f-1   12.0            micro Latin label (wordmark, folio)
       f-2   13.5 →  14.4    kicker · meta · caption
       f-3   15.0 →  18.0    body · lede · annotation
       f-4   16.7 →  22.5    deck · large link · comparison term
       f-5   18.7 →  28.1    closing statement
       f-6   20.8 →  35.2    small heading
       f-7   23.2 →  44.0    heading
       f-8   25.9 →  54.9    large heading
       f-9   28.8 →  68.7    section headline
       f-10  32.1 →  85.8    section display
       f-11  35.8 → 107.3    stage display
       f-12  40.0 → 134.1    statement display
       f-13  44.6 → 167.6    hero display
     ────────────────────────────────────────────────────────── */
  --f-1:  12px;
  --f-2:  clamp(13.45px, calc(13.176px + 0.073vw), 14.40px);
  --f-3:  clamp(15.00px, calc(14.123px + 0.231vw), 18.00px);
  --f-4:  clamp(16.73px, calc(15.037px + 0.444vw), 22.50px);
  --f-5:  clamp(18.65px, calc(15.878px + 0.729vw), 28.12px);
  --f-6:  clamp(20.79px, calc(16.594px + 1.105vw), 35.16px);
  --f-7:  clamp(23.18px, calc(17.115px + 1.597vw), 43.95px);
  --f-8:  clamp(25.85px, calc(17.350px + 2.237vw), 54.93px);
  --f-9:  clamp(28.82px, calc(17.177px + 3.065vw), 68.66px);
  --f-10: clamp(32.14px, calc(16.443px + 4.130vw), 85.83px);
  --f-11: clamp(35.83px, calc(14.947px + 5.497vw), 107.29px);
  --f-12: clamp(39.95px, calc(12.432px + 7.243vw), 134.11px);
  --f-13: clamp(44.55px, calc(8.569px + 9.468vw), 167.64px);

  /* ── LEADING ───────────────────────────────────────────────────
     Hebrew needs more room than Latin defaults. Body sits at 1.72
     (inside the 1.5-1.75 rule). Display is tighter than body but
     never below 1.05 - ק ן ך ף ץ descend, and at 134px a 0.97
     leading puts them into the line below.
     ────────────────────────────────────────────────────────── */
  --lh-display: 1.05;
  --lh-head:    1.14;
  --lh-deck:    1.5;
  --lh-body:    1.72;
  --lh-note:    1.62;
  --lh-label:   1.5;
  /* the one all-Latin display line (the demo wordmarks) may go
     tighter than Hebrew ever should - no descenders to protect */
  --lh-latin:   .92;

  /* ── SPACE SCALE ───────────────────────────────────────────────
     One unit, one ratio. 1.5 desktop / 1.34 phone, base 8px / 6px,
     same 380→1680 interpolation as the type scale. Every vertical
     gap, every section padding and every inline offset on this page
     is one of these steps or a whole multiple of --indent.

       s-1    6 →   8     hairline gap
       s-2    8 →  12     tight cluster
       s-3   11 →  18     label to line
       s-4   14 →  27     paragraph gap
       s-5   19 →  41     kicker to headline · gutter (edge-flush)
       s-6   26 →  61     element group
       s-7   35 →  91     block separation · THE INLINE STEP
       s-8   47 → 137     section rhythm (compressed)
       s-9   62 → 205     section rhythm (expanded)
       s-10  84 → 308     reserve
     ────────────────────────────────────────────────────────── */
  --s-1:  clamp(6.00px,  calc(5.415px + 0.154vw),   8.00px);
  --s-2:  clamp(8.04px,  calc(6.882px + 0.305vw),  12.00px);
  --s-3:  clamp(10.77px, calc(8.661px + 0.556vw),  18.00px);
  --s-4:  clamp(14.44px, calc(10.764px + 0.966vw), 27.00px);
  --s-5:  clamp(19.35px, calc(13.161px + 1.627vw), 40.50px);
  --s-6:  clamp(25.92px, calc(15.742px + 2.679vw), 60.75px);
  --s-7:  clamp(34.74px, calc(18.253px + 4.338vw), 91.12px);
  --s-8:  clamp(46.55px, calc(20.197px + 6.934vw), 136.69px);
  --s-9:  clamp(62.37px, calc(20.672px + 10.974vw), 205.03px);
  --s-10: clamp(83.58px, calc(18.111px + 17.228vw), 307.55px);

  /* THE inline step. Every horizontal offset on the page - the
     argument cascade, the principle rows, the CTA button offset -
     is 1x, 2x or 3x of this. Asymmetry on a shared unit reads as
     confidence; asymmetry on arbitrary values reads as broken. */
  --indent: var(--s-7);

  /* Gutters stay a per-section decision - that is what keeps the
     silhouettes different - but each one is a NAMED step, not a
     fresh clamp. Four registers, deliberately far apart. */
  --gut-edge:  var(--s-5);   /* hero · cta · chrome  */
  --gut-tight: var(--s-4);   /* inc · ragged rows    */
  --gut-mid:   var(--s-7);   /* arg · proc · = indent */
  --gut-deep:  var(--s-8);   /* gal-lead · edge      */
  --gut: var(--gut-edge);

  /* Measures. One value per reading register, used everywhere. */
  --measure:      66ch;  /* sustained reading (~65 Hebrew chars/line) */
  --measure-lede: 46ch;  /* lede / deck        */
  --measure-note: 40ch;  /* hanging annotation */
  --measure-deck: 34ch;  /* the one lead-in    */
  --measure-display: 22ch;  /* display headline wrap */

  /* how far the fixed chrome reaches down into a first screen */
  --head-clear: clamp(64px, 7vh, 88px);

  --ease: cubic-bezier(.2, 0, 0, 1);
  --slow: cubic-bezier(.16, 1, .3, 1);
}

/* ── reset ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--deep);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-b);
  font-weight: 400;
  font-size: var(--f-3);      /* the body step. the scale's anchor. */
  line-height: var(--lh-body);
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
b, strong { font-weight: 600; }

/* Hebrew has no italic tradition. Kill it at the root. */
i, em, cite, address, dfn, var { font-style: normal; }

img, canvas, iframe, svg { display: block; max-inline-size: 100%; }

:focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 4px;
  border-radius: 2px;
}

::selection { background: var(--accent-deep); color: #fff; }

.svg-defs { position: absolute; inline-size: 0; block-size: 0; }

/* the single arrow mark. monoline, currentColor, 1.6 stroke. */
.ar, .lnk {
  inline-size: 26px;
  block-size: 12px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}

.skip {
  position: fixed;
  inset-block-start: -100px;
  inset-inline-start: 16px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--ink);
  color: var(--deep);
  font-weight: 600;
  transition: inset-block-start .18s var(--ease);
}
.skip:focus { inset-block-start: 12px; }

/* ── the two atmosphere layers over the whole document ──────────
   Vignette first, grain over it. --vig is scrubbed on scroll, so
   the frame closes in on the deep sections and opens up over the
   gallery where the work has to read cleanly.
   ─────────────────────────────────────────────────────────── */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 88;
  pointer-events: none;
  background:
    radial-gradient(128% 96% at 50% 46%,
      transparent 34%,
      rgba(2, 3, 6, calc(var(--vig) * .5)) 74%,
      rgba(2, 3, 6, var(--vig)) 100%);
}

/* film grain. cinematic texture, not decorative geometry. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* ── shared type atoms ──────────────────────────────────────── */
/* ONE kicker. Same step, same weight, same colour, same gap below,
   in every section. It was previously three near-identical clamps
   with four different gaps under them, which is exactly the kind of
   almost-the-same that reads as sloppy rather than as variation. */
.kick,
.hero-kick {
  font-family: var(--font-b);
  font-size: var(--f-2);
  font-weight: 600;
  line-height: var(--lh-label);
  color: var(--ink-faint);
  margin-block-end: var(--s-5);
}
/* the hero kicker is a grid row, its gap is owned by the grid */
.hero-kick { margin-block-end: 0; }

.soft { color: var(--ink-dim); }

.mark {
  font-family: var(--font-d);
  font-size: var(--f-1);
  font-weight: 600;
  color: var(--ink-dim);
  transition: color .2s var(--ease);
}
.mark bdi { letter-spacing: .34em; } /* Latin wordmark only */
.mark:hover { color: var(--ink); }

/* growing-underline hover, the house link move */
.go {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  position: relative;
  font-family: var(--font-d);
  font-size: var(--f-4);
  font-weight: 400;
  color: var(--ink);
  padding-block-end: 8px;
}
.go::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  block-size: 1px;
  background: currentColor;
  opacity: .3;
  transition: opacity .3s var(--ease), background-color .3s var(--ease);
}
.go:hover::after { opacity: 1; background: var(--accent); }
.go .ar { transition: transform .3s var(--slow); }
.go:hover .ar { transform: translateX(-10px); }

/* hairline-bordered rectangle CTA that inverts on hover (brand §4) */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  border: 1px solid rgba(255, 255, 255, .3);
  font-family: var(--font-d);
  font-size: var(--f-3);
  font-weight: 400;
  color: var(--ink);
  background: transparent;
  transition: background-color .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease);
}
.btn:hover { background: var(--ink); color: var(--deep); border-color: var(--ink); }
.btn .ar { transition: transform .3s var(--slow); }
.btn:hover .ar { transform: translateX(-8px); }
.btn-lit { border-color: var(--accent); }
.btn-lit:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

/* ── header · flush to both viewport edges ──────────────────── */
.head {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 92;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-5) var(--gut-edge);
  transition: opacity .35s var(--ease), visibility .35s var(--ease);
}
/* content scrolls under fixed chrome, so the chrome carries its own
   soft falloff instead of blend-mode-fighting whatever passes below */
.head::before {
  content: "";
  position: absolute;
  inset-block: 0 auto;
  inset-inline: 0;
  block-size: 132px;
  z-index: -1;
  pointer-events: none;
  /* Deep enough to actually clear the wordmark. On a phone the long
     stacked sections push full-contrast copy under this bar, and a
     .8-to-transparent falloff let display type collide with it. */
  background: linear-gradient(to bottom,
    rgba(6, 7, 11, .94) 0%, rgba(6, 7, 11, .82) 34%,
    rgba(6, 7, 11, .42) 68%, rgba(6, 7, 11, 0) 100%);
}
/* The rail is a full-screen takeover. Studio chrome steps aside for
   it rather than blend-mode-fighting four foreign palettes. */
.head.is-away { opacity: 0; visibility: hidden; }
.head-cta {
  font-size: var(--f-2);
  line-height: var(--lh-label);
  font-weight: 600;
  color: var(--ink);
  padding-block-end: var(--s-1);
  border-block-end: 1px solid transparent;
  transition: border-color .25s var(--ease);
}
.head-cta:hover { border-block-end-color: currentColor; }

/* ═══ 1 · HERO ══════════════════════════════════════════════════
   Full viewport. Type block flush to the inline-start edge,
   luminous shaft field cropped by the inline-end edge, corners
   occupied. Four stacked depth planes behind the type: bloom,
   cold corner lift, the shafts themselves, the protecting veil.
   ═════════════════════════════════════════════════════════════ */
.hero {
  --gut: var(--gut-edge);
  position: relative;
  min-block-size: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* top inset = the chrome it has to clear, plus one rhythm step */
  padding: calc(var(--head-clear) + var(--s-6)) var(--gut) var(--s-6);
  isolation: isolate;
  overflow: hidden;
  background: var(--deep);
}

/* the atmosphere the shafts sit inside. logical insets only, so the
   whole composition mirrors if the document ever runs LTR. */
.hero-depth { position: absolute; inset: 0; z-index: -4; pointer-events: none; }
.hero-depth::before,
.hero-depth::after { content: ""; position: absolute; border-radius: 50%; }
/* core bloom, directly behind the shaft field */
.hero-depth::before {
  inset-block: -14% -6%;
  inset-inline-end: -18%;
  inline-size: 74%;
  background: radial-gradient(50% 50% at 50% 50%, var(--wash-core), transparent 70%);
  filter: blur(46px);
}
/* cold lift in the opposite corner so the dark half is not dead */
.hero-depth::after {
  inset-block-end: -26%;
  inset-inline-start: -14%;
  inline-size: 78%;
  block-size: 64%;
  background: radial-gradient(50% 50% at 50% 50%, var(--wash-far), transparent 72%);
  filter: blur(56px);
}

.blinds, .blinds-fb {
  position: absolute;
  inset-block: -9% -9%;
  inset-inline-end: 0;
  inline-size: min(60vw, 940px);
  z-index: -2;
  block-size: 118%;
}
.blinds { mix-blend-mode: screen; }
/* graceful degradation: static CSS shafts in the same brand ramp */
.blinds-fb {
  z-index: -3;
  background:
    repeating-linear-gradient(90deg,
      rgba(255, 255, 255, .10) 0 3px,
      transparent 3px 16px),
    linear-gradient(112deg, var(--accent-deep), var(--accent) 52%, var(--accent-soft));
  opacity: .55;
  transition: opacity .6s var(--ease);
}
/* The field is anchored to the inline-end edge and must stay opaque
   at the screen edge it bleeds off. Gradients have no logical axis,
   so the falloff is declared per direction rather than hardcoded. */
[dir="rtl"] .blinds-fb {
  -webkit-mask-image: linear-gradient(to right, #000 6%, transparent 80%);
          mask-image: linear-gradient(to right, #000 6%, transparent 80%);
}
[dir="ltr"] .blinds-fb {
  -webkit-mask-image: linear-gradient(to left, #000 6%, transparent 80%);
          mask-image: linear-gradient(to left, #000 6%, transparent 80%);
}
.blinds-ok .blinds-fb { opacity: 0; }

.hero-veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* scrims that protect the corner type only. The field itself is
     left alone, otherwise the brand blue never reads. */
  background: linear-gradient(to bottom,
    rgba(6, 7, 11, .82) 0%, rgba(6, 7, 11, 0) 20%,
    rgba(6, 7, 11, 0) 56%, rgba(6, 7, 11, .9) 100%);
}

.hero-kick { align-self: start; }

.hero-h {
  align-self: center;
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-13);
  line-height: var(--lh-display);
  margin-block: var(--s-6);
  margin-inline-start: -.015em; /* optical flush to the edge */
}
.hero-h .ln { display: block; overflow: hidden; }
.hero-h .ln-i { display: block; }
.hero-h .ln:nth-child(2) { color: var(--ink-dim); }

.hero-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--s-7);
}
.hero-lede {
  max-inline-size: var(--measure-lede);
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-dim);
}
.hero-act {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-5);
  text-align: end;
}
.hero-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s-1) var(--s-5);
  font-size: var(--f-2);
  color: var(--ink-faint);
}

/* ═══ 2 · ARGUMENT ══════════════════════════════════════════════
   A cascade, not three guesses.

   The gutter IS the step: --gut resolves to --indent, so the kicker
   and the first display line share step 1, and every following line
   moves exactly one more step toward the inline-end. The offsets
   read 1x / 2x / 3x, which the eye can count. It used to run gut,
   gut+15vw, gut+46vw - a 15vw move followed by a 31vw move - which
   is why three lines read as three misalignments instead of as a
   designed descent.

   The prose then returns to step 1 and fills the wedge the cascade
   opens, instead of being jammed into the leftover corner beneath
   the largest line at a 46ch scrap of measure. It gets a deck, a
   60ch measure and a full block of air above it.
   ═════════════════════════════════════════════════════════════ */
.arg {
  --indent: var(--gut-mid);   /* the section's local step ... */
  --gut: var(--indent);       /* ... and its gutter is step 1 */
  position: relative;
  padding-block: var(--s-9) var(--s-8);
  padding-inline: 0;
  background: linear-gradient(to bottom,
    var(--deep) 0%, var(--bg-cool) 34%, var(--bg-lift) 100%);
  overflow: hidden;
}
/* one soft plane so the long dark stretch is not a flat wall */
.arg-depth {
  position: absolute;
  inset-block-start: -12%;
  inset-inline-start: -16%;
  inline-size: 72%;
  block-size: 62%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%, var(--wash-far), transparent 70%);
  filter: blur(50px);
}
.arg > *:not(.arg-depth) { position: relative; z-index: 1; }
.arg .kick { padding-inline: var(--gut); }

.arg-h {
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-12);
  line-height: var(--lh-display);
  white-space: nowrap;
}
.arg-h .st {
  display: block;
  /* 1x, 2x, 3x of the one inline step. Nothing else, ever. */
  margin-inline-start: calc(var(--indent) * var(--st));
}
.arg-h .st-1 { --st: 1; }
.arg-h .st-2 { --st: 2; color: var(--ink-dim); }
.arg-h .st-3 { --st: 3; }

.arg-say {
  position: relative;
  z-index: 2;
  margin-inline-start: var(--indent);   /* back to step 1, inside the wedge */
  margin-inline-end: auto;
  margin-block-start: var(--s-7);
  inline-size: min(var(--measure), calc(100% - var(--indent) * 2));
  display: grid;
  gap: var(--s-4);
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-dim);
}
/* The deck. Gives the block its own internal hierarchy so it reads
   as placed copy with a lead-in, not as an undifferentiated slab
   that landed wherever there was room. */
.arg-say > p:first-child {
  max-inline-size: var(--measure-deck);
  font-size: var(--f-4);
  line-height: var(--lh-deck);
  color: var(--ink);
  text-wrap: balance;
}

/* Four rows that span the whole screen: the principle sits on one
   edge, its explanation on the other, and the void between them is
   the composition. No rule, no box, no column of tiles. */
.prins {
  margin-block-start: var(--s-9);
  padding-inline: var(--gut);
  display: grid;
  gap: var(--s-7);
}
.prins li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, var(--measure-note));
  gap: var(--s-2) var(--s-7);
  align-items: baseline;
  padding-inline-start: calc(var(--indent) * var(--st, 0));
}
.prins h3 {
  font-family: var(--font-d);
  font-size: var(--f-7);
  font-weight: 300;
  line-height: var(--lh-head);
  color: var(--ink);
}
.prins p {
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-faint);
}
/* Syncopated so the four rows never lock into a table - but every
   position is a whole multiple of the same step, so they read as
   rhythm rather than as four rows that failed to line up. */
.prins li:nth-child(2) { --st: 2; }
.prins li:nth-child(3) { --st: 1; }
.prins li:nth-child(4) { --st: 3; }

/* ═══ 3 · GALLERY ══════════════════════════════════════════════
   Lead sits at the deepest inset on the page - deliberate
   contrast against the edge-flush sections either side of it.
   ═════════════════════════════════════════════════════════════ */
.gal-lead {
  --gut: var(--gut-deep);
  padding-block: var(--s-8) var(--s-7);
  padding-inline: var(--gut);
  background: var(--bg-lift);
}
.gal-h {
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-10);
  line-height: var(--lh-display);
  max-inline-size: var(--measure-display);
}
.gal-note {
  margin-block-start: var(--s-5);
  max-inline-size: var(--measure-lede);
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-faint);
}

/* the rail. four live demo pages, each the full screen. */
.gal { position: relative; background: var(--bg-lift); }
.gal-pin {
  position: relative;
  block-size: 100vh;
  block-size: 100svh;
  overflow: hidden;
}
.rail {
  display: flex;
  block-size: 100%;
  inline-size: max-content;
  will-change: transform;
}
.panel {
  position: relative;
  flex: none;
  inline-size: 100vw;
  block-size: 100%;
  overflow: hidden;
  background: var(--pf);
  isolation: isolate;
}

/* live preview. the colour field underneath is the fallback: if the
   iframe never loads, the panel is still a full-bleed field, not a card. */
.pv { position: absolute; inset: 0; overflow: hidden; }
.pv-field {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(90% 70% at 70% 20%,
      color-mix(in srgb, var(--pa) 26%, transparent), transparent 70%),
    var(--pf);
}
/* Grid centring, not auto margins: when the item is wider than the
   area, RTL auto-margin resolution collapses it against one edge. */
.pv-scroll {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
/* The frame renders at twice the panel in both axes and is scaled
   back down, so the demo lays out at a real desktop width and its
   viewport-height hero resolves to exactly one panel. Percentages
   keep it correct at every breakpoint; grid placement centres the
   overflow, so no physical left/right is ever named. */
.pv iframe {
  grid-area: 1 / 1;
  border: 0;
  inline-size: 200%;
  block-size: 200%;
  max-inline-size: none;
  transform: scale(.5);
  transform-origin: 50% 50%;
  opacity: 0;
  transition: opacity .9s var(--ease);
  pointer-events: none;
}
.panel.is-ready iframe { opacity: 1; }

/* type over image. wears the demo's own palette, so each panel
   reads as that world rather than as an אילן חוסיד caption. */
.p-type {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: 2;
  padding: var(--s-6);
  color: var(--pi);
}
/* The demo underneath has display type of its own. The scrim has to
   actually clear a stage for the overlay, not just tint it. */
.p-type::before {
  content: "";
  position: absolute;
  inset-block: -30% 0;
  inset-inline: 0;
  z-index: -1;
  background: linear-gradient(to top,
    var(--pf) 0%, var(--pf) 62%, transparent 100%);
}
/* index · sector. the numeral is what makes four panels read as a
   range rather than as four unrelated screenshots. */
.p-niche {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--f-2);
  line-height: var(--lh-label);
  font-weight: 600;
}
.p-num {
  letter-spacing: .16em; /* Latin numerals only */
  opacity: .42;
}
.p-niche span { opacity: .6; }
.p-niche span::before {
  content: "";
  display: inline-block;
  inline-size: 22px;
  block-size: 1px;
  vertical-align: middle;
  margin-inline-end: var(--s-3);
  background: currentColor;
  opacity: .5;
}
/* The panel name is the one all-Latin display line on the page, so
   it gets the Latin leading. Hebrew display never goes this tight. */
.p-name {
  font-family: var(--font-d);
  font-weight: 300;
  font-size: var(--f-13);
  line-height: var(--lh-latin);
  margin-block: .04em .12em;
}
.p-name bdi { letter-spacing: .01em; } /* Latin wordmark only */
.p-reg {
  font-size: var(--f-3);
  line-height: var(--lh-body);
  opacity: .7;
  max-inline-size: var(--measure-lede);
}
.p-go {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  margin-block-start: var(--s-5);
  padding-block-end: var(--s-1);
  font-family: var(--font-d);
  font-size: var(--f-4);
  border-block-end: 1px solid currentColor;
  transition: color .25s var(--ease), gap .25s var(--slow);
}
.p-go:hover { color: var(--pa); gap: var(--s-5); }

/* per-panel travel readout. mobile only - it is the vertical
   counterpart of the rail's own progress rule. */
.p-bar {
  display: none;
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 3;
  block-size: 2px;
  background: color-mix(in srgb, var(--pi) 12%, transparent);
}
.p-bar span {
  display: block;
  block-size: 100%;
  inline-size: 100%;
  transform-origin: 100% 50%;
  background: var(--pa);
}
[dir="ltr"] .p-bar span { transform-origin: 0 50%; }

/* travelling progress. functional readout, not a decorative rule.
   It only means anything while the rail is actually pinned, so it
   is opt-in rather than opt-out. */
.rail-run {
  display: none;
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 6;
  block-size: 2px;
  background: rgba(255, 255, 255, .14);
}
.rail-run span {
  display: block;
  block-size: 100%;
  inline-size: 0%;
  background: var(--accent);
}

/* ═══ 4 · INCLUDED ═════════════════════════════════════════════
   Ragged alternating rows at three scales. The zigzag outline of
   the block is the layout. Tightest gutter on the page.

   The three row widths step on the SAME 1.25 ratio as the type
   scale: 60ch / 75ch / 94ch. That is what makes the rag read as
   three deliberate registers rather than three arbitrary widths.
   ═════════════════════════════════════════════════════════════ */
.inc {
  --gut: var(--gut-tight);
  position: relative;
  padding-block: var(--s-9) var(--s-8);
  padding-inline: 0;
  background: linear-gradient(to bottom,
    var(--bg-lift) 0%, var(--bg) 44%, var(--bg-cool) 100%);
  overflow: hidden;
}
.inc-kick { padding-inline-start: var(--gut); }
.inc-h {
  padding-inline-start: var(--gut);
  margin-block: 0 var(--s-8);
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-10);
  line-height: var(--lh-display);
}

.inc-list { display: grid; gap: var(--s-6); }
/* the biggest rows get room to run long; that is what makes the
   block's outline ragged instead of columnar */
.inc-list li { max-inline-size: min(var(--measure), 94vw); }
.inc-list .s-lg { max-inline-size: min(75ch, 95vw); }
.inc-list .s-xl { max-inline-size: min(94ch, 96vw); }
.inc-list h3 {
  font-family: var(--font-d);
  font-weight: 300;
  line-height: var(--lh-display);
  color: var(--ink);
}
.inc-list p {
  margin-block-start: var(--s-3);
  max-inline-size: var(--measure-note);
  font-size: var(--f-3);
  line-height: var(--lh-note);
  color: var(--ink-faint);
}
.e-s { margin-inline-end: auto; padding-inline-start: var(--gut); }
.e-e {
  margin-inline-start: auto;
  padding-inline-end: var(--gut);
  text-align: end;
}
.e-e p { margin-inline-start: auto; }
/* three registers, three steps apart on the one ladder */
.s-xl h3 { font-size: var(--f-9); }
.s-lg h3 { font-size: var(--f-8); }
.s-md h3 { font-size: var(--f-6); color: var(--ink-dim); }

/* ═══ 5 · THE EDGE ═════════════════════════════════════════════
   Stationary stage. Three beats swap in place while the field
   behind them warms to brand blue. Breathing density.
   ═════════════════════════════════════════════════════════════ */
.edge {
  --gut: var(--gut-deep);
  position: relative;
  background: linear-gradient(to bottom, var(--bg-cool), #08090e);
}
.edge-pin {
  position: relative;
  block-size: 100vh;
  block-size: 100svh;
  overflow: hidden;
}
/* Resting state is ON. The blue rise is an enhancement layered over
   it under .js-motion, never a precondition for the section having
   a ground - authoring `opacity: 0` here unconditionally is the same
   bug class as a hidden headline, just with lower stakes. */
.edge-field {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: .42;
  background:
    radial-gradient(85% 75% at 12% 96%,
      color-mix(in srgb, var(--accent) 40%, transparent), transparent 62%),
    radial-gradient(70% 60% at 96% 6%,
      color-mix(in srgb, var(--accent-deep) 32%, transparent), transparent 66%);
}
.beat {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  align-content: center;
  gap: var(--s-5);
  padding-block: calc(var(--head-clear) + var(--s-5)) var(--s-7);
  padding-inline: var(--gut);
}
.edge-h {
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-11);
  line-height: var(--lh-display);
}
.edge-h2 { font-size: var(--f-10); }
.edge-p {
  display: grid;
  gap: var(--s-4);
  max-inline-size: var(--measure);
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-dim);
}

/* the comparison. plain type and space. no table, no borders. */
.vs { display: grid; gap: var(--s-4); }
.vs li {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s-1) var(--s-7);
  align-items: baseline;
}
.vs b {
  font-family: var(--font-d);
  font-weight: 400;
  font-size: var(--f-4);
  line-height: var(--lh-head);
  color: var(--ink);
}
.vs .no {
  font-size: var(--f-2);
  line-height: var(--lh-note);
  color: var(--ink-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.vs .no.out { text-decoration: none; opacity: .88; }
.vs .yes {
  font-size: var(--f-2);
  line-height: var(--lh-note);
  color: var(--ink);
  font-weight: 600;
}
.sign {
  margin-block-start: var(--s-5);
  font-family: var(--font-d);
  font-weight: 300;
  font-size: var(--f-5);
  line-height: var(--lh-head);
  color: var(--ink-dim);
}

/* ═══ 6 · PROCESS ══════════════════════════════════════════════
   The page's one hard cut to white. A full-bleed paper band
   slices the dark; inside it a single long band drifts on scroll,
   cropped by both viewport edges at every moment.
   ═════════════════════════════════════════════════════════════ */
.proc {
  --gut: var(--s-6);
  position: relative;
  padding-block: var(--s-8) var(--s-8);
  background: var(--deep);
  overflow: hidden;
}
.proc-kick { padding-inline-start: var(--gut); }
/* The band rides ABOVE the fixed vignette (z 88) and below the
   grain (z 90). A vignette is a lens artefact on the dark film;
   let it wash the corners of a white slab and the slab stops
   reading as an overlay and starts reading as a bad scan. Grain
   still crosses it, which is what keeps it in the same film. */
.proc-band {
  position: relative;
  z-index: 89;
  background: var(--paper);
  color: var(--paper-ink);
  padding-block: var(--s-7);
  overflow: hidden;
}
/* the single accent on this screen: the brand ramp as a 2px rule
   on the cut edge, so the white reads as an overlay and not a
   section that lost its background */
.proc-band::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 2px;
  background: linear-gradient(90deg,
    var(--accent-soft), var(--accent) 45%, var(--accent-deep));
}
/* the track opens on the kicker's axis, so step 01 and the section
   label share one optical start. The trailing inset is scroll
   travel, not typography, and stays viewport-relative. */
.proc-track {
  display: flex;
  align-items: flex-start;
  gap: var(--s-6);
  inline-size: max-content;
  padding-inline-start: var(--gut);
  padding-inline-end: 14vw;
  will-change: transform;
}
/* The only viewport-relative value left outside the two ladders.
   It is a track COLUMN WIDTH, not a type size or a gap, and main.js
   derives the horizontal scroll travel from it - snapping it to a
   space step would change approved motion for no typographic gain. */
.step { inline-size: clamp(190px, 21vw, 290px); }
.step-n {
  display: block;
  font-family: var(--font-d);
  font-size: var(--f-1);
  font-weight: 600;
  letter-spacing: .24em; /* Latin numerals only */
  color: var(--paper-faint);
  margin-block-end: var(--s-3);
}
.step h3 {
  font-family: var(--font-d);
  font-weight: 300;
  font-size: var(--f-7);
  line-height: var(--lh-head);
  margin-block-end: var(--s-2);
  color: var(--paper-ink);
}
.step p {
  font-size: var(--f-2);
  line-height: var(--lh-note);
  color: var(--paper-dim);
}
.lnk {
  margin-block-start: var(--s-6);
  color: var(--paper-line);
  align-self: flex-start;
}
.proc-run {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 2px;
  background: rgba(16, 17, 22, .09);
}
.proc-run span {
  display: block;
  block-size: 100%;
  inline-size: 100%;
  transform-origin: 100% 50%;
  background: var(--paper-ink);
}
[dir="ltr"] .proc-run span { transform-origin: 0 50%; }

/* ═══ 7 · CTA ══════════════════════════════════════════════════
   Display line flush to the inline-start edge. The hero's shaft
   field returns, mirrored onto the opposite edge - the page
   closes on the frame it opened with, reversed.
   ═════════════════════════════════════════════════════════════ */
/* Four rows, no row gap: the gap was authored for two and was
   silently applied three times, which pushed the section 180px
   past the viewport and cut the headline in half on the last
   screen of the page. Spacing is per-element; the slack lives in
   the last row so the contacts hang in the far corner. */
.cta {
  --gut: var(--gut-edge);
  position: relative;
  min-block-size: 84svh;
  display: grid;
  grid-template-rows: auto auto auto 1fr;
  gap: 0;
  padding-block: var(--s-8) var(--s-5);
  padding-inline: 0;
  background: var(--deep);
  overflow: hidden;
  isolation: isolate;
}
.cta-shafts {
  position: absolute;
  inset-block: -8% -8%;
  inset-inline-start: 0;
  inline-size: min(56vw, 820px);
  block-size: 116%;
  z-index: 0;
  mix-blend-mode: screen;
}
.cta-field {
  position: absolute;
  inset-block-end: -34%;
  inset-inline-start: -18%;
  inline-size: 88%;
  block-size: 78%;
  z-index: 0;
  background: radial-gradient(50% 50% at 50% 50%,
    color-mix(in srgb, var(--accent) 40%, transparent), transparent 70%);
  filter: blur(34px);
}
.cta-veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(6, 7, 11, .74) 0%, rgba(6, 7, 11, .18) 30%,
    rgba(6, 7, 11, .3) 70%, rgba(6, 7, 11, .78) 100%);
}
.cta > *:not([aria-hidden="true"]) { position: relative; z-index: 2; }

.cta-h {
  padding-inline-start: var(--gut);
  margin-inline-start: -.015em;
  font-family: var(--font-d);
  font-weight: 700;
  font-size: var(--f-12);
  line-height: var(--lh-display);
  align-self: start;
}
.cta-lede {
  padding-inline-start: var(--gut);
  margin-block-start: var(--s-5);
  max-inline-size: var(--measure-lede);
  font-size: var(--f-3);
  line-height: var(--lh-body);
  color: var(--ink-dim);
}
.cta-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-block-start: var(--s-6);
  /* one full step off the headline axis, on purpose and on the unit */
  padding-inline-start: calc(var(--gut) + var(--indent));
}
.cta-lines {
  display: grid;
  gap: var(--s-2);
  align-content: end;
  justify-items: end;
  margin-block-start: var(--s-6);
  padding-inline-end: var(--gut);
  text-align: end;
  font-size: var(--f-2);
  line-height: var(--lh-label);
}
.cta-lines li { display: flex; gap: var(--s-3); align-items: baseline; }
.cta-lines span { color: var(--ink-faint); }
.cta-lines a {
  color: var(--ink-dim);
  border-block-end: 1px solid transparent;
  transition: color .22s var(--ease), border-color .22s var(--ease);
}
.cta-lines a:hover { color: var(--ink); border-block-end-color: var(--ink-ghost); }

/* ── footer ─────────────────────────────────────────────────── */
.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5) var(--s-6);
  padding-block: var(--s-6);
  padding-inline: var(--gut-edge);
  background: var(--deep);
  font-size: var(--f-2);
  line-height: var(--lh-label);
  color: var(--ink-faint);
}
.foot-nav { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }
.foot-nav a { transition: color .2s var(--ease); }
.foot-nav a:hover { color: var(--ink); }
.foot-c { color: var(--ink-faint); }

/* ═══ hidden start states ══════════════════════════════════════
   EVERY hidden start state on this page lives under .js-motion,
   and main.js adds that class only when GSAP is on the page AND
   the visitor has not asked for reduced motion. Any path that
   skips the animation therefore skips the hiding too: the worst
   failure mode is "no animation", never "invisible content".
   Nothing below may be authored unconditionally.
   ═════════════════════════════════════════════════════════════ */
.js-motion [data-fx] { opacity: 0; transform: translateY(22px); }
.js-motion .hero-h .ln-i { transform: translateY(106%); }
.js-motion .hero-kick,
.js-motion .hero-lede,
.js-motion .hero-act { opacity: 0; }
/* the two canvas fields arrive; without motion they are simply on */
.js-motion .blinds,
.js-motion .cta-shafts { opacity: 0; }
/* progress readouts start empty only when something will fill them */
.js-motion .p-bar span,
.js-motion .proc-run span { transform: scaleX(0); }
/* the edge field rises with the pinned stage / the touch scrub */
.js-motion .edge-field { opacity: 0; }
@media (min-width: 861px) {
  .js-motion .rail-run { display: block; }
}

/* ═══ responsive ═══════════════════════════════════════════════
   Narrow screens step DOWN the same two ladders - they never
   invent a value. A cascade that needs three steps of --s-7 at
   1440px needs three steps of --s-5 at 900px and three of --s-3
   on a phone; the rhythm survives, the arithmetic just shrinks.
   ═════════════════════════════════════════════════════════════ */
@media (max-width: 1000px) {
  .hero-foot { grid-template-columns: minmax(0, 1fr); gap: var(--s-6); }
  .hero-act { align-items: flex-start; text-align: start; }
  .hero-strip { justify-content: flex-start; }
  /* one column, but the syncopation survives on a smaller step */
  .prins li {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-2);
    padding-inline-start: calc(var(--s-5) * var(--st, 0));
  }
  .vs li { grid-template-columns: minmax(0, 1fr); gap: var(--s-1); }
}

@media (max-width: 860px) {
  /* The rail degrades to full-viewport vertical panels. No forced
     horizontal scrub on a phone - but the panels are not left
     static either: main.js parallaxes each preview and fills each
     panel's own travel bar as the thumb moves. */
  .gal-pin, .gal.no-pin .gal-pin { block-size: auto; overflow: visible; }
  .rail, .gal.no-pin .rail {
    flex-direction: column;
    inline-size: 100%;
    transform: none !important;
  }
  .panel {
    inline-size: 100%;
    block-size: 90vh;
    block-size: 90svh;
  }
  /* room for the preview to travel without exposing an edge */
  .pv { inset-block: -9% -9%; }
  .p-bar { display: block; }

  /* The caption is short on a phone, so a -30% overhang is only
     ~55px of fade and the demo's own copy ghosts into it. Give the
     scrim a longer run-up. */
  .p-type::before { inset-block: -85% 0; }

  /* On a phone the demo gets to be itself: the frame is the panel's
     own size, so each page lays out at a real phone width and its
     own mobile design is what you see. The desktop 2x-and-scale
     trick exists to force a desktop layout - here that would just
     shrink a mobile layout to half size and make it unreadable. */
  .pv iframe {
    inline-size: 100%;
    block-size: 100%;
    transform: none;
  }

  /* the pinned stage becomes three stacked beats */
  .edge-pin { block-size: auto; overflow: visible; }
  .beat {
    position: static;
    padding-block: var(--s-8);
  }
  .edge-field { position: absolute; }

  /* deep insets are a wide-screen luxury; both sections drop two
     steps so the measure stays readable rather than squeezed */
  .edge     { --gut: var(--s-6); }
  .gal-lead { --gut: var(--s-6); }

  /* Two steps down the ladder, both scales at once: the display
     drops f-12 -> f-10 and the cascade unit drops s-7 -> s-5, so
     the three lines keep their 1x/2x/3x relationship inside a
     375px viewport instead of running off it. */
  .arg    { --indent: var(--s-5); }
  .arg-h  { font-size: var(--f-10); }
  .arg-say { margin-block-start: var(--s-6); }

  .proc-track { padding-inline-end: 30vw; }
}

@media (max-width: 560px) {
  .hero-h { font-size: var(--f-12); margin-block: var(--s-5); }
  .blinds, .blinds-fb { inline-size: 86vw; }
  .cta-shafts { inline-size: 84vw; }
  .p-type { padding: var(--s-5) var(--s-4) var(--s-6); }
  .p-reg { font-size: var(--f-2); }
  .inc-list li, .inc-list .s-lg, .inc-list .s-xl { max-inline-size: 100%; }
  .prins li { padding-inline-start: calc(var(--s-3) * var(--st, 0)); }
  .cta-acts { padding-inline-start: var(--gut); }
  .cta-lines { justify-items: start; text-align: start; padding-inline: var(--gut); }
  .foot { flex-direction: column; align-items: flex-start; }
}

/* ═══ reduced motion ═══════════════════════════════════════════
   .js-motion is never applied here, so no hidden start state is
   ever authored. These rules only unwind the structural bits that
   exist for the pinned layouts.
   ═════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .gal-pin { block-size: auto; overflow: visible; }
  .rail { flex-direction: column; inline-size: 100%; transform: none !important; }
  .panel { inline-size: 100%; block-size: 90svh; }
  .p-bar, .rail-run { display: none; }
  .edge-pin { block-size: auto; overflow: visible; }
  .beat { position: static; }
  .proc-track { transform: none !important; }
  .proc-run span { transform: scaleX(1); }
}


/* ═══ violet register ════════════════════════════════════════════════
   Palette and weight taken from the reference: deep purple ground,
   violet accent, BOLD display type rather than light. Glow behind the
   headline is what makes that reference feel lit rather than printed.
   ═════════════════════════════════════════════════════════════════ */
.hero { position: relative; overflow: hidden }
.hero::before {
  content: ""; position: absolute; z-index: -3; pointer-events: none;
  inline-size: 120%; block-size: 90%;
  inset-block-start: -18%; inset-inline-end: -22%;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--accent) 46%, transparent),
    color-mix(in srgb, var(--accent-deep) 22%, transparent) 58%,
    transparent 78%);
  filter: blur(18px);
}
.hero-h b, .arg-h b, .gal-h b, .inc-h b, .edge-h b, .cta-h b { color: var(--accent-soft) }

/* A pill under the headline, the way the reference marks its promise. */
.hero-kick {
  /* inline-block alone is not enough: as a grid item it still stretches to
     the track. justify-self + fit-content makes it hug its own text. */
  display: inline-block;
  justify-self: start;
  inline-size: fit-content;
  max-inline-size: fit-content;
  padding: .5em 1.25em;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  color: var(--accent-soft);
}

/* Buttons go solid violet with a rounded pill shape, not hairline boxes. */
.go, .btn, .cta-acts a:first-child {
  border-radius: 999px;
}

/* Real screenshots instead of live iframes: same picture, a fraction of the
   weight, and nothing to fail at load. The palette field stays on top as a
   tint so each panel still reads in its demo's own colour. */
.pv { position: relative; overflow: hidden }
.pv-shot {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%;
  object-fit: cover; object-position: top center;
}
.pv-field { position: absolute; inset: 0 }

/* ═══ process · vertical on phones ═══════════════════════════════════
   The band is a horizontally scrubbed track. On a narrow viewport only
   two of the five steps ever fit, and the section is too short for the
   scrub to travel far, so steps 01/02/05 were unreachable and the copy
   clipped at the edge. On a phone the track becomes an ordinary stack.
   The JS tween is skipped at the same breakpoint (see main.js).
   ═════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  .proc-band { overflow: visible }
  .proc-track {
    flex-direction: column;
    inline-size: auto;
    max-inline-size: 100%;
    gap: var(--s-5);
    padding-inline: var(--gut);
    transform: none !important;   /* GSAP must not leave an offset behind */
  }
  .step {
    inline-size: auto;
    max-inline-size: 100%;
    padding-block-end: var(--s-5);
    border-block-end: 1px solid rgba(255,255,255,.12);
  }
  .step:last-child { border-block-end: 0 }
  .step p { max-inline-size: 46ch }
  .proc-run { display: none }     /* a progress bar for a track that no longer moves */
}

/* ═══ light-dominant structure ═══════════════════════════════════════
   The reference is a WHITE page with dark bands, not a dark page. That
   structural difference - not the hue - is what made every dark build
   read as heavy. Body is light; three sections invert.
   ═════════════════════════════════════════════════════════════════ */
html, body { background: #fff; color: var(--ink); }

/* The three dark bands REDEFINE the ink tokens rather than patching
   individual selectors. Patching is how the hero's second headline line
   ended up dark-on-dark: it reads --ink-dim, which the light theme had
   flipped to a dark value. Any element inside a band now inherits light
   ink automatically, including ones added later. */
.hero, .edge, .cta, .foot {
  --ink:       #ffffff;
  --ink-dim:   rgba(255, 255, 255, .72);
  --ink-faint: rgba(255, 255, 255, .48);
  --ink-ghost: rgba(255, 255, 255, .16);
  background: var(--deep);
  color: #fff;
}
.hero *, .edge *, .cta *, .foot * { border-color: rgba(255,255,255,.18) }
.hero .hero-kick { color: var(--accent-soft) }
.hero-h b, .edge-h b, .cta-h b { color: var(--accent-soft) }
.hero .go, .cta .btn { color: #fff }
.hero .go::after, .cta .btn::after { background: rgba(255,255,255,.5) }

/* light sections carry the accent as ink, not as glow */
.arg, .gal-lead, .gal, .inc, .proc { background: #fff; color: var(--ink) }
.arg-h b, .gal-h b, .inc-h b { color: var(--accent-deep) }
.arg .kick, .gal-lead .kick, .inc .kick, .proc-kick { color: var(--accent-deep) }
.arg-say p, .gal-note, .inc-item p, .step p { color: var(--ink-dim) }
.prins li h3, .inc-item h3, .step h3 { color: var(--ink) }
.arg-depth { display: none }          /* a dark-page glow on a white page */

/* header follows the section under it rather than assuming dark */
.head {
  background: rgba(255,255,255,.86);
  border-block-end: 1px solid rgba(11,14,20,.10);
}
.mark { color: var(--ink) }
.head-cta { background: var(--accent-deep); color: #fff; border: 0 }

/* process steps sit on white now */
@media (max-width: 760px) {
  .step { border-block-end-color: rgba(11,14,20,.12) }
}


/* Header sits over the dark hero at the top of the page but over white
   further down, so it cannot assume either. Solid dark while the hero is
   behind it; main.js already toggles .is-lit on scroll for other reasons,
   so reuse that rather than adding a second observer. */
.head { background: rgba(11,14,20,.82); border-block-end-color: rgba(255,255,255,.12) }
.head .mark { color: #fff }
.head-cta { background: var(--accent); color: #0B0E14; border-radius: 999px; padding: .6em 1.4em }
.head-cta:hover { background: #fff }

/* .foot is a dark band too - it reads --ink-faint, which the light theme
   flipped to rgba(11,14,20,.48). Over the same #0B0E14 ground that resolves
   to an identical colour: 1.00:1, invisible. It now redefines its ink with
   the other bands, so this cannot drift again. */
.foot-nav a, .foot-c { color: rgba(255,255,255,.62) }
.foot-nav a:hover { color: #fff }

/* ═══ MOTION LAYER ═══════════════════════════════════════════════════
   Bigger display type, masked line reveals on every heading, a ticker,
   parallax on the work shots, and a live card. All hidden start states
   live under .js-motion so the failure mode is "no animation", never
   "invisible page".
   ═════════════════════════════════════════════════════════════════ */

/* type goes up a gear */
.hero-h { font-size: clamp(46px, 11.2vw, 196px); letter-spacing: -.015em }
.arg-h, .cta-h { font-size: clamp(40px, 8.6vw, 150px); letter-spacing: -.012em }
.gal-h, .inc-h, .edge-h { font-size: clamp(34px, 6.4vw, 104px); letter-spacing: -.01em }

/* masked line reveal · the mask is the effect, not a fade */
.arg-h .ln, .gal-h .ln, .inc-h .ln, .edge-h .ln, .cta-h .ln {
  display: block; overflow: hidden;
}
.arg-h .ln-i, .gal-h .ln-i, .inc-h .ln-i, .edge-h .ln-i, .cta-h .ln-i {
  display: block;
}
.js-motion .ln-i { transform: translateY(110%); }
.ln-i.up {
  transform: none;
  transition: transform 1s cubic-bezier(.16,1,.3,1);
}

/* ── ticker · a moving band of what actually goes into a page ─────── */
.ticker {
  overflow: hidden;
  padding-block: var(--s-5);
  background: var(--deep);
  border-block: 1px solid rgba(255,255,255,.10);
  --tick: #ffffff;
}
.ticker-run {
  display: flex; align-items: center; gap: var(--s-5);
  inline-size: max-content;
  will-change: transform;
  animation: tick 34s linear infinite;
}
.ticker-run span {
  font-family: var(--font-d); font-weight: 700;
  font-size: clamp(24px, 3.4vw, 54px);
  color: var(--tick); white-space: nowrap; opacity: .92;
}
.ticker-run i {
  inline-size: 9px; block-size: 9px; border-radius: 50%;
  background: var(--accent); flex: 0 0 auto;
}
@keyframes tick { from { transform: translate3d(0,0,0) } to { transform: translate3d(50%,0,0) } }

/* ── the work shots · parallax inside their frame, live on hover ──── */
.pv { overflow: hidden }
.pv-shot {
  transform: scale(1.14) translateY(var(--par, 0px));
  transition: transform .7s cubic-bezier(.16,1,.3,1), filter .5s var(--ease);
  filter: saturate(.96);
}
.panel:hover .pv-shot { transform: scale(1.2) translateY(var(--par, 0px)); filter: saturate(1.06) }
.panel .p-name { transition: transform .45s cubic-bezier(.16,1,.3,1) }
.panel:hover .p-name { transform: translateX(calc(var(--s-2) * -1)) }

/* ── a sharper card edge ─────────────────────────────────────────── */
.panel { transition: transform .5s cubic-bezier(.16,1,.3,1) }
.panel:hover { transform: translateY(-8px) }

@media (prefers-reduced-motion: reduce) {
  .js-motion .ln-i { transform: none }
  .ticker-run { animation: none }
  .pv-shot, .panel, .panel:hover, .panel:hover .pv-shot { transform: none; transition: none }
}

/* the comparison labels its columns once instead of repeating them per row */
.vs-head b { min-block-size: 0 }
.vs-head span { font-weight: 700; opacity: .55; font-size: var(--f-2) }
.vs-head { border-block-end: 1px solid rgba(255,255,255,.2); padding-block-end: var(--s-2) }

/* ═══ fewer words, read bigger ═══════════════════════════════════════
   The page lost about a third of its copy. What survives is the load-
   bearing line in each section, so it steps up the ladder rather than
   staying at body size and floating in the space the cuts opened.
   ═════════════════════════════════════════════════════════════════ */
.hero-lede { font-size: var(--f-5); max-inline-size: 24ch }
.gal-note  { font-size: var(--f-4); max-inline-size: 26ch }
.arg-say p { font-size: var(--f-5); max-inline-size: 22ch }
.edge-p p, .edge-p { font-size: var(--f-4); max-inline-size: 26ch }
.cta-p     { font-size: var(--f-4) }
.prins li h3, .inc-item h3 { font-size: var(--f-6) }
.prins li p, .inc-item p, .step-p { font-size: var(--f-3); max-inline-size: 28ch }
.sign { font-size: var(--f-6) }

/* The cascade steps 1x/2x/3x of --indent. On a phone the third line starts
   3 steps in and its text is the longest of the three, so its glyphs ran off
   the inline edge - the box fit, the letters did not. Below 700px the ladder
   compresses to 0/1/2 half-steps: the cascade still reads as a cascade, and
   every word survives. */
@media (max-width: 700px) {
  .arg-h .st-1 { margin-inline-start: 0 }
  .arg-h .st-2 { margin-inline-start: calc(var(--indent) * .5) }
  .arg-h .st-3 { margin-inline-start: var(--indent) }
  .arg-h { font-size: clamp(30px, 8.2vw, 54px) }
}
