/* ============================================================================
   landing.css: v2. Page-scoped styles for the public landing (DESIGN.md §7;
   the Phantom/Duolingo engagement formula on the Wezy laws).
   Mobile-FIRST: every rule below is the phone experience; ≥768px enhances.
   Tokens only; logical properties only.
   ========================================================================== */

/* =================== THE AMBIENT JOURNEY (the living canvas) ===================
   A FIXED, full-viewport stack of three soft AURORA scenes (tokens:
   --bg-depth, --bg-lift, --bg-warm; grain-free warm light; the hero keeps
   its own painted wash: the journey runs from the card story DOWN). app.js (armAmbience) sets ONE
   active scene from the section under the viewport center; layers crossfade
   on --motion-morph, opacity only (compositor; the fixed layers never
   repaint on scroll), reduced motion collapses it to an instant switch, and
   no-JS keeps the server-rendered dawn. The §11 lane: a reversible
   COLOR/LIGHT state; the LIFT scene alone additionally drifts (the
   operator-sanctioned living pools below), the other scenes stay still. */
.ambience {
  position: fixed;
  inset: 0;
  z-index: -1; /* above the body fill, below all content */
  pointer-events: none;
}

.ambience-layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* LINEAR (not a decelerate curve) so a scene change mid-fade re-targets seamlessly: a
     constant-rate opacity crossfade has no acceleration to stutter when rapid scroll outruns it;
     --motion-ambience (snappier than the 2s band morph) keeps the fade TRACKING the scroll rather
     than trailing + blending three scenes on a fast up/down flick. */
  /* VISIBILITY RIDES THE FADE so an invisible scene costs NOTHING. opacity:0 still leaves a
     full-viewport layer in the compositor: measured on the closer's scroll-linked rocket,
     the three-layer stack cost 32% long frames against 7% with the ambience removed, and
     that gap was there whichever scene was active. Pairing visibility with the opacity
     transition (delayed OUT by the fade's own duration, immediate IN) lets the engine skip
     the two scenes that are not showing, while the crossfade itself is untouched: during a
     fade BOTH layers are `visible`, so the blend is identical to before. */
  visibility: hidden;
  transition:
    opacity var(--motion-ambience) var(--ease-linear),
    visibility 0s linear var(--motion-ambience);
  /* promote each scene to its OWN compositor layer (the lag fix): the full-viewport
     radial+linear gradient then rasterizes ONCE to a GPU texture, so the crossfade BLENDS
     textures instead of REPAINTING the gradient every frame, and this fixed layer is not
     re-rasterized on scroll (the iOS-Safari fixed-element-repaint cost). A justified 4th
     will-change site (perf budget): these layers are core animated atmosphere. */
  will-change: opacity;
  transform: translateZ(0);
}

.ambience-layer[data-layer="depth"] { background: var(--bg-depth); }
.ambience-layer[data-layer="lift"] { background: var(--bg-lift); overflow: hidden; }
.ambience-layer[data-layer="warm"] { background: var(--bg-warm); }

/* THE LIVING LIFT SCENE (operator-directed; joins the rainbow key as the second
   sanctioned ambient loop — this supersedes the "nothing translates, nothing loops" line for
   THIS scene): two blurred rainbow pools DRIFT and cross on their own non-harmonic clocks
   over the quiet --bg-lift horizon, so the showcase ground moves fluidly on its own — alive
   and present, bottom-anchored so it never fills the section. Compositor-only (translate/
   scale on pre-rasterized blurred pseudos); the scene's opacity gate still decides WHEN it
   shows, reduced motion parks the drift and keeps the painted horizon. */
.ambience-layer[data-layer="lift"]::before,
.ambience-layer[data-layer="lift"]::after {
  content: "";
  position: absolute;
  inset-block-end: -10%;
  block-size: 66%;
  inline-size: 78%;
  border-radius: 50%;
  filter: blur(52px);
  pointer-events: none;
}

/* the cool pool: blue arcing through cyan into teal, home on the physical left */
.ambience-layer[data-layer="lift"]::before {
  inset-inline-start: -10%;
  background: var(--rainbow-pool-cool);
  animation: lift-drift-cool 19s ease-in-out infinite alternate;
}

/* the warm pool: green through amber into gold, home on the physical right */
.ambience-layer[data-layer="lift"]::after {
  inset-inline-end: -10%;
  background: var(--rainbow-pool-warm);
  animation: lift-drift-warm 14.5s ease-in-out infinite alternate;
}

@keyframes lift-drift-cool {
  from { translate: -6vw 2vh; scale: 0.92; }
  to { translate: 11vw -4vh; scale: 1.14; }
}

@keyframes lift-drift-warm {
  from { translate: 7vw -3vh; scale: 1.12; }
  to { translate: -10vw 3vh; scale: 0.9; }
}

/* THE DRIFT RUNS ONLY WHILE ITS SCENE IS ON SCREEN. Left always-running, these two large
   blurred layers cost a raster every frame even at opacity 0 — measured on the closer's
   scroll-linked rocket: 25% of frames ran long with the scene invisible-but-animating, 0%
   with the layer absent, and neither the blur, the clip, nor layer promotion moved that
   number. `opacity: 0` hides a layer; it does not stop its animations, and the reader felt
   the difference as judder in a completely different section. Pausing by default and
   running only under the active scene is the same trick the source site uses for its own
   off-screen sections, and it changes nothing about how the scene looks while it shows. */
.ambience-layer[data-layer="lift"]::before,
.ambience-layer[data-layer="lift"]::after {
  animation-play-state: paused;
}

.ambience[data-scene="lift"] .ambience-layer[data-layer="lift"]::before,
.ambience[data-scene="lift"] .ambience-layer[data-layer="lift"]::after {
  animation-play-state: running;
}

/* both motion-off signals kill the drift (the strobe wall — the OS preference and the
   platform's own :root.a11y-motion menu); the painted horizon stays in both */
@media (prefers-reduced-motion: reduce) {
  .ambience-layer[data-layer="lift"]::before,
  .ambience-layer[data-layer="lift"]::after {
    animation: none;
  }
}

:root.a11y-motion .ambience-layer[data-layer="lift"]::before,
:root.a11y-motion .ambience-layer[data-layer="lift"]::after {
  animation: none;
}

.ambience[data-scene="depth"] .ambience-layer[data-layer="depth"],
.ambience[data-scene="lift"] .ambience-layer[data-layer="lift"],
.ambience[data-scene="warm"] .ambience-layer[data-layer="warm"] {
  opacity: 1;
  visibility: visible;
  transition:
    opacity var(--motion-ambience) var(--ease-linear),
    visibility 0s; /* IN is immediate: the layer must be paintable before it fades up */
}

/* (the frontpage header scale moved to components.css "THE FUNNEL HEADER SCALE",
   the shell-component law: a page sheet never styles the shared chrome; the ramp now rides the
   .shell-glass funnel hook across the landing + login + register as ONE component.) */

/* =================== HERO: lit from above, ONE spark prompt =================== */
/* THE HERO CLUSTER IS CENTRED IN ITS OWN BOX, on every device. Growing the ground to a full
   desktop screen moves only the hero's BOTTOM edge, so the cluster kept its padding offset from
   the top and left ~400px of bare ground beneath the CTAs at 1920x1080. Centring re-balances it.
   `safe` centring, never plain: plain `center` overflows in BOTH directions, so a cluster taller
   than its box (narrow widths, or the a11y text-scale presets) would push its own headline up
   behind the sticky topbar with no way to scroll back. `safe` degrades to start in that case.
   On phones the box is content-driven, so this is a no-op there: the cluster already fills it. */
.hero {
  position: relative; /* the cream backdrop ::before positions against the hero box */
  background: var(--bg-hero-landing); /* the shared funnel ground + the settle (tokens.css):
     (user call) the hero rides the SAME var(--bg-hero-lit) base the auth
     pages paint, plus only the settle band into the landing ground: hero and funnel are one
     voice by token reference */
  display: grid;
  align-content: safe center;
  padding-block-start: min(var(--section-pad), 7svh); /* cadence, but yields on short screens */
  /* the bottom additionally pays for the hero's dedicated gradient-transition band
     (--hero-settle-band, tokens.css): the settle layer spans exactly this space, so the ground
     melts into the page over a real runway instead of compressing into a smudge (user call). */
  padding-block-end: calc(min(var(--section-pad), 7svh) + var(--hero-settle-band));
  /* THE HERO RAIL: the shared --funnel-rail (tokens.css), wider than the 1080 container,
     which on a ~1990px screen left about 900px of dead margin and starved BOTH columns. The
     funnel HEADER rides the same token, so bar and hero share one edge; every other band
     keeps the standard rail. */
  --hero-rail: var(--funnel-rail);
  /* THE COPY MEASURE IS THE ANCHOR: one width that the headline, the subline and the button
     row ALL resolve to, so their inline-end edges line up instead of stepping.

     Why a MEASURE and not a font-size: each block's painted width is its character count times
     its size. The headline is 20 characters (9.97x its size); the subline is 35 (17.1x). Two
     independent sizes therefore produce a staircase (measured, 259px of step at 1999) and no
     choice of ratio fixes it except the one where the widths agree. Dividing ONE measure by
     each block's own character ratio makes the edges align by construction, at every width.
     The 1.71 title:sub ratio is that arithmetic, not a taste call. */
  --copy-measure: min(84vw, 600px);   /* phones: the measure IS the rail (one column) */
  /* THE STACKED POSTER (phones + portrait tablets; operator level-up): the title
     balance-wraps to TWO stacked display lines while the hero is single-column, closing the
     measured 767→768 seam where the old flip dropped the title 57px→25px. The widest wrapped
     line ("זירת העסקים") measures 5.48x its font-size; 6.1 leaves ~10% headroom so balance
     always lands the same two lines; 92px is the stacked cap. The ≥1024 stage re-derives ONE
     nowrap line from its own wider measure (the operator's call: desktop reads one line). */
  --hero-title: min(calc(var(--copy-measure) / 6.1), 92px);
  /* the button row rides its label (row ≈ 21.4x label, measured); 22.3 keeps the row ending
     with the text blocks; the 34px cap is the label's saturation partner. The 21px FLOOR
     (was 17) is the phone's gain from the same call: the divisor only starts winning past
     ~470px, so below that the floor IS the label size. */
  --hero-label: max(21px, min(calc(var(--copy-measure) / 22.3), 34px));
  /* the round bottom corners: MATCH the marketplace/search heroes (--space-5 / 40px; user's call: "make
     them match the features rounding"). The corner ARCS READ round because the cream backdrop below them
     shows through (a navy body otherwise hid the gaps navy-on-navy). overflow:clip was REMOVED so that
     backdrop isn't clipped to the rounded shape; the rounded fill is the border-radius's job (it clips
     the background); content stays inside the box on its own. */
  border-end-start-radius: var(--space-5);
  border-end-end-radius: var(--space-5);
}

