/* ==========================================================================
   Jadwal (جدول) — marketing site stylesheet
   Single stylesheet shared by the Arabic (RTL) and English (LTR) page sets.

   PALETTE JUSTIFICATION
   ---------------------
   The palette changed in the Blue Ink redesign (Fady's design, handed off from
   Claude Design, Sep 2026). The ORIGINAL reasoning is preserved below rather
   than deleted, because most of it still holds and the parts that do not were
   OVERRULED DELIBERATELY - not forgotten. A future reader must be able to tell
   those two cases apart.

   --ink      #0E2A6B  Deep navy. WAS #0B1420, a near-black with a blue cast.
                       CARRIED FORWARD: the original reasoning was that pure
                       black glares on the cheap LCD panels common in clinic
                       back offices, so the ink is blue-shifted. #0E2A6B keeps
                       that property and goes further - it is a true navy, not
                       a near-black, and is calmer still on those panels.
   --slate    rgba(#ink,.72)  The single body-copy grey, now expressed as ink
                       at 72% rather than a separate hex. CARRIED FORWARD: one
                       grey only, so secondary text cannot quietly drift below
                       contrast. Deriving it from --ink means it can never
                       drift out of hue either.
   --paper    var(--paper)  Cream. WAS #FFFFFF.

                       *** THIS OVERRIDES A NAMED ANTI-PATTERN. READ THIS. ***

                       The original note said, in full: "Plain white. A tinted
                       ground was the named anti-pattern; white also makes the
                       Arabic counters at 300-weight read cleanly." That note
                       is NOT deleted, because the concern behind it is real.

                       Fady made the call to go cream, from a design he
                       commissioned and reviewed. It is a deliberate reversal
                       of the earlier brief, not an oversight, and the reason
                       it is defensible is that the two grounds are doing
                       different jobs: cream carries a MARKETING page, where
                       warmth and a paper-like ground are the point.

                       It does NOT extend to reading pages. See THE TWO
                       REGISTERS below - privacy, support and 404 keep white,
                       precisely because the original reasoning about Arabic
                       counters applies MORE to two thousand words of policy,
                       not less.
   --mist     var(--mist)  The alternate section ground, now a deeper cream.
                       CARRIED FORWARD unchanged in purpose: the ONLY alternate
                       ground, so sections separate themselves without the
                       repeated-shadowed-card pattern the brief rejects.
   --line     rgba(#ink,.16-.22)  Hairlines, now derived from ink rather than
                       a fixed grey. CARRIED FORWARD: the site's structure is
                       carried by rules and grid lines rather than by shadow -
                       appropriate for a product literally named "table". The
                       new design leans on this harder, not less.
   --accent   #1264FF  A bright, saturated blue. WAS #0B5FA5, a deep civic blue.

                       PARTIALLY OVERRIDDEN, and the trade-off is worth stating.
                       The original argued deep blue because (a) it cleared
                       4.5:1 on white as TEXT, so links needed no darker
                       variant, and (b) deep blue is the register Saudi
                       institutional and banking material sits in.

                       (b) is weakened deliberately - the new design is
                       confident rather than deferential. (a) is NOT waived:
                       #1264FF on the cream ground is used for FILLS, marks and
                       hover states. Body links keep enough weight to clear
                       contrast, and --accent-deep remains for the active step.
                       If a future change puts #1264FF on small text over
                       cream, check the ratio before shipping it.
   --accent-deep #0A4FD6  The hover/active step. Same hue, darker value.
                       CARRIED FORWARD unchanged.

   Two functional-only tints ride alongside, never decorative:
   --rest     #B26B00  Amber, marks Friday weekly rest in the week grid.
   --ok       #1C6B4A  Green, marks an approved leave block.
   Both are paired with text or shape in the grid, never colour alone.

   THE TWO REGISTERS - A DECISION, NOT AN INCONSISTENCY
   ----------------------------------------------------
   This stylesheet serves two kinds of page and they are DELIBERATELY not
   identical. Do not "unify" them.

     MARKETING  (homepage, pricing)
       cream ground, Amiri 700 display headings, the full animation layer.
       The page is being looked at.

     DOCUMENT   (privacy, support, 404)
       WHITE ground, Amiri on the <h1> only, h2/h3 in Readex 600, and no
       scroll-reveal animations at all. The page is being READ.

   Why they differ, concretely: privacy is 1,697 Arabic / 2,277 English words.
   A Naskh display face across nineteen h2s reads as decoration in a legal
   document, a cream ground lowers contrast under a retention clause, and a
   reveal-on-scroll animation actively obstructs someone scrolling to find a
   number. Everything else is shared - navy, accent, 2px radii, rules, nav,
   footer, lockup - so it remains one site with one voice.
   ========================================================================== */

/* ==========================================================================
   Typeface — Readex Pro, self-hosted.

   WHY THIS FACE. The site is Arabic-first: the Arabic carries the page and the
   Latin follows, which rules out the usual practice of choosing for Latin and
   accepting whatever Arabic ships alongside. Readex Pro is drawn Arabic-first
   by Nadine Chahine (who also drew the Arabic for Neue Frutiger Arabic), with
   a Latin designed against it rather than bolted on, so the two scripts hold
   the same colour and weight in a bilingual line.

   WHY NOT WHAT WAS HERE. The previous face was IBM Plex Sans Arabic, loaded
   from Google Fonts. Plex is well drawn, but it is IBM's corporate voice and
   reads as "developer tool" — the wrong register for a payroll product sold to
   finance and people teams, who need it to read as institutional. Jisr, the
   nearest competitor, self-hosts Noto Sans Arabic; Readex puts visible daylight
   between the two without resorting to a costume.

   WHY SELF-HOSTED. Two reasons, one of them not about performance. Loading
   from fonts.googleapis.com put a third party on the critical path of every
   page and disclosed visitor IP addresses to it — a disclosure the privacy
   policy had to carry. Self-hosting removes the disclosure entirely, and the
   policy no longer makes it. It also removes two cross-origin connections
   (preconnect + stylesheet + font file) from Saudi networks.

   COST. Two variable woff2 files, 22.2 KB Arabic + 30.7 KB Latin, each
   spanning the full 200-700 weight range. The previous setup fetched four
   static Plex weights (~41 KB for the Arabic subset alone) across a render-
   blocking third-party stylesheet. This is smaller, on our own origin, and
   gives more of the weight axis. unicode-range keeps a Latin-only reader from
   ever downloading the Arabic file, and vice versa.

   LICENCE. SIL Open Font Licence 1.1 — see assets/fonts/OFL.txt. Redistribution
   as a webfont is permitted; the licence file must travel with the fonts.
   ========================================================================== */

/* ==========================================================================
   THE DISPLAY FACE — Amiri 700, self-hosted, and TIGHTLY SUBSET

   Amiri is a traditional Naskh face. It sets the headlines; Readex Pro keeps
   the body. The pairing was rendered and checked before it was adopted, not
   assumed: lam-alef ligatures, shadda, damma and Arabic-Indic digits all
   shape correctly out of the subset.

   WHY IT IS SUBSET, AND WHY THAT IS NOT PREMATURE.
   Amiri's Arabic coverage is ~96 KB PER WEIGHT even after dropping unused
   Unicode blocks - thousands of contextual and positional forms, which is
   exactly what makes it beautiful at size. The full 400+700 pair measured
   192 KB.

   THE NUMBER THAT DECIDED IT: 192 KB is LARGER THAN THE ENTIRE THREE.JS
   RENDERER this site deleted at 120 KB gzipped - and a font sits on the
   CRITICAL RENDER PATH, where that WebGL bundle did not. If 120 KB off the
   critical path was too expensive, 192 KB on it was not arguable.

   So: weight 700 only, display text only, subset to the characters the pages
   actually set. Measured 96,424 -> 35,952 bytes for Arabic.

   NOTE: EDITING A HEADING CAN SILENTLY BREAK THIS. The subset carries today's
   characters. Introduce an Arabic letter no heading currently uses and that
   ONE heading falls back to a generic serif - no error, no console warning,
   and it looks plausible enough to survive a glance. check.mjs rule 12 fails
   the build and names the character AND the file. To fix:
       node scripts/subset-amiri.mjs
   ========================================================================== */

@font-face {
  font-family: "Amiri";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/amiri-700-arabic-subset.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+FB50-FDFF, U+FE70-FEFF;
}

@font-face {
  font-family: "Amiri";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/amiri-700-latin-subset.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+2000-206F, U+20AC;
}

