/* ==========================================================================
   Aleem — «المحاسب الشامل» landing page. Revision 2 of the visual layer.

   Every value in §1–§4 below is copied from `docs/design-tokens.md`. Where a
   rule is a contrast or a font-geometry constraint rather than taste, the
   number that forces it is in the comment beside it. Four of them have already
   produced a wrong page somewhere:

     1. Gold #B79767 is 2.75 on white, 2.55 on #F4F7F7, 2.51 on teal — below
        even the 3:1 floor for a non-text element. So it is never text, never
        a border, never an icon. It is a FILL under #0E1F1F text (the VAT chip)
        and a decorative hairline that holds no text (the rule over a heading,
        the reading-progress bar). Nothing else.
     2. Alexandria's Arabic ink spans 1.527em at wght 400 and 1.725em at 900,
        against a declared line box of 1.219 — ~25% taller than it says. So
        the leading is supplied here, and `overflow: hidden` appears nowhere
        in this file on anything holding text: it clips Arabic while Latin
        looks fine. Where a box needs clipping it is `clip-path`.
     3. #4A8281 is 4.37 on white. Control boundaries and large text only —
        never body text. #D6E0E0 is 1.35 and is decorative hairlines only.
     4. `--measure` is a PROSE cap, not a container width. `.wrap` is the
        container; `.lead` and `.prose` are what get capped.

   ── What revision 2 adds, in one paragraph ────────────────────────────────
   A reading-progress hairline; a masthead link; a hero stack with an eyebrow,
   a drawn underline on the last word, a second (quiet) link, a no-payment
   line and a name tag on the photograph; three titled pain cards; the nine
   topics under three stage cards joined by a line that fills on scroll; a
   photograph that settles as it scrolls into view; a heading over the proof;
   three steps over the rail; a form that rises when it opens and a drawn tick
   on the thank-you; a heading over the FAQ; a closing call; and a booking bar
   pinned to a phone's bottom edge once the hero has gone. Every entrance below
   the fold is `view()`-driven with `animation-fill-mode: none`; nothing above
   the fold ever touches opacity; and `prefers-reduced-motion: reduce` gets
   none of it.

   No framework, no build step. Custom properties work everywhere without one.
   ========================================================================== */

:root {
  /* ── §1.1 Confirmed brand palette — from the logo's own pixels ────────── */
  --aleem-teal:  #2F6261;   /* 96.4% of the logo's opaque pixels */
  --aleem-gold:  #B79767;   /* 1.8% — FILL ONLY on light grounds */

  /* ── §1.2 Roles ──────────────────────────────────────────────────────── */
  --colour-surface:        #FFFFFF;
  --colour-surface-sunk:   #F4F7F7;
  --colour-surface-brand:  #2F6261;
  --colour-surface-deep:   #1F4241;
  --colour-surface-ink:    #0E1F1F;

  --colour-text:           #0E1F1F;   /* 17.01 on white, 15.79 on sunk */
  --colour-text-muted:     #5B6666;   /* 5.94 on white, 5.51 on sunk */
  --colour-text-brand:     #2F6261;   /* 6.91 on white */
  --colour-text-on-dark:   #FFFFFF;   /* 6.91 on teal, 17.01 on ink */

  --colour-text-on-brand-soft: #D9E6E5;  /* 5.39 on #2F6261, 8.57 on #1F4241 */
  --colour-text-on-ink-soft:   #A9BAB9;  /* 8.43 on #0E1F1F */

  --colour-action:         #2F6261;   /* white label = 6.91 */
  --colour-action-hover:   #1F4241;   /* white label = 10.97 */
  --colour-action-text:    #FFFFFF;

  --colour-accent:         #B79767;   /* FILL only — see the header note */
  --colour-accent-text:    #0E1F1F;   /* 6.19 on that fill */
  --colour-accent-on-dark: #C2A77E;   /* 7.39 on ink */

  --colour-border:         #4A8281;   /* 4.37 — control boundaries, NOT body */
  --colour-rule:           #D6E0E0;   /* 1.35 — decorative hairlines ONLY */
  --colour-rule-dark:      rgb(255 255 255 / 0.22);
  --colour-wash:           rgb(47 98 97 / 0.08);   /* composites to #EAEFEF */

  --colour-invalid:        #8A2B20;   /* 7.36 on white */

  --colour-focus:          #0E1F1F;
  --colour-focus-offset:   #FFFFFF;
  --focus-ring: 0 0 0 2px var(--colour-focus-offset), 0 0 0 4px var(--colour-focus);

  /* ── §2 Type ─────────────────────────────────────────────────────────── */
  --font-family: 'Alexandria', 'Segoe UI', system-ui, sans-serif;

  --text-body:  clamp(1.0625rem, 1rem + 0.3vw, 1.125rem);   /* 17 → 18 */
  --text-small: 0.9375rem;                                  /* 15 */
  --text-tiny:  0.8125rem;                                  /* 13 */
  --text-lead:  clamp(1.1875rem, 1.05rem + 0.6vw, 1.375rem);/* 19 → 22 */
  --text-h3:    clamp(1.25rem, 1.1rem + 0.7vw, 1.5rem);     /* 20 → 24 */
  --text-h2:    clamp(1.625rem, 1.35rem + 1.4vw, 2.375rem); /* 26 → 38 */
  --text-h1:    clamp(2.125rem, 1.55rem + 2.6vw, 3.25rem);  /* 34 → 52 — 2.89x body at the desktop end */

  --text-display: clamp(2.75rem, 1.9rem + 4.2vw, 4.5rem);   /* 44 → 72 — §5 */
  --text-price:   clamp(2.25rem, 1.75rem + 2.5vw, 3.25rem); /* 36 → 52 — §6.4 */

  /* Leading. Alexandria's Arabic ink spans 1.527em, so content prose sits at
     1.75 (0.22em of air over the ink), headings at 1.5, and anything headed
     by payload text — a Place, a Session label — at 1.75 as well.
     `CONTENT-LEADING-CRAMPED` holds a 1.6 floor on content prose;
     `LEADING-TOO-TIGHT` holds 1.4 everywhere. */
  --leading-body:    1.75;
  --leading-heading: 1.5;
  --leading-lead:    1.7;
  --leading-data:    1.75;
  --leading-tight:   1.4;    /* single-line controls ONLY, with padding */

  --weight-body: 400; --weight-emphasis: 600; --weight-heading: 700;

  /* A PROSE cap. Never a container — see the header note, item 4. */
  --measure: 42rem;
  /* A heading and the lead under it, capped together as one centred object. */
  --measure-head:  38rem;
  /* The CEILING on any line of Arabic body text; `MEASURE-TOO-WIDE` enforces it. */
  --measure-prose: 46rem;

  /* ── §3 Spacing — linear 4px scale ───────────────────────────────────── */
  --space-1: 0.25rem; --space-2: 0.5rem;  --space-3: 0.75rem; --space-4: 1rem;
  --space-5: 1.5rem;  --space-6: 2rem;    --space-7: 2.5rem;  --space-8: 3rem;
  --space-9: 4rem;    --space-10: 5rem;   --space-11: 6rem;

  --section-padding-block: clamp(3.5rem, 8vw, 6.5rem);
  --container-max:    75rem;
  --container-gutter: clamp(1rem, 4vw, 2rem);

  /* ── §4 Radius and elevation ─────────────────────────────────────────── */
  --radius-sm: 0.25rem; --radius-md: 0.5rem; --radius-lg: 1rem;
  --radius-xl: 1.5rem;  --radius-pill: 999px;

  /* Horizontal offset pinned to zero: shadows have no logical form and do not
     flip in RTL. */
  --shadow-sm: 0 1px 2px rgb(14 31 31 / 0.06);
  --shadow-md: 0 2px 8px rgb(14 31 31 / 0.08);
  --shadow-lg: 0 8px 24px rgb(14 31 31 / 0.10);
  --shadow-xl: 0 18px 48px rgb(14 31 31 / 0.14);
  /* A card that has been lifted towards the cursor. */
  --shadow-hover: 0 14px 34px rgb(14 31 31 / 0.14);

  /* ── §5 Motion ───────────────────────────────────────────────────────── */
  /* THE CURVE IS WHAT MAKES IT FEEL PHYSICAL, NOT THE DURATION.
       · `--ease-out-expo` — an entrance. Almost all the distance in the first
         third, so a thing arrives rather than slides.
       · `--ease-spring` — anything with mass: the portrait landing, a button
         released. Overshoots to 1.06 and settles. `transform` only.
       · `--ease-soft` — ease-out-cubic. Colour, shadow. */
  --ease-out:      cubic-bezier(0.215, 0.61, 0.355, 1);
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-soft:     cubic-bezier(0.33, 1, 0.68, 1);

  --dur-micro: 120ms;   /* a press */
  --dur-ui:    220ms;   /* chip, card, hover */
  --dur-enter: 560ms;   /* a marketing entrance */
  --dur-hero:  720ms;   /* the hero's own, slower — it is the first thing seen */
  --dur-pick:  420ms;   /* the spring on a chip and on the Session card */
}

