/* Shared chrome for the service pages. The landing keeps its own inline <style> for the
   hero/core; everything here is the part that must look identical across all ten pages. */

/* ===== THE BRAND COLOURS ARE NOT DECLARED HERE ANY MORE (2026-08-07) =====
   Every value below is an ALIAS onto `palette.css`, which is generated from
   `design/palette.mjs` and written into this folder AND into the Next app. The landing and
   the platform used to hold two independent copies of the same brand, which is a promise to
   keep two files in sync by hand — and the blue is exactly the kind of value where a
   one-digit divergence goes unnoticed for months.

   The names below do NOT change and neither do the rendered values; only where they come
   from changed. `node scripts/build-palette.mjs --check` fails if palette.css has drifted
   from its source.

   The three left as literals are genuinely this page's own, not brand:
     --gold-ink  a mid orange the platform has no use for (the deep orange is the token)
     --line      a 9% hairline tuned for marketing whitespace; the platform's is denser
                 (14%) because a 1.18:1 line vanishes in a 40-row table
     --ease / --nav-h  not colours at all. */
:root {
  --blue: var(--t-accent);
  --blue-deep: var(--t-accent-deep);
  --gold: var(--t-orange-vivid);
  --gold-rgb: var(--t-orange-vivid-rgb);
  --gold-ink: #B45309;
  --gold-deep: var(--t-orange-ink);
  --ink: var(--t-ink);
  --muted: var(--t-ink-2);
  --line: rgba(20,48,107,.09);
  --ease: cubic-bezier(.2,.8,.2,1);
  --nav-h: 66px;

  /* ===== THE PLATFORM ACCENT FAMILY (owner ruling, 2026-08-06) =====
     Four accents, blue is THE primary. Each comes as a PAIR, and the pair is a contrast
     rule, not a style choice — measured on the white ground:
       vivid  (-rgb): glows, halos, tints, edges — DECORATIVE ONLY.
              green 2.28:1 and orange 2.04:1 fail even the 3:1 graphics bar on white.
       ink:   anything that carries meaning — text, ticks, slider fills, focus rings.
              blue 4.94, green 5.02, orange 5.42, red 6.47 — all clear text AA. */
  --c-blue-rgb:   var(--t-blue-vivid-rgb);   --c-blue-ink:   var(--t-blue-ink);
  --c-green-rgb:  var(--t-green-vivid-rgb);  --c-green-ink:  var(--t-green-ink);
  --c-orange-rgb: var(--t-orange-vivid-rgb); --c-orange-ink: var(--t-orange-ink);
  --c-red-rgb:    var(--t-red-vivid-rgb);    --c-red-ink:    var(--t-red-ink);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: #fff; color: var(--ink);
  font-family: 'Sora', system-ui, sans-serif; -webkit-font-smoothing: antialiased;
  padding-top: var(--nav-h);
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

@keyframes talosBlip { 0%,100% { opacity:.35 } 50% { opacity:1 } }

.pill {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 20px; border-radius: 100px;
  font-family: 'Space Grotesk', sans-serif; font-size: 12.5px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--blue);
  background: linear-gradient(180deg, rgba(255,255,255,.96) 0%, rgba(228,238,255,.78) 100%);
  border: 1px solid rgba(31,98,255,.26);
  box-shadow: 0 12px 26px -14px rgba(15,75,230,.5), inset 0 1px 0 #fff;
}
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--blue); box-shadow: 0 0 10px rgba(31,98,255,.85); animation: talosBlip 2.4s ease-in-out infinite; }

/* ===== nav ===== */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40; height: var(--nav-h);
  display: flex; align-items: center; gap: 28px; padding: 0 min(6vw, 60px);
  background: #fff; border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: center; gap: 9px; font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 19px; }
