/* ═══════════════════════════════════════════════════════════════════════════
   SOLIS — site.css
   Plain CSS, no build step. Order is load-bearing, keep it:
     1 tokens · 2 base · 3 typography · 4 frame · 5 components
     6 sections · 7 motion · 8 reduced motion
   Design rules: sharp frame, liquid light. Logical properties only.
   Docs: docs/DESIGN_SYSTEM.md · docs/MOTION.md
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ 1. TOKENS ════════════════════════════════════════════════════════════ */

:root {
  /* ─ color: light canvas ─ */
  --backdrop: #C9D3D3;        /* outside the frame */
  --paper: #ECF1F1;           /* frame / canvas (brand paper) */
  --tile: #F7FAFA;            /* raised flat cells */
  --tile-hover: #FFFFFF;
  --ink: #0D1516;             /* brand ink */
  --ink-2: #1B2627;
  /* Never remapped. Surfaces flip --ink, so anything that must stay literally
     dark (or literally paper) reaches for these instead. */
  --ink-base: #0D1516;
  --paper-base: #ECF1F1;
  /* The strong, high-contrast fill for the current surface, and its text.
     On paper that is dark ink; on a dark panel it inverts to paper. */
  --fill-strong: var(--ink-base);
  --on-fill-strong: var(--paper-base);
  --ink-muted: #5E6B6C;       /* 4.85:1 on paper */
  --ink-faint: rgba(13, 21, 22, .38);
  --line: rgba(13, 21, 22, .10);
  --line-strong: rgba(13, 21, 22, .18);

  /* ─ color: brand accents ─ */
  --accent: #59A7AC;          /* fills, dots, borders — NOT body text on paper (2.44:1) */
  --accent-brand: #61BBC1;    /* exact color of the logo files */
  --accent-soft: #85C8CD;     /* on dark surfaces */
  --accent-ink: #2A6A6E;      /* teal TEXT on light (5.44:1) */
  --signal: #E65656;          /* rare: window dot, errors. Decorative only on light (3.16:1) */
  --signal-ink: #C73E3E;      /* error text on light */

  /* ─ color: dark surfaces (stage, panels) ─ */
  --panel-deep: #0B1314;
  --panel-mid: #123034;
  --panel-glow: #1F5A5E;
  --on-panel: #ECF1F1;
  --on-panel-muted: rgba(236, 241, 241, .62);
  --line-on-dark: rgba(236, 241, 241, .10);

  /* ─ type ─ */
  /* The -fb families below are metric-matched, so the swap from fallback to
     webfont changes no box and CLS stays at 0 even when the font arrives
     late on a slow connection. */
  --font-ar: "IBM Plex Sans Arabic", "Plex Arabic fb", system-ui, sans-serif;
  --font-en: "Inter Tight", "Inter Tight fb", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;
  --fs-hud: 9.5px;
  --fs-label: 11px;
  --fs-mono-xs: 12px;
  --fs-small: 14px;
  --fs-body: clamp(15px, 1.15vw, 17px);
  --fs-lead: clamp(16px, 1.4vw, 19px);
  --fs-h3: 20px;
  --fs-h2: clamp(28px, 3.6vw, 52px);
  --fs-h1: clamp(36px, 4.4vw, 68px);
  --fs-stat: clamp(36px, 5vw, 72px);
  --fs-quote: clamp(24px, 3.4vw, 46px);

  /* Latin tracking. Applied under :lang(en) and to mono only — never Arabic. */
  --track-h1: -.025em;
  --track-h2: -.018em;
  --track-mono: .14em;
  --track-eyebrow: .18em;

  /* ─ space (4px base) ─ */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px; --sp-5: 24px;
  --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px; --sp-10: 140px;
  --gutter: clamp(16px, 2.4vw, 32px);
  --section-y: clamp(64px, 9vw, 140px);
  --tile-gap: 3px;
  --frame-m: 0px;                       /* full bleed — no backdrop margin */
  --measure: 1440px;                    /* content max width inside the frame */

  /* ─ radius: sharp frame, liquid light ─ */
  --r-tile: 3px;
  --r-panel: 8px;
  --r-frame: 0px;
  --r-round: 999px;           /* ONLY for dots, the sun, liquid elements */

  /* ─ elevation / light ─ */
  --shadow-tile: 0 1px 0 rgba(13, 21, 22, .04);
  --shadow-lift: 0 12px 32px -12px rgba(13, 21, 22, .22);
  --glow-sun: 0 0 40px 10px rgba(223, 244, 245, .55), 0 0 120px 40px rgba(97, 187, 193, .35);

  /* ─ motion ─ */
  --dur-1: 120ms; --dur-2: 220ms; --dur-3: 420ms; --dur-4: 700ms; --dur-5: 1100ms;
  --ease-out: cubic-bezier(.16, 1, .3, 1);        /* expo out — default for reveals */
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --ease-fall: cubic-bezier(.55, 0, .9, .4);      /* gravity */
  --ease-land: cubic-bezier(.34, 1.56, .64, 1);   /* fallback; upgraded to linear() below */
  --ease-soft: cubic-bezier(.22, 1.2, .36, 1);    /* fallback */

  /* ─ z ─ */
  --z-stage: 1; --z-nav: 50; --z-cursor: 80; --z-intro: 90;
}

/* ── metric-matched fallbacks ─────────────────────────────────────────────
   Measured against the real webfonts: the advance width is matched with
   size-adjust and the line box with ascent/descent-override, so text occupies
   the same space before and after the webfont loads. This is what keeps CLS
   at 0 rather than merely small. */

@font-face {
  font-family: "Inter Tight fb";
  src: local("Segoe UI"), local("Helvetica Neue"), local("Arial");
  size-adjust: 97.29%;
  ascent-override: 99.7%;
  descent-override: 24.67%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Plex Arabic fb";
  src: local("Segoe UI"), local("Tahoma"), local("Arial");
  size-adjust: 93.76%;
  ascent-override: 116.26%;
  descent-override: 44.8%;
  line-gap-override: 0%;
}

@supports (animation-timing-function: linear(0, 1)) {
  :root {
    /* damped spring ζ≈.42 — weighted landing with one visible bounce */
    --ease-land: linear(0, .094, .318, .59, .846, 1.047, 1.174, 1.229, 1.226, 1.184, 1.123, 1.06, 1.007, .97, .95, .946, .952, .965, .98, .994, 1.004, 1.01, 1.013, 1.012, 1.01, 1.006, 1.003, 1, .998, .997, .997);
    /* soft spring ζ≈.62 — liquid, for brand elements */
    --ease-soft: linear(0, .101, .319, .561, .771, .926, 1.023, 1.071, 1.084, 1.075, 1.057, 1.037, 1.019, 1.006, .998, .994, .993, .994, .995, .997, .998, .999, 1);
  }
}

/* Registered properties so light can be animated as a single number. */
@property --sun    { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --grid-a { syntax: "<number>"; inherits: true; initial-value: .05; }
@property --mx     { syntax: "<number>"; inherits: true; initial-value: .5; }
@property --my     { syntax: "<number>"; inherits: true; initial-value: .5; }

/* Dark surfaces remap the semantic tokens, so one component works on both. */
.s-panel,
.s-stage {
  --ink: var(--on-panel);
  --ink-muted: var(--on-panel-muted);
  --line: var(--line-on-dark);
  --line-strong: rgba(236, 241, 241, .18);
  --accent-ink: var(--accent-soft);
  --tile: rgba(236, 241, 241, .04);
  --tile-hover: rgba(236, 241, 241, .08);
  --fill-strong: var(--paper-base);
  --on-fill-strong: var(--ink-base);
}


/* ═══ 2. BASE ══════════════════════════════════════════════════════════════ */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-en);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;           /* no horizontal scroll, without trapping position:sticky */
}

img,
svg { display: block; max-width: 100%; }

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--accent);
  color: var(--ink);
}

/* One focus ring for the whole site. Never removed, only re-offset. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-tile);
}

/* Anchored sections clear the compact bar when jumped to. */
[id] { scroll-margin-block-start: calc(var(--frame-m) + 72px); }

/* Screen-reader-only, still focusable. */
.s-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* ═══ 3. TYPOGRAPHY ════════════════════════════════════════════════════════ */

html[lang="ar"] body { font-family: var(--font-ar); }
html[lang="en"] body { font-family: var(--font-en); }

/* Arabic is non-negotiable: zero tracking everywhere, taller leading.
   Tracking tokens below are re-applied only under :lang(en) and to mono. */
html[lang="ar"] * { letter-spacing: 0; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 400;
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
  line-height: 1.25;          /* Arabic default */
}

h2 {
  font-size: var(--fs-h2);
  line-height: 1.22;
}

h3 {
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.4;
}

p { margin: 0; }

/* Latin gets the tight, tracked-in setting the reference asks for. */
html[lang="en"] h1 { line-height: .98; letter-spacing: var(--track-h1); }
html[lang="en"] h2 { line-height: 1.08; letter-spacing: var(--track-h2); }
html[lang="en"] body { line-height: 1.55; }
html[lang="ar"] body { line-height: 1.8; }

.s-lead {
  font-size: var(--fs-lead);
  color: var(--ink-muted);
  text-wrap: pretty;
}

html[lang="ar"] .s-lead { line-height: 1.8; }
html[lang="en"] .s-lead { line-height: 1.55; }

/* Mono is for data only: eyebrows, HUD, indices, the window title, the clock.
   It is always LTR — these strings are Latin or numeric in both languages. */
.s-mono {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-xs);
  font-weight: 400;
  letter-spacing: var(--track-mono);
  /* isolate is required: on an inline box, `direction` alone does nothing.
     Without it "+000 000 0000" reorders to "0000 000 000+" inside RTL text. */
  direction: ltr;
  unicode-bidi: isolate;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}

html[lang="ar"] .s-mono { letter-spacing: var(--track-mono); }

/* Numbers never reorder, in either language. */
.s-num {
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}


/* ═══ 4. FRAME ═════════════════════════════════════════════════════════════ */

/* The light card floating on the darker backdrop. The whole page lives inside
   it, so the card reads as one continuous sheet rather than stacked sections. */
.s-frame {
  position: relative;
  margin: var(--frame-m);
  min-height: calc(100svh - (var(--frame-m) * 2));
  background: var(--paper);
  border: 0;
  border-radius: var(--r-frame);
  isolation: isolate;
  overflow: clip;
}