/* the CREAM BACKDROP: the ONLY thing made cream (the user's call: just the hero banner). A z-index:-1
   layer scoped to the HERO BOX ALONE, behind the navy fill, so the hero's rounded bottom corners reveal
   cream and read ROUNDED. It NEVER touches the body or the fixed ambient layers (which is why the
   whole-body-cream attempt bled gray through the semi-transparent ambient crossfade, reverted); below
   the hero the ambient is untouched. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--cream-landing); /* the darker landing ground: MUST match .ticker (the corner seam) */
}

.hero-inner {
  display: grid;
  /* SPLIT BY AXIS. The single `gap` used a 3svh cap, a HEIGHT term governing what is a
     HORIZONTAL gap on desktop, which crushed it to 31px while the outer margins sat at 317px
     each; the pair read as glued together in an empty field. The column gap now rides WIDTH
     (the axis it actually spans) and only the row gap, which exists when the pose stacks above
     the copy on phones, yields to a short screen. */
  column-gap: clamp(var(--space-4), 4vw, 96px);
  row-gap: min(var(--space-6), 3svh);
  align-items: center;
  justify-items: center;
  /* ONE EXPLICIT FULL-WIDTH TRACK. Left implicit, the column sized itself to the nowrap
     headline's min-content width (342px inside a 359px rail), so every item centred inside an
     UNDERSIZED track rather than on the page: the pose measured 31px off centre. minmax(0,1fr)
     pins the track to the rail so centring is centring on the page. */
  grid-template-columns: minmax(0, 1fr);
  text-align: center;
  inline-size: var(--hero-rail);
  max-inline-size: none;  /* overrides the shared .container cap for THIS page's hero only */
  margin-inline: auto;    /* the cluster stays horizontally centred on the page */
}

/* ================= THE HERO SCALE: ONE MEASURE, EVERY ELEMENT DERIVED =================
   Every hero metric derives from --copy-measure with its own measured divisor, so the whole
   cluster grows as a UNIT and the parts stay in proportion at every width — continuous within
   each arm (the §13 ramp law); the 1024 flip changes the COMPOSITION (stacked poster → the
   one-line pair stage), so the type formula changes with it by design.

        metric        @390 (stacked)   @1440 (stage, measure 806)   saturation
        title          54  (2 lines)    76.8 (1 line)                92 / 940-measure
        subline        18.2 (bold)      44.8                         (measure/18)
        CTA label      17               32 (capped)                  32
        CTA box        64               96  (label x 3)              96
   ======================================================================================== */
.hero-title {
  /* TWO STACKED DISPLAY LINES, every width (text-wrap: balance splits at the natural
     "זירת העסקים / של ישראל" beat); the size is DERIVED from the widest line's measured
     5.48x ratio (--hero-title above), never guessed. Was one nowrap line at measure/10.5 —
     the poster level-up IS the change (the seam data lives with --hero-title). */
  font-size: var(--hero-title);
  text-wrap: balance;
  /* the measure BOUNDS the box: without it the title's one-line max-content sizes the desktop
     grid track (measured: 1024 overflowed the rail and squeezed the mascot to 283px; 1920
     fell back to a single 913px line) — the cap is what makes balance actually break. */
  max-inline-size: var(--copy-measure);
  font-weight: var(--w-display);
  line-height: var(--leading-tight);
}

.hero-sub {
  margin-block-start: min(var(--space-5), 3svh); /* air under the headline, yields when short */
  /* BOLD (operator call): at --w-heading the widest of its two lines
     measures 17.3x its size (re-measured at 700; was 17.03 at 500); 18 gives ~4% headroom
     and holds the 1.71 title:sub construction ratio on the one-line stage (10.5/18) —
     uncapped, so the pair's edges keep ending together at every desktop width. */
  font-size: max(18px, calc(var(--copy-measure) / 18));
  max-inline-size: var(--copy-measure);
  font-weight: var(--w-heading);
  line-height: var(--leading-loose);
  color: var(--white); /* white under the headline; gold is for accents */
}

/* ONE spark CTA dominates, full-width on the phone (Duolingo/Fogg §9);
   the quiet secondary sits under it */
.hero-ctas {
  margin-block-start: min(var(--space-6), 4svh);
  inline-size: var(--copy-measure);   /* the third block resolves to the same measure */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  max-inline-size: 460px;
  margin-inline: auto;
}

/* BIGGER hero CTAs (scoped to the hero: the global .btn is untouched): taller + a larger label so the
   spark dominates the banner (logged-out AND logged-in both flow through here). flex-shrink:0 keeps each
   label on ONE line beside the now-bigger Rishi; the row wraps gracefully only if it truly must. */
.hero-ctas .btn {
  /* the box follows its own LABEL (3.3x it), not a second scale system: one anchor for the
     whole cluster. Floor 72px (the "bigger buttons" call; was 58, then 64) stays
     clear of the 48px tap minimum and keeps the key reading substantial on the smallest
     phone; the LABEL stays pinned to --hero-label; growing it would break the aligned-edges
     construction above. */
  min-block-size: max(72px, calc(var(--hero-label) * 3.3));
  /* natural width: the label divisor above already lands the pair on the shared measure, so
     no stretching is needed (and stretching is what made the keys read as over-long) */
  flex: 0 0 auto;
  padding-inline: clamp(var(--space-4), 1.6vw + 0.7rem, var(--space-5));
  font-size: var(--hero-label); /* the 17px floor lives in the token itself */
  flex-shrink: 0;
  white-space: nowrap;
}

/* Rish stands in his light pool (the halo below), no edge tricks; the rhythm
   stays honest and the depth comes from the light */
/* CENTRED EXPLICITLY. `justify-self: center` centres the grid ITEM, but this wrapper
   shrink-wraps its picture while the hand-drawn hint is absolutely positioned outside that
   box, so the item's box centred while the drawing sat 15px off. A grid with centred items
   centres the picture itself, which is what the eye actually tracks. */
.hero-rishi {
  justify-self: center;
  display: grid;
  justify-items: center;
  inline-size: 100%;
  position: relative;
  z-index: 0;
}

/* THE LIGHT POOL RIDES THE PICTURE, not the column. It hung off .hero-rishi, which spans
   the FULL grid track (100%), so `closest-side` resolved against a wide box and the pool
   painted as a horizontally STRETCHED ellipse that grew with every width (operator-caught).
   The key anchor shrink-wraps the square img exactly, so the same inset there
   is square by construction at every scale, and the gradient reads as a round glow. */
.hero-key-anchor::before {
  content: "";
  position: absolute;
  inset: -12%;
  z-index: -1;
  background: var(--halo-gold);
  pointer-events: none;
}

/* the mascot rides the SAME schedule as the copy (380px at 390 → 640px at 1440) so it grows
   in step with the headline instead of jumping at a breakpoint. ONE ramp replaces the former
   320px/520px pair, which stepped at 768 and left the pose out of proportion either side of it. */
.hero-rishi img {
  /* fills its own column so it reads BIG, with a height ceiling so it can never be what pushes
     the cluster past the fold: the pose is the element that yields when the screen is short */
  /* PHONES KEEP A LARGE POSE. An earlier pass drove this to 22svh (186px at 390x844) so the
     cluster would fit one screen, but the pose is the BRAND element, and shrinking it 42%
     below its previous 320px to satisfy an overflow boolean made the section worse, not
     better. On phones the pose stacks below the copy, so the hero simply runs taller than one
     screen there; that is the correct trade, and it is what this hero did before. */
  max-block-size: min(46svh, 380px);
  inline-size: auto;
  max-inline-size: 100%; /* never overflow the column horizontally (scales down on a narrow desktop) */
}

/* ---- THE KEY-HOLE THEME TOGGLE: the sun/moon key set INTO the bow hole of Rishi's
   key, so an anonymous visitor can play with the theme. The anchor shrink-wraps the
   IMG exactly (inline-block + block img: no baseline descender gap), so every %
   inset below is a fraction OF THE PICTURE and the slot tracks the hole at every
   scale. The fractions are MEASURED from the asset's alpha channel (hole center
   86.42%, 19.75%; diameter ~8.5%): change the art, re-measure, never eyeball.
   RTL: inset-inline-end = physical LEFT (the image never mirrors). ---- */
.hero-key-anchor {
  position: relative;
  display: inline-block;
}
.hero-key-anchor img { display: block; }

.hero-key-slot {
  position: absolute;
  /* the hole center X (physical left): alpha-measured 86.42%, then +0.22% (≈1px at the 1440
     render, physically RIGHT): the circle sat a pixel left of the hole (the user's
     fit calibration; in RTL a LARGER inset-inline-end/`left` moves the slot right) */
  inset-inline-end: 86.64%;
  inset-block-start: 19.75%;     /* the hole center Y */
  inline-size: 11%;              /* a touch over the 8.5% hole, so the key reads SET INTO the bow */
  aspect-ratio: 1;
  transform: translate(-50%, -50%); /* physical: center the slot ON the hole */
  z-index: 3;                    /* above the hint: the key wins where the arrow tip meets it */
}
.hero-key-slot .theme-toggle {
  position: relative;            /* the ::after tap extender anchors here */
  inline-size: 100%;
  block-size: 100%;
}
/* the visual key scales with the picture (≈30px at the smallest 320 render), so an
   invisible extender keeps the EFFECTIVE target at the ≥44-48px floor (DESIGN §10) */
.hero-key-slot .theme-toggle::after {
  content: "";
  position: absolute;
  inset: -30%;                   /* %-of-PADDING-box: clears the 44px floor at the 320 render */
  border-radius: var(--r-full);
}
.hero-key-slot .theme-toggle svg {
  inline-size: 68%;
  block-size: 68%;
}

/* the hand-drawn nudge: ONE svg (text + curve arrow) positioned as image fractions,
   so the whole drawing scales with the picture; currentColor rides --gold-bright,
   which is champagne on the dark hero and deep brown on the beige one (§2.8). */
.hero-key-hint {
  position: absolute;
  inset-inline-end: 35%;         /* the drawing's physical-left edge */
  inset-block-start: 1%;
  inline-size: 50%;
  color: var(--gold-bright);
  pointer-events: none;
  z-index: 2;
}
.hero-key-hint text {
  font-family: var(--font-ui);
  font-weight: var(--w-heading);
}
/* the staggered playful pair: the small opener, then the bigger punchier "עלי"
   (sizes in viewBox units, so the drawing scales as one) */