/* ==========================================================================
   Base
   ========================================================================== */

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

html {
  /* `both-edges`: `stable` alone reserves the gutter on ONE side, the left in
     RTL, and put every band 15px off the viewport's true centre. */
  scrollbar-gutter: stable both-edges;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--colour-surface);
  color: var(--colour-text);
  font-family: var(--font-family);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  font-synthesis: none;    /* §2.1 — the family has no italic; never shear it */
  letter-spacing: normal;  /* §2.4 — inert between Arabic letters anyway */
  text-align: start;       /* §2.4 — never `right`; it survives into LTR islands */
  -webkit-text-size-adjust: 100%;
}

/* §2.4 — never `justify` on Arabic. */
p, li { text-wrap: pretty; }

h1, h2, h3 {
  line-height: var(--leading-heading);
  font-weight: var(--weight-heading);
  margin: 0 0 var(--space-4);
  letter-spacing: -0.01em;
  text-wrap: balance;
}
h1 { font-size: var(--text-h1); }
h2 { font-size: var(--text-h2); color: var(--colour-text-brand); }  /* 6.91 */
h3 { font-size: var(--text-h3); }
p  { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--colour-text-brand); }        /* 6.91 on white and on sunk */
img { max-width: 100%; height: auto; display: block; }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: calc(var(--radius-md) + 2px);
}

/* ==========================================================================
   Motion

   Two mechanisms, and the difference between them is why this page does not
   flash blank on a Saudi mobile network:

   ── above the fold: TRANSFORM ONLY. An `opacity: 0 → 1` entrance is a blank
      frame for its whole duration, and this page is reached from a paid ad.
   ── below the fold: `view()` WITH `animation-fill-mode: none`. `both` parks
      everything below the fold at opacity 0 in a full-page screenshot and
      hides it from every rule in `tools/visual-check.mjs`
      (`CONTENT-HIDDEN-BY-MOTION` is the guard, watched going red).
   ========================================================================== */

/* ── below the fold: three reveals, not one repeated ──────────────────────
     · `reveal-in`   — prose and headings. A short rise.
     · `reveal-mark` — a numbered or ticked item. Further, slightly small.
     · `reveal-lift` — a card or a figure. Furthest, with a scale. */