/* Horizontal rhythm: everything inside the frame shares these gutters. */
.s-wrap {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.s-section {
  padding-block: var(--section-y);
}


/* ═══ 5. COMPONENTS ════════════════════════════════════════════════════════ */

/* ── 5.1 frame edges ──────────────────────────────────────────────────────
   The card keeps a real border for the no-JS and reduced-motion paths. During
   the intro that border goes transparent and these four hairlines draw in its
   place, from the top-start corner outward. Same pixels either way. */

.s-frame__edge {
  position: absolute;
  z-index: 3;
  background: var(--line-strong);
  opacity: 0;
  pointer-events: none;
}

.s-frame__edge--top,
.s-frame__edge--bottom { inset-inline: 0; block-size: 1px; transform-origin: left center; }
.s-frame__edge--start,
.s-frame__edge--end    { inset-block: 0; inline-size: 1px; transform-origin: center top; }

.s-frame__edge--top    { inset-block-start: 0; }
.s-frame__edge--bottom { inset-block-end: 0; }
.s-frame__edge--start  { inset-inline-start: 0; }
.s-frame__edge--end    { inset-inline-end: 0; }

[dir="rtl"] .s-frame__edge--top,
[dir="rtl"] .s-frame__edge--bottom { transform-origin: right center; }

.s-frame__edge { opacity: var(--intro); }


/* ── 5.2 arrow ────────────────────────────────────────────────────────────
   One glyph, mirrored by the document direction. Never a second SVG. */

.s-arrow {
  flex: none;
  inline-size: 16px;
  block-size: 16px;
}

[dir="rtl"] .s-arrow:not(.s-arrow--up) { scale: -1 1; }

.s-arrow--up { rotate: -90deg; }


/* ── 5.3 tile ─────────────────────────────────────────────────────────────
   Flat cell. Label at the start, arrow pushed to the far end, fill sweeping
   in from the inline-start on hover. */

.s-tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: 44px;
  padding-inline: 14px;
  background: var(--tile);
  border: 0;
  border-radius: var(--r-tile);
  color: var(--ink-muted);
  font-family: inherit;
  font-size: var(--fs-label);
  text-align: start;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur-2) var(--ease-out),
              background-color var(--dur-2) var(--ease-out);
}

html[lang="en"] .s-tile { letter-spacing: .04em; }

.s-tile__fill {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 380ms var(--ease-out);
}

[dir="rtl"] .s-tile__fill { transform-origin: right center; }

.s-tile__label { min-inline-size: 0; }
.s-tile__arrow { display: flex; margin-inline-start: auto; }

.s-tile--ink { background: var(--fill-strong); color: var(--on-fill-strong); }
.s-tile--ink .s-tile__fill { background: var(--accent); }

.s-tile--ghost { background: transparent; box-shadow: inset 0 0 0 1px var(--line); }

.s-tile.is-active { color: var(--ink); }
.s-panel .s-tile.is-active { color: var(--on-panel); }

@media (hover: hover) and (pointer: fine) {
  .s-tile:hover { color: var(--on-fill-strong); }
  .s-tile:hover .s-tile__fill { transform: scaleX(1); }
  .s-tile--ink:hover { color: var(--ink-base); }
}

.s-tile:active { scale: .98; }

.s-tile[aria-disabled="true"] { opacity: .5; pointer-events: none; }


/* ── 5.4 btn ──────────────────────────────────────────────────────────────
   Near-square action. The fill is its own layer so the intro can pour ink
   across it, and the label sits in a clip so it can roll up. */

.s-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  min-block-size: 52px;
  padding-inline: 20px;
  border: 0;
  border-radius: var(--r-tile);
  background: transparent;
  color: var(--on-fill-strong);
  font-family: inherit;
  font-size: var(--fs-small);
  font-weight: 500;
  text-align: start;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur-2) var(--ease-out);
}

.s-btn--wide { min-inline-size: 220px; }

.s-btn__fill {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--fill-strong);
  transform-origin: left center;
  transition: background-color var(--dur-2) var(--ease-out);
}

[dir="rtl"] .s-btn__fill { transform-origin: right center; }

.s-btn__label { display: block; overflow: hidden; }
.s-btn__text { display: block; }
.s-btn__arrow { display: flex; margin-inline-start: auto; }

.s-btn--accent { color: var(--ink-base); }
.s-btn--accent .s-btn__fill { background: var(--accent); }

.s-btn--line { color: var(--ink); }
.s-btn--line .s-btn__text { color: var(--ink); }
.s-btn--line .s-btn__fill { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); }

@media (hover: hover) and (pointer: fine) {
  .s-btn--ink:hover .s-btn__fill { background: color-mix(in oklab, var(--fill-strong) 88%, var(--accent)); }
  .s-btn--accent:hover .s-btn__fill { background: var(--accent-brand); }
  .s-btn--line:hover .s-btn__fill { background: var(--tile-hover); }
}

.s-btn:active { scale: .98; }

.s-btn:disabled { cursor: not-allowed; opacity: .6; }


/* ── 5.5 eyebrow + word split ─────────────────────────────────────────────── */

.s-eyebrow {
  margin-block-end: var(--sp-4);
  font-size: var(--fs-mono-xs);
  letter-spacing: var(--track-eyebrow);
  color: var(--accent-ink);
}

html[lang="ar"] .s-eyebrow { letter-spacing: var(--track-eyebrow); }

.s-words { display: block; }
.s-word { display: inline-block; }

/* The highlighted word. The sunlit sweep is added in the motion layer. */
.s-hl { color: var(--accent-ink); }
.s-panel .s-hl,
.s-stage .s-hl { color: var(--accent-soft); }


/* ── 5.6 section head ─────────────────────────────────────────────────────── */

.s-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-5);
  padding-block-end: var(--sp-5);
  border-block-end: 1px solid var(--line);
  margin-block-end: var(--sp-7);
}

.s-head__main { max-inline-size: 60ch; }
.s-head__title { max-inline-size: 18ch; }
.s-head__lead { margin-block-start: var(--sp-4); max-inline-size: 46ch; }
.s-head__aside { color: var(--ink-muted); }


/* ── 5.7 panel (dark surface) ─────────────────────────────────────────────── */

.s-panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--r-panel);
  background: radial-gradient(120% 90% at 50% 0%, var(--panel-mid) 0%, var(--panel-deep) 68%);
  color: var(--on-panel);
}

.s-panel__grid,
.s-stage__grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, #ECF1F1 1px, transparent 1px),
    linear-gradient(to bottom, #ECF1F1 1px, transparent 1px);
  background-size: 56px 56px;
  opacity: var(--grid-a);
  /* Masked by a radial fade centred on the light source, so the grid is
     something the light falls across rather than a lattice drawn on top.
     --impact-x/y are set by JS from the slab's landing corner; the fallbacks
     stay in the var() call so the stage's own values still inherit down. */
  mask-image: radial-gradient(78% 78% at var(--impact-x, 50%) var(--impact-y, 40%),
              #000 0%, rgba(0, 0, 0, .55) 42%, transparent 82%);
}

/* Film grain from gradients rather than an SVG noise image.
   A full-panel background IMAGE is a valid Largest Contentful Paint
   candidate, and this decorative texture was beating the headline to it —
   LCP was reporting the grain at 3.4s while the actual content painted at
   1.0s. Gradients are excluded from LCP by spec, and three coprime stipples
   at 7% overlay are visually indistinguishable from the turbulence. */
.s-panel__grain,
.s-stage__grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .07;
  mix-blend-mode: overlay;
  background-image:
    repeating-conic-gradient(from 13deg, #FFF 0% 25%, transparent 0% 50%),
    repeating-conic-gradient(from 67deg, #FFF 0% 25%, transparent 0% 50%),
    repeating-conic-gradient(from 41deg, #000 0% 25%, transparent 0% 50%);
  background-size: 3px 3px, 5px 5px, 7px 7px;
}

.s-panel__body {
  position: relative;
  z-index: 2;
  padding: clamp(28px, 4vw, 56px);
}


/* ── 5.8 window (contact chrome) ──────────────────────────────────────────── */

.s-window {
  overflow: hidden;
  background: var(--tile);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-panel);
}

.s-window__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border-block-end: 1px solid var(--line);
}

.s-window__dot {
  inline-size: 8px;
  block-size: 8px;
  border-radius: var(--r-round);
}

.s-window__dot--1 { background: var(--signal); }
.s-window__dot--2 { background: var(--accent); }
.s-window__dot--3 { background: var(--accent-soft); }

.s-window__title {
  margin-inline-start: var(--sp-2);
  min-block-size: 1.4em;
  font-size: var(--fs-label);
  color: var(--ink-muted);
}

.s-window__body { padding: clamp(24px, 4vw, 56px); }


/* ── 5.9 field ────────────────────────────────────────────────────────────
   Flat tile. The accent sweep runs from the inline-start on focus; the border
   colour changes with it so the state reads even without the sweep. */

.s-field {
  position: relative;
  display: block;
}

.s-field__control {
  inline-size: 100%;
  min-block-size: 52px;
  padding: 14px 16px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  color: var(--ink);
  font-size: 16px;            /* 16px or iOS zooms the page on focus */
  line-height: 1.5;
  transition: border-color var(--dur-2) var(--ease-out),
              background-color var(--dur-2) var(--ease-out);
}

.s-field--textarea .s-field__control { resize: vertical; min-block-size: 120px; }

.s-field--select .s-field__control {
  appearance: none;
  padding-inline-end: 44px;
  cursor: pointer;
}

.s-field__chevron {
  position: absolute;
  inset-inline-end: 14px;
  inset-block-start: 50%;
  translate: 0 -50%;
  display: flex;
  color: var(--ink-muted);
  pointer-events: none;
}

.s-field__control::placeholder { color: var(--ink-faint); }

.s-field__control:focus { outline: none; border-color: var(--accent); }
.s-field__control:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.s-field__sweep {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  block-size: 2px;
  background: var(--accent);
  border-radius: 0 0 var(--r-tile) var(--r-tile);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 380ms var(--ease-out);
  pointer-events: none;
}

[dir="rtl"] .s-field__sweep { transform-origin: right center; }

.s-field:focus-within .s-field__sweep { transform: scaleX(1); }

.s-field__control[aria-invalid="true"] { border-color: var(--signal-ink); }


/* ── 5.10 logo ────────────────────────────────────────────────────────────
   Brand files only. Sits in logical order so the mark leads in the reading
   direction, but the images themselves are NEVER mirrored. */

.s-logo {
  --mark-h: 48px;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
}

.s-logo__mark,
.s-logo__word { inline-size: auto; }

.s-logo__mark { block-size: var(--mark-h); }
.s-logo__word { block-size: calc(var(--mark-h) * .62); }

.s-logo--hero    { --mark-h: clamp(40px, 4.2vw, 64px); }
.s-logo--compact { --mark-h: 24px; gap: var(--sp-2); }

/* Footer lockup is the wordmark alone, at horizon scale. */
.s-logo--footer { display: block; inline-size: 100%; }
.s-logo--footer .s-logo__mark { display: none; }
.s-logo--footer .s-logo__word {
  inline-size: min(100%, 900px);
  block-size: auto;
  margin-inline: auto;
  opacity: .9;
}

/* Belt and braces: nothing may ever flip the brand. */
.s-logo img { scale: 1 1 !important; rotate: none !important; }


/* ═══ 6. SECTIONS ══════════════════════════════════════════════════════════ */

/* ── 6.1 shared section rhythm ────────────────────────────────────────────── */

.s-section--flush > .s-wrap { padding-inline: var(--gutter); }

.s-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--accent-ink);
  font-size: var(--fs-small);
}