.hero-key-hint .hint-w1 { font-size: 25px; }
.hero-key-hint .hint-w2 { font-size: 32px; }

/* LTR TWINS (the pose is a PHOTO, never mirrored: the key stays physically RIGHT in both
   directions, so both fractions above must land on the SAME physical side under LTR).
   · the two insets are calibrated as physical-LEFT fractions, which `inset-inline-end`
     spells under RTL and `inset-inline-start` spells under LTR.
   · an svg <text> anchors at the run's START, i.e. its RIGHT edge under RTL (what the two
     `x` values above are) and its LEFT edge under LTR: anchoring at the END restores the
     same two word positions instead of letting the words run off the viewBox. */
html[dir="ltr"] .hero-key-slot { inset-inline-end: auto; inset-inline-start: 86.64%; }
html[dir="ltr"] .hero-key-hint { inset-inline-end: auto; inset-inline-start: 35%; }
html[dir="ltr"] .hero-key-hint text { text-anchor: end; }

/* =================== TRUST CHIPS: centred directly under the hero cluster ===================
   Moved INTO the hero (user call): the three cues sit right under the hero elements,
   centred, inheriting the hero's own ground (no separate cream band). */
.hero-trust {
  margin-block-start: min(var(--space-6), 4svh);
  color: var(--white); /* the hero-sub token pair: white on the navy hero, ink on the beige one */
}

/* ONE flexible row (operator call: the cues SPAN the rail, dynamically scaled):
   the row escapes the 1080 container onto the hero rail and never wraps; the chip font rides
   a fitted ramp derived from the painted sum (27.9x font + 157, measured), so the three cues
   fit one row by construction at every >=768 width and space-between spreads the slack.
   Phones keep the stacked wrap arm above. */
@media (min-width: 768px) {
  /* the class pair outranks the later .ticker-row base (equal-specificity order trap,
     measured: bare .hero-trust lost wrap/gap/justify to it) */
  .ticker-row.hero-trust {
    inline-size: var(--hero-rail);
    max-inline-size: none;
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 0;
  }

  .hero-trust .ticker-chip {
    /* fitted against the rail MINUS the container's inline padding (measured: forgetting it
       let flex-shrink fold the chip text at 1024); nowrap + no-shrink keep the fit honest */
    font-size: clamp(15px, 3.1vw - 8px, 30px);
    white-space: nowrap;
    flex: 0 0 auto;
  }
}

.ticker-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  /* generous breathing room between the (now much larger) cues; on mobile they stack and the row gap
     spaces them vertically. */
  gap: var(--space-4) var(--space-6);
}

.ticker-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3); /* the larger gold check needs more room from its text */
  padding: var(--space-1) var(--space-2);
  border-radius: var(--r-full);
  /* no fill, no ring; quiet trust cues, not buttons: just the gold double-check + ink text resting on
     the band. SIGNIFICANTLY larger (was --text-caption) + heading-weight = a confident trust statement
     that scales smoothly desktop↔mobile (clamp floors at lead/18 on phones, caps at h2/24 on desktop). */
  background: none;
  border: none;
  /* upsized with the poster cluster: floor 20 → cap 30, riding the same growth */
  font-size: clamp(20px, 3vw, 30px);
  font-weight: var(--w-heading);
  line-height: var(--leading-tight);
}

.ticker-chip svg {
  /* em-proportional: the gold check scales WITH its own chip's fitted font on every arm */
  inline-size: 1.35em;
  block-size: 1.35em;
  flex: 0 0 auto; /* the prominent gold double-check never shrinks */
  color: var(--gold-bright); /* the hero accent pair: champagne on the navy hero, deep brown on beige */
}

/* =================== SECTION BANDS: one cadence for the whole page =================== */
.section-light {
  background: var(--cream-landing);
  color: var(--ink);
  padding-block: var(--section-pad);
}

.section-dark {
  /* the AMBIENT JOURNEY shows through untinted (the lift spotlight glows behind
     the gold rings); the band paints NO ground of its own — the violet
     --bg-band-edge seam feathers were removed at the operator's direction,
     the journey's own black is the seam */
  color: var(--white);
  padding-block: var(--section-pad);
}

/* the #how section's mid-viewport morph (base.css theme-shift) paints no navy of its
   own: the cream sheet dissolves OPEN, revealing the depth scene of the ambient journey
   behind the one-click stage */
.section-light[data-theme-shift].theme-dark {
  background-color: transparent;
}

/* the "איך זה עובד?" title: BIGGER + scalable (clamp 36px → 60px, desktop AND mobile), and it turns
   from BLACK to the app's GOLD GRADIENT as the section darkens (was black→white): background-clip
   :text holds the gradient, and the color fades ink → transparent over --motion-morph to reveal it
   (the .text-grad technique, transitioned). User call. */
/* the story section opens TIGHTER under the hero (operator call): the hero already
   pays a full settle-band runway above this edge, so the shared section cadence landed on top
   of it as a second gap. Only the TOP is trimmed and only for this one section — every other
   band, including this section's own bottom, keeps the page cadence. */
#how {
  padding-block-start: clamp(80px, 9vw, 96px); /* air above the title (operator: more on phones) */
  overflow-x: clip; /* the stage rides the funnel rail past the 1080 column; the SECTION clips it */
}

#how .section-title {
  font-size: clamp(2.25rem, 4.5vw + 0.9rem, 3.75rem);
  text-wrap: balance;
  background: var(--grad-gold);
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--ink); /* opaque black at rest: covers the gradient behind the text */
  /* keep the reveal-engine entrance (opacity/transform, [data-reveal] in base.css) AND add the
     black→gradient color fade, listing all three so this rule doesn't clobber the entrance. */
  transition:
    opacity var(--motion-reveal) var(--ease-emphasized),
    transform var(--motion-reveal) var(--ease-emphasized),
    color var(--motion-morph) var(--ease-emphasized);
}
#how.theme-dark .section-title {
  color: transparent; /* reveal the gold gradient when the section hits the viewport centre */
}

/* the feature-section title ("כל הכלים לעסק מצליח, בקלות."), WHITE
   (operator call; was the gold gradient) + LARGER & scalable: clamps 36px (mobile) → 56px
   (desktop), a notch below the #how title (longer line). */
#features .section-title {
  color: var(--white);
  font-size: clamp(2.25rem, 4vw + 0.8rem, 3.5rem);
  line-height: var(--leading-tight);
}

/* MORE air under that title, scalable + matched across widths (user's call): clamps 80px (mobile) →
   104px (desktop), scoped to the homepage so the dashboards' shared grid keeps the standard space-6. */
#features .features-grid {
  margin-block-start: clamp(5rem, 8vw, var(--space-7));
}

/* match the gap BELOW the grid to the gap ABOVE it (the title→grid margin) so the buttons sit with equal
   air top↔bottom (user's call: the default section-pad read tighter than the title→grid gap on mobile).
   max() so the desktop's already-larger section-pad is never reduced. */
#features {
  padding-block-end: max(clamp(5rem, 8vw, var(--space-7)), var(--section-pad));
}

/* =================== THE ONE-CLICK STAGE (#how; DESIGN.md §7 "The one-click stage") ===================
   THE MACHINE BEHIND THE CURTAIN. The reading-START column = the editorial copy closing on ONE
   round physical gold key; the END column = the machine: a canvas-painted dotted dome (the
   V7 context-dome grammar, app.js oneClick paints it from the tokens: the lattice, the
   sphere's brighter edge, the light pool the hub stands in), the agent HUB at its centre,
   the agent's four beats as glass CARDS on the dome's rim, self-drawing WIRES with a comet
   (a soft tail behind a bright bead), and the SLOT under the hub (the ask that becomes the
   outcome, carrying the conversion spark). The stage and the roster rail ride ONE --space-6
   rhythm. Every hidden state is DOUBLE-GATED like the reveal engine (base.css): no-JS sees
   scene one settled in its approved shape, reduced motion sees the beats land instantly.
   EVERY light in the machine rides opacity/transform on its own layer (compositor-only, §8):
   a box-shadow transition repaints the blur each frame and cost 100ms+ frames at 1440 when
   measured headed.
   THE POLAR VOCABULARY: every anchored piece (hub · cards · slot) sits at the machine's
   centre line and translates by (--ax, --ay) × --R; --dir = 1 in RTL, -1 in LTR, so the arc
   reads start→end in either direction with the same numbers. */
.oc {
  --dir: 1;
  /* a flex column: a rail-wide stage centres over BOTH edges (a grid's auto track sized to
     it and overflowed one side; the fixed-track fix was a private grid recipe) */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}
html[dir="ltr"] .oc { --dir: -1; }

.oc-stage {
  position: relative;
  inline-size: 100%;
  display: grid;
  justify-items: center;
  gap: var(--space-6);
  align-items: center;
}

/* the painted dome + the wires span the WHOLE stage (the cable runs from the key in the
   copy column to the hub in the machine); both are decoration, both read the live layout */
.oc-dome,
.oc-wires {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  pointer-events: none;
  z-index: 0;
}
/* the field bleeds one --space-8 past the stage's top and bottom (the sphere's lower half was
   cut at the stage edge, measured); the island offsets its coordinates by the bleed */
.oc-dome {
  inset-block: calc(-1 * var(--space-8));
  block-size: calc(100% + 2 * var(--space-8));
  color: var(--gold-bright); /* the ONE ink the island reads back */
}

.oc-wire {
  fill: none;
  stroke: var(--gold-bright);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.34;
  /* the self-draw: --len is measured by the island; unset = a solid line (no-JS floor) */
  stroke-dasharray: var(--len, 0);
  stroke-dashoffset: var(--len, 0);
  transition:
    stroke-dashoffset var(--motion-reveal) var(--ease-emphasized),
    opacity var(--motion-state) var(--ease-standard);
}
.oc-wire.is-live { stroke-dashoffset: 0; opacity: 0.72; }
/* THE COMET: a 28px --sheen bead riding a 90px --gold-bright tail; both are one dash on a gap
   the length of the path, their fronts aligned by the tail's shorter travel (its end offset
   is 34, the bead's -28: same distance, same clock) */
.oc-spark,
.oc-tail {
  fill: none;
  stroke-linecap: round;
  opacity: 0;
}
.oc-spark {
  stroke: var(--sheen);
  stroke-width: 3;
  stroke-dasharray: 28 var(--len, 0);
  stroke-dashoffset: calc(var(--len, 0) + 28);
}
.oc-tail {
  stroke: var(--gold-bright);
  stroke-width: 4;
  stroke-dasharray: 90 var(--len, 0);
  stroke-dashoffset: calc(var(--len, 0) + 90);
}
.oc-spark.is-live,
.oc-tail.is-live {
  transition:
    stroke-dashoffset var(--motion-celebrate) var(--ease-linear),
    opacity var(--motion-micro) var(--ease-standard) var(--motion-celebrate);
  opacity: 0;
}
.oc-spark.is-live { stroke-dashoffset: -28px; }
.oc-tail.is-live { stroke-dashoffset: 34px; }
/* the comet is VISIBLE while it travels: the delayed opacity leg above only fades it out at
   the end; the start rides these two, which the .is-live transition lists override for
   the fade-out leg */
