/* ===========================================================================
   Cycles — stylesheet.

   Split out of index.html so the browser caches it apart from the markup, so a
   duplicated selector is findable, and so scripts/check.js can read one file
   instead of slicing a <style> block out of 3,000 lines. There is no build
   step: this is the sheet the browser gets, byte for byte.

   Order below: tokens and themes · loader · chrome and headline · hub, nodes
   and brain · scenes · dialogs · booking · responsive.
   =========================================================================== */
/* =====================================================================
   THEME TOKENS — everything visual reads from these. Dark is the brand
   default; light is a full alternate palette (not just inverted).
   ===================================================================== */
:root,[data-theme=dark]{
  color-scheme:dark;
  /* Near-black, not navy. The reference decks read as "electric" because the
     ground is almost black and the blue is the only saturated thing on it; a
     navy ground competes with the accent and both end up muted. */
  --void:#01030A;--deep:#03060F;
  --text:#EAEDFB;--muted:#9BA6CF;--faint:#6c75a1;   /* 4.53:1 on --deep; --faint is only ever 11-13px text, so AA needs 4.5 not 3 */
  /* Same family as the logo's #5E81F4, pushed toward the electric end: more
     chroma, a touch more light. The hue is untouched, so the brand still reads. */
  --b-deep:#1F4BFF;--b-1:#3D66FF;--b-2:#4E7BFF;--b-3:#6B93FF;--b-4:#8AB0FF;--b-light:#B6CCFF;
  --accent:#4E7BFF;--core:#FFFFFF;                 /* --core = the "hot" centre of any glow */
  --panel:rgba(8,12,26,.62);--panel-line:rgba(120,150,255,.2);--panel-blur:12px;
  /* Vertical lane reserved at the bottom of the viewport for the Cycles agent
     launcher, which positions itself and whose shadow DOM we do not style.
     Measured, not guessed: the launcher sits 30px off the bottom and stands
     60px tall, so it owns the first 90px; 104 leaves a 14px gap above it.
     Anything that would otherwise reach the bottom edge — the caption bar, the
     launcher sheet, the constellation's last row — clears this, so nothing ever
     shares a line with the call button. */
  --agent-lane:104px;
  /* Horizontal reserve for the same launcher, used when something has to sit
     beside it on the bottom row rather than above it. 150px wide + 30px off
     the right edge + a 20px gap. */
  --agent-side:200px;
  --chip:rgba(140,160,240,.1);--chip-line:rgba(150,170,245,.22);
  --ring-bg:radial-gradient(circle at 50% 36%, rgba(20,28,58,.97), rgba(4,6,14,.98));--ring-line:rgba(160,182,255,.55);
  /* the node lens: translucent so the starfield behind it actually refracts */
  --lens:linear-gradient(160deg, rgba(108,140,215,.34) 0%, rgba(44,66,132,.24) 55%, rgba(12,20,44,.52) 100%);
  --lens-spec:rgba(255,255,255,.42);--lens-rim:rgba(160,190,255,.20);--lens-sh:rgba(0,0,0,.46);
  --mark-lift:saturate(1.18) brightness(1.16);
  --mark-sh:drop-shadow(0 1.5px 2.5px rgba(6,10,32,.26));
  --mark-sh-hi:drop-shadow(0 2.5px 5px rgba(6,10,32,.32));
  --line:rgba(78,116,252,.5);--line-dot:#5E86FD;--pulse:#ffffff;
  --glow-a:rgba(31,75,255,.78);--glow-b:rgba(31,75,255,.4);
  --bg-glow-1:rgba(31,75,255,.3);--bg-glow-2:rgba(78,123,255,.16);--vignette:rgba(0,1,4,.94);
  --halo-1:rgba(150,180,255,.26);--halo-2:rgba(31,75,255,.4);--halo-3:rgba(31,75,255,.1);
  --glass-1:rgba(120,150,255,.14);--glass-2:rgba(58,92,251,.08);--glass-3:rgba(20,30,90,.22);--glass-bright:1.02;--glass-sat:200%;
  --brain-fill:#31459a;--brain-fill-a:.10;--brain-fill2:#16204a;--brain-fill2-a:.16;--brain-line:#86ACFF;
  --sc-card:rgba(20,28,58,.85);--sc-card-line:rgba(150,170,245,.25);--sc-bg:linear-gradient(150deg, rgba(20,27,54,.9), rgba(9,12,26,.95));
  --ok:#22C55E;--warn:#F59E0B;--bad:#F87171;
  --h1:#ffffff;--shadow-text:0 2px 20px rgba(3,6,18,.9);
  --glass-hi:rgba(255,255,255,.14);--glass-hi-2:rgba(255,255,255,.05);
  --disp:"Sora",system-ui,sans-serif;--body:"Inter",system-ui,-apple-system,sans-serif;
}
[data-theme=light]{
  color-scheme:light;
  --void:#F6F8FF;--deep:#EEF2FF;
  --text:#0B1335;--muted:#4E5A8A;--faint:#5f6c9d;             /* 4.56:1 on --deep. #6673A4 measured 4.12 and missed AA despite the comment claiming it. */
  --accent:#3A5CFB;--core:#ffffff;
  --panel:rgba(255,255,255,.82);--panel-line:rgba(58,92,251,.14);--panel-blur:14px;
  --chip:rgba(58,92,251,.08);--chip-line:rgba(58,92,251,.22);
  --ring-bg:radial-gradient(circle at 50% 36%, #ffffff, #F1F4FF);--ring-line:rgba(58,92,251,.38);
  --lens:linear-gradient(160deg, rgba(255,255,255,.92) 0%, rgba(227,235,253,.74) 55%, rgba(198,214,248,.62) 100%);
  --lens-spec:rgba(255,255,255,1);--lens-rim:rgba(118,148,220,.22);--lens-sh:rgba(58,84,160,.16);
  --mark-lift:none;
  --mark-sh:drop-shadow(0 1px 1.5px rgba(42,64,150,.13));
  --mark-sh-hi:drop-shadow(0 2px 3px rgba(42,64,150,.17));
  --line:rgba(58,92,251,.34);--line-dot:#3A5CFB;--pulse:#3A5CFB;
  --glow-a:rgba(58,92,251,.32);--glow-b:rgba(58,92,251,.12);
  --bg-glow-1:rgba(58,92,251,.10);--bg-glow-2:rgba(120,150,255,.10);--vignette:rgba(20,30,90,.08);
  --halo-1:rgba(58,92,251,.22);--halo-2:rgba(58,92,251,.2);--halo-3:rgba(58,92,251,.05);
  --glass-1:rgba(92,124,255,.30);--glass-2:rgba(58,92,251,.36);--glass-3:rgba(30,52,170,.46);--glass-bright:1.0;--glass-sat:200%;
  --brain-fill:#3A5CFB;--brain-fill-a:.16;--brain-fill2:#1F3BC7;--brain-fill2-a:.12;--brain-line:#2D49D9;
  --ok:#12883E;--warn:#B16105;--bad:#DC2626;                  /* ok/warn darkened from #16A34A/#D97706 — WCAG AA (4.5:1) as text */
  --h1:#0B1335;--shadow-text:none;
  --glass-hi:rgba(255,255,255,.85);--glass-hi-2:rgba(255,255,255,.3);
  --sc-card:#ffffff;--sc-card-line:rgba(58,92,251,.18);--sc-bg:linear-gradient(150deg,#ffffff,#EEF2FF);
}
[lang=ar]{--disp:"IBM Plex Sans Arabic","Sora",system-ui,sans-serif;--body:"IBM Plex Sans Arabic","Inter",system-ui,sans-serif}
[lang=ar] body{font-feature-settings:"liga","calt"}

*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--void);color:var(--text);font-family:var(--body);overflow:hidden;-webkit-font-smoothing:antialiased;transition:background .5s ease,color .5s ease}
button{font-family:inherit;color:inherit;cursor:pointer}
/* ===== GLASSMORPHISM — one frosted-glass treatment shared by every card/chip/pill
   surface: blur + saturate what's behind it, plus a hairline top highlight where
   light would catch a real pane of glass. ===== */
.tn-tabs,.seg,.cap-btn,.cbtn,.a-chip,.ic,.orch,.tab.active,.seg span.on,
.core-box,.step,.back,.how-card,.help-card{
  backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
}
/* elements above with no competing box-shadow of their own get the hairline directly */
.tn-tabs,.seg,.cap-btn,.cbtn,.a-chip,.ic,.orch,.step,.back{
  box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2);
}
/* the rest already carry their own box-shadow, so the hairline is merged in below */
.how-card,.help-card{box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2), 0 30px 90px rgba(2,4,12,.4)}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:6px}
.node:focus-visible,.node:focus{outline:none}   /* the ring itself carries the focus state */
/* pill/circular controls need the focus ring to match their own radius, not the
   generic 6px above — otherwise a rounded button gets a squared-off outline
   floating around it, reading as a stray double border */
.tab:focus-visible,.tn-tabs:focus-visible,.seg:focus-visible,.cap-btn:focus-visible,
.cbtn:focus-visible,.back:focus-visible,.tbtn:focus-visible,.cta:focus-visible,
.book-success-ic:focus-visible,.cap-ic:focus-visible{border-radius:999px}
/* Moving focus programmatically (e.g. to the Back button when a feature page
   opens, for screen-reader users) still matches :focus-visible in most
   browsers, which drew a ring around it on every plain mouse click too —
   see focusQuiet() below. The DOM focus move itself is unaffected (screen
   readers still get it); only the visible ring is suppressed. */
.focus-quiet:focus-visible{outline:none}
#stars{position:fixed;inset:0;z-index:0}
@property --gx{syntax:'<percentage>';inherits:false;initial-value:50%}
@property --gy{syntax:'<percentage>';inherits:false;initial-value:46%}
.bg-glow{position:fixed;inset:0;z-index:0;pointer-events:none;--gx:50%;--gy:46%;
  background:radial-gradient(1200px 800px at var(--gx) var(--gy), var(--bg-glow-1), transparent 60%),
   radial-gradient(900px 900px at 82% 90%, var(--bg-glow-2), transparent 58%);
  transition:--gx 1.2s cubic-bezier(.2,.7,.2,1), --gy 1.2s cubic-bezier(.2,.7,.2,1)}
.vignette{position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(120% 120% at 50% 50%, transparent 48%, var(--vignette) 100%)}
.stage{position:relative;z-index:2;height:100%;width:100%;overflow:hidden}

/* ===== LOADER ===== */
/* Flex column with a gap, not grid + an absolutely positioned skip line. The
   skip used to be pinned to the bottom while the loader block was centred, so
   on a short viewport the two met and "Ready" printed on top of "Tap anywhere
   to enter". As flow items separated by a gap they cannot overlap at any
   height, whatever the status text says. */
#loader{position:absolute;inset:0;z-index:20;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(20px,6vh,58px);padding:24px 16px clamp(20px,4vh,44px);transition:opacity .8s ease, transform .8s cubic-bezier(.2,.7,.2,1)}
#loader.gone{opacity:0;transform:scale(1.06);pointer-events:none}
.loadwrap{display:flex;flex-direction:column;align-items:center;text-align:center;transform:translateY(-2vh)}
.load-rings{position:relative;width:clamp(220px,30vmin,360px);height:clamp(220px,30vmin,360px);display:grid;place-items:center;margin-bottom:8px}
.load-rings .rg{position:absolute;border-radius:50%;border:1px solid var(--panel-line)}
.rg.a{inset:0;animation:spin 18s linear infinite}
.rg.a::after{content:"";position:absolute;top:-3px;left:50%;width:6px;height:6px;border-radius:50%;background:var(--b-light);box-shadow:0 0 12px var(--b-3);transform:translateX(-50%)}
.rg.b{inset:13%;animation:spin 12s linear infinite reverse}
.rg.b::after{content:"";position:absolute;bottom:-2px;left:50%;width:4px;height:4px;border-radius:50%;background:var(--b-3);box-shadow:0 0 10px var(--b-2);transform:translateX(-50%)}
.load-rings::before{content:"";position:absolute;inset:18%;border-radius:50%;z-index:1;pointer-events:none;
  background:radial-gradient(circle, var(--glow-a) 0%, transparent 70%);filter:blur(24px);
  animation:pulseglow 3.4s ease-in-out infinite}