.s-link::after {
  content: "";
  position: absolute;
  inset-block-end: -3px;
  inset-inline: 0;
  block-size: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out);
}

[dir="rtl"] .s-link::after { transform-origin: right center; }

@media (hover: hover) and (pointer: fine) {
  .s-link:hover::after { transform: scaleX(1); }
}

.s-dot {
  display: inline-block;
  flex: none;
  inline-size: 5px;
  block-size: 5px;
  margin-inline-end: var(--sp-2);
  border-radius: var(--r-round);
  background: var(--accent);
  vertical-align: middle;
}


/* ── 6.2 compact bar ──────────────────────────────────────────────────────
   One nav is live at a time. This one is inert until the hero scrolls away,
   so the keyboard and screen readers never meet two copies of the links. */

.s-compact {
  position: fixed;
  inset-block-start: 0;
  inset-inline: var(--frame-m);
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: var(--tile-gap);
  padding: var(--sp-2) var(--gutter);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(16px) saturate(1.2);
  border-block-end: 1px solid var(--line);
  transform: translateY(-101%);
  visibility: hidden;
}

.s-compact.is-on { transform: none; visibility: visible; }

.s-compact__logo { display: flex; margin-inline-end: var(--sp-4); }
.s-compact__nav { display: flex; gap: var(--tile-gap); margin-inline-start: auto; }
.s-compact__tile { min-block-size: 36px; }


/* ── 6.3 hero ─────────────────────────────────────────────────────────────
   Two columns, one viewport, one composition. The void is load-bearing: it is
   what makes the headline land where it does. */

.s-hero {
  display: grid;
  grid-template-columns: minmax(300px, .44fr) 1fr;
  min-block-size: calc(100svh - (var(--frame-m) * 2));
}

.s-hero__start {
  display: flex;
  flex-direction: column;
  padding: var(--gutter);
  border-inline-end: 1px solid var(--line);
  min-inline-size: 0;
}

.s-hero__logo { align-self: flex-start; }

/* Intentional emptiness. It eats the free space, which is what anchors the
   action row to the bottom of the column — and, being the only flexible
   thing in the column, it is also what yields first when there is not
   enough. The floor is deliberately low: the Arabic headline wraps to four
   lines at 1.25 leading and needs ~40px more than the English one, so a tall
   floor here pushed the Arabic hero past a single viewport. */
.s-hero__void { flex: 1; min-block-size: clamp(12px, 4vh, 120px); }

.s-hero__eyebrow { margin-block-end: clamp(16px, 2.4vh, 28px); }

.s-hero__title { max-inline-size: 12ch; }
html[lang="en"] .s-hero__title { max-inline-size: 11ch; }

.s-hero__lead { margin-block-start: 20px; max-inline-size: 36ch; }

.s-hero__act { margin-block-start: clamp(28px, 6vh, 72px); }

.s-hero__note {
  display: flex;
  align-items: center;
  margin-block-start: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

.s-hero__browse { margin-block-start: var(--sp-3); }

.s-hero__end {
  display: flex;
  flex-direction: column;
  gap: var(--tile-gap);
  padding: var(--gutter);
  min-inline-size: 0;
}

.s-nav { position: relative; display: flex; gap: var(--tile-gap); }
.s-nav__tile { flex: var(--grow, 1) 1 0; min-inline-size: 0; }
.s-nav__tile .s-tile__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.s-tile--lang {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  letter-spacing: .08em;
  direction: ltr;
}

/* Slides between tiles; JS sets its width and offset. */
.s-nav__ind {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  block-size: 2px;
  inline-size: 0;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
}

.s-menu__btn { display: none; }

.s-hero__stage { flex: 1; min-block-size: 520px; }


/* ── 6.4 stage (hero panel) ───────────────────────────────────────────────
   Layered back to front. --sun drives the base gradient, the grid mask and
   the bloom together, so one number moves all of the light at once. */

.s-stage {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--r-panel);
  background: var(--panel-deep);
  color: var(--on-panel);
  container-type: inline-size;
  /* The one point everything shares: the slab's contact corner, the
     shockwave origin, the grid-flash centre and the sun. JS recomputes it
     from the slab's real box; these are the pre-JS defaults. */
  --impact-x: 20%;
  --impact-y: 80%;
}

.s-stage__base {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: radial-gradient(95% 85% at var(--impact-x) var(--impact-y),
              var(--panel-glow) 0%, var(--panel-mid) 40%, var(--panel-deep) 76%);
  opacity: calc(.22 + var(--sun) * .78);
}

.s-stage__grid { z-index: 1; }
.s-stage__grain { z-index: 3; }

/* Ambient light lives inside the stage now — teal only, no red, slow. */
.s-stage__ambient {
  position: absolute;
  z-index: 2;
  border-radius: var(--r-round);
  filter: blur(60px);
  pointer-events: none;
}

.s-stage__ambient--a {
  inline-size: 52%;
  aspect-ratio: 1;
  inset-block-start: -12%;
  inset-inline-start: -8%;
  background: radial-gradient(circle, var(--accent) 0%, transparent 68%);
  opacity: calc(.30 * var(--sun));
}

.s-stage__ambient--b {
  inline-size: 44%;
  aspect-ratio: 1;
  inset-block-end: -14%;
  inset-inline-end: -10%;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 65%);
  opacity: calc(.22 * var(--sun));
}


/* ── 6.5 marquee ──────────────────────────────────────────────────────────── */

.s-marquee {
  display: flex;
  align-items: center;
  block-size: 48px;
  overflow: hidden;
  background: var(--paper);
  border-block: 1px solid var(--line);
}

.s-marquee__clip { inline-size: 100%; }
.s-marquee__track { display: flex; inline-size: max-content; }

.s-marquee__group {
  display: flex;
  align-items: center;
  gap: 44px;
  padding-inline-end: 44px;
}

.s-marquee__item {
  font-size: 12px;
  letter-spacing: .14em;
  color: var(--ink-muted);
  white-space: nowrap;
}

/* A liquid dot, not a diamond — the one round thing allowed in the frame. */
.s-marquee__dot {
  flex: none;
  inline-size: 8px;
  block-size: 8px;
  border-radius: var(--r-round);
  background: var(--accent);
}


/* ── 6.6 services + orbit ─────────────────────────────────────────────────── */

.s-services__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(40px, 6vw, 90px);
  align-items: center;
}

.s-services__lead { margin-block-start: 20px; max-inline-size: 42ch; }

.s-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-6) 0 0;
  padding: 0;
  list-style: none;
}

/* Square tiles, not pills. */
.s-tag {
  display: inline-block;
  padding: 7px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-tile);
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--accent-ink);
}

/* Stacked in one grid cell so nothing needs left/right centring. */
.s-orbit {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 100%;
  max-inline-size: 520px;
  margin-inline: auto;
  aspect-ratio: 1;
  /* Every child is sized against the INLINE axis. The centre mark is a tall
     544x971 PNG, and a percentage block-size here is indefinite — it would
     fall back to the image's intrinsic height, force the row open and beat
     aspect-ratio. cqi units break that cycle; min-block-size:0 stops the
     grid item's automatic minimum from doing the same thing. */
  container-type: inline-size;
  min-block-size: 0;
}

.s-orbit > * { grid-area: 1 / 1; }

.s-orbit__rings,
.s-orbit__beams { inline-size: 100cqi; block-size: 100cqi; }

.s-orbit__ring { fill: none; vector-effect: non-scaling-stroke; }
.s-orbit__ring--outer { stroke: var(--line-on-dark); stroke-width: 1; }
.s-orbit__ring--inner { stroke: rgba(89, 167, 172, .3); stroke-width: 1; stroke-dasharray: 2 3; }

.s-orbit__halo {
  inline-size: 46cqi;
  aspect-ratio: 1;
  border-radius: var(--r-round);
  background: radial-gradient(circle, rgba(97, 187, 193, .30) 0%, transparent 66%);
  filter: blur(18px);
  opacity: var(--sun);
  pointer-events: none;
}

.s-orbit__mark { block-size: 26cqi; inline-size: auto; }

.s-orbit__ring-wrap {
  position: relative;
  inline-size: 100cqi;
  block-size: 100cqi;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The geometry contract: a zero-size point carries the orbit position, and
   the counter-rotating span inside cancels the ring spin. Entrance motion
   only ever touches .s-orbit__cap. */
.s-orbit__point {
  position: absolute;
  inline-size: 0;
  block-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.s-orbit__counter { flex: 0 0 auto; display: block; }

.s-orbit__cap {
  display: block;
  padding: 8px 14px;
  background: var(--panel-deep);
  border: 1px solid var(--edge, var(--line-on-dark));
  border-radius: 4px;
  font-size: 13.5px;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--on-panel);
  transition: background-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out),
              opacity var(--dur-2) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .s-orbit__cap:hover { background: var(--accent); color: var(--ink-base); }
}