.oc-spark.is-live { animation: oc-comet-bead var(--motion-celebrate) var(--ease-linear) 1; }
.oc-tail.is-live { animation: oc-comet-tail var(--motion-celebrate) var(--ease-linear) 1; }
@keyframes oc-comet-bead { 0% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; } }
@keyframes oc-comet-tail { 0% { opacity: 0.62; } 85% { opacity: 0.62; } 100% { opacity: 0; } }

/* =================== THE COPY COLUMN =================== */
.oc-copy {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  text-align: center;
  container-type: inline-size; /* the title ramps against ITS column (below) */
  inline-size: min(100%, 34rem); /* containment zeroes the intrinsic width: size it */
}
.oc-title {
  margin: 0;
  display: grid;
  /* the vw ramp, capped by the column: the longest span ("בלחיצה אחת." = 5.67em) must
     hold ONE line, so 17cqi keeps it under the copy's width at every share ("תדמיינו עסק," = 5.54em) */
  font-size: min(clamp(3rem, 4.4vw + 0.8rem, 6.75rem), 17cqi);
  font-weight: var(--w-display);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
/* the Latin projection runs ~20% wider than the Hebrew, so the en arm steps the ramp down
   one notch and keeps the two-line fold (measured: "Run a business." folded to three) */
html[lang="en"] .oc-title { font-size: min(clamp(2.5rem, 3.2vw + 0.6rem, 4.25rem), 10cqi); } /* "Imagine a business," = 9.63em */
.oc-t1 {
  color: var(--ink);
  transition: color var(--motion-morph) var(--ease-emphasized);
}
#how.theme-dark .oc-t1 { color: var(--white); }
.oc-sub {
  margin: 0;
  margin-block-start: var(--space-2);
  max-inline-size: 30rem;
  font-size: clamp(1.0625rem, 0.6vw + 0.85rem, 1.5rem);
  font-weight: var(--w-body);
  line-height: var(--leading);
  color: var(--white); /* the primary-text role: white on dark (operator), the ink on beige */
  text-wrap: balance;
}
.oc-nudge { display: block; } /* the nudge at the key sits on its own line (operator) */

/* THE KEY: the dashboard agent CTA's material at key scale (operator: the rainbow like the
   /dashboard buttons and their gradient hover glow): the iridescent --grad-agent-wash face
   inside the full-strength hue-sweep rim on the §6 squircle, wearing the §4 .hover-bloom whose
   halo burns the BRAND ramp (--bloom-fill: --wezy-gradient, boosted, scaled 100% 200% so its
   colourful arc fills the halo); hover lifts 2px + ring-shine, press = scale(0.96) (the
   cockpit's own beat); the auto-run's self-press (.is-pressed) fires the same halo flash. */
.oc-key {
  --oc-keysize: clamp(128px, 9vw + 44px, 224px);
  --bloom-fill: var(--wezy-gradient);
  margin-block-start: var(--space-4);
  --bloom-boost: saturate(1.8) brightness(1.25);
  inline-size: var(--oc-keysize);
  block-size: var(--oc-keysize);
  display: grid;
  place-items: center;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--r-squircle);
  corner-shape: squircle;
  background:
    var(--grad-agent-wash) padding-box,
    linear-gradient(115deg, var(--hue-1), var(--hue-3), var(--hue-5), var(--hue-7)) border-box;
  box-shadow: var(--glass-edge), var(--glass-shadow-sm);
  color: var(--ink);
  font: inherit;
  font-size: clamp(1.125rem, 0.7vw + 0.85rem, 1.75rem);
  font-weight: var(--w-heading);
  cursor: pointer;
  transition:
    transform var(--motion-press) var(--ease-standard),
    box-shadow var(--motion-bloom) var(--ease-bloom);
}
.oc-key::before,
.oc-approve::before { background-size: 100% 200%; } /* the cockpit's ramp scaling */
.oc-key:hover { box-shadow: var(--glass-edge), var(--glass-shadow-sm), var(--ring-shine); transform: translateY(-2px); }
.oc-key:focus-visible { box-shadow: var(--glass-edge), var(--focus-ring-lit); }
.oc-key:active,
.oc-key.is-pressed { transform: scale(0.96); }
.oc-key.is-pressed::before { opacity: 1; filter: blur(8px) var(--bloom-boost); transition-delay: 0s; }
.oc-key-face {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
}
.oc-key svg {
  display: block;
  inline-size: calc(var(--oc-keysize) * 0.5);
  block-size: calc(var(--oc-keysize) * 0.5);
  color: var(--white); /* the tap hand is WHITE on the dark face (operator); the ink on beige */
  filter: drop-shadow(0 2px 6px color-mix(in srgb, var(--navy-deep) 45%, transparent));
}
/* the member's press KICKS the key (a dip and a bounce back; the :active dip alone read as a
   still): the class restarts per press from the island, reduced motion drops it */
.oc-key.is-kick { animation: oc-key-kick var(--motion-state) var(--ease-emphasized); }
@keyframes oc-key-kick {
  0% { transform: scale(1); }
  35% { transform: scale(0.9); }
  100% { transform: scale(1); }
}
/* THE PRESS COUNTER (operator: fun, big, white): +N bursts off the key's top-end corner on every
   MEMBER press, overshoots with a small twist, throws a gold ring, then drifts up and fades; the
   count lives in the island until a full reload (no storage), and the auto-run's self-press never
   counts. `direction: ltr` keeps "+3" reading as typed inside the RTL page; reduced motion (the MQ
   + the a11y engine's class) pins the badge steady instead (the tokens collapse to 1ms there: a
   pop would never be seen). */
.oc-key-count {
  --oc-ring: color-mix(in srgb, var(--gold-bright) 70%, transparent);
  position: absolute;
  inset-block-start: -0.6em;
  inset-inline-end: -0.6em;
  z-index: 2;
  min-inline-size: 2.6em;
  padding: 0.18em 0.6em;
  border-radius: var(--r-full);
  background: var(--wezy-gradient);
  color: var(--paper); /* the ramp never flips with the theme, so its digits stay the constant white */
  font-size: 1.15em;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  direction: ltr;
  unicode-bidi: isolate;
  text-align: center;
  text-shadow: 0 1px 2px color-mix(in srgb, var(--navy-deep) 40%, transparent);
  box-shadow: var(--glass-shadow-sm), 0 0 0 0 var(--oc-ring);
  transform-origin: 50% 100%;
  opacity: 0;
  pointer-events: none;
}
.oc-key-count.is-pop { animation: oc-count-pop var(--motion-celebrate) var(--ease-emphasized) both; }
@keyframes oc-count-pop {
  0% { opacity: 0; transform: translateY(8px) scale(0.3) rotate(-16deg); box-shadow: var(--glass-shadow-sm), 0 0 0 0 var(--oc-ring); }
  16% { opacity: 1; transform: translateY(-10px) scale(1.55) rotate(7deg); }
  34% { transform: translateY(-14px) scale(1) rotate(-3deg); box-shadow: var(--glass-shadow-sm), 0 0 0 16px transparent; }
  48% { transform: translateY(-15px) scale(1.18) rotate(0deg); }
  72% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-48px) scale(0.85) rotate(0deg); box-shadow: var(--glass-shadow-sm), 0 0 0 16px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .oc-key.is-kick { animation: none; }
  .oc-key-count.is-pop { animation: none; opacity: 1; }
}
:root.a11y-motion .oc-key.is-kick { animation: none; }
:root.a11y-motion .oc-key-count.is-pop { animation: none; opacity: 1; }
/* =================== THE MACHINE =================== */
.oc-machine {
  --R: 42cqi;                 /* the dome's rim radius, a share of the machine's width */
  --hub-y: 50%;               /* the hub centre line */
  --hub: clamp(176px, 24cqi, 320px);
  position: relative;
  z-index: 1;
  container-type: inline-size;
  inline-size: 100%;
  aspect-ratio: 1000 / 900;
}
/* THE POLAR ANCHOR: centred on the machine's axis, offset by the beat's rim vector; the
   translate's 50% half-width leg centres the box in either direction through --dir */
.oc-anchor {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-start: calc(var(--hub-y) - var(--ay, 0) * var(--R));
  translate: calc(var(--dir) * (var(--ax, 0) * var(--R) + 50%)) -50%;
}