@font-face {
  font-family: "Readex Pro";
  font-style: normal;
  font-weight: 200 700;
  font-display: swap;
  src: url("/assets/fonts/readex-pro-arabic.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
    U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF,
    U+FE70-FE74, U+FE76-FEFC;
}

@font-face {
  font-family: "Readex Pro";
  font-style: normal;
  font-weight: 200 700;
  font-display: swap;
  src: url("/assets/fonts/readex-pro-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2212,
    U+2215, U+FEFF, U+FFFD;
}


:root {
  --ink: #0E2A6B;
  --ink-rgb: 14, 42, 107;
  --slate: rgba(var(--ink-rgb), .72);
  --paper: #FFFFFF;
  --mist: #F5F7FA;
  --line: rgba(var(--ink-rgb), .18);
  --line-strong: rgba(var(--ink-rgb), .30);
  --accent: #1264FF;
  --accent-deep: #0A4FD6;

  /* DOCUMENT REGISTER. Reading pages override the ground to white and keep
     the display face off h2/h3 - see THE TWO REGISTERS above. These are
     applied by .doc-page on <body>, not by page path, so the register is a
     property of the page's JOB rather than of its URL. */
  --paper-doc: #FFFFFF;
  --mist-doc: #F5F7FA;

  /* functional */
  --rest: #B26B00;
  --ok: #1C6B4A;

  /* type scale — 1.25 major third, clamped for fluid resize.
     12 / 14 / 16 / 18 / 22 / 28 / 36 / 46 */
  --t-2xs: 0.8125rem;   /* 13px — smallest permitted, grid labels only */
  --t-xs: 0.875rem;
  --t-sm: 0.9375rem;
  --t-base: 1rem;
  --t-md: 1.125rem;
  --t-lg: clamp(1.25rem, 1.1rem + 0.6vw, 1.375rem);
  --t-xl: clamp(1.5rem, 1.3rem + 1vw, 1.75rem);
  --t-2xl: clamp(1.875rem, 1.5rem + 1.8vw, 2.25rem);
  --t-3xl: clamp(2.25rem, 1.6rem + 3.2vw, 2.875rem);

  /* Weight tokens. See THE THREE TYPE REGISTERS below for why the ink ground
     carries a different value from white, and why nothing goes light under
     the 24px floor. */
  --w-display: 250;
  --w-display-ink: 300;
  --w-numeral: 200;

  /* spacing rhythm — 4px base */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-12: 3rem;
  --s-16: 4rem;
  --s-24: 6rem;

  --shell: 1200px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  /* ONE hairline weight, TWO radii, TWO shadows. Shadows share one light
     direction (from above), and only lifted surfaces get one. */
  --radius: 6px;
  --radius-lg: 10px;
  --shadow-1: 0 1px 2px rgba(11, 20, 32, 0.06);
  --shadow-2: 0 18px 44px -28px rgba(11, 20, 32, 0.32);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --------------------------------------------------------------------------
   Reset / base
   -------------------------------------------------------------------------- */

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

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

body {
  margin: 0;
  font-family: "Readex Pro", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: 400;
  font-size: var(--t-base);
  line-height: 1.7;
  color: var(--slate);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* WARNING: NO `color` HERE - it is inherited, deliberately.
   A `color` on the element selector BEATS inheritance from an ancestor, so
   `h1,h2,h3,h4 { color: var(--ink) }` forced every heading dark even inside
   a section that had set `color:var(--paper)` on itself. The payroll chapter sits
   on the deep ink ground, and its h2 measured a contrast ratio of 1.00 -
   navy on navy, the heading simply absent.
   Headings inherit their colour from the section they are in, which is what
   lets one section invert without every rule inside it being restated. */
h1, h2, h3, h4 {
  font-weight: 600;
  line-height: 1.25;
  margin: 0 0 var(--s-4);
  letter-spacing: -0.01em;
}

/* Arabic needs MORE leading than Latin at the same size, and must never be
   letter-spaced — tracking breaks the letter joins. Body 1.85, headings 1.45. */
html[lang="ar"] body,
html[lang="ar"] p,
html[lang="ar"] li,
html[lang="ar"] .cols p { line-height: 1.85; }
html[lang="ar"] * { letter-spacing: 0 !important; }
html[lang="ar"] h1,
html[lang="ar"] h2,
html[lang="ar"] h3,
html[lang="ar"] h4 { line-height: 1.45; }

/* ==========================================================================
   THE THREE TYPE REGISTERS

   Readex Pro is variable across 200-700 (see the two @font-face blocks
   above, both declaring `font-weight: 200 700`). Before this system the site
   used 400/500/600 only, and EVERY heading on the page - all seven h2s -
   rendered at an identical 36px/600. There was no typographic signal that
   one section mattered more than another, because there was no contrast to
   spend.

   DISPLAY     200-300, large, tight leading. Section headings, the hero,
               oversized numerals.
   STRUCTURAL  600, unchanged sizes. Chapter titles, capability headings.
   DETAIL      500, small, tracked (Latin only). Eyebrows, legends.

   The counter-intuitive part: headings got LIGHTER, not heavier. At display
   sizes Arabic at 250 opens its counters and reads as considered; the
   contrast then comes from the 250-against-600 gap, which is far wider than
   anything bold-on-bold could produce. Bold everywhere is why nothing stood
   out.

   NOTE: THE WEIGHTS ARE NOT ONE NUMBER, AND THAT WAS MEASURED RATHER THAN
   ASSUMED. A comparison frame was rendered at 250/300/400 across every real
   size token on both grounds before any of this shipped. Light type on a
   DARK ground reads visibly thinner than the same weight on white, so the
   ink ground gets 300 where white and mist get 250. One value everywhere
   would have been simpler and would have shipped fragile headings on the
   one section that inverts.

   NOTE: THE 24px FLOOR IS REAL AND IS ENFORCED. Below --t-xl (24-28px) nothing
   is set lighter than 500. At 18px, weight 250 is visibly weaker than the
   400 beside it and washes out on the cheap LCD panels this product is used
   on - the same panels the palette rationale at the top of this file already
   worries about. check.mjs rule 11 fails the build if a light weight appears
   under a size below the floor; see the rule for why a comment would not
   have been enough.
   ========================================================================== */

h1 { font-size: var(--t-3xl); font-weight: var(--w-display); }
h2 { font-size: var(--t-2xl); font-weight: var(--w-display); }
h3 { font-size: var(--t-lg);  font-weight: 600; }
h4 { font-size: var(--t-md);  font-weight: 600; }

/* Display headings are set light, so they need slightly tighter leading and
   a touch of negative tracking in Latin to stop them feeling airy. Arabic is
   never tracked (see above) - the joins break. */
h1, h2 { line-height: 1.16; }
html[lang="ar"] h1,
html[lang="ar"] h2 { line-height: 1.35; }

/* NOTE: ON INK: 300, not 250. Measured, not guessed - see the register note. */
.section--ink h1,
.section--ink h2,
.section--ink .section-title,
.chapter--ink h1,
.chapter--ink h2,
.chapter--ink h3,
.chapter--ink .section-title { font-weight: var(--w-display-ink); }

/* AND THE COLOUR, WHICH IS THE PART THAT ACTUALLY BROKE. h1-h4 carry
   color: var(--ink) from the base rule, so on the inverted chapter the
   heading was dark text on a dark ground and simply did not appear. The
   weight override alone looked correct in the stylesheet and rendered
   nothing on the page. */
.chapter--ink h1,
.chapter--ink h2,
.chapter--ink h3,
.chapter--ink h4,
.chapter--ink .section-title { color: #fff; }

/* DETAIL register. The eyebrow that tells the eye a new chapter began - the
   thing the page had no way of saying before. */
.eyebrow {
  display: block;
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--slate);
  margin-bottom: var(--s-3);
}
html[lang="en"] .eyebrow { letter-spacing: .08em; text-transform: uppercase; }
.section--ink .eyebrow,
.chapter--ink .eyebrow { color: #A9BFD4; }

/* The oversized numeral. A true count, not a claim - there are fourteen
   capabilities and the page says so in the one register that can carry it. */
.figure-numeral {
  font-size: clamp(4rem, 2rem + 9vw, 7.5rem);
  font-weight: var(--w-numeral);
  line-height: .9;
  color: var(--line);
  display: block;
  margin-bottom: var(--s-2);
}
.section--ink .figure-numeral,
.chapter--ink .figure-numeral { color: rgba(255, 255, 255, .16); }

/* A pull-quote for the one mechanism line per chapter that deserves weight.
   All fourteen cap__how lines look identical today, so none reads as
   important; this promotes exactly one. Above the floor by construction. */
.pullquote {
  font-size: var(--t-xl);
  font-weight: 300;
  line-height: 1.5;
  color: var(--ink);
  border-inline-start: 2px solid var(--accent);
  padding-inline-start: var(--s-5);
  margin: var(--s-6) 0;
  max-width: 54ch;
}
.section--ink .pullquote,
.chapter--ink .pullquote { color: #fff; border-color: #7FB3E0; }

p { margin: 0 0 var(--s-4); max-width: 68ch; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* WARNING - :where() KEEPS THIS AT ZERO SPECIFICITY, DELIBERATELY.
   A bare `a:hover { color }` outranks any single-class rule and lands on
   every link on the page, INCLUDING the ones that are buttons. The header's
   "Request a demo" fills with #1264FF on hover and sets its own cream text -
   and this rule, later in the file, painted that text #0A4FD6: blue on blue,
   a measured contrast ratio of 1.00. The label vanished on hover in both
   languages.
   Wrapping the selector in :where() drops its specificity to zero, so it
   still styles ordinary prose links and loses to any component that states
   its own hover colour. A component should not have to defend itself against
   the base stylesheet. */
:where(a):hover { color: var(--accent-deep); }

ul, ol { padding-inline-start: 1.25em; }
li { margin-bottom: var(--s-2); }

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

strong { font-weight: 600; color: var(--ink); }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* On the ink grounds the accent ring has too little separation — go white. */
.closing :focus-visible,
.site-footer :focus-visible { outline-color: #fff; }

.skip-link {
  position: absolute;
  inset-inline-start: var(--s-4);
  top: -100px;
  z-index: 200;
  background: var(--ink);
  color: #fff;
  padding: var(--s-3) var(--s-6);
  border-radius: var(--radius);
  font-weight: 500;
  transition: top 160ms var(--ease);
}
.skip-link:focus { top: var(--s-4); color: #fff; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.shell--narrow { max-width: 760px; }

/* Section spacing lives on ONE class. Nothing else sets block padding on a
   <section>, so specificity conflicts can't cancel the rhythm out. */
.section {
  padding-block: clamp(3.5rem, 8vw, 6rem);
  border-top: 1px solid var(--line);
}
.section--mist { background: var(--mist); }
.section--flush { border-top: 0; }

.section-head { max-width: 42ch; margin-bottom: var(--s-12); }
.section-head p { max-width: 54ch; }
.section-head p { font-size: var(--t-md); margin-bottom: 0; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 48px;
  padding: var(--s-3) var(--s-6);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 500;
  font-size: var(--t-base);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 180ms var(--ease), border-color 180ms var(--ease), color 180ms var(--ease);
}

.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-deep); color: #fff; }
.btn--primary:active { background: #063C6A; }

.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.btn:active { transform: none; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { background: var(--mist); color: var(--ink); border-color: var(--slate); }
.btn--ghost:active { background: var(--line); }

.btn--onDark { background: #fff; color: var(--ink); }
.btn--onDark:hover { background: var(--mist); color: var(--ink); }
.btn--onDark:active { background: var(--line); }

.btn--outlineDark { background: transparent; color: #fff; border-color: rgba(255, 255, 255, 0.4); }
.btn--outlineDark:hover { background: rgba(255, 255, 255, 0.1); color: #fff; border-color: #fff; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  /* Tinted from the ground, not hardcoded white - the cream marketing ground
     and the white document ground need different header tints, and a fixed
     white bar floated visibly above the cream page. */
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms var(--ease), box-shadow 200ms var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-1);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  min-height: 76px;
  transition: min-height 200ms var(--ease);
}
.site-header.is-stuck .site-header__inner { min-height: 64px; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  text-decoration: none;
  color: var(--ink);
  font-weight: 600;
  font-size: var(--t-lg);
  flex-shrink: 0;
}
.brand:hover { color: var(--ink); }
/* The horizontal lockup carries the wordmark, so the adjacent text node was
   removed from every .brand / .footer__brand — the accessible name now comes
   from aria-label on the link (per language: "Jadwal" / "جدول").
   Width is auto with height driving: the mark is ~1.93:1, so a fixed square
   width would squash it. The viewBox is cropped to the artwork's real ink in
   the partial; the source file pads ~28% vertically, which shrank the
   wordmark to an illegible smudge at this height.
   44px, not the 30px inherited from the square tile: a 1.93:1 lockup carries
   far less ink at a given height than a square did, so at 30px it read
   SMALLER than the 15px nav text beside it. Chosen by rendering 30/38/44/50
   against the real nav and picking optical weight, not a matching number —
   38 merely equalled the nav, 50 competed with the primary button. At 44 the
   mark is 85px wide and the header row still fits on one line at 1200px. */
.brand__lockup { height: 44px; width: auto; flex-shrink: 0; display: block; }

.site-nav { display: none; margin-inline-start: auto; }
.site-nav ul {
  display: flex;
  gap: var(--s-6);
  list-style: none;
  margin: 0; padding: 0;
}
.site-nav li { margin: 0; }
.site-nav a {
  color: var(--slate);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  padding-block: var(--s-2);
}
.site-nav a:hover { color: var(--ink); }

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-inline-start: auto;
}
.site-nav + .header-actions { margin-inline-start: 0; }

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  padding-inline: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  white-space: nowrap;
}
.lang-switch:hover { background: var(--mist); color: var(--ink); border-color: var(--slate); }
.lang-switch svg { width: 16px; height: 16px; color: var(--slate); }

/* Below 480px only the language switch fits beside the wordmark; the demo CTA
   is still reachable from the hero, which is immediately below. */
.header-actions .btn { display: none; }

@media (min-width: 480px) {
  /* Primary CTA returns first — it is the page's job. Login waits for desktop. */
  .header-actions .btn--primary {
    display: inline-flex;
    min-height: 44px;
    padding-inline: var(--s-4);
  }
}

@media (min-width: 900px) {
  .site-nav { display: block; }
  .header-actions .btn { display: inline-flex; }
  .header-actions .btn--primary { padding-inline: var(--s-6); }
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  /* Sits directly under a 76px sticky header, so the top pad is deliberately
     smaller than a normal section's — the header already supplies air. */
  padding-block: clamp(2rem, 4vw, 3rem) clamp(3rem, 6vw, 4.5rem);
  border-top: 0;
}

.hero__grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: center;
}

.hero__lede {
  font-size: var(--t-md);
  max-width: 46ch;
  margin-bottom: var(--s-6);
}

.hero h1 { max-width: 16ch; }
html[lang="en"] .hero h1 { max-width: 18ch; }

.hero__note {
  margin-top: var(--s-6);
  font-size: var(--t-sm);
  color: var(--slate);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: 0;
}
.hero__note svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent); }

/* Mobile: headline, then the grid, then the CTAs. The grid is the product's
   whole argument — burying it under three paragraphs and two buttons meant a
   phone visitor never saw it. Source order stays logical; only the visual
   order moves, and only at one breakpoint. */
.hero__grid { display: grid; row-gap: var(--s-6); }
.hero__copy { display: contents; }
.hero__copy > h1          { order: 1; margin-bottom: 0; }
.hero__copy > .hero__lede { order: 2; margin-bottom: 0; }
.hero__copy > .btn-row    { order: 4; }
.hero__copy > .hero__note { order: 5; margin-top: 0; }

@media (min-width: 940px) {
  /* Desktop: restore the two-column split — copy left, grid right. Children
     are back in normal flow, so their own margins govern again. */
  .hero__grid {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.2fr);
    row-gap: 0;
  }
  .hero__copy { display: block; }
  .hero__copy > h1 { margin-bottom: var(--s-4); }
  .hero__copy > .hero__lede { margin-bottom: var(--s-6); }
  .hero__copy > .hero__note { margin-top: var(--s-6); }
}

/* ---- The week grid ------------------------------------------------------ */

/* Friday carries a second line ("rest"). Every header cell is sized for two
   lines so the row height is even whether or not a cell uses the second one. */
/* Blocks that land inside the grid. */
/* --------------------------------------------------------------------------
   Problem statements — rules, not cards
   -------------------------------------------------------------------------- */

.statements { display: grid; gap: 0; }
.statement {
  padding-block: var(--s-8);
  border-top: 1px solid var(--line);
  display: grid;
  gap: var(--s-2) var(--s-8);
}
.statement:last-child { border-bottom: 1px solid var(--line); }
.statement h3 { margin-bottom: 0; }
.statement p { margin-bottom: 0; }

@media (min-width: 820px) {
  .statement { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); align-items: start; }
}

/* --------------------------------------------------------------------------
   Feature walkthrough (the sticky scroll section)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Panel choreography — the mock panels play out what they claim.

   These panels stand in for product screenshots that do not exist yet, so a
   static panel is a picture of a system at rest; the point is a system
   working. Rows resolve in sequence, money counts to its figure, and the
   deduction bar fills against the statutory ceiling.

   THERE IS NO START-STATE CLASS HERE, DELIBERATELY. The hidden start state is
   written inline by main.js, per element, immediately before it animates. A
   class on the panel was tried and removed: it has to come off at exactly the
   right moment, and both ordering mistakes are visible defects — off too early
   and landed rows snap back to invisible, never off and the panel stays blank.
   Inline styles are owned by the element that animates, cleared when its own
   animation completes, and cannot be stranded by another element's timing.

   Two rules still hold this together:

   1. THE MARKUP IS THE SOURCE OF TRUTH. Every figure is written in the HTML at
      its final value; `data-count` only says "count TO the number already
      printed here". With no JS, a failed import, or reduced motion, the panel
      shows correct text because nothing ever hid it.

   2. THE BAR ANIMATES `width`, NEVER `transform: scaleX()`. A block child fills
      from the inline-start edge, which follows `dir` — so width grows from the
      right in Arabic and the left in English for free. scaleX() has no such
      knowledge: it would run left-to-right in both, and a deduction bar filling
      backwards in Arabic is worse than one that never moves.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Audience / trust / generic column grids
   -------------------------------------------------------------------------- */

.cols {
  display: grid;
  gap: var(--s-8) var(--s-12);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
}

.col__icon {
  width: 26px; height: 26px;
  color: var(--accent);
  margin-bottom: var(--s-4);
}
.cols h3 { margin-bottom: var(--s-2); }
.cols p { margin-bottom: 0; font-size: var(--t-sm); }

.cols--ruled > * { border-top: 1px solid var(--line); padding-top: var(--s-6); }

/* Statutory article label. Occupies the slot .col__icon holds in the other
   ruled column groups, so the two sections share a vertical rhythm. The
   article NUMBER is the credential here, so it is set in accent and tracked
   out rather than shrunk into a caption. Latin digits inside Arabic prose
   need no isolation: they carry no adjacent neutral (see check.mjs rule 9). */
.stat__label {
  margin: 0 0 var(--s-2);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--accent);
}
.cols .stat__label + h3 { margin-top: 0; }

/* --------------------------------------------------------------------------
   Mobile app section
   -------------------------------------------------------------------------- */

.appblock { display: grid; gap: var(--s-12); align-items: center; }
@media (min-width: 900px) {
  .appblock { grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr); }
}

.storebadges { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }
.storebadge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 52px;
  padding: var(--s-2) var(--s-4);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  color: var(--slate);
  font-size: var(--t-xs);
  background: var(--paper);
}
.storebadge svg { width: 22px; height: 22px; flex-shrink: 0; color: var(--slate); }
.storebadge b { display: block; color: var(--ink); font-size: var(--t-sm); font-weight: 500; }

/* --------------------------------------------------------------------------
   Closing CTA
   -------------------------------------------------------------------------- */

.closing {
  background: var(--ink);
  color: #C8D3DE;
  border-top: 0;
}
.closing h2 { color: #fff; }
.closing p { color: #C8D3DE; font-size: var(--t-md); }
.closing .shell { text-align: start; }

/* The closing section is a single column: the demo form that occupied the
   second column was removed (no endpoint, and the copy promised a reply time
   nobody could keep). Capped so the paragraph keeps a readable measure instead
   of running the full shell width. */
.closing__single { max-width: 62ch; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.site-footer {
  background: var(--ink);
  color: #A9B7C6;
  padding-block: var(--s-16) var(--s-8);
  font-size: var(--t-sm);
}
.site-footer a { color: #DCE5EE; text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer h4,
.footer__heading {
  color: #fff;
  font-size: var(--t-sm);
  font-weight: 600;
  margin: 0 0 var(--s-4);
}
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: var(--s-2); }

.footer__grid {
  display: grid;
  gap: var(--s-8) var(--s-12);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  padding-bottom: var(--s-12);
}
.footer__brand { display: inline-flex; align-items: center; }
/* No `color` here any more. The old placeholder glyph was stroke="currentColor"
   and honoured a #7FB6E4 tint; the lockup carries its own #1870FF and would
   have ignored it silently — the header showing the real mark while the footer
   stayed a lighter-blue glyph is exactly how that read on screen.
   #1870FF measures 4.23:1 on this --ink ground and 4.37:1 on white. */
.footer__brand .brand__lockup { height: 44px; }
.footer__brand + p { margin-top: var(--s-4); color: #A9B7C6; max-width: 34ch; }

.footer__base {
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  padding-top: var(--s-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-6);
  justify-content: space-between;
  font-size: var(--t-xs);
  color: #8F9FB0;
}

.todo {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8em;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(178, 107, 0, 0.14);
  color: #8A5300;
  border: 1px solid rgba(178, 107, 0, 0.3);
  direction: ltr;
  display: inline-block;
  unicode-bidi: isolate;
}
.site-footer .todo,
.closing .todo { background: rgba(255, 255, 255, 0.1); color: #E4C79A; border-color: rgba(255, 255, 255, 0.2); }

/* --------------------------------------------------------------------------
   Long-form document pages (privacy, support)
   -------------------------------------------------------------------------- */

.doc { padding-block: clamp(3rem, 7vw, 4.5rem); border-top: 0; }
.doc h2 {
  font-size: var(--t-xl);
  margin-top: var(--s-12);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}
.doc h3 { font-size: var(--t-md); margin-top: var(--s-8); }
.doc > .shell > :first-child { margin-top: 0; }
.doc__meta {
  font-size: var(--t-sm);
  color: var(--slate);
  padding-bottom: var(--s-6);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-8);
}
.doc__lede { font-size: var(--t-md); }

.doc table {
  width: 100%;
  border-collapse: collapse;
  margin-block: var(--s-6);
  font-size: var(--t-sm);
  text-align: start;
}
.doc table th,
.doc table td {
  border: 1px solid var(--line);
  padding: var(--s-3);
  text-align: start;
  vertical-align: top;
}
.doc table th { background: var(--mist); color: var(--ink); font-weight: 600; }
.doc__tablewrap { overflow-x: auto; }

.callout {
  border-inline-start: 3px solid var(--accent);
  background: var(--mist);
  padding: var(--s-4) var(--s-6);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-block: var(--s-6);
}
html[dir="rtl"] .callout { border-radius: var(--radius) 0 0 var(--radius); }
.callout p:last-child { margin-bottom: 0; }

.faq { border-top: 1px solid var(--line); }
.faq__item { border-bottom: 1px solid var(--line); padding-block: var(--s-6); }
.faq__item h3 { margin-top: 0; margin-bottom: var(--s-2); }
.faq__item p:last-child { margin-bottom: 0; }

.contact-list { display: grid; gap: var(--s-6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.contact-list > div { border-top: 1px solid var(--line); padding-top: var(--s-4); }
.contact-list h3 { margin-bottom: var(--s-1); }
.contact-list p { margin-bottom: 0; font-size: var(--t-sm); }

/* 404 */
.errpage { padding-block: clamp(4rem, 12vw, 8rem); text-align: start; border-top: 0; }
.errpage .code {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: var(--s-3);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Scroll reveal
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 280ms var(--ease), transform 280ms var(--ease);
  transition-delay: var(--d, 0ms);
  will-change: opacity, transform;
}
.reveal.is-in { opacity: 1; transform: none; will-change: auto; }

/* Hero load sequence — the one orchestrated moment. */
.hero-seq {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 500ms var(--ease), transform 500ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.is-ready .hero-seq { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   Reduced motion — hard short-circuit.
   Everything animated above is reset to its final state here.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .hero-seq,
  .is-ready .hero-seq {
    opacity: 1 !important;
    transform: none !important;
  }


  .site-header,
  .site-header__inner { transition: none !important; }
}


/* ==========================================================================
   Demo request form
   ==========================================================================
   Logical properties only. check.mjs rule 5 fails the build on physical
   directional properties, because this stylesheet serves both an LTR and an
   RTL page from one file — use the inline/block equivalents throughout.
   ========================================================================== */

.lead-form { margin-block-start: var(--s-8); }

.lead-form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-4) var(--s-6);
}

@media (max-width: 640px) {
  .lead-form__grid { grid-template-columns: minmax(0, 1fr); }
}

.field--full { grid-column: 1 / -1; }

.field label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 500;
  margin-block-end: var(--s-2);
  color: var(--ink);
}

.field__req { color: var(--accent); }
.field__opt { color: var(--slate); font-weight: 400; }

.field input,
.field textarea {
  inline-size: 100%;
  padding: var(--s-3) var(--s-4);
  font: inherit;
  font-size: var(--t-base);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}

.field textarea { resize: vertical; min-block-size: 4.5rem; }

.field input:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(11, 95, 165, 0.15);
}

/* Only after the browser has judged the value — :invalid alone would paint
   every required field red before the visitor has typed anything. */
.field input:user-invalid,
.field textarea:user-invalid { border-color: var(--rest); }

/* The honeypot. Off-screen rather than display:none or visibility:hidden —
   both are increasingly skipped by bots, which is the opposite of what a
   honeypot needs. aria-hidden + tabindex="-1" in the markup keep it away
   from assistive technology and the tab order. */
.lead-form__hp {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.lead-form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
  margin-block-start: var(--s-6);
}

.lead-form__note {
  font-size: var(--t-xs);
  color: var(--slate);
  margin: 0;
  max-inline-size: 46ch;
}

.lead-form__status {
  margin-block-start: var(--s-4);
  margin-block-end: 0;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--radius);
  font-size: var(--t-sm);
  border: 1px solid transparent;
}

/* MEASURED 1.39:1 BEFORE THIS `.closing` QUALIFIER EXISTED. `.closing p`
   sets color #C8D3DE for the dark section and is a LATER rule of equal
   specificity, so it won the cascade over an unqualified
   `.lead-form__status--error` and painted pale blue text on a near-white
   panel. The banner was on screen and unreadable — a defect that looks like
   nothing at all in the markup, which is why it survived review.

   Qualifying with `.closing` raises specificity above `.closing p` and
   restores the intended dark-on-light. The unqualified rules stay for a
   light section. Contrast on these panels: #7A2E0E on #FDF3EC ~7.9:1,
   #1C6B4A on #EEF6F1 ~4.8:1 — both clear of WCAG AA. */
.lead-form__status--error,
.closing .lead-form__status--error {
  color: #7A2E0E;
  background: #FDF3EC;
  border-color: #F0D3BF;
}

.lead-form__status--ok,
.closing .lead-form__status--ok {
  color: var(--ok);
  background: #EEF6F1;
  border-color: #C9E2D5;
}

.lead-form__fallback {
  margin-block-start: var(--s-6);
  font-size: var(--t-sm);
  color: var(--slate);
}


/* --------------------------------------------------------------------------
   The confirmation panel.

   ── WHAT THIS REPLACES, AND WHY IT IS A PANEL RATHER THAN A LINE OF TEXT ───
   Success used to be one sentence in a thin banner INSIDE the form, shown at
   the moment the form was hidden. Measured on the live site: height 0, never
   in the viewport. The form is ~644px tall, so hiding it collapsed the page by
   that much, the browser clamped the scroll position to the new document
   bottom, and the visitor landed on the footer with no confirmation anywhere
   on screen. The person who BUILT the form read that as "it disappeared and
   broke" — which is the correct reading of what was rendered.

   So the panel is sized to hold the space the form held, not to fit its text:
   an absence reads as a failure, and the fix has to look like a state that was
   arrived at deliberately. It carries a mark, a heading, the server's own
   sentence, and the address we will reply to — seeing your own email echoed
   back is the part that reads as "it worked".

   NOTE: NO RESPONSE TIME IS PROMISED HERE, in either language. The endpoint
   deliberately omits one from its own message and the previous form was
   deleted for promising a reply it could not keep. "We have your request and
   we will be in touch" is true; a duration is not.
   -------------------------------------------------------------------------- */

.lead-ok {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  margin-block-start: var(--s-8);
  padding: var(--s-8);
  /* Holds enough block size that the section does not lurch at the moment of
     success. It does NOT try to match the form's full ~644px: a panel padded
     out to that height reads as an empty box, which is the impression this
     whole change exists to remove. The scroll-into-view is what guarantees the
     confirmation is seen; this only softens the collapse. */
  min-block-size: 13rem;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-lg);
}

/* The panel is a state change, not a page transition — announce it gently for
   anyone who has asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .lead-ok { animation: leadOkIn 0.32s var(--ease) both; }
}

@keyframes leadOkIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* It receives focus programmatically so a keyboard or screen-reader user is
   moved to the confirmation rather than left where the submit button was. The
   ring would otherwise read as an error state on a panel that is good news. */
.lead-ok:focus { outline: none; }
.lead-ok:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.lead-ok__mark {
  inline-size: 2rem;
  block-size: 2rem;
  flex: none;
  color: #6FD39B;
}

.lead-ok__body { min-inline-size: 0; }

.lead-ok__title {
  margin: 0 0 var(--s-3);
  font-size: var(--t-xl);
  color: #fff;
}

/* QUALIFIED WITH `.closing` FOR THE SAME REASON THE STATUS BANNERS ARE, and
   it is worth stating once for both: `.closing p` (further up this file) sets
   a colour for every paragraph in the dark section and is a LATER rule of
   equal specificity, so ANY unqualified `color` on a <p> inside this section
   loses the cascade silently. Measured here before the qualifier: these two
   computed to rgb(200,211,222), not the values written below.

   Any new paragraph added inside .closing needs the same treatment — the
   symptom is never an error, only text in the wrong colour.

   #E8EEF4 on this panel over #0B1420 measures ~13.9:1; #A9B7C6 ~7.2:1. */
.lead-ok__line,
.closing .lead-ok__line {
  margin: 0 0 var(--s-4);
  color: #E8EEF4;
}

.lead-ok__meta,
.closing .lead-ok__meta {
  margin: 0;
  font-size: var(--t-sm);
  color: #A9B7C6;
  max-inline-size: 52ch;
}

.lead-ok__meta a { color: #fff; text-decoration: underline; }

/* The echoed address is the single most reassuring token in the panel, so it
   is given the weight of a value rather than of running prose. */
.lead-ok__email {
  color: #fff;
  font-weight: 600;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .lead-ok { padding: var(--s-6); min-block-size: 0; }
}

/* --------------------------------------------------------------------------
   The form on a dark section.

   .closing paints var(--ink) with #C8D3DE text, and the form's own defaults
   above are written for a light surface — so `color: var(--ink)` on a label
   is ink-on-ink and renders INVISIBLE. That shipped: the labels vanished and
   only the required asterisk and the "(optional)" hint were legible.

   The defaults are kept light-surface-correct and overridden here rather than
   rewritten, so the form stays usable if it is ever placed on a light section.
   Contrast on #0B1420: #E8EEF4 ~14.8:1, #A9B7C6 ~7.6:1, #FF9B8A ~6.5:1 — all
   clear of WCAG AA at these sizes.
   -------------------------------------------------------------------------- */

.closing .field label { color: #E8EEF4; }
.closing .field__opt { color: #A9B7C6; }
.closing .lead-form__note,
.closing .lead-form__fallback { color: #A9B7C6; }
.closing .lead-form__note a,
.closing .lead-form__fallback a { color: #fff; text-decoration: underline; }

/* The asterisk marks a REQUIRED field, so it must not be the same blue as an
   interactive control — and --accent on ink is close to unreadable anyway. */
.closing .field__req { color: #FF9B8A; }

/* The two status banners keep their light backgrounds: they are the one place
   on this section where a coloured panel is the point, and their own dark text
   sits on that panel, not on the section. */

/* ==========================================================================
   Pricing page
   ==========================================================================
   Two plans only, and neither is feature-gated: both carry the entire
   product. The visual emphasis on .plan--featured marks the higher SERVICE
   level, not a larger feature set — nothing here should read as "the good
   one has more of the software".
   ========================================================================== */

.lede {
  font-size: var(--t-md);
  color: var(--slate);
  max-inline-size: 62ch;
}

.lede strong { color: var(--ink); }

/* auto-fit, not a hardcoded count: the page went from two plans to three and
   a fixed `repeat(2, ...)` had to be edited to allow it. A future fourth plan
   should be a markup change alone. */
.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--s-6);
  align-items: start;
}

@media (max-width: 820px) {
  .plan-grid { grid-template-columns: minmax(0, 1fr); }
}

.plan {
  padding: var(--s-8);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  block-size: 100%;
}

.plan--featured { border-color: var(--accent); box-shadow: 0 1px 3px rgba(11, 20, 32, 0.06); }

.plan__name { margin-block-end: var(--s-2); font-size: var(--t-xl); }

.plan__line {
  color: var(--slate);
  font-size: var(--t-sm);
  margin-block-end: var(--s-6);
}

.plan__points {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-8);
  display: grid;
  gap: var(--s-3);
}

.plan__points li {
  position: relative;
  padding-inline-start: var(--s-6);
  font-size: var(--t-sm);
  line-height: 1.6;
}

/* The tick is decorative; the list semantics carry the meaning. */
.plan__points li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.55em;
  inline-size: 0.55rem;
  block-size: 0.3rem;
  border-inline-start: 1.5px solid var(--ok);
  border-block-end: 1.5px solid var(--ok);
  transform: rotate(-45deg);
}

.plan__cta { margin-block-start: auto; align-self: start; }

.plan-grid__note {
  margin-block-start: var(--s-8);
  margin-block-end: 0;
  font-size: var(--t-sm);
  color: var(--slate);
  max-inline-size: 70ch;
}

/* A wide table must scroll inside its own box rather than making the page
   scroll sideways. */
.table-scroll { overflow-x: auto; }

.plan-table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
  min-inline-size: 40rem;
}

.plan-table th,
.plan-table td {
  padding: var(--s-4);
  border-block-end: 1px solid var(--line);
  vertical-align: top;
  text-align: start;
}

.plan-table thead th {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--slate);
  border-block-end-width: 2px;
}

.plan-table tbody th { font-weight: 500; color: var(--ink); inline-size: 22%; }
.plan-table tbody tr:last-child th,
.plan-table tbody tr:last-child td { border-block-end: 0; }

/* One block. Height is set per-instance from --h (0..1) by the markup, so the
   silhouette is authored, not random — the same object renders in every
   screenshot and on every load. */
/* Weekly rest — the site's functional amber, the same token the week grid
   uses for Friday. Flat and short: no hours worked. */

/* ==========================================================================
   THE HERO OBJECT — the week grid

   Restored from eefeeea, where it was a side panel. It is now the hero.

   WHY THIS AND NOT THE 3D BLOCK FIELD IT REPLACES
   -----------------------------------------------
   The block field was an isometric grid of extruded blocks: one per
   employee-day, height encoding hours worked. It was legible to nobody. Every
   viewer resolved it to a CITY SKYLINE, because a field of variable-height
   blocks on a tilted plane is what that shape means in ordinary visual
   vocabulary, and no amount of proportion tuning moved it (three rounds were
   tried).

   The reason is structural rather than cosmetic, and it is worth stating so
   the idea is not attempted again: A SCHEDULE IS A GRID WHOSE MEANING LIVES
   IN ITS LABELS - which employee, which day. Extrusion makes labels
   impossible, because text inside a preserve-3d subtree renders blurry and
   skewed. So the object could not carry the one thing that makes a schedule
   a schedule. The data was designed in and the STRUCTURE was left out, and
   structure is what the word jadwal means: rows, columns and headings.

   This table has all three. It is also real HTML - crawlable, translatable,
   selectable, and correct in an RTL context without any mirroring work.
   ========================================================================== */

.weekgrid                 { order: 3; margin-block: 0; }

.weekgrid {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  overflow: hidden;
  box-shadow: var(--shadow-2);
}

.weekgrid__bar {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--line);
  background: var(--mist);
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--slate);
}