/* ── 6.7 work rail ────────────────────────────────────────────────────────── */

.s-section--rail {
  /* Keeps the first card flush with the section gutter at every width. */
  --rail-pad: max(var(--gutter), calc((100% - var(--measure)) / 2 + var(--gutter)));
}

.s-rail {
  display: flex;
  gap: clamp(12px, 1.6vw, 22px);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: x mandatory;
  padding-block: clamp(24px, 3vw, 44px);
  scrollbar-width: thin;
  scrollbar-color: rgba(13, 21, 22, .25) transparent;
}

.s-rail__pad { flex: 0 0 calc(var(--rail-pad) - clamp(12px, 1.6vw, 22px)); }

.s-rail::-webkit-scrollbar { block-size: 3px; }
.s-rail::-webkit-scrollbar-thumb { background: rgba(13, 21, 22, .25); }
.s-rail::-webkit-scrollbar-track { background: var(--line); }

.s-work { flex: 0 0 min(78vw, 420px); scroll-snap-align: center; }

.s-work__media {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  background: var(--tile);
}

.s-work__img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.s-work__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  font-size: 12px;
  background-image: repeating-linear-gradient(
    -45deg, var(--line) 0 1px, transparent 1px 11px);
}

.s-work__cap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-block-start: var(--tile-gap);
  padding: 12px 14px;
  background: var(--tile);
  border-radius: var(--r-tile);
}

.s-work__title { font-size: 15px; font-weight: 500; }
.s-work__meta { font-size: 11px; color: var(--accent-ink); }


/* ── 6.8 signal (stats) ───────────────────────────────────────────────────── */

.s-signal { position: relative; }

.s-signal__scan {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  z-index: 4;
  block-size: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  pointer-events: none;
}

.s-signal__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
}

.s-stat {
  position: relative;
  padding: clamp(18px, 2.2vw, 30px);
  border-inline-start: 1px solid var(--line);
}

.s-stat:first-child { border-inline-start: 0; padding-inline-start: 0; }

.s-stat__value {
  font-family: var(--font-mono);
  font-size: var(--fs-stat);
  font-weight: 500;
  line-height: 1;
}

.s-stat--accent .s-stat__value { color: var(--accent-soft); }

/* The counter climbs from 0 to its final value, so the box is reserved for
   the final digit count up front. Without this the grid cell resizes
   mid-count and everything below it moves. */
.s-stat__num {
  display: inline-block;
  min-inline-size: calc(var(--digits, 1) * 1ch);
  text-align: end;
}

.s-stat__suffix { display: inline-block; }

.s-stat__bloom {
  position: absolute;
  z-index: -1;
  inset-block-start: 4%;
  inset-inline-start: -10%;
  inline-size: 74%;
  aspect-ratio: 1;
  border-radius: var(--r-round);
  background: radial-gradient(circle, rgba(133, 200, 205, .26) 0%, transparent 68%);
  filter: blur(26px);
  opacity: var(--sun);
  pointer-events: none;
}

.s-stat__label {
  margin-block-start: 10px;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}


/* ── 6.9 process ──────────────────────────────────────────────────────────── */

.s-process__title { margin-block-start: 0; max-inline-size: 20ch; }

.s-steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: clamp(18px, 2.4vw, 28px);
  margin-block-start: clamp(34px, 4.5vw, 62px);
  padding-block-start: 28px;
}

/* The connector. Its fill is scroll-linked, so the path draws as you read. */
.s-steps__path {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 1px;
  background: var(--line);
}

.s-steps__path-fill {
  display: block;
  block-size: 100%;
  inline-size: 0;
  background: var(--accent);
}

.s-step {
  position: relative;
  padding: 24px;
  background: var(--tile);
  border-radius: var(--r-tile);
  border-block-start: 2px solid var(--line);
  transition: background-color var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out),
              box-shadow var(--dur-3) var(--ease-out);
}

.s-step__bar {
  position: absolute;
  inset-block-start: -2px;
  inset-inline: 0;
  block-size: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
}

[dir="rtl"] .s-step__bar { transform-origin: right center; }

.s-step__num { font-size: 11px; color: var(--accent-ink); overflow: hidden; }
.s-step__numRoll { display: block; }
.s-step__title { margin-block: 12px 10px; }
.s-step__body { font-size: var(--fs-small); color: var(--ink-muted); }

@media (hover: hover) and (pointer: fine) {
  .s-step:hover {
    background: var(--tile-hover);
    transform: translateY(-3px);
    box-shadow: var(--shadow-lift);
  }
}


/* ── 6.10 quote ───────────────────────────────────────────────────────────── */

.s-quote { margin: 0; text-align: center; }

.s-quote__text {
  margin-inline: auto;
  font-size: var(--fs-quote);
  font-weight: 300;
  text-wrap: pretty;
}

html[lang="ar"] .s-quote__text { max-inline-size: 24ch; line-height: 1.5; }
html[lang="en"] .s-quote__text { max-inline-size: 22ch; line-height: 1.3; }

/* Only ever colours marks the copy already contains. */
.s-mark { color: var(--accent); }

.s-quote__src {
  display: block;
  min-block-size: 1.4em;
  margin-block-start: var(--sp-5);
  font-size: 11px;
  letter-spacing: .16em;
  color: var(--accent-ink);
  font-style: normal;
}


/* ── 6.11 contact ─────────────────────────────────────────────────────────── */

.s-contact__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: clamp(28px, 4vw, 64px);
}

.s-contact__title { font-size: var(--fs-h2); max-inline-size: 15ch; }
.s-contact__lead { margin-block-start: 20px; max-inline-size: 38ch; }

.s-caret { color: var(--accent); }

.s-contact__links {
  display: flex;
  flex-direction: column;
  gap: var(--tile-gap);
  margin-block-start: var(--sp-6);
  max-inline-size: 360px;
}

.s-contact__link { min-block-size: 48px; }
.s-contact__link .s-mono { font-size: 13px; }

.s-form { display: flex; flex-direction: column; gap: 13px; }

/* Off-screen, never display:none — bots skip hidden fields. */
.s-honey {
  position: absolute;
  inset-inline-start: -9999px;
  inline-size: 1px;
  block-size: 1px;
  opacity: 0;
}

.s-form__submit { inline-size: 100%; }

.s-form__status {
  min-block-size: 1.2em;
  font-size: var(--fs-small);
  color: var(--accent-ink);
}

.s-form__status[data-state="error"] { color: var(--signal-ink); }


/* ── 6.12 footer ──────────────────────────────────────────────────────────
   The wordmark rises from the frame's bottom edge like a horizon, and the sun
   sinks behind it. Bookend to the opening sunrise. */

.s-footer { padding-block-start: clamp(36px, 5vw, 70px); }

.s-footer__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block-end: 22px;
  border-block-end: 1px solid var(--line);
}

.s-footer__copy { font-size: 11px; letter-spacing: .1em; color: var(--ink-faint); }
.s-footer__top { min-block-size: 40px; }

/* Sun and wordmark share one grid cell, so both centre without any
   left/right and the sun can sink behind the horizon on scroll. */
.s-footer__horizon {
  display: grid;
  margin-block-start: clamp(24px, 4vw, 48px);
  overflow: hidden;
}

.s-footer__horizon > * { grid-area: 1 / 1; }