.oc-hub {
  --ax: 0; --ay: 0;
  inline-size: var(--hub);
  block-size: var(--hub);
  display: grid;
  place-items: center;
  border-radius: var(--r-squircle);
  corner-shape: squircle;
  /* the film over the CARD tone (opaque, so the field never bleeds through) and the
     pool the agent stands in, painted INSIDE the plate */
  background:
    radial-gradient(60% 50% at 50% 62%, color-mix(in srgb, var(--gold-bright) 16%, transparent), transparent 100%),
    var(--glass-post), var(--navy-2);
  border: 1px solid var(--glass-post-border);
  transform-style: preserve-3d; /* the glow layer sits BEHIND the face on depth (the §4 idiom) */
  /* the HOUSE: an inner bezel band (one tone up, translucent) inside the lit top edge */
  box-shadow:
    var(--glass-post-shadow),
    inset 0 1px 0 var(--mix-white-12),
    inset 0 0 0 8px color-mix(in srgb, var(--navy-3) 55%, transparent),
    inset 0 0 0 9px var(--mix-white-06);
}
.oc-hub::before { /* the RIM: the dashboard agent CTA's hue sweep (the house = the switcher's twin) */
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  corner-shape: inherit;
  padding: 2px;
  background: linear-gradient(115deg, var(--hue-1), var(--hue-3), var(--hue-5), var(--hue-7));
  -webkit-mask:
    linear-gradient(var(--white) 0 0) content-box,
    linear-gradient(var(--white) 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(var(--white) 0 0) content-box,
    linear-gradient(var(--white) 0 0);
  mask-composite: exclude;
  opacity: 0.8;
  transition: opacity var(--motion-state) var(--ease-standard);
  pointer-events: none;
}
/* THE HALO: two concentric rings outside the plate (the Framer emblem grammar), quiet until
   the agent lights */
.oc-hub-halo,
.oc-hub-halo::before {
  position: absolute;
  border-radius: inherit;
  corner-shape: inherit;
  border: 1px solid var(--mix-goldbright-40);
  opacity: 0.35;
  transition: opacity var(--motion-bloom) var(--ease-bloom);
  pointer-events: none;
}
.oc-hub-halo { inset: -18px; border-radius: calc(var(--r-squircle) + 3%); }
.oc-hub-halo::before { content: ""; inset: -20px; border-radius: inherit; opacity: 0.6; }
.oc-hub.is-lit .oc-hub-halo { opacity: 1; }
.oc-hub::after { /* the light: the BRAND RAMP blurred behind the house (the key's own §4
                    bloom recipe: --wezy-gradient scaled 100% 200%, boosted), faded in on
                    its own layer, never a shadow transition (operator: the house glows in
                    the same colour as the button) */
  content: "";
  position: absolute;
  inset: -2px;
  /* translateZ(-1px) under preserve-3d, never z-index: a negative z pseudo paints ABOVE
     its own parent's background inside the parent's stacking context (measured: the ramp
     filled the house's face) */
  transform: translateZ(-1px);
  border-radius: inherit;
  corner-shape: inherit;
  background: var(--wezy-gradient);
  background-size: 100% 200%;
  filter: blur(18px) saturate(1.8) brightness(1.25);
  opacity: 0;
  transition: opacity var(--motion-bloom) var(--ease-bloom);
  pointer-events: none;
}
.oc-hub.is-lit::after { opacity: 1; } /* the brand ramp keeps its full colour on both arms */
.oc-hub.is-lit::before { opacity: 1; }
.oc-hub.is-done::after { animation: oc-hubglow var(--motion-celebrate) var(--ease-standard) 1; }
@keyframes oc-hubglow {
  0% { scale: 1; }
  40% { scale: 1.16; }
  100% { scale: 1; }
}
.oc-poster {
  display: block;
  grid-area: 1 / 1;
  transition: opacity var(--motion-state) var(--ease-standard);
}
.oc-poster img {
  display: block;
  inline-size: calc(var(--hub) * 0.92);
  block-size: auto;
}
/* the agent REACTS when the click reaches it: one hop (transform only) */
.oc-hub.is-lit .oc-poster img { animation: oc-hop var(--motion-reveal) var(--ease-spring) 1; }
@keyframes oc-hop {
  0% { transform: translateY(0); }
  40% { transform: translateY(-9px); }
  100% { transform: translateY(0); }
}
.oc-hub.is-swapping .oc-poster { opacity: 0; }
.oc-scene { display: contents; }
.oc-scene[hidden] { display: none; }
/* each agent's identity HUE (the §2 category wheel as a GROUND, never an accent): the tool
   tag on every card wears it */
.oc-scene[data-oc-scene="general"] { --lens-hue: var(--hue-3); }
.oc-scene[data-oc-scene="finance"] { --lens-hue: var(--hue-0); }
.oc-scene[data-oc-scene="marketing"] { --lens-hue: var(--hue-5); }
.oc-scene[data-oc-scene="bureaucracy"] { --lens-hue: var(--hue-2); }
.oc-scene[data-oc-scene="designer"] { --lens-hue: var(--hue-4); }
.oc-nodes { list-style: none; margin: 0; padding: 0; display: contents; }
/* THE RIM ANGLES, keyed by beat index (reading-cos · sin): start side → the apex → the end
   side, the approval last; a style attribute cannot carry them under the nonce CSP */
.oc-node[data-oc-node="ask"] { --ax: 0.82; --ay: 0; }
.oc-node[data-oc-node="0"] { --ax: 0.31; --ay: 0.94; }
.oc-node[data-oc-node="1"] { --ax: -0.81; --ay: 0.59; }
.oc-node[data-oc-node="2"] { --ax: -0.81; --ay: -0.59; }
/* THE ORBIT: the five satellites sit on the sphere's rim at ONE radius around the house,
   72° apart in reading order — the ask level on the near side, the three steps over the
   top to the far side, the approval on the lower near side (a near-side column read
   awkward on wide screens, operator-caught) */

/* THE NODE: a glass CARD on the rim in the Tines node grammar (Mobbin): a coloured TOOL TAG
   (the beat's pictogram on the agent's hue), an eyebrow naming the platform door the beat
   works in, the title, and the gold double check. Dim until the wire reaches it; lit = the
   §4 gradient ring + the glow layer. */
.oc-node {
  --disc: clamp(38px, 4.4cqi, 54px);
  inline-size: clamp(11.5rem, 28cqi, 20rem);
  color: var(--ink);
  transition:
    opacity var(--motion-reveal) var(--ease-emphasized),
    color var(--motion-morph) var(--ease-emphasized);
}
#how.theme-dark .oc-node { color: var(--white); }
.oc-node-card {
  --card-ring: var(--glass-post-border);
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 12px;
  border-radius: 14px;
  corner-shape: squircle;
  background:
    var(--glass-post) padding-box,
    linear-gradient(var(--navy-2), var(--navy-2)) padding-box,
    linear-gradient(var(--card-ring), var(--card-ring)) border-box;
  border: 1px solid transparent;
  box-shadow: var(--glass-post-shadow), inset 0 1px 0 var(--mix-white-06);
}
.oc-node.is-on .oc-node-card {
  background:
    var(--glass-post) padding-box,
    linear-gradient(var(--navy-2), var(--navy-2)) padding-box,
    var(--grad-gold) border-box;
}
.oc-node-card::after { /* the light layer */
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  corner-shape: inherit;
  box-shadow: var(--glow-gold-tight);
  opacity: 0;
  transition: opacity var(--motion-bloom) var(--ease-bloom);
  pointer-events: none;
}
.oc-node.is-on .oc-node-card::after { opacity: var(--machine-glow); }
/* the TOOL TAG: the pictogram on the agent's hue, a rounded square one step tighter than
   the card */
.oc-node-disc {
  display: grid;
  place-items: center;
  inline-size: var(--disc);
  block-size: var(--disc);
  border-radius: 10px;
  corner-shape: squircle;
  background: color-mix(in srgb, var(--lens-hue, var(--navy-3)) 78%, var(--navy-2));
  border: 1px solid var(--mix-white-12);
  box-shadow: var(--edge-light);
}
.oc-node-disc svg { inline-size: 66%; block-size: 66%; }
.oc-node-body { flex: 1 1 auto; display: grid; gap: 2px; min-inline-size: 0; }
.oc-node-kicker {
  font-size: clamp(0.75rem, 0.6cqi + 0.4rem, 0.95rem);
  font-weight: var(--w-medium);
  line-height: 1.2;
  color: var(--gold-bright);
  opacity: 0.85;
}
.oc-node-text {
  min-inline-size: 0;
  font-size: clamp(0.9375rem, 0.9cqi + 0.5rem, 1.3rem);
  font-weight: var(--w-medium);
  line-height: 1.3;
  text-wrap: pretty;
}
.oc-node-wait .oc-node-text { font-weight: var(--w-heading); }
/* THE ASK NODE: the member's own line on the input-well tone (the composer's voice), the
   wand on a gold tag; never dim (the member typed it) */
.oc-node-ask { inline-size: clamp(12rem, 30cqi, 20rem); }
.oc-node-ask .oc-node-card {
  background:
    linear-gradient(var(--navy-3), var(--navy-3)) padding-box,
    linear-gradient(var(--mix-goldbright-40), var(--mix-goldbright-40)) border-box;
}
.oc-node-disc-ask {
  background: var(--grad-feature-disc);
  border-color: var(--mix-goldbright-40);
}
/* THE MARK: the gold double check is the whole "done" (the hero trust-chip glyph), popping
   in on the spring; the approval card shows it only once approved */
.oc-node-mark {
  flex: 0 0 auto;
  display: grid;
  inline-size: clamp(22px, 2.6cqi, 30px);
  block-size: clamp(22px, 2.6cqi, 30px);
  color: var(--gold-bright);
  transition:
    opacity var(--motion-micro) var(--ease-standard),
    transform var(--motion-state) var(--ease-spring);
}
.oc-node-mark svg { inline-size: 100%; block-size: 100%; }
/* THE APPROVE KEY: the same material at pill scale, the double check leading; the
   invitation glow rides its own layer below */
.oc-approve {
  --bloom-fill: var(--wezy-gradient);
  --bloom-boost: saturate(1.8) brightness(1.25);
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-block-size: 42px;
  padding-inline: var(--space-2) var(--space-3);
  border: 2px solid transparent;
  border-radius: var(--r-full);
  background:
    var(--grad-agent-wash) padding-box,
    linear-gradient(115deg, var(--hue-1), var(--hue-3), var(--hue-5), var(--hue-7)) border-box;
  box-shadow: var(--glass-edge), var(--glass-shadow-sm);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-body);
  font-weight: var(--w-heading);
  cursor: pointer;
  transition:
    opacity var(--motion-state) var(--ease-standard),
    transform var(--motion-state) var(--ease-spring),
    box-shadow var(--motion-bloom) var(--ease-bloom);
}
.oc-approve:hover { box-shadow: var(--glass-edge), var(--glass-shadow-sm), var(--ring-shine); transform: translateY(-2px); }
.oc-approve:focus-visible { box-shadow: var(--glass-edge), var(--focus-ring-lit); }
.oc-approve:active { transform: scale(0.96); }
.oc-approve-mark { display: grid; inline-size: 22px; block-size: 22px; color: var(--gold-bright); }
.oc-approve-mark svg { inline-size: 100%; block-size: 100%; }
/* the invitation: ONE celebrate-glow breath when the wire reaches the approval (a
   one-shot beat, never a loop: §10), a glow layer breathing on opacity */
.oc-approve::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  transform: translateZ(-2px);
  box-shadow: var(--glow-celebrate);
  opacity: 0;
  pointer-events: none;
}
.oc-scene.is-ready .oc-approve::after { animation: oc-invite var(--motion-celebrate) var(--ease-standard) 1; }
@keyframes oc-invite {
  0% { opacity: 0; }
  40% { opacity: var(--machine-glow); }
  100% { opacity: 0; }
}

/* THE SLOT: under the house; the APPROVAL card (the platform's own law made visible) and the
   OUTCOME share one box and crossfade on the member's tap; the outcome carries the ONE spark
   onward (the end beat lands on what was accomplished plus one next step, §9) */