@keyframes reveal-in {
  from { opacity: 0; transform: translateY(1.25rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes reveal-mark {
  from { opacity: 0; transform: translateY(1.75rem) scale(0.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes reveal-lift {
  from { opacity: 0; transform: translateY(2.25rem) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* ── the hero: transform only, and a different distance per element ─────── */
@keyframes hero-rise {
  from { transform: translateY(1.5rem); }
  to   { transform: none; }
}
@keyframes hero-rise-far {
  from { transform: translateY(2.5rem); }
  to   { transform: none; }
}
@keyframes hero-land {
  from { transform: translateY(1.75rem) scale(0.96); }
  to   { transform: none; }
}
@keyframes hero-portrait-in {
  from { transform: translateY(1.5rem) scale(0.9); }
  to   { transform: none; }
}
/* The name tag slides out from under the frame after the frame has landed. */
@keyframes tag-in {
  from { transform: translateY(-0.75rem) scale(0.9); }
  to   { transform: none; }
}
/* One ring, once, expanding out from behind the portrait as it lands. A
   pseudo-element with no text, so opacity is free here. */
@keyframes halo {
  0%   { transform: scale(0.62); opacity: 0; }
  30%  { opacity: 0.7; }
  100% { transform: scale(1.3); opacity: 0; }
}
/* The underline under the headline's last word, drawn in from the start
   edge after the headline has arrived. `background-size`, never a border. */
@keyframes mark-draw {
  from { background-size: 0% 0.16em; }
  to   { background-size: 100% 0.16em; }
}

/* The panel that swaps when a Place is chosen, and its contents behind it.
   Transform only — the scroll reveal stays the ONE mechanism on this page
   that touches opacity. */
@keyframes panel-in {
  from { transform: translateY(0.75rem) scale(0.988); }
  to   { transform: none; }
}
@keyframes panel-row-in {
  from { transform: translateY(0.5rem); }
  to   { transform: none; }
}
/* The form, expanding in place under the Session the visitor just chose. */
@keyframes form-in {
  from { transform: translateY(0.75rem) scale(0.985); }
  to   { transform: none; }
}
/* A chip being picked: squashed, then released back to its own size. Never
   past 1 — a transform inside a scroller widens the scroller. */
@keyframes chip-pick {
  0%   { transform: scale(0.92); }
  100% { transform: none; }
}
/* The tick on the thank-you, drawn stroke by stroke. */
@keyframes tick-draw {
  from { stroke-dashoffset: 48; }
  to   { stroke-dashoffset: 0; }
}
@keyframes tick-pop {
  from { transform: scale(0.6); }
  to   { transform: none; }
}
/* The phone's booking bar, rising from the bottom edge. */
@keyframes sticky-in {
  from { transform: translateY(110%); }
  to   { transform: none; }
}
/* The hero's ambience, two layers at different rates in opposite directions. */
@keyframes drift {
  0%,100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.75; }
  50%     { transform: translate3d(2%, -3%, 0) scale(1.08); opacity: 1; }
}
@keyframes drift-slow {
  0%,100% { transform: translate3d(0, 0, 0) scale(1.04); opacity: 0.5; }
  50%     { transform: translate3d(-2%, 3%, 0) scale(1); opacity: 0.85; }
}
/* Scroll-linked: the reading-progress bar, the stage line, the photograph. */
@keyframes progress-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes line-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes photo-settle {
  from { transform: scale(1.07); }
  to   { transform: scale(1); }
}

@media (prefers-reduced-motion: no-preference) {

  /* ── the reading-progress hairline ───────────────────────────────────── */
  .progress {
    animation: progress-grow linear both;
    animation-timeline: scroll(root);
  }

  /* ── §1 the hero, choreographed ──────────────────────────────────────
     Seven objects, seven arrivals, in the order they are meant to be read:
     the portrait first, then the eyebrow, the headline, the line under it,
     the button, the note, and last the figures that back it all up. */
  .hero-copy > .reveal { animation: hero-rise var(--dur-hero) var(--ease-out-expo) both; }
  .hero-copy > .reveal:nth-child(1) { animation-delay: 40ms; }
  .hero-copy > .reveal:nth-child(2) { animation-delay: 110ms; }
  .hero-copy > .reveal:nth-child(3) { animation-delay: 200ms; }
  /* The button lands with weight rather than sliding to a stop. */
  .hero-copy > .reveal:nth-child(4) {
    animation: hero-land var(--dur-enter) var(--ease-spring) 300ms both;
  }
  .hero-copy > .reveal:nth-child(5) { animation-delay: 380ms; }
  .hero-copy > .reveal:nth-child(6) {
    animation: hero-rise-far var(--dur-hero) var(--ease-out-expo) 440ms both;
  }
  /* The underline is drawn once the headline has stopped moving. `both` is
     safe here: the property is `background-size`, not opacity. */
  .hero h1 .mark { animation: mark-draw 640ms var(--ease-out-expo) 820ms both; }

  .hero-figure { animation: hero-portrait-in 820ms var(--ease-spring) both; }
  .hero-tag    { animation: tag-in 520ms var(--ease-spring) 620ms both; }
  .hero-figure::after {
    /* `backwards`, never `both`: `both` would park the ring on its last
       keyframe at 130% of the frame for the rest of the page's life. */
    animation: halo 1100ms var(--ease-out) 220ms backwards;
  }

  .band-hero::before { animation: drift 18s ease-in-out infinite; will-change: transform; }
  .band-hero::after  { animation: drift-slow 26s ease-in-out infinite; will-change: transform; }

  /* ── §6 the choice, answering ──────────────────────────────────────── */
  /* `data-animate` is set by `app.js` only when the VISITOR acted. */
  .chip[data-animate="true"] > * { animation: chip-pick var(--dur-pick) var(--ease-out-expo) both; }

  .panel[data-animate="true"] { animation: panel-in var(--dur-pick) var(--ease-out-expo) both; }
  .panel[data-animate="true"] > * { animation: panel-row-in 380ms var(--ease-out) both; }
  .panel[data-animate="true"] > :nth-child(1) { animation-delay:  60ms; }
  .panel[data-animate="true"] > :nth-child(2) { animation-delay: 110ms; }
  .panel[data-animate="true"] > :nth-child(3) { animation-delay: 160ms; }
  .panel[data-animate="true"] > :nth-child(n+4) { animation-delay: 210ms; }

  .form-card[data-animate="true"] { animation: form-in var(--dur-pick) var(--ease-out-expo) both; }

  .thanks-tick { animation: tick-pop 480ms var(--ease-spring) both; }
  .thanks-tick path { animation: tick-draw 520ms var(--ease-out) 180ms both; }

  .sticky-cta:not([hidden]) { animation: sticky-in 460ms var(--ease-out-expo) both; }

  @supports (animation-timeline: view()) {
    /* Everything below the fold. NOT applied to the hero, whose entrance is
       the time-based one above. */
    .section .reveal,
    .proof .reveal,
    .closing .reveal {
      animation-name: reveal-in;
      animation-timing-function: var(--ease-out-expo);
      /* Read this line before changing it. `both` parks every below-fold
         element at opacity 0 in a full-page screenshot. */
      animation-fill-mode: none;
      animation-timeline: view();
      /* The range IS the duration. `entry` alone is a few pixels of scroll for
         a small item; ending inside `contain` makes it ~230px — a reveal you
         can watch — and it always completes before the element leaves. */
      animation-range: entry 4% contain 22%;
    }

    /* The stagger is a RANGE and not a delay: a delay on a `view()` animation
       is ignored, because there is no clock. */
    .section .reveal:nth-child(2),    .proof .reveal:nth-child(2),   .closing .reveal:nth-child(2)   { animation-range: entry 10% contain 28%; }
    .section .reveal:nth-child(3),    .proof .reveal:nth-child(3),   .closing .reveal:nth-child(3)   { animation-range: entry 16% contain 34%; }
    .section .reveal:nth-child(4),    .proof .reveal:nth-child(4)    { animation-range: entry 22% contain 40%; }
    .section .reveal:nth-child(5),    .proof .reveal:nth-child(5)    { animation-range: entry 28% contain 46%; }
    .section .reveal:nth-child(n+6),  .proof .reveal:nth-child(n+6)  { animation-range: entry 32% contain 50%; }

    /* ── and what each kind of thing does when its turn comes ─────────── */
    .pains li.reveal        { animation-name: reveal-mark; }
    .stage.reveal,
    .delivery.reveal,
    .faq.reveal,
    .tutor-figure.reveal,
    .room-figure.reveal,
    .proof-figure.reveal,
    .strip-proof li.reveal  { animation-name: reveal-lift; }

    /* The line joining the three stages fills as the block scrolls into
       view. Transform only, on a pseudo-element that holds no text; its
       declared style is the finished state, so outside the range — which is
       only ever off screen or already read — it simply stands full. */
    .stages::after {
      animation: line-fill linear both;
      animation-timeline: view();
      animation-range: entry 0% contain 55%;
    }

    /* The room settles from a slight zoom to rest as it arrives. `clip-path`
       on the figure rather than `overflow: hidden` — item 2 in the header. */
    .room-figure img {
      animation: photo-settle linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 70%;
    }
  }
}

/* WCAG 2.2 SC 2.3.3. Someone who asked their OS for less motion gets none:
   the `no-preference` block above never matches, and this sweeps up
   transitions and anything added later. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }
  /* A scroll-linked animation has no duration to shorten: the timeline is
     the scroll. It is switched off, and the declared style is the resting
     one — a full line, a settled photograph, and no progress bar. */
  .stages::after, .room-figure img, .progress { animation: none !important; }
  .progress { display: none; }
}

/* ==========================================================================
   The reading-progress hairline
   ========================================================================== */

/* Fixed, 3px, gold-to-teal, and reserving no space. It holds no text, so it
   is outside every contrast rule; and it is a `background`, not a border, so
   the gold in it is decoration by construction. In RTL the bar grows from the
   right edge: `transform-origin` has no logical form, so it is said physically. */
.progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 3px;
  z-index: 50;
  pointer-events: none;
  background: linear-gradient(to left, var(--aleem-gold), var(--aleem-teal));
  transform: scaleX(0);
  transform-origin: right center;
}

/* ==========================================================================
   Bands and containers — `.wrap` is the CONTAINER and it is 1200px.
   ========================================================================== */

.band { padding-block: var(--section-padding-block); }
.band-plain { background: var(--colour-surface); }
.band-sunk  { background: var(--colour-surface-sunk); }
.band-ink   { background: var(--colour-surface-ink); color: var(--colour-text-on-dark); }

.band-ink h2, .band-ink h3 { color: var(--colour-text-on-dark); }
.band-ink a { color: var(--colour-accent-on-dark); }   /* 7.39 on ink */

.wrap {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-gutter);
}

/* The prose cap, applied to text and never to a container. */
.lead, .prose { max-width: var(--measure); }

.lead {
  font-size: var(--text-lead);
  line-height: var(--leading-lead);
  color: var(--colour-text-muted);            /* 5.94 on white, 5.51 on sunk */
}
.lead strong { color: var(--colour-text); font-weight: var(--weight-heading); }

/* ── the centred section ──────────────────────────────────────────────────
   Omar, 2026-09-05: «عايز الصفحة تبقي Centered». The whole page is composed
   on one vertical axis. Centred is not narrow: `.wrap` stays 1200px, and what
   is capped is the TEXT — a heading and its lead at `--measure-head`, prose
   at `--measure`. `COMPOSITION-OFF-AXIS` and `MEASURE-TOO-WIDE` hold both. */
.section-grid { display: grid; gap: var(--space-8); }

.section-head,
.section-head-lead {
  text-align: center;
  max-width: var(--measure-head);
  margin-inline: auto;
}
.section-head > :last-child { margin-bottom: 0; }
.section-head-lead { margin-bottom: var(--space-8); }
.section-head .lead,
.section-head-lead .lead { margin-inline: auto; }

/* A gold hairline over each section heading. Decorative, carries nothing,
   and is the one use `design-tokens.md` §1.4 names first. `margin-inline:
   auto` is not cosmetic: a fixed-width block ignores `text-align`. */
.section-head h2::before {
  content: "";
  display: block;
  width: 3rem; height: 3px;
  margin-block-end: var(--space-5);
  margin-inline: auto;
  border-radius: var(--radius-pill);
  background: var(--aleem-gold);
}

/* The same head on a dark band: white heading, soft lead. */
.section-head-dark h2 { color: var(--colour-text-on-dark); }
.section-head-dark .lead { color: var(--colour-text-on-brand-soft); }
.band-ink .section-head-dark .lead { color: var(--colour-text-on-ink-soft); }   /* 8.43 */

/* ── the balanced row ─────────────────────────────────────────────────────
   A wrapping flex row with `justify-content: center` and `flex-grow: 0`
   centres whatever is left over in an incomplete last row, at any count and
   any width. `ROW-GROUP-RAGGED` asserts exactly that. */
.row-group {
  --row-gap: var(--space-6);
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-6) var(--row-gap);
}
.row-group > * { flex: 0 1 100%; }
@media (min-width: 40rem) {
  .row-group > * { flex: 0 1 calc((100% - var(--row-gap)) / 2); }
}
@media (min-width: 62rem) {
  .row-group > * { flex: 0 1 calc((100% - 2 * var(--row-gap)) / 3); }
}

/* ── the eyebrow pill ─────────────────────────────────────────────────────
   Small, bold, in a translucent pill. On the teal the label is pure white
   (6.91 on the band; the 12% white wash behind it lightens the ground a
   little, and white still clears 4.5 by a wide margin). */
.eyebrow {
  display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--text-small);
  font-weight: var(--weight-emphasis);
  line-height: var(--leading-tight);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  margin: 0 0 var(--space-3);
}
/* Each half stays on one line; at 13px on a 360px phone the two fit side by
   side, and if a Place name ever makes them not, the pill wraps between them
   rather than inside a word. */
.eyebrow > span { white-space: nowrap; }
.eyebrow-dot {
  width: 0.375rem; height: 0.375rem; border-radius: 50%;
  background: currentColor; opacity: 0.55;
}
.eyebrow-hero {
  color: var(--colour-text-on-dark);
  background: rgb(255 255 255 / 0.12);
  border: 1px solid rgb(255 255 255 / 0.22);
}

/* ==========================================================================
   Masthead
   ========================================================================== */

.masthead { padding-block: var(--space-4); }
/* Three columns, the wordmark in the middle one, so it sits on the page's
   axis whether or not the link beside it exists at this width. */
.masthead-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-4);
}
.masthead-spacer { grid-column: 1; }
.logo { grid-column: 2; width: 148px; height: auto; }
/* The link at the inline-END, where Saudi sites keep their masthead action.
   A text link, deliberately quieter than the hero's button under it. */