.s-footer__sun {
  place-self: start center;
  z-index: 0;
  inline-size: 28px;
  block-size: 28px;
  margin-block-start: 6%;
  border-radius: var(--r-round);
  background: radial-gradient(circle, #FFFFFF 0%, #DFF4F5 42%, rgba(97, 187, 193, 0) 72%);
  box-shadow: var(--glow-sun);
  opacity: var(--sun);
  pointer-events: none;
}

.s-footer__mark { place-self: end center; z-index: 1; margin-block-end: -11%; }


/* ── 6.13 menu sheet ──────────────────────────────────────────────────────
   The same .s-nav__links element is a row of flex children on desktop and a
   drop sheet under 700px. Nothing is duplicated, so the accessibility tree
   only ever holds one copy of the navigation. */

.s-nav__links { display: contents; }

.s-menu__btn { display: none; }

.s-menu__glyph {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  margin-inline-start: auto;
  inline-size: 14px;
}

.s-menu__glyph i {
  display: block;
  block-size: 1px;
  background: currentColor;
  transition: transform var(--dur-2) var(--ease-out);
}


/* ═══ 6.14 RESPONSIVE ═════════════════════════════════════════════════════ */

/* ── 900–1199: the split holds, everything tightens ───────────────────────── */

@media (max-width: 1199px) {
  .s-hero { grid-template-columns: minmax(300px, .46fr) 1fr; }
  .s-nav__tile { padding-inline: 10px; }
  .s-hero__stage { min-block-size: 440px; }
}


/* ── short desktop viewports ──────────────────────────────────────────────
   A 1440x800 laptop is the tight case, and Arabic is the tight language: its
   headline wraps to four lines at 1.25 leading. The type steps down and the
   vertical gaps tighten so the hero still resolves to a single screen. */

@media (min-width: 900px) and (max-height: 880px) {
  .s-hero__title { font-size: clamp(30px, 3.4vw, 50px); }
  .s-hero__lead { font-size: clamp(15px, 1.1vw, 17px); margin-block-start: 16px; }
  .s-hero__act { margin-block-start: clamp(18px, 3vh, 40px); }
  .s-hero__eyebrow { margin-block-end: clamp(10px, 1.6vh, 18px); }
  .s-logo--hero { --mark-h: clamp(36px, 3.4vw, 52px); }
}


/* ── 700–899: two rows — logo + nav + stage, then text beside the action ──── */

@media (max-width: 899px) and (min-width: 700px) {
  .s-hero {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "logo  nav"
      "stage stage"
      "say   act";
    gap: var(--tile-gap) var(--sp-6);
    padding: var(--gutter);
    min-block-size: 0;
  }

  .s-hero__start,
  .s-hero__end { display: contents; }

  .s-hero__logo  { grid-area: logo; align-self: center; }
  .s-nav         { grid-area: nav; }
  .s-hero__stage { grid-area: stage; min-block-size: 60svh; margin-block-start: var(--sp-4); }
  .s-hero__say   { grid-area: say; margin-block-start: var(--sp-6); }
  .s-hero__act   { grid-area: act; margin-block-start: var(--sp-6); align-self: end; }
  .s-hero__void  { display: none; }

  .s-logo--hero { --mark-h: 40px; }
  .s-hero__title { max-inline-size: 16ch; }

  /* Wrap to a second row rather than shrinking the labels to ellipsis. */
  .s-nav { flex-wrap: wrap; justify-content: flex-end; }
  .s-nav__tile { flex: 0 1 auto; }
  .s-nav__tile .s-tile__label { overflow: visible; text-overflow: clip; }
}


/* ── < 700: one column, stage first, nav behind a menu tile ───────────────── */

@media (max-width: 699px) {
  .s-hero {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "logo  nav"
      "stage stage"
      "say   say"
      "act   act";
    gap: var(--tile-gap);
    padding: var(--gutter);
    min-block-size: 0;
  }

  .s-hero__start,
  .s-hero__end { display: contents; }

  .s-hero__logo  { grid-area: logo; align-self: center; }
  .s-nav         { grid-area: nav; }
  .s-hero__void  { display: none; }

  /* The stage comes first on mobile, so the drop is the first thing seen. */
  .s-hero__stage {
    grid-area: stage;
    min-block-size: min(56svh, 460px);
    margin-block-start: var(--sp-4);
  }

  .s-hero__say { grid-area: say; margin-block-start: var(--sp-6); }
  .s-hero__act { grid-area: act; margin-block-start: var(--sp-5); }

  .s-logo--hero { --mark-h: 26px; }
  .s-hero__title { max-inline-size: none; }
  .s-hero__cta { inline-size: 100%; }

  /* Top bar holds only language, menu and the CTA. */
  .s-nav { position: relative; justify-content: flex-end; }
  .s-menu__btn { display: flex; flex: 0 1 auto; }
  .s-nav__tile--cta { flex: 0 1 auto; }

  .s-nav__links {
    position: absolute;
    z-index: calc(var(--z-nav) - 1);
    inset-block-start: calc(100% + var(--tile-gap));
    inset-inline: 0;
    display: grid;
    gap: var(--tile-gap);
    visibility: hidden;
  }

  .s-nav__links .s-nav__tile {
    min-block-size: 56px;
    font-size: var(--fs-small);
    box-shadow: var(--shadow-lift);
    opacity: 0;
    transform: translateY(-8px);
  }

  .s-nav.is-menu-open .s-nav__links { visibility: visible; }

  .s-nav.is-menu-open .s-nav__links .s-nav__tile {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur-3) var(--ease-out) calc(var(--i, 0) * 40ms),
                transform var(--dur-3) var(--ease-out) calc(var(--i, 0) * 40ms);
  }

  .s-menu__btn[aria-expanded="true"] .s-menu__glyph i:first-child { transform: translateY(2.5px) rotate(45deg); }
  .s-menu__btn[aria-expanded="true"] .s-menu__glyph i:last-child  { transform: translateY(-2.5px) rotate(-45deg); }

  /* The compact bar keeps only the brand and the CTA at this width. */
  .s-compact__nav .s-compact__tile:not(.s-tile--ink) { display: none; }

  .s-orbit { max-inline-size: min(92vw, 420px); }
  .s-orbit__cap { font-size: 12px; padding: 6px 10px; }

  .s-signal__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .s-stat:nth-child(odd) { border-inline-start: 0; padding-inline-start: 0; }

  /* Stacked steps: the path runs down the inline-start edge instead. */
  .s-steps { padding-block-start: 0; padding-inline-start: 20px; }

  .s-steps__path {
    inset-block: 0;
    inset-inline: 0 auto;
    inline-size: 1px;
    block-size: auto;
  }

  .s-steps__path-fill { inline-size: 100%; block-size: 0; }

  .s-footer__row { gap: var(--sp-3); }
}


/* ── very small: keep the type from crowding ──────────────────────────────── */

@media (max-width: 430px) {
  .s-logo--hero { --mark-h: 22px; }
  /* Tighten the cells rather than clipping the CTA's label to an ellipsis. */
  .s-nav { gap: 2px; }
  .s-nav__tile,
  .s-menu__btn { padding-inline: 9px; gap: var(--sp-1); }
  .s-nav__tile--cta .s-tile__label { overflow: visible; text-overflow: clip; }
}


/* ── 6.15 stage: glass slab ───────────────────────────────────────────────
   Anchored by its LOWER-START CORNER, which is the one point that matters:
   the impact point, the shockwave origin, the grid-flash centre and the sun
   all sit exactly there. Rotating about that corner keeps it fixed whatever
   the angle, which is why the corner is the transform-origin and not the
   centre. */

.s-glass {
  position: absolute;
  z-index: 5;
  /* 76%, not the brief's 64%: at 64% the slab floats clear of both side
     edges and never "overflows the panel edge" the way section 3 describes.
     76% is the smallest width that reaches the end edge from this corner. */
  inline-size: 76%;
  aspect-ratio: 1 / 1.04;
  /* Bottom-start corner pinned to the impact point; the slab hangs upward
     and overflows the stage's top-end edge, as in the reference. */
  inset-inline-start: var(--impact-x);
  inset-block-end: calc(100% - var(--impact-y));
  pointer-events: none;
}

.s-glass__fall,
.s-glass__squash,
.s-glass__slab,
.s-glass__ghost {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  inline-size: 100%;
  block-size: 100%;
}

/* Rotation about the contact corner. Mirrored, not flipped, in RTL. */
.s-glass__fall {
  transform-origin: left bottom;
  rotate: -14deg;
}

[dir="rtl"] .s-glass__fall { transform-origin: right bottom; rotate: 14deg; }

/* Its own origin, so the impact squash can pivot on the contact edge
   without disturbing the fall's rotation. */
.s-glass__squash { transform-origin: left bottom; }
[dir="rtl"] .s-glass__squash { transform-origin: right bottom; }

.s-glass__slab {
  overflow: hidden;
  border: 1px solid rgba(236, 241, 241, .16);
  border-radius: 6px;
  background: linear-gradient(145deg,
              rgba(133, 200, 205, .55),
              rgba(89, 167, 172, .16) 60%,
              rgba(236, 241, 241, .10));
  /* Static. Animating a backdrop filter is the single most expensive thing
     this page could do, so movement comes from transforms and __spec. */
  backdrop-filter: blur(22px) saturate(1.3);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
}

/* Motion-blur trail for the fall. A duplicate ghost, never a filter on the
   backdrop layer. */
.s-glass__ghost {
  z-index: -1;
  border-radius: 6px;
  background: linear-gradient(145deg, rgba(133, 200, 205, .3), rgba(89, 167, 172, .08) 70%, transparent);
  transform-origin: left bottom;
  rotate: -14deg;
  opacity: 0;
}

[dir="rtl"] .s-glass__ghost { transform-origin: right bottom; rotate: 14deg; }

/* The Solis S, embossed and frosted inside the glass. Rotates with the slab,
   never flipped. cqi again: a percentage block-size on this tall PNG would
   fall back to its intrinsic height. */
.s-glass__slab {
  container-type: inline-size;
  display: flex;
  align-items: center;
  justify-content: center;
}

.s-glass__mark {
  block-size: 46cqi;
  inline-size: auto;
  filter: blur(10px);
  opacity: .36;
  mix-blend-mode: soft-light;
}

/* Diagonal band for the light sweep. At rest it is invisible; the pointer
   sheen below is what keeps the glass alive. */
.s-glass__spec {
  position: absolute;
  inset: -20%;
  background: linear-gradient(115deg,
              transparent 34%, rgba(255, 255, 255, .55) 50%, transparent 66%);
  mix-blend-mode: screen;
  opacity: 0;
}

/* Pointer-reactive highlight. */
.s-glass__slab::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(58% 58% at calc(var(--mx) * 100%) calc(var(--my) * 100%),
              rgba(255, 255, 255, .16), transparent 72%);
  pointer-events: none;
}

/* The lit edge: brighter inner line on the two sides facing the sun,
   faded away from the contact corner. */