.load-logo{position:relative;width:50%;z-index:2}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes pulseglow{0%,100%{opacity:.55;transform:scale(.94)}50%{opacity:1;transform:scale(1.08)}}
.load-word{height:clamp(30px,3.4vw,52px);margin-top:6px;filter:drop-shadow(0 6px 22px var(--glow-b));opacity:0;animation:rise .9s .35s cubic-bezier(.2,.7,.2,1) forwards}
.load-sub{font-family:var(--disp);font-weight:400;letter-spacing:.34em;font-size:clamp(11px,1.1vw,15px);color:var(--b-4);margin-top:18px;text-indent:.34em;opacity:0;animation:rise .9s .6s cubic-bezier(.2,.7,.2,1) forwards}
[lang=ar] .load-sub{letter-spacing:.06em;text-indent:0;font-weight:500}
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.load-track{width:clamp(200px,22vw,300px);height:2px;background:var(--panel-line);border-radius:2px;margin-top:30px;overflow:hidden;opacity:0;animation:rise .8s .8s forwards}
.load-fill{height:100%;width:0;border-radius:2px;background:linear-gradient(90deg,var(--b-deep),var(--core));box-shadow:0 0 16px var(--glow-a);animation:fill 2.7s .9s cubic-bezier(.5,.05,.2,1) forwards}
[dir=rtl] .load-fill{background:linear-gradient(270deg,var(--b-deep),var(--core))}
@keyframes fill{to{width:100%}}
.load-status{font-family:var(--disp);font-size:clamp(11px,.95vw,13px);color:var(--faint);letter-spacing:.02em;margin-top:14px;min-height:1.2em;opacity:0;animation:rise .8s .9s forwards}
/* Centred by left:0/right:0 + text-align, NOT by translateX(-50%): the shared
   `rise` animation ends on `transform:none`, which wiped the centring transform
   and left this sitting with its left edge on the midline. */
.load-skip{text-align:center;color:var(--faint);font-size:13px;letter-spacing:.04em;opacity:0;animation:rise .8s 1.6s forwards}
/* The loader is seven stacked pieces — rings, mark, wordmark, tagline, track,
   status, skip — sized for a desktop window. On a phone that column ran past
   the bottom of the screen and clipped the one line that tells you what to do.
   Everything shrinks together here so the composition keeps its proportions
   instead of collapsing one element at a time. */
@media (max-height:700px), (max-width:560px){
  #loader{gap:clamp(12px,3vh,26px);padding:16px 16px clamp(16px,3vh,28px)}
  .load-rings{width:clamp(132px,34vmin,200px);height:clamp(132px,34vmin,200px);margin-bottom:2px}
  .load-word{height:clamp(24px,7vw,34px)}
  .load-sub{margin-top:12px;letter-spacing:.24em;font-size:clamp(10px,2.6vw,12px)}
  .load-track{margin-top:18px;width:min(62vw,240px)}
  .load-status{margin-top:9px}
  .load-skip{font-size:12.5px}
}
/* The call button has nothing to answer until the visitor is inside, so it
   fades in with the hub.
   NEVER set pointer-events on this element. The host is a full-viewport
   position:fixed container — 100% x 100% at 0,0 — that merely parks its bubble
   in a corner, and it keeps itself click-through with its own
   pointer-events:none, re-enabling only the bubble inside its shadow DOM.
   Writing pointer-events:auto here overrode that and turned the whole page into
   one giant click target: every button, the scroll, and the narration (a
   document-level click handler stops it whenever the path crosses the widget)
   all died at once. Gate with visibility instead — it hides the subtree and
   removes it from hit-testing without touching the widget's own rules. */
elevenlabs-convai{opacity:0;visibility:hidden;transition:opacity .5s ease .3s, visibility 0s linear .8s;
  /* The widget parks its bubble with logical positioning, so it mirrors to the
     bottom-LEFT when the page turns RTL. Pinning direction:ltr on the host keeps
     it bottom-right in both languages, which is where the caption reserves its
     gap (a physical `right`, for the same reason). This sets direction only —
     never pointer-events; see the warning above. */
  direction:ltr}
body.entered elevenlabs-convai{opacity:1;visibility:visible;transition:opacity .5s ease .3s, visibility 0s}

/* ===== HUB ===== */
#hub{position:absolute;inset:0;opacity:0;pointer-events:none;transition:opacity .7s ease, transform .7s cubic-bezier(.2,.7,.2,1);transform:scale(.97)}
#hub.active{opacity:1;pointer-events:auto;transform:none}
#hub.dim{opacity:0;transform:scale(.94);pointer-events:none}

/* top bar — presentation chrome, not a landing page */
.chrome{position:absolute;top:0;left:0;right:0;z-index:18;transition:transform .45s cubic-bezier(.2,.7,.2,1), opacity .35s ease}
#hub.chrome-hidden .chrome{transform:translateY(-100%);opacity:0;pointer-events:none}
.chrome-handle{position:absolute;top:0;left:50%;z-index:19;transform:translate(-50%,-110%);display:inline-flex;align-items:center;gap:8px;padding:6px 14px 7px;border-radius:0 0 12px 12px;
  background:var(--panel);border:1px solid var(--panel-line);border-top:0;font:600 12px var(--disp);color:var(--muted);backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);box-shadow:inset 0 1px 0 var(--glass-hi);transition:transform .4s cubic-bezier(.2,.7,.2,1), color .2s}
.chrome-handle svg{width:14px;height:14px;stroke:var(--accent);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.chrome-handle:hover{color:var(--h1)}
#hub.chrome-hidden .chrome-handle{transform:translate(-50%,0)}
.topnav{position:relative;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:14px;height:64px;padding:0 clamp(16px,2.4vw,40px);
  background:var(--panel);backdrop-filter:blur(var(--panel-blur)) saturate(130%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(130%);
  border-bottom:1px solid var(--panel-line);box-shadow:inset 0 1px 0 var(--glass-hi);opacity:0;transform:translateY(-8px);transition:opacity .7s ease .9s, transform .7s cubic-bezier(.2,.7,.2,1) .9s, background .5s}
#hub.active .topnav{opacity:1;transform:none}
#hub.settled .topnav{transition:opacity .4s, transform .4s, background .5s}
.tbtn.hidebtn svg{transform:rotate(180deg)}
.tn-logo{justify-self:start;height:30px;display:inline-flex;align-items:center;gap:7px;filter:saturate(1.35) contrast(1.1) drop-shadow(0 2px 8px var(--glow-b))}
.tn-mark{height:30px;display:block}
.tn-word{height:19px;display:block}
/* No flex-direction override here on purpose. A `row` flex container already
   lays its children out along the writing direction, so under [dir=rtl] the
   mark — the first child — lands on the right and the wordmark follows to its
   left, which is what Arabic wants. Adding row-reverse pushed the mark back to
   the left, the very bug this split was meant to fix. The Latin wordmark itself
   is never mirrored; only the order of the two pieces changes. */
.tn-tabs{display:flex;gap:2px;justify-self:center;padding:4px;border-radius:999px;background:var(--chip);border:1px solid var(--chip-line)}
.tab{border:0;background:none;padding:7px 14px;border-radius:999px;font:600 12.5px var(--disp);letter-spacing:.02em;color:var(--muted);white-space:nowrap;transition:color .2s, background .2s;display:inline-flex;align-items:center;gap:6px}
.tab .ai-ic{width:13px;height:13px;flex:0 0 auto;fill:var(--accent);animation:aiTwinkle 2.4s ease-in-out infinite}
@keyframes aiTwinkle{0%,100%{opacity:.55;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}
.tab:hover{color:var(--h1)}
.tab.active{color:var(--h1);background:var(--panel);box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2), 0 2px 10px rgba(2,4,12,.15)}
[lang=ar] .tab{letter-spacing:0;font-size:13.5px}
/* Browsers give <button> the default arrow, not a hand — only <a> gets the
   hand for free. Eight interactive things here were plain buttons, so the
   cursor never changed and every one of them read as disabled on hover, even
   though the click worked. Declared once, in one place, so a new control cannot
   quietly inherit the same bug. :disabled is excluded on purpose. */
.tbtn,.cta,.seg,.node,.tab,.cbtn,.back,.chrome-handle,.dialog-close,.ltile,.slot-btn,.slot-day-btn,
.set-row,.launcher-card a,.launcher-card button{cursor:pointer}
.tbtn:disabled,.cta:disabled,.cbtn:disabled,button:disabled{cursor:default}
/* ===== launcher: the chapters as tiles =====
   A 3x3 button opens a tile grid, the pattern people already know from an app
   launcher. On desktop it is an anchored popover beside the rail (an extra way
   in, not a replacement); on a phone the rail is gone and this is the only way,
   which is the point — five wrapped pills were the widest thing in the header. */
/* ===== settings popover =====
   Anchored to its own button rather than to the header, so it lands under the
   gear in both writing directions without a second rule. */
.settings{position:absolute;top:calc(100% + 10px);inset-inline-end:0;z-index:18;width:250px;
  opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-6px) scale(.98);
  transition:opacity .18s, transform .18s cubic-bezier(.2,.7,.2,1), visibility 0s linear .18s}
.settings.show{opacity:1;visibility:visible;pointer-events:auto;transform:none;transition:opacity .18s, transform .18s cubic-bezier(.2,.7,.2,1), visibility 0s}
.settings-card{padding:8px;border-radius:16px;background:var(--panel);border:1px solid var(--panel-line);
  box-shadow:0 22px 60px rgba(3,6,18,.34);backdrop-filter:blur(var(--panel-blur)) saturate(150%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(150%)}
.set-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border-radius:11px}
.set-row+.set-row{margin-top:2px}
.set-row:hover{background:var(--chip)}
.set-lab{font:600 12.5px var(--disp);color:var(--ink);white-space:nowrap}
.set-ctl{display:inline-flex;align-items:center;gap:4px}
.launcher{position:absolute;inset:0;z-index:17;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .2s, visibility 0s linear .2s}
.launcher.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .2s, visibility 0s}
.launcher-card{position:absolute;top:60px;inset-inline-end:clamp(12px,2.4vw,40px);width:min(324px,calc(100vw - 24px));
  padding:16px;border-radius:20px;background:var(--panel);border:1px solid var(--panel-line);
  box-shadow:0 26px 70px rgba(3,6,18,.34);backdrop-filter:blur(var(--panel-blur)) saturate(150%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(150%);
  transform:translateY(-8px) scale(.98);opacity:0;transition:transform .22s cubic-bezier(.2,.7,.2,1), opacity .22s}
.launcher.show .launcher-card{transform:none;opacity:1}
.launcher-t{margin:0 0 12px;font:600 11px var(--disp);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);text-align:start}
.launcher-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.ltile{display:grid;justify-items:center;align-content:start;gap:8px;padding:12px 6px 11px;border:0;border-radius:14px;background:none;cursor:pointer;
  font:600 11.5px var(--disp);color:var(--ink);line-height:1.25;text-align:center;text-decoration:none;transition:background .18s}