.masthead-cta {
  grid-column: 3;
  justify-self: end;
  font-size: var(--text-small);
  font-weight: var(--weight-emphasis);
  line-height: var(--leading-tight);
  text-decoration: none;
  color: var(--colour-text-brand);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--colour-border);     /* 4.37 — a control boundary */
  border-radius: var(--radius-pill);
  transition: background-color var(--dur-ui) var(--ease-soft), color var(--dur-ui) var(--ease-soft),
    border-color var(--dur-ui) var(--ease-soft);
}
.masthead-cta:hover {
  background: var(--colour-action); color: var(--colour-action-text);
  border-color: var(--colour-action);
}

/* ==========================================================================
   §1 Hero — the band is the artwork
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  /* THE HERO'S HEIGHT IS A BUDGET. `HERO-CTA-BELOW-FOLD` measures the
     button's bottom edge at 360×780, 780×360, 768×1024 and 1440×900 after
     every change; the numbers below are what keeps it inside all four. */
  padding-block: var(--space-6) var(--space-9);
  color: var(--colour-text-on-dark);
}

/* `background-color` is the LIGHTER end of the gradient on purpose: the check
   composites text against the computed colour, and everything on this band
   is measured against #2F6261. */
.band-hero {
  background-color: var(--colour-surface-brand);
  background-image:
    url("assets/brand-field.svg"),
    linear-gradient(160deg, #2F6261 0%, #275453 42%, #1F4241 100%);
  background-repeat: no-repeat, no-repeat;
  background-position: left center, center;
  background-size: min(88%, 940px) 132%, cover;
}

/* The ambience: two drifting glows on pseudo-elements that hold no text.
   Inset by arithmetic so the drift can never overflow the band — overflow
   here scrolls the document sideways in RTL. */
.band-hero::before {
  content: "";
  position: absolute;
  inset: 6% 12%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(50% 60% at 26% 36%, rgb(94 158 156 / 0.55), transparent 72%);
}
.band-hero::after {
  content: "";
  position: absolute;
  inset: 14% 18%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(46% 56% at 72% 66%, rgb(120 186 184 / 0.32), transparent 70%);
}
.band-hero { position: relative; isolation: isolate; }

/* One centred column, the portrait at the top of it. The markup reads copy
   first, portrait second — the order a screen reader should hear. */
.hero-grid {
  display: grid;
  gap: var(--space-4);
  justify-items: center;
  text-align: center;
}
.hero-figure { order: -1; }
.hero-copy { max-width: 48rem; }

.hero h1 {
  margin-bottom: var(--space-4);
  color: var(--colour-text-on-dark);          /* 6.91 on #2F6261 */
  letter-spacing: -0.02em;
}
/* The drawn underline. A white stroke under the last word, as a background
   image so it is neither a border nor gold; `.mark` inherits the headline's
   colour and size and adds nothing but the stroke. */
.hero h1 .mark {
  background-image: linear-gradient(rgb(255 255 255 / 0.62), rgb(255 255 255 / 0.62));
  background-repeat: no-repeat;
  background-position: right 0.06em;
  background-size: 100% 0.16em;
  padding-bottom: 0.08em;
}
.hero .lead {
  color: var(--colour-text-on-brand-soft);    /* 5.39 on #2F6261 */
  margin-bottom: var(--space-5);
  margin-inline: auto;
  /* 45rem, not `--measure`: one line fewer at 22px, and 720px is under the
     736px ceiling `MEASURE-TOO-WIDE` holds. */
  max-width: 45rem;
}
.hero .lead strong { color: var(--colour-text-on-dark); }

/* The button and the quiet link beside it, on one line where there is room. */
.hero-action {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-3) var(--space-5);
  margin: 0 0 var(--space-4);
}
.link-quiet {
  color: var(--colour-text-on-dark);          /* 6.91 */
  font-weight: var(--weight-emphasis);
  font-size: var(--text-body);
  line-height: var(--leading-tight);
  text-decoration: none;
  padding: var(--space-2) var(--space-1);
  /* An underline that grows in from the start edge on hover — the same
     device as the headline's, at link weight. */
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: right bottom 0.15em;
  background-size: 0% 1px;
  transition: background-size var(--dur-ui) var(--ease-out-expo);
}
.link-quiet:hover { background-size: 100% 1px; }

/* What pressing the button costs — nothing yet. Soft, small, one line. */
.hero-note {
  color: var(--colour-text-on-brand-soft);    /* 5.39 */
  font-size: var(--text-small);
  max-width: var(--measure);
  margin: 0 auto var(--space-6);
}

/* ── the portrait, in its own shape, with a name tag on the frame ───────── */
.hero-figure {
  display: grid;
  place-items: center;
  position: relative;
  /* ONE SIZE, TWO USERS: the frame and the ring that expands from behind it. */
  --portrait: clamp(6.5rem, 18vw, 9rem);
  --portrait-ratio: 640 / 853;
}
.hero-frame {
  position: relative;
  /* Room for the tag that overhangs the bottom edge. */
  padding-bottom: 0.9rem;
}
/* The arrival ring. `inset: 0; margin: auto` centres without a translate,
   which has no logical form. */
.hero-figure::after {
  content: "";
  position: absolute;
  inset: 0 0 0.9rem;
  margin: auto;
  width: var(--portrait);
  aspect-ratio: var(--portrait-ratio);
  height: auto;
  border-radius: var(--radius-xl);
  border: 2px solid rgb(255 255 255 / 0.4);
  pointer-events: none;
  opacity: 0;
  z-index: 0;
}
.hero-portrait {
  position: relative;
  z-index: 1;
  width: var(--portrait);
  height: auto;               /* its own ratio, uncropped */
  border-radius: var(--radius-xl);
  background: var(--colour-surface);
  box-shadow:
    0 0 0 6px rgb(255 255 255 / 0.14),
    0 0 0 10px rgb(255 255 255 / 0.07),
    0 24px 48px rgb(14 31 31 / 0.35);
}
/* The name, on a chip with its own white ground, overhanging the frame's
   bottom edge. Text on a chip, not text over a photograph: the chip's fill is
   what the contrast is measured against, and teal on white is 6.91. */
.hero-tag {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  margin-inline: auto;
  width: max-content;
  max-width: 100%;
  z-index: 2;
  display: inline-block;
  font-size: var(--text-tiny);
  line-height: var(--leading-tight);
  color: var(--colour-text-brand);
  background: var(--colour-surface);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-md);
  white-space: nowrap;
}

/* ── the three figures, quiet instance ──────────────────────────────────── */
.strip {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: center;
  gap: var(--space-2) var(--space-5);
  font-size: var(--text-small);
}
.strip li { display: flex; align-items: baseline; gap: 0.35em; }
.strip li + li::before {
  content: "·"; color: var(--colour-rule); margin-inline-end: var(--space-3);
}
.strip strong {
  font-size: var(--text-h3); font-weight: var(--weight-heading);
  line-height: var(--leading-tight);
  /* What makes the count-up cost nothing: every digit the same width. */
  font-variant-numeric: tabular-nums;
}
.strip-hero { color: var(--colour-text-on-brand-soft); }   /* 5.39 */
.strip-hero strong { color: var(--colour-text-on-dark); }  /* 6.91 */
.strip-hero li + li::before { color: var(--colour-rule-dark); }

/* ==========================================================================
   Buttons
   ========================================================================== */