.oc-slot {
  --ax: 0.31;
  --ay: -0.94;
  display: grid;
  inline-size: clamp(16rem, 38cqi, 26rem);
}
.oc-wait,
.oc-outcome {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-2) var(--space-4) var(--space-2) var(--space-2);
  padding-inline: var(--space-2) var(--space-4);
  border-radius: var(--r-lg);
  corner-shape: squircle;
  border: 1px solid var(--glass-post-border);
  background: var(--glass-post), var(--navy-2);
  box-shadow: var(--glass-post-shadow);
  color: var(--ink);
  font-size: clamp(1rem, 0.9cqi + 0.5rem, 1.35rem);
  font-weight: var(--w-medium);
  line-height: 1.4;
  transition:
    opacity var(--motion-reveal) var(--ease-emphasized),
    transform var(--motion-reveal) var(--ease-emphasized),
    color var(--motion-morph) var(--ease-emphasized),
    visibility 0s;
}
#how.theme-dark .oc-wait,
#how.theme-dark .oc-outcome { color: var(--white); }
/* the approval card keeps the node card's anatomy (tag · body · the key) */
.oc-wait {
  --disc: clamp(38px, 4.4cqi, 54px); /* the tag's size lives on .oc-node; the approval card sits outside it */
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 12px;
  border-radius: 14px;
  font-size: inherit;
  font-weight: var(--w-heading);
  transition:
    opacity var(--motion-reveal) var(--ease-emphasized),
    visibility 0s;
}
.oc-outcome {
  --side-stroke: var(--gold-bright);
  padding-block: var(--space-3);
  font-weight: var(--w-heading);
}
.oc-outcome-glyph {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  border-radius: var(--r-full);
}
.oc-outcome-glyph svg { inline-size: 100%; block-size: 100%; }
.oc-ask-text { min-inline-size: 0; }
/* the caret: alive only while the ask types (the island adds .is-typing for the run of
   words and removes it after), so the resting screen stays still (§10) */
.oc-caret {
  display: inline-block;
  inline-size: 2px;
  block-size: 1.1em;
  margin-inline-start: 3px;
  vertical-align: -0.2em;
  border-radius: 1px;
  background: var(--gold-bright);
  opacity: 0;
}
.oc-caret.is-typing { animation: oc-caret 0.9s steps(2, jump-none) infinite; }
@keyframes oc-caret { 0% { opacity: 1; } 100% { opacity: 0; } }
.oc-outcome-body { display: grid; gap: var(--space-1); min-inline-size: 0; }
/* the spark onward, inside the outcome: a text key, never a second big key (§9 one prompt).
   The id-scoped selector outranks landing.css's `.section-light a:not(.btn)` blue link rule
   (measured: the spark rendered blue in every arm) */
#how .oc-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-body);
  font-weight: var(--w-heading);
  color: var(--gold-bright);
  text-decoration-color: var(--mix-goldbright-55);
  text-underline-offset: 5px;
}
/* LTR twin: the trailing glyph is the FORWARD arrow of the reading direction, authored as
   the RTL "←"; under LTR forward is rightward, so the same glyph flips on its own axis. */
html[dir="ltr"] #how .oc-cta > span[aria-hidden] {
  display: inline-block;
  transform: scaleX(-1);
}

/* =================== THE LAB (the operator's pick; the losers leave) =================== */
/* B: pill rows + the round portal house */
#how.lab-b .oc-node-card { border-radius: var(--r-full); padding: 8px 14px 8px 8px; padding-inline: 8px 14px; }
#how.lab-b .oc-node-disc { border-radius: var(--r-full); }
#how.lab-b .oc-node-kicker { display: none; }
#how.lab-b .oc-hub,
#how.lab-b .oc-hub::before,
#how.lab-b .oc-hub::after,
#how.lab-b .oc-hub-halo,
#how.lab-b .oc-hub-halo::before { border-radius: var(--r-full); corner-shape: round; }
#how.lab-b .oc-hub::before { padding: 3px; }
/* C: the ticket (a hue rail at the start, a bare glyph) + the shadow-box house */
#how.lab-c .oc-node-card { border-radius: 12px; padding-inline-start: 18px; }
#how.lab-c .oc-node-card::before {
  content: "";
  position: absolute;
  inset-inline-start: 7px;
  inset-block: 12px;
  inline-size: 3px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--lens-hue, var(--gold)) 55%, var(--white));
}
#how.lab-c .oc-node-disc { inline-size: 30px; block-size: 30px; background: transparent; border: none; box-shadow: none; }
#how.lab-c .oc-node-kicker { color: color-mix(in srgb, var(--lens-hue, var(--gold)) 45%, var(--white)); opacity: 1; }
#how.lab-c .oc-hub {
  box-shadow:
    var(--glass-post-shadow),
    inset 0 0 0 10px color-mix(in srgb, var(--navy-3) 85%, transparent),
    inset 0 0 0 11px var(--mix-white-12),
    inset 0 12px 24px color-mix(in srgb, var(--navy-deep) 40%, transparent);
}
#how.lab-c .oc-hub-halo { display: none; }

/* =================== THE STATES (the island only says WHEN) =================== */
@media (scripting: enabled) {
  .oc-scene:not(.is-ready) .oc-approve { opacity: 0; transform: scale(0.9); visibility: hidden; }
  .oc-scene:not(.is-done) .oc-outcome { opacity: 0; visibility: hidden; }
  .oc-scene.is-done .oc-wait { opacity: 0; visibility: hidden; }
}
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .oc-node:not(.is-on):not(.oc-node-ask) { opacity: 0.5; }
  .oc-node:not(.is-on) .oc-node-mark { opacity: 0; transform: scale(0.5); }
  .oc-scene:not(.is-ready) .oc-wait { opacity: 0.5; }
  .oc-scene:not(.is-done) .oc-outcome { transform: translateY(var(--space-2)); }
}
@media (prefers-reduced-motion: reduce) {
  .oc-scene.is-ready .oc-approve::after,
  .oc-hub.is-done::after,
  .oc-hub.is-lit .oc-poster img,
  .oc-caret.is-typing { animation: none; }
}
:root.a11y-motion .oc-caret.is-typing { animation: none; }

/* =================== THE POSTURES =================== */
/* phones + tablets + the narrow desktop band (< 1280: a rim cannot seat four cards without
   collisions, measured at 1024 and 1100): copy above, the machine as a SPINE (hub → the cards
   in flow → the slot) */
@media (max-width: 1279px) {
  .oc-machine {
    aspect-ratio: auto;
    display: grid;
    justify-items: center;
    gap: var(--space-4);
    padding-block-start: var(--space-3);
  }
  .oc-anchor {
    position: static;
    translate: none;
  }
  /* the hub keeps a positioned box: its ring pseudo and its name hang off IT, never off
     the machine (measured: the ring framed the whole spine) */
  .oc-hub { position: relative; inset: auto; }
  .oc-nodes { display: contents; }
  .oc-node { inline-size: min(100%, 27rem); }
  .oc-node-ask { order: -1; margin-block-end: var(--space-5); } /* clear of the house's halo rings */
  .oc-hub { order: 0; }
  .oc-node:not(.oc-node-ask) { order: 1; }
  .oc-node-card { min-block-size: var(--tap-min); }
  .oc-slot { order: 2; inline-size: min(100%, 27rem); translate: none; inset: auto; }
  .oc-machine { gap: var(--space-2); }
  /* the field bleeds to the viewport's edges (the sphere ran past the stage's sides on a
     phone and cut, measured); the island offsets its x by the bleed */
  .oc-dome { inset-inline: calc(-1 * var(--container-pad)); inline-size: calc(100% + 2 * var(--container-pad)); }
  .oc-hub { margin-block: var(--space-4) var(--space-5); }
}
/* the edge device (≤400): the pip drops its word and keeps the mark (the §13 word-drop
   grammar) */
@media (max-width: 400px) {
  .oc-node { --disc: 40px; }
}
/* desktop: the copy column at the reading start, the machine at the end; the stage escapes
   the 1080 column onto the funnel rail (the hero-trust precedent) so the dome has room */
@media (min-width: 1280px) {
  .oc-stage {
    inline-size: var(--funnel-rail);
    max-inline-size: 1760px; /* the rail's own reach: a 2000px screen fills (operator) */
    display: flex;
    align-items: center;
    column-gap: clamp(var(--space-5), 4vw, var(--space-8));
    min-block-size: clamp(760px, 56vw, 1120px);
  }
  .oc-copy { flex: 8 1 0; min-inline-size: 0; }
  .oc-machine { flex: 16 1 0; min-inline-size: 0; }
  .oc-copy {
    justify-items: start;
    text-align: start;
    padding-inline-start: var(--space-3);
    max-inline-size: none;
  }
  .oc-key { margin-block-start: var(--space-5); }
}
/* the laptop band (1280-1439): the rim is narrow, so the cards take a wider share of it on
   one step smaller type and tighter padding (measured: a five-line card at 1280 otherwise) */
@media (min-width: 1280px) and (max-width: 1360px) {
  .oc-copy { flex: 9 1 0; }  /* the laptop band lends the title one more share */
  .oc-machine { flex: 15 1 0; }
  .oc-node { inline-size: clamp(11rem, 27cqi, 14rem); }
  .oc-node-text { font-size: 0.875rem; }
  .oc-node-card { padding: 8px 10px; gap: var(--space-2); }
}
@media (min-width: 1360px) {
  .oc-stage { column-gap: var(--space-6); }
}

/* =================== THE ROSTER RAIL =================== */
/* the five agents on ONE glass rail under the machine (the cockpit drawer's pods): the
   pressed pod ringed gold on the card tone, the rest quiet ink */
.oc-agents {
  position: relative;
  z-index: 1;
  margin-block-start: clamp(var(--space-4), 3vw, var(--space-6)); /* + the stage gap: one level, scaling */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-1);
  border-radius: var(--r-full);
  background: var(--glass-post);
  border: 1px solid var(--glass-post-border);
  box-shadow: var(--glass-post-shadow);
}
.oc-agent {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: clamp(var(--tap-min), 2.8vw, 60px);
  padding-inline: var(--space-2) var(--space-4);
  border-radius: var(--r-full);
  border: 1px solid transparent;
  background: transparent;
  font: inherit;
  font-size: clamp(1rem, 0.5vw + 0.8rem, 1.3rem);
  font-weight: var(--w-medium);
  color: var(--slate);
  cursor: pointer;
  transition:
    background var(--motion-micro) var(--ease-standard),
    border-color var(--motion-micro) var(--ease-standard),
    color var(--motion-morph) var(--ease-emphasized),
    box-shadow var(--motion-bloom) var(--ease-bloom),
    transform var(--motion-press) var(--ease-spring);
}
.oc-agent:hover { background: var(--state-hover); color: var(--ink); box-shadow: var(--glow-gold); }
.oc-agent:active { transform: scale(0.97); }
.oc-agent:focus-visible { box-shadow: var(--focus-ring-lit); }
.oc-agent[aria-pressed="true"] {
  background:
    linear-gradient(var(--navy-2), var(--navy-2)) padding-box,
    var(--grad-gold) border-box;
  border-color: transparent;
  color: var(--white);
}
.oc-agent[aria-pressed="true"]:where(:hover) { box-shadow: var(--glow-gold); }
#how.theme-dark .oc-agent { color: var(--slate-on-dark); }
#how.theme-dark .oc-agent:hover,
#how.theme-dark .oc-agent[aria-pressed="true"] { color: var(--white); }
.oc-agent-disc {
  flex: 0 0 auto;
  display: grid;
  inline-size: clamp(30px, 2vw, 40px);
  block-size: clamp(30px, 2vw, 40px);
}
.oc-agent-disc svg { inline-size: 100%; block-size: 100%; }
/* the rail wraps into rows on a phone: a panel corner, never a three-row pill blob (this
   override sits AFTER the rail's base rule: same specificity, the later wins) */