.ltile:hover,.ltile:focus-visible{background:var(--chip)}
.ltile i{width:42px;height:42px;border-radius:13px;display:grid;place-items:center;background:color-mix(in srgb, var(--accent) 13%, transparent);border:1px solid var(--chip-line)}
.ltile svg{width:20px;height:20px;stroke:var(--accent);fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.ltile[aria-current=true] i{background:var(--accent);border-color:var(--accent)}
.ltile[aria-current=true] svg{stroke:#fff}
.ltile[aria-current=true]{color:var(--accent)}
/* Group heading inside the grid: spans every column so the two halves read as
   two lists, not one run of eight. */
.launcher-sec{grid-column:1/-1;margin:14px 0 6px;padding-top:12px;border-top:1px solid var(--panel-line)}
.tn-right{display:flex;align-items:center;gap:8px;justify-self:end}
.seg{display:inline-flex;padding:3px;border-radius:999px;background:var(--chip);border:1px solid var(--chip-line);gap:2px}
.seg[hidden]{display:none}
.seg span{padding:5px 10px;border-radius:999px;font:700 11.5px var(--disp);color:var(--muted);letter-spacing:.06em;cursor:pointer;transition:background .2s,color .2s}
.seg span.on{background:var(--panel);color:var(--h1);box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2), 0 2px 8px rgba(2,4,12,.15)}
.tbtn{height:36px;min-width:36px;padding:0 10px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;gap:8px;
  background:var(--chip);border:1px solid var(--chip-line);font:600 12.5px var(--disp);color:var(--text);transition:border-color .25s, background .25s}
.tbtn:hover{border-color:var(--accent)}
.tbtn svg{width:16px;height:16px;stroke:var(--accent);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.tbtn .sun{display:none}[data-theme=light] .tbtn .sun{display:block}[data-theme=light] .tbtn .moon{display:none}
/* Shared by every play/pause control that toggles narration state — the
   topnav voice-guide button, the feature-page flat bar, and the cycle
   walkthrough's own pause button — one rule instead of three copies that
   can silently drift out of sync (exactly what happened once already). */
.playpause .ic-pause{display:none}
.playpause.is-playing .ic-play{display:none}
.playpause.is-playing .ic-pause{display:block}
#muteBtn .spk-off{display:none}#muteBtn.is-muted .spk-on{display:none}#muteBtn.is-muted .spk-off{display:block}#muteBtn.is-muted{border-color:var(--bad)}
.cta{height:36px;padding:0 16px;border-radius:10px;border:0;background:var(--accent);color:#fff;font:700 12.5px var(--disp);letter-spacing:.02em;box-shadow:0 8px 24px color-mix(in srgb, var(--accent) 35%, transparent);transition:transform .2s, box-shadow .2s}
a.cta{display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
a.cta:link,a.cta:visited{color:#fff}
.cta:hover{transform:translateY(-1px);box-shadow:0 12px 30px color-mix(in srgb, var(--accent) 45%, transparent)}
/* Secondary CTA: the live demo. Outlined so the booking button stays the primary
   action — the demo is the lower-commitment door, not a competing one. */
/* headline — centred under the bar, gradient type */
.headline{position:absolute;left:0;right:0;top:calc(64px + clamp(30px,6vh,72px));z-index:8;text-align:center;padding:0 clamp(16px,4vw,60px);pointer-events:none;
  opacity:0;transform:translateY(-6px);transition:opacity .8s ease 1.3s, transform .8s cubic-bezier(.2,.7,.2,1) 1.3s}
#hub.active .headline{opacity:1;transform:none}
#hub.settled .headline{transition:opacity .4s, transform .4s}
/* The headline is the page's one statement; hiding the chrome should clear the
   furniture around it, not the statement itself. It only slides up into the
   space the header just vacated. */
#hub.chrome-hidden .headline{opacity:1;transform:none;top:clamp(18px,4vh,42px)}
.headline h1,.headline p{text-align:center;margin-inline:auto}
/* The gradient used to sweep the WHOLE sentence, which meant every word was
   mid-fade and none of them was the subject. It now belongs to <em> — the two
   words the claim is about — and the rest of the line sits in one solid colour.
   The emphasis reads instantly instead of being averaged across nine words. */
.headline h1{max-width:min(92vw,980px);font-family:var(--disp);font-weight:800;font-size:clamp(26px,3.5vw,54px);line-height:1.08;letter-spacing:-.028em;margin:0 auto;text-wrap:balance;
  background:linear-gradient(96deg, color-mix(in srgb, var(--h1) 86%, var(--accent)) 0%, var(--h1) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;
  filter:drop-shadow(0 6px 24px color-mix(in srgb, var(--accent) 22%, transparent))}
[dir=rtl] .headline h1{background:linear-gradient(264deg, color-mix(in srgb, var(--h1) 86%, var(--accent)) 0%, var(--h1) 100%);-webkit-background-clip:text;background-clip:text}
[data-theme=light] .headline h1{background:linear-gradient(96deg, color-mix(in srgb, #0B1335 84%, var(--accent)) 0%, #0B1335 100%);-webkit-background-clip:text;background-clip:text}
[data-theme=light][dir=rtl] .headline h1{background:linear-gradient(264deg, color-mix(in srgb, #0B1335 84%, var(--accent)) 0%, #0B1335 100%);-webkit-background-clip:text;background-clip:text}


/* The tagline is two beats: a claim, then its payoff. The h1's gradient runs
   toward --accent anyway, so resolving the <em> to that endpoint lets the second
   beat read as the answer — needed in Arabic especially, where both beats fit on
   one line. -webkit-text-fill-color is required: the h1 paints its glyphs via
   background-clip:text, which `color` alone can't override on a descendant. */
/* -webkit-text-fill-color:transparent is what actually reveals the gradient
   behind the glyphs; `color:transparent` alone is overridden by the inherited
   fill on WebKit. The angle flips for Arabic so the sweep always runs with the
   reading direction — light at the start, accent at the end. */
.headline h1 em{font-style:normal;background:linear-gradient(96deg, var(--b-light) 0%, var(--accent) 92%);
  -webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
[dir=rtl] .headline h1 em{background:linear-gradient(264deg, var(--b-light) 0%, var(--accent) 92%);-webkit-background-clip:text;background-clip:text}
[data-theme=light] .headline h1 em{background:linear-gradient(96deg, var(--b-1) 0%, var(--accent) 92%);-webkit-background-clip:text;background-clip:text}
[data-theme=light][dir=rtl] .headline h1 em{background:linear-gradient(264deg, var(--b-1) 0%, var(--accent) 92%);-webkit-background-clip:text;background-clip:text}
/* Caps, in English only, and with the tracking sign flipped. You asked for
   this three times; my objection was never that caps look bad, it was that
   -.028em kerning is set for lowercase and jams capitals together, and that
   Arabic has no caps so the two languages would stop matching. Both are
   answered here: English gets +.012em, which is what caps need to breathe, and
   Arabic gets the equivalent weight in the only currency it has — a heavier
   face and tighter leading. The two now read with the same density without
   pretending Arabic has a case it does not. */
[lang=en] .headline h1{text-transform:uppercase;letter-spacing:.012em;line-height:1.14;font-size:clamp(23px,3.1vw,47px)}
[lang=ar] .headline h1{max-width:min(92vw,1040px);font-weight:800;letter-spacing:0;line-height:1.32;font-size:clamp(24px,3.1vw,48px)}
/* text-wrap:pretty, not balance: balance evens out line lengths and on a
   two-line sub that leaves a short orphan; pretty only protects the last line.
   58ch instead of 64 because the measure reads long under a centred headline. */
/* The eyebrow is where the caps belong: wide tracking at a small size reads as
   a label, and it is the same treatment the loader already uses for REVENUE
   CYCLE INTELLIGENCE, so the two screens rhyme. text-indent compensates for the
   trailing letter-space, which otherwise pushes centred tracked caps left. */
.kicker-lead{font-family:var(--disp);font-weight:600;font-size:clamp(10px,.82vw,12px);letter-spacing:.32em;text-indent:.32em;
  text-transform:uppercase;color:var(--accent);margin:clamp(12px,1.6vh,18px) auto 0;opacity:.92}
/* Arabic has no case, so the label reads through tracking and weight alone. */
[lang=ar] .kicker-lead{letter-spacing:.14em;text-indent:.14em;text-transform:none;font-size:clamp(11px,.9vw,13px);font-weight:500}
/* A mixed colour, not opacity on --text: opacity fades the glyphs toward the
   background and greys the whole line, while color-mix keeps them solid and
   tints them toward the accent so the block reads as one family. */
.headline p{color:color-mix(in srgb, var(--text) 74%, var(--accent));font-size:clamp(15px,1.35vw,20px);margin:clamp(10px,1.6vh,18px) auto 0;max-width:46ch;line-height:1.55;letter-spacing:.004em;text-wrap:pretty}
[lang=ar] .headline p{line-height:1.8;font-size:clamp(15.5px,1.4vw,21px);letter-spacing:0;max-width:44ch}
/* Scale the headline down before dropping anything, and only hide the sub when
   the ring genuinely cannot afford its ~64px. The old threshold was 980px,
   which hid the positioning line on virtually every laptop — most visitors
   never saw it. The ring needs ~440px of constellation height; with the sub
   present that lands at about 760px of viewport. */
@media (max-height:900px){.headline h1{font-size:clamp(24px,2.9vw,40px)}.headline p{font-size:clamp(14px,1.1vw,16.5px);margin-top:clamp(8px,1.1vh,12px)}}
/* These thresholds were set when the sub-line was two wrapped rows costing
   ~64px. The kicker replaced it and costs ~30px — one 12px line plus its
   margin — so it survives much further down. It is also the only place the
   product is named as Saudi, which is worth more than the pixels. */
@media (max-height:760px){.headline h1{font-size:clamp(20px,2.2vw,30px)}.headline{padding-top:10px;padding-bottom:6px}}
@media (max-height:560px){.kicker-lead{display:none}}
#hub.compact-header .headline h1{font-size:clamp(18px,1.8vw,26px)}
#hub.compact-header .kicker-lead{margin-top:clamp(6px,1vh,10px);font-size:clamp(9.5px,.75vw,11px)}

.constellation{position:absolute;inset:64px 0 0 0}
.nodes{position:absolute;inset:0;pointer-events:none}
.nodes .node{pointer-events:auto}
#links{position:absolute;inset:0;pointer-events:none;z-index:3}
.conn{stroke:var(--line);stroke-width:1;fill:none;transition:stroke .4s, stroke-width .4s}
.pulse{fill:var(--pulse);filter:drop-shadow(0 0 4px var(--pulse)) drop-shadow(0 0 12px var(--b-2))}
.pulse.fast{display:none;r:2.6}
.link.lit .pulse.fast{display:block}
.cdot{fill:var(--line-dot);opacity:.9;transition:fill .4s}
.port{fill:var(--core);filter:drop-shadow(0 0 4px var(--core)) drop-shadow(0 0 12px var(--b-2));transition:fill .4s}
[data-theme=light] .port{fill:var(--b-deep);filter:drop-shadow(0 0 4px rgba(58,92,251,.5))}
.link{transition:opacity .3s ease}
#links.focus-mode .link:not(.lit){opacity:.22}
.link.lit .conn{stroke:var(--nc);stroke-width:1.4;filter:drop-shadow(0 0 3px var(--nc))}
.link.lit .cdot,.link.lit .port{fill:var(--nc)}
.cycseg{fill:none;stroke:var(--b-3);stroke-width:1.5;stroke-linecap:round;opacity:0;
  filter:drop-shadow(0 0 5px var(--glow-a));transition:stroke-dashoffset 1.1s cubic-bezier(.5,.1,.3,1), opacity .5s ease}
.cycseg.on{opacity:.26}
.cycseg.on.cur{opacity:.95;stroke:var(--b-light)}
[data-theme=light] .cycseg.on.cur{stroke:var(--b-deep)}
.segdot{fill:var(--pulse);opacity:0;filter:drop-shadow(0 0 4px var(--pulse)) drop-shadow(0 0 9px var(--b-light));transition:opacity .3s}

/* brain */
.brainwrap{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:4;
  width:clamp(280px,min(43vmin,40vh),640px);height:clamp(280px,min(43vmin,40vh),640px);display:grid;place-items:center}
@property --hx{syntax:'<percentage>';inherits:false;initial-value:50%}
@property --hy{syntax:'<percentage>';inherits:false;initial-value:47%}
.brainhalo{position:absolute;inset:-10%;border-radius:50%;--hx:50%;--hy:47%;
  background:radial-gradient(circle at var(--hx) var(--hy), var(--halo-1) 0%, var(--halo-2) 24%, var(--halo-3) 52%, transparent 70%);
  filter:blur(12px) saturate(140%);animation:breathe 7s ease-in-out infinite}
.brainsvg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.bbody{fill:var(--brain-fill);opacity:var(--brain-fill-a)}
.bbody2{fill:var(--brain-fill2);opacity:var(--brain-fill2-a)}
/* Lit from inside, then glazed on top: the core sits under the constellation so
   the stars read against a warm centre, the specular sits above the fills so it
   behaves like a reflection rather than another tint. */
.bcore{mix-blend-mode:screen;pointer-events:none}
.bspec{pointer-events:none}
/* The rim is what makes glass read as glass: a hard bright edge with light
   bleeding off it, not a faint outline. Two shadows — a tight one for the edge
   itself and a wide one for the bloom around it. */
.boutline{fill:none;stroke:var(--brain-line);stroke-width:2.2;opacity:1;
  filter:drop-shadow(0 0 2px var(--core)) drop-shadow(0 0 9px var(--glow-a)) drop-shadow(0 0 26px var(--glow-b))}
.brainglass{position:absolute;left:0;top:0;width:512px;height:512px;transform-origin:0 0;pointer-events:none;
  background:linear-gradient(155deg, var(--glass-1) 0%, var(--glass-2) 55%, var(--glass-3) 100%);
  /* --glass-sat is 200% in both themes, which is what this always was. It is a
     token only so the two themes CAN diverge: the filter acts on the background
     starfield showing through the glass, so lowering it in one theme is the
     lever for the blue blobs that appear behind the hemispheres if the glass is
     ever made more transparent. Changing the glass opacity without this is what
     made them visible once already. */
  backdrop-filter:blur(18px) saturate(var(--glass-sat)) brightness(var(--glass-bright));-webkit-backdrop-filter:blur(18px) saturate(var(--glass-sat)) brightness(var(--glass-bright))}
/* the emblem: a crisp mark resting in the brain's centre, framed by a soft disc + the tech ring */
/* nucleus: the point every capability connects to — a core, not a logo */
.nucleus{position:absolute;inset:0;margin:auto;width:8px;height:8px;border-radius:50%;background:var(--core);
  box-shadow:0 0 4px var(--core), 0 0 14px var(--core), 0 0 34px var(--glow-a), 0 0 64px var(--glow-b);pointer-events:none;transition:background .3s, box-shadow .3s}
/* z-index:-1 puts the three rings BEHIND the brain instead of drawn across it.
   .nucleus has no stacking context of its own, so these negative-z pseudos join
   .brainwrap's context and paint before every positioned sibling — the body,
   the glass and the constellation canvas all land on top. The payoff is that
   .brainglass's backdrop-filter now blurs them: they read as depth under frosted
   glass rather than as hairlines ruled over the stars. The nucleus dot itself
   keeps auto z-index and stays the brightest thing on screen. */
.nucleus::before,.nucleus::after{content:"";position:absolute;inset:-22px;border-radius:50%;border:1px solid var(--ring-line);opacity:.55}
/* The inner ring stays IN FRONT, the outer two go behind. One crisp edge at the
   centre holds the eye and gives the frosted layers something to be measured
   against; three of them ruled across the stars was the noise. Depth needs one
   element on each side of the glass, not all of them on one. */
.nucleus::after{inset:-46px;border-style:dashed;opacity:.35;z-index:-1;animation:spin 40s linear infinite}
#hub.focus-mode .nucleus{background:var(--fc,var(--core));box-shadow:0 0 6px var(--fc,var(--core)), 0 0 16px var(--fc,var(--glow-a))}
.bcanvas{position:absolute;inset:0;width:100%;height:100%}
.techring{position:absolute;inset:0;margin:auto;border-radius:50%;width:34%;height:34%;border:1px dashed var(--ring-line);opacity:.4;z-index:-1;animation:spin 60s linear infinite}
@keyframes breathe{0%,100%{opacity:.85;transform:scale(1)}50%{opacity:1;transform:scale(1.03)}}


/* nodes */
.node{position:absolute;z-index:7;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:12px;
  background:none;border:0;padding:0;text-align:center;width:max-content;transition:transform .35s cubic-bezier(.2,.7,.2,1);opacity:0}
#hub.active .node{opacity:1;transition:transform .35s cubic-bezier(.2,.7,.2,1), opacity .6s ease var(--node-delay,0s)}
#hub.settled .node{transition:transform .3s cubic-bezier(.2,.7,.2,1), opacity .3s ease}
#hub.focus-mode .node:not(.focus){opacity:.52}
.node .ring{width:clamp(62px,7vmin,104px);height:clamp(62px,7vmin,104px);border-radius:50%;display:grid;place-items:center;position:relative;
  /* at rest the ring is only a hint — the mark is itself an object, and a second
     container around it was competing with it for the eye */
  background:radial-gradient(125% 120% at 50% 116%, color-mix(in srgb, var(--nc,var(--accent)) 26%, transparent), transparent 72%);
  border:1px solid color-mix(in srgb, var(--nc,var(--accent)) 42%, transparent);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--nc,var(--accent)) 10%, transparent), 0 0 22px color-mix(in srgb, var(--nc,var(--accent)) 18%, transparent);
  transition:border-color .3s, box-shadow .3s, background .3s, transform .35s cubic-bezier(.2,.7,.2,1)}
/* orbiting arc that appears on hover / focus */
.node .ring::before{content:"";position:absolute;inset:-7px;border-radius:50%;opacity:0;transition:opacity .35s;
  background:conic-gradient(from 0deg, transparent 0 68%, var(--nc,var(--accent)) 86%, transparent 100%);
  -webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));mask:radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  animation:spin 3.4s linear infinite}
.node:hover .ring::before,.node:focus-visible .ring::before,.node.focus .ring::before{opacity:.85}
/* Focus lights the ring rather than merely tinting its border. */
.node:hover .ring,.node.focus .ring{border-color:color-mix(in srgb, var(--nc,var(--accent)) 80%, transparent);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--nc,var(--accent)) 30%, transparent), 0 0 40px color-mix(in srgb, var(--nc,var(--accent)) 38%, transparent)}
.node .ring svg{width:64%;height:64%;overflow:visible;
  filter:var(--mark-lift) var(--mark-sh);transition:filter .3s, transform .35s cubic-bezier(.2,.7,.2,1)}
.node .num{position:absolute;top:-5px;inset-inline-end:-5px;width:23px;height:23px;border-radius:50%;background:var(--nc,var(--b-2));color:#fff;
  font:700 11.5px/23px var(--disp);text-align:center;box-shadow:0 0 10px var(--nc,var(--b-2));opacity:0;transform:scale(.5);transition:opacity .35s, transform .35s cubic-bezier(.2,.7,.2,1)}
#hub.cycle-mode .node .num{opacity:1;transform:none}
.node .lab{font-family:var(--disp);font-weight:700;text-transform:uppercase;letter-spacing:.1em;font-size:clamp(13.5px,1.4vw,21px);color:var(--text);
  text-shadow:var(--shadow-text);max-width:11ch;line-height:1.2;transition:color .3s, letter-spacing .35s, transform .35s}
[lang=ar] .node .lab{text-transform:none;letter-spacing:0;max-width:14ch;font-weight:700;line-height:1.45;font-size:clamp(14.5px,1.5vw,22.5px)}
.node:hover,.node:focus-visible{transform:translate(-50%,-50%) scale(1.04)}
/* emphasis is hue and glow — never a lens body, which competed with the mark */
.node:hover .ring,.node:focus-visible .ring,.node.focus .ring{
  border-color:color-mix(in srgb, var(--nc,var(--accent)) 70%, transparent);
  background:radial-gradient(125% 120% at 50% 116%, color-mix(in srgb, var(--nc,var(--accent)) 34%, transparent), transparent 70%);
  box-shadow:0 0 18px color-mix(in srgb, var(--nc,var(--accent)) 30%, transparent)}
[data-theme=light] .node:hover .ring,[data-theme=light] .node:focus-visible .ring,[data-theme=light] .node.focus .ring{
  border-color:color-mix(in srgb, var(--nc,var(--accent)) 60%, transparent);
  box-shadow:0 6px 18px rgba(58,84,160,.14), 0 0 14px color-mix(in srgb, var(--nc,var(--accent)) 20%, transparent)}
.node:hover .ring svg,.node:focus-visible .ring svg,.node.focus .ring svg{transform:scale(1.05) translateY(-1px);
  filter:var(--mark-lift) var(--mark-sh-hi)}
.node:hover .lab,.node.focus .lab{color:var(--h1);letter-spacing:.115em}
[lang=ar] .node:hover .lab,[lang=ar] .node.focus .lab{letter-spacing:0;transform:translateY(-1px)}
.node.focus{transform:translate(-50%,-50%) scale(1.04)}

/* caption bar */
.caption{position:absolute;left:50%;bottom:clamp(14px,2.6vh,40px);transform:translateX(-50%);z-index:8;--fc:var(--accent);
  display:flex;align-items:center;gap:14px;white-space:nowrap;max-width:min(94vw,1040px);
  padding:9px 16px 9px 12px;border-radius:999px;background:var(--panel);border:1px solid var(--panel-line);
  backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
  box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2);
  font-family:var(--disp);color:var(--text);opacity:0;overflow:hidden;
  transition:opacity .8s ease 1.6s, border-color .35s, box-shadow .35s, background .5s}
#hub.active .caption{opacity:1}
#hub.settled .caption{transition:opacity .4s ease, border-color .35s, box-shadow .35s, background .5s}
.caption.live{border-color:color-mix(in srgb, var(--fc) 45%, transparent);box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2), 0 0 22px color-mix(in srgb, var(--fc) 16%, transparent), 0 10px 40px rgba(2,4,12,.2)}
.cap-idle,.cap-live{display:flex;align-items:center;gap:14px;min-width:0}
.caption.live .cap-idle{display:none}.caption:not(.live) .cap-live{display:none}
.cap-idle{padding-inline-start:6px;font-weight:600;font-size:clamp(13.5px,1.15vw,17px);letter-spacing:.02em}
[lang=ar] .cap-idle{letter-spacing:0;font-size:clamp(14.5px,1.2vw,18px)}
[lang=ar] .cap-text b{font-size:clamp(15px,1.25vw,19px)}
[lang=ar] .cap-text span{font-size:clamp(13px,1.05vw,15.5px)}
[lang=ar] .kbd{font-size:clamp(12px,.95vw,14px)}
[lang=ar] .cap-btn{font-size:13.5px}
.caption .dot{width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 12px var(--accent);animation:blink 2.4s ease-in-out infinite;flex:0 0 auto}
@keyframes blink{0%,100%{opacity:.35}50%{opacity:1}}
.kbd{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-weight:500;font-size:clamp(11px,.9vw,13px)}
.kbd b{font:600 11px/1 var(--disp);color:var(--accent);padding:4px 7px;border-radius:6px;background:var(--chip);border:1px solid var(--chip-line);letter-spacing:.02em}
.cap-sep{width:1px;height:22px;background:var(--panel-line);flex:0 0 auto}
.cap-btn{background:var(--chip);border:1px solid var(--chip-line);border-radius:999px;padding:7px 14px;font:600 12.5px var(--disp);color:var(--accent);letter-spacing:.02em;transition:background .25s,border-color .25s}
.cap-btn:hover{background:color-mix(in srgb, var(--accent) 16%, transparent);border-color:var(--accent)}
.cap-ic{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  background:radial-gradient(125% 120% at 50% 116%, color-mix(in srgb, var(--fc) 22%, transparent), transparent 70%);
  border:1px solid color-mix(in srgb, var(--fc) 45%, transparent);
  box-shadow:0 0 14px color-mix(in srgb, var(--fc) 22%, transparent)}
.cap-ic svg{width:25px;height:25px;overflow:visible}
.cap-text{display:flex;flex-direction:column;gap:2px;min-width:0}
.cap-text b{font-weight:700;font-size:clamp(14px,1.2vw,18px);letter-spacing:-.005em;color:var(--h1)}
.cap-text span{font-family:var(--body);font-weight:450;font-size:clamp(12px,1vw,14.5px);color:var(--accent);opacity:.9;max-width:44ch;overflow:hidden;text-overflow:ellipsis}
.cap-metric{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.cap-metric b{font-weight:700;font-size:clamp(20px,1.9vw,30px);letter-spacing:-.02em;line-height:1;direction:ltr;
  background:linear-gradient(180deg,var(--h1),var(--fc));-webkit-background-clip:text;background-clip:text;color:transparent}
.cap-metric small{font-family:var(--body);font-size:clamp(11px,.9vw,13px);color:var(--muted);white-space:nowrap;line-height:1.2}
.cap-idx{color:var(--muted);font-weight:600;font-size:clamp(11px,.9vw,13px);letter-spacing:.06em;flex:0 0 auto}
[lang=ar] .cap-idx{letter-spacing:0}
.caption.swap .cap-live{animation:capin .4s cubic-bezier(.2,.7,.2,1)}
@keyframes capin{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
/* cycle controls + progress inside the caption */
.cap-ctl{display:none;align-items:center;gap:4px;flex:0 0 auto}
.caption.cyc .cap-ctl{display:inline-flex}
.caption.cyc .cap-open{display:none}
.cbtn{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;background:var(--chip);border:1px solid var(--chip-line);transition:border-color .2s,background .2s}
.cbtn:hover{border-color:var(--accent)}
.cbtn svg{width:14px;height:14px;fill:var(--accent);stroke:none}
[dir=rtl] .cbtn svg.flip{transform:scaleX(-1)}
.cap-rail{display:none;gap:5px;align-items:center;flex:0 0 auto}
.caption.cyc .cap-rail{display:inline-flex}
.cap-rail i{width:6px;height:6px;border-radius:3px;background:var(--panel-line);transition:width .35s, background .35s}
.cap-rail i.done{background:color-mix(in srgb, var(--fc) 45%, transparent)}
.cap-rail i.cur{width:18px;background:var(--fc);box-shadow:0 0 8px var(--fc)}
.cap-prog{position:absolute;inset-inline-start:0;bottom:0;height:2px;width:0;background:linear-gradient(90deg,var(--fc),var(--core));opacity:0}
[dir=rtl] .cap-prog{background:linear-gradient(270deg,var(--fc),var(--core))}
/* ===== QR dialog — scan to open this experience / book a demo on your own phone.
   Summoned on demand from the launcher tile instead of floating on screen, so
   it never competes with the caption bar or (on phones, where scanning your
   own screen makes no sense anyway) anything else. ===== */
.how.qr .how-card{width:min(90vw,300px);text-align:center}
.qr-badge-code{width:180px;height:180px;margin:18px auto 0;border-radius:14px;background:#fff;padding:14px;display:grid;place-items:center;overflow:hidden}
.qr-badge-code img,.qr-badge-code canvas,.qr-badge-code table{width:100%!important;height:100%!important}
.caption.cyc .cap-prog{opacity:.9}
@media (max-width:1100px){.cap-text span{display:none}}
@media (max-width:900px){.kbd,.cap-idx,.cap-rail{display:none!important}}
body.nocursor,body.nocursor *{cursor:none!important}
/* how-it-works overlay (orchestration architecture) */
.how{position:absolute;inset:0;z-index:15;display:grid;place-items:safe center;padding:clamp(76px,16vh,190px) 20px 20px;background:rgba(3,4,16,.5);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .25s, visibility 0s linear .25s}
[data-theme=light] .how{background:rgba(240,244,255,.6)}
.how.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .25s, visibility 0s}
/* max-height:100%, not 94vh. The grid area is the viewport MINUS .how's top
   padding (up to 190px to clear the header), so a 94vh card was always taller
   than the box holding it. With place-items:center a too-tall item overflows
   equally top and bottom, and the overflowing top is unreachable — the card
   scrolled internally while its own head and foot sat outside the screen.
   100% resolves against the padded area, so the card always fits and its own
   overflow:auto does the scrolling. `safe center` is the second guard: it falls
   back to start alignment whenever centring would push content out of view. */
.how-card{position:relative;width:min(96vw,1180px);max-height:100%;overflow:auto;padding:28px 32px 20px;border-radius:24px;background:var(--panel);border:1px solid var(--panel-line);box-shadow:0 30px 90px rgba(2,4,12,.4);transform:translateY(8px);transition:transform .3s cubic-bezier(.2,.7,.2,1)}
.how-card>h3{padding-inline-end:40px}
.dialog-close{position:absolute;top:20px;inset-inline-end:20px;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  background:var(--chip);border:1px solid var(--chip-line);z-index:2;transition:border-color .2s,background .2s}
.dialog-close:hover{border-color:var(--accent)}
.dialog-close svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:2;stroke-linecap:round}
.dialog-close:hover svg{stroke:var(--accent)}
.how.show .how-card{transform:none}
.how h3{margin:0 0 8px;font:700 clamp(18px,1.6vw,26px) var(--disp);color:var(--h1);letter-spacing:-.01em}
.how-sub{margin:0 0 20px;color:var(--muted);font-size:clamp(13px,1.02vw,15.5px);line-height:1.55;max-width:96ch}
[lang=ar] .how-sub{line-height:1.85}
.arch{display:grid;gap:10px}
.arch-row{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.arch-row .a-chip{padding:8px 14px;border-radius:999px;background:var(--chip);border:1px solid var(--chip-line);font:600 12.5px var(--disp);color:var(--text)}
.arch-row.dst .a-chip{border-color:color-mix(in srgb, var(--accent) 45%, transparent);color:var(--accent)}
.arch-arrow{height:22px;position:relative}
.arch-arrow::before{content:"";position:absolute;left:50%;top:0;bottom:6px;width:1px;background:var(--accent);opacity:.6}
.arch-arrow::after{content:"";position:absolute;left:50%;bottom:0;width:7px;height:7px;border-right:1px solid var(--accent);border-bottom:1px solid var(--accent);transform:translateX(-50%) rotate(45deg);opacity:.8}
.arch-arrow .flow{position:absolute;left:50%;top:0;width:5px;height:5px;margin-left:-2.5px;border-radius:50%;background:var(--core);box-shadow:0 0 8px 2px var(--accent);animation:archFlow 2.4s ease-in-out infinite}
.arch-arrow:nth-of-type(4) .flow{animation-delay:1.2s}
@keyframes archFlow{0%{top:0;opacity:0}14%{opacity:1}82%{opacity:1}100%{top:16px;opacity:0}}
.arch-core{padding:16px;border-radius:18px;border:1px solid color-mix(in srgb, var(--accent) 50%, transparent);background:linear-gradient(160deg, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%);box-shadow:0 0 30px color-mix(in srgb, var(--accent) 14%, transparent);animation:coreGlow 3.6s ease-in-out infinite}
@keyframes coreGlow{0%,100%{box-shadow:0 0 30px color-mix(in srgb, var(--accent) 14%, transparent)}50%{box-shadow:0 0 46px color-mix(in srgb, var(--accent) 26%, transparent)}}
.core-title{font:700 clamp(13px,1.05vw,15.5px) var(--disp);color:var(--h1);text-align:center;margin-bottom:14px;letter-spacing:.02em}
/* Flow strip: the whole data path on one line, so the pillars below get the
   panel's vertical room instead of competing with two chip rows and two arrows. */
/* Both ends exchange WITH the engine, so the strip carries traffic in both
   directions: Cycles reads the HIS and writes corrections back into it, and it
   sends to NPHIES and takes the response. A single arrow told half the story.
   Each end also lists what actually crosses, which the two bare labels did not. */
.arch-flow{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;margin:0 0 22px}
.a-end{flex:0 1 auto;min-width:0;padding:11px 16px;border-radius:14px;background:var(--chip);border:1px solid var(--chip-line);text-align:start}
.a-end b{display:block;font:700 12.5px var(--disp);color:var(--h1);margin-bottom:5px}
.a-end ul{margin:0;padding:0;list-style:none;display:grid;gap:2px}
.a-end li{font:500 11.5px var(--disp);color:var(--muted);line-height:1.45;position:relative;padding-inline-start:11px}
.a-end li::before{content:"";position:absolute;inset-inline-start:0;top:.58em;width:3px;height:3px;border-radius:50%;background:color-mix(in srgb, var(--accent) 70%, transparent)}
.a-hub{flex:0 0 auto;padding:11px 18px;border-radius:999px;font:700 13px var(--disp);white-space:nowrap;
  background:color-mix(in srgb, var(--accent) 16%, transparent);border:1px solid color-mix(in srgb, var(--accent) 55%, transparent);color:var(--accent);
  box-shadow:0 0 24px color-mix(in srgb, var(--accent) 18%, transparent)}
/* Two hairlines, one per direction, each with its own travelling dot. */
.a-link{position:relative;width:52px;height:9px;flex:0 0 auto}
/* z-index matters here: ::after paints after the element's own children, so the
   lower rail was drawn ON TOP of its travelling dot while the upper rail (a
   ::before) was drawn under it. One dot in front, one behind, from paint order
   alone. Rails behind, dots in front, explicitly. */
.a-link::before,.a-link::after{content:"";position:absolute;left:0;right:0;height:1px;z-index:0;background:color-mix(in srgb, var(--accent) 42%, transparent)}
.a-link::before{top:1px}.a-link::after{bottom:1px}
.a-link i{position:absolute;z-index:1;width:5px;height:5px;border-radius:50%;background:var(--core);box-shadow:0 0 8px 2px var(--accent)}
/* Both dots are anchored left and moved by transform only. The lower one used
   `right:0`, which resolves against the opposite edge and put it off the line
   in one direction. Anchoring both the same way makes the two rails behave
   identically whichever way the page reads. */
.a-link i.fwd{top:-2px;left:0;animation:aFwd 2.6s ease-in-out infinite}
.a-link i.bwd{bottom:-2px;left:47px;animation:aBwd 2.6s ease-in-out infinite;animation-delay:1.3s}
@keyframes aFwd{0%{transform:translateX(0);opacity:0}15%{opacity:1}85%{opacity:1}100%{transform:translateX(47px);opacity:0}}
@keyframes aBwd{0%{transform:translateX(0);opacity:0}15%{opacity:1}85%{opacity:1}100%{transform:translateX(-47px);opacity:0}}
/* ===== agents taxonomy ===== */
.tax{margin-top:22px;padding-top:18px;border-top:1px solid var(--panel-line)}
.tax-t{margin:0 0 12px;font:700 13.5px var(--disp);color:var(--h1)}
.tax-t em{display:block;font-style:normal;font-weight:500;font-size:12px;color:var(--muted);margin-top:3px;line-height:1.5}
.tax-list{display:grid;gap:6px}
.tax-item{border:1px solid var(--panel-line);border-radius:12px;background:var(--panel);overflow:hidden}
.tax-item[open]{border-color:color-mix(in srgb, var(--accent) 45%, transparent)}
.tax-item summary{display:flex;align-items:center;gap:10px;padding:10px 13px;cursor:pointer;list-style:none;font:600 12.5px var(--disp);color:var(--h1)}
.tax-item summary::-webkit-details-marker{display:none}
.tax-item summary::after{content:"";margin-inline-start:auto;width:7px;height:7px;flex:0 0 auto;
  border-right:1.6px solid var(--accent);border-bottom:1.6px solid var(--accent);transform:rotate(45deg) translateY(-2px);transition:transform .2s}
.tax-item[open] summary::after{transform:rotate(225deg) translateY(-2px)}
.tax-code{flex:0 0 auto;padding:3px 7px;border-radius:6px;background:color-mix(in srgb, var(--accent) 14%, transparent);
  color:var(--accent);font:700 10.5px var(--disp);letter-spacing:.04em}
.tax-dom{flex:0 0 auto;font-weight:500;font-size:11.5px;color:var(--muted)}
.tax-body{padding:0 13px 13px;display:grid;gap:9px}
.tax-obj{font-size:12.5px;color:var(--text);line-height:1.6;margin:0}
.tax-io{display:grid;grid-template-columns:1fr 1fr;gap:9px}
@media (max-width:640px){.tax-io{grid-template-columns:1fr}.tax-dom{display:none}}
.tax-io h5{margin:0 0 4px;font:600 10.5px var(--disp);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.tax-io ul{margin:0;padding:0;list-style:none;display:grid;gap:2px}
.tax-io li{font-size:11.5px;color:var(--muted);line-height:1.5;padding-inline-start:10px;position:relative}
.tax-io li::before{content:"";position:absolute;inset-inline-start:0;top:.55em;width:3px;height:3px;border-radius:50%;background:color-mix(in srgb, var(--accent) 65%, transparent)}
.tax-std{font-size:11px;color:var(--muted);padding-top:7px;border-top:1px dashed var(--panel-line)}
.tax-std b{color:color-mix(in srgb, var(--accent) 80%, transparent);font-weight:600}
/* 2x2, not 1x4: at four across, each pillar was a 150px column and the body
   text broke every three words. Two columns give the sentences a real measure. */
.core-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;counter-reset:pillar}
.core-box::before{content:counter(pillar,decimal-leading-zero);position:absolute;top:13px;inset-inline-end:14px;
  font:700 11px var(--disp);color:color-mix(in srgb, var(--accent) 60%, transparent);letter-spacing:.06em}
.core-box em{display:block;font-style:normal;font-weight:600;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:color-mix(in srgb, var(--accent) 75%, transparent);margin:-2px 0 7px}
@media (max-width:1000px){.core-grid{grid-template-columns:1fr}}
.core-box{position:relative;counter-increment:pillar;padding:14px 14px 12px;border-radius:14px;background:var(--panel);border:1px solid var(--panel-line);animation:coreBoxLit 4.8s ease-in-out infinite;animation-delay:calc(var(--i,0) * .5s)}
@keyframes coreBoxLit{0%,78%,100%{border-color:var(--panel-line);box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2)}86%{border-color:var(--accent);box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2), 0 0 18px color-mix(in srgb, var(--accent) 30%, transparent)}}
.core-box b{padding-inline-end:28px;display:flex;align-items:center;gap:8px;font:700 clamp(13px,1.02vw,15px) var(--disp);color:var(--h1);margin-bottom:6px}
.core-box b svg{width:18px;height:18px;stroke:var(--accent);fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex:0 0 auto}
.core-box.agent b svg{fill:var(--accent);stroke:none}
.core-box>span{font-size:clamp(12px,.92vw,13.5px);color:var(--muted);line-height:1.5}
[lang=ar] .core-box>span{line-height:1.8}
.core-box b span{flex:1;min-width:0}
.how-foot{margin:16px 0 0;color:var(--faint);font-size:12.5px;text-align:center}
.how.next .how-card{width:min(96vw,900px)}
/* Six phases now, so three across reads as two rows of three rather than
   one long row of tiny columns. */
/* ===== onboarding roadmap =====
   A rail with numbered nodes, not six loose tiles. The line running behind the
   nodes is what makes it read as a sequence at a glance; the gate breaks it,
   which is the whole point of the screen. */
.road{margin-top:22px;text-align:start}
.road-head{display:flex;align-items:center;gap:10px;margin:0 0 14px}
.road-head b{font:700 12px var(--disp);letter-spacing:.06em;color:var(--h1)}
.road-head span{font:600 10px var(--disp);letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb, var(--accent) 70%, transparent)}
.road-head::after{content:"";flex:1;height:1px;background:var(--panel-line)}
/* The rail: one hairline behind the node badges, clipped to the row. */
.road-row{position:relative;display:grid;grid-template-columns:repeat(3,1fr);gap:14px;padding-top:15px}
.road-row::before{content:"";position:absolute;top:15px;inset-inline:14%;height:1px;background:linear-gradient(to right,transparent,color-mix(in srgb, var(--accent) 40%, transparent) 12%,color-mix(in srgb, var(--accent) 40%, transparent) 88%,transparent)}
@media (max-width:900px){.road-row{grid-template-columns:1fr}.road-row::before{display:none}}
.road-step{position:relative;padding:26px 18px 16px;border-radius:16px;background:var(--panel);border:1px solid var(--panel-line);
  transition:border-color .2s, transform .2s}
.road-step:hover{border-color:color-mix(in srgb, var(--accent) 45%, transparent);transform:translateY(-2px)}
/* Node badge sits ON the rail, centred on the card's top edge. */
.road-step .rs-n{position:absolute;top:-15px;inset-inline-start:18px;width:30px;height:30px;border-radius:50%;
  display:grid;place-items:center;font:700 11.5px var(--disp);color:var(--accent);
  background:var(--panel);border:1px solid color-mix(in srgb, var(--accent) 45%, transparent)}
.road-step:hover .rs-n{background:var(--accent);color:#fff;border-color:var(--accent)}
.road-step b{display:block;font:700 13.5px var(--disp);color:var(--h1);margin:0 0 2px}
.road-step em{display:block;font-style:normal;font:600 10px var(--disp);letter-spacing:.1em;text-transform:uppercase;
  color:color-mix(in srgb, var(--accent) 68%, transparent);margin:0 0 9px}
.road-step p{margin:0 0 12px;font-size:12.5px;line-height:1.6;color:var(--muted)}
.road-step .rs-w{display:inline-block;padding:4px 11px;border-radius:999px;background:var(--chip);
  border:1px solid var(--chip-line);font:600 11px var(--disp);color:var(--text)}
/* The gate. Full-bleed accent band with a hard left edge — the one element on
   the screen that is not a card, so the eye cannot read past it unregistered. */
.road-gate{position:relative;display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:26px 0;padding:16px 20px;
  border-radius:14px;border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  background:linear-gradient(90deg, color-mix(in srgb, var(--accent) 18%, transparent), color-mix(in srgb, var(--accent) 6%, transparent));
  box-shadow:0 0 34px color-mix(in srgb, var(--accent) 14%, transparent)}
[dir=rtl] .road-gate{background:linear-gradient(270deg, color-mix(in srgb, var(--accent) 18%, transparent), color-mix(in srgb, var(--accent) 6%, transparent))}
.road-gate .g-day{flex:0 0 auto;padding:7px 14px;border-radius:999px;background:var(--accent);color:#fff;
  font:700 11.5px var(--disp);letter-spacing:.05em;box-shadow:0 6px 18px color-mix(in srgb, var(--accent) 38%, transparent)}
.road-gate .g-t{font:700 14px var(--disp);color:var(--h1)}
.road-gate .g-b{flex:1 1 240px;min-width:0;font-size:12.5px;line-height:1.55;color:var(--muted)}
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
@media (max-width:1040px){.steps{grid-template-columns:repeat(2,1fr)}}
@media (max-width:760px){.steps{grid-template-columns:1fr}}
.step{padding:16px;border-radius:16px;background:var(--panel);border:1px solid var(--panel-line);position:relative}
.step:not(:last-child)::after{content:"";position:absolute;top:31px;left:100%;width:14px;height:1px;background:var(--accent);opacity:.5}
[dir=rtl] .step:not(:last-child)::after{left:auto;right:100%}
@media (max-width:760px){.step:not(:last-child)::after{display:none}}
.step i{display:inline-grid;place-items:center;width:30px;height:30px;border-radius:50%;background:var(--accent);color:#fff;font:700 13px var(--disp);font-style:normal;margin-bottom:10px;animation:stepPulse 4.5s ease-in-out infinite;animation-delay:calc(var(--i,0) * 1.1s)}
@keyframes stepPulse{0%,18%,100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent)}9%{box-shadow:0 0 0 6px color-mix(in srgb, var(--accent) 24%, transparent)}}
.step b{display:block;font:700 clamp(14px,1.05vw,16px) var(--disp);color:var(--h1);margin-bottom:6px}
.step span{display:block;color:var(--muted);font-size:clamp(12.5px,.95vw,14px);line-height:1.5}
[lang=ar] .step span{line-height:1.8}
.step small{display:inline-block;margin-top:10px;padding:4px 10px;border-radius:999px;background:var(--chip);border:1px solid var(--chip-line);color:var(--accent);font:600 11.5px var(--disp)}
/* gap + wrap: this row can hold two buttons (book + live demo) and had neither,
   so on a narrow screen they touched and then overflowed the panel. */
.next-cta{display:flex;justify-content:center;flex-wrap:wrap;gap:10px;margin-top:20px}
.next-cta[hidden]{display:none}
.turnstile-wrap{display:flex;justify-content:center;margin-top:16px}
.turnstile-wrap[hidden]{display:none}
.book-err{color:var(--bad)}
.cta.big{height:46px;padding:0 26px;font-size:14.5px;border-radius:12px}
.cta.big:disabled{opacity:.6;pointer-events:none}
/* ===== About Cycles (article) ===== */
.how.faq .how-card{width:min(96vw,880px)}
.how.faq h3{display:flex;align-items:center;gap:10px}
.how.faq h3 .ai-ic{width:20px;height:20px;fill:var(--accent);flex:0 0 auto;animation:aiTwinkle 2.4s ease-in-out infinite}
.about{margin-top:20px;max-height:60vh;overflow-y:auto;padding-inline-end:8px;
  /* The article is long enough to scroll; fade the bottom edge so a cut-off
     paragraph reads as "more below" rather than as clipped text. JS drops the
     mask once the reader reaches the end (and when it doesn't overflow). */
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 36px),transparent);
  mask-image:linear-gradient(to bottom,#000 calc(100% - 36px),transparent)}
.about.at-end{-webkit-mask-image:none;mask-image:none}
.about-lede{margin:0 0 30px;padding-inline-start:16px;border-inline-start:2px solid var(--accent);
  font:500 clamp(14.5px,1.22vw,17.5px)/1.62 var(--disp);color:var(--h1);max-width:68ch}
[lang=ar] .about-lede{line-height:1.95}
.about section{margin:0 0 24px;max-width:72ch}
.about section:last-of-type{margin-bottom:0}
.about h4{margin:0 0 8px;display:flex;align-items:center;gap:9px;letter-spacing:-.005em;
  font:700 clamp(14px,1.1vw,16.5px) var(--disp);color:var(--h1)}
.about h4::before{content:"";flex:0 0 auto;width:5px;height:5px;border-radius:50%;background:var(--accent);
  box-shadow:0 0 8px color-mix(in srgb, var(--accent) 60%, transparent)}
/* Scoped to `section` on purpose: a bare `.about p` (specificity 0,1,1) outranks
   `.about-lede` (0,1,0) and would silently zero the lede's bottom margin. */
.about section p{margin:0;color:var(--muted);font-size:clamp(13px,1.02vw,15px);line-height:1.68}
[lang=ar] .about section p{line-height:1.95}
.about-tags{display:flex;flex-wrap:wrap;gap:7px;margin-top:13px}
.about-tags span{padding:5px 11px;border-radius:999px;background:var(--chip);border:1px solid var(--chip-line);
  font:600 11.5px var(--disp);color:var(--accent)}
/* ===== book-a-demo form ===== */
.how.book .how-card{width:min(96vw,620px)}
.book-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 16px;margin-top:18px}
@media (max-width:600px){.book-grid{grid-template-columns:1fr}}
.book-field{display:flex;flex-direction:column;gap:6px;text-align:start;margin-bottom:10px}
.book-field[hidden]{display:none}
.book-field.full{grid-column:1/-1}
.book-field label{font:600 12.5px var(--disp);color:var(--muted);letter-spacing:.02em}
.book-field input,.book-field select{height:44px;padding:0 14px;border-radius:12px;background:var(--chip);border:1px solid var(--chip-line);color:var(--text);font:500 14px var(--body);width:100%;
  backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
  transition:border-color .2s,background .2s}
.book-field input::placeholder{color:var(--faint)}
.book-field input:focus,.book-field select:focus{outline:none;border-color:var(--accent);background:var(--panel)}
.book-field.invalid input,.book-field.invalid select{border-color:var(--bad)}
.book-field .err{font-size:11.5px;color:var(--bad);min-height:14px}
/* مكوّن رقم الهاتف: مفتاح الدولة يسار الحقل، منقول عن
   rcm.cycles.sa (src/components/phone-whatsapp-input.tsx) — اختيار المفتاح
   بعلمه يغني عن حقل "الدولة" المنفصل، ويجعل الرقم المُرسَل دولياً دائماً. */
.phone-country-row{display:grid;grid-template-columns:minmax(92px,110px) 1fr;gap:8px}
@media (max-width:600px){.phone-country-row{grid-template-columns:1fr}}
.phone-country-select{
  /* نفس ارتفاع وحدود بقية حقول النموذج — الشبكة تضعه في نفس الصف. */
  height:44px;padding:0 8px;border-radius:12px;background:var(--chip);
  border:1px solid var(--chip-line);color:var(--text);font:500 13.5px var(--body);
  backdrop-filter:blur(var(--panel-blur)) saturate(140%);
  -webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
  transition:border-color .2s,background .2s}
.phone-country-select:focus{outline:none;border-color:var(--accent);background:var(--panel)}
/* المفتاح والرقم لاتينيان دائماً، فيُقرآن من اليسار حتى في الواجهة العربية. */
.phone-country-row>input{direction:ltr;text-align:start}
[dir=rtl] .phone-country-row>input{text-align:left}
.book-success,.book-slots,.book-confirm{display:none;text-align:center;padding:8px 0 4px}
#book.sent .book-success{display:block}
#book.sent #bookForm{display:none}
#book.slots #bookForm{display:none}
#book.slots .book-slots{display:block}
#book.confirm #bookForm{display:none}
#book.confirm .book-confirm{display:block}
.book-success-ic{width:56px;height:56px;margin:0 auto 16px;border-radius:50%;background:color-mix(in srgb, var(--ok) 16%, transparent);border:1px solid color-mix(in srgb, var(--ok) 45%, transparent);display:grid;place-items:center}
.book-success-ic svg{width:26px;height:26px;stroke:var(--ok);fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.book-tz-hint{font-size:12px;color:var(--muted);margin:-8px 0 16px}
/* Slot picker: a day rail you swipe, then that day's times — instead of every
   day stacked as one long wall of identical chips, which made the dialog
   scroll for pages and gave no sense of "which day am I looking at". */
.slot-rail{position:relative;margin:0 0 18px}
.slot-days{display:flex;gap:8px;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  padding:2px 0 10px;scrollbar-width:none;-ms-overflow-style:none}
.slot-days::-webkit-scrollbar{display:none}
.slot-day-btn{flex:0 0 auto;scroll-snap-align:center;min-width:82px;padding:9px 14px;border-radius:14px;cursor:pointer;
  background:var(--chip);border:1px solid var(--chip-line);color:var(--muted);text-align:center;
  display:grid;gap:2px;transition:background .2s,border-color .2s,color .2s}
.slot-day-btn b{font:700 15px var(--disp);color:var(--ink);line-height:1.1}
.slot-day-btn span{font:600 11px var(--disp);letter-spacing:.04em}
.slot-day-btn em{font:600 10.5px var(--disp);font-style:normal;opacity:.75}
.slot-day-btn:hover{border-color:var(--accent)}
.slot-day-btn[aria-selected=true]{background:var(--accent);border-color:var(--accent);color:#fff}
.slot-day-btn[aria-selected=true] b{color:#fff}
/* Edge fades tell the eye the rail keeps going. Pointer-events off so they
   never swallow a tap on the first or last day. */
.slot-rail::before,.slot-rail::after{content:"";position:absolute;top:0;bottom:10px;width:28px;pointer-events:none;z-index:1}
.slot-rail::before{inset-inline-start:0;background:linear-gradient(to right,var(--panel) 20%,transparent)}
.slot-rail::after{inset-inline-end:0;background:linear-gradient(to left,var(--panel) 20%,transparent)}
[dir=rtl] .slot-rail::before{background:linear-gradient(to left,var(--panel) 20%,transparent)}
[dir=rtl] .slot-rail::after{background:linear-gradient(to right,var(--panel) 20%,transparent)}
.slot-times{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:8px}
.slot-btn{background:var(--chip);border:1px solid var(--chip-line);border-radius:12px;padding:10px 8px;font:600 13px var(--disp);color:var(--accent);cursor:pointer;transition:background .2s,border-color .2s,transform .15s}
.slot-btn:hover{background:color-mix(in srgb, var(--accent) 16%, transparent);border-color:var(--accent);transform:translateY(-1px)}
.slot-part{grid-column:1/-1;font:600 11px var(--disp);color:var(--muted);letter-spacing:.06em;text-transform:uppercase;margin:6px 0 -2px;text-align:start}
.slot-part:first-child{margin-top:0}
.book-confirm .how-sub{text-align:center}
.cta.ghost{background:transparent;color:var(--accent);box-shadow:none;border:1px solid var(--chip-line)}
.cta.ghost:hover{background:var(--chip);box-shadow:none;transform:none}
.book-confirm .next-cta{gap:10px}
/* shortcuts overlay */
.help{position:absolute;inset:0;z-index:15;display:grid;place-items:center;padding-top:clamp(64px,14vh,170px);background:rgba(3,4,16,.45);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .25s, visibility 0s linear .25s}
[data-theme=light] .help{background:rgba(240,244,255,.55)}
.help.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .25s, visibility 0s}
.help-card{position:relative;min-width:min(92vw,560px);max-width:92vw;max-height:88vh;overflow:auto;padding:26px 30px 22px;border-radius:22px;background:var(--panel);border:1px solid var(--panel-line);box-shadow:0 30px 80px rgba(2,4,12,.35);transform:translateY(8px);transition:transform .3s cubic-bezier(.2,.7,.2,1)}
.help-card>h3{padding-inline-end:40px}
.help.show .help-card{transform:none}
.help h3{margin:0 0 18px;font:700 clamp(17px,1.4vw,22px) var(--disp);color:var(--h1)}
.help-grid{display:grid;grid-template-columns:auto 1fr;gap:10px 18px;align-items:center}
.help-grid .k{display:inline-flex;gap:5px}
.help-grid .k b{font:600 12px/1 var(--disp);color:var(--accent);padding:6px 9px;border-radius:7px;background:var(--chip);border:1px solid var(--chip-line);min-width:30px;text-align:center}
.help-grid span{font-size:clamp(13px,1vw,15px);color:var(--text)}
.help-foot{margin:18px 0 0;color:var(--muted);font-size:12.5px}

/* ===== MOBILE / PORTRAIT — the hub becomes a scrolling column ===== */
/* The third condition is about height, not phones. Eight labelled nodes on a
   ring need roughly 90px of vertical radius to clear each other, and the
   budget — viewport minus header, headline and caption — only reaches that at
   about 640px tall. Below it the ellipse flattened until the ring became a row
   and the labels printed on top of one another. A short landscape window gets
   the stacked layout for the same reason a phone does: there is no room for a
   ring. isMobile() in the script carries the identical test; change both or
   neither, or the script positions for one layout while the CSS paints the
   other. */
@media (max-width:760px), (max-width:900px) and (orientation:portrait), (max-height:640px){
  #hub{overflow:auto;-webkit-overflow-scrolling:touch}
  .chrome{position:sticky;top:0}
  /* Two deliberate rows instead of whatever wrapping produced. Row 1: brand at
     one end, the controls at the other, booking last so it reads as the action.
     Row 2: the tab rail, full width. `order` puts them there regardless of DOM
     order, and margin-inline-start:auto on the first control pushes the whole
     control group away from the brand instead of leaving a ragged gap. */
  /* Two deliberate rows instead of whatever the wrap produced. Row 1 is the
     logo at one end and the control cluster at the other; row 2 is the tab rail
     at full width. Only three children here — #lock, .tn-tabs, .tn-right — so
     margin-inline-start:auto on the cluster does the whole job. */
  /* One row, always. With the chapter rail hidden and the loose icons folded
     into the settings popover, the header is the logo and three buttons —
     launcher, settings, hide — so there is nothing left to wrap. nowrap makes
     that a guarantee rather than a coincidence of the current button count. */
  .topnav{display:flex;height:auto;flex-wrap:nowrap;align-items:center;gap:8px;padding:8px 12px;min-height:52px}
  #lock{order:0;flex:0 0 auto}
  .tn-right{order:1;margin-inline-start:auto;display:flex;align-items:center;gap:6px;flex:0 0 auto}
  /* 40px targets: the WCAG minimum for a touch control, and they stay on one
     line because there are only three of them. */
  .tn-right .tbtn{width:40px;height:40px}
  .tn-mark{height:26px}.tn-word{height:16px}
  .headline{position:static;top:auto;padding:clamp(22px,5vh,40px) 14px clamp(10px,2vh,18px);pointer-events:auto}
  /* Hiding the header must not also close the gap above the headline. The base
     rule here sets 22–40px of top padding; the old override replaced it with
     14–24px, so collapsing the chrome visibly tightened the very space it had
     just freed. It now adds to it instead. */
  #hub.chrome-hidden .headline{display:block;padding-top:clamp(30px,6vh,54px)}
  .headline h1{max-width:none}
  .headline p{display:block}
  /* The hide toggle matters MORE on a phone than on a desktop: the header takes
     two rows here, and collapsing it is the only way to see the whole hub. It
     was hidden, leaving .chrome-handle as a way back from a state nothing could
     enter. */
  #hideBtn{display:inline-flex}
  .how,.help{position:fixed;padding-top:120px}
  /* The chapter rail goes away entirely on a phone and the 3x3 launcher takes
     its place: the rail was a second full-width row that had to be swiped, and
     it made the header taller than the content it introduced. */
  .tn-tabs{display:none}
  #gridBtn{display:inline-flex}
  /* Bottom sheet, not a popover: a panel anchored to a top-right button is out
     of thumb reach on a phone. Four across, so all seven tiles fit two rows. */
  .launcher{position:fixed;background:rgba(3,4,16,.45);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
  .launcher-card{top:auto;bottom:0;inset-inline:0;width:auto;max-width:none;padding:18px 16px calc(22px + var(--agent-lane));
    border-radius:22px 22px 0 0;transform:translateY(14px)}
  .launcher-grid{grid-template-columns:repeat(4,1fr);gap:4px}
  .ltile{font-size:11px}
  .ltile i{width:46px;height:46px}
  /* Trim the crowded topnav on a phone: fullscreen isn't useful, and scanning a
     QR code on the same phone showing it makes no sense. Never hide #ctaBtn
     with them — it is the booking funnel's entry point, and dropping it left a
     phone visitor with no way to book from the hub at all. It stays, compact.
     Target by id: a bare `.cta` also matches every dialog button (book submit,
     slot confirm, even the success dialog's close). */
  #fullBtn{display:none}
  /* Full-width and thumb-sized wherever a CTA closes a panel. */
  .next-cta .cta,.feat-cta .cta{width:100%;max-width:340px;height:46px}
  .chrome-handle{position:fixed}
  .headline{position:static;max-width:none;padding:clamp(22px,5vh,40px) 18px clamp(10px,2vh,18px);text-align:center}
  .headline p{margin-inline:auto}
  #hub.compact-header .kicker-lead{display:block}
  /* The brain used to sit as a 300px block ABOVE the capability grid, so a phone
     showed a picture, then a list — two unrelated objects stacked. It is behind
     the cards now: same composition as the desktop hub, where the capabilities
     surround the brain, just flattened into one column. The cards already carry
     a panel background and a backdrop blur, so they stay readable over it. */
  /* overflow-x:clip, because the brain behind the cards is deliberately wider
     than the column it sits in — without it those extra pixels became a real
     horizontal scroll and a dead strip at the edge of the page. `clip` rather
     than `hidden` so it never turns this into a scroll container. */
  .constellation{position:relative;overflow-x:clip;display:flex;flex-direction:column;align-items:center;gap:14px;padding:0 14px 120px;height:auto}
  #links{display:none}
  .brainwrap{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:0;
    width:min(104vw,420px);height:min(104vw,420px);margin:0;pointer-events:none;opacity:.3;
    -webkit-mask-image:radial-gradient(circle at 50% 50%,#000 26%,transparent 66%);
            mask-image:radial-gradient(circle at 50% 50%,#000 26%,transparent 66%)}
  .nodes{position:relative;z-index:1;display:grid;grid-template-columns:1fr 1fr;gap:10px;width:100%;pointer-events:auto}
  .node{position:static;transform:none!important;width:auto;flex-direction:row;justify-content:flex-start;gap:12px;text-align:start;padding:10px 12px;border-radius:14px;background:var(--panel);border:1px solid var(--panel-line);opacity:1;
    backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
    box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2)}
  .node .ring{width:44px;height:44px;flex:0 0 auto}
  .node .ring::before{display:none}
  .node .lab{max-width:none;font-size:13px;text-transform:none;letter-spacing:.01em}
  /* The stage number is always on here. Around the brain it only appears during
     the cycle walkthrough, because the positions themselves imply an order. A
     stacked list implies nothing, so 1..8 is what says these are sequential
     stages and not eight unrelated features — the same reason their DOM order
     was worth fixing. It stays a badge on the ring: .num is a child of .ring,
     not of .node, so it cannot be pulled out into the row without rebuilding
     the markup the desktop ring depends on. */
  .node .num{top:-5px;inset-inline-end:auto;inset-inline-start:-5px;width:20px;height:20px;font-size:10.5px;line-height:20px;
    opacity:1;transform:none;background:var(--panel);color:var(--muted);border:1px solid var(--panel-line);font-weight:700}
  .node.focus .num{background:var(--nc,var(--accent));border-color:var(--nc,var(--accent));color:#fff}
  #hub.focus-mode .node:not(.focus){opacity:.7}
  .node.focus{border-color:var(--nc,var(--accent))}
  /* The Cycles agent launcher pins itself to the bottom of the viewport and we
     do not control its shadow DOM, so the caption gets out of its way instead
     of fighting it: the bar sits one launcher-height up, and the two stack
     rather than overlap. --agent-lane is the one number to change if the
     launcher ever grows; the constellation's bottom padding tracks it so the
     last capability card is never left underneath either of them. */
  /* pointer-events:none on the bar, auto on what you can press. It is a HUD
     strip lying across a scrollable list, and a finger or a wheel starting on
     it had nothing to scroll — the gesture died on the bar. Now it passes
     straight through to the cards underneath, and only the buttons catch it. */
  .caption{position:fixed;left:12px;right:12px;bottom:calc(12px + var(--agent-lane));transform:none;max-width:none;border-radius:16px;white-space:normal;padding:10px 14px;pointer-events:none}
  .caption button,.caption a,.caption .cbtn{pointer-events:auto}
  .constellation{padding-bottom:calc(72px + var(--agent-lane))}
  /* Landscape and short: stack nothing. The bar shares the bottom row with the
     agent launcher instead of floating a row above it, which is what pushed it
     into the middle of the card grid. The launcher is physically bottom-right
     whatever the writing direction, so this reserve is `right`, not an
     inline-end that would flip to the wrong side in Arabic. */
  @media (orientation:landscape){
    .caption{bottom:16px;right:calc(16px + var(--agent-side))}
    .constellation{padding-bottom:calc(96px + var(--agent-lane))}
  }
  /* One row. The two chips were wrapping onto a second line, which turned a
     status strip into a ragged two-line block. Smaller chips, a tighter gap,
     and the label truncates before the buttons are pushed down. */
  .cap-idle,.cap-live{flex-wrap:nowrap;gap:8px}
  .cap-idle>[data-t=select],.cap-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .caption .cbtn{padding:6px 11px;font-size:11.5px;flex:0 0 auto}
  .cap-sep{display:none}
  .cap-text span{display:none}
  .help-card,.how-card{padding:20px 18px 16px}
  .core-grid{grid-template-columns:1fr}
  #feature{padding:14px 16px 28px}
  #feature .feat-body{display:flex;flex-direction:column;align-items:stretch;gap:18px;margin-top:14px;overflow:visible}
  #feature .video{width:100%;height:auto;aspect-ratio:16/9;flex:0 0 auto}
  #feature .feat-text{max-width:none;overflow:visible;max-height:none;padding-inline-end:0}
  #feature .metrics{grid-template-columns:repeat(3,1fr);gap:10px}
  #feature .feat-visual{order:-1} /* graphic still shows first on a phone, text follows */
  #feature .feat-title{font-size:clamp(26px,7vw,40px)}
  .nucleus::after{inset:-34px}
}
/* ===== FEATURE ===== */
#feature{position:absolute;inset:0;z-index:12;display:flex;flex-direction:column;padding:clamp(20px,3vw,48px) clamp(24px,4.5vw,76px);opacity:0;visibility:hidden;pointer-events:none;transform:scale(1.04);transition:opacity .5s ease, transform .5s cubic-bezier(.2,.7,.2,1), visibility 0s linear .5s;overflow-y:auto}
#feature.show{opacity:1;visibility:visible;pointer-events:auto;transform:scale(1);transition:opacity .5s ease, transform .5s cubic-bezier(.2,.7,.2,1), visibility 0s}
.feat-top{display:flex;align-items:center;justify-content:space-between;gap:20px}
.back{display:inline-flex;align-items:center;gap:11px;background:var(--panel);border:1px solid var(--panel-line);border-radius:999px;padding:11px 20px 11px 15px;font-family:var(--disp);font-weight:500;font-size:clamp(13px,1vw,15px);transition:background .25s,border-color .25s}
.back:hover{border-color:var(--accent)}
.back svg{width:17px;height:17px;stroke:var(--accent);stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
[dir=rtl] .back svg{transform:scaleX(-1)}
.feat-brand img{height:clamp(20px,1.9vw,30px);opacity:.9;filter:saturate(1.35) contrast(1.1) drop-shadow(0 2px 6px var(--glow-b))}
.feat-body{flex:1;min-height:0;width:100%;max-width:1480px;margin:clamp(16px,2.4vh,34px) auto 0;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(28px,4vw,72px);align-items:start}
[lang=ar] .feat-body{grid-template-columns:minmax(0,1.2fr) minmax(0,1.05fr)} /* Arabic copy reliably runs longer — give it more of the row */
/* text column scrolls on its own; the graphic column never moves */
.feat-text{max-width:600px;justify-self:start;align-self:stretch;min-height:0;overflow-y:auto;padding-inline-end:6px}
[lang=ar] .feat-text{max-width:100%}
.feat-visual{display:flex;flex-direction:column;gap:22px}
.video{position:relative;aspect-ratio:16/9;border-radius:20px;overflow:hidden;background:var(--sc-bg);border:1px solid var(--panel-line);box-shadow:0 30px 80px rgba(3,6,18,.25), inset 0 0 60px rgba(94,129,244,.06)}
.video video{width:100%;height:100%;object-fit:cover;display:block}
.video .glowedge{position:absolute;inset:0;border-radius:20px;pointer-events:none;box-shadow:inset 0 0 0 1px var(--accent);opacity:.35}
.scene{position:absolute;inset:0}
.scene svg{width:100%;height:100%;display:block;direction:ltr}
/* direction:ltr above stops separate LTR/RTL runs on the SAME line (mixed
   Arabic+Latin, e.g. a metric value) from being mis-ordered relative to
   each other. But it was ALSO forcing every *pure*-Arabic label (no Latin
   mixed in — the kpi label under "8s", the translated chip/scene labels)
   to resolve as if it were an LTR run, visibly reversing the Arabic glyphs.
   unicode-bidi:plaintext fixes exactly this: each <text> picks its OWN
   paragraph direction from its own first strong character instead of
   inheriting the forced one, so a pure-Arabic label reads correctly while
   a mixed value still benefits from the direction:ltr ordering above. */
.scene text{unicode-bidi:plaintext}
/* Reverted: mirroring the whole scene via scaleX(-1) with a counter-flip on
   <text> (transform-box:fill-box) looked correct in review but rendered
   real Arabic text backwards/mispositioned in practice — transform-box on
   SVG <text> isn't reliable enough across browsers to trust here. Scenes
   stay visually left-to-right in both languages; only the story/progress
   track (a genuine progress indicator, not illustrative content) is
   RTL-aware, via explicit coordinates in SC.story() below — the same
   narrower fix that was verified working before this whole-scene attempt. */
.scene .card{fill:var(--sc-card);stroke:var(--sc-card-line);stroke-width:1}
.scene .ln{fill:none;stroke:var(--accent);color:var(--accent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.scene .ln2{fill:none;stroke:var(--accent);stroke-width:1.2;stroke-linecap:round;opacity:.45}
.scene .soft{fill:none;stroke:var(--panel-line);stroke-width:1}
.scene .bar{fill:var(--accent);opacity:.55}
.scene .acc{fill:var(--accent)}
.scene .txt{fill:var(--text);font:600 12px var(--disp)}
.scene .sm{fill:var(--muted);font:500 10px var(--body);letter-spacing:.02em}
/* Safari/WebKit has a real, narrow bug: any letter-spacing on Arabic text
   inside an SVG <text> element corrupts its glyph layout (looks like
   reversed/garbled characters) — confirmed by bisecting a static, isolated
   reproduction outside the app entirely; nothing to do with bidi/direction,
   which is why every unicode-bidi/direction fix tried first had zero
   effect. Arabic script's cursive joining plus WebKit's SVG glyph-advance
   handling of letter-spacing is the actual combination that breaks. Chrome
   is unaffected either way, so this only needs to zero it out for ar. */
[lang=ar] .scene .sm{letter-spacing:normal}
.scene .big{fill:var(--text);font:700 22px var(--disp);letter-spacing:-.02em}
.scene .chip{fill:color-mix(in srgb, var(--accent) 14%, transparent);stroke:var(--accent);stroke-width:1}
.scene .chip-t{fill:var(--accent);font:600 10.5px var(--disp)}
.scene .tick{fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.scene .ok{fill:var(--ok)}.scene .bad{fill:var(--bad)}.scene .warn{fill:var(--warn)}
.scene .chip.ok{fill:color-mix(in srgb, var(--ok) 16%, transparent);stroke:var(--ok)}.scene .chip-t.ok{fill:var(--ok)}
.scene .chip.warn{fill:color-mix(in srgb, var(--warn) 16%, transparent);stroke:var(--warn)}.scene .chip-t.warn{fill:var(--warn)}
.scene .g-line{fill:var(--sc-card);opacity:.9}
/* beat-driven scene effects: the runner sets opacity/transform/dashoffset each frame */
.scene [data-fx]{transform-box:fill-box;transform-origin:center}
.scene [data-fx=rise],.scene [data-fx=shrink]{transform-origin:bottom}
.scene .story{fill:var(--h1);font:600 clamp(12px,1vw,14.5px) var(--disp)}
.scene .ptrack{fill:var(--panel-line)}
.scene .pbar{fill:url(#bar-grad)}
.scene .ptick{fill:var(--accent);opacity:.55}
.scene .halo{fill:none;stroke:var(--accent);stroke-width:1.2}
[data-theme=light] .scene .card{filter:drop-shadow(0 4px 12px rgba(58,92,251,.10))}
.kicker{display:inline-flex;align-items:center;gap:9px;color:var(--accent);font-family:var(--disp);font-weight:500;font-size:clamp(12px,1vw,14.5px);margin:0 0 14px}
.kicker .ic{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;background:var(--chip);border:1px solid var(--chip-line)}
.kicker .ic svg{width:17px;height:17px;stroke:var(--accent);color:var(--accent);stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round}
.feat-title{font-family:var(--disp);font-weight:600;letter-spacing:-.015em;font-size:clamp(30px,4.4vw,62px);line-height:1.03;margin:0 0 12px;color:var(--h1)}
[lang=ar] .feat-title{letter-spacing:0;line-height:1.3;font-weight:700;font-size:clamp(30px,4vw,58px)}
.feat-purpose{font-size:clamp(16px,1.5vw,23px);color:var(--accent);line-height:1.4;margin:0 0 20px;max-width:26ch;font-weight:450}
[lang=ar] .feat-purpose{line-height:1.7;max-width:34ch}
.feat-desc{color:var(--muted);font-size:clamp(14px,1.12vw,17px);line-height:1.62;max-width:52ch;margin:0 0 22px}
.helps{list-style:none;padding:0;margin:0 0 26px;display:grid;gap:11px;max-width:52ch}
.helps li{display:flex;gap:13px;align-items:flex-start;color:var(--text);font-size:clamp(13.5px,1.08vw,16px);line-height:1.45}
.helps li span{flex:1;min-width:0}
[lang=ar] .helps li{line-height:1.8;font-size:clamp(14.5px,1.12vw,17px)}
[lang=ar] .feat-desc{line-height:1.9;font-size:clamp(15px,1.18vw,18px)}
.helps li::before{content:"";flex:0 0 auto;width:8px;height:8px;margin-top:7px;border-radius:2px;background:var(--accent);box-shadow:0 0 10px var(--accent);transform:rotate(45deg)}
.orch{margin:0 0 22px;padding:14px 16px;border-radius:14px;background:var(--chip);border:1px solid var(--chip-line);max-width:56ch}
.feat-cta{margin:0 0 4px}
.feat-cta .cta{height:42px;padding:0 24px;font-size:13.5px}
.orch-t{font:600 11.5px var(--disp);letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:10px}
[lang=ar] .orch-t{letter-spacing:0;font-size:12.5px}
.orch-rows{display:grid;gap:8px}
.orch-row{display:flex;gap:10px;align-items:flex-start;font-size:clamp(12.5px,.98vw,14.5px);line-height:1.45;color:var(--text)}
.orch-row span{flex:1;min-width:0}
[lang=ar] .orch-row{line-height:1.75;font-size:clamp(13.5px,1.05vw,15.5px)}
.orch-row svg{flex:0 0 auto;width:18px;height:18px;margin-top:1px;stroke:var(--accent);fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.orch-row.agent svg{fill:var(--accent);stroke:none}
.metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(12px,1.6vw,26px);border-top:1px solid var(--panel-line);padding-top:clamp(16px,2.2vh,26px)}
/* ===== feature-page voice bar — flat pill, same language as the homepage caption ===== */
.feat-audio{display:flex;align-items:center;gap:12px;padding:9px 16px;border-radius:999px;
  background:var(--panel);border:1px solid var(--panel-line);
  backdrop-filter:blur(var(--panel-blur)) saturate(140%);-webkit-backdrop-filter:blur(var(--panel-blur)) saturate(140%);
  box-shadow:inset 0 1px 0 var(--glass-hi), inset 0 -1px 0 var(--glass-hi-2)}
.feat-audio-label{font:600 12.5px var(--disp);color:var(--muted);flex:0 0 auto;white-space:nowrap}
.feat-audio-prog{flex:1;height:3px;border-radius:2px;background:var(--panel-line);overflow:hidden}
.feat-audio-fill{height:100%;width:0;background:linear-gradient(90deg,var(--accent),var(--core));border-radius:2px}
[dir=rtl] .feat-audio-fill{background:linear-gradient(270deg,var(--accent),var(--core))}
.metric .val{font-family:var(--disp);font-weight:600;letter-spacing:-.02em;font-size:clamp(26px,3.4vw,46px);line-height:1;direction:ltr;display:inline-block;background:linear-gradient(180deg,var(--h1),var(--accent));-webkit-background-clip:text;background-clip:text;color:transparent}
.metric .lab{color:var(--muted);font-size:clamp(11.5px,.92vw,13.5px);line-height:1.35;margin-top:9px;max-width:16ch}
[lang=ar] .metric .lab{max-width:none;line-height:1.6}
@media (max-width:900px){.feat-body{grid-template-columns:1fr;gap:22px;overflow:auto;align-items:start}.feat-text{overflow:visible;max-height:none;padding-inline-end:0}}
@media (prefers-reduced-motion:reduce){*{animation:none!important}}