.cta {
  position: relative;
  display: inline-block; text-align: center; text-decoration: none;
  font: inherit; font-weight: var(--weight-heading);
  line-height: var(--leading-tight);
  background: var(--colour-action);           /* white label = 6.91 */
  color: var(--colour-action-text);
  border: 0; border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-7);
  cursor: pointer;
  /* `clip-path`, never `overflow: hidden`, on a box that holds text. It clips
     the sheen below to the button's own rounded shape. */
  clip-path: inset(0 round var(--radius-md));
  transition:
    background-color var(--dur-ui) var(--ease-soft),
    box-shadow var(--dur-ui) var(--ease-soft),
    transform var(--dur-pick) var(--ease-spring);
  min-height: 44px;   /* SC 2.5.8 target size */
  box-shadow: var(--shadow-sm);
}
/* A sheen that sweeps across on hover. A pseudo-element with no text, moved
   on transform only. */
.cta::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgb(255 255 255 / 0.22) 50%, transparent 65%);
  transform: translateX(120%);
  transition: transform 640ms var(--ease-out-expo);
}
.cta:hover::after { transform: translateX(-120%); }
/* Lifts towards the cursor, presses back under the finger, and releases on a
   spring — the difference between a button that responds and one that changes
   colour. */
.cta:hover { background: var(--colour-action-hover); box-shadow: var(--shadow-md); transform: translateY(-2px); }   /* 10.97 */
.cta:active {
  transform: translateY(0) scale(0.965);
  box-shadow: var(--shadow-sm);
  transition-duration: var(--dur-micro);
  transition-timing-function: var(--ease-out);
}
.cta-block { display: block; width: 100%; }
.cta-lg {
  font-size: var(--text-lead);
  padding: var(--space-4) var(--space-9);
  border-radius: var(--radius-md);
}

/* On the teal band a teal button is invisible. White fill, teal label: 6.91,
   and it makes the primary action the single lightest object in the hero. */
.cta-invert {
  background: var(--colour-surface);
  color: var(--colour-text-brand);
  box-shadow: 0 10px 30px rgb(14 31 31 / 0.28);
}
.cta-invert::after {
  background: linear-gradient(105deg, transparent 35%, rgb(47 98 97 / 0.12) 50%, transparent 65%);
}
.cta-invert:hover {
  background: var(--colour-surface);
  color: var(--colour-action-hover);          /* 10.97 on white */
  box-shadow: 0 18px 44px rgb(14 31 31 / 0.4);
}
.cta-invert:active { box-shadow: 0 6px 18px rgb(14 31 31 / 0.3); }

/* ==========================================================================
   Icons — Lucide 0.469.0, ISC. Inlined; ~2.4 KB of markup in `index.html`.

   Three rules, each checked by `ICON-NOT-DECORATIVE` / `GOLD-MISUSE`:
     1. DECORATIVE. `aria-hidden="true"`, no `<title>`, no `aria-label`.
     2. `currentColor`. The stroke inherits, so an icon cannot drift out of
        contrast with the text beside it.
     3. NOT DIRECTION-SENSITIVE. No arrows, no chevrons. The two glyphs that
        hold start-aligned text lines are mirrored explicitly.
   ========================================================================== */

.icon {
  flex: 0 0 auto;
  display: block;
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
[dir="rtl"] .icon-mirror { transform: scaleX(-1); }

/* The curriculum's mark: a glyph in a tinted disc, above the words, on the
   same axis. A wash, not a border. */
.icon-tile {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-inline: auto;
  margin-block-end: var(--space-3);
  border-radius: 50%;
  background: var(--colour-wash);
  color: var(--colour-text-brand);            /* 6.91 on white — inherited */
  transition: background-color var(--dur-ui) var(--ease-soft), transform var(--dur-ui) var(--ease-out);
}
.icon-tile .icon { width: 1.375rem; height: 1.375rem; }
.topics li:hover .icon-tile { background: rgb(47 98 97 / 0.14); transform: translateY(-2px); }

/* ==========================================================================
   Photographs — four, real, uncropped, unfiltered, and nothing laid over them
   ========================================================================== */

figure { margin: 0; }

.room-figure,
.proof-figure {
  width: 100%;
  margin-inline: auto;
}
.room-figure img,
.proof-figure img {
  width: 100%;
  height: auto;              /* the ratio comes from the width/height attrs */
  border-radius: var(--radius-xl);
}

/* §4, between the stages and the delivery difference. Capped under its own
   800px so it is never upscaled. The figure clips the settling zoom with
   `clip-path` — never `overflow`, even on a box with no text, so the rule in
   the header stays a rule and not a habit. */
.room-figure {
  max-width: 46rem;
  margin-block-start: var(--space-10);
  border-radius: var(--radius-xl);
  clip-path: inset(0 round var(--radius-xl));
  box-shadow: var(--shadow-lg);
}
.room-figure img { transform-origin: center; }

/* §5, above the two figures it is the evidence for. A drop shadow is
   invisible on #0E1F1F, so the separation is a hairline. */
.proof-figure {
  max-width: 60rem;
  margin-block-end: var(--space-9);
}
.proof-figure img {
  box-shadow:
    0 0 0 1px rgb(255 255 255 / 0.14),
    0 24px 60px rgb(0 0 0 / 0.45);
}

/* ==========================================================================
   Cards — one object, used by the pains, the stages and the FAQ
   ========================================================================== */

.card {
  background: var(--colour-surface);
  border-radius: var(--radius-xl);
  padding: var(--space-7) var(--space-6);
  box-shadow: var(--shadow-md);
  text-align: center;
  transition: transform var(--dur-ui) var(--ease-out), box-shadow var(--dur-ui) var(--ease-soft);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-hover); }

/* ==========================================================================
   §2 Pains — three titled cards, numbered
   ========================================================================== */

.pains { counter-reset: pain; }
.pains li {
  counter-increment: pain;
  position: relative;
  /* On the white band the card needs an edge of its own. A decorative
     hairline — #D6E0E0 is 1.35 and is nothing else. */
  border: 1px solid var(--colour-rule);
  padding-top: var(--space-8);
}
/* The numeral in a tinted disc — the same object as §4's icon tile, with a
   digit inside it. It is a CSS counter and NOT a text node. */
.pains li::before {
  content: counter(pain);
  display: grid;
  place-items: center;
  width: 3rem; height: 3rem;
  margin-inline: auto;
  margin-block-end: var(--space-4);
  border-radius: 50%;
  background: var(--colour-wash);
  font-size: var(--text-h3);
  font-weight: var(--weight-heading);
  line-height: 1;
  color: var(--colour-text-brand);      /* 6.91 on white */
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-ui) var(--ease-soft), color var(--dur-ui) var(--ease-soft);
}
.pains li:hover::before { background: var(--colour-action); color: var(--colour-action-text); }   /* 6.91 */
.pains li h3 {
  color: var(--colour-text-brand);
  font-size: var(--text-h3);
  margin-bottom: var(--space-3);
}
.pains li p {
  margin: 0;
  color: var(--colour-text-muted);      /* 5.94 on white */
  line-height: var(--leading-body);
}

/* ==========================================================================
   §4 Curriculum — three stages on a line, nine topics under them
   ========================================================================== */

.stages {
  counter-reset: stage;
  list-style: none; margin: 0; padding: 0;
  position: relative;
  display: grid;
  gap: var(--space-7);
}
.stage {
  counter-increment: stage;
  position: relative;
  background: var(--colour-surface);
  border-radius: var(--radius-xl);
  padding: var(--space-8) var(--space-5) var(--space-6);
  box-shadow: var(--shadow-md);
  text-align: center;
  transition: transform var(--dur-ui) var(--ease-out), box-shadow var(--dur-ui) var(--ease-soft);
}
.stage:hover { transform: translateY(-4px); box-shadow: var(--shadow-hover); }

/* The node: a teal disc carrying the stage number, sitting half over the
   card's top edge and — on the desktop — on the line that joins the three. */
.stage-node {
  position: absolute;
  inset-inline: 0;
  top: -1.5rem;
  margin-inline: auto;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: var(--colour-action);
  color: var(--colour-action-text);            /* 6.91 */
  display: grid; place-items: center;
  font-size: var(--text-h3);
  font-weight: var(--weight-heading);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 6px var(--colour-surface-sunk), var(--shadow-md);
}
.stage-node::before { content: counter(stage); }

.stage-kicker {
  margin: 0 0 var(--space-1);
  font-size: var(--text-tiny);
  font-weight: var(--weight-emphasis);
  color: var(--colour-text-muted);             /* 5.94 */
  line-height: var(--leading-tight);
}
.stage-title {
  color: var(--colour-text-brand);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--colour-rule);   /* decorative hairline only */
}
.topics {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-5);
}
.topics li {
  text-align: center;
  font-size: var(--text-body);
  line-height: var(--leading-body);
}