/* ===== the brand mark, animated =====
   Inline SVG, not an <img>: the five parts have to be individually addressable for the
   trails to travel. Pure CSS — no JS, and nothing to load.

   NOT the WebGL mark. At 27x21 the 3D build renders to unreadable mush (measured against
   this SVG at the same size), and it would pull 607 KB of three.js onto all 30 pages for
   a logo smaller than a favicon.

   The gesture is `send`, the same choreography the 3D clip uses: the trails shoot out and
   fade, the flap dips, then everything settles. A long rest between plays — this sits in
   the nav on every page, and a mark that never stops moving is a mark you stop reading. */
.brand .mark { height: 21px; width: auto; flex: none; overflow: visible; }
.brand .mark-p { fill: var(--blue); }

@media (prefers-reduced-motion: no-preference) {
  .brand .mark-p--trail {
    animation: markTrail 6.5s var(--ease, ease-in-out) infinite;
    transform-box: fill-box;
    transform-origin: right center;
  }
  /* Staggered so they read as three separate trails leaving, not one bar. */
  .brand .mark-p[data-part='line-top'] { animation-delay: 0.06s; }
  .brand .mark-p[data-part='line-bot'] { animation-delay: 0.12s; }
  .brand .mark-p--flap {
    animation: markFlap 6.5s var(--ease, ease-in-out) infinite;
    transform-box: fill-box;
    transform-origin: 50% 100%;
  }
  .brand:hover .mark-p--trail,
  .brand:hover .mark-p--flap { animation-duration: 2.6s; }
}

/* Percentages, not seconds: the whole gesture happens in the first ~18% and the rest of
   the cycle is deliberate stillness. */