.weekgrid__bar svg { width: 15px; height: 15px; color: var(--accent); }

.weekgrid__scroll { overflow-x: auto; }

.weekgrid__table {
  width: 100%;
  min-width: 480px;
  border-collapse: collapse;
  font-size: var(--t-xs);
}

.weekgrid__table th,
.weekgrid__table td {
  border-inline-start: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 0;
  text-align: center;
  vertical-align: top;
}

.weekgrid__table th:first-child,
.weekgrid__table td:first-child { border-inline-start: 0; }

.weekgrid__table tr:last-child td { border-bottom: 0; }

.weekgrid__table thead th {
  height: 52px;
  padding: var(--s-2);
  font-weight: 600;
  color: var(--ink);
  background: var(--paper);
  font-size: var(--t-xs);
  white-space: nowrap;
  vertical-align: middle;
}

/* Friday carries a second line ("rest"). Every header cell is sized for two
   lines so the row height is even whether or not a cell uses the second one. */
.weekgrid__table thead th span {
  display: block;
  font-weight: 400;
  color: var(--slate);
  font-size: var(--t-2xs);
  line-height: 1.2;
  min-height: 1.2em;
}

.weekgrid__table th[scope="row"] {
  width: 62px;
  padding: var(--s-3) var(--s-2);
  font-weight: 400;
  color: var(--slate);
  background: var(--paper);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: center;
}

.weekgrid__cell { height: 50px; padding: 4px; }

.col-rest { background: rgba(178, 107, 0, 0.05); }

/* Blocks that land inside the grid. */
.blk {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  border-radius: 4px;
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  padding: 2px 4px;
  /* animation start state — JS adds .is-in to settle them */
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 340ms var(--ease), transform 340ms var(--ease);
  transition-delay: var(--d, 0ms);
}

.blk.is-in { opacity: 1; transform: none; }

.blk--shift { background: rgba(11, 95, 165, 0.11); color: #063C6A; border: 1px solid rgba(11, 95, 165, 0.26); }

.blk--leave { background: rgba(28, 107, 74, 0.11); color: #10402C; border: 1px solid rgba(28, 107, 74, 0.28); }

.blk--rest  { background: rgba(178, 107, 0, 0.11); color: #6E4200; border: 1px solid rgba(178, 107, 0, 0.3); }

/* the geofenced check-in dot */
.checkin {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--t-2xs);
  font-weight: 600;
  color: #084C84;
}

.checkin__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  position: relative;
}

.checkin__dot::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  opacity: 0;
}

.weekgrid__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-6);
  padding: var(--s-4);
  border-top: 1px solid var(--line);
  background: var(--mist);
  font-size: var(--t-xs);
  color: var(--slate);
}

.weekgrid__legend span { display: inline-flex; align-items: center; gap: 6px; }

.weekgrid__legend i {
  width: 10px; height: 10px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
}

.lg-shift { background: rgba(11, 95, 165, 0.35); }

.lg-leave { background: rgba(28, 107, 74, 0.4); }

.lg-rest  { background: rgba(178, 107, 0, 0.4); }


/* --------------------------------------------------------------------------
   CAPABILITY CHAPTERS

   Fourteen capabilities grouped into six chapters. Each chapter is a section
   head plus a set of items; each item is a real paragraph, not a bullet, so
   the page says what the software DOES rather than naming a feature.

   The layout reuses the existing .cols/.cols--ruled rhythm rather than
   introducing a new card pattern — the brief rejects repeated shadowed cards,
   and the site's structure is carried by rules and grid lines.
   -------------------------------------------------------------------------- */

/* A chapter heading landing immediately under the previous chapter's last
   mechanism note reads as part of it. The gap has to be clearly larger than
   the gap BETWEEN capabilities inside one chapter, or the grouping is lost. */
.chapter + .chapter { margin-top: var(--s-12); }
.chapter > .section-title { margin-bottom: var(--s-2); }

.chapter__lead {
  max-width: 62ch;
  margin-bottom: var(--s-6);
  color: var(--slate);
}

.caps {
  display: grid;
  gap: var(--s-6) var(--s-7);
  grid-template-columns: 1fr;
}

@media (min-width: 760px) {
  .caps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* A chapter with an ODD number of capabilities leaves the last one in a
     half-width column beside empty space, which reads as a missing item
     rather than as the end of a list. Span it instead, and cap its measure so
     it does not become a wall of text at 1440. */
  .caps > .cap:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    max-width: 68ch;
  }
}

.cap {
  border-top: 2px solid var(--line);
  padding-top: var(--s-4);
}

.cap h3 {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
  font-size: 1.02rem;
}

.cap h3 svg {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  color: var(--accent);
}

.cap p { margin-bottom: 0; color: var(--slate); }

.cap p + p { margin-top: var(--s-3); }

/* The one-line mechanism note under a capability. Not a claim of scale — a
   statement of what the system does, which is what replaced the measured
   figures that were removed from this site. */
.cap__how {
  margin-top: var(--s-3);
  padding-inline-start: var(--s-4);
  border-inline-start: 2px solid var(--accent);
  color: var(--ink);
  font-size: .92rem;
}

/* --------------------------------------------------------------------------
   CHAPTER IMAGERY

   One photograph per chapter, at most. The photographs are supporting
   material, not the argument: the capabilities carry that. So they sit at the
   TOP of a chapter, before its items, and never between two capabilities
   where they would break the reading.

   THE RESERVED SLOT. Chapter 2 (time and place) carries a slot with NO image
   in it yet. That is deliberate, not an oversight: the check-in photograph is
   the one image on this site depicting the actual product moment, and every
   verified stock candidate was a European retail counter. A European counter
   standing in for Riyadh reads as stock to precisely the customer this site
   is written for, so the slot waits for a real photograph shot in one of the
   customer's own pharmacies.

   The reserved slot renders NOTHING and occupies NO space until an image
   exists (`.chapter__figure:empty { display: none }`), and the aspect-ratio
   box means dropping one in later will not reflow the page around it.
   -------------------------------------------------------------------------- */

.chapter__figure {
  margin: 0 0 var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--mist);
}

/* An empty reserved slot must not paint a grey box on the page. */
.chapter__figure:empty { display: none; }