/* On a phone the stages stack, and a short vertical rule between two cards
   says they are one sequence. */
.stage + .stage::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: calc(-1 * var(--space-7));
  margin-inline: auto;
  width: 2px;
  height: var(--space-7);
  background: var(--colour-rule);
}

@media (min-width: 62rem) {
  .stages {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-6);
    /* Room above the cards for the nodes and the line through them. */
    padding-top: var(--space-4);
  }
  .stage + .stage::before { content: none; }

  /* The line through the three nodes: a hairline track, and over it the
     teal fill that grows with the scroll. Both run from the first node's
     centre to the last's — one sixth in from each side, which is where the
     centre of a third-width column is. Neither holds text. */
  .stages::before,
  .stages::after {
    content: "";
    position: absolute;
    top: calc(var(--space-4) - 1.5rem + 1.5rem - 2px);
    inset-inline: calc(100% / 6);
    height: 4px;
    border-radius: var(--radius-pill);
    pointer-events: none;
  }
  .stages::before { background: var(--colour-rule); }
  .stages::after {
    background: linear-gradient(to left, var(--aleem-teal), var(--colour-border));
    transform-origin: right center;
  }
  .stage-node { z-index: 1; }
}

/* ── the two modes, given the room the distinction is worth ─────────────── */
.delivery {
  margin-top: var(--space-10);
  background: var(--colour-surface);
  border-radius: var(--radius-xl);
  padding: var(--space-8) var(--space-6);
  max-width: 56rem;
  margin-inline: auto;
  text-align: center;
  box-shadow: var(--shadow-md);
}
.delivery-intro {
  font-size: var(--text-lead);
  line-height: var(--leading-lead);
  font-weight: var(--weight-emphasis);
  margin-bottom: var(--space-6);
  max-width: var(--measure);
  margin-inline: auto;
}
.delivery-modes {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-5);
}
@media (min-width: 40rem) {
  .delivery-modes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-5); }
}
/* Equal siblings. «نفس المحتوى في الطريقتين» is a statement and not a
   comparison (#3), so neither card may be styled as the better buy. */
.delivery-modes li {
  background: var(--colour-surface-sunk);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-5);
  text-align: center;
  transition: transform var(--dur-ui) var(--ease-out), background-color var(--dur-ui) var(--ease-soft);
}
.delivery-modes li:hover { transform: translateY(-3px); background: #EEF3F3; }
.delivery-modes .icon-mode {
  width: 1.75rem;
  height: 1.75rem;
  margin-inline: auto;
  margin-block-end: var(--space-3);
  color: var(--colour-text-brand);            /* 6.91 on white */
}
.delivery-modes strong {
  display: block;
  font-size: var(--text-h3);
  line-height: var(--leading-heading);
  color: var(--colour-text-brand);            /* 6.91 on white */
  margin-bottom: var(--space-2);
}

/* ==========================================================================
   §3 Instructor
   ========================================================================== */

.tutor-grid {
  display: grid; gap: var(--space-7);
  justify-items: center;
  text-align: center;
}
.tutor-body { max-width: var(--measure); }

.tutor-figure { display: grid; place-items: center; }
.tutor-photo {
  width: clamp(10rem, 26vw, 16rem);
  height: clamp(10rem, 26vw, 16rem);
  border-radius: var(--radius-xl);
  background: var(--colour-surface);
  object-fit: cover;
  object-position: 50% 12%;
  /* A white ring, then a teal one — the photograph framed rather than
     floating. Never gold. */
  box-shadow: 0 0 0 5px var(--colour-surface), 0 0 0 7px var(--colour-text-brand), var(--shadow-lg);
}

.tutor-name { font-size: var(--text-h3); line-height: var(--leading-heading); margin-bottom: var(--space-5); }
.tutor-claim { font-size: var(--text-lead); line-height: var(--leading-lead); max-width: var(--measure); margin-inline: auto; }
.tutor-claim strong { color: var(--colour-text-brand); }
/* The paragraph break between the career figure and Aleem's own record is a
   decision, not spacing (copy §3). The gap is widened, never closed. */
.tutor-claim + .tutor-claim {
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--colour-rule);   /* decorative hairline only */
}

/* ==========================================================================
   §5 Numbers, repeated — the LOUD instance
   ========================================================================== */

.proof { padding-block: var(--space-10); }
.proof .section-head { margin-bottom: var(--space-8); }

.strip-proof {
  display: grid;
  gap: var(--space-8);
  color: var(--colour-text-on-ink-soft);      /* 8.43 on #0E1F1F */
  font-size: var(--text-body);
}
@media (min-width: 48rem) {
  .strip-proof { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-6); }
}
.strip-proof li {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: var(--space-1);
  text-align: center;
}
.strip-proof li + li::before { content: none; }
@media (min-width: 48rem) {
  .strip-proof li + li { border-inline-start: 1px solid var(--colour-rule-dark); }
}
.strip-proof strong {
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  color: var(--colour-accent-on-dark);         /* 7.39 on #0E1F1F */
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

/* ==========================================================================
   §6 Selector B — the place rail
   ========================================================================== */

#booking { scroll-margin-block-start: var(--space-6); }

/* ── the three steps over the rail ────────────────────────────────────────
   Numbered cells, centred, wrapping. The number is a counter in a teal
   disc; the step is one short line. */
.steps {
  counter-reset: step;
  list-style: none; margin: var(--space-6) auto 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-3) var(--space-6);
}
.steps li {
  counter-increment: step;
  display: flex; align-items: center; gap: var(--space-3);
  font-size: var(--text-small);
  font-weight: var(--weight-emphasis);
  line-height: var(--leading-tight);
  color: var(--colour-text);
}
.steps li::before {
  content: counter(step);
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem;
  border-radius: 50%;
  background: var(--colour-action);
  color: var(--colour-action-text);           /* 6.91 */
  font-size: var(--text-tiny);
  font-weight: var(--weight-heading);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* `overflow-x: auto`, never `hidden`. The rail bleeds to the gutter so a chip
   is cut by the viewport edge rather than stopping flush inside a padded box. */
.rail {
  display: flex; gap: var(--space-2);
  overflow-x: auto; overscroll-behavior-inline: contain;
  scrollbar-width: none;
  margin-inline: calc(-1 * var(--container-gutter));
  padding-inline: var(--container-gutter);
  padding-block: var(--space-2) var(--space-5);
  scroll-padding-inline: var(--container-gutter);
  scroll-snap-type: inline proximity;
}
.rail::-webkit-scrollbar { display: none; }

/* Centred only when the chips fit — measured by `app.js`, never guessed. */
.rail:not([data-overflow="true"]) { justify-content: center; }
.rail-shell:not(:has(.rail[data-overflow="true"]))::after { display: none; }

/* THE PEEK, as arithmetic: when the chips overflow, every chip takes one
   pitch, chosen so the edge lands 60% of the way into the third chip. */
.rail[data-overflow="true"] .chip {
  flex: 0 0 calc((100% + var(--container-gutter) - 2 * var(--space-2)) / 2.6);
  min-width: max-content;
}

.rail-shell { position: relative; }
.rail-shell::after {
  content: ""; position: absolute; inset-block: 0; inset-inline-end: 0;
  width: var(--space-8); pointer-events: none;
  background: linear-gradient(to left, var(--colour-surface-sunk) 12%, transparent);
}
[dir="rtl"] .rail-shell::after {
  background: linear-gradient(to right, var(--colour-surface-sunk) 12%, transparent);
}

/* ── the chip, and the price on it (#10's recorded decision) ────────────── */
.chip {
  flex: 0 0 auto; font: inherit; cursor: pointer;
  display: grid; gap: 0.1rem; justify-items: center; align-content: center;
  background: var(--colour-surface); color: var(--colour-text);
  border: 1px solid var(--colour-border);     /* 4.37 — clears the 3:1 floor */
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  min-height: 44px;   /* SC 2.5.8 target size */
  text-align: center;
  scroll-snap-align: start;
  transition:
    background-color var(--dur-ui) var(--ease-soft),
    border-color var(--dur-ui) var(--ease-soft),
    color var(--dur-ui) var(--ease-soft),
    transform var(--dur-ui) var(--ease-out),
    box-shadow var(--dur-ui) var(--ease-soft);
}
.chip:hover {
  border-color: var(--colour-text-brand);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.chip:active {
  transform: translateY(0) scale(0.955);
  transition-duration: var(--dur-micro);
  transition-timing-function: var(--ease-out);
}

.chip-place {
  font-size: var(--text-body);
  font-weight: var(--weight-emphasis);
  line-height: 1.45;
  white-space: nowrap;
}
.chip-price {
  font-size: var(--text-small);
  font-weight: var(--weight-heading);
  line-height: 1.45;
  white-space: nowrap;
  color: var(--colour-text-brand);            /* 6.91 on white */
  font-variant-numeric: tabular-nums;
}
.chip-price .sar { font-size: var(--text-tiny); font-weight: var(--weight-emphasis); margin-inline-start: 0.25em; }

.chip[aria-selected="true"] {
  background: var(--aleem-teal); border-color: var(--aleem-teal);
  color: var(--colour-text-on-dark);          /* 6.91 */
  box-shadow: var(--shadow-md);
}
.chip[aria-selected="true"] .chip-place { font-weight: var(--weight-heading); }
.chip[aria-selected="true"] .chip-price { color: var(--colour-text-on-brand-soft); }  /* 5.39 */

/* ── the Session panel — the one element that converts ─────────────────── */
.panel {
  border: 0;
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  background: var(--colour-surface);
  box-shadow: var(--shadow-xl);
  position: relative;
  isolation: isolate;
  text-align: center;
}
@media (min-width: 40rem) { .panel { padding: var(--space-8); } }

/* The situational line. Not shortened, and never balanced by a recording
   line on the حضوري side — copy §6.2 and §10. */
.situation {
  font-size: var(--text-lead);
  line-height: var(--leading-lead);
  color: var(--colour-text);
  margin: 0 auto var(--space-6);
  padding-bottom: var(--space-6);
  max-width: var(--measure);
  border-bottom: 1px solid var(--colour-rule);   /* decorative hairline only */
}

/* The spec strip: each label directly over its value, the pairs in a
   wrapping centred row. `LABEL-VALUE-SPLIT` holds it. */
.rows {
  margin: 0 0 var(--space-7);
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-6);
}
.row {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: var(--space-1);
  flex: 0 1 auto;
  min-width: 7rem;
  max-width: 20rem;
  text-align: center;
}
.row dt { color: var(--colour-text-muted); font-size: var(--text-small); }
.row dd { margin: 0; font-weight: var(--weight-emphasis); }
.row-place dd {
  font-weight: var(--weight-heading);
  line-height: var(--leading-data);
  font-size: var(--text-h3);
  color: var(--colour-text-brand);
}

/* ── §6.4 price block ─────────────────────────────────────────────────── */
.price-block {
  display: flex; flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-2) var(--space-4);
  background: var(--colour-surface-sunk);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}