@media (max-width: 1279px) {
  .oc-agents { border-radius: var(--r-lg); inline-size: min(100%, 27rem); }
}

/* the 9-feature ring grid moved to components.css at Layer 8 (multi-page: the
   landing + the three dashboards; one source, never a copy) */

/* the discs are the dashboard's PHONE posture at every width (operator): the library app-icon
   disc (the lit --grad-feature-disc fill in the --grad-gold ring, the hover bloom behind it)
   with the ring one step down, exactly the ≤767 dashboard rule (dashboard.css). The glass-film
   disc + masked ring that lived here was retired for it. */
#features .feature-disc {
  border-width: 2px;
}

/* =================== CLOSER: the page's END beat (§10) =================== */
.closer-inner {
  display: grid;
  gap: var(--space-5);
  justify-items: center;
  text-align: center;
  max-inline-size: 640px; /* a touch wider so the bigger title/text breathe */
  margin-inline: auto;
}

.closer-inner picture {
  position: relative;
  z-index: 0; /* stacking context for the -1 halo */
}

.closer-inner picture::before {
  content: "";
  position: absolute;
  inset: -10%;
  z-index: -1;
  background: var(--halo-gold);
}

/* the launch drift: the rocket's own vector (exhaust trailing bottom-left,
   nose to the top-right), as the closer scrolls through the viewport, Rishi
   climbs from slightly below-left of rest to slightly above-right,
   scroll-LINKED 1:1 (the sticky-stack lane). The scrub director is
   armLaunchDrift in app.js; Firefox ESR ships NO CSS animation-timeline
   (verified live), so JS owns the progress and CSS owns the mapping: the
   director writes --launch-p 0→1 and this transform rides it along the
   diagonal, ±half a --reveal-travel-lg around rest per axis (token-derived;
   the §11 ≤32px ceiling per axis). The drift rides the img while the
   one-shot zoom reveal owns <picture>, so the two transforms compose, and
   the halo stays put: Rishi rises through its light pool. Compositor-only;
   no-JS and reduced motion (the director declines to arm) hold this rest
   pose. */
.closer-inner picture img {
  --launch-p: 0.5; /* rest: until/unless the director scrubs it */
  /* LARGER + scalable rocket Rishi (was ~285px from the 300px source; now a 600px source): clamps
     ~300px (mobile) → 500px (desktop), scaling up briskly through the mid widths. */
  inline-size: clamp(300px, 50vw, 500px);
  block-size: auto;
  max-inline-size: 100%; /* never overflow the narrow mobile column */
  /* ±half of --launch-travel around rest per axis: 2x the former excursion (it rode
     --reveal-travel-lg and read too subtle to notice — operator call), which
     lands the per-axis displacement exactly ON the §11 32px ceiling, not past it. */
  /* translate3d, not translate: a 2D transform driven by a custom property re-rasterizes
     this ~500px image on the MAIN THREAD every scroll frame (the operator-caught judder,
     louder once the travel doubled). The 3D form + will-change promote it to its own
     compositor layer, so each frame only re-composites an existing texture. Both are
     universally supported (translate3d predates every engine's current release; the
     -webkit- prefix is unnecessary since Safari 9), so this costs no compatibility. */
  will-change: transform;
  transform: translate3d(
    calc((var(--launch-p) - 0.5) * var(--launch-travel)),
    calc((0.5 - var(--launch-p)) * var(--launch-travel)),
    0
  );
}

/* the closer CTA, LARGER + scalable too (was the base 56px/18px .btn): taller, a bigger label,
   wider. On the §13 390→1440 schedule; upsized again with the rest of the page's
   keys (box 64→80 became 70→88 · label 20→24 became 23→30). */
.closer-inner .btn {
  min-block-size: clamp(70px, 63.31px + 1.714vw, 88px);
  padding-inline: clamp(var(--space-6), 8vw, var(--space-7));
  font-size: clamp(23px, 20.4px + 0.667vw, 30px);
}

/* the closer ("איתך בכל צעד") title, BIGGER + scalable + visually striking (was the base section-title):
   clamps 36px (mobile) → 60px (desktop), fluidly. */
#with-you .section-title {
  font-size: clamp(2.25rem, 4.5vw + 0.9rem, 3.75rem);
  line-height: var(--leading-tight);
}

.closer-inner p {
  color: var(--ink); /* the final argument reads in INK, not gray */
  /* bigger + scalable too (was the default body size): clamps 18px → 24px */
  font-size: clamp(var(--text-lead), 1.6vw + 0.55rem, var(--text-h2));
  font-weight: var(--w-medium);
  line-height: var(--leading-loose);
}

/* THE HERO GROUND FILLS THE DESKTOP SCREEN. Measured before the change: at 1920x1080 the hero
   painted 764px tall and stopped at y=844, leaving 236px of bare viewport beneath it: the
   wallpaper ran out before the screen did.

   A FLOOR, not a fixed height: min-block-size can only ever GROW the hero, so a short desktop
   viewport (1024x768, where the content-driven 764px already exceeds the available 688px)
   keeps exactly the height it has today. A fixed block-size would have SHRUNK those.

   The topbar is a sticky IN-FLOW component, so the hero box starts at --topbar-h and the
   remaining screen is 100svh minus that bar; subtracting it is what makes the ground end
   exactly at the viewport bottom instead of hanging one bar-height below it.
   svh, not vh: vh resolves to the LARGEST viewport, which would overshoot wherever browser
   chrome is dynamic. On desktop the two agree, so this costs nothing and stays correct if the
   floor is ever widened to smaller screens.

   Scoped to ≥1024 (desktop) deliberately: phones and tablets keep their current content-driven
   hero untouched. */
@media (min-width: 1200px) {
  .hero {
    /* the bleed above pulls the hero under the bar and regrows the band through a transparent
       border, so with border-box sizing the floor is now the WHOLE screen, not screen-minus-bar.
       + the settle band: the runway rides BELOW the first screen, and because the same band sits
       in padding-block-end, the centering content-box stays exactly one screen: the cluster
       centers where it always did (growing only the padding had shifted it up; user-caught). */
    min-block-size: calc(100svh + var(--hero-settle-band));
  }
}

/* =================== DESKTOP (≥1200px): the side-by-side stage ===================
   Moved 768 → 1024 → 1200 (two operator calls): at 768 the two-column flip
   starved the copy column (the title measured 25px against the stacked 57px one viewport
   narrower — the seam the poster formula closes), and at 1024 the pair still read cramped on
   mid-size screens, where the operator wants the PHONE composition: a big pose sitting under
   the CTA row. Tablets and small laptops therefore keep the stacked poster; the pair stage
   begins only where both columns have real room. */
@media (min-width: 1200px) {
  .hero-inner {
    /* the pair CLAIMS the rail (operator call: space-taking, not spacing): the
       copy track hugs its measure, the mascot track takes ALL the remainder and the img
       fills it — no center deadspace by construction. Track 1 is the copy: in RTL the
       first track is the physical RIGHT, and the copy precedes the mascot in DOM. */
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(var(--space-4), 3vw, 72px);
    text-align: start;
  }

  .hero {
    /* the stage measure: wide enough that the ONE-line title + the mascot CLAIM the rail
       together (operator call: real space-taking, no center deadspace) — at 1440
       the copy column runs ~763px and the mascot fills the remainder; 940 caps the pair at
       the 1720 rail's budget. Still svh-capped for short screens. */
    --copy-measure: min(46vw, 108svh, 940px);
    /* the stage re-derives the title as ONE nowrap line (the operator's call): the string
       measures 9.93x its size (re-measured); 10.5 keeps ~5% headroom inside the measure */
    --hero-title: calc(var(--copy-measure) / 10.5);
  }

  .hero-title {
    white-space: nowrap; /* the stage title is one line; balance is a stacked-arm behavior */
  }

  /* BESIDE the copy now, not above it: the pose CLAIMS its whole track (width-first, the
     space-taking call). The width lands on the ANCHOR (100% of the track is definite there;
     the shrink-wrapping picture chain otherwise breaks the % cycle) and flows down, so the
     anchor still hugs the img exactly and the key-hole slot fractions stay structural. The
     svh term in the WIDTH cap is the fold guard: the pose is intrinsically square, so
     width <= 62svh means height <= 62svh — no height cap that could letterbox the img
     inside its anchor and desync the slot. */
  .hero-key-anchor {
    inline-size: min(100%, 62svh, 760px);
  }

  .hero-key-anchor picture,
  .hero-rishi img {
    inline-size: 100%;
  }

  .hero-rishi img {
    max-block-size: none; /* the stacked arms' height caps are superseded by the width cap */
  }

  .hero-ctas {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    max-inline-size: none;
    inline-size: fit-content;   /* desktop: the pair is its natural width, not stretched */
    margin-inline: auto;        /* …and sits CENTERED in the copy column (operator call;
                                   flush-start left 114px of empty column beside it) */
  }
}

/* the stacked-poster TABLET band only (the ≥1024 stage owns its own 62svh cap, and this file
   orders that block first, so an unbounded 768 rule would win the cascade over it): the
   phone's 380px mascot cap reads small under the 92px tablet title */
/* MID-SIZE (768-1023, the stacked poster's upper half): the pose sits under the CTA row
   like the phone, but BIG — the phone's 380px cap left it small in a tablet frame
   (operator-caught). It keeps growing with the viewport up to 620px, still
   height-bounded so a short landscape tablet can never be pushed past the fold. */
@media (min-width: 768px) and (max-width: 1199px) {
  .hero-rishi img {
    max-block-size: min(58svh, 620px);
  }
}

/* =================== ≥768px: the journey panels widen =================== */
@media (min-width: 768px) {
  .stack-panel .step-num {
    inline-size: 92px;
    block-size: 92px;
    font-size: var(--text-display);
  }

  .stack-panel img {
    max-block-size: 420px; /* the big desktop Rishi (a 600px source) */
  }
}