.chapter__figure img {
  display: block;
  width: 100%;
  height: auto;
  /* Pinned so the 1x and 2x sources, and any future replacement shot at the
     same ratio, all reserve identical space. CLS stays at 0. */
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

@media (min-width: 760px) {
  /* Wide enough to matter, not so wide it competes with the hero object.
     The height cap matters as much as the width: at 3:2 and 620px the photo
     ran to ~410px tall and dominated the chapter it was supposed to
     support. */
  .chapter__figure { max-width: 520px; }
  .chapter__figure img { aspect-ratio: 16 / 9; }
}

/* --------------------------------------------------------------------------
   ICONS

   The sheet itself paints nothing; see partials/icons.html for the system
   (24x24, stroke-only, 1.5 weight, currentColor, grid motif from the mark).
   -------------------------------------------------------------------------- */

.icon-sheet { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* The icon rides the text baseline rather than sitting on it. */
  vertical-align: -.15em;
}

.icon--lg { width: 30px; height: 30px; }
.icon--sm { width: 17px; height: 17px; }

/* --------------------------------------------------------------------------
   CHAPTER RHYTHM - five treatments, each earned

   MEASURED PROBLEM. The capabilities section was 4,087px tall - 46% of the
   whole page - and internally it was the same shape five times over: title,
   lead paragraph, optional figure, two-column grid. Six other sections came
   in at 634-1,350px and were reasonably varied. So the monotony was not
   spread across the page, it was CONCENTRATED in the one section that is
   half of it, and the ground alternation that separates every other section
   did nothing at all across that unbroken white field.

   THE RULE APPLIED HERE: a chapter looks different because it IS different.
   Nothing below varies to relieve boredom.

     1 people record  two-column, figure leading. The introduction: it
                      establishes the pattern so the later breaks read AS
                      breaks. Deliberately ordinary.
     2 time + place   full-bleed mist band, one wide column. This chapter is
                      about a grid, and the band is where the reserved
                      check-in photograph lands.
     3 payslip        INVERTED, ink ground. The money chapter and the site's
                      most consequential claim. Inversion is the strongest
                      signal available and is spent exactly ONCE.
     4 money before   two-column with oversized numerals. The reporting
                      chapter; numerals are its subject.
     5 who can do     QUIET. Narrow, generous, no figure. After an inverted
                      section and a numeral-heavy one the eye needs to stop.
                      Quiet is a treatment, not an absence.
   -------------------------------------------------------------------------- */

/* --- ground by meaning, not by alternation ------------------------------
   The old scheme alternated white / mist / white / mist mechanically, which
   says nothing except "a new section". These say what KIND of thing this is:
   mist for context, white for capability, ink for the two moments that
   actually matter (the payslip chapter, and the demo). */

/* FULL-BLEED OUT OF .shell, AND BACK IN AGAIN.

   The chapter sits inside .shell, which is max-width 1200 and already has a
   gutter. Breaking out is margin-inline: calc(50% - 50vw) - that is correct.
   The trap is the padding: an earlier version used
   calc(50vw - 50% + var(--s-6)), which double-counts the shell's own gutter
   and, once the viewport passed the max-width, resolved small enough that the
   content ran to the very edge of the screen with the icons clipped off it.

   Instead: break out with margin, then put the content back on the shell's
   own grid with an inner wrapper. The band paints edge to edge; the text
   lines up with every other section on the page.                          */
.chapter--band,
.chapter--ink {
  margin-inline: calc(50% - 50vw);
  padding-block: var(--s-10);
}
.chapter--band > *,
.chapter--ink > * {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.chapter--band { background: var(--mist); }

.chapter--ink {
  background: var(--ink);
  color: #C8D6E4;
}
.chapter--ink .cap { border-top-color: rgba(255, 255, 255, .16); }
.chapter--ink .cap p { color: #A9BFD4; }
.chapter--ink .cap__how { color: #fff; border-color: #7FB3E0; }
.chapter--ink .chapter__lead { color: #A9BFD4; }
.chapter--ink .icon { color: #7FB3E0; }

/* The quiet chapter. Narrow measure, more air, nothing competing. */
.chapter--quiet .caps { grid-template-columns: 1fr; max-width: 60ch; }
.chapter--quiet { padding-block: var(--s-8); }

/* The wide chapter: one column at full width rather than two half-width
   ones, so the band reads as a band rather than as more of the same grid. */
.chapter--wide .caps { grid-template-columns: 1fr; max-width: 74ch; }

@media (min-width: 900px) {
  .chapter--wide .caps { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: none; }
}

/* Numerals chapter: the figure sits beside the heading rather than above. */
.chapter--numeral .chapter__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
}

/* --------------------------------------------------------------------------
   THE HERO OBJECT, sized as a hero

   Restored from a side panel, where it was small by design. As the page's one
   bold element it carries more weight: bigger cells, a larger caption, and a
   light sweep across it on pointer move (the reveal mechanism kept from the
   object it replaces - a lighting effect, not a geometry one).
   -------------------------------------------------------------------------- */

.weekgrid { position: relative; overflow: hidden; }

@media (min-width: 940px) {
  /* Centre the object against the copy rather than pinning it to the top of
     its column, which left a block of dead space under it. */
  .hero__grid { align-items: center; }
  .weekgrid__cell { height: 62px; }
  .weekgrid__table th,
  .weekgrid__table td { font-size: var(--t-sm); }
  .weekgrid__bar { font-size: var(--t-sm); }
}

/* The sweep. A soft highlight tracking the pointer across the grid, driven by
   --mx/--my written from main.js. It sits ABOVE the table and ignores the
   pointer, so nothing about selection or scrolling changes.

   Under reduced motion main.js never writes the variables and never starts a
   listener, so the default position below is what renders - a still, faint
   highlight rather than a moving one. */
.weekgrid__sweep {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(38% 46% at var(--mx, 78%) var(--my, 16%),
              rgba(11, 95, 165, .10) 0%, transparent 70%);
  z-index: 2;
}

@media (prefers-reduced-motion: reduce) {
  .weekgrid__sweep { transition: none !important; }
}

/* ==========================================================================
   THE DISPLAY REGISTER

   Amiri 700 sets the headings on MARKETING pages. On DOCUMENT pages it sets
   the <h1> only and everything below stays Readex - see THE TWO REGISTERS in
   the palette note for why, and do not unify them.

   NOTE: DIGITS. Amiri's Arabic-Indic numerals are calligraphic. Lovely in a
   headline, wrong in a payroll table, where tabular alignment beats
   character - a column of figures that does not line up is worse than a
   column that is merely plain. So any element carrying data keeps Readex for
   its numerals via .tabular, and .figure-numeral (display only) keeps Amiri.
   ========================================================================== */

h1, h2, .section-title, .display {
  font-family: "Amiri", "Readex Pro", Georgia, serif;
  font-weight: 700;
  line-height: 1.42;
}

/* Arabic Naskh needs more leading than the Latin at the same size. */
html[lang="ar"] h1,
html[lang="ar"] h2,
html[lang="ar"] .section-title,
html[lang="ar"] .display { line-height: 1.45; }

/* Tabular figures keep the body face: alignment over character. */
.tabular,
.tabular * {
  font-family: "Readex Pro", system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
}

/* ---- DOCUMENT REGISTER --------------------------------------------------
   Applied by .doc-page on <body>. A reading page: white ground, display face
   on the h1 alone, no scroll reveals. */
body.doc-page { background: var(--paper-doc); }

/* THE HEADER MUST FOLLOW THE GROUND, IN BOTH DIRECTIONS. It was hardcoded
   white and floated above the cream marketing page; deriving it from --paper
   fixed that. But --paper is still cream on a document page, so the same
   defect reappeared inverted: a cream bar above a white policy. Rebinding
   --paper inside the register fixes both at once, because everything tinted
   from the ground now follows the register rather than the site default. */
body.doc-page { --paper: var(--paper-doc); --mist: var(--mist-doc); }
body.doc-page .section--mist { background: var(--mist-doc); }
body.doc-page h2,
body.doc-page h3,
body.doc-page .section-title {
  font-family: "Readex Pro", system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.35;
}

/* ==========================================================================
   THE SCREENS SECTION — tabbed product screens on real demo-tenant data

   THE HARDEST SECTION IN THE DESIGN, and built first on purpose: 12
   behaviours across 6 distinct types, two tables, a fixed three-column grid,
   and ZERO overflow handling in the source mockup. If the system survives
   here it survives the other ten; the reverse would not have been true.

   NOTE: MOBILE: THE PANES SCROLL HORIZONTALLY, THEY DO NOT STACK.
   A payslip table stacked into label/value pairs stops resembling a payslip,
   which is the same failure the 3D block field had - the structure IS the
   meaning. A table people expect to scroll sideways is honest. This is the
   one place on the site where horizontal scroll is correct, and it is
   correct because the reader has already tapped a tab to look at it.
   ========================================================================== */

.screens__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-6);
}

.screens__tab {
  appearance: none;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--slate);
  font: inherit;
  font-size: var(--t-sm);
  padding: 10px 18px;
  border-radius: 2px;
  cursor: pointer;
  transition: background 160ms var(--ease), color 160ms var(--ease),
              border-color 160ms var(--ease);
}
.screens__tab:hover { border-color: var(--line-strong); color: var(--ink); }
.screens__tab[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.screens__stage {
  border: 1px solid var(--line);
  background: var(--paper);
  border-radius: 2px;
}

/* Panes are stacked in the same grid cell so switching one does not reflow
   the page - the stage keeps the height of the tallest pane. */
.screens__panes { display: grid; }
.screens__pane {
  grid-area: 1 / 1;
  min-width: 0;
  visibility: hidden;
  opacity: 0;
  transition: opacity 220ms var(--ease);
}
.screens__pane[data-active] { visibility: visible; opacity: 1; }

/* The scroll frame. Edge fade tells the reader more exists without a
   scrollbar being visible on a phone. */
.screens__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.screens__table {
  width: 100%;
  min-width: 620px;          /* below this the columns collide; scroll instead */
  border-collapse: collapse;
  font-size: var(--t-sm);
}
.screens__table th,
.screens__table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  text-align: start;
  white-space: nowrap;
}
.screens__table thead th {
  font-weight: 600;
  font-size: var(--t-xs);
  color: var(--slate);
}
.screens__table tbody tr:last-child td { border-bottom: 0; }

.screens__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
}

.pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 11px;
  border-radius: 100px;
  font-size: var(--t-xs);
  font-weight: 500;
  background: rgba(var(--ink-rgb), .07);
  color: var(--slate);
}
.pill--on { background: rgba(18, 100, 255, .10); color: var(--accent); }

.avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(18, 100, 255, .12);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--t-xs);
  font-weight: 600;
  flex: none;
}

@media (max-width: 720px) {
  .screens__tab { padding: 9px 14px; font-size: var(--t-xs); }
  .screens__bar { padding: var(--s-3) var(--s-4); }
}

/* ==========================================================================
   BLUE INK SECTIONS — the numbered-step and chapter treatments

   Ported from the Claude Design handoff. The mockup had ZERO media queries
   and eleven fixed multi-column grids, so every layout below carries its own
   responsive behaviour: the desktop arrangement is the special case, declared
   at a breakpoint, and the phone arrangement is the default.
   ========================================================================== */

/* ---- numbered statements (problem, money) ------------------------------- */
.steps { display: grid; gap: var(--s-7); }
@media (min-width: 780px) {
  .steps--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
  .steps--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
  .steps--3 > * + *,
  .steps--4 > * + * {
    border-inline-start: 1px solid var(--line);
    padding-inline-start: clamp(20px, 3vw, 46px);
  }
  .steps--3 > *:not(:last-child),
  .steps--4 > *:not(:last-child) { padding-inline-end: clamp(20px, 3vw, 46px); }
}

.step__num {
  font-family: "Amiri", serif;
  font-weight: 700;
  font-size: var(--t-xl);
  color: var(--accent);
  display: block;
  margin-bottom: var(--s-3);
}
.step__title {
  font-family: "Amiri", serif;
  font-weight: 700;
  font-size: clamp(1.25rem, 1.05rem + .9vw, 1.75rem);
  line-height: 1.6;
  margin: 0 0 var(--s-2);
}
.step p { margin: 0; color: var(--slate); }

/* ---- the chapter head shared by product/time/payroll/money/roles -------- */
.chap { padding-block: clamp(52px, 9vh, 108px); border-top: 1px solid var(--line); }
.chap__head { max-width: 62ch; margin-bottom: var(--s-8); }
.chap__lede { margin: var(--s-4) 0 0; color: var(--slate); font-size: var(--t-md); }

.chap__points {
  display: grid;
  gap: var(--s-4);
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--slate);
}
@media (min-width: 700px) { .chap__points { grid-template-columns: repeat(3, minmax(0,1fr)); } }

/* ---- compliance list ---------------------------------------------------- */
.laws { display: grid; gap: 0; margin-top: var(--s-6); }
.law {
  display: grid;
  gap: var(--s-1) var(--s-6);
  padding: var(--s-5) 0;
  border-top: 1px solid var(--line);
}
@media (min-width: 700px) {
  .law { grid-template-columns: 140px minmax(0, 1fr); align-items: baseline; }
}
.law__ref { font-family: "Amiri", serif; font-weight: 700; color: var(--accent); }
.law__text { margin: 0; font-size: var(--t-md); }

/* ---- security list ------------------------------------------------------ */
.facts { display: grid; gap: 0; }
.fact {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  padding: var(--s-5) 0;
  border-top: 1px solid var(--line);
}
.fact .icon { color: var(--accent); margin-top: 2px; }
.fact p { margin: 0; }

/* ---- app section -------------------------------------------------------- */
.app-grid { display: grid; gap: var(--s-8); }
@media (min-width: 860px) {
  .app-grid { grid-template-columns: minmax(0,.9fr) minmax(0,1.1fr); align-items: center; }
}
.app-list { display: grid; gap: var(--s-3); margin: var(--s-6) 0 0; padding: 0; list-style: none; }
.app-list li {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) 0; border-top: 1px solid var(--line);
  font-size: var(--t-sm);
}
.app-list .icon { color: var(--accent); }

/* A reading page does not animate its prose into view. Someone scrolling a
   privacy policy to find a retention period should not wait for the clause to
   fade in - the animation is between them and the answer. main.js checks the
   same class, so no observer is attached either; this is the stylesheet half
   of that guard, and it also covers a reader whose script fails to load. */
/* .no-reveal is the MIDDLE CASE: pricing keeps the marketing register - the
   cream ground and the Amiri headings - because it is a page being looked at,
   but it is short, factual and read top to bottom, so its content should not
   animate into view. Two properties that happened to travel together on the
   homepage are separable, and pricing is where they separate. */
body.doc-page .reveal,
body.doc-page .hero-seq,
body.no-reveal .reveal,
body.no-reveal .hero-seq {
  opacity: 1 !important;
  transform: none !important;
}

/* ==========================================================================
   THE APP SECTION — the floating phone and its cards.

   Ported from the Blue Ink handoff (Jadwal Hero Blue Ink.dc.html) rather than
   reinterpreted. An earlier pass replaced this whole composition with a text
   list, which kept the CONTENT and dropped the thing that made the section
   read as a product: a device that hovers, breathes a shadow, and swaps
   between two real screens on its own.

   Eight keyframes, all from the handoff, names kept so the two can be
   diffed:
     jw-hover   the phone's perspective float
     jw-shadow  the ground shadow breathing in counter-phase
     jw-swapA/B the two screens cross-fading on an 11s cycle
     jw-pulse   the check-in button's expanding ring
     jw-lift    a card's entrance
     jw-float   a card's idle drift, each at a different period so they
                never sync up into a single pulsing block
     jw-cell    the hero grid cell (used by the week grid)

   WARNING: EVERY ONE OF THESE IS INFINITE. They must all stop under
   prefers-reduced-motion — see the block at the end of this file. An infinite
   animation is the one kind a reduced-motion reader cannot escape by
   scrolling past it.
   ========================================================================== */