.s-glass__edge {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  border-inline-start: 1px solid rgba(223, 244, 245, .8);
  border-block-end: 1px solid rgba(223, 244, 245, .8);
  mask-image: radial-gradient(72% 72% at 0% 100%, #000 0%, transparent 76%);
}

[dir="rtl"] .s-glass__edge {
  mask-image: radial-gradient(72% 72% at 100% 100%, #000 0%, transparent 76%);
}

/* Floor shadow under the landing spot. Grows during the fall, tightens on
   contact — the thing that actually sells the height. */
.s-stage__shadow {
  position: absolute;
  z-index: 4;
  inset-inline-start: var(--impact-x);
  inset-block-start: var(--impact-y);
  inline-size: 0;
  block-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.s-stage__shadow::before {
  content: "";
  flex: none;
  inline-size: 30cqw;
  block-size: 42px;
  border-radius: var(--r-round);
  background: radial-gradient(closest-side, rgba(3, 8, 9, .8), transparent 74%);
  filter: blur(9px);
  opacity: .3;
}


/* ── 6.16 the sun ─────────────────────────────────────────────────────────
   Sits exactly on the slab's lit corner. Same coordinates as the shockwave
   and the grid flash — computed once, used by everything. */

.s-sun {
  --sun-size: clamp(40px, 4vw, 64px);
  position: absolute;
  z-index: 8;
  inset-inline-start: var(--impact-x);
  inset-block-start: var(--impact-y);
  inline-size: 0;
  block-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.s-sun__orb {
  flex: none;
  inline-size: var(--sun-size);
  block-size: var(--sun-size);
  border-radius: var(--r-round);
  background: radial-gradient(circle,
              #FFFFFF 0%, #FFFFFF 26%, #DFF4F5 44%, rgba(133, 200, 205, .5) 62%,
              rgba(97, 187, 193, 0) 78%);
  box-shadow:
    0 0 calc(40px * var(--sun)) calc(10px * var(--sun)) rgba(223, 244, 245, .55),
    0 0 calc(120px * var(--sun)) calc(40px * var(--sun)) rgba(97, 187, 193, .35);
  opacity: var(--sun);
}

/* Shockwave rings — intro only, hence opacity 0 at rest. */
.s-sun__ring {
  position: absolute;
  inline-size: var(--sun-size);
  block-size: var(--sun-size);
  border: 1px solid var(--accent-soft);
  border-radius: var(--r-round);
  opacity: 0;
}


/* ── 6.17 HUD ─────────────────────────────────────────────────────────────
   Dot, connector tick, caption, value. Decorative: every number here is
   repeated for real in the Signal section. */

.s-hud {
  position: absolute;
  z-index: 9;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  pointer-events: none;
}

.s-hud__dot {
  position: relative;
  flex: none;
  inline-size: 5px;
  block-size: 5px;
  margin-block-start: 5px;
  border-radius: var(--r-round);
  background: var(--on-panel-muted);
}

.s-hud--accent .s-hud__dot { background: var(--accent-soft); }

.s-hud__ping {
  position: absolute;
  inset: 0;
  border-radius: var(--r-round);
  background: var(--accent-soft);
  opacity: 0;
}

.s-hud__tick {
  flex: none;
  inline-size: 10px;
  block-size: 1px;
  margin-block-start: 7px;
  background: var(--line-on-dark);
  transform-origin: left center;
}

[dir="rtl"] .s-hud__tick { transform-origin: right center; }

.s-hud__body { display: flex; flex-direction: column; gap: 2px; }

.s-hud__caption {
  /* Typed in from empty, so its line box is reserved — an empty inline box
     has no line box at all, and the label would resize as it fills. */
  min-block-size: 1.4em;
  font-size: var(--fs-hud);
  line-height: 1.4;
  letter-spacing: .1em;
  color: var(--on-panel-muted);
  white-space: nowrap;
}

html[lang="ar"] .s-hud__caption { letter-spacing: 0; }

.s-hud__value {
  font-size: 11.5px;
  line-height: 1.2;
  color: var(--on-panel);
}

.s-hud--accent .s-hud__value { color: var(--accent-soft); }

.s-hud--clock .s-hud__dot { background: var(--accent); }


/* ── 6.18 stage responsive ────────────────────────────────────────────────── */

@media (max-width: 699px) {
  .s-glass { inline-size: 86%; }
  .s-sun { --sun-size: 38px; }

  /* Three labels at this width, not four. */
  .s-hud--drop-sm { display: none; }

  .s-hud__caption { font-size: 9px; }
  .s-hud__value { font-size: 10.5px; }
}


/* ── 6.19 inner-page bar ──────────────────────────────────────────────────
   The work pages have no hero, so the nav is one sticky row from the start:
   the compact bar's glass, the hero nav's tiles. */

.s-bar {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: var(--tile-gap);
  padding: var(--sp-2) var(--gutter);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(16px) saturate(1.2);
  border-block-end: 1px solid var(--line);
}

.s-bar__logo { display: flex; margin-inline-end: var(--sp-4); }
.s-bar__nav { display: flex; gap: var(--tile-gap); margin-inline-start: auto; }
.s-bar__tile { min-block-size: 40px; }

@media (max-width: 699px) {
  .s-bar__tile--home { display: none; }
}

@media (max-width: 419px) {
  .s-bar__logo .s-logo__word { display: none; }
  .s-bar__tile { padding-inline: 10px; }
}

/* The home rail's way into the archive. */
.s-rail__more { display: flex; justify-content: flex-end; }


/* ── 6.20 work archive ────────────────────────────────────────────────────── */

.s-archive { padding-block-start: clamp(40px, 6vw, 96px); }
.s-archive__title { font-size: var(--fs-h1); max-inline-size: 16ch; }

.s-archive__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: clamp(20px, 2.4vw, 36px) clamp(12px, 1.6vw, 22px);
}

/* The rail card, freed from the rail: it fills its cell instead of a fixed
   flex basis, and keeps the same hover. */
.s-archive__grid .s-work { flex: none; }

@media (hover: hover) and (pointer: fine) {
  .s-archive__grid .s-work:hover .s-work__img { scale: 1.04; }
}


/* ── 6.21 case study ──────────────────────────────────────────────────────
   A 12-column sheet. Words sit on an offset reading column (4 → 10); media
   takes the full measure, or the reading column when asked to. Sharp frames
   around every image, liquid only in the light. */

.s-case__head {
  padding-block: clamp(40px, 6vw, 96px) clamp(28px, 4vw, 56px);
}

/* The eyebrow's look without .s-eyebrow: that class is scrambled by the
   heading decode, which would flatten the link inside this one. */
.s-case__eyebrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-block-end: var(--sp-4);
  letter-spacing: var(--track-eyebrow);
  color: var(--accent-ink);
}

html[lang="ar"] .s-case__eyebrow { letter-spacing: var(--track-eyebrow); }
.s-case__back { color: inherit; }

@media (hover: hover) and (pointer: fine) {
  .s-case__back:hover { color: var(--ink); }
}

.s-case__title {
  font-size: var(--fs-h1);
  max-inline-size: 20ch;
}

.s-case__intro {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: var(--sp-6);
  margin-block-start: clamp(28px, 4vw, 56px);
  padding-block-start: var(--sp-5);
  border-block-start: 1px solid var(--line);
}

.s-case__lead { grid-column: 1 / span 7; max-inline-size: 58ch; }

.s-case__meta {
  grid-column: 9 / -1;
  display: grid;
  gap: var(--tile-gap);
  margin: 0;
  align-self: start;
}

.s-case__meta:only-child { grid-column: 1 / span 5; }

.s-case__fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 12px 14px;
  background: var(--tile);
  border-radius: var(--r-tile);
}

.s-case__fact dt { font-size: var(--fs-label); color: var(--ink-muted); }
.s-case__fact dd { margin: 0; font-size: var(--fs-small); font-weight: 500; text-align: end; }
html[lang="en"] .s-case__fact dt { letter-spacing: .04em; text-transform: uppercase; }

.s-case__draft {
  margin-block-start: var(--sp-5);
  padding: 10px 14px;
  border-radius: var(--r-tile);
  background: color-mix(in srgb, var(--signal) 10%, transparent);
  color: var(--signal-ink);
  font-size: 11px;
}

/* Cover: full measure, sharp frame. */
.s-case__cover { margin-block: 0; }

.s-case__cover-frame {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  background: var(--tile);
}

.s-case__cover img {
  inline-size: 100%;
  block-size: auto;
  max-block-size: 86svh;
  object-fit: cover;
}

/* The body sheet. */
.s-case__body {
  --block-gap: clamp(28px, 4vw, 64px);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: var(--block-gap);
  padding-block: clamp(48px, 7vw, 112px);
}

.s-block { grid-column: 1 / -1; margin: 0; min-inline-size: 0; }

.s-block--heading,
.s-block--text,
.s-block--quote { grid-column: 4 / span 7; }

.s-block--heading {
  font-size: clamp(22px, 2.4vw, 34px);
  font-weight: 400;
  line-height: 1.3;
  /* A heading belongs to the text under it, so it sits closer to it. */
  margin-block-end: calc(var(--block-gap) * -.55);
}

html[lang="en"] .s-block--heading { letter-spacing: var(--track-h2); line-height: 1.15; }

.s-block--text {
  display: grid;
  gap: 1em;
  font-size: var(--fs-lead);
  color: var(--ink);
  text-wrap: pretty;
}

.s-block--quote {
  padding-inline-start: var(--sp-5);
  border-inline-start: 2px solid var(--accent);
}

.s-block--quote p {
  font-size: clamp(22px, 2.6vw, 36px);
  line-height: 1.4;
  text-wrap: balance;
}

html[lang="en"] .s-block--quote p { letter-spacing: var(--track-h2); line-height: 1.2; }

.s-block--quote cite {
  display: block;
  margin-block-start: var(--sp-4);
  font-style: normal;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

/* Media: an image (wide, full bleed of the measure, or on the reading
   column), a gallery, a film. */
.s-block--narrow { grid-column: 4 / span 7; }

/* Full: out to the frame's edges, past the measure. */
.s-block--full { margin-inline: calc(50% - 50vw); }
.s-block--full .s-shot { border-inline: 0; border-radius: 0; }
.s-block--full figcaption { padding-inline: var(--gutter); }

.s-block--media figcaption {
  margin-block-start: var(--sp-3);
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

.s-shot {
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  background: var(--tile);
  overflow: hidden;
  cursor: zoom-in;
}

.s-shot img {
  inline-size: 100%;
  block-size: auto;
  transition: scale var(--dur-4) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .s-shot:hover img { scale: 1.02; }
}

.s-gallery { display: grid; gap: var(--sp-2); }
.s-gallery--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.s-gallery--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Gallery cells share one shape so the grid reads as a contact sheet. */
.s-gallery__item { aspect-ratio: 4 / 5; }
.s-gallery__item img { block-size: 100%; object-fit: cover; }

.s-film,
.s-embed {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-tile);
  background: var(--panel-deep);
}

.s-film video { display: block; inline-size: 100%; block-size: auto; max-block-size: 90svh; }

.s-embed { aspect-ratio: 16 / 9; }
.s-embed iframe { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; border: 0; }

/* End: the invitation, then the next project. */
.s-case__end {
  display: grid;
  gap: var(--sp-6);
  padding-block: var(--sp-6) var(--section-y);
  border-block-start: 1px solid var(--line);
}

.s-case__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  padding-block: var(--sp-5);
}

.s-case__cta-title { font-size: var(--fs-h2); max-inline-size: 18ch; }

.s-next {
  display: grid;
  grid-template-columns: minmax(96px, 180px) 1fr auto;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3);
  background: var(--tile);
  border-radius: var(--r-tile);
  transition: background-color var(--dur-2) var(--ease-out);
}

.s-next__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r-tile);
  background: repeating-linear-gradient(-45deg, var(--line) 0 1px, transparent 1px 11px);
}

.s-next__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: scale var(--dur-4) var(--ease-out);
}

.s-next__say { display: grid; gap: var(--sp-2); min-inline-size: 0; }
.s-next__label { font-size: var(--fs-label); color: var(--accent-ink); }
html[lang="en"] .s-next__label { letter-spacing: .08em; text-transform: uppercase; }
.s-next__title { font-size: clamp(22px, 3vw, 44px); line-height: 1.2; }
html[lang="en"] .s-next__title { letter-spacing: var(--track-h2); line-height: 1.05; }
.s-next__arrow { display: flex; padding-inline: var(--sp-4); color: var(--ink-muted); }
.s-next__arrow .s-arrow { inline-size: 24px; block-size: 24px; }

