/* =====================================================================
   foundation/css/base.css
   Shell + hero for the umanodesign.studio replica (phase 1).
   Layout and motion are RE-IMPLEMENTED from measurements
   (_capture/styles-*.json, 00-global/umano-motion-spec.md). Their fonts,
   images and video are scaffold only: replace before launch.

   Breakpoint: the original switches layout at width <= 768px
   (React `innerWidth <= 768`). Same here: @media (max-width: 768px).
   ===================================================================== */

/* ---------- Fonts (scaffold: AM Le Cygne is theirs, replace) ---------- */
@font-face { font-family: "AM Le Cygne"; src: url("../assets/AMLeCygne-Noir.otf") format("opentype"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "AM Le Cygne"; src: url("../assets/AMLeCygne-Clair.otf") format("opentype"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: Inter; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../assets/inter-latin.woff2") format("woff2");
  unicode-range: U+0-FF, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC, U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: Inter; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../assets/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF, U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

/* ---------- Brand Arabic face: thmanyah sans (LOCAL PREVIEW ONLY, see assets/brand/fonts/LICENCE-NOTE.md) ----------
   unicode-range = Arabic script blocks only, so Latin (wordmark, digits, punctuation, spaces) keeps AM Le Cygne / Inter
   and only Arabic glyphs come from thmanyah. Lalezar / IBM Plex Sans Arabic stay in the stacks as fallbacks.
   Weight mapping (FONT-SWAP-NOTES.md section 12): "thmanyah display" = thmanyah SERIF DISPLAY (the calligraphic face of the foundry's
   style guide): 100-600 Medium, 700-800 Bold (every headline: the guide sets its headlines in Bold), 900-1000 Black (footer giant word);
   "thmanyah sans" 100-400 Regular (body), 500-600 Medium (UI, buttons; no SemiBold exists), 700-800 Bold, 900-1000 Black. */
@font-face { font-family: "thmanyah display"; src: url("../assets/brand/fonts/thmanyahserifdisplay-Medium.woff2") format("woff2"); font-weight: 100 600; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah display"; src: url("../assets/brand/fonts/thmanyahserifdisplay-Bold.woff2") format("woff2"); font-weight: 700 800; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah display"; src: url("../assets/brand/fonts/thmanyahserifdisplay-Black.woff2") format("woff2"); font-weight: 900 1000; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah sans"; src: url("../assets/brand/fonts/thmanyahsans-Regular.woff2") format("woff2"); font-weight: 100 400; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah sans"; src: url("../assets/brand/fonts/thmanyahsans-Medium.woff2") format("woff2"); font-weight: 500 600; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah sans"; src: url("../assets/brand/fonts/thmanyahsans-Bold.woff2") format("woff2"); font-weight: 700 800; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }
@font-face { font-family: "thmanyah sans"; src: url("../assets/brand/fonts/thmanyahsans-Black.woff2") format("woff2"); font-weight: 900 1000; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; }

/* ---------- Tokens (every value measured on the live site) ---------- */
:root {
  /* colour */
  --orange: #f26b6c;        /* hero bg, active link, CTA after hero, cursor */
  --orange-deep: #e66b6d;   /* --color-brand in their CSS; rarely used */
  --ink: #140906;           /* hero h1 + sub */
  --night: #0a0d12;         /* dark sections, cursor over hero, dark text */
  --navy: #181d27;          /* nav links, progress dots */
  --grey-600: #535862;      /* small notification label */
  --line: #e9eaeb;
  --intro-grey: #e7e8e6;    /* intro start background, theme-color */
  --pill: #f0f0f0;          /* nav pill */
  --page: #f2f3f5;          /* page root + footer */
  --paper: #ffffff;
  --cream: #ede7db;         /* how-it-works last card (mixes to --night) */
  --night-2: #1c2230;       /* client story card surface */
  --white-05: rgba(255, 255, 255, .05); /* open FAQ row */

  /* type families (keep the stack: 'TWK Lausanne' is referenced but never loaded on the original, so it renders Inter) */
  --f-display: "thmanyah display", "AM Le Cygne", "Lalezar", "Playfair Display", Georgia, serif;
  --f-sub: "thmanyah sans", "TWK Lausanne", "Inter", "IBM Plex Sans Arabic", sans-serif;
  --f-ui: "thmanyah sans", "Inter", "IBM Plex Sans Arabic", sans-serif;
  --ff-off: "calt" 0, "liga" 0, "dlig" 0, "clig" 0;

  /* type scale, desktop (mobile overrides below) */
  --t-hero: 72px;   --lh-hero: 78px;   --ls-hero: -1.44px;
  --t-sub: 24px;    --lh-sub: 32px;    --ls-sub: -0.24px;
  --t-statement: 36px; --lh-statement: 44px; --ls-statement: -0.72px;
  --t-h2-stories: 115.2px; --lh-h2-stories: 109.44px;
  --t-h2-pricing: 64px; --lh-h2-pricing: 64px;
  --t-h2-faq: 36px; --lh-h2-faq: 44px;
  --t-nav: 16px;
  --t-body: 16px; --lh-body: 24px;

  /* radius */
  --r-pill: 55px; --r-cta: 43px; --r-hero: 42px; --r-card: 17px; --r-media: 10px; --r-story: 16px;

  /* spacing */
  --nav-top: 16px; --nav-h: 81px; --hero-pt: 120px; --hero-pb: 42px; --gutter: 32px;

  /* motion (see _capture/keyframes-and-easings.md) */
  --e-mask: cubic-bezier(.76, 0, .24, 1);       /* .85s word rise */
  --e-media: cubic-bezier(.165, .84, .44, 1);   /* card media 1.8s, card rise 1.2s */
  --e-zoom: cubic-bezier(.25, .46, .45, .94);   /* intro phone zoom 1.3s, cookie .5s */
  --e-ui: cubic-bezier(.4, 0, .2, 1);           /* nav grid .45s, dots, story zoom */
  --e-nav: cubic-bezier(.4, 0, .6, 1);          /* nav in/out .5s */
  --e-out: cubic-bezier(.16, 1, .3, 1);         /* rotating-word width .35s, modals */
  --e-spring: cubic-bezier(.34, 1.56, .64, 1);  /* notif card height .6s, hovers, chips */
  --e-spring-soft: cubic-bezier(.34, 1.4, .64, 1); /* FAQ answer */
  --e-settle: cubic-bezier(0, 0, .2, 1);        /* phone settle on tall screens .8s */

  /* layers */
  --z-content: 1; --z-nav: 100; --z-nav-intro: 10000; --z-intro: 9999; --z-cookie: 9999;
  --z-noise: 99996; --z-cursor-canvas: 99997; --z-cursor-dot: 99998; --z-menu: 10001;
}
@media (max-width: 768px) {
  :root {
    --t-hero: clamp(42px, 11vw, 52px); --lh-hero: 1.2; --ls-hero: -0.72px; /* phone type pass 2026-10-17: was 36/44 (half of desktop 72) */
    --t-sub: 19px; --lh-sub: 30px;                                          /* was 18/28 */
    --t-statement: 24px; --lh-statement: 34px;
    --t-h2-stories: 42px; --lh-h2-stories: 39.9px;
    --t-h2-pricing: 36px; --lh-h2-pricing: 36px;
    --t-h2-faq: 28px;
    --hero-pb: 0px;
  }
}

/* ---------- Reset (theirs: * { box-sizing; margin:0; padding:0 }) ---------- */
*, ::before, ::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
/* RTL mirror (COPY-SWAP-NOTES.md, "RTL mirror"): <html dir="rtl"> flips every flex/grid row, block start and text start. Layout rules that
   are direction-dependent are logical (inline-start/end). --dir is the sign for what logical properties cannot express:
   horizontal translations, rotations, keyframes (an LTR value times --dir). JS reads the same sign as App.dir. */
:root { --dir: 1; }
:root[dir="rtl"] { --dir: -1; }
/* directional icons only (arrows, the megaphone): mirrored in RTL. Never on logos, marks or the brand mark. */
:root[dir="rtl"] .rtl-flip { transform: scaleX(-1); }
body { color: var(--navy); background-color: #fafafa; -webkit-font-smoothing: antialiased; font-family: var(--f-ui); font-size: 14px; }
img, video, canvas, svg { display: inline-block; }
a { color: inherit; }
button { font: inherit; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* scroll lock while the intro runs (original injects the same rule) */
html.is-intro, html.is-intro body { overflow: hidden !important; }

/* ---------- Page root (their landing wrapper) ---------- */
.page { font-family: var(--f-ui); overflow-x: clip; background: var(--page); min-height: 100vh; }
/* content sits ABOVE the fixed footer; margin-bottom = footer height (set by JS) */
.content { position: relative; z-index: var(--z-content); margin-bottom: var(--footer-h, 569px); }
@media (max-width: 768px) { .content { margin-bottom: var(--footer-h, 552px); } }
.hero-wrap { background: var(--paper); }

/* ---------- Section slots (filled by phase-2 agents) ---------- */
/* Reserved heights = measured heights, so the page length matches the original
   (desktop 12826px, mobile 11767px). They switch off once the slot has element children. */
.slot { position: relative; display: flow-root; }
.slot:not(:has(> :not(.slot__label))) { height: var(--slot-h); background: var(--slot-bg, var(--paper)); }
@media (max-width: 768px) { .slot:not(:has(> :not(.slot__label))) { height: var(--slot-h-m, var(--slot-h)); } }
.slot__label { position: sticky; top: 50vh; display: block; width: max-content; margin: 0 auto; transform: translateY(-50%);
  font: 500 12px/1.4 var(--f-ui); letter-spacing: .02em; color: rgba(127, 127, 127, .8); padding: 6px 12px; border: 1px dashed rgba(127, 127, 127, .45); border-radius: 8px; pointer-events: none; }

/* ---------- Footer curtain ---------- */
.curtain { position: fixed; bottom: 0; left: 0; right: 0; z-index: 0; }
.curtain > .slot:not(:has(> :not(.slot__label))) { background: var(--page); }
.curtain .slot__label { position: static; transform: none; top: auto; margin: 40px auto 0; }

/* ---------- Grain (noise.png at 2%, static) ---------- */
.grain { position: fixed; inset: 0; background-image: url("../assets/noise.png"); opacity: .02; pointer-events: none; z-index: var(--z-noise); }

/* ---------- Preloader ---------- */
.pre { position: fixed; inset: 0; z-index: 99999; background: var(--cream); display: none; align-items: center; justify-content: center; }
html.is-intro.is-pre .pre { display: flex; }
.pre__fill { clip-path: inset(100% 0 0 0); transition: clip-path .3s ease-out; }

/* ---------- Nav pill ---------- */
.nav { position: fixed; top: var(--nav-top); left: 0; right: 0; z-index: var(--z-nav); display: flex; justify-content: center; pointer-events: none;
  opacity: 0; transform: translateY(-200%); transition: opacity .5s ease, transform .5s var(--e-nav); }
html.is-intro .nav { z-index: var(--z-nav-intro); }
html.nav-in .nav { opacity: 1; transform: translateY(0); }
.nav__header { pointer-events: auto; }
.nav__pill { display: flex; align-items: center; background: var(--pill); border-radius: var(--r-pill); padding: 0 21px; gap: 24px; height: var(--nav-h);
  box-shadow: none; white-space: nowrap; will-change: transform; }
.nav__logo { display: flex; align-items: center; padding: 4px 8px; flex-shrink: 0; cursor: pointer; }
.nav__logo img { height: 32px; width: auto; display: block; }
.nav__links { display: grid; grid-template-columns: 1fr; transition: grid-template-columns .45s var(--e-ui); overflow: hidden; }
.nav__links-in { display: flex; align-items: center; min-width: 0; opacity: 1; transition: opacity .3s ease; }
.nav.is-collapsed:not(:hover) .nav__links { grid-template-columns: 0fr; }
.nav.is-collapsed:not(:hover) .nav__links-in { opacity: 0; transition: none; }
.nav__menu { display: flex; align-items: center; gap: 2px; }
.nav__menu a { font: 600 var(--t-nav) var(--f-ui); color: var(--navy); text-decoration: none; padding: 6px 10px; border-radius: 8px; flex-shrink: 0; transition: color .2s ease; }
.nav__menu a.is-active { font-weight: 800; color: var(--orange); }
.nav__menu [data-zone-set] { display: none; }
.nav[data-zone="hero"] .nav__menu [data-zone-set="hero"], .nav[data-zone="links"] .nav__menu [data-zone-set="links"] { display: contents; }
.nav__dots { display: none; align-items: center; gap: 7px; padding: 0 10px; height: 32px; }
.nav[data-zone="dots"] .nav__dots { display: flex; }
.nav[data-zone="dots"] .nav__menu { display: none; }
.nav__dots i { display: block; height: 8px; width: 8px; flex-shrink: 0; border-radius: 4px; background: rgba(24, 29, 39, .25); transition: width .45s var(--e-ui), background .3s ease; }
.nav__dots i.is-on { width: 28px; background: var(--navy); }
.nav__cta { font: 600 16px var(--f-ui); background: #000; color: #fff; border: none; border-radius: var(--r-cta); padding: 10px 20px; cursor: pointer; flex-shrink: 0; margin-inline-start: 4px; text-decoration: none; }
.nav[data-cta="orange"] .nav__cta { background: var(--orange); }
.nav__burger { display: none; }

@media (max-width: 768px) {
  .nav__pill { justify-content: space-between; padding: 0; padding-inline: 14px 12px; gap: 6px; width: min(375px, calc(100vw - 32px)); }
  .nav__logo { padding: 0; }
  .nav__logo img { height: 34px; }
  .nav__links { display: none; }
  .nav__cta { font-size: 15px; padding: 10px 14px; margin-inline-start: 0; white-space: nowrap; } /* was 13px / 10px 12px */
  .nav[data-zone="dots"] .nav__logo { display: none; }
  .nav[data-zone="dots"] .nav__links { display: grid; }
  .nav[data-zone="dots"] .nav__dots { gap: 6px; padding: 0 4px; }
  .nav__dots i { height: 7px; width: 7px; }
  .nav__dots i.is-on { width: 24px; }
  .nav__burger { display: flex; flex-direction: column; justify-content: center; gap: 5px; flex-shrink: 0; background: #000; color: #fff; border: none; border-radius: var(--r-cta); padding: 10px 14px; cursor: pointer; }
  .nav__burger span { display: block; width: 18px; height: 2px; background: #fff; border-radius: 1px; }
  /* mobile CRO r1 M3: 48px tap targets, 8px apart (the pill is taller than 48 so nothing grows) */
  .nav__cta, .nav__burger { min-height: 48px; }
  .nav__burger { min-width: 48px; }
  .nav__pill { gap: 8px; }
}

/* mobile full-screen menu */
/* top = nav top: the original renders the sheet inside the fixed + transformed nav (its containing block), so it sits 16px down
   (a 16px strip of the page shows above it, see _ref/m-menu-open.png) and runs 16px past the bottom. We keep our own z-order
   (above the cookie card); the original sheet is capped at the nav's z 100, under the cookie card. */
.mmenu { position: fixed; top: var(--nav-top); left: 0; right: 0; z-index: var(--z-menu); background: #000; display: flex; flex-direction: column; padding: 0 24px; height: 100dvh;
  opacity: 0; pointer-events: none; visibility: hidden; transition: opacity .3s ease, visibility 0s linear .3s; }
.mmenu.is-open { opacity: 1; pointer-events: auto; visibility: visible; transition: opacity .3s ease, visibility 0s; }
.mmenu__top { display: flex; justify-content: flex-end; padding: 24px 0; }
.mmenu__close { background: none; border: none; cursor: pointer; padding: 8px; min-width: 48px; min-height: 48px; } /* mobile CRO r1 M7 */
.mmenu__nav { display: flex; flex-direction: column; gap: 12px; flex: 1; justify-content: center; }
.mmenu__nav a { font: 700 48px/1.2 var(--f-display); color: var(--orange); text-decoration: none; }
.mmenu__foot { padding-bottom: calc(32px + env(safe-area-inset-bottom, 0px)); } /* mobile CRO r1 M7 */
.mmenu__cta { display: block; width: 100%; background: var(--orange); border-radius: 14px; padding: 18px 24px; font: 600 18px var(--f-ui); color: #fff; text-align: center; text-decoration: none; }
@media (min-width: 769px) { .mmenu { display: none; } }

/* ---------- 01 Hero ---------- */
.hero { position: relative; background: var(--orange); overflow: hidden; display: flex; flex-direction: column; align-items: center;
  padding-top: var(--hero-pt); padding-bottom: var(--hero-pb); }
.hero__copy { text-align: center; padding: 40px 32px 0; max-width: 700px; }
.hero__title { font-family: var(--f-display); font-weight: 700; font-size: var(--t-hero); line-height: var(--lh-hero); letter-spacing: var(--ls-hero);
  color: var(--ink); margin: 0; -webkit-font-smoothing: antialiased; font-feature-settings: var(--ff-off); }
.hero__line { display: block; }
/* word mask: padding/negative margin keeps descenders unclipped */
.hero__mask { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .2em; margin-bottom: -.2em; }
.hero__word { display: inline-block; transform: translateY(0); transition: transform .85s var(--e-mask); }
.hero__sub { font-family: var(--f-sub); font-weight: 600; font-size: var(--t-sub); line-height: var(--lh-sub); letter-spacing: var(--ls-sub);
  color: var(--ink); margin: 16px 0 0; text-wrap: balance; transition: opacity .6s ease, transform .6s ease; } /* was nowrap (for the rotating word); the 2026-10-14 static sub line is ~1030px at 1440, so it wraps in the 636px box (2 balanced lines) */
.hero__rot { display: inline-block; vertical-align: bottom; overflow: hidden; transition: width .35s var(--e-out); }
.hero__rot strong { font-family: var(--f-sub); font-weight: 700; display: inline-block; white-space: nowrap; transition: opacity .25s ease, transform .3s ease; }
.hero__rot strong.is-out { opacity: 0; transform: translateY(6px); }
.hero__shift { display: block; flex-shrink: 0; }
.hero__phone { position: relative; width: 891px; height: 634px; margin-top: 40px; flex-shrink: 0; transform-origin: 50% 40%; will-change: transform; }
/* hand + phone overlays: physical left on purpose. They sit on the screen of a photo asset that is not mirrored (RTL mirror notes). */
.hero__hand { position: absolute; top: -31px; left: -85px; width: 1061px; height: 707px; pointer-events: none; max-width: none; }
.hero__status { position: absolute; left: 321px; top: 54px; width: 249px; height: 38px; display: flex; align-items: center; justify-content: space-between; padding: 0 15px; }
.hero__time { font: 600 10.5px var(--f-ui); color: #000; }
.hero__icons { display: flex; gap: 4px; align-items: center; }
.hero__note { position: absolute; left: 340px; top: 115px; width: 211px; height: 442px; background: #fff; border-radius: var(--r-card); padding: 6px;
  display: flex; flex-direction: column; gap: 9px; overflow: hidden; }
.hero__note-head { display: flex; gap: 9px; align-items: center; flex-shrink: 0; }
.hero__app { background: var(--orange); border-radius: 10px; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.hero__app img { width: 19px; height: 24px; object-fit: contain; }
.hero__note-text { display: flex; flex-direction: column; gap: 1px; }
.hero__note-kicker { font: 400 7px/18px var(--f-ui); color: var(--grey-600); }
.hero__note-title { font: 500 10.5px/16px var(--f-ui); color: var(--night); margin-top: -2px; }
.hero__video { flex: 1; width: 100%; min-height: 0; border-radius: var(--r-media); object-fit: cover; display: block; }

@media (max-width: 768px) {
  .hero__copy { padding: 24px 20px 0; max-width: 440px; }
  .hero__sub { white-space: normal; }
  .hero__shift { display: contents; }
  .hero__phone { margin-top: auto; transform-origin: 50% 100%; }
}

/* ---------- 00 Image hero: video in the letters, typography art in two layers (HERO-IMAGE-NOTES.md, "Video-in-text scroll hero" > "Typography art") ----------
   .himg is 500svh tall and holds a sticky stage (100svh): pinned for 400svh, then it leaves as the coral section rises.
   In the stage (.himg__frame): the media (poster <picture> + the scrub <video>, full bleed, object-fit cover) and over it one SVG with two
   planes: the line-1 paper (.himg__cream--1, cream masked by «يا زين النمو!») and the line-2 paper (.himg__cream--2, cream masked by
   «بس من يلحق الشغل؟»). app.js drives both from the scroll (phase A zooms line 1 in, phase B zooms line 2 back out) and the load intro;
   the video never scales. Tunables: section height here (500svh = pin + one screen); the phase breakpoints, zoom, scrub and motion
   values in app.js (PH, ZOOM_EASE, LOCKUP, OPTICAL, ENTER, BREATH). */
.himg-wrap { background: var(--orange); } /* the squeeze margins/corners reveal the next section's colour (the coral hero reveals white for the same reason) */
.himg { position: relative; height: 500vh; height: 500svh;
  --fx: 50%; --fy: 40%; }                     /* full-reveal framing: on viewports wider than 16:9 the crop keeps the rider and the hooves */
.himg__stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }
.himg__frame { position: absolute; inset: 0; transform-origin: 50% 40%; }
.himg__media { position: absolute; inset: 0; overflow: hidden; background: #24170e; } /* ember dark under everything: the letters are never empty before the poster paints */
/* 24px LQIP (blurred) under the poster: shows only while the poster decodes */
.himg__media::before { content: ""; position: absolute; inset: -4%; background: url("../assets/brand/hero/hero03-scrub-lqip-desktop-24.webp") var(--fx) var(--fy) / cover no-repeat; filter: blur(18px); }
.himg__media picture { position: absolute; inset: 0; display: block; }
.himg__img, .himg__vid { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--fx) var(--fy); }
/* the scrub video: frame 0 = the poster, so .is-live (first frame decoded) is a no-op visually; the short fade hides any decoder colour step */
.himg__vid { opacity: 0; pointer-events: none; transition: opacity .25s ease; }
.himg__vid.is-live { opacity: 1; }
html.reduce-motion .himg__vid { display: none; }
/* the planes. Every transform lives on SVG groups inside the masks (vector, re-rasterised each frame, so the letter edges stay sharp at any
   scale). .is-gone = that plane's hero stroke already covers the viewport: nothing left to paint. */
.himg__sheet { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.himg__cream { fill: var(--cream); }
.himg__cream.is-gone { visibility: hidden; }
.himg__cream--2 { display: none; }
.himg__cream--2.is-on, html.reduce-motion .himg__still .himg__cream { display: inline; }
.himg__ln { display: none; }
.himg__ln.is-on { display: inline; }
/* intro: line 1 is hidden until T0 (app.js then fades the whole lockup in as one unit) */
html.is-intro:not(.p0) .himg__ln[data-role="m1"] { opacity: 0; }
@media (max-width: 768px) {
  .himg { --fx: 50%; --fy: 36.5%; } /* portrait cut (sky-stretched 870-tall canvas, crop centred on x 720: whole rider + horse nose) */
  .himg__media::before { background-image: url("../assets/brand/hero/hero03-scrub-lqip-portrait-24.webp"); }
}
/* nav pill over the cream paper (app.js sets .is-on-light while either paper covers most of the screen): #f0f0f0 on cream is 1.07:1, so it
   gets a soft warm-ink shadow there (rgb 20,9,6); none over the video or the coral */
/* nav pill shadow removed 2026-10-14 (user: no shadow on the header, ever). .is-on-light is still toggled by app.js but styles nothing. */
.nav__pill { box-shadow: none !important; }

/* reduced motion (?motion=reduce or the OS setting): no pin, no intro, no zoom, no scrub, no video. Screen one = line 1 with the poster inside
   its letters; screen two (.himg__still) = line 2 at rest with the poster inside its letters (the same mask, never zoomed here). */
.himg__still { display: none; }
html.reduce-motion .himg { height: auto; }
html.reduce-motion .himg__stage { position: relative; }
html.reduce-motion .himg__still { display: block; position: relative; height: 100vh; height: 100svh; overflow: hidden; background: #24170e; }
.himg__still picture { position: absolute; inset: 0; display: block; }
.himg__still img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--fx) var(--fy); }
.himg__still-sheet { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ---------- 01 coral hero (now section two): its intro states play on scroll ----------
   app.js adds .is-in once the section's top crosses 70% of the viewport (words rise with the 0/100/220/320ms delays below,
   card springs 62 -> 442px, video starts) and .is-sub 600ms later (sub fades up, rotating word starts): the old p3 / p3s
   steps with the same durations and easings. Gated on html.full-motion, so reduced motion shows the end state. */
html.full-motion .hero__screen { transition: opacity .6s ease; }
html.full-motion .hero:not(.is-in) .hero__screen { opacity: 0; }
html.full-motion .hero:not(.is-in) .hero__video { visibility: hidden; }
html.full-motion .hero:not(.is-in) .hero__word { transform: translateY(130%); }
html.full-motion .hero:not(.is-sub) .hero__sub { opacity: 0; transform: translateY(16px); }
.hero__line:first-child .hero__mask:nth-child(1) .hero__word { transition-delay: 0ms; }
.hero__line:first-child .hero__mask:nth-child(2) .hero__word { transition-delay: 100ms; }
.hero__line:last-child  .hero__mask:nth-child(1) .hero__word { transition-delay: 220ms; }
.hero__line:last-child  .hero__mask:nth-child(2) .hero__word { transition-delay: 320ms; }

/* ---------- Custom cursor (desktop, fine pointer only; injected by app.js) ---------- */
html.has-cursor, html.has-cursor *, html.has-cursor *::before, html.has-cursor *::after { cursor: none !important; }
html.has-cursor [data-cursor-dot], html.has-cursor [data-cursor-dot] * {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Ccircle cx='6' cy='6' r='5' fill='%230a0d12'/%3E%3C/svg%3E") 6 6, pointer !important; }
html.has-cursor [data-cursor-dot], html.has-cursor [data-cursor-dot] * { cursor: none !important; } /* cards use the same grown blob as every button */
.cur-cv { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: var(--z-cursor-canvas); }
.cur-dot { position: fixed; top: 0; left: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--orange); pointer-events: none;
  z-index: var(--z-cursor-dot); will-change: transform; transform: translate(-204px, -204px); transition: background .2s ease, opacity .15s ease; }

/* ---------- Shared helpers section agents may use ---------- */
/* generic fade-up (umano's only reveal): opacity + 32px, .65s ease, IO threshold .12, once, one wrapper per section */
.fade-up { opacity: 0; transform: translateY(32px); transition: opacity .65s ease, transform .65s ease; }
.fade-up.is-in { opacity: 1; transform: translateY(0); }

/* ---------- Reduced motion (umano has none; ours). html.reduce-motion is set in <head> from
   data-motion="auto|full|reduce", the ?motion= URL param, or the OS setting when auto. ---------- */
html.reduce-motion .fade-up { opacity: 1; transform: none; transition: none; }
html.reduce-motion .hero__word, html.reduce-motion .hero__sub, html.reduce-motion .hero__rot, html.reduce-motion .hero__rot strong,
html.reduce-motion .nav, html.reduce-motion .nav__links, html.reduce-motion .nav__links-in { transition: none !important; }

/* copy-swap (d): Arabic breaks under negative tracking (letters detach). Zero it only on the elements whose computed
   letter-spacing is negative and that now hold Arabic. :root[lang="ar"] lifts specificity over the section rules (loaded later). */
:root[lang="ar"] .hero__title, :root[lang="ar"] .hero__sub,
:root[lang="ar"] [data-section="03-statement"] .st__text,
:root[lang="ar"] [data-section="04-how-it-works"] .hiw__title, :root[lang="ar"] [data-section="04-how-it-works"] .hiw__desc,
:root[lang="ar"] [data-section="05-client-stories"] .cs__title,
:root[lang="ar"] [data-section="06-pricing"] .pr__h2, :root[lang="ar"] [data-section="06-pricing"] .pr__price,
:root[lang="ar"] [data-section="07-faq"] .faq__title,
:root[lang="ar"] [data-section="08-footer"] .ft__mail text { letter-spacing: 0; }

/* thmanyah headroom: Arabic ascenders rise above the mask box; gives the word masks room so dots on ف are not clipped and nothing peeks out before the intro rise. Tested: measurements identical. */
.hero__mask { padding-top: .15em; margin-top: -.15em; }
html.is-intro .hero__word { transform: translateY(130%); }

/* thmanyah contextual forms: thmanyah sans keeps its Arabic contextual alternates (seen+yeh, beh/teh/yeh before reh and noon,
   the .calt2/.wide tooth-spacing chains: 64 chained rules) under the "liga" feature, not "calt". --ff-off ("liga" 0, inherited
   from the Latin original) stripped them from the hero h1 only. The h1 holds no Latin ligature pair (the AM Le Cygne glyph is a
   single «…»), so the font default is restored. See FONT-SWAP-NOTES.md section 11. */
:root[lang="ar"] .hero__title { font-feature-settings: normal; }

/* ---------- thmanyah serif display (FONT-SWAP-NOTES.md section 12) ----------
   Display roles that were not on --f-display: the 04 card titles (card 5 is the takeover title) and the footer giant word.
   Their Latin tail keeps the old stack, so spaces / ':' / line boxes still come from Inter exactly as before. */
:root[lang="ar"] [data-section="04-how-it-works"] .hiw__title { font-family: "thmanyah display", "TWK Lausanne", "Inter", "IBM Plex Sans Arabic", sans-serif; }
:root[lang="ar"] [data-section="08-footer"] .ft__mail text { font-family: "thmanyah display", "TWK Lausanne", Inter, "IBM Plex Sans Arabic", sans-serif; }
/* The phone menu is navigation: it stays thmanyah sans Black, as it rendered before the serif swap. */
:root[lang="ar"] .mmenu__nav a { font-family: "thmanyah sans", "AM Le Cygne", "Lalezar", "Playfair Display", Georgia, serif; font-weight: 900; }
/* Swash (ss01: the long final forms of beh/teh/qaf/kaf/noon/yeh...). The guide (pp. 15-16): never in two adjacent words, never
   often in one sentence. So ONE swash per sentence: the hero's last word «بالواتساب؟» (the beh tail runs under the ؟, as the
   swash teh does on the guide's cover) and «ثابت» in the takeover title (.hiw__sw). «فريق…» stays plain: its swash qaf ran its
   tail under the ellipsis. Contextual joins (liga: 67 chained rules, rlig) stay on everywhere through the font defaults;
   no kashida (U+0640) is inserted anywhere. */
:root[lang="ar"] .hero__line:last-child .hero__mask:nth-child(2) .hero__word,
:root[lang="ar"] [data-section="04-how-it-works"] .hiw__sw { font-feature-settings: "ss01" 1; }

/* Arabic headline word gaps: the space glyph comes from the Latin fallback and reads tight under serif display tails (FONT-SWAP-NOTES section 12). Headline roles only, never body. */
:root[lang="ar"] .hero__title,
:root[lang="ar"] [data-section="03-statement"] .st__text,
:root[lang="ar"] [data-section="04-how-it-works"] .hiw__title,
:root[lang="ar"] [data-section="05-client-stories"] .cs__title,
:root[lang="ar"] [data-section="06-pricing"] .pr__head h3,
:root[lang="ar"] [data-section="07-faq"] .faq__title { word-spacing: .09em; }

/* ---------- Live films v1 (2026-10-15, COPY-SWAP-NOTES.md): film 4 «الرحلة» plays in the held phone's screen ----------
   js/films/boot.js mounts the live-code film (lab/trailer-engine journey, 'phone' variant) into .hero__film, which takes the old
   notif.mp4 <video>'s place and box in the note card (flex: 1 under the app header, var(--r-media) corners, clipped). The engine
   cover-fits its stage to the box and refits while the card springs open (62 -> 442 px). The hand photo and app.js's tilt and lift
   of .hero__phone are unchanged. Revert: cp backups/pre-live-films/base.css css/base.css (and index.html). */
/* Coral phone: full-bleed iOS journey (2026-10-16, COPY-SWAP-NOTES.md). The note card is gone: the film covers the photo's glass edge
   to edge (measured: 245.7×541.3 at 322.7, 54.9 in .hero__phone, corner 36.5; the box below is that glass rounded out to whole pixels,
   so the cover fit is exact) and the island redraws the photo's Dynamic Island over it (measured 78.2×22.8 at 406.4, 62.0, #0e0e0e).
   The film draws its own iOS status bar, so the page's .hero__status hides once the film is in (one status bar). The screen fades in
   when the section scrolls in (.is-in; it used to spring 14 -> 442 px). Physical left like the hand (photo not mirrored).
   Revert: cp backups/pre-full-bleed/css/base.css css/base.css (+ index.html, js/films/boot.js, js/films/src). */
.hero__screen { position: absolute; left: 322.5px; top: 54.5px; width: 246px; height: 542px; border-radius: 36.8px; overflow: hidden; background: #fff; }
.hero__screen > .hero__film { position: absolute; inset: 0; opacity: 0; transition: opacity .5s ease; }
.hero__screen > .hero__film.is-film { opacity: 1; }
.hero__island { position: absolute; left: 406.1px; top: 61.7px; width: 78.8px; height: 23.4px; border-radius: 11.7px; background: #0e0e0e; pointer-events: none; }
.hero__phone:has(.hero__film.is-film) .hero__status { visibility: hidden; }
html.reduce-motion .hero__screen, html.reduce-motion .hero__screen > .hero__film { transition: none; }

/* mobile CRO r1 M1: WhatsApp dock, phone only (<= 700px). JS (app.js) adds .is-on; ?dock=0 removes it. */
.wa-dock { display: none; }
@media (max-width: 700px) {
  .wa-dock { display: flex; align-items: center; justify-content: center; gap: 10px; box-shadow: 0 10px 28px rgba(10,13,18,.22), 0 2px 6px rgba(10,13,18,.12); position: fixed; z-index: var(--z-nav); inset-inline: 0; margin-inline: auto;
    width: min(340px, calc(100vw - 40px)); bottom: calc(16px + env(safe-area-inset-bottom, 0px)); height: 56px; border-radius: var(--r-cta);
    background: var(--orange); color: #fff; font: 700 18px var(--f-ui); text-decoration: none; white-space: nowrap;
    opacity: 0; transform: translateY(24px); visibility: hidden; pointer-events: none;
    transition: opacity .4s var(--e-out), transform .4s var(--e-out), visibility 0s linear .4s; }
  .wa-dock.is-on { opacity: 1; transform: none; visibility: visible; pointer-events: auto; transition-delay: 0s; }
  html.reduce-motion .wa-dock { transition: none; }
}

/* mobile CRO r2 (N1, N4, N8) */
.wa-dock__ic { flex: none; }
@media (max-width: 700px) {
  html.dock-live .nav__cta { display: none; } /* N1: the dock carries the CTA while it is up */
}
@media (max-width: 768px) {
  html.menu-open, html.menu-open body { overflow: hidden; } /* N8: scroll lock under the menu sheet */
}

/* mobile CRO r3 P1/P3 */
@media (max-width: 700px) {
  html.at-end .nav__pill { transform: translateY(calc(-100% - 24px)); transition: transform .4s var(--e-out); } /* P3: footer fully revealed, the pill steps away so the tagline is clear */
  html.reduce-motion.at-end .nav__pill { transition: none; }
}

/* ---------- Mobile component design 3.2 / 3.3 (2026-10-18, NOTES-mcd-nav-strip.md): phone nav pill + menu sheet ----------
   Gated at 540, not the spec's 768, so the 550 tablet view stays pixel-identical (same gate as the offer, FAQ and footer builds).
   Pill: 64 tall on the 16 px page edge (the cards' edge line), 48 px circle burger, 48 px pill CTA set beside the burger.
   Sheet: night, full screen from the top (no page strip), close button on the burger's exact spot, links + CTA bottom-anchored in thumb reach. */
@media (max-width: 540px) {
  :root { --m-1: 4px; --m-2: 8px; --m-3: 12px; --m-4: 16px; --m-5: 20px; --m-6: 24px; --m-7: 32px; --m-8: 40px; --m-9: 48px; --m-10: 64px; }
  .nav__pill { height: 64px; width: calc(100vw - 32px); padding-inline: 16px 8px; border-radius: 32px; gap: 8px; }
  .nav__logo img { height: 28px; }
  .nav__cta { height: 48px; min-height: 48px; display: inline-flex; align-items: center; padding: 0 16px; border-radius: 999px; font: 700 15px/1 var(--f-ui); margin-inline-start: auto; }
  .nav__burger { width: 48px; height: 48px; min-width: 48px; padding: 0; border-radius: 50%; align-items: center; }
  .nav__burger span { width: 18px; }

  .mmenu { top: 0; height: 100vh; height: 100dvh; padding: 0 16px; background: var(--night); }
  .mmenu__top { padding: 24px 0 0; padding-inline-end: 8px; }             /* close box = the burger's box: 24 px from the top, 24 px from the end edge */
  .mmenu__close { width: 48px; height: 48px; padding: 0; border-radius: 50%; background: rgba(255, 255, 255, .08); display: grid; place-items: center; }
  .mmenu__close svg { width: 24px; height: 24px; }
  .mmenu__nav { justify-content: flex-end; gap: 0; padding-bottom: 24px; }
  .mmenu__nav a { position: relative; display: flex; align-items: center; min-height: 56px; font-size: 30px; line-height: 36px; }
  .mmenu__nav a + a { margin-top: 8px; }                                   /* 56 tall + 8 apart = a 64 px row pitch; the hairline sits mid-gap */
  .mmenu__nav a::before { content: ""; position: absolute; inset-inline: 0; top: -4.5px; height: 1px; background: rgba(255, 255, 255, .12); pointer-events: none; }
  .mmenu__cta { height: 56px; display: flex; align-items: center; justify-content: center; padding: 0 24px; border-radius: 999px; font: 700 17px/1 var(--f-ui); }
  .mmenu__next { margin-top: 12px; font: 400 14px/22px var(--f-ui); color: rgba(255, 255, 255, .55); text-align: center; }
  /* entrance: the links and CTA rise 16 px as the sheet fades in */
  .mmenu__nav, .mmenu__foot { transform: translateY(16px); transition: transform .4s var(--e-out); }
  .mmenu.is-open .mmenu__nav, .mmenu.is-open .mmenu__foot { transform: none; }
  html.reduce-motion .mmenu, html.reduce-motion .mmenu__nav, html.reduce-motion .mmenu__foot { transition: none; }
}
.mmenu__next { display: none; }
@media (max-width: 540px) { .mmenu__next { display: block; } }

/* ---------- Owner batch 2026-10-18 (NOTES-owner-batch-ux.md) ----------
   E: the nav pill is mirrored. Logo at the LEFT edge, CTA (desktop) / burger (phone) at the RIGHT edge, the phone CTA beside the burger, inward.
      The page stays RTL: only the pill's flex row is reversed (DOM order unchanged). The menu sheet's close button follows the burger to the right.
   F: in-flow WhatsApp CTAs, owner's cut: one after the why-us pin releases, one in the FAQ's sticky head. Same pill, same label «كلّمنا عن مشروعك».
      Desktop and tablet only: hidden <= 540 px, where the dock carries reach (541-700 the dock also steps aside while one is on screen, app.js). */
.nav__pill { flex-direction: row-reverse; }
.nav__cta { margin-inline: 0 4px; }                 /* the 4 px faces the links, which now sit on the CTA's left (inline-end) */
.mmenu__top { justify-content: flex-start; }        /* close button on the right, on the burger's side */
@media (max-width: 768px) {
  .nav__pill { padding-inline: 12px 14px; }         /* mirrored 14 / 12: 12 on the burger's (right) side */
  .nav__cta { margin-inline: 0 auto; }              /* the free space sits between the logo and the CTA, so the CTA rests beside the burger */
}
@media (max-width: 540px) {
  .nav__pill { padding-inline: 8px 16px; }          /* mirrored 16 / 8: burger box 24 px from the right edge, logo 32 px from the left */
  .mmenu__top { padding-inline: 8px 0; }            /* close box = the burger's box: 24 px from the top, 24 px from the right */
}

.sec-cta { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.sec-cta__btn { display: inline-flex; align-items: center; justify-content: center; height: 56px; padding: 0 32px; border-radius: 999px;
  background: var(--orange); color: #fff; font: 600 17px/1 var(--f-ui); text-decoration: none; white-space: nowrap; transition: background .3s ease, color .3s ease; }
.sec-cta__btn:hover { background: #fff; color: var(--night); }
.sec-cta__btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.sec-cta__next { margin: 0; font: 400 15px/24px var(--f-ui); color: rgba(255, 255, 255, .55); }
html.reduce-motion .sec-cta__btn { transition: none; }
.sec-cta--hero { margin-top: 32px; transition: opacity .6s ease, transform .6s ease; } /* coral hero pill: 32px under the sub, rises with it */
[data-section="01-hero"] .sec-cta--hero .sec-cta__btn { background: var(--night); }
[data-section="01-hero"] .sec-cta--hero .sec-cta__btn:hover { background: #fff; color: var(--night); }
html.full-motion .hero:not(.is-sub) .sec-cta--hero { opacity: 0; transform: translateY(16px); }
[data-section="07-faq"] .sec-cta--faq { align-items: flex-start; margin-top: 8px; } /* inside .faq__head: sticky beside the list at >= 1100 px, under the lead on one column */
@media (max-width: 540px) { .sec-cta { display: none; } }