@keyframes jw-cell   { from { opacity: 0; transform: scale(.82); } to { opacity: 1; transform: scale(1); } }
@keyframes jw-float  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes jw-lift   { from { opacity: 0; transform: translateY(26px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes jw-shadow { 0%, 100% { transform: scaleX(1); opacity: .5; } 50% { transform: scaleX(.9); opacity: .32; } }
@keyframes jw-swapA  { 0%, 42% { opacity: 1; } 50%, 92% { opacity: 0; } 100% { opacity: 1; } }
@keyframes jw-swapB  { 0%, 42% { opacity: 0; } 50%, 92% { opacity: 1; } 100% { opacity: 0; } }
@keyframes jw-pulse  { 0%, 100% { box-shadow: 0 0 0 0 rgba(18, 100, 255, .5); } 70% { box-shadow: 0 0 0 14px rgba(18, 100, 255, 0); } }

/* The handoff rotates the phone with rotateY(-9deg), which leans it AWAY from
   the reader on an RTL page and INTO the page on an LTR one. The sign is
   flipped for the English build so the device leans the same way relative to
   the text in both languages. */
@keyframes jw-hover {
  0%, 100% { transform: perspective(1200px) rotateY(-9deg) rotateX(2deg) translateY(0); }
  50%      { transform: perspective(1200px) rotateY(-9deg) rotateX(2deg) translateY(-14px); }
}
@keyframes jw-hover-ltr {
  0%, 100% { transform: perspective(1200px) rotateY(9deg) rotateX(2deg) translateY(0); }
  50%      { transform: perspective(1200px) rotateY(9deg) rotateX(2deg) translateY(-14px); }
}

.app-stage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(60px, 7vw, 110px);
  margin-top: clamp(44px, 7vh, 80px);
}

/* --- the three cards that drift beside the phone ------------------------- */
.app-cards {
  width: min(100%, 232px);
  display: flex;
  flex-direction: column;
  gap: 18px;
  flex: none;
}
.app-card__anim { animation: jw-lift .9s cubic-bezier(.16, 1, .3, 1) both, jw-float 6s ease-in-out infinite; }
.app-card__anim:nth-child(1) { animation-delay: .05s, .95s; }
.app-card__anim:nth-child(2) { animation-delay: .2s, 1.1s; animation-duration: .9s, 7.5s; }
.app-card__anim:nth-child(3) { animation-delay: .35s, 1.25s; animation-duration: .9s, 9s; }

.app-card {
  box-sizing: border-box;
  width: 100%;
  background: var(--paper);
  border: 1px solid rgba(var(--ink-rgb), .26);
  padding: 15px 17px;
}
/* Three different rotations and scales, so the stack reads as a pile of real
   notifications rather than a list that happens to be tilted. */
.app-card--1 { transform: rotate(-5deg) scale(1.05); box-shadow: 0 28px 42px -22px rgba(var(--ink-rgb), .6); }
.app-card--2 { transform: rotate(4deg)  scale(1);    box-shadow: 0 18px 30px -20px rgba(var(--ink-rgb), .5); }
.app-card--3 { transform: rotate(-2deg) scale(.93);  box-shadow: 0 12px 20px -16px rgba(var(--ink-rgb), .42); opacity: .92; }

.app-card__row { display: flex; align-items: center; gap: 11px; }
.app-card__col { display: flex; flex-direction: column; gap: 6px; }
.app-card__k { font-size: 11px; color: rgba(var(--ink-rgb), .6); }
.app-card__v { font-size: 13px; font-weight: 500; }

/* --- the phone ----------------------------------------------------------- */
.phone-wrap { position: relative; width: 246px; flex: none; margin: 20px 0 clamp(54px, 8vh, 88px); }

.phone-shadow {
  position: absolute; z-index: 0;
  inset-inline-start: 50%; inset-block-end: -42px;
  inline-size: 200px; block-size: 26px; margin-inline-start: -100px;
  background: radial-gradient(50% 50% at 50% 50%, rgba(var(--ink-rgb), .45), rgba(var(--ink-rgb), 0) 70%);
  animation: jw-shadow 7s ease-in-out infinite;
}
.phone-tilt { position: relative; z-index: 2; transform-style: preserve-3d; animation: jw-hover 7s ease-in-out infinite; }
[dir="ltr"] .phone-tilt { animation-name: jw-hover-ltr; }

.phone-body {
  width: 246px;
  aspect-ratio: 9 / 16.5;
  background: var(--ink);
  border-radius: 34px;
  padding: 9px;
  box-shadow: -22px 30px 60px -28px rgba(var(--ink-rgb), .6), 0 2px 0 rgba(255, 255, 255, .12) inset;
}
[dir="ltr"] .phone-body { box-shadow: 22px 30px 60px -28px rgba(var(--ink-rgb), .6), 0 2px 0 rgba(255, 255, 255, .12) inset; }

.phone-screen { position: relative; height: 100%; background: var(--paper); border-radius: 26px; overflow: hidden; }

.phone-view {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  background: var(--paper);
}
.phone-view--a { animation: jw-swapA 11s ease-in-out infinite; }
.phone-view--b { animation: jw-swapB 11s ease-in-out infinite; }

.phone-top { display: flex; align-items: center; justify-content: space-between; padding: 15px 15px 11px; }
.phone-brand { display: flex; align-items: center; gap: 7px; }
.phone-brand span { font-family: "Amiri", Georgia, serif; font-size: 18px; font-weight: 700; }
.phone-avatar { width: 23px; height: 23px; border: 1px solid rgba(var(--ink-rgb), .3); border-radius: 50%; }

.phone-meta { padding: 2px 15px 0; }
.phone-meta small { display: block; font-size: 10.5px; color: rgba(var(--ink-rgb), .6); }
.phone-meta strong { display: block; font-size: 14px; font-weight: 500; margin-top: 7px; }

.phone-cta {
  margin: 14px 15px;
  background: var(--accent); color: #FFFFFF;
  border-radius: 4px; padding: 14px;
  text-align: center; font-size: 13.5px; font-weight: 500;
  animation: jw-pulse 3.2s ease-out infinite;
}

.phone-rows { padding: 0 15px; display: flex; flex-direction: column; font-size: 12px; color: rgba(var(--ink-rgb), .8); }
.phone-rows > span,
.phone-kv > span {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 12px 0;
  border-top: 1px solid rgba(var(--ink-rgb), .16);
}
.phone-rows svg { flex: none; opacity: .5; }
/* The chevron points the way "forward" reads, which is left in Arabic. */
[dir="ltr"] .phone-rows svg { transform: scaleX(-1); }

.phone-kv { padding: 0 15px; display: flex; flex-direction: column; font-size: 12px; }
.phone-kv > span { padding: 11px 0; }
.phone-kv em { font-style: normal; color: rgba(var(--ink-rgb), .6); }
.phone-kv b { font-weight: 500; }

.phone-back { display: flex; align-items: center; gap: 9px; padding: 15px; }
.phone-back span { font-size: 13.5px; font-weight: 500; }
[dir="ltr"] .phone-back svg { transform: scaleX(-1); }

.phone-note {
  margin: 16px 15px 0;
  border: 1px solid rgba(18, 100, 255, .45);
  background: rgba(18, 100, 255, .07);
  padding: 13px;
  display: flex; align-items: center; gap: 10px;
}
.phone-note svg { flex: none; }
.phone-note span { font-size: 11.5px; line-height: 1.6; }

.phone-foot {
  margin-top: auto;
  padding: 11px 15px;
  border-top: 1px solid rgba(var(--ink-rgb), .16);
  font-size: 10px; color: rgba(var(--ink-rgb), .5);
}

/* WARNING - REDUCED MOTION: every animation above is INFINITE. A reader who has
   asked for less motion cannot scroll away from a loop, so these are stopped
   outright rather than shortened. The phone still shows screen A, the cards
   still sit in their pile, and the section still says what it says. */
@media (prefers-reduced-motion: reduce) {
  /* THIS BLOCK WAS ENTIRELY DEAD, and a live accessibility defect.

     This block used to name .app-card__anim, .phone-shadow, .phone-tilt,
     .phone-view--a/--b and .phone-cta. MEASURED: all six appear ZERO times in
     the shipped pages — the rebuild moved every one of these onto generated
     class names (.b5b, .b5e, .b5h, .b5k, .b5l, .b5o, .b5w, .b61), so the
     entire block matched nothing and a visitor who asked for reduced motion
     still got five INFINITE animations. The CSS still read as correct, which
     is why it survived; nothing here was ever wrong to look at.

     THE CLASS LIST BELOW WILL DRIFT AGAIN — it is pinned to generated
     names, which the inline-style hoist reassigns on every rebuild. A CSS
     selector cannot express "whatever carries jw-float" without :has() gymnastics
     that would not cover shorthand `animation:` anyway.

     What makes this safe is NOT the selector: it is that section C of
     verify-behaviour.mjs asserts the RESULT (live-animations must be 0 under
     reduce) rather than the selector, so the next rebuild that renames these
     classes fails the check instead of silently un-fixing accessibility.
     That check is what caught this block being entirely dead. */
  .b5b, .b5e, .b5h, .b5k, .b5l, .b5o, .b5w, .b61 {
    animation: none !important;
  }
  .b5b, .b5e, .b5h { opacity: 1; transform: none; }
  .b61 { opacity: 0; }
}

/* ==========================================================================
   ANCHOR LANDINGS UNDER THE STICKY HEADER

   The header is sticky at 64px when stuck (.site-header.is-stuck). Nothing
   accounted for it, so every nav link — which is how this page is actually
   navigated — landed with the target heading UNDERNEATH the header. The
   section was on screen and its title was not.

   Found by screenshotting a section rather than by reading, and it had been
   true of all eleven sections since the nav was written. A jump link is one
   of the few things on a page that cannot be checked by looking at the page
   in its resting state.

   The extra 12px is breathing room so the heading does not sit flush against
   the header's bottom edge.
   ========================================================================== */
/* 76px was the height of the OLD sticky header plus breathing room. The Blue
   Ink nav is not sticky, so an anchor no longer lands underneath anything -
   but a small offset still reads better than a heading flush against the top
   edge, and the curtain wipe lands on the same value. */
:where(section[id], h2[id], h3[id]) { scroll-margin-block-start: 24px; }

/* The phone's brand mark rides .icon for its stroke; only the size differs.
   It carried its own class alone at first and rendered as an empty box —
   .icon is what supplies fill/stroke, and a bare <svg><use> inherits
   nothing from the sheet it points into. */
.phone-mark { width: 18px; height: 18px; color: var(--ink); }

/* ==========================================================================
   THE EXPERIENCE LAYER — the interactions from the Blue Ink handoff.

   Paired with assets/js/experience.js. Every rule here is decoration: if the
   script never loads, nothing below applies and the page is unchanged.

   All of it is off under prefers-reduced-motion, enforced in the script
   rather than here, so a guarded behaviour never attaches a listener in the
   first place.
   ========================================================================== */

/* --- the scroll progress bar -------------------------------------------- */
.fx-bar {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 2px;
  background: var(--accent);
  transform: scaleX(0);
  /* origin is set by the script from the document direction — the bar must
     grow from the edge the reader starts at, which is the right in Arabic. */
  z-index: 95;
  pointer-events: none;
}

/* --- the trailing ring --------------------------------------------------
   Pointer-fine only (the script checks). It sits above the page and never
   takes a click. */
.fx-cursor {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 26px;
  block-size: 26px;
  margin: -13px 0 0 -13px;
  border: 1px solid rgba(18, 100, 255, .55);
  border-radius: 50%;
  z-index: 96;
  pointer-events: none;
  opacity: 0;
  transition: inline-size .25s, block-size .25s, margin .25s, background .25s, opacity .3s;
}
.fx-cursor.is-big {
  inline-size: 54px;
  block-size: 54px;
  margin: -27px 0 0 -27px;
  background: rgba(18, 100, 255, .12);
}

/* --- the week grid probe ------------------------------------------------
   Hovering a cell dims everything outside its row and column. The dimming
   is applied to the TABLE (.is-probing) rather than to each cell, so one
   class toggle does the work and the cells only carry their own state. */
.weekgrid__table.is-probing .blk { opacity: .5; transition: opacity .3s ease; }
.weekgrid__table tr.is-hot .blk,
.weekgrid__table td.is-col .blk { opacity: 1; }
.weekgrid__table td.is-hot .blk {
  opacity: 1;
  transform: scale(1.06);
  outline: 1px solid rgba(18, 100, 255, .85);
  outline-offset: 1px;
}
.weekgrid__table .blk { transition: transform .3s cubic-bezier(.16, 1, .3, 1), opacity .3s ease; }
.weekgrid__table th.is-hot { color: var(--accent); font-weight: 600; }
.weekgrid__table th { transition: color .3s ease; }

/* --- tilt and magnet ---------------------------------------------------- */
[data-tilt] { will-change: transform; transition: box-shadow .4s ease; }
[data-magnet] { transition: transform .35s cubic-bezier(.16, 1, .3, 1); }

/* --- cards lift --------------------------------------------------------- */
[data-card] { transition: background .35s ease, transform .35s cubic-bezier(.16, 1, .3, 1); }
[data-card].is-lift { background: rgba(18, 100, 255, .07); transform: translateY(-4px); }

/* --- stepped numerals ---------------------------------------------------
   The script writes opacity/transform inline per frame. This only supplies
   the resting state for when the script is absent, so a numeral is never
   left faint on a page with no JS. */
[data-num] { transition: opacity .3s ease; }

@media (prefers-reduced-motion: reduce) {
  .fx-bar, .fx-cursor { display: none; }
  [data-num] { opacity: 1 !important; transform: none !important; }
}


/* ==========================================================================
   THE HANDOFF'S OWN STYLES, HOISTED OUT OF ITS MARKUP.

   Jadwal Hero Blue Ink.dc.html carried 633 inline style="" attributes.
   .rebuild/convert.mjs mapped each unique declaration to one generated class
   (243 of them; identical declarations collapse) and rewrote the attributes.

   WHY MECHANICALLY. Re-typing 633 declarations by hand is where a "verbatim"
   port stops being verbatim - every one is an opportunity to improve
   something, and the sum of those improvements is a different design. This
   way the rules below are the handoff's own values, unread by me.

   The class names (b0, b1, b2...) are deliberately meaningless. They are
   generated output, not a naming scheme to extend: anything new belongs in
   the authored sections above, under a name that says what it is.
   ========================================================================== */

/* Readex Pro, not IBM Plex Sans Arabic. The handoff CSS named IBM Plex and
   this rule sits AFTER the design system's own body face, so it won the
   cascade - but the face was never self-hosted. Only the two homepages
   loaded it, from Google; every other page fell silently back to Segoe UI.
   The design system is Readex Pro plus Amiri, both self-hosted, and that
   was decided with the weight measured. */
body{margin:0;background:var(--paper);color:#0E2A6B;font-family:"Readex Pro",system-ui,-apple-system,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}
a{color:#0E2A6B;text-decoration:none}
/* The handoff's own link hover, scoped the same way and for the same reason
   as the one above: at plain `a:hover` it outranked .bc:hover and painted the
   header button's label the colour of its own fill. */
:where(a):hover{color:#0A4FD6}
::selection{background:#1264FF;color:var(--paper)}
@keyframes jw-cell{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:scale(1)}}
@keyframes jw-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
@keyframes jw-hover{0%,100%{transform:perspective(1200px) rotateY(-9deg) rotateX(2deg) translateY(0)}50%{transform:perspective(1200px) rotateY(-9deg) rotateX(2deg) translateY(-14px)}}
@keyframes jw-shadow{0%,100%{transform:scaleX(1);opacity:.5}50%{transform:scaleX(.9);opacity:.32}}
@keyframes jw-swapA{0%,42%{opacity:1}50%,92%{opacity:0}100%{opacity:1}}
@keyframes jw-swapB{0%,42%{opacity:0}50%,92%{opacity:1}100%{opacity:0}}
@keyframes jw-lift{from{opacity:0;transform:translateY(26px) scale(.96)}to{opacity:1;transform:none}}
@keyframes jw-pulse{0%,100%{box-shadow:0 0 0 0 rgba(18,100,255,.5)}70%{box-shadow:0 0 0 14px rgba(18,100,255,0)}}

.b0{min-height:100svh;background:var(--paper);display:flex;flex-direction:column}
.b1{position:fixed;inset-block-start:0;inset-inline-start:0;inline-size:26px;block-size:26px;margin:-13px 0 0 -13px;border:1px solid rgba(18,100,255,.55);border-radius:50%;z-index:96;pointer-events:none;opacity:0;transition:width .25s,height .25s,margin .25s,background .25s,opacity .3s}
.b2{position:fixed;inset-block-start:0;inset-inline-start:0;inset-inline-end:0;block-size:2px;background:#1264FF;transform:scaleX(0);transform-origin:100% 50%;z-index:95;pointer-events:none}
.b3{position:fixed;inset:0;background:#0E2A6B;z-index:90;transform:translateY(100%);pointer-events:none}
.b4{display:flex;align-items:center;justify-content:space-between;gap:28px;padding:26px clamp(20px,4.5vw,72px);max-width:1440px;inline-size:100%;margin:0 auto;box-sizing:border-box}
.b5{display:flex;align-items:center;gap:38px}
.b6{display:flex;align-items:center;gap:11px}
.b7{display:block;block-size:32px;inline-size:auto}
.b8{font-family:'Amiri',serif;font-size:30px;font-weight:700;line-height:1}
.b9{display:flex;gap:26px;font-size:14px;color:rgba(14,42,107,.7)}
.ba{display:flex;align-items:center;gap:20px;flex-wrap:wrap;min-inline-size:0}
.bb{font-size:14px;color:rgba(14,42,107,.7)}
.bc{font-size:14px;padding:11px 22px;border:1px solid rgba(14,42,107,.35);border-radius:2px}
.bd{flex:1;display:flex;align-items:center;min-inline-size:0;padding:clamp(28px,6vh,80px) clamp(20px,4.5vw,72px) clamp(24px,5vh,60px)}
.be{max-width:1440px;inline-size:100%;margin:0 auto;display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(32px,6vw,96px);align-items:center}
.bf{display:flex;flex-direction:column;gap:34px;min-width:0}
.bg{font-size:12.5px;font-weight:500;color:rgba(14,42,107,.72)}
.bh{margin:0;font-family:'Amiri',serif;font-weight:700;font-size:clamp(34px,4.6vw,68px);line-height:1.42;letter-spacing:0;text-wrap:pretty}
.bi{margin:0;max-width:38ch;font-size:clamp(15px,1.25vw,19px);line-height:1.85;color:rgba(14,42,107,.72)}
.bj{display:flex;flex-wrap:wrap;align-items:center;gap:18px;margin-top:6px}
.bk{background:#1264FF;color:#FFFFFF;font-size:15.5px;font-weight:500;padding:17px 34px;border-radius:2px}
.bl{display:flex;flex-wrap:wrap;gap:14px 30px;margin-top:14px;padding-block-start:26px;border-top:1px solid rgba(14,42,107,.16);font-size:13px;color:rgba(14,42,107,.72)}
.bm{min-width:0;display:flex;justify-content:center}
.bn{position:relative;inline-size:100%;max-width:560px}
.bo{position:absolute;inset-block-start:-46px;inset-inline-start:-56px;inline-size:190px;block-size:190px;border:1px solid rgba(14,42,107,.22);border-radius:50%}
.bp{position:absolute;inset-block-end:-34px;inset-inline-end:-30px;inline-size:96px;block-size:96px;background:rgba(14,42,107,.06);border-radius:50%}
.bq{position:relative;background:var(--paper);border:1px solid rgba(14,42,107,.22);padding:clamp(20px,2.4vw,34px);transform-origin:top right;will-change:transform;transition:box-shadow .4s ease}
.br{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:22px}
.bs{font-family:'Amiri',serif;font-size:22px;font-weight:700}
.bt{font-size:12px;color:rgba(14,42,107,.70)}
.bu{display:flex;gap:12px}
.bv{display:grid;grid-template-rows:repeat(5,1fr);gap:8px;align-items:center;padding-block-start:24px;font-size:11.5px;line-height:1;color:rgba(14,42,107,.72);text-align:start;white-space:nowrap}
.bw{flex:1;min-width:0}
.bx{display:grid;grid-template-columns:repeat(8,1fr);gap:8px;margin-bottom:8px;font-size:10.5px;color:rgba(14,42,107,.70);text-align:center}
.by{display:grid;grid-template-columns:repeat(8,1fr);gap:8px}
.bz{display:block;aspect-ratio:1;background:#1264FF}
.b10{display:block;aspect-ratio:1;background:rgba(14,42,107,.1)}
.b11{display:block;aspect-ratio:1;background:repeating-linear-gradient(135deg,rgba(14,42,107,.55) 0 2px,rgba(14,42,107,0) 2px 5px);outline:1px solid rgba(14,42,107,.25);outline-offset:-1px}
.b12{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-top:26px;padding-block-start:20px;border-top:1px solid rgba(14,42,107,.18)}
.b13{display:flex;flex-direction:column;gap:6px}
.b14{font-size:11.5px;color:rgba(14,42,107,.70)}
.b15{display:flex;gap:16px;font-size:11.5px;color:rgba(14,42,107,.72)}
.b16{display:flex;align-items:center;gap:7px}
.b17{inline-size:9px;block-size:9px;background:#1264FF;display:block}
.b18{inline-size:9px;block-size:9px;display:block;background:repeating-linear-gradient(135deg,rgba(14,42,107,.55) 0 2px,rgba(14,42,107,0) 2px 5px);outline:1px solid rgba(14,42,107,.25);outline-offset:-1px}
.b19{border-top:1px solid rgba(14,42,107,.16);padding:clamp(60px,11vh,130px) clamp(20px,4.5vw,72px)}
.b1a{max-width:1440px;margin:0 auto}
.b1b{font-size:12.5px;font-weight:500;color:rgba(14,42,107,.70)}
.b1c{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));margin-top:44px}
.b1d{padding-inline-end:clamp(20px,3vw,54px)}
.b1e{font-family:'Amiri',serif;font-size:20px;color:#1264FF}
.b1f{margin:14px 0 0;font-family:'Amiri',serif;font-size:clamp(22px,2.1vw,30px);line-height:1.6;text-wrap:pretty}
.b1g{border-inline-start:1px solid rgba(14,42,107,.16);padding-inline:clamp(20px,3vw,54px)}
.b1h{border-inline-start:1px solid rgba(14,42,107,.16);padding-inline-start:clamp(20px,3vw,54px)}
.b1i{border-top:1px solid rgba(14,42,107,.16);padding:clamp(60px,11vh,120px) clamp(20px,4.5vw,72px) clamp(46px,8vh,90px)}
.b1j{max-width:1440px;margin:0 auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(30px,5vw,80px);align-items:center}
.b1k{display:flex;flex-direction:column;gap:22px;min-width:0}
.b1l{display:flex;align-items:center;gap:12px;color:#1264FF}
.b1m{font-size:12.5px;font-weight:500;color:rgba(14,42,107,.7)}
.b1n{margin:0;font-family:'Amiri',serif;font-weight:700;font-size:clamp(28px,3.2vw,46px);line-height:1.45}
.b1o{margin:0;max-width:40ch;font-size:16px;line-height:1.9;color:rgba(14,42,107,.75)}
.b1p{display:flex;flex-direction:column;font-size:14.5px;color:rgba(14,42,107,.75);margin-top:6px}
.b1q{padding:14px 0;border-top:1px solid rgba(14,42,107,.16)}
.b1r{padding:14px 0;border-top:1px solid rgba(14,42,107,.16);border-block-end:1px solid rgba(14,42,107,.16)}
.b1s{margin:0;min-width:0;display:flex;flex-direction:column;gap:12px}
.b1t{block-size:480px;min-width:0}
.b1u{block-size:100%;box-sizing:border-box;display:flex;flex-direction:column;background:#FFFFFF;border:1px solid rgba(14,42,107,.14);box-shadow:0 24px 44px -30px rgba(14,42,107,.45);color:#0E2A6B;font-size:12.5px;overflow:hidden;transform-origin:top right;will-change:transform;transition:box-shadow .4s ease}
.b1v{flex:none;display:flex;align-items:center;justify-content:space-between;gap:14px;padding:15px 18px;border-block-end:1px solid rgba(14,42,107,.12)}
.b1w{font-size:13px;font-weight:500}
.b1x{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}
.b1y{padding:16px 18px;display:flex;align-items:center;gap:13px;border-block-end:1px solid rgba(14,42,107,.12)}
.b1z{inline-size:42px;block-size:42px;border-radius:50%;background:rgba(18,100,255,.12);color:#1264FF;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600;flex:none}
.b20{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0}
.b21{font-size:15px;font-weight:600}
.b22{display:inline-flex;align-items:center;padding:4px 10px;border-radius:100px;font-size:11px;font-weight:500;background:rgba(18,100,255,.1);color:#1264FF}
.b23{display:flex;gap:18px;padding:12px 18px 0;font-size:12px;color:rgba(14,42,107,.70)}
.b24{padding-bottom:9px;border-block-end:2px solid #1264FF;color:#0E2A6B;font-weight:500}
.b25{border-top:1px solid rgba(14,42,107,.12);padding:16px 18px;display:flex;flex-direction:column;gap:16px;flex:1}
.b26{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}
.b27{display:flex;flex-direction:column;gap:5px}
.b28{font-size:11px;color:rgba(14,42,107,.70)}
.b29{font-size:13px}
.b2a{border-top:1px solid rgba(14,42,107,.12);padding-block-start:15px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}
.b2b{direction:ltr;display:inline-block;font-size:12px}
.b2c{flex:none;padding:11px 18px;border-top:1px solid rgba(14,42,107,.12);font-size:11px;color:rgba(14,42,107,.70)}
.b2d{font-size:13px;color:rgba(14,42,107,.7)}
.b2e{border-top:1px solid rgba(14,42,107,.16);border-block-end:1px solid rgba(14,42,107,.16);background:rgba(18,100,255,.055);padding:clamp(46px,8vh,86px) clamp(20px,4.5vw,72px)}
.b2f{display:flex;flex-direction:column;gap:20px;min-width:0}
.b2g{margin:0;font-size:16px;line-height:1.9;color:rgba(14,42,107,.75)}
.b2h{display:flex;flex-wrap:wrap;gap:10px 26px;font-size:13.5px;color:rgba(14,42,107,.7)}
.b2i{margin:0;inline-size:100%;min-width:0;display:flex;flex-direction:column;gap:12px}
.b2j{inline-size:100%;border-collapse:collapse}
.b2k{text-align:end;font-weight:500;font-size:11px;color:rgba(14,42,107,.70);padding:10px 18px;border-block-end:1px solid rgba(14,42,107,.12);white-space:nowrap}
.b2l{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12)}
.b2m{display:flex;flex-direction:column;gap:3px}
.b2n{font-variant-numeric:tabular-nums}
.b2o{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12);font-size:11.5px}
.b2p{display:inline-flex;align-items:center;padding:4px 10px;border-radius:100px;font-size:11px;font-weight:500;background:transparent;border:1px solid rgba(14,42,107,.3);color:rgba(14,42,107,.70)}
.b2q{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;color:rgba(14,42,107,.70)}
.b2r{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;font-weight:500;color:rgba(14,42,107,.70)}
.b2s{display:inline-flex;align-items:center;padding:4px 10px;border-radius:100px;font-size:11px;font-weight:500;background:rgba(14,42,107,.07);color:rgba(14,42,107,.7)}
.b2t{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;color:#0E2A6B}
.b2u{padding:12px 18px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;font-weight:500;color:#0E2A6B}
.b2v{flex:1}
.b2w{background:#0E2A6B;color:var(--paper);padding:clamp(56px,10vh,110px) clamp(20px,4.5vw,72px)}
.b2x{display:flex;align-items:center;gap:12px;color:var(--paper)}
.b2y{font-size:12.5px;font-weight:500;color:rgba(239,233,222,.7)}
.b2z{margin:0;max-width:42ch;font-size:16px;line-height:1.9;color:rgba(239,233,222,.8)}
.b30{font-size:13px;color:rgba(239,233,222,.6)}
.b31{margin:0;min-width:0;display:flex;flex-direction:column;gap:14px}
.b32{padding:14px 18px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:9px;border-block-end:1px solid rgba(14,42,107,.12)}
.b33{border:1px solid rgba(14,42,107,.12);padding:11px 13px;display:flex;flex-direction:column;gap:6px}
.b34{font-size:16px;font-weight:500;color:#0E2A6B;font-variant-numeric:tabular-nums}
.b35{font-size:16px;font-weight:500;color:#1264FF;font-variant-numeric:tabular-nums}
.b36{padding:14px 18px;flex:1;display:flex;flex-direction:column}
.b37{border:1px solid rgba(14,42,107,.12)}
.b38{padding:8px 13px;background:rgba(14,42,107,.04);border-block-end:1px solid rgba(14,42,107,.12);font-size:11px;color:rgba(14,42,107,.70)}
.b39{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 13px;border-block-end:1px solid rgba(14,42,107,.12)}
.b3a{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 13px;border-block-end:1px solid rgba(14,42,107,.12);font-weight:600}
.b3b{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 13px;background:rgba(18,100,255,.06);font-weight:600}
.b3c{font-variant-numeric:tabular-nums;font-size:15px;color:#1264FF}
.b3d{font-size:12.5px;color:rgba(239,233,222,.65)}
.b3e{padding:clamp(60px,11vh,120px) clamp(20px,4.5vw,72px)}
.b3f{margin:18px 0 0;font-family:'Amiri',serif;font-weight:700;font-size:clamp(28px,3.2vw,46px);line-height:1.45}
.b3g{margin:16px 0 0;max-width:52ch;font-size:16px;line-height:1.9;color:rgba(14,42,107,.75)}
.b3h{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:clamp(20px,3vw,44px);margin-top:clamp(36px,6vh,64px)}
.b3i{display:flex;flex-direction:column;gap:12px}
.b3j{font-family:'Amiri',serif;font-size:clamp(56px,7vw,104px);line-height:.9;color:#1264FF}
.b3k{font-size:17px;font-weight:500;padding-block-start:12px;border-top:1px solid rgba(14,42,107,.2)}
.b3l{font-size:14px;line-height:1.8;color:rgba(14,42,107,.7)}
.b3m{padding:clamp(50px,9vh,100px) clamp(20px,4.5vw,72px) clamp(70px,12vh,140px)}
.b3n{max-width:640px;margin:0 auto;text-align:center;display:flex;flex-direction:column;align-items:center;gap:22px}
.b3o{color:#1264FF}
.b3p{margin:0;font-family:'Amiri',serif;font-weight:700;font-size:clamp(26px,3vw,42px);line-height:1.5}
.b3q{margin:0;font-size:16px;line-height:2;color:rgba(14,42,107,.75)}
.b3r{border-top:1px solid rgba(14,42,107,.16);padding:clamp(60px,11vh,120px) clamp(20px,4.5vw,72px)}
.b3s{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:16px}
.b3t{font-size:13px;color:rgba(14,42,107,.72)}
.b3u{display:flex;flex-wrap:wrap;gap:10px;margin-top:clamp(26px,4vh,40px)}
.b3v{font-family:inherit;font-size:13px;font-weight:500;padding:11px 22px;border:1px solid rgba(14,42,107,.3);background:transparent;color:rgba(14,42,107,.70);cursor:pointer}
.b3w{position:relative;block-size:460px;margin-top:22px}
.b3x{position:absolute;inset:0;display:flex;align-items:stretch;transition:opacity .55s cubic-bezier(.16,1,.3,1),transform .55s cubic-bezier(.16,1,.3,1)}
.b3y{inline-size:100%;display:flex;flex-direction:column}
.b3z{background:#FFFFFF;border:1px solid rgba(14,42,107,.14);box-shadow:0 20px 40px -30px rgba(14,42,107,.45);color:#0E2A6B;font-size:12.5px;min-width:0;overflow:hidden;block-size:100%;display:flex;flex-direction:column}
.b40{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px;padding:16px 18px}
.b41{display:flex;gap:8px}
.b42{inline-size:100%;border-collapse:collapse;border-top:1px solid rgba(14,42,107,.12)}
.b43{text-align:end;font-weight:500;font-size:11px;color:rgba(14,42,107,.70);padding:11px 14px;border-block-end:1px solid rgba(14,42,107,.12);white-space:nowrap}
.b44{padding:13px 14px;border-block-end:1px solid rgba(14,42,107,.12)}
.b45{font-weight:500}
.b46{display:flex;align-items:center;gap:9px}
.b47{inline-size:28px;block-size:28px;border-radius:50%;background:rgba(18,100,255,.12);color:#1264FF;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;flex:none}
.b48{display:flex;flex-direction:column;gap:2px}
.b49{font-size:12px;direction:ltr;display:inline-block}
.b4a{color:rgba(14,42,107,.70)}
.b4b{background:#1264FF;color:#fff;padding:6px 13px;font-size:11.5px;font-weight:500}
.b4c{border:1px solid rgba(14,42,107,.28);padding:6px 13px;font-size:11.5px;color:rgba(14,42,107,.70)}
.b4d{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 18px;font-size:11.5px;color:rgba(14,42,107,.70)}
.b4e{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:16px 18px;border-block-end:1px solid rgba(14,42,107,.12)}
.b4f{font-size:15px;font-weight:600;font-variant-numeric:tabular-nums}
.b4g{display:flex;flex-direction:column;align-items:flex-end;gap:7px}
.b4h{padding:16px 18px;flex:1;display:flex;flex-direction:column}
.b4i{display:block;font-size:11px;color:rgba(14,42,107,.70);margin-bottom:10px}
.b4j{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.b4k{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;background:rgba(18,100,255,.05);border:1px solid rgba(14,42,107,.12)}
.b4l{font-size:12px}
.b4m{display:flex;align-items:center;gap:6px;font-size:11px;color:#1264FF;font-weight:500}
.b4n{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid rgba(14,42,107,.12)}
.b4o{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:16px}
.b4p{background:#1264FF;color:#fff;padding:9px 18px;font-size:12px;font-weight:500}
.b4q{border:1px solid rgba(14,42,107,.28);padding:9px 18px;font-size:12px;color:rgba(14,42,107,.70)}
.b4r{font-size:12px;color:#1264FF}
.b4s{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:16px 18px}
.b4t{padding:13px 14px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums}
.b4u{padding:13px 14px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;color:#0E2A6B}
.b4v{font-size:11.5px;color:#1264FF}
.b4w{padding:13px 14px;border-block-end:1px solid rgba(14,42,107,.12);font-variant-numeric:tabular-nums;color:rgba(14,42,107,.70)}
.b4x{padding:13px 18px;font-size:11.5px;color:rgba(14,42,107,.70)}
.b4y{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr));gap:1px;background:rgba(14,42,107,.18);margin-top:clamp(34px,6vh,58px);border:1px solid rgba(14,42,107,.18)}
.b4z{background:var(--paper);padding:clamp(24px,2.6vw,36px);display:flex;flex-direction:column;gap:14px;transition:background .35s ease,transform .35s cubic-bezier(.16,1,.3,1)}
.b50{font-family:'Amiri',serif;font-size:26px;font-weight:700;color:#1264FF}
.b51{font-size:15px;line-height:1.9;color:rgba(14,42,107,.8)}
.b52{border-top:1px solid rgba(14,42,107,.16);background:rgba(18,100,255,.055);padding:clamp(60px,11vh,120px) clamp(20px,4.5vw,72px);overflow:hidden}
.b53{display:flex;flex-direction:column;gap:20px;max-width:46ch}
.b54{display:flex;flex-wrap:wrap;gap:8px}
.b55{background:var(--paper);border:1px solid rgba(14,42,107,.24);padding:9px 15px;font-size:12.5px;transition:background .35s ease,transform .35s cubic-bezier(.16,1,.3,1)}
.b56{display:flex;flex-wrap:wrap;align-items:center;gap:18px;margin-top:2px}
/* STORE BADGES — Apple and Google artwork, shipped unmodified.
   Both vendors forbid recreating or restyling the badge, so .b57 carries NO
   border, NO background, NO padding, NO hover tint and NO filter: it is a bare
   link around the official image. The placeholder this replaced DID have a
   border, so adding one back looks like a restoration rather than a breach.
   Don't.

   NOTE: THE TWO BADGES ARE SET AT DIFFERENT HEIGHTS ON PURPOSE — 48px and 71px —
   AND THAT IS NOT A MISTAKE TO "FIX" BY EQUALISING THEM.

   MEASURED, not estimated: Apple's SVG canvas is 100% badge, edge to edge.
   Google's PNG ships with transparent padding baked in — the visible capsule is
   only 130 of its 192 canvas rows, i.e. 67.71%. So at one shared height the
   Google mark renders ~32% smaller and the pair reads as unbalanced, which is
   exactly what was reported.

   HEIGHT IS THE ONLY LEGITIMATE LEVER. Forcing equal WIDTHS would rescale one
   badge's wordmark against its own artwork, which both vendors prohibit.
   Instead each badge's height is tuned independently so the VISIBLE marks match:
   48 / 0.6771 ≈ 71. Both then show a ~48px capsule.

   Each still clears its own minimum with room to spare (Apple 40px, Google
   28px), and the 18px gap satisfies the larger of the two clear-space
   requirements — a quarter of each badge's OWN height, so 12px for Apple and
   17.75px for Google. If either height changes, re-derive the gap from the
   TALLER badge, not from a remembered number. */
.b57{display:inline-flex;align-items:center;text-decoration:none;border:0;padding:0;background:none}
.b57 img{display:block;inline-size:auto}
.b57 .b57a{block-size:48px}   /* App Store: canvas is all badge */
.b57 .b57b{block-size:71px}   /* Google Play: canvas is 67.71% badge */
.b57:focus-visible{outline:2px solid #1264FF;outline-offset:3px}
.b59{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:clamp(60px,7vw,110px);margin-top:clamp(44px,7vh,80px)}
.b5a{inline-size:min(100%,232px);display:flex;flex-direction:column;gap:18px;flex:none}
.b5b{animation:jw-lift .9s cubic-bezier(.16,1,.3,1) .05s both,jw-float 6s ease-in-out .95s infinite}
.b5c{box-sizing:border-box;inline-size:100%;background:var(--paper);border:1px solid rgba(14,42,107,.26);padding:15px 17px;transform:rotate(-5deg) scale(1.05);box-shadow:0 28px 42px -22px rgba(14,42,107,.6)}
.b5d{flex:none}
.b5e{animation:jw-lift .9s cubic-bezier(.16,1,.3,1) .2s both,jw-float 7.5s ease-in-out 1.1s infinite}
.b5f{box-sizing:border-box;inline-size:100%;background:var(--paper);border:1px solid rgba(14,42,107,.26);padding:15px 17px;transform:rotate(4deg) scale(1);box-shadow:0 18px 30px -20px rgba(14,42,107,.5)}
.b5g{font-size:11px;color:rgba(14,42,107,.72)}
.b5h{animation:jw-lift .9s cubic-bezier(.16,1,.3,1) .35s both,jw-float 9s ease-in-out 1.25s infinite}
.b5i{box-sizing:border-box;inline-size:100%;background:var(--paper);border:1px solid rgba(14,42,107,.26);padding:15px 17px;transform:rotate(-2deg) scale(0.93);box-shadow:0 12px 20px -16px rgba(14,42,107,.42);opacity:.92}
.b5j{position:relative;inline-size:246px;flex:none;margin:20px 0 clamp(54px,8vh,88px)}
.b5k{position:absolute;z-index:0;inset-inline-start:50%;inset-block-end:-42px;inline-size:200px;block-size:26px;margin-inline-start:-100px;background:radial-gradient(50% 50% at 50% 50%,rgba(14,42,107,.45),rgba(14,42,107,0) 70%);animation:jw-shadow 7s ease-in-out infinite}
.b5l{position:relative;z-index:2;transform-style:preserve-3d;animation:jw-hover 7s ease-in-out infinite}
.b5m{inline-size:246px;aspect-ratio:9/16.5;background:#0E2A6B;border-radius:34px;padding:9px;box-shadow:-22px 30px 60px -28px rgba(14,42,107,.6),0 2px 0 rgba(255,255,255,.12) inset}
.b5n{position:relative;block-size:100%;background:var(--paper);border-radius:26px;overflow:hidden}
.b5o{position:absolute;inset:0;display:flex;flex-direction:column;animation:jw-swapA 11s ease-in-out infinite}
.b5p{display:flex;align-items:center;justify-content:space-between;padding:15px 15px 11px}
.b5q{display:block;block-size:18px;inline-size:auto}
.b5r{font-family:'Amiri',serif;font-size:18px;font-weight:700}
.b5s{inline-size:23px;block-size:23px;border:1px solid rgba(14,42,107,.3);border-radius:50%}
.b5t{padding:2px 15px 0}
.b5u{display:block;font-size:10.5px;color:rgba(14,42,107,.72)}
.b5v{display:block;font-size:14px;font-weight:500;margin-top:7px}
.b5w{margin:14px 15px;background:#1264FF;color:#FFFFFF;border-radius:4px;padding:14px;text-align:center;font-size:13.5px;font-weight:500;animation:jw-pulse 3.2s ease-out infinite}
.b5x{padding:0 15px;display:flex;flex-direction:column;font-size:12px;color:rgba(14,42,107,.8)}
.b5y{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 0;border-top:1px solid rgba(14,42,107,.16)}
.b5z{flex:none;opacity:.5}
.b60{margin-top:auto;padding:11px 15px;border-top:1px solid rgba(14,42,107,.16);font-size:10px;color:rgba(14,42,107,.70)}
.b61{position:absolute;inset:0;display:flex;flex-direction:column;background:var(--paper);animation:jw-swapB 11s ease-in-out infinite}
.b62{display:flex;align-items:center;gap:9px;padding:15px}
.b63{font-size:13.5px;font-weight:500}
.b64{padding:0 15px;display:flex;flex-direction:column;font-size:12px}
.b65{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 0;border-top:1px solid rgba(14,42,107,.16)}
.b66{color:rgba(14,42,107,.72)}
.b67{margin:16px 15px 0;border:1px solid rgba(18,100,255,.45);background:rgba(18,100,255,.07);padding:13px;display:flex;align-items:center;gap:10px}
.b68{font-size:11.5px;line-height:1.6}
.b69{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));gap:clamp(26px,3.4vw,52px);margin-top:clamp(34px,6vh,58px)}
.b6a{display:flex;flex-direction:column;gap:14px}
.b6b{font-size:15.5px;line-height:1.8;color:rgba(14,42,107,.85);padding-block-start:12px;border-top:1px solid rgba(14,42,107,.2)}
.b6c{max-width:1440px;margin:0 auto;display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);gap:clamp(30px,5vw,80px);align-items:start}
.b6d{display:flex;flex-direction:column;gap:18px}
.b6e{margin:0;max-width:34ch;font-size:16px;line-height:1.9;color:rgba(14,42,107,.75)}
.b6f{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px}
.b6g{display:flex;flex-direction:column;gap:9px}
.b6h{font-family:inherit;font-size:15px;color:#0E2A6B;background:transparent;border:0;border-block-end:1px solid rgba(14,42,107,.35);padding:11px 2px;outline:none}
.b6i{font-family:inherit;font-size:15px;color:#0E2A6B;background:transparent;border:0;border-block-end:1px solid rgba(14,42,107,.35);padding:11px 2px;outline:none;text-align:end}
.b6j{color:rgba(14,42,107,.70)}
.b6k{display:flex;flex-direction:column;gap:9px;grid-column:1 / -1}
.b6l{font-family:inherit;font-size:15px;color:#0E2A6B;background:transparent;border:0;border-block-end:1px solid rgba(14,42,107,.35);padding:11px 2px;outline:none;resize:vertical}
.b6m{grid-column:1 / -1;justify-self:start;background:#1264FF;color:#FFFFFF;border:0;font-family:inherit;font-size:15.5px;font-weight:500;padding:17px 34px;border-radius:2px;cursor:pointer;margin-top:8px}
.b6n{border-top:1px solid rgba(14,42,107,.16);padding:34px clamp(20px,4.5vw,72px);display:flex;flex-wrap:wrap;gap:16px;justify-content:space-between;align-items:center;font-size:13px;color:rgba(14,42,107,.72)}
.b6o{display:flex;align-items:center;gap:10px}
.b6p{display:block;block-size:24px;inline-size:auto}
.b6q{font-family:'Amiri',serif;font-size:22px;font-weight:700;color:#0E2A6B}
.bc:hover{background:#1264FF;color:var(--paper);border-color:#1264FF}
.bk:hover{background:#0A4FD6}
.b6m:hover{background:#0A4FD6}

/* ==========================================================================
   [hidden] MUST WIN. This is a one-line rule with a long story.

   The HTML `hidden` attribute is only `display: none` in the UA stylesheet,
   so ANY author rule that sets display beats it. `.lead-ok { display: flex }`
   did exactly that, and the demo form's success panel - "وصلنا طلبك" - was
   on screen at all times, 208px tall, before anyone had submitted anything.

   WARNING - THIS SHIPPED. It is present on main and therefore on the live site. It
   was not introduced by the redesign; the redesign only made it VISIBLE,
   because the closing section changed from a pale ground to the deep ink one
   and a panel that had been quietly blending in became a bright green tick
   under the form.

   That is the fourth time on this project that a defect was found by looking
   at a render rather than by reading code, and the second involving this
   exact element (#lf-ok was previously measured at zero height because it
   was nested INSIDE the form it was meant to replace).

   The lesson worth keeping is not about lead-ok. It is that a element hidden
   with the attribute is only as hidden as the cascade allows, and every
   component that sets `display` on a toggleable element re-opens this. So
   the guard is global and marked !important deliberately: `hidden` is a
   statement of intent from the markup, and no component rule should be able
   to overrule it by accident.
   ========================================================================== */
[hidden] { display: none !important; }

/* ==========================================================================
   ACCENT ON CREAM: #1264FF MEASURES 4.05 AND BODY TEXT NEEDS 4.5.

   The brand blue is fine as a large display colour - the 56-104px chapter
   numerals only need 3:1 and clear it comfortably - but at 13-20px it is
   below the threshold for normal text.

   #0A4FD6 (accent-deep, already the hover colour, so the same family) is
   5.60 on cream. It is used for the SMALL accent text only, so the large
   numerals keep the brighter blue and the hierarchy is unchanged.

   Measured against var(--paper), not estimated.
   ========================================================================== */
.b1e { color: #0A4FD6; }   /* 20px chapter numerals in the problem list */
/* .b58 was the 13px "قريبًا" pill inside the placeholder store badges. Both
   placeholders were replaced by the real App Store / Google Play artwork when
   the app went live, so the class has no markup left and its contrast override
   went with it. */

/* ==========================================================================
   THE SCREENS TABS, AND THE STAGE THAT WAS CLIPPING THEM.

   The handoff drives these with data-tab / data-pane and its own runtime,
   which we do not ship. Three things followed from that:

     1. The buttons were inert - no handler, so clicking changed nothing.
     2. Only the first pane was ever visible, since nothing toggled them.
     3. The stage carried a hard `block-size: 460px` with `overflow: hidden`
        on the panel, and the loan table is taller than that, so its last row
        and its footnote were cut off mid-line.

   The handoff's runtime measured the tallest pane on load and on resize and
   wrote the height back. Rather than reimplement that in JS - a measurement
   that has to re-run after fonts load, on every resize, and is wrong for one
   frame each time - the stage is laid out with grid: all panes occupy the
   same cell, so the stage is naturally as tall as the tallest one and no
   measurement is needed at all.
   ========================================================================== */

/* Every pane stacks in one grid cell. The stage then sizes to the tallest,
   which is what the handoff's JS was computing. */
[data-screens-stage] {
  display: grid;
  block-size: auto !important;   /* overrides the handoff's fixed 460px */
}
[data-screens-stage] > [data-pane] {
  grid-area: 1 / 1;
  position: static !important;   /* was absolute; grid stacking replaces it */
  opacity: 0;
  transform: translateY(18px);
  pointer-events: none;
}
[data-screens-stage] > [data-pane].is-on {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* The panel can grow now, so nothing is cut off. */
[data-panel] { block-size: auto !important; }

/* Tab buttons: the handoff's own selected treatment. */
[data-tab] { transition: background .25s ease, color .25s ease, border-color .25s ease; }
[data-tab].is-on {
  background: var(--accent);
  color: #FFFFFF;
  border-color: var(--accent);
}
[data-tab]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ==========================================================================
   THE HERO GRID PROBE - a cell reacts, and its row and column recede.
   ========================================================================== */
[data-grid] i { transition: transform .3s cubic-bezier(.16,1,.3,1), opacity .3s ease, outline-color .3s ease; position: relative; }
[data-grid].is-probing i { opacity: .55; }
[data-grid] i.is-near { opacity: .55; }
[data-grid] i.is-hot {
  opacity: 1;
  transform: scale(1.42);
  z-index: 3;
  outline: 1px solid rgba(18, 100, 255, .85);
  outline-offset: 1px;
}
[data-days] span { transition: color .3s ease, font-weight .3s ease; }
[data-days] span.is-hot { color: var(--accent); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  [data-grid] i, [data-screens-stage] > [data-pane] { transition: none; }
  [data-screens-stage] > [data-pane] { transform: none; }
}

/* The handoff's section reveals. data-revealed is set by experience.js; the
   resting state lives here so a reader with no JS sees the page in full
   rather than a blank column. */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal]:not([data-revealed]) { opacity: 0; transform: translateY(28px); }
  [data-reveal] {
    transition: opacity .85s cubic-bezier(.16, 1, .3, 1),
                transform .95s cubic-bezier(.16, 1, .3, 1);
  }
  [data-reveal][data-revealed] { opacity: 1; transform: none; }
}

/* The navigation curtain: an ink wipe over in-page jumps. Driven by
   experience.js; never shown under reduced motion, where the jump is instant. */
.fx-curtain {
  position: fixed;
  inset: 0;
  background: var(--ink);
  z-index: 90;
  transform: translateY(100%);
  pointer-events: none;
}
.fx-curtain.is-down { transition: transform .5s cubic-bezier(.76, 0, .24, 1); transform: translateY(0); }
.fx-curtain.is-up   { transition: transform .5s cubic-bezier(.76, 0, .24, 1); transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) { .fx-curtain { display: none; } }

/* ==========================================================================
   THE SUCCESS PANEL, REPAINTED FOR A LIGHT GROUND.

   Everything about this panel was written for `.closing` - a deep navy
   section the old page ended with. White title, #E8EEF4 body, #A9B7C6 meta,
   white underlined links: all correct on navy, all near-invisible on cream.
   The handoff's demo section is cream, `.closing` does not exist on any page
   any more, and the panel measured 1.21:1 - white on var(--paper).

   WARNING: the rules above are not deleted, and that is deliberate. They are
   still correct FOR A DARK SECTION, and the comments on them record two real
   cascade defects (`.closing p` silently beating an unqualified colour) that
   whoever reinstates a dark section will hit again. What follows overrides
   them for the ground we actually ship.

   Contrast on var(--paper), measured not estimated:
     title  #0E2A6B  11.13:1
     line   rgba(ink,.80)  6.53:1
     meta   rgba(ink,.72)  5.20:1
     mark   #1C6B4A  5.90:1
   ========================================================================== */
.lead-ok {
  background: rgba(18, 100, 255, .05);
  border: 1px solid rgba(18, 100, 255, .30);
}
.lead-ok__mark  { color: #1C6B4A; }
.lead-ok__title { color: var(--ink); }
.lead-ok__line  { color: rgba(var(--ink-rgb), .80); }
.lead-ok__meta  { color: rgba(var(--ink-rgb), .72); }
.lead-ok__meta a,
.lead-ok__email { color: var(--accent-deep); }
.lead-ok__meta a { text-decoration: underline; }

/* ==========================================================================
   MOBILE. The handoff was authored at desktop width only - no media queries
   at all - so every page overflowed horizontally below ~700px. Measured at
   320/390: the document was 593px wide inside a 320px viewport.

   Two causes, not one:
     1. The nav's link row does not wrap, so logo + four links + toggle +
        login + button sit on one line no matter how narrow the viewport.
     2. The product screens contain real tables (payslip, service desk, loan
        schedule) that are legitimately wider than a phone.

   The tables are NOT squeezed. A payslip with six columns crushed into 320px
   is unreadable; scrolling it sideways inside its own frame is how a table
   is read on a phone, and the page itself stays still.
   ========================================================================== */

@media (max-width: 720px) {
  /* The nav stacks: brand on its own line, then the links, then the actions.
     Nothing is hidden behind a menu button - there are only four links and
     they fit on two rows. */
  nav.b4 {
    flex-wrap: wrap;
    gap: 14px;
    padding-block: 18px;
  }
  nav.b4 > div { flex-wrap: wrap; gap: 14px 20px; min-inline-size: 0; }
  nav.b4 .b9 { flex-wrap: wrap; gap: 12px 18px; font-size: 13px; }

  /* Section padding tightens; the handoff's clamp floor is still desktop-ish. */
  section { padding-inline: 18px !important; }

  /* WARNING: EVERY FIXED-COUNT GRID COLLAPSES TO ONE COLUMN.
     A first attempt named four classes and missed ten - including .b1j, the
     two-column chapter layout (text beside screenshot) that was still running
     at 390px and giving each side 162px. THAT was the real cause of the
     shredded tables: the table was inside a 160px frame, so no amount of
     min-width on the table itself could help.
     The list is generated from the stylesheet rather than typed, so a grid
     added later cannot be forgotten - see .rebuild/ for the extraction. */
  .be, .b1j, .b26, .b2a, .b32, .b4j, .b6c, .b6f {
    grid-template-columns: 1fr !important;
  }
}

/* Tables scroll inside their own frame, at every width.

   Scoped to the table's OWN parent rather than to a named wrapper: the
   handoff puts its tables inside several different containers ([data-panel]
   in the screens section, a plain div in the attendance chapter), and a rule
   naming one of them silently misses the others. `:has()` asks the question
   directly - "the element that contains a table" - instead of enumerating
   the places a table happens to live today. */
:where(div, section):has(> table) {
  /* WARNING: overflow-x, NOT overflow. The handoff sets `overflow: hidden` on some
     of these wrappers (.b1x), and a shorthand from a zero-specificity
     :where() loses to it - the table then cannot scroll and pushes the whole
     page wide instead. The !important is on the axis only: vertical clipping
     is deliberate in the handoff's panels and is left alone. */
  overflow-x: auto !important;
  -webkit-overflow-scrolling: touch;
}
/* WARNING: NO `min-inline-size: max-content` HERE.
   A first attempt set it, and privacy's data table - which had been fitting
   a phone perfectly well by wrapping its cells - was forced to 1210px and
   made to scroll for no reason. A table only needs a minimum when its
   content genuinely cannot wrap; the handoff's product tables carry their
   own widths already, and everything else should be left to wrap.
   The overflow on the parent is the whole fix. */

/* The hero's month grid is 8 columns of shifts across 5 roles. Squeezed into
   320px each cell is 2mm wide and the graphic says nothing, so it scrolls
   inside its own frame instead.

   WARNING: THE SCROLL MUST BE ON THE ELEMENT THAT DIRECTLY WRAPS THE WIDE ONE.
   A first attempt put overflow on [data-tilt] and min-inline-size on the grid
   four levels below it; the intervening divs simply grew and the PAGE got
   wider - 593px became 927px, worse than before the fix. .bx is the flex row
   holding the role labels and the grid; .by is the column that contains the
   day header and the cells, and is the one that must scroll. */
@media (max-width: 720px) {
  .by { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .by > [data-grid],
  .by > [data-days] { min-inline-size: 380px; }
}

/* The hero's two decorative circles sit deliberately outside their frame
   (inset-inline-end: -30px). On a wide viewport that overhang is inside the
   page gutter and invisible as overflow; on a phone there is no gutter left
   and they push the document wider than the screen.

   Clipped at the section rather than hidden: the part of the circle that is
   on screen is still drawn, exactly as designed, and only the overhang is
   cut. Diagnosed by asking the browser which elements had a bounding box
   outside the viewport - the answer was two circles and a bidi span, not the
   tables everyone assumes. */
@media (max-width: 720px) {
  section, main { overflow-x: clip; }
}

/* ==========================================================================
   THE FOOTER, AND THE ONLY WAY TO REACH FOUR OF THE TEN PAGES.

   The handoff's footer is one line: the lockup and "Riyadh, Saudi Arabia".
   Its nav carries four same-page fragments. Between them, /pricing/,
   /support/, /privacy-policy/ and the language toggle were reachable from NOWHERE -
   four of the ten pages we ship, with no route in except by typing the URL.

   That is not a handoff defect. A single-page mockup has no other pages to
   link to; the omission only becomes one when the mockup becomes a site.

   Built in the handoff's own idiom - same hairline border, same 34px block
   padding, same 13px muted text - rather than reinstating the old footer's
   markup, which belonged to a different design.
   ========================================================================== */

.site-foot {
  border-block-start: 1px solid rgba(var(--ink-rgb), .16);
  padding: 44px clamp(20px, 4.5vw, 72px) 34px;
  display: grid;
  gap: 32px;
  font-size: 13px;
  color: rgba(var(--ink-rgb), .72);
}

.site-foot__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 28px 32px;
}

.site-foot__head {
  margin: 0 0 12px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  /* .72, not .55. The measured floor on this cream ground is .70 for
     body-size text, and I reached for .55 out of habit while writing this
     block - the same value the contrast pass had already raised everywhere
     else in the file. A number that was wrong once is not safer the second
     time it is typed. */
  color: rgba(var(--ink-rgb), .72);
}

.site-foot__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.site-foot__list a { color: rgba(var(--ink-rgb), .78); }
.site-foot__list a:hover { color: var(--accent-deep); }

.site-foot__base {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 20px;
  justify-content: space-between;
  align-items: center;
  padding-block-start: 26px;
  border-block-start: 1px solid rgba(var(--ink-rgb), .12);
}

/* ==========================================================================
   THE GROUND IS WHITE.

   The Blue Ink handoff paints #EFE9DE - a warm cream - and the conversion
   carried that literal into 22 rules as well as into the --paper token.
   Changing the token alone would have left those 22 unchanged and produced a
   page half white and half cream, which is the composition defect this
   project has hit repeatedly: each half correct, the relationship wrong.

   So every literal now reads the token.

   The SECOND ground - the alternating band that separates one section from
   the next - went #E7E0D2 -> #F4F2EC -> #F5F7FA. The middle step was still
   warm, and warm next to white reads as yellow rather than as a neutral
   band: a tint only looks neutral beside something warmer, and once the page
   went white it had nothing to be neutral against. #F5F7FA is faintly COOL,
   which sits under the navy ink instead of fighting it. Removing the band
   entirely was the alternative and would erase the section rhythm.

   WARNING: CONTRAST IS RE-DERIVED, NOT ASSUMED. Every alpha in this file was
   calibrated against #EFE9DE: .70 was the measured floor for 4.5:1. White is
   a LIGHTER ground, so every ink-on-ground ratio can only improve - but that
   is an argument, not a measurement, and the contrast sweep is re-run below.
   ========================================================================== */

/* ==========================================================================
   MOBILE TABLES: give them a floor, so the scroll container is actually used.

   THE DEFECT, and why the earlier fix made it invisible instead of fixing it.
   The handoff's tables are `inline-size: 100%`. Wrapping them in an
   overflow-x container removed the page-level overflow - and the table then
   OBEYED the squeeze rather than scrolling: three columns inside 160px, every
   cell shredded to one word per line. Section B measured zero overflow and
   was right; the page was still unreadable. `overflow-x: auto` on a container
   does nothing for a child that has agreed to shrink.

   So the child must refuse. `min-inline-size` on the table means it keeps
   legible columns and the container scrolls - which is what the container was
   added for.

   WARNING: THE FLOOR IS PER TABLE, not global. A previous attempt set
   `min-inline-size: max-content` on every table and forced privacy's
   three-column data table to 1210px, making it scroll when it had been
   fitting a phone comfortably. Content that CAN wrap should wrap; only a
   table whose columns are structural gets a floor.
   ========================================================================== */
@media (max-width: 720px) {
  /* The product screens: attendance report, service desk, loan schedule.
     Their columns are a record's fields - shrinking them destroys the row. */
  [data-panel] table,
  .b2j,
  /* The service-desk table in the screens panel. Its cells hold whole
     sentences ("Annual Leave · Sep 23 to Oct 22, 2026 (22 days)") and at
     360px they shredded to 11 words over 8 LINES - measured, and the last
     shredding left on any page. Its scroll container (.b3z, overflow:auto)
     was already there and unused, exactly like the tables above: the floor
     is what makes the container do its job. */
  .b42 { min-inline-size: 760px; }

  /* SIX columns, not the three or four the 560px floor was sized for.
     MEASURED at 560: the table did reach its floor and its scroll container
     worked, and the longest cell STILL got 76px of it while the two action
     buttons took 167 - auto table layout distributing by content, not by
     need. The floor has to clear what the widest row actually wants, so it
     is derived from the column that shreds, not from the other tables. */

  /* WARNING: PROSE TABLES STACK. They do not scroll and they do not shrink.

     privacy carries a three- and a four-column table whose cells are whole
     sentences. At 390px each column gets ~90px and every cell shreds to one
     word per line - 44 of the check's findings on that page alone. Scrolling
     is the wrong answer here: a reader comparing a row's three fields would
     have to scroll sideways for each row, and the columns are prose rather
     than a record's fields.

     So each row becomes a labelled block. The <th scope="col"> text is
     carried into a ::before via a data-label attribute... except NO markup
     change is needed: the headers are read by the screen reader from the
     real <th>, and sighted readers get the row as three stacked sentences
     under one heading. The header row is hidden because it labels columns
     that no longer exist visually.

     WARNING: THE TABLE SEMANTICS SURVIVE. display:block on table elements would
     normally destroy the accessibility tree, so `role` is restored
     explicitly - the screen-reader experience is unchanged and only the
     visual layout differs. */
  .doc-page table,
  .no-reveal table { display: block; min-inline-size: 0; }
  .doc-page thead,
  .no-reveal thead { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); }
  .doc-page tbody, .doc-page tr, .doc-page td, .doc-page th,
  .no-reveal tbody, .no-reveal tr, .no-reveal td, .no-reveal th { display: block; }
  .doc-page tr,
  .no-reveal tr {
    padding-block: var(--s-4, 1rem);
    border-block-end: 1px solid rgba(var(--ink-rgb), .14);
  }
  .doc-page td,
  .no-reveal td { padding-block: .3rem; padding-inline: 0; border: 0; }
  /* The first cell of each row carries the weight, so a reader scanning the
     stack can tell where one row ends and the next begins. */
  .doc-page td:first-child,
  .no-reveal td:first-child { font-weight: 600; }
}

/* ==========================================================================
   THE LAST FIVE MOBILE DEFECTS.

   1. `main` overflowed its own viewport by 10px. It is a flex container, and
      a flex ITEM defaults to `min-width: auto` - it refuses to shrink below
      its content's intrinsic width no matter what the parent says. This is
      the single most common flexbox trap and it does not announce itself:
      the page simply is 10px too wide.

   2. The service-desk summary cell held a whole sentence in a column sized
      for a ticket id, shredding to 11 words over 8 lines. Its panel is given
      the same scroll treatment as the tables it sits beside.

   3. .b1x carried `overflow: hidden`, so the employee card inside it was cut
      off with no way to reach the rest. Scrolls on the inline axis now, and
      keeps its vertical clipping.
   ========================================================================== */
@media (max-width: 720px) {
  /* (1) let every flex item shrink. */
  main, main > *, [data-panel] > *, .b1t, .b1u { min-inline-size: 0; }

  /* (2) + (3) panels scroll on the inline axis rather than clipping. */
  .b1x { overflow-x: auto; overflow-y: hidden; }

  /* The screens panels hold real records; give them the same floor the
     tables have so their columns stay legible while the frame scrolls. */
  .b3z, .b4h { min-inline-size: 0; }
  .b3z > *, .b4h > * { min-inline-size: 0; }
}

/* ==========================================================================
   THE PHONE, LARGER.

   The handoff draws it at 246px, which is small beside a 46px chapter
   heading and makes its two screens hard to read - the whole point of the
   section is that a reader can see what the employee sees.

   306px on a wide viewport, and it scales down with the viewport rather than
   being pinned: `min()` keeps it inside a phone-width column, where 306px
   would otherwise be nearly the whole screen. The cards beside it grow in
   proportion so the group keeps its composition.

   aspect-ratio does the rest - the screens, the type inside them and the
   ground shadow all follow the width, so nothing needs re-measuring.
   ========================================================================== */
/* WARNING: THE CLASS NAMES ARE THE GENERATED ONES, and the first version of this
   rule used .phone-wrap / .phone-body from the PREVIOUS build - which appear
   on no page at all, so it styled nothing. The conversion replaced that
   markup with the handoff's own; .b5j is the wrapper, .b5m the device, .b5h
   the card column. Verified by reading the built page, not by recalling what
   the classes used to be. */
.b5j { inline-size: min(306px, 78vw); }
.b5m { inline-size: 100%; }
.b5a { inline-size: min(100%, 268px); }

/* On a phone the device would fill the screen; keep it clearly a device
   sitting on the page rather than the page itself. */
@media (max-width: 720px) {
  .b5j { inline-size: min(262px, 68vw); }
  .b5a { inline-size: min(100%, 240px); }
}

/* ==========================================================================
   THE PHONE NAV DRAWER

   Measured on a 390px phone: logo + 6 section links + 3 actions filled 300px
   before any content, so the headline sat below the fold and a visitor's
   first screen was a menu rather than the product. Nothing was clipped - the
   flex-wrap fix worked - and it was still the wrong first impression.

   NO JAVASCRIPT. The drawer is a checkbox and a label, so it opens with CSS
   alone. That is a hard requirement, not a preference: a menu that needs JS
   to open is a menu that can trap a visitor with no way back to the page.
   With CSS but no JS it works; with neither it degrades to the wrapped nav,
   which is the current behaviour and is navigable.

   The checkbox is NOT [hidden] - it is clipped instead. `hidden` removes an
   element from the tab order, which would leave a keyboard user unable to
   open the menu at all.

   The demo CTA stays OUTSIDE the drawer at every width. It is the one action
   the page exists for, and hiding it behind a tap is the kind of tidiness
   that costs conversions.
   ========================================================================== */

.navstate {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.navtoggle { display: none; }

@media (max-width: 720px) {
  .navtoggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 44px;
    block-size: 44px;
    flex: 0 0 auto;
    cursor: pointer;
    border: 1px solid rgba(14, 42, 107, .22);
    border-radius: 2px;
    order: 3;
  }

  /* Three bars drawn from one element: the middle is the box's own border,
     the outer two are pseudo-elements. Fewer nodes than three spans, and it
     cannot fall out of sync with itself. */
  .navtoggle__bars,
  .navtoggle__bars::before,
  .navtoggle__bars::after {
    display: block;
    inline-size: 18px;
    block-size: 2px;
    background: var(--ink, #0E2A6B);
    border-radius: 2px;
  }

  .navtoggle__bars { position: relative; }

  .navtoggle__bars::before,
  .navtoggle__bars::after {
    content: '';
    position: absolute;
    inset-inline-start: 0;
  }

  .navtoggle__bars::before { inset-block-start: -6px; }
  .navtoggle__bars::after { inset-block-start: 6px; }

  /* The nav becomes: lockup | demo CTA | toggle. The section links and the
     secondary actions move into the drawer. */
  nav.b4 {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: nowrap;
  }

  nav.b4 > .b5 { flex: 1 1 auto; min-inline-size: 0; }

  .b9,
  .ba > a:not(.bc) {
    display: none;
  }

  .ba {
    flex: 0 0 auto;
    gap: 0;
    order: 2;
  }

  .bc {
    font-size: 13px;
    padding: 11px 14px;
    white-space: nowrap;
  }

  /* OPEN: the drawer is the section links plus the actions the bar dropped.
     align-items:flex-start keeps the toggle and the lockup on the TOP row.
     Without it the nav's default centring measures against the whole opened
     drawer, and the close control floats to the vertical middle - away from
     the logo, and away from where a visitor looks to shut a menu. */
  .navstate:checked ~ nav.b4 {
    flex-wrap: wrap;
    align-items: flex-start;
  }

  .navstate:checked ~ nav.b4 .b9 {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    inline-size: 100%;
    gap: 0;
    order: 4;
    margin-block-start: 12px;
    border-block-start: 1px solid rgba(14, 42, 107, .14);
  }

  .navstate:checked ~ nav.b4 .b9 > a {
    padding: 14px 4px;
    border-block-end: 1px solid rgba(14, 42, 107, .10);
  }

  .navstate:checked ~ nav.b4 .ba {
    order: 5;
    inline-size: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 10px 18px;
    margin-block-start: 12px;
  }

  .navstate:checked ~ nav.b4 .ba > a:not(.bc) {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
  }

  /* The bars become an X, so the control says what it will do next. */
  .navstate:checked ~ nav.b4 .navtoggle__bars { background: transparent; }
  .navstate:checked ~ nav.b4 .navtoggle__bars::before { inset-block-start: 0; transform: rotate(45deg); }
  .navstate:checked ~ nav.b4 .navtoggle__bars::after { inset-block-start: 0; transform: rotate(-45deg); }
}

/* Focus must be visible on the label, since the input it controls is clipped. */
.navstate:focus-visible ~ nav.b4 .navtoggle {
  outline: 2px solid var(--accent, #1264FF);
  outline-offset: 2px;
}