@media (hover: hover) and (pointer: fine) {
  .s-next:hover { background: var(--tile-hover); }
  .s-next:hover .s-next__media img { scale: 1.06; }
  .s-next:hover .s-next__arrow { color: var(--ink); }
}

/* Lightbox for zoomed stills. A native <dialog>, so focus and Escape come free. */
.s-lightbox {
  inline-size: 100vw;
  max-inline-size: 100vw;
  block-size: 100svh;
  max-block-size: 100svh;
  margin: 0;
  padding: var(--gutter);
  border: 0;
  background: color-mix(in srgb, var(--panel-deep) 94%, transparent);
  color: var(--on-panel);
}

.s-lightbox[open] { display: grid; place-items: center; }
.s-lightbox::backdrop { background: transparent; }

.s-lightbox img {
  max-inline-size: 100%;
  max-block-size: calc(100svh - var(--gutter) * 2 - 56px);
  inline-size: auto;
  block-size: auto;
  border-radius: var(--r-tile);
}

.s-lightbox__close {
  position: absolute;
  inset-block-start: var(--gutter);
  inset-inline-end: var(--gutter);
  min-block-size: 44px;
  padding-inline: 16px;
  border: 1px solid var(--line-on-dark);
  border-radius: var(--r-tile);
  background: transparent;
  color: var(--on-panel);
  font-size: var(--fs-small);
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .s-lightbox__close:hover { background: rgba(236, 241, 241, .08); }
}

@media (max-width: 899px) {
  .s-case__lead,
  .s-case__meta,
  .s-case__meta:only-child { grid-column: 1 / -1; }

  .s-block--heading,
  .s-block--text,
  .s-block--quote,
  .s-block--narrow { grid-column: 1 / -1; }
}

@media (max-width: 599px) {
  .s-gallery--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .s-next { grid-template-columns: 88px 1fr; gap: var(--sp-4); }
  .s-next__arrow { display: none; }
}


/* ═══ 7. MOTION ════════════════════════════════════════════════════════════
   Every intro "from" state is written as `final + (--intro × delta)`.
   --intro is 1 while html.js-intro is set and 0 otherwise, so:
     · no JS, no class  -> --intro is 0 -> the page is simply finished
     · JS runs          -> WAAPI drives the real choreography
     · JS dies mid-way  -> the 4s failsafe keyframe drives --intro to 0 and
                           every one of these states resolves to final
   One number, one failsafe, no duplicated "visible" rules.
   ═════════════════════════════════════════════════════════════════════════ */

@property --intro { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --glint { syntax: "<percentage>"; inherits: false; initial-value: 100%; }

/* Direction signs, so a single calc() serves both writing modes. */
:root            { --dirx: 1;  --tilt: -1; }
html[dir="rtl"]  { --dirx: -1; --tilt: 1; }

.js-intro { --intro: 1; animation: s-failsafe 1ms linear 4s forwards; }

@keyframes s-failsafe { to { --intro: 0; } }


/* ── 7.1 act 1 — the frame draws ──────────────────────────────────────────── */

.s-frame__fill {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--paper);
  opacity: calc(1 - var(--intro));
}

/* The frame paints its own paper; only during the intro does it step aside
   so .s-frame__fill can fade in underneath the drawn edges. */
.js-intro .s-frame { background: transparent; }

/* Declared above as opacity: var(--intro) — visible only while the intro is
   running, and gone afterwards, with no resting border to match. */

.s-frame__edge--top,
.s-frame__edge--bottom { transform: scaleX(calc(1 - var(--intro))); }
.s-frame__edge--start,
.s-frame__edge--end    { transform: scaleY(calc(1 - var(--intro))); }


/* ── 7.2 act 2 — structure ────────────────────────────────────────────────── */

/* The column divider draws downward, so it is its own element rather than a
   border — and a real element, not a pseudo, so the timeline can target it
   like anything else. It is hidden outright once the columns stack. */
.s-hero__start { position: relative; border-inline-end: 0; }

.s-hero__divider {
  position: absolute;
  inset-block: 0;
  inset-inline-end: -1px;
  inline-size: 1px;
  background: var(--line);
  transform: scaleY(calc(1 - var(--intro)));
  transform-origin: center top;
  pointer-events: none;
}

@media (max-width: 899px) {
  .s-hero__divider { display: none; }
}

.s-nav__tile,
.s-menu__btn {
  clip-path: inset(0 0 calc(100% * var(--intro)) 0);
  translate: 0 calc(-10px * var(--intro));
}

.s-logo__mark { clip-path: inset(calc(100% * var(--intro)) 0 0 0); }
.s-logo__word { clip-path: inset(0 calc(100% * var(--intro)) 0 0); }

html[dir="rtl"] .s-logo__word { clip-path: inset(0 0 0 calc(100% * var(--intro))); }


/* ── 7.3 act 3 — the stage opens ──────────────────────────────────────────── */

.s-hero__stage {
  clip-path: inset(calc(50% * var(--intro)) 0 calc(50% * var(--intro)) 0 round var(--r-panel));
}

.js-intro .s-hero__stage { --sun: 0; --grid-a: 0; }


/* ── 7.4 act 4 — the drop ─────────────────────────────────────────────────── */

.s-glass__fall {
  translate: 0 calc(-135% * var(--intro));
  /* -4deg while falling, -14deg once settled. It never snaps: the rotation
     continues through the landing. */
  rotate: calc(var(--tilt) * (14deg - 10deg * var(--intro)));
}

[dir="rtl"] .s-glass__fall { rotate: calc(var(--tilt) * (14deg - 10deg * var(--intro))); }

.s-stage__shadow::before {
  opacity: calc(.3 - .3 * var(--intro));
  scale: calc(1 - .6 * var(--intro));
}


/* ── 7.5 act 5 — sunrise ──────────────────────────────────────────────────── */

.s-sun__orb { scale: calc(1 - var(--intro)); }

.s-glass__mark {
  opacity: calc(.36 - .36 * var(--intro));
  filter: blur(calc(10px + 18px * var(--intro)));
}

.s-glass__edge { opacity: calc(1 - var(--intro)); }


/* ── 7.6 act 6 — the words are lit ────────────────────────────────────────── */

.s-hero__eyebrow { opacity: calc(1 - var(--intro)); }

.s-hero__title .s-word {
  opacity: calc(1 - var(--intro));
  translate: 0 calc(.6em * var(--intro));
  rotate: calc(1.5deg * var(--intro));
  filter: blur(calc(10px * var(--intro)));
}

.s-hero__lead {
  clip-path: inset(0 0 calc(100% * var(--intro)) 0);
  translate: 0 calc(12px * var(--intro));
}

/* The sunlit pass. Applied by JS for the length of the sweep only, so a
   failure can never leave the word transparent. */