/* ---- ≥900px: THE ZIGZAG JOURNEY, copy | lit node | art, alternating around the spine
   (supersedes the earlier single-column desktop call; the redesign IS the change). The disc
   column is the path's rail: the thread hangs from the disc, through the panel and across
   the gap, to the next panel's disc, so the whole story reads as ONE drawn route. ---- */
@media (min-width: 900px) {
  .stack {
    gap: var(--space-7);
  }

  .stack-panel {
    grid-template-areas: "copy num art";
    grid-template-columns: 1fr 120px 1fr;
    column-gap: var(--space-5);
    max-inline-size: none;
    min-block-size: 46vh;
    text-align: start;
  }

  /* the mirrored beat: every second step swaps sides around the rail */
  .stack-panel:nth-child(even) {
    grid-template-areas: "art num copy";
  }

  .stack-panel .step-num {
    place-self: center;
  }

  /* natural Hebrew start-alignment on BOTH sides: the right-side copy aligns to its outer
     edge, the left-side copy hugs the spine; both read right-to-left naturally */
  .stack-copy {
    justify-items: start;
    align-self: center;
  }

  .stack-art {
    justify-self: center;
  }

  /* the thread rides the NUM rail (the panel's exact center column), from below the disc
     across the row and the .stack gap to the next disc */
  .stack-seg {
    inset-block-start: calc(50% + 46px + var(--space-3)); /* below the centered 92px disc */
    inset-block-end: calc(-1 * var(--space-7) - 50% + 46px);
    block-size: auto;
  }
}

/* (The wide-desktop ≥1160 'display moment' h3 jump was REMOVED; the base clamp now scales the title
   smoothly + big at every width, and the panels stack full-width so the title always has the room.) */

/* =================== FAQ: the quiet ledger (roadmap.md "Cross-cut passes" SEO/AEO; the level-up) ===
   The Linear/Dovetail FAQ grammar in the brand voice: a sticky side HEADER (Rishi-chat as
   the calm host) beside ONE lit ledger of divided rows; the nine per-row card rings are
   gone (the de-cramping move). Native <details name> = the exclusive accordion; the open
   settle animates where interpolate-size/::details-content exist (progressive; elsewhere
   instant); content always in the served HTML. Both themes ride the role tokens. */
.faq-grid {
  max-inline-size: 1080px;
}

.faq-head {
  text-align: center;
  margin-block-end: var(--space-6);
}

.faq-head img {
  /* UPSIZED (operator call): Rishi hosts this section, so he reads at a real
     size instead of a thumbnail (was 96-132px) */
  max-block-size: clamp(150px, 20vw, 200px);
  inline-size: auto;
}

.faq .section-title {
  /* the #features gradient-title grammar, one system */
  background: var(--grad-gold);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* upsized with its pose (was 2-3rem): the host title now carries the section */
  font-size: clamp(2.5rem, 4vw + 1rem, 4rem);
  line-height: var(--leading-tight);
}

/* ONE ledger surface holding ALL the rows, as TRUE LIQUID GLASS (operator call:
   transparent, no colour tint, a border): the shared --glass-post family (tokens.css) — a
   translucent WHITE film over a saturating blur, a lit white rim, catchlight shadows — the
   same recipe the community feed's glass cards wear, so the platform has ONE glass, not a
   second dialect. It replaces the tinted --grad-lit-card fill + gold gradient ring, so the
   section's ground now reads THROUGH the ledger. Both theme arms and the a11y-contrast
   fallback (which collapses the family to a solid seat + hairline, no blur) come with the
   tokens. The hairline gold dividers between rows are untouched. */
.faq-list {
  background: var(--glass-post);
  border: 1px solid var(--glass-post-border);
  border-radius: var(--r);
  box-shadow: var(--glass-post-shadow);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  backdrop-filter: var(--glass-post-blur);
  color: var(--white);
}

.faq-item {
  contain: layout; /* the leaf-component reflow isolation (frontend.md) */
  interpolate-size: allow-keywords; /* lets block-size animate to auto where supported */
}

.faq-item + .faq-item {
  border-block-start: 1px solid color-mix(in srgb, var(--gold) 26%, transparent);
}

.faq-q {
  list-style: none; /* our caret, not the UA marker */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-block-size: var(--tap-min);
  padding: var(--space-4) var(--space-5);
  cursor: pointer;
  transition: background-color var(--motion-micro) var(--ease-standard);
}

.faq-q::-webkit-details-marker { display: none; }

/* the hand hovers a row: the state-layer wash (the M3 grammar), token-timed */
.faq-q:hover { background-color: var(--state-hover); }
.faq-q:active { background-color: var(--state-press); }
.faq-item:first-of-type .faq-q { border-start-start-radius: var(--r); border-start-end-radius: var(--r); }
.faq-item:last-of-type:not([open]) .faq-q { border-end-start-radius: var(--r); border-end-end-radius: var(--r); }

.faq-q h3 {
  margin: 0;
  font-size: var(--text-h3);
  font-weight: var(--w-heading);
  line-height: var(--leading-heading);
  color: var(--white);
  transition: color var(--motion-micro) var(--ease-standard);
}

/* the open row's question turns gradient-gold, the "this one is speaking" cue */
.faq-item[open] .faq-q h3 {
  background: var(--grad-gold);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* the down-caret (the .field-select border-caret grammar): flips UP on open */
.faq-caret {
  flex: 0 0 auto;
  inline-size: 12px;
  block-size: 12px;
  border-block-end: 3px solid var(--gold-bright);
  border-inline-start: 3px solid var(--gold-bright);
  border-radius: 2px;
  transform: rotate(45deg);
  transition: transform var(--motion-state) var(--ease-standard);
}

.faq-item[open] .faq-caret { transform: rotate(-135deg); }
/* LTR twin: `border-inline-start` FLIPS with the document direction while the rotation does
   not. RTL draws the corner bottom-RIGHT (+45deg = down, -135deg = up); LTR draws it
   bottom-LEFT, which needs the opposite rotations for the same two glyphs (the
   community.css .feed-field-wrap precedent; without it the caret reads as a sideways '‹'). */
html[dir="ltr"] .faq-caret { transform: rotate(-45deg); }
html[dir="ltr"] .faq-item[open] .faq-caret { transform: rotate(135deg); }

.faq-a {
  margin: 0;
  padding: 0 var(--space-5) var(--space-5);
  font-size: var(--text-body);
  line-height: var(--leading-loose);
  color: var(--white);
  max-inline-size: 68ch; /* the reading measure inside the ledger */
}

/* the smooth open: height-to-auto + fade where ::details-content/interpolate-size exist
   (Chromium today; elsewhere the row opens instantly; meaning never depends on the motion).
   Token-timed, so the reduced-motion kill switch collapses it. */
.faq-item::details-content {
  opacity: 0;
  block-size: 0;
  overflow: clip;
  transition: block-size var(--motion-state) var(--ease-standard),
              opacity var(--motion-state) var(--ease-standard),
              content-visibility var(--motion-state) allow-discrete;
}

.faq-item[open]::details-content {
  opacity: 1;
  block-size: auto;
}

.faq-cta {
  text-align: center;
  margin-block-start: var(--space-5);
}

/* the FAQ-end CTA rides the frontpage button scale too (the §13 390→1440 schedule:
   box 66→80 · label 21→26 · pad 40→64; upsized with the page's other keys),
   a step under the closer, which stays the dominant act.
   Full-width (user call): the key spans the SAME rail as the ledger card above it,
   so the pair reads as one column. */
.faq-cta .btn {
  inline-size: 100%;
  min-block-size: clamp(66px, 60.8px + 1.333vw, 80px);
  font-size: clamp(21px, 19.14px + 0.476vw, 26px);
  padding-inline: clamp(var(--space-5), 31.09px + 2.286vw, var(--space-6));
}

/* ≥900px: the Linear side-header split, the host column (sticky, start-aligned) beside the
   ledger; the RTL grid puts the header at the inline-start (physically right) naturally */
@media (min-width: 900px) {
  .faq-grid {
    display: grid;
    /* the host column HUGS its content (was 2fr): a fractional column is wider than the
       centred pose+title inside it, so the host's painted edge sat ~56px inside the page
       margin while the ledger filled its own column to the edge — the side spacing looked
       uneven even though both boxes measured 40/40 (operator-caught at ~1015px). Hugging
       makes the painted content the column, so both outer edges are the SAME margin at
       every width, and the leftover width goes to the ledger where it is useful. */
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(var(--space-5), 4vw, var(--space-7));
    align-items: start;
  }

  .faq-head {
    position: sticky;
    /* clears the STICKY anonymous topbar (--topbar-h = its pinned box) + breathing room:
       a bare --space-6 (64px) parked the head's first 16px UNDER the 80px glass bar */
    inset-block-start: calc(var(--topbar-h) + var(--space-3));
    /* the pose and the title are CENTRED AS ONE UNIT in the host column (operator call).
       Centring is what makes the pair robust: rishi-chat.png carries its own
       transparent margins (alpha-measured 2.50% start / 2.67% end), so any EDGE alignment
       depends on the asset and drifts the moment the art is re-exported, while a shared
       centre line stays true at every scale (those two margins differ by 0.17% of the
       canvas, which is sub-pixel here). */
    display: grid;
    justify-items: center;
    text-align: center;
    margin-block-end: 0;
  }

  .faq-head img { max-block-size: clamp(200px, 19vw, 300px); }
}

/* ============================================================================
   THE SAFARI BLUR MIRROR'S ARMS (frontend.md "A MIRRORED LITERAL CARRIES NO ARMS").
   WebKit resolves no custom property inside -webkit-backdrop-filter and has no unprefixed
   backdrop-filter, so the blur above ships as a hand-mirrored LITERAL. A literal carries no
   arms: every way tokens.css drops --glass-post-blur to none must be restated HERE as a
   selector, or the degrade works on Blink and Gecko and silently fails on Safari.
   The @supports fallback needs no mirror (a failed feature query takes the whole declaration,
   and it is false on WebKit anyway); the reduced-transparency MEDIA arm and the three ROOT-CLASS
   arms do. Only the BLUR is dropped: the same arms already flip --glass-post itself to the
   opaque ladder, which reaches every engine through the token.
   THE GROUND CLASS ALONE, never the theme it is paired with (the two-theme law bans a theme
   class in a consumer sheet); over-covering the mismatched pairing only ever DROPS a blur.
   ========================================================================= */
@media (prefers-reduced-transparency: reduce) {
  .faq-list {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
:root:is(.a11y-contrast, .cg-minimal-light, .cg-minimal-dark) .faq-list {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