/* The line break between the figures and the chip: zero height, full basis. */
.price-block::before {
  content: "";
  flex: 0 0 100%;
  order: 1;
}
.price-now {
  font-size: var(--text-price);
  font-weight: var(--weight-heading);
  line-height: var(--leading-tight);
  letter-spacing: -0.03em;
  color: var(--colour-text);
  font-variant-numeric: tabular-nums;
}
.sar { font-size: var(--text-lead); font-weight: var(--weight-emphasis); margin-inline-start: 0.2em; }
/* The struck figure appears alone: no percentage, no «وفّر» (copy §6.4). */
.price-was {
  font-size: var(--text-lead); color: var(--colour-text-muted);
  text-decoration: line-through; font-weight: var(--weight-body);
  font-variant-numeric: tabular-nums;
}
/* THE ONE PLACE GOLD IS A FILL UNDER TEXT. #0E1F1F on it: 6.19. */
.vat {
  display: inline-block;
  order: 2;
  flex: 0 0 auto;
  width: fit-content;
  background: var(--colour-accent); color: var(--colour-accent-text);
  font-size: var(--text-tiny); font-weight: var(--weight-emphasis);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-3);
  line-height: 1.9;
}

.panel > .cta {
  margin-top: var(--space-6);
  margin-inline: auto;
  width: min(100%, 22rem);
}

/* ── §6.6 the form (F2 — expands in place, the choice still on screen) ── */
.form-card {
  margin-top: var(--space-7);
  background: var(--colour-surface-sunk);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  max-width: 30rem;
  margin-inline: auto;
  text-align: center;
}
.field { margin-bottom: var(--space-5); }
.field label {
  display: block; font-size: var(--text-small);
  font-weight: var(--weight-emphasis); margin-bottom: var(--space-2);
}
/* The label is centred and the field is not: `text-align` inherits into an
   input, and a name drifting from the middle outwards is a bug. */
.field input {
  width: 100%; font: inherit; font-size: 1rem;
  text-align: start;
  line-height: var(--leading-tight);
  padding: var(--space-3) var(--space-4); min-height: 48px;
  border: 1px solid var(--colour-border);     /* 4.06 on sunk */
  border-radius: var(--radius-md);
  background: var(--colour-surface); color: var(--colour-text);
  transition: border-color var(--dur-ui) ease, box-shadow var(--dur-ui) ease;
}
.field input:hover { border-color: var(--colour-text-brand); }
.field input::placeholder { color: var(--colour-text-muted); opacity: 1; }
.field input[aria-invalid="true"] { border-color: var(--colour-invalid); border-width: 2px; }

/* §5.4 — the `+966` stays OUTSIDE the input, and the group is `dir="ltr"`. */
.tel { display: flex; align-items: stretch; gap: var(--space-2); }
.tel-affix {
  flex: 0 0 auto; display: flex; align-items: center;
  padding-inline: var(--space-4);
  background: var(--colour-surface); color: var(--colour-text);
  border: 1px solid var(--colour-border); border-radius: var(--radius-md);
  font-variant-numeric: tabular-nums;
}
.tel input { flex: 1 1 auto; text-align: start; min-width: 0; }  /* `start` is left when dir resolves ltr */
/* The affix is a flag image and a <select> now. The wrapper carries the
   affix box (border, background) so the two read as one control; the select
   inside is bare and keeps the browser's own arrow — a control that can
   change must look like one. Tight on purpose: every pixel here is taken
   from the number field, which on a 390px phone has ~106px for eleven digits. */
.tel-country-wrap {
  padding-inline: var(--space-2) 0;
  gap: var(--space-1);
  cursor: pointer;
}
.tel-country-wrap:hover, .tel-country-wrap:focus-within { border-color: var(--colour-text-brand); }
.tel-flag {
  width: 20px; height: 15px; flex: 0 0 auto;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgb(14 31 31 / 0.12);   /* a white stripe still has an edge */
}
.tel-country {
  font: inherit; font-size: 1rem; line-height: var(--leading-tight);
  min-height: 46px; width: auto; flex: 0 0 auto;
  padding-inline: var(--space-1) var(--space-1);
  border: 0; background: transparent; color: inherit;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.tel-country:focus-visible { box-shadow: none; outline: none; }

.consent {
  font-size: var(--text-tiny); color: var(--colour-text-muted);
  margin: var(--space-5) 0 0;
}
.consent a { color: var(--colour-text-brand); }
/* The no-payment line under the form — the hero's sentence, with a small
   glyph before it. Body colour rather than muted: it is the answer to the
   question the visitor is asking at this exact moment. */
.trust {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  font-size: var(--text-small);
  color: var(--colour-text);
  margin: var(--space-5) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--colour-rule);   /* decorative hairline only */
}
.trust .icon { width: 1.125rem; height: 1.125rem; color: var(--colour-text-brand); }

/* ── §6.7 empty state · §9 thank-you ──────────────────────────────────── */
.capture, .thanks {
  border-radius: var(--radius-xl);
  padding: var(--space-8) var(--space-6);
  background: var(--colour-surface);
  box-shadow: var(--shadow-lg);
  text-align: center;
}
.capture h3, .thanks h3 { margin-bottom: var(--space-3); }
.capture-title { font-size: var(--text-h2); color: var(--colour-text-brand); margin-bottom: var(--space-4); }
.capture > p {
  max-width: var(--measure); margin-inline: auto;
  font-size: var(--text-lead); line-height: var(--leading-lead);
}
.capture .form-card { margin-top: var(--space-6); }
.thanks {
  margin-top: var(--space-6);
  background: var(--colour-surface-sunk);
  box-shadow: none;
  padding: var(--space-6);
  max-width: 34rem;
  margin-inline: auto;
  border-top: 3px solid var(--colour-text-brand);
}
.thanks p { max-width: var(--measure); margin-inline: auto; }
.thanks h3 { color: var(--colour-text-brand); }
/* `app.js` moves focus to this heading so a screen reader announces the
   confirmation. A heading is not a control, so it draws no ring. */