@keyframes markTrail {
  0%, 4%   { transform: translateX(0); opacity: 1; }
  10%      { transform: translateX(150px); opacity: 0; }
  10.01%   { transform: translateX(0); opacity: 0; }
  18%, 100% { transform: translateX(0); opacity: 1; }
}
@keyframes markFlap {
  0%, 3%   { transform: scaleY(1); }
  8%       { transform: scaleY(0.86); }
  16%, 100% { transform: scaleY(1); }
}
.brand .accent { color: var(--blue); }
.nav-links { display: flex; align-items: center; gap: 26px; margin-left: 14px; }
.nav-links a, .nav-drop { font-size: 14.5px; font-weight: 500; color: #46587A; transition: color .18s var(--ease); }
.nav-links a:hover, .nav-drop:hover { color: var(--blue); }
.nav-drop {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit;
}
.nav-drop .caret { font-size: 10px; transition: transform .2s var(--ease); }
.nav-drop[aria-expanded="true"] { color: var(--blue); }
.nav-drop[aria-expanded="true"] .caret { transform: rotate(180deg); }
.nav-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.nav-login { font-size: 14.5px; font-weight: 600; padding: 9px 18px; border-radius: 100px; border: 1px solid rgba(20,48,107,.16); }
.nav-login:hover { border-color: rgba(31,98,255,.5); color: var(--blue); }
.btn-primary, .nav-cta {
  font-weight: 600; color: #fff; border-radius: 100px; display: inline-flex; align-items: center; gap: 10px;
  background: linear-gradient(180deg, #4B8CFF 0%, #1250E6 62%, #0A3AC8 100%);
  box-shadow: 0 12px 26px -10px rgba(15,75,230,.55), inset 0 1px 0 rgba(255,255,255,.45);
}
.nav-cta { font-size: 14.5px; padding: 10px 20px; }
.btn-primary { font-size: 15.5px; padding: 15px 26px; }
.btn-secondary {
  font-weight: 600; font-size: 15.5px; border-radius: 100px; padding: 15px 24px;
  display: inline-flex; align-items: center; gap: 10px; color: #14306B;
  background: #F3F6FC; border: 1px solid rgba(31,98,255,.18);
}

/* ===== mega menu =====
   Anchored to the nav, not to the button, so it spans the page like the reference does.
   Kept in the DOM and toggled with a class rather than built on open, so keyboard focus
   order and the aria-controls relationship stay real. */
.mm {
  position: absolute; top: var(--nav-h); left: 0; right: 0;
  background: #fff; border-bottom: 1px solid var(--line);
  box-shadow: 0 28px 50px -28px rgba(12,44,130,.28);
  /* Animated open. visibility — NOT [hidden] — is what makes this possible: [hidden] is
     display:none, which cannot transition at all, so the panel used to blink into place.
     visibility still takes the panel out of the tab order while closed, and the delayed
     visibility transition lets the fade-out finish before it is pulled from the a11y tree. */
  opacity: 0; visibility: hidden; transform: translateY(-9px);
  transition: opacity .19s var(--ease), transform .26s var(--ease), visibility 0s linear .26s;
}
.mm.is-open {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .2s var(--ease), transform .34s var(--ease), visibility 0s;
}
/* Columns rise in behind the panel. Staggered per COLUMN rather than per item so the
   entrance delay can never leak onto .mm-item's hover transition and make hover feel laggy. */
.mm-col { opacity: 0; transform: translateY(9px); transition: opacity .12s var(--ease), transform .12s var(--ease); }
.mm.is-open .mm-col { opacity: 1; transform: none; transition: opacity .34s var(--ease), transform .44s var(--ease); }
.mm.is-open .mm-col:nth-child(2) { transition-delay: .05s; }
.mm.is-open .mm-col:nth-child(3) { transition-delay: .1s; }
.mm.is-open .mm-col:nth-child(4) { transition-delay: .15s; }
.mm-inner {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 30px;
  padding: 34px min(6vw, 60px) 28px; max-width: 1400px; margin: 0 auto;
}
.mm-head {
  font-family: 'Space Grotesk', sans-serif; font-size: 11px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: #8296B4; margin-bottom: 14px;
}
.mm-item {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 9px 10px; margin: 0 -10px; border-radius: 12px;
  transition: background .16s var(--ease);
}
.mm-item:hover { background: #F4F7FE; }
.mm-dot { width: 8px; height: 8px; border-radius: 3px; background: var(--blue); margin-top: 6px; flex: 0 0 8px; }
.mm-item:nth-child(odd) .mm-dot { background: var(--gold); }
.mm-txt { display: block; }
.mm-txt b { display: block; font-size: 14.5px; font-weight: 600; color: var(--ink); }
.mm-txt em { display: block; font-style: normal; font-size: 12.6px; line-height: 1.45; color: var(--muted); margin-top: 2px; }
.mm-foot {
  padding: 14px min(6vw, 60px); background: #F7F9FD; border-top: 1px solid var(--line);
  font-size: 13.4px; color: var(--muted);
}
.mm-foot a { color: var(--blue); font-weight: 600; }
@media (max-width: 900px) { .mm-inner { grid-template-columns: repeat(2, 1fr); } }

/* ===== service page ===== */
.svc { max-width: 1180px; margin: 0 auto; padding: 56px min(6vw, 40px) 90px; }
/* block, not inline-block: as an inline the pill flowed up alongside it and the two
   collided on one line */
.crumb { display: block; width: fit-content; font-size: 13.6px; color: var(--muted); margin-bottom: 20px; }
.crumb:hover { color: var(--blue); }
.svc-head .pill { margin-bottom: 18px; }
.svc-head h1 { font-size: clamp(30px, 4vw, 46px); font-weight: 800; letter-spacing: -.025em; margin: 0 0 16px; }
.svc-head > p { font-size: 17.5px; line-height: 1.65; color: var(--muted); max-width: 720px; margin: 0 0 30px; }
.svc-cta { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 54px; }

/* ===== screenshots =====
   These images are dark 16:9 composites that already carry their own annotation panel and
   caption. So the job here is to present them like a SCREEN — dark bezel, one fixed stage,
   a crossfade between them — and to keep the written copy to a short lead-in rather than a
   second description competing with the one printed inside the picture. */
.shots { display: grid; grid-template-columns: 306px minmax(0, 1fr); gap: 28px; align-items: start; }
.shots.is-single { grid-template-columns: minmax(0, 1fr); }

.shotnav { display: flex; flex-direction: column; gap: 3px; }
.shotnav-item {
  display: flex; gap: 12px; align-items: flex-start; width: 100%; text-align: left;
  font-family: inherit; cursor: pointer; padding: 13px 14px; border-radius: 13px;
  background: transparent; border: 1px solid transparent;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.shotnav-item:hover { background: #F4F7FE; }
.shotnav-item.is-on { background: #F1F6FF; border-color: rgba(31,98,255,.24); }
.si-i {
  flex: 0 0 auto; margin-top: 3px; letter-spacing: .06em; color: #A9B7CE;
  font-family: 'Space Grotesk', sans-serif; font-size: 11px; font-weight: 700;
  transition: color .2s var(--ease);
}
.shotnav-item.is-on .si-i { color: var(--blue); }
.si-t { min-width: 0; }
.si-t b { display: block; font-size: 14.6px; font-weight: 600; color: var(--ink); }
.si-t em { display: block; font-style: normal; font-size: 12.9px; line-height: 1.5; color: var(--muted); margin-top: 3px; }

/* A fixed 16:9 stage with the frames stacked inside it: the height never changes, so
   switching shot cannot jolt the page. */
.stage {
  position: relative; aspect-ratio: 16 / 9; border-radius: 18px; overflow: hidden;
  background: #050A16; border: 1px solid rgba(20,48,107,.14);
  box-shadow: 0 44px 84px -44px rgba(8,26,72,.6), 0 10px 24px -14px rgba(8,26,72,.32);
}
.frame {
  position: absolute; inset: 0; margin: 0; opacity: 0; pointer-events: none;
  transform: scale(1.022);
  transition: opacity .45s var(--ease), transform .85s var(--ease);
}
.frame.is-on { opacity: 1; transform: none; pointer-events: auto; }
.frame img { width: 100%; height: 100%; object-fit: cover; }
.shot-cap { margin: 15px 2px 0; font-size: 13.8px; line-height: 1.6; color: var(--muted); max-width: 760px; }

@media (max-width: 900px) {
  /* Too narrow for a side rail, and the per-shot blurb would push the image off the fold —
     so the rail degrades to a scrollable label strip and the copy goes with the image. */
  .shots { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .shotnav { flex-direction: row; overflow-x: auto; gap: 8px; padding-bottom: 4px; }
  .shotnav-item {
    flex: 0 0 auto; width: auto; padding: 9px 15px; border-radius: 100px;
    background: #F3F6FC; border-color: var(--line);
  }
  .shotnav-item.is-on { background: var(--blue); border-color: var(--blue); }
  .shotnav-item.is-on .si-t b { color: #fff; }
  .si-i, .si-t em { display: none; }
  .si-t b { font-size: 13.4px; white-space: nowrap; }
}

/* ===== scroll reveal =====
   Named .rise, NOT .reveal: the landing has its own .reveal/.in system in its inline
   <style>, and `.js .reveal` here would out-specify `.reveal.in` there and pin the whole
   landing page at opacity 0.
   Gated on .js so that with scripting off the content is simply visible rather than
   permanently transparent — a reveal that never fires must fail open. */
.js .rise { opacity: 0; transform: translateY(15px); }
.js .rise.is-in { opacity: 1; transform: none; transition: opacity .6s var(--ease), transform .72s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .js .rise, .js .rise.is-in { opacity: 1; transform: none; transition: none; }
  .mm, .mm.is-open, .mm-col, .mm.is-open .mm-col, .frame { transition-duration: .01ms !important; transition-delay: 0s !important; }
  html { scroll-behavior: auto; }
}

.svc-more { margin-top: 66px; padding-top: 28px; border-top: 1px solid var(--line); }
.svc-more-head { font-family: 'Space Grotesk', sans-serif; font-size: 11.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: #8296B4; margin-bottom: 16px; }
.svc-more-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.svc-more-grid a {
  font-size: 14px; font-weight: 600; color: #46587A;
  padding: 9px 16px; border-radius: 100px; background: #F3F6FC; border: 1px solid var(--line);
  transition: all .18s var(--ease);
}
.svc-more-grid a:hover { color: var(--blue); border-color: rgba(31,98,255,.34); }

.mini-foot { border-top: 1px solid var(--line); padding: 30px min(6vw, 40px); max-width: 1180px; margin: 0 auto; color: #8296B4; font-size: 13px; }
.legal-note { font-size: 12.4px; line-height: 1.7; color: #8296B4; max-width: 900px; margin: 0 0 14px; }

/* ===== "Inside the service" — scroll + cursor-driven explanation =====
   Two mechanisms, both taken from the current best-practice pattern (researched
   2026-08-06: Linear reveals per-section, the spotlight card is the Vercel/Cursor
   pattern; Laravel's own homepage is static):

   1. A progress line that FILLS as you read — a gradient through all four platform
      accents, revealed by scaleY, with each step lighting up in its own accent as the
      fill passes it. Scroll-linked, not autonomous, so it never moves on its own.
   2. A cursor spotlight inside each card: mousemove writes --mx/--my and the card's
      overlay paints a radial glow there in the step's own accent. Hover-capable
      pointers only — on touch the overlay simply never appears.

   Everything is gated to fail OPEN: with no JS the steps are plain readable cards. */
.howit { margin-top: 78px; padding-top: 34px; border-top: 1px solid var(--line); }
.howit-kicker {
  font-family: 'Space Grotesk', sans-serif; font-size: 11.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: #8296B4; margin-bottom: 10px;
}
.howit h2 { font-size: clamp(24px, 3vw, 32px); font-weight: 800; letter-spacing: -.02em; margin: 0 0 8px; }
.howit-sub { font-size: 15.4px; color: var(--muted); margin: 0 0 40px; max-width: 640px; }

.howit-steps { position: relative; max-width: 860px; }
/* the rail: a static faint track + a fill that carries all four accents top-to-bottom */
.howit-rail {
  position: absolute; top: 26px; bottom: 26px; left: 25px; width: 2px;
  background: var(--line); border-radius: 2px;
}
.howit-fill {
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgb(var(--c-blue-rgb)) 0%, rgb(var(--c-green-rgb)) 36%,
    rgb(var(--c-orange-rgb)) 68%, rgb(var(--c-red-rgb)) 100%);
  transform-origin: top; transform: scaleY(var(--p, 0));
  border-radius: 2px;
}

.hstep { position: relative; display: flex; gap: 22px; padding: 13px 0; }
.hnum {
  position: relative; z-index: 1; flex: 0 0 52px; width: 52px; height: 52px;
  display: grid; place-items: center; border-radius: 14px; margin-top: 2px;
  background: #fff; border: 1px solid var(--line);
  font-family: 'Space Grotesk', sans-serif; font-size: 15px; font-weight: 700; color: #8296B4;
  transition: color .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease), transform .3s var(--ease);
}
.hstep.is-active .hnum {
  color: var(--acc-ink); border-color: rgba(var(--acc), .5); transform: scale(1.05);
  box-shadow: 0 0 0 4px rgba(var(--acc), .12), 0 10px 24px -10px rgba(var(--acc), .55);
}

.hcard {
  position: relative; flex: 1; min-width: 0; overflow: hidden;
  padding: 18px 20px; border-radius: 16px;
  background: #fff; border: 1px solid var(--line);
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.hstep.is-active .hcard {
  border-color: rgba(var(--acc), .34);
  box-shadow: 0 18px 40px -24px rgba(var(--acc), .45);
}
.hcard h3 { font-size: 16.5px; font-weight: 700; margin: 0 0 6px; letter-spacing: -.01em; }
.hcard p { font-size: 14.4px; line-height: 1.68; color: #3E4F6B; margin: 0; }
.hstep.is-active .hcard h3 { color: var(--acc-ink); }

/* the cursor spotlight: painted on an overlay so the glow can sit UNDER the text but
   over the white card. Opacity is flipped by :hover alone — no JS needed to hide it. */
.hcard::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              rgba(var(--acc), .13), transparent 62%);
  transition: opacity .35s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .hcard:hover::after { opacity: 1; }
  .hcard:hover { border-color: rgba(var(--acc), .45); }
}

@media (max-width: 640px) {
  .howit-rail { left: 21px; }
  .hstep { gap: 16px; }
  .hnum { flex-basis: 44px; width: 44px; height: 44px; border-radius: 12px; font-size: 13.5px; }
}
@media (prefers-reduced-motion: reduce) {
  .hnum, .hcard, .hcard::after { transition: none; }
  .hstep.is-active .hnum { transform: none; }
}

/* a step highlighted from the OTHER side of a two-way link (e.g. hovering the matching
   slab in the landing's isometric) — same look as the scroll-active state */
.hstep.is-hot .hcard { border-color: rgba(var(--acc), .45); box-shadow: 0 18px 40px -24px rgba(var(--acc), .5); }
.hstep.is-hot .hcard h3 { color: var(--acc-ink); }
.hstep.is-hot .hnum { color: var(--acc-ink); border-color: rgba(var(--acc), .5); }

/* ===== compact nav dropdown (the three legal documents) =====
   Same mechanics as the Services mega panel — visibility, not [hidden], so it can animate —
   but anchored to its own trigger rather than spanning the nav, because a full-bleed panel
   for three links reads as a mistake.

   The vertical anchor is exact rather than eyeballed: the trigger's centre IS the nav's
   centre (both .nav and .nav-links centre their items), so the nav's bottom edge is always
   half a nav-height below it — hence top: calc(50% + var(--nav-h) / 2). */
.nav-item { position: relative; display: inline-flex; align-items: center; }
.mmini {
  position: absolute; top: calc(50% + var(--nav-h) / 2); left: -14px;
  min-width: 268px; padding: 8px;
  background: #fff; border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 26px 48px -26px rgba(12,44,130,.34), 0 4px 12px -6px rgba(12,44,130,.12);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity .18s var(--ease), transform .26s var(--ease), visibility 0s linear .26s;
}
.mmini.is-open {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .2s var(--ease), transform .32s var(--ease), visibility 0s;
}
.mmini a {
  display: block; padding: 10px 12px; border-radius: 11px;
  opacity: 0; transform: translateY(6px);
  /* per-property delays, NOT a blanket transition-delay: a shared delay would also hold
     back `background`, and the hover highlight would feel laggy for no reason */
  transition: opacity .1s var(--ease), transform .1s var(--ease), background .16s var(--ease);
}
.mmini.is-open a {
  opacity: 1; transform: none;
  transition: opacity .3s var(--ease) .03s, transform .36s var(--ease) .03s, background .16s var(--ease) 0s;
}
.mmini.is-open a:nth-child(2) { transition-delay: .07s, .07s, 0s; }
.mmini.is-open a:nth-child(3) { transition-delay: .11s, .11s, 0s; }
.mmini a:hover { background: #F4F7FE; }
.mmini b { display: block; font-size: 14px; font-weight: 600; color: var(--ink); }
.mmini em { display: block; font-style: normal; font-size: 12.2px; line-height: 1.45; color: var(--muted); margin-top: 2px; }
/* "you are here" — set at runtime, because the nav markup is byte-identical on every page */
.mmini a.is-here { background: #F1F6FF; }
.mmini a.is-here b { color: var(--blue); }

@media (max-width: 940px) { .mmini { left: auto; right: -14px; } }
@media (prefers-reduced-motion: reduce) {
  .mmini, .mmini a, .mmini.is-open a { transition-duration: .01ms !important; transition-delay: 0s !important; }
}

/* ===== RTL =====
   The Arabic build sets dir="rtl" on <html>. Everything below is what direction-agnostic
   layout could not express on its own.

   Deliberately NOT flipped: the hero core and the isometric stack. Those are scenes, not
   text — a 3D core mirrored for Arabic is the same core, and mirroring the isometric would
   break the 2:1 projection the whole figure is built on. Only reading order flips. */
[dir="rtl"] .nav-links { margin-left: 0; margin-right: 14px; }
[dir="rtl"] .nav-actions { margin-left: 0; margin-right: auto; }
[dir="rtl"] .mmini { left: auto; right: -14px; }
[dir="rtl"] .toc a { border-left: 0; border-right: 2px solid var(--line); padding: 7px 13px 7px 0; }
[dir="rtl"] .toc a:hover, [dir="rtl"] .toc a.is-here { border-right-color: var(--blue); }
[dir="rtl"] .toc-rail { left: auto; right: 0; }
[dir="rtl"] .ulist { padding-left: 0; padding-right: 20px; }
[dir="rtl"] .howit-rail { left: auto; right: 25px; }
[dir="rtl"] .stacklist .howit-rail { left: auto; right: 21px; }
[dir="rtl"] .pr-frow dd, [dir="rtl"] .si-t, [dir="rtl"] .shotnav-item { text-align: right; }
[dir="rtl"] .ct-msg, [dir="rtl"] .hstep, [dir="rtl"] .sp-card { text-align: right; }

/* Latin fragments inside Arabic prose — brand names, emails, prices — need an explicit
   isolate or the bidi algorithm reorders the punctuation around them. */
[dir="rtl"] .ct-mail, [dir="rtl"] .pr-amount, [dir="rtl"] .pr-ticks, [dir="rtl"] .pr-egp {
  unicode-bidi: isolate;
}
[dir="rtl"] .pr-ticks { direction: ltr; }

/* SVG LABELS INSIDE THE ISOMETRIC.
   The slab labels carry no text-anchor, so they default to `start`. Under an RTL base
   direction `start` becomes the RIGHT edge, and every label grows leftward straight out of
   its slab — which is exactly what the Arabic build did.

   The fix is to pin the SCENE's text to LTR, not to mirror the scene. The isometric is a
   diagram whose anchors were computed against a 2:1 projection; flipping it would break the
   projection, and each label still shapes right-to-left internally, so the Arabic reads
   correctly. Only the anchor stops flipping. */
[dir="rtl"] .stackfig text { direction: ltr; }

/* the arrow glyphs in CTAs point the wrong way once the text runs right-to-left */
[dir="rtl"] .btn-primary span:last-child,
[dir="rtl"] .pr-cta a span:last-child,
[dir="rtl"] .ct-submit .label { transform: scaleX(1); }
[dir="rtl"] .mm-foot a, [dir="rtl"] .crumb { unicode-bidi: isolate; }

@media (max-width: 940px) { [dir="rtl"] .mmini { right: auto; left: -14px; } }

/* locale switch — quieter than the auth buttons it sits beside; it is a preference, not an action */
.nav-lang {
  font-size: 13.6px; font-weight: 600; color: #46587A;
  padding: 8px 13px; border-radius: 100px; border: 1px solid var(--line);
  transition: color .18s var(--ease), border-color .18s var(--ease);
}
.nav-lang:hover { color: var(--blue); border-color: rgba(31,98,255,.4); }
@media (max-width: 640px) { .nav-lang { display: none; } }