.s-hl.is-lit {
  background-image: linear-gradient(100deg,
                    var(--accent-ink) 34%, #DFF4F5 50%, var(--accent-ink) 66%);
  background-size: 300% 100%;
  background-position: var(--glint) 0;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}


/* ── 7.7 act 7 — HUD boot ─────────────────────────────────────────────────── */

.s-hud__dot  { scale: calc(1 - var(--intro)); }
.s-hud__tick { transform: scaleX(calc(1 - var(--intro))); }
.s-hud__body { opacity: calc(1 - var(--intro)); translate: 0 calc(4px * var(--intro)); }


/* ── 7.8 act 8 — action ───────────────────────────────────────────────────── */

.s-hero__cta .s-btn__fill  { transform: scaleX(calc(1 - var(--intro))); }
.s-hero__cta .s-btn__text  { translate: 0 calc(100% * var(--intro)); }
.s-hero__cta .s-btn__arrow {
  opacity: calc(1 - var(--intro));
  translate: calc(-26px * var(--dirx) * var(--intro)) 0;
}

.s-hero__note,
.s-hero__browse {
  opacity: calc(1 - var(--intro));
  translate: 0 calc(8px * var(--intro));
}

.s-marquee__clip { translate: 0 calc(100% * var(--intro)); }


/* ── 7.9 living things ────────────────────────────────────────────────────
   The only loops on the page: the sun breathing, the clock dot, the marquee,
   the orbit, the scanline and the ambient light. Nothing else repeats. */

@keyframes s-breathe { from { --sun: 1; } to { --sun: .92; } }
@keyframes s-ping    { from { scale: 1; opacity: .6; } to { scale: 3; opacity: 0; } }
@keyframes s-caret   { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes s-scan    { from { translate: 0 -100%; } to { translate: 0 1200%; } }
@keyframes s-spin      { from { rotate: 0deg; } to { rotate: 360deg; } }
@keyframes s-spin-back { from { rotate: 0deg; } to { rotate: -360deg; } }
/* transform, not translate: parallax claims the translate property below,
   and the two compose rather than overwrite. */
@keyframes s-drift-a { from { transform: translate(-6%, -3%) scale(1); }    to { transform: translate(8%, 6%) scale(1.18); } }
@keyframes s-drift-b { from { transform: translate(6%, 5%) scale(1.14); }   to { transform: translate(-8%, -5%) scale(1); } }

.s-caret { animation: s-caret 1.1s step-end infinite; }

.s-signal__scan { animation: s-scan 9s linear infinite; }

.s-stage__ambient--a { animation: s-drift-a 22s ease-in-out infinite alternate; }
.s-stage__ambient--b { animation: s-drift-b 27s ease-in-out infinite alternate; }

.s-hud--clock .s-hud__dot { animation: s-caret 1.8s ease-in-out infinite; }

/* Orbit: the ring spins, each capsule counter-spins by exactly the same
   amount. Both are paused until the entrance sequence has landed. */
.s-orbit__ring-wrap { animation: s-spin 44s linear infinite; }
.s-orbit__counter   { animation: s-spin-back 44s linear infinite; }

.s-orbit.is-held .s-orbit__ring-wrap,
.s-orbit.is-held .s-orbit__counter { animation-play-state: paused; }

/* Sun idle. JS pauses it whenever the stage is off-screen. */
.s-stage.is-breathing { animation: s-breathe 5s ease-in-out infinite alternate; }

@keyframes s-ticker  { from { translate: 0 0; }    to { translate: -50% 0; } }
@keyframes s-tickerR { from { translate: -50% 0; } to { translate: 0 0; } }

.s-marquee__track { animation: s-ticker 34s linear infinite; }
html[dir="rtl"] .s-marquee__track { animation-name: s-tickerR; }


/* ── 7.10 will-change discipline ──────────────────────────────────────────
   Added just before a sequence, removed the moment it finishes. */

.is-animating { will-change: transform, opacity, filter; }


/* ── 7.11 navigation ──────────────────────────────────────────────────────
   The tile hover fill lives in section 5; this is the arrow's exit-and-return
   and the compact bar's show/hide. */

.s-tile__arrow,
.s-btn__arrow { transition: translate var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out); }

@media (hover: hover) and (pointer: fine) {
  /* Out towards the end and gone, then back in from the start and settle. */
  .s-tile:hover .s-tile__arrow,
  .s-btn:hover .s-btn__arrow { animation: s-arrow-cycle 420ms var(--ease-land) both; }
}

@keyframes s-arrow-cycle {
  0%   { translate: 0 0; opacity: 1; }
  42%  { translate: calc(18px * var(--dirx)) 0; opacity: 0; }
  43%  { translate: calc(-18px * var(--dirx)) 0; opacity: 0; }
  100% { translate: 0 0; opacity: 1; }
}

.s-nav__ind { transition: opacity var(--dur-2) var(--ease-out); }

.s-compact { transition: transform 350ms var(--ease-out); }
.s-compact.is-on.is-up { transform: translateY(-101%); }


/* ── 7.12 marquee ─────────────────────────────────────────────────────────
   The track carries the ticker translate, the strip carries the velocity
   skew. Two properties, two elements, no collision. */

.s-marquee__track { transform-origin: center center; }


/* ── 7.13 orbit ───────────────────────────────────────────────────────────
   pathLength=100 turns stroke-dashoffset into a plain 0-100 progress. */

.s-orbit__ring--outer,
.s-orbit__mask { stroke-dasharray: 100; }

.s-orbit__beam {
  stroke: var(--accent-soft);
  stroke-width: 1;
  stroke-dasharray: 100;
  vector-effect: non-scaling-stroke;
  opacity: .7;
}

/* Everything that is not the hovered capsule steps back. */
.s-orbit.is-focused .s-orbit__cap { opacity: .45; }
.s-orbit .s-orbit__cap.is-hot { opacity: 1; background: var(--accent); color: var(--ink-base); }


/* ── 7.14 work rail ───────────────────────────────────────────────────────
   The custom cursor replaces the native one only inside the rail, and
   cursor:grab stays as the fallback. */

.s-work { transition: transform var(--dur-3) var(--ease-soft); }
.s-work__img { transition: scale var(--dur-4) var(--ease-out); }

.s-rail { cursor: grab; }
.s-rail.is-dragging { cursor: grabbing; scroll-behavior: auto; }

@media (hover: hover) and (pointer: fine) {
  .s-rail.has-cursor { cursor: none; }
  .s-rail.has-cursor a { cursor: none; }
  .s-work:hover .s-work__img { scale: 1.04; }
}

.s-cursor {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: var(--z-cursor);
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 76px;
  block-size: 76px;
  border-radius: var(--r-round);
  background: var(--ink-base);
  color: var(--paper-base);
  pointer-events: none;
  opacity: 0;
  scale: .8;
  transition: opacity var(--dur-2) var(--ease-out), scale var(--dur-3) var(--ease-soft);
}

.s-cursor.is-on { opacity: 1; scale: 1; }
.s-cursor__label { font-size: 11px; letter-spacing: .12em; }


/* ── 7.15 signal ──────────────────────────────────────────────────────────── */

.s-stat__bloom { transform-origin: center; }


/* ── 7.16 process ─────────────────────────────────────────────────────────
   Reversible: is-reached toggles both ways, so scrolling back up unfills. */

.s-steps__path-fill { transition: none; }

.s-step.is-reached .s-step__bar { transform: scaleX(1); }
.s-step__bar { transition: transform 500ms var(--ease-out); }

.js-ready .s-step__title,
.js-ready .s-step__body { opacity: .55; }

.s-step__title,
.s-step__body { transition: opacity var(--dur-3) var(--ease-out); }

.s-step.is-reached .s-step__title,
.s-step.is-reached .s-step__body { opacity: 1; }


/* ── 7.17 quote ───────────────────────────────────────────────────────────── */

.js-ready .s-quote__text .s-word { opacity: .14; }
.s-quote.is-lit .s-mark { color: var(--accent); text-shadow: 0 0 18px rgba(89, 167, 172, .5); }
.s-mark { transition: text-shadow var(--dur-4) var(--ease-out); }


/* ── 7.18 contact ─────────────────────────────────────────────────────────
   Sending, success and error. Every state is announced through the live
   region in the form, not just drawn. */

.s-btn.is-sending .s-btn__fill::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inline-size: 40%;
  background: linear-gradient(90deg, transparent, rgba(236, 241, 241, .35), transparent);
  animation: s-loadbar 900ms linear infinite;
}

@keyframes s-loadbar {
  from { translate: -100% 0; }
  to   { translate: 250% 0; }
}

.s-btn.is-sent .s-btn__fill { background: var(--accent); }
.s-btn.is-sent { color: var(--ink-base); }

.s-form.is-error { animation: s-shake 360ms var(--ease-out); }

@keyframes s-shake {
  0%, 100% { translate: 0 0; }
  20% { translate: 4px 0; }
  45% { translate: -3px 0; }
  70% { translate: 2px 0; }
  88% { translate: -1px 0; }
}

/* Mini sun burst from the button centre on success. */
.s-burst {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 0;
  block-size: 0;
  pointer-events: none;
}

.s-burst i {
  position: absolute;
  inline-size: 2px;
  block-size: 10px;
  margin-block-start: -5px;
  margin-inline-start: -1px;
  background: var(--paper-base);
  border-radius: 1px;
  transform-origin: center;
}


/* ── 7.19 footer ──────────────────────────────────────────────────────────── */

.s-footer__sun { transition: none; }


/* ── 7.20 magnetic buttons ────────────────────────────────────────────────── */

.s-btn[data-magnetic] { transition: translate var(--dur-2) var(--ease-out); }
.s-btn[data-magnetic] .s-btn__label { transition: translate var(--dur-2) var(--ease-out); }


/* ── 7.21 stage parallax depths ───────────────────────────────────────────
   JS lerps --mx/--my across the stage; each layer moves by its own depth, so
   the panel reads as a space rather than a picture. The mark inside the glass
   moves against the others, which is what makes the glass feel like glass.
   Everything rests at 0 when --mx/--my sit at .5, so reduced motion and no-JS
   simply never move. */

.s-stage {
  --px: calc(var(--mx) - .5);
  --py: calc(var(--my) - .5);
}

.s-stage__grid    { translate: calc(var(--px) * 4px)   calc(var(--py) * 4px); }    /* depth  2 */
.s-stage__ambient { translate: calc(var(--px) * 8px)   calc(var(--py) * 8px); }    /* depth  4 */
.s-glass          { translate: calc(var(--px) * 20px)  calc(var(--py) * 20px); }   /* depth 10 */
.s-glass__mark    { translate: calc(var(--px) * -12px) calc(var(--py) * -12px); }  /* depth  6, against */
.s-hud            { translate: calc(var(--px) * 8px)   calc(var(--py) * 8px); }    /* depth  4 */

/* 14px of depth plus up to 18px of lean toward the pointer. */
.s-sun            { translate: calc(var(--px) * 64px)  calc(var(--py) * 64px); }


/* ── 7.22 work pages ──────────────────────────────────────────────────────
   Blocks rise into place as they are reached. The "from" state hangs off
   .js-reveal, which site.js sets only when it will also reveal them — so no
   JS and reduced motion both get the finished page. */

.js-reveal [data-reveal] {
  transition: opacity var(--dur-4) var(--ease-out),
              translate var(--dur-4) var(--ease-out);
}

.js-reveal [data-reveal]:not(.is-in) { opacity: 0; translate: 0 22px; }


/* ═══ 8. REDUCED MOTION ════════════════════════════════════════════════════
   A calm, complete, fully usable page. Not a degraded one: nothing is
   hidden, nothing waits for a scroll, and the only thing still moving is
   the clock's digits — which are information, not decoration.
   ═════════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {

  html { scroll-behavior: auto; }

  /* Kill every loop and every transition. The clock writes itself from JS,
     so its digits keep updating without any animation. */
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* Reveals become a plain fade, and only where JS is driving them. */
  .js-ready .is-in { animation: s-fade 200ms linear both; }

  @keyframes s-fade { from { opacity: 0; } to { opacity: 1; } }

  /* Nothing may be left waiting for a scroll position that never animates.
     These are the two states declared in CSS rather than driven from a
     keyframe, so they are the two that would otherwise strand content. */
  .js-ready .s-quote__text .s-word,
  .js-ready .s-step__title,
  .js-ready .s-step__body { opacity: 1; }

  .s-step .s-step__bar { transform: scaleX(1); }
  .s-steps__path-fill { inline-size: 100%; block-size: 100%; }

  /* The marquee becomes a static wrapped row — still readable, no scroll. */
  .s-marquee {
    block-size: auto;
    padding-block: var(--sp-3);
  }

  .s-marquee__track {
    flex-wrap: wrap;
    inline-size: 100%;
    animation: none;
    transform: none;
  }

  .s-marquee__group { flex-wrap: wrap; row-gap: var(--sp-2); }
  .s-marquee__group:nth-child(2) { display: none; }

  /* No parallax: every layer sits at rest. */
  .s-stage__grid,
  .s-stage__ambient,
  .s-glass,
  .s-glass__mark,
  .s-hud,
  .s-sun { translate: none; }

  .s-stage__ambient { transform: none; }

  /* The custom drag cursor never appears; the native one is never hidden. */
  .s-cursor { display: none; }
  .s-rail.has-cursor,
  .s-rail.has-cursor a { cursor: auto; }

  /* The orbit holds still rather than spinning. */
  .s-orbit__ring-wrap,
  .s-orbit__counter { animation: none; }
}