.thanks h3:focus, .thanks h3:focus-visible { box-shadow: none; outline: none; }
.thanks p:last-child { margin-bottom: 0; }
/* The tick: a teal disc with a stroke that draws itself. Decorative,
   `aria-hidden`, `currentColor`. */
.thanks-tick {
  display: grid; place-items: center;
  width: 3.5rem; height: 3.5rem;
  margin: 0 auto var(--space-4);
  border-radius: 50%;
  background: var(--colour-action);
  color: var(--colour-action-text);
}
.thanks-tick .icon { width: 1.75rem; height: 1.75rem; stroke-width: 2.5; }
.thanks-tick path { stroke-dasharray: 48; }

/* ==========================================================================
   §7 FAQ — a disclosure, open by default, one column
   ========================================================================== */

.faq-grid {
  display: grid; gap: var(--space-4); align-items: start;
  max-width: 48rem;
  margin-inline: auto;
}
.faq {
  background: var(--colour-surface);
  border: 1px solid var(--colour-rule);       /* decorative hairline only */
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-7);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-ui) ease, transform var(--dur-ui) var(--ease-out);
}
.faq:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.faq summary {
  display: flex; align-items: flex-start; justify-content: center;
  gap: var(--space-4);
  cursor: pointer;
  list-style: none;
  min-height: 44px;   /* SC 2.5.8 */
}
.faq summary .icon {
  width: 1.25rem;
  height: 1.25rem;
  align-self: center;
  color: var(--colour-text-brand);
  stroke-width: 2;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary h3 {
  margin: 0;
  flex: 0 1 auto;
  text-align: center;
  color: var(--colour-text-brand);
  font-size: var(--text-h3);
}
/* The marker: two bars that cross — a plus that becomes a minus. */
.faq summary::after {
  content: "";
  flex: 0 0 auto;
  align-self: center;
  width: 1.25rem; height: 1.25rem;
  background:
    linear-gradient(var(--colour-text-brand) 0 0) center / 100% 2px no-repeat,
    linear-gradient(var(--colour-text-brand) 0 0) center / 2px 100% no-repeat;
  transition: transform 320ms var(--ease-spring), opacity var(--dur-ui) var(--ease-soft);
}
.faq[open] summary::after {
  background: linear-gradient(var(--colour-text-brand) 0 0) center / 100% 2px no-repeat;
  transform: rotate(180deg);
  opacity: 0.75;
}
.faq-answer { padding-top: var(--space-4); text-align: center; }
.faq-answer p {
  margin: 0;
  color: var(--colour-text);
  line-height: var(--leading-body);
  max-width: var(--measure);
  margin-inline: auto;
}

/* ==========================================================================
   §7.5 The closing call
   ========================================================================== */

.closing { padding-block: var(--space-10); }
.closing-head { max-width: 42rem; }
.closing-action { margin: var(--space-6) 0 0; }

/* ==========================================================================
   §8 Footer
   ========================================================================== */

.site-footer { padding-block: var(--space-9); }
.footer-grid {
  display: grid; gap: var(--space-6);
  justify-items: center;
  text-align: center;
}
.band-ink p { margin-bottom: var(--space-3); }
.band-ink p:last-child { margin-bottom: 0; }
.footer-identity p { color: var(--colour-text-on-ink-soft); }   /* 8.43 */
.footer-name { font-size: var(--text-h3); line-height: var(--leading-heading); }
.footer-name strong { color: var(--colour-text-on-dark); }
.footer-contact { font-size: var(--text-small); }
.footer-links { margin-top: var(--space-4); }

/* ==========================================================================
   The phone's booking bar
   ========================================================================== */

/* `hidden` until `motion.js` sees the hero leave, hidden again while §6 is
   on screen. Never on a desktop: the hero's button and the masthead's link
   are one scroll away. */
.sticky-cta {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--container-gutter);
  padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background: var(--colour-surface);
  box-shadow: 0 -8px 24px rgb(14 31 31 / 0.14);
}
.sticky-cta[hidden] { display: none; }
.sticky-cta-name {
  font-size: var(--text-small);
  font-weight: var(--weight-emphasis);
  line-height: var(--leading-tight);
  color: var(--colour-text);
  min-width: 0;
  white-space: nowrap;
}
/* 13px and 24px of button padding, measured at 360px: 123 + 154px of content
   inside 360 − 3 × 16 of gutters and gap. At 15px and 32px it was 360 exactly
   and the button overlapped the name. */
.sticky-cta-name { font-size: var(--text-tiny); }
.sticky-cta .cta { flex: 0 0 auto; padding-inline: var(--space-5); }
@media (min-width: 48rem) { .sticky-cta { display: none; } }

/* ==========================================================================
   A phone held sideways — 780×360. The hero becomes two columns because a
   stacked one does not fit; `COMPOSITION-OFF-AXIS` exempts the hero, and
   only the hero, below 512px of viewport height.
   ========================================================================== */

@media (orientation: landscape) and (max-height: 32rem) {
  :root { --section-padding-block: var(--space-7); }

  .masthead { padding-block: var(--space-3); }
  .logo { width: 112px; }

  .masthead { padding-block: var(--space-2); }
  .logo { width: 96px; }
  .hero { padding-block: var(--space-3) var(--space-6); }
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-6);
    align-items: center;
    justify-items: center;
  }
  .hero-figure { order: 0; }
  /* 360px of height. The eyebrow is the least load-bearing line in the hero
     and it is the one that goes; the headline steps down to 24.8px against an
     18px body — 1.38x, over `FLAT-HIERARCHY`'s 1.35x floor here. */
  .eyebrow-hero { display: none; }
  .hero h1 { font-size: 1.55rem; margin-bottom: var(--space-2); }
  .hero .lead { font-size: var(--text-small); margin-bottom: var(--space-3); }
  .hero-action { margin-bottom: var(--space-2); }
  .hero-action .cta-lg { font-size: var(--text-body); padding: var(--space-3) var(--space-7); }
  .hero-note { margin-bottom: var(--space-3); }
  .hero-figure { --portrait: 6.5rem; }
  /* No ring here: the grid column is exactly as wide as the portrait, so a
     ring at 130% of it is horizontal scroll for 1.1s. */
  .hero-figure::after { display: none; }

  .proof { padding-block: var(--space-8); }
  .closing { padding-block: var(--space-8); }
}

/* ==========================================================================
   The phone — 360×780, the viewport most of the paid traffic arrives on
   ========================================================================== */

@media (max-width: 47.9375rem) {
  .rail:not([data-overflow="true"]) { padding-inline: var(--container-gutter); }

  /* The masthead's link is the sticky bar's job here. The spacer and the
     link both go, and the wordmark keeps the middle column. */
  .masthead-cta { display: none; }
  .masthead-row { grid-template-columns: 1fr auto 1fr; }

  /* THE FIRST SCREEN. The band rhythm compresses rather than the type: the
     masthead and the hero's own padding give back their pixels, the portrait
     sits at 6.5rem, and the headline, the lead and the button are inside
     780px. `HERO-CTA-BELOW-FOLD` measures it after every change. */
  .masthead { padding-block: var(--space-2); }
  .hero { padding-block: var(--space-4) var(--space-7); }
  .hero-grid { gap: var(--space-2); }
  .hero-figure { --portrait: 6.5rem; }
  .hero-frame { padding-bottom: 0.75rem; }
  .hero-figure::after { inset-block-end: 0.75rem; }
  /* 157 + 6 + 108px of content at 13px, measured: it fits on one line with
     12px of side padding and 8px gaps, and not with 16 and 12. */
  .eyebrow-hero { margin-bottom: var(--space-2); font-size: var(--text-tiny); padding: 0.375rem var(--space-3); gap: var(--space-2); }
  .hero h1 { margin-bottom: var(--space-3); }
  .hero .lead { margin-bottom: var(--space-3); }
  .hero-action { gap: var(--space-2) var(--space-4); }
  .hero-note { margin-bottom: var(--space-5); }

  .stage { padding-inline: var(--space-4); }
  .steps { gap: var(--space-2) var(--space-5); }
}
