/* Cairo (SIL OFL) — bundled, never fetched from a CDN: the strict CSP
       forbids external origins, and a self-hosted face renders identically on
       every device instead of depending on what the OS happens to have.
       Arabic subset only; Cairo's Latin file and the logo's faces below carry the rest. */
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:400;
      font-display:swap; src:url("fonts/cairo-400.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:"Cairo"; font-style:normal; font-weight:500;
      font-display:swap; src:url("fonts/cairo-500.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:"Cairo"; font-style:normal; font-weight:600;
      font-display:swap; src:url("fonts/cairo-500.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:"Cairo"; font-style:normal; font-weight:700;
      font-display:swap; src:url("fonts/cairo-700.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:"Cairo"; font-style:normal; font-weight:800;
      font-display:swap; src:url("fonts/cairo-800.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; }
    /* The Cairo files above are an Arabic-only subset: no digits, no Latin, not
       even a full stop. Every figure on the site — the counters, +965, each KWD
       amount — was painted in whatever the device had (DejaVu, Segoe, SF). Cairo's
       own Latin subset, one variable file for every weight, fills that range. */
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:400;
      font-display:swap; src:url("fonts/cairo-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:500;
      font-display:swap; src:url("fonts/cairo-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:600;
      font-display:swap; src:url("fonts/cairo-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:700;
      font-display:swap; src:url("fonts/cairo-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"Cairo"; font-style:normal; font-weight:800;
      font-display:swap; src:url("fonts/cairo-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    /* The logo's Latin faces (design/site_fonts.py): Chakra Petch for the
       Latin half of a display line, JetBrains Mono for figures, handles and
       the ">_" prompt. Latin-only subsets with Cairo's Latin range, so they
       claim no Arabic and Cairo keeps every Arabic letter. SIL OFL. */
    @font-face { font-family:"Chakra Petch"; font-style:normal; font-weight:600;
      font-display:swap; src:url("fonts/chakrapetch-600.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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"Chakra Petch"; font-style:normal; font-weight:700;
      font-display:swap; src:url("fonts/chakrapetch-700.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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    @font-face { font-family:"JetBrains Mono"; font-style:normal; font-weight:100 800;
      font-display:swap; src:url("fonts/jetbrainsmono-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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
    /* The token set is identical on every page of this site — divergence
       between pages has been a real bug before, and the test suite fails on it. */
    :root { --lh-ui: 1.35; --lh-head: 1.4; --lh-text: 1.5; --lh-read: 1.6;
      color-scheme: dark;   /* one dark theme on every device: the logo's own ground */
      /* THE LOGO'S THEME (owner's approval, 2026-10-07): the near-black ground
         of the English logo, its amber, its white. Every value is solved in
         OKLCH against WCAG, never picked by eye. The surfaces lift the ground's
         own lightness at its own hue, so they stay near-neutral (red minus blue
         at most 3: no brown paper). On a dark page the binding surface is the
         LIGHTEST one an ink can land on, so every ink is graded on panel-3. */
      --bg: #070a0e; --panel: #10151b; --panel-2: #171e27; --panel-3: #202a35;
      /* clarity pass (2026-10-07): OKLCH L .141 · .197 · .229 · .266 at hue 70,
         chroma .0035, so a card is 1.09:1 off the page (was 1.07) and the
         hairline 1.79:1 on a card (was 1.53) */
      --border: #354251;        /* card and rule hairlines, 1.79:1 on a card: decoration, not a control's edge */
      --border-input: #6f7b8a;  /* a field's edge, 3.40:1 on panel-3 */
      --text: #f3f5f7;          /* 12.92:1 on panel-3, 15.44:1 on a card */
      --muted: #b7c0cb;         /* 7.80:1 on panel-3, 9.32:1 on a card (was 7.02) */
      --tint: #e7b567;          /* the logo's amber: links, focus, accents, 7.41:1 on panel-3 */
      --tint-hover: #f2c87c;    /* the amber one step lighter, for a hovered amber fill */
      --on-tint: #070a0e;       /* ink on an amber fill, 9.66:1. White on amber is 2.06:1 */
      --stripe: #876432;        /* the logo's dark band: the amber at 55% */
      --tint-strong: #070a0e;   /* the bar: the logo's ground. theme-color matches it */
      --on-bar: #f4f4f4;        /* every label on the bar, 18.09:1 */
      --on-bar-bd: #687585;     /* the only edge of a control on the bar, 4.25:1 */
      --on-bar-fill: #19212a;   /* hover and active fill on the bar, its labels 13.73:1 */
      --sand: #f2d855;          /* warnings only: a yellow, lighter than the amber accent */
      --good: #3ab873; --danger: #f68179; --info: #68a6f3;   /* each 6.0:1 on panel-3 */
      --warn-bg: #10151b;
      /* charts: one amber ramp, every step at least 2:1 on the card, monotone
         in lightness so later steps carry more ink */
      --ord-1: #5f431d; --ord-2: #80602f; --ord-3: #a57c42; --ord-4: #c99a54; --ord-5: #e7b567;
      --viz-pos: #3ab873; --viz-neg: #f68179; --viz-zero: #5f6b78; --viz-grid: #2c3641;
      /* type: Cairo for Arabic everywhere. The logo's own Latin faces carry
         Latin-only ranges, so Arabic in the same element falls through to Cairo */
      --display: "Chakra Petch", "Cairo", system-ui, sans-serif;
      --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, "Cairo", monospace;
      --sans: "Cairo", system-ui, -apple-system, "Segoe UI", Roboto, "Noto Kufi Arabic", "Noto Sans Arabic", sans-serif;
    }

    * { box-sizing: border-box; }
    [hidden] { display: none !important; }
    body { margin: 0; min-height: 100vh; background: var(--bg); color: var(--text); font-family: var(--sans); }
    a { color: var(--tint); text-decoration: none; }

    /* Centred masthead: the logo, the terminal line beneath it, then the nav,
       one axis, one rhythm.
       Spacing is one scale on every page: 4 · 6 · 8 · 12 · 16 · 20 · 24 · 32 · 40 · 56.
       Interactive rows sit at 44px by intent, not by snapping. */
    /* ═══════ the masthead: the logo on its own ground ═══════
       (the dark theme, owner's approval 2026-10-07). The bar is the logo's
       near-black ground (--tint-strong = --bg), closed by the logo's fading
       amber rule. Every label on it is solved: #f4f4f4 at 18.09:1, the amber
       at 9.66:1. It shrinks once the page scrolls, or a full masthead would eat
       a fifth of a phone screen on every section. */
    header {
      position: sticky; top: 0; z-index: 50;
      display: flex; flex-direction: column; align-items: center; gap: 8px;
      padding: 12px 20px; background: var(--tint-strong);
      border-bottom: 1px solid var(--on-bar-fill);
      transition: padding .22s ease;
    }
    header::after { content: ""; position: absolute; inset-inline: 0; bottom: -1px; height: 1px;
      background: linear-gradient(90deg, rgba(231, 181, 103, 0), rgba(231, 181, 103, .55), rgba(231, 181, 103, 0));
      pointer-events: none; }
    .brand { display: flex; flex-direction: column; align-items: center; gap: 8px;
      text-align: center; color: var(--on-bar); }
    /* the logo: the English lockup's wordmark, outlined (design/logo-en/build.py
       writes it between the markers below, with three stripe bands so every
       dark band is a whole pixel at this size), and the logo's own glow at
       the same sigma per letter height as the kit's (40 on a 212px word) */
    .brand .logo { display: block; flex: none; width: 280px; height: auto;
      overflow: visible; --glow: 8px; filter: drop-shadow(0 0 var(--glow) rgba(231, 181, 103, .32));
      transition: width .22s ease; }
    /* the halo keeps the kit's sigma per letter height at every width (8px
       on the 280px word): a fixed 8px on the 140px compact word was twice
       the logo's glow and hazed the letters' feet into the CODE row */
    html.scrolled .brand .logo { --glow: 5px; }
    /* the terminal line: what the company is, in Arabic, behind the logo's
       prompt and before its cursor. The cursor stands still: an endless
       animation in a sticky bar would run on every screen of the page */
    .brand .term { display: inline-flex; align-items: center; gap: 8px; font-family: var(--sans);
      font-size: 13px; font-weight: 600; line-height: var(--lh-ui); color: var(--on-bar);
      overflow: hidden; max-height: 24px; transition: max-height .22s ease, opacity .22s ease; }
    .brand .term .pr { font-family: var(--mono); font-weight: 700; color: var(--tint);
      direction: ltr; unicode-bidi: isolate; }
    .brand .term .cur { display: inline-block; width: .47em; height: 1em; background: var(--tint); opacity: .85; }
    /* scrolled: the bar becomes a slim strip with the logo still centred; the
       terminal line collapses, the company's name (the logo) stays */
    html.scrolled header { padding-block: 8px; }
    html.scrolled .brand { gap: 4px; }
    html.scrolled .brand .logo { width: 168px; }
    html.scrolled .brand .term { max-height: 0; opacity: 0; }

    nav.site { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; justify-content: center; }
    nav.site a, .btn {
      font-size: 14px; line-height: var(--lh-ui); font-weight: 600; color: var(--text);
      padding: 12px 16px; border-radius: 8px; border: 1px solid transparent;
      cursor: pointer; background: transparent; font-family: var(--sans);
    }
    /* on the bar: light links, and the one call to action is the logo's amber
       with the ground's ink (9.66:1; white on amber would be 2.06) */
    nav.site a { color: var(--on-bar); }
    nav.site a:hover { background: var(--on-bar-fill); }
    nav.site .btn.primary { background: var(--tint); color: var(--on-tint); border-color: var(--tint); }
    nav.site .btn.primary .ic { stroke: var(--on-tint); color: var(--on-tint); }
    nav.site .btn.primary:hover { background: var(--tint-hover); border-color: var(--tint-hover); }
    header a:focus-visible, header .btn:focus-visible { outline: 2px solid var(--on-bar); outline-offset: 2px; }

    .btn.primary { background: var(--tint); color: var(--on-tint); border-color: var(--tint); }
    .btn.outline { border-color: var(--border-input); background: var(--panel-2); }
    /* states, the same on every page: a hover that can be seen (a border that
       turns amber, not a fill one step lighter), a disabled that still reads */
    .btn { font-weight: 700; }
    /* a keyboard journey starts at the content, not seven stops of chrome */
    .skip { position: absolute; top: -56px; inset-inline-start: 8px; z-index: 100; background: var(--tint);
      color: var(--on-tint); padding: 8px 12px; border-radius: 8px; font-weight: 700; }
    .skip:focus { top: 8px; outline: 2px solid var(--on-bar); outline-offset: 2px; }
    main:focus, [tabindex="-1"]:focus { outline: none; }
   /* the links above stay 600: bold, four wrap at 320px */
    .btn:hover { background: var(--panel-3); border-color: var(--tint); }
    .btn.primary:hover { background: var(--tint-hover); border-color: var(--tint-hover); }
    .btn:disabled { opacity: .6; cursor: not-allowed; }
    /* scoped to main and the footer: unscoped, .btn:focus-visible (0,2,0) beat
       the bar's light ring (0,1,1) */
    main a:focus-visible, main .btn:focus-visible, footer a:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }

    main { max-width: 1060px; margin: 0 auto; padding: 16px 20px 40px;  line-height: var(--lh-text); }

    /* ═══════ rails: the sliders that replaced the card grids ═══════
       (owner's request, 2026-07-30: "less grids, slide"). One horizontal
       scroll-snap track per section; the cards keep the site's card anatomy.
       The track is native overflow scroll, so it swipes on touch, drags on
       trackpads, and arrow-scrolls when focused — the buttons and dots are
       an enhancement on top, not the mechanism. Without JS the arrows stay
       hidden (html.js gates them) and the rail is still a swipeable row. */
    .rowhead { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
    .rowhead h2.section { margin-bottom: 0; }
    .rowhead .sub { margin-bottom: 0; }
    .railnav { display: none; gap: 6px; flex: none; padding-bottom: 4px; }
    html.js .railnav { display: flex; }
    .arrow { width: 44px; height: 44px; border-radius: 12px; border: 1px solid var(--border-input);
      background: var(--panel); color: var(--tint); display: grid; place-items: center;
      cursor: pointer; padding: 0; transition: background .18s ease, opacity .18s ease; }
    .arrow:hover { background: var(--panel-2); border-color: var(--tint); }
    .arrow:disabled { opacity: .35; cursor: default; }
    .arrow:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }
    .arrow .ic { width: 18px; height: 18px; }
    .arrow.prev .ic { transform: scaleX(-1); }  /* RTL: previous returns rightwards */

    .railwrap { position: relative; margin-top: 12px; }
    .rail { display: grid; grid-auto-flow: column; grid-auto-columns: min(78vw, 264px);
      gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory;
      padding: 8px 4px 12px; margin: -8px -4px 0; scroll-padding-inline: 4px;
      scrollbar-width: none; }
    .rail::-webkit-scrollbar { display: none; }
    .rail > * { scroll-snap-align: start; }
    .rail:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; border-radius: 8px; }
    #nokhatha .rail { grid-auto-columns: min(84vw, 320px); }
    #services .rail { grid-auto-columns: min(84vw, 312px); }

    /* the fade marks the edge that still hides content; JS clears the
       fade on the exhausted side via at-start / at-end. Gated behind html.js
       like the arrows: without the script nothing maintains the classes, and
       a permanent fade over an exhausted edge lies about hidden content. */
    html.js .railwrap::before, html.js .railwrap::after { content: ""; position: absolute; top: 0;
      bottom: 12px; width: 28px; pointer-events: none; z-index: 1; transition: opacity .25s ease; }
    html.js .railwrap::before { left: -4px; background: linear-gradient(90deg, var(--bg), rgba(7, 10, 14, 0)); }
    html.js .railwrap::after { right: -4px; background: linear-gradient(270deg, var(--bg), rgba(7, 10, 14, 0)); }
    .slider.at-start .railwrap::after { opacity: 0; }
    .slider.at-end .railwrap::before { opacity: 0; }
    .dots { display: flex; justify-content: center; gap: 6px; margin-top: 8px; }
    .dots span { width: 8px; height: 8px; border-radius: 999px; background: var(--border-input);
      transition: background .25s ease, width .25s ease; }
    .dots span.on { background: var(--tint); width: 20px; }
    .slider.no-slide .railnav, .slider.no-slide .dots { display: none; }

    /* ═══════ the flow map: what the system actually does, drawn ═══════
       The sentence above it says a number is written once and travels to the
       financial statement. This shows it: two sources feed one core, the core
       feeds the filing, and current runs along the wires between them. It is a
       labelled diagram first and an animation second — with motion off it still
       reads as the same explanation, which is why the labels are real text and
       not decoration. */
    .flowmap { display: flex; align-items: center; gap: 8px; margin-top: 16px;
      padding: 16px; background: var(--panel-2); border: 1px solid var(--border);
      border-radius: 12px; }
    .fcol { display: flex; flex-direction: column; gap: 8px; }
    .fnode { flex: none; background: var(--panel); border: 1px solid var(--border);
      border-radius: 12px; padding: 8px 12px; display: flex; align-items: center; gap: 8px;
      min-width: 0; }
    .fnode .ic { width: 18px; height: 18px; }
    .fnode b { font-size: 13px; display: block; line-height: 1.4; }
    .fnode span { font-size: 12px; color: var(--muted); display: block; line-height: 1.4; }
    .fnode.hub { border-color: var(--tint);  }
    /* the wire: dashes that travel from the sources toward the filing */
    /* The dashes live on a layer one period longer than the wire, and the
       layer slides by that period: the same picture as moving the background,
       but a transform runs on the compositor, where background-position
       repainted every wire on every frame. */
    .wire { flex: 1; min-width: 24px; height: 2px; border-radius: 2px;
      position: relative; overflow: hidden; opacity: .55; }
    .wire::before { content: ""; position: absolute; inset: 0 -20px 0 0;
      background-image: linear-gradient(90deg, var(--tint) 0 45%, transparent 45% 100%);
      background-size: 20px 2px; background-repeat: repeat-x; }
    html.motion .wire::before { animation: flow 1.1s linear infinite; }
    @keyframes flow { to { transform: translateX(-20px); } }
    /* each source carries its own wire so the line always meets the node it
       leaves — a single stretched connector cannot know where two boxes of
       unknown height sit, and drifted off them as soon as the copy changed */
    /* nodes size to their labels and never wrap; the wires take what is left,
       so the diagram keeps its rhythm instead of squeezing the words */
    .fcol.sources { flex: none; }
    .frow { display: flex; align-items: center; gap: 8px; }
    .frow .fnode { flex: none; }
    .frow .wire { flex: 1; min-width: 36px; }
    .fnode b, .fnode span { white-space: nowrap; }
    .frow .wire::before { animation-delay: .3s; }
    .frow:first-child .wire::before { animation-delay: 0s; }
    /* the row needs ~840px to hold its labels unwrapped; below that it
       becomes a vertical pipeline rather than a squeezed one */
    @media (max-width: 820px) {
      .flowmap { flex-direction: column; align-items: stretch; }
      /* a node as wide as the rail held its label at one edge while the wire
         ran down the centre, so the two never met */
      .flowmap .fnode { width: min(100%, 320px); align-self: center; }
      .frow { flex-direction: column; align-items: stretch; }
      .fcol.sources { display: flex; flex-direction: column; }
      .fnode b, .fnode span { white-space: normal; }
      /* a 20px dash in a 22px run showed one mark and read as a stray dot —
         the vertical wire needs a tighter pattern to read as a line at all */
      .wire { min-height: 28px; height: 28px; width: 2px; align-self: center; opacity: .7; }
      .wire::before { inset: -9px 0 0 0;
        background-image: linear-gradient(180deg, var(--tint) 0 50%, transparent 50% 100%);
        background-size: 2px 9px; background-repeat: repeat-y; }
      html.motion .wire::before { animation: flowv .9s linear infinite; }
      @keyframes flowv { to { transform: translateY(9px); } }
    }


    /* ═══════ motion ═══════
       Movement here has one job: to say "this arrived" and "this responds".
       Everything is opacity and transform only — no layout property is
       animated, so nothing reflows mid-frame — and every one of these rules is
       switched off wholesale under prefers-reduced-motion at the end of the
       sheet. Sections reveal as a whole block, never card by card: staggering
       siblings would leave cards of one row on different baselines while the
       animation ran. (The vertical flow timeline is the one deliberate
       exception — its items stagger top-to-bottom, which cannot break a
       shared baseline.) */
    @keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
    @keyframes draw { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
    @keyframes sheen { from { background-position: 100% 0; } to { background-position: -100% 0; } }
    @keyframes pulse { 0%, 100% { opacity: .35; transform: scale(1); } 50% { opacity: 1; transform: scale(1.35); } }

    /* The hidden state is applied only once the script has taken charge of
       revealing it (html.motion). Written the other way round — hidden by
       default, shown by JS — a blocked or failed script leaves the whole page
       blank, and so does any renderer that never scrolls. */
    html.motion [data-reveal] { opacity: 0; transform: translateY(16px); transition: opacity .5s ease, transform .5s cubic-bezier(.2,.7,.3,1); }
    html.motion [data-reveal].in { opacity: 1; transform: none; }

    /* Every drawing on this page animates forever: gears turn, current runs
       down the wires, bars fill, a dot pulses. Measured, that is 80 infinite
       animations on a desktop — and 66 of them were running while scrolled
       out of sight, which is battery and CPU spent on pixels nobody can see,
       and 66 more things competing with the scroll itself.

       They pause when they leave the viewport and resume where they stopped,
       so nothing jumps and nothing looks different while you are looking at
       it. Written in this direction on purpose: the class is added BY the
       script, so a blocked script, a browser without IntersectionObserver, or
       a renderer that never scrolls leaves everything running exactly as
       before — never frozen mid-drawing, which is the failure this page's
       reveal rule already exists to avoid.

       !important is load-bearing, not laziness: every animation on this page is
       declared with the `animation` shorthand, and the shorthand resets
       animation-play-state to running. Those declarations all sit below this
       rule, so without !important the pause is overwritten on every animated
       element and the class does nothing — measured: 65 of 80 kept running. */
    html.motion .offscreen,
    html.motion .offscreen *,
    html.motion .offscreen::before { animation-play-state: paused !important; }

    /* backwards, not both: a fill that outlives the entrance keeps the mark
       on its own compositor layer, and on a 2.625× phone that layer is
       resampled at a fractional offset, which softens the logo's stripes */
    .brand .logo { animation: draw .7s cubic-bezier(.2,.7,.3,1) backwards; }
    .hero .kicker { animation: rise .5s ease both .05s; }
    .hero h1      { animation: rise .5s ease both .14s; }
    .hero .lead   { animation: rise .5s ease both .22s; }
    .hero .claimart{ animation: rise .5s ease both .27s; }
    .hero .actions{ animation: rise .5s ease both .34s; }
    .hero .stats  { animation: rise .5s ease both .4s; }

    /* the flagship row catches the light once on arrival, then stays still */
    .product.lead::after {
      content: ""; position: absolute; inset: 0; border-radius: 12px; pointer-events: none;
      background: linear-gradient(90deg, transparent 40%, rgba(231, 181, 103, .16) 50%, transparent 60%);
      background-size: 250% 100%; animation: sheen 2.4s ease-out 1 .4s;
    }
    /* a live dot on the flagship: the system is running, not a screenshot */
    .live { width: 7px; height: 7px; border-radius: 999px; background: var(--good);
      display: inline-block; animation: pulse 2s ease-in-out infinite; }

    /* Icons that carry their meaning in motion: the gear turns, the AI spark
       breathes, the design pen keeps drawing its stroke. Part-level animation
       can't reach inside a <use> clone, so these are inlined from the same
       drawn set. The global reduced-motion block stops all of them. */
    @keyframes icspin { to { transform: rotate(360deg); } }
    @keyframes icpulse { 0%, 100% { opacity: .35; transform: scale(.75); }
                         50% { opacity: 1; transform: scale(1.1); } }
    @keyframes icdraw { 0% { stroke-dashoffset: 26; } 55%, 72% { stroke-dashoffset: 0; }
                        100% { stroke-dashoffset: -26; } }
    .ic .spin { animation: icspin 9s linear infinite; transform-box: fill-box; transform-origin: center; }
    .ic .spark { animation: icpulse 2.6s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
    .ic .draw { stroke-dasharray: 26; animation: icdraw 3.6s ease-in-out infinite; }

    .card, .channel { transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease; }
    .card:hover { transform: translateY(-3px); border-color: var(--tint);
      box-shadow: 0 8px 24px rgba(231, 181, 103, .18); }   /* raised: the same amber lift as the resting call pill */
    .channel:hover { transform: translateY(-3px); border-color: var(--tint);
      box-shadow: 0 8px 24px rgba(231, 181, 103, .18); }
    .card:hover .tile, .channel:hover .tile { background: var(--tint); }
    .card:hover .tile .ic, .channel:hover .tile .ic { stroke: var(--on-tint); color: var(--on-tint); }
    .tile { transition: background .22s ease; }
    /* every icon answers the pointer, not only the three that animate their own
       parts: those three are inlined so their pieces can move, and a <use> clone
       cannot be reached inside — but the whole mark can still respond */
    .tile .ic { transition: stroke .22s ease, transform .3s cubic-bezier(.2,.7,.3,1); }
    .card:hover .tile .ic, .channel:hover .tile .ic { transform: scale(1.14) rotate(-4deg); }
    .fnode .ic { transition: transform .3s cubic-bezier(.2,.7,.3,1); }
    .fnode:hover .ic { transform: scale(1.15); }
    .btn { transition: transform .18s ease, opacity .18s ease; }
    .btn:hover { transform: translateY(-1px); }
    /* ripple: a pressed primary button answers where it was touched */
    .btn.primary { position: relative; overflow: hidden; }
    .rip { position: absolute; width: 24px; height: 24px; border-radius: 999px;
      background: rgba(7, 10, 14, .28); transform: scale(0); pointer-events: none;
      animation: rip .55s ease-out forwards; }
    @keyframes rip { to { transform: scale(9); opacity: 0; } }

    /* ═══════ hero: full-height, over the logo's code rain ═══════
       The art layer is the banner's rain: Arabic letters, digits and code
       marks in amber, drawn by the script into columns (without the script
       the layer stays empty and the hero reads the same). It fades out behind
       the type, so no line of text ever sits on a glyph, and the whole field
       drifts down on ONE compositor animation, paused off screen and stopped
       under reduced motion like everything else here. */
    .hero { position: relative; text-align: center; overflow: hidden;
      padding: 32px 0 24px; min-height: clamp(420px, calc(100vh - 320px), 680px);
      display: flex; flex-direction: column; justify-content: center; }
    /* the rain keeps to the margins: the text column (the counters' row is
       the widest line, 23% to 77% of the hero) is never under a glyph */
    .heroart { position: absolute; inset: 0; pointer-events: none; overflow: hidden;
      -webkit-mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0) 20%, rgba(0, 0, 0, 0) 80%, #000 100%);
      mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0) 20%, rgba(0, 0, 0, 0) 80%, #000 100%); }
    .rain { position: absolute; inset-inline: 0; top: 0; }
    html.motion .rain { animation: rain 60s linear infinite; }
    @keyframes rain { from { transform: translateY(-50%); } to { transform: translateY(0); } }
    .rain i { position: absolute; display: block; width: 1em; text-align: center; font-style: normal;
      font-family: var(--mono); line-height: 1; color: var(--tint); }
    .rain i.hd { color: var(--on-bar); text-shadow: 0 0 10px rgba(231, 181, 103, .9); }
    .hero > * { position: relative; }
    /* .hero > * matched the art layer too and, coming later at the same
       specificity, made it a 0px-tall relative box */
    .hero > .heroart { position: absolute; }
    /* the kicker is the logo's terminal line: the prompt, what we are, the cursor */
    .hero .kicker {
      display: inline-flex; align-items: center; gap: 8px; background: var(--panel-2); border: 1px solid var(--border);
      color: var(--on-bar); border-radius: 999px; padding: 6px 16px; font-size: 13px; font-weight: 700;
      align-self: center;
    }
    .hero .kicker .pr { font-family: var(--mono); color: var(--tint); direction: ltr; unicode-bidi: isolate; }
    /* the logo's cursor: .47em wide, one em tall, amber at .85 (16 x 34 on its 34px tag) */
    .hero .kicker .cur { display: inline-block; width: .47em; height: 1em; background: var(--tint); opacity: .85; }
    html.motion .hero .kicker .cur { animation: blink 1.1s steps(1, end) infinite; }
    @keyframes blink { 0%, 49% { opacity: .85; } 50%, 100% { opacity: 0; } }
    .hero h1 { font-size: clamp(28px, 4.4vw, 44px); margin: 8px 0 4px; line-height: 1.4; text-wrap: balance; }
    .hero h1 .en { color: var(--tint); direction: ltr; display: inline-block; unicode-bidi: isolate;
      font-family: var(--display); font-weight: 700; letter-spacing: .02em; font-size: .62em; }
    .hero .lead { color: var(--muted); max-width: 620px; margin: 0 auto 16px; font-size: 16px; line-height: 1.8; }
    /* ═══════ the hero claim, drawn ═══════
       One screen on the reading start, the parts that run the work on the
       other end, and current flowing between them. Two stroke weights only,
       the same amber ink as everything else, and nothing here is hidden at
       rest — the animation adds a travelling pulse and takes nothing away. */
    .claimart { margin: 0 auto 16px; max-width: 300px; }
    .claimart svg { width: 100%; height: auto; display: block; overflow: visible; }
    /* Same reasoning as the card drawings: --border is a hairline, and the
       frame, the modules and the wires were nearly not there. --border-input
       is the solved 3:1 value; the boxes take the card's own fill. */
    .claimart .site rect, .claimart .mods rect { fill: var(--panel); stroke: var(--border-input); stroke-width: 1.4; }
    .claimart .site path, .claimart .site circle { fill: var(--border-input); stroke: none; }
    .claimart .site path { stroke: var(--border-input); stroke-width: 1.4; fill: none; stroke-linecap: round; }
    .claimart .glyph { fill: none; stroke: var(--tint); stroke-width: 1.4;
      stroke-linecap: round; stroke-linejoin: round; }
    .claimart .glyph ellipse { fill: none; }
    .claimart .wires path { fill: none; stroke: var(--border-input); stroke-width: 1.4; }
    .claimart .hub { fill: var(--tint); }
    /* the current: one short dash per wire, crossing it from the site outwards.
       999 as the gap keeps a single dash on the path whatever its length. */
    .claimart .flow path { fill: none; stroke: var(--tint); stroke-width: 2.2;
      stroke-linecap: round; stroke-dasharray: 7 999; stroke-dashoffset: 60; }
    html.motion .claimart .flow path { animation: current 2.6s linear infinite; }
    html.motion .claimart .flow path:nth-child(2) { animation-delay: .5s; }
    html.motion .claimart .flow path:nth-child(3) { animation-delay: .68s; }
    html.motion .claimart .flow path:nth-child(4) { animation-delay: .86s; }
    @keyframes current { from { stroke-dashoffset: 60; } to { stroke-dashoffset: -60; } }
    html.motion .claimart .mods rect { animation: modon 2.6s ease-in-out infinite; }
    html.motion .claimart .mods rect:nth-child(2) { animation-delay: .18s; }
    html.motion .claimart .mods rect:nth-child(3) { animation-delay: .36s; }
    @keyframes modon {
      0%, 26%, 100% { stroke: var(--border-input); }
      34%, 52%      { stroke: var(--tint); }
    }

    .hero .actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
    .hero .actions .btn { will-change: transform; }

    /* real numbers only: units, checks, dependencies, offline — all verifiable */
    .stats { display: flex; justify-content: center; gap: 32px; flex-wrap: wrap; margin-top: 24px; }
    .stat { display: flex; flex-direction: column; gap: 4px; min-width: 96px; }
    .stat b.num { font-family: var(--display); font-size: 26px; font-weight: 700; color: var(--tint);
      direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums; }
    .stat span { color: var(--muted); font-size: 13px; }
    .scrollcue { position: absolute; bottom: 8px; inset-inline-start: 50%; transform: translateX(50%);
      color: var(--muted); display: none; }
    html.motion .scrollcue { display: block; animation: cue 1.8s ease-in-out infinite; }
    @keyframes cue { 0%, 100% { transform: translate(50%, 0); opacity: .5; }
                     50% { transform: translate(50%, 8px); opacity: 1; } }
    /* 24px on both axes: the cue measured 22 wide, the only target on the
       site under the WCAG 2.2 floor */
    .scrollcue { padding: 4px; }
    .scrollcue .ic { transform: rotate(-90deg); width: 24px; height: 24px; display: block; }


    /* Arabic in Cairo needs line-height >= 1.35 at display sizes, or a damma
       collides with the line above. Measured: 18 headings sat at 1.2 — the
       browser default — including a 52px h1 that wraps to two lines. */
    h1, h2, h3, .num, h2.section, .product h3, .card h3 {
      line-height: 1.4;
    }
    h2.section { font-size: 20px; margin: 32px 0 4px; }
    h2.section::after {
      content: ""; display: block; width: 96px; height: 2px; border-radius: 2px;
      margin-top: 6px; background: linear-gradient(270deg, rgba(231, 181, 103, .55), rgba(231, 181, 103, 0));
    }
    .sub { color: var(--muted); margin: 0 0 12px; line-height: 1.75; }

    .card {
      background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px;
      display: flex; flex-direction: column; gap: 6px;
    }
    /* One drawn icon family instead of emoji: emoji are a different typeface on
       every platform (and a different colour), so the page looked different on
       every device. These are stroked paths that inherit currentColor, weigh a
       few hundred bytes in total, and need no font to load. */
    .ic { width: 20px; height: 20px; flex: none; stroke: var(--tint); color: var(--tint); fill: none;
      stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: -.22em; }
    .ic.sm { width: 16px; height: 16px; stroke-width: 2; }
    .btn.primary .ic { stroke: var(--on-tint); color: var(--on-tint); }
    .card h3 { margin: 0; font-size: 16px; display: flex; align-items: center; gap: 8px; }
    .card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.65; }
    /* The icon carries the card now that the copy is one line: it sits in its
       own tile at the head of the card, big enough to read at a glance. */
    .tile { width: 38px; height: 38px; border-radius: 12px; background: var(--panel-2);
      display: grid; place-items: center; flex: none; }
    .card .tile .ic { width: 21px; height: 21px; }
    .card .chip { margin-top: auto;  line-height: var(--lh-ui); }
    .chip {
      font-size: 12px; font-weight: 700; border-radius: 999px; padding: 4px 8px;
      display: inline-flex; align-items: center; gap: 4px;
      background: var(--panel-2); border: 1px solid var(--border); color: var(--muted);
      align-self: flex-start;
    }
    .chip.on { color: var(--tint); border-color: var(--tint); }
    /* the five things each service actually covers, as quiet mini-chips */
    ul.feats { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
    ul.feats li { font-size: 12px; font-weight: 600; color: var(--muted); background: var(--panel-2);
      border: 1px solid var(--border); border-radius: 999px; padding: 4px 8px;  line-height: var(--lh-ui); }
    .card:hover ul.feats li { border-color: var(--tint); }

    /* mini feature cards on the edge rail: icon + claim, nothing else */



    /* The flagship product gets a wide card of its own — النوخذة is a system we
       built and run, not one service tile among six. This, the numbered steps
       and the contact bar are the first version's components, kept. */
    .product {
      background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
      padding: 16px; display: grid; grid-template-columns: 1fr auto; gap: 16px;
      align-items: center; margin-top: 12px; position: relative; overflow: hidden;
    }
    .product.lead { border-color: var(--tint); 
      border-inline-start-width: 0; padding-inline-start: 20px;
      transition: transform .3s ease, box-shadow .3s ease; will-change: transform; }
    .product.lead::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 4px;
      background: repeating-linear-gradient(180deg, var(--tint) 0 5px, var(--stripe) 5px 7px); }
    .product h3 { margin: 0 0 6px; font-size: 20px; display: flex; align-items: center; gap: 8px; }
    .product p { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.75; }
    .product .go { align-self: center; white-space: nowrap; }
    /* the arrow is the drawn chevron, not a typed ← that each device set in its own
       font; it takes the button's ink, the ground's dark on the amber fill */
    .btn.go { display: inline-flex; align-items: center; gap: 8px; }
    .btn.go .ic { width: 18px; height: 18px; stroke: currentColor; color: currentColor; }
    @media (max-width: 620px) {
      .product { grid-template-columns: 1fr; }
      .product .go { justify-self: stretch; justify-content: center; }   /* inline-flex: text-align centres nothing */
    }

    /* ═══════ the automation flow: request to running system, one line ═══════
       A vertical timeline whose spine draws itself as the section arrives and
       whose stations light in order — the one deliberate stagger on the page. */
    ol.flow { list-style: none; counter-reset: f; margin: 16px 0 0; padding: 0; position: relative;
      max-width: 560px; }
    ol.flow::before { content: ""; position: absolute; top: 8px; bottom: 8px;
      inset-inline-start: 15px; width: 2px; background: var(--border-input);
      transform-origin: top; }
    html.motion [data-reveal] ol.flow::before { transform: scaleY(0); transition: transform 1.6s cubic-bezier(.4,0,.2,1) .1s; }
    html.motion [data-reveal].in ol.flow::before { transform: scaleY(1); }
    ol.flow li { counter-increment: f; position: relative; padding: 0 44px 20px 0; }
    ol.flow li:last-child { padding-bottom: 0; }
    ol.flow li::before { content: counter(f); position: absolute; inset-inline-start: 0; top: 0;
      width: 32px; height: 32px; border-radius: 999px; display: grid; place-items: center;
      background: var(--panel); border: 2px solid var(--tint); color: var(--tint);
      font-family: var(--mono); font-weight: 700; font-size: 13px; }
    ol.flow li.now::before { background: var(--tint); color: var(--on-tint); }
    ol.flow li b { display: block; font-size: 16px; margin: 4px 0 4px; }
    ol.flow li span { color: var(--muted); font-size: 13px; line-height: 1.65; }
    html.motion [data-reveal] ol.flow li { opacity: 0; transform: translateY(10px);
      transition: opacity .45s ease, transform .45s ease; }
    html.motion [data-reveal].in ol.flow li { opacity: 1; transform: none; }

    /* ═══════ and the same flow, laid across the page on a wide screen ═══════
       Measured at 1440: the spine is capped at 560px and each station's own
       content is about 150px of it, so seven two-word labels ran down the far
       right of the section and left roughly five sixths of the page empty —
       a column of air taller than the viewport. A process reads across, not
       down, once there is room for it to.

       The connector is drawn per station, from this circle's centre to the
       next one's, rather than as one line inset by half a column: the inset
       version needs the step COUNT baked into a calc(), and would quietly
       stop meeting the circles the day an eighth step is added. Each segment
       measures itself, so the count can change and nothing has to know. */
    @media (min-width: 900px) {
      ol.flow { max-width: none; display: flex; align-items: flex-start; }
      /* the single sweeping spine is a vertical idea; the segments replace it */
      ol.flow::before { display: none; }
      ol.flow li { flex: 1 1 0; min-width: 0; padding: 0 8px;
        display: flex; flex-direction: column; align-items: center; text-align: center; }
      ol.flow li::before { position: static; margin-bottom: 8px; }
      ol.flow li::after { content: ""; position: absolute; top: 15px; height: 2px;
        background: var(--border-input);
        inset-inline-start: calc(50% + 16px); inset-inline-end: calc(-50% + 16px); }
      ol.flow li:last-child::after { content: none; }
      ol.flow li b { margin: 0; }
      html.motion [data-reveal] ol.flow li::after { transform: scaleX(0);
        transform-origin: right; transition: transform .5s ease; }
      html.motion [data-reveal].in ol.flow li::after { transform: scaleX(1); }
    }
    ol.flow li:nth-child(2) { transition-delay: .16s; }
    ol.flow li:nth-child(3) { transition-delay: .32s; }
    ol.flow li:nth-child(4) { transition-delay: .48s; }
    ol.flow li:nth-child(5) { transition-delay: .64s; }
    ol.flow li:nth-child(6) { transition-delay: .8s; }
    ol.flow li:nth-child(7) { transition-delay: .96s; }

    /* how-we-work: eight numbered discs joined by a rule — a timeline that
       slides horizontally on wide screens (eight will not fit on any desktop,
       so it is driven by the same rail arrows and dots as the card sections)
       and stacks vertically on a phone */










    /* Contact channels, as on the live site — the same three, laid as one bar
       of pills: icon tile, label, value, reading start-aligned like a row.
       The bar wraps rather than squeezing: at tablet widths three pills in one
       row truncated the email address to an ellipsis, which is worse than a
       second row — the value IS the content here. */
    .channels { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }
    .channel { flex: 1 1 240px; min-width: 0; background: var(--panel); border: 1px solid var(--border);
      border-radius: 12px; padding: 12px 16px; display: flex; align-items: center; gap: 12px;
      color: var(--text); }
    .channel:hover { border-color: var(--tint); }
    .channel .tile { width: 40px; height: 40px; border-radius: 12px; }
    .channel .tile .ic { width: 22px; height: 22px; }
    .channel .t { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
    .channel b { font-size: 16px; }
    .channel span.v { color: var(--muted); font-size: 13px; direction: ltr; unicode-bidi: isolate;
      text-align: start; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ═══════ the project form: floating labels, honest validation ═══════
       There is no server behind this page (and the CSP forbids form posts) —
       a valid submission composes the message and hands it to WhatsApp, the
       same channel the bar below offers. JS-gated: without the script the
       channels are the contact surface, not a dead form. */
    .qwrap { display: none; }
    html.js .qwrap { display: block; }
    .qform { background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
      padding: 20px; margin-top: 12px; display: grid; gap: 16px;
      grid-template-columns: 1fr 1fr; }
    .qform .field { position: relative; }
    .qform .field.wide { grid-column: 1 / -1; }
    .qform input, .qform select, .qform textarea {
      width: 100%; font-family: var(--sans); font-size: 16px; color: var(--text);
      background: var(--panel-2); border: 1px solid var(--border-input); border-radius: 8px;
      padding: 20px 12px 6px; transition: border-color .2s ease; }
    .qform textarea { min-height: 96px; resize: vertical; }
    .qform input:focus, .qform select:focus, .qform textarea:focus { border-color: var(--tint); }
    .qform :is(input, select, textarea):focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }   /* the ring the other pages draw */
    .qform label { position: absolute; inset-inline-start: 12px; top: 13px; color: var(--muted);
      font-size: 14px; pointer-events: none; transition: top .18s ease, font-size .18s ease; }
    .qform input:focus + label, .qform input:not(:placeholder-shown) + label,
    .qform textarea:focus + label, .qform textarea:not(:placeholder-shown) + label,
    .qform select + label { top: 4px; font-size: 12px; color: var(--tint); }
    .qform [aria-invalid="true"] { border-color: var(--danger); }
    .qform .hint { display: none; color: var(--danger); font-size: 12px; margin-top: 4px; }
    .qform [aria-invalid="true"] ~ .hint { display: block; }
    .qform .send { grid-column: 1 / -1; justify-self: start; display: inline-flex;
      align-items: center; gap: 8px; }
    .qform .send.sent { background: var(--good); border-color: var(--good); color: var(--on-tint); }
    .qform .send .ok { display: none; }
    .qform .send.sent .ok { display: inline; stroke-dasharray: 20; animation: okdraw .5s ease-out forwards; }
    .qform .send.sent .lbl { display: none; }
    @keyframes okdraw { from { stroke-dashoffset: 20; } to { stroke-dashoffset: 0; } }

    /* ═══════ what we build, drawn instead of written ═══════
       Four scenes carry these cards: gears that turn, a pen that draws, two
       devices whose screens fill, and code that types itself. The label under
       each is two words — the picture is the description, which is the whole
       point of drawing them. Every part is a stroked path in brand ink, so
       they weigh nothing and need no image request. */
    .scene { display: block; width: 100%; height: 136px; border-radius: 12px;
      background: var(--panel-2); stroke: var(--tint); color: var(--tint); fill: none;
      stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
    /* The structure of every drawing (the window frame, the chart axis, the
       delivery route, the tab bar) is drawn in --border-input, the value
       solved for this site's 3:1 boundary rule, not in --border, a hairline
       below even the 2:1 set for chart marks. The amber subject stays well
       above it, so the hierarchy holds: subject, then setting. */
    .scene .soft { stroke: var(--border-input); }
    /* the band's facts are drawn small: a third of a row each, above one line
       of text, so the drawing explains and the sentence only names */
    .scene.sm { height: 60px; background: none; }
    /* the flagship row is wide, so its drawing is too — and it carries the
       unit names inside itself, which is why the row needs no chip list */
    .scene.wide { height: 150px; margin-top: 12px; max-width: 620px; }
    .scene .tab { font-size: 11px; }
    .scene .tab.on { fill: var(--tint); }
    .scene .ok { stroke: var(--good); }
    .scene text { fill: var(--muted); stroke: none; font-family: var(--sans);
      font-size: 11px; font-weight: 700; }




    @keyframes dash  { to { stroke-dashoffset: -28; } }
    @keyframes drawIn { 0% { stroke-dashoffset: 120; } 60%, 100% { stroke-dashoffset: 0; } }
    @keyframes fillBar { 0%, 8% { transform: scaleX(.06); } 38%, 100% { transform: scaleX(1); } }
    html.motion .scene .wire2 { stroke-dasharray: 7 7; animation: dash 1.1s linear infinite; }
    html.motion .scene .pen { stroke-dasharray: 120; animation: drawIn 4s ease-in-out infinite; }
    html.motion .scene .bar { transform-box: fill-box; transform-origin: right center;
      animation: fillBar 3.2s ease-in-out infinite; }
    html.motion .scene .bar:nth-of-type(2) { animation-delay: .25s; }
    html.motion .scene .bar:nth-of-type(3) { animation-delay: .5s; }

    /* ═══════ each service explained by a drawing ═══════
       Six scenes, one per service card, in the same idiom as the four above:
       a page whose content fills, a device that installs, blocks that fit
       together, a model wired to its sources, a pen over an artboard, and a
       cloud feeding its machines. Every scene is complete at rest — motion
       only sets already-drawn parts moving — so a reduced-motion visitor,
       a print, and a screenshot all read the same explanation. */
    /* the offer cards keep their taller 136px scene — this is the service rail */
    .card > .scene { height: 108px; }
    @keyframes fitIn   { 0%, 10% { transform: translate(15px, -11px); opacity: .3; }
                         45%, 100% { transform: none; opacity: 1; } }
    @keyframes pulseIn { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
    @keyframes rise    { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
    html.motion .scene .fit { transform-box: fill-box; animation: fitIn 4s ease-in-out infinite; }
    html.motion .scene .pulse { animation: pulseIn 2.4s ease-in-out infinite; }
    html.motion .scene .pulse.d1 { animation-delay: .5s; }
    html.motion .scene .pulse.d2 { animation-delay: 1s; }
    html.motion .scene .rise { transform-box: fill-box; animation: rise 3.4s ease-in-out infinite; }

    /* ═══════ البحار: the voice assistant, one tap from anywhere ═══════
       النوخذة is the captain; البحار is the sailor who answers. The control is
       a sticky pill that opens the ElevenLabs agent in a new tab — not an
       embedded widget: the site's CSP is default-src 'none' with no external
       origins, and opening it for a third-party widget would undo the whole
       security posture. It ships hidden and is revealed by the script only
       once an agent URL is configured, so a dead button can never reach a
       visitor. */
    .callfab {
      /* inline-start (the right, in RTL): the rails put their arrows at the
         inline-end, and a fixed pill there would sit on top of a real control */
      position: fixed; inset-block-end: 20px; inset-inline-start: 20px; z-index: 60;
      display: inline-flex; align-items: center; gap: 8px;
      background: var(--tint); color: var(--on-tint); border-radius: 999px;
      padding: 8px 16px 8px 12px; min-height: 48px;
      box-shadow: 0 8px 24px rgba(231, 181, 103, .18);
      transition: transform .22s cubic-bezier(.2,.7,.3,1), box-shadow .22s ease;
    }
    .callfab:hover { transform: translateY(-3px); box-shadow: 0 12px 30px rgba(231, 181, 103, .26); }
    /* it steps aside over the contact bar and the footer: down there the
       channels are on screen anyway, and a fixed pill would sit on one of
       them — measured, it landed squarely on واتساب */
    .callfab.away { opacity: 0; transform: translateY(16px); pointer-events: none; }
    .callfab:focus-visible { outline: 2px solid var(--tint); outline-offset: 3px; }
    /* The pill is deliberately a size DOWN from the card titles. It floats
       over the page, so every pixel of it is a pixel that can land on a
       heading or a button — and the dodge that moves it out of the way is
       measured: at 16/12 it grew to 203x67 and started covering content at
       two more scroll positions, dropping the share of the page it is
       actually visible on. Smaller pill, more of it seen. */
    .callfab .ic { stroke: var(--on-tint); color: var(--on-tint); width: 22px; height: 22px; }
    .callfab b { font-size: 14px; font-weight: 800; line-height: 1.25; display: block; }
    .callfab span { font-size: 12px; color: var(--on-tint); display: block; }
    /* a live ring: the assistant is answering now, not a form that waits */
    .callfab .halo { position: absolute; inset: 0; border-radius: 999px;
      border: 2px solid var(--tint); opacity: 0; pointer-events: none; }
    html.motion .callfab .halo { animation: halo 2.6s ease-out infinite; }
    @keyframes halo {
      0%   { opacity: .7; transform: scale(1); }
      70%  { opacity: 0;  transform: scale(1.18); }
      100% { opacity: 0;  transform: scale(1.18); }
    }
    @media (max-width: 640px) {
      /* Measured on a 390×844 phone: one card filled a third of the fold,
         and the flagship row's drawing took 150 of its 302px. The drawings
         come down; nothing they explain is lost, because each still sits
         above the line of text that names it. */
      .card > .scene { height: 88px; }
      .scene.wide { height: 110px; }
      /* Measured: the labelled pill is 188px wide and covered the first
         section heading outright. On a 390px screen there is no margin to
         put a wide pill in, so it becomes a disc — the label lives in
         aria-label, where a screen reader still reads it. */
      /* and it moves to the inline-end corner on a phone. inline-start was
         chosen so it would not sit on the rails' arrows — but the arrows are
         hidden at this width, the thumb scrolls instead, so the corner is
         free. In RTL that puts the disc where a line ENDS rather than where
         it starts: measured, at inline-start it was covering the first
         characters of every heading it passed. */
      .callfab { inset-block-end: 14px; inset-inline-start: auto; inset-inline-end: 14px;
        padding: 0; width: 48px; height: 48px; min-height: 48px;
        justify-content: center; gap: 0; }
      .callfab .fabtext { display: none; }
      .callfab .ic { width: 24px; height: 24px; }
    }

    /* ═══════ footer: the company, the map of the site, the channels ═══════
       A base one step off the page (the card's own surface), opened by the
       logo's fading amber rule so it reads as the foot of the masthead's
       column. Four columns (who we are, the company, what we do, the system)
       with the real channels written out, not only as icon buttons. */
    footer { background: var(--panel); border-top: 1px solid var(--border); margin-top: 32px;
      color: var(--muted); font-size: 13px; line-height: 1.9; }
    footer::before { content: ""; display: block; height: 2px;
      background: linear-gradient(90deg, rgba(231, 181, 103, 0), rgba(231, 181, 103, .55), rgba(231, 181, 103, 0)); }
    .fcols { max-width: 1060px; margin: 0 auto; padding: 32px 20px 24px;
      display: flex; flex-wrap: wrap; gap: 32px 24px; }
    .fcols > div { flex: 1 1 180px; min-width: 0; }
    .fcols .fbrand { flex: 1 1 260px; }
    .fcols b.fh { display: block; color: var(--text); font-size: 14px; margin-bottom: 8px; }
    /* a link that answers the pointer: it steps toward the RTL start */
    .fcols nav a { display: block; color: var(--muted); padding: 4px 0;
      transition: color .18s ease, transform .18s ease; }
    .fcols nav a:hover { color: var(--tint); transform: translateX(-4px); }
    /* THE 44px RULE IS ABOUT FINGERS, so it is asked of fingers. Measured, the
       footer's twenty-one links stood 32px tall and the three contact lines
       36px — over the 24px WCAG floor, under this site's own ~44px intent.
       Padding them to 44 everywhere would add a quarter of a screen to a
       footer that a mouse hits perfectly well at 32, so the height is spent
       where it buys something: a coarse pointer. */
    @media (pointer: coarse) {
      .fcols nav a { padding: 10px 0; }
      .fcontact a { padding: 10px 0; min-height: 44px; }
    }
    /* the AC monogram (favicon.svg, on its own rounded tile) beside the name
       set in the logo's own face: ALMUHALLAB in its amber, CODE in its white */
    .fbrand .fmark { display: flex; align-items: center; gap: 12px; }
    .fbrand .logo { display: block; width: 44px; height: 44px; flex: none; }
    .fbrand .name { display: flex; flex-direction: column; line-height: 1.35; }
    .fbrand .name .en { font-family: var(--display); font-weight: 700; font-size: 18px;
      letter-spacing: .06em; color: var(--text); direction: ltr; unicode-bidi: isolate; text-align: right; }
    .fbrand .name .en b { color: var(--tint); font-weight: 700; }
    .fbrand .name small { font-size: 12px; font-weight: 600; color: var(--muted); }
    .fbrand p { margin: 12px 0 0; max-width: 30ch; }

    /* the channels, written out — an icon button alone hides the number */
    .fcontact { display: flex; flex-direction: column; align-items: flex-start;
      gap: 4px; margin-top: 12px; }
    .fcontact a { display: inline-flex; align-items: center; gap: 8px; color: var(--muted);
      padding: 6px 0; min-height: 32px; transition: color .18s ease; }
    .fcontact a:hover { color: var(--tint); }
    .fcontact .ic { width: 16px; height: 16px; stroke: var(--muted); color: var(--muted); stroke-width: 2;
      transition: stroke .18s ease, color .18s ease; }
    .fcontact a:hover .ic { stroke: var(--tint); color: var(--tint); }
    .fcontact .v { direction: ltr; unicode-bidi: isolate; }


    .base { border-top: 1px solid var(--border); padding: 16px 20px;
      display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 16px; }
    .base .made { display: inline-flex; align-items: center; gap: 6px; }
    .base .made .mk { display: block; width: 18px; height: 18px; }   /* the monogram, small */
    .base .top { display: inline-flex; align-items: center; gap: 6px; color: var(--tint);
      font-weight: 700; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border-input);
      background: var(--panel); transition: border-color .18s ease, transform .18s ease; }
    .base .top:hover { border-color: var(--tint); transform: translateY(-2px); }
    .base .top .ic { width: 14px; height: 14px; transform: rotate(90deg); stroke-width: 2.3; }

    /* The sticky bar covers whatever an in-page link jumps to, so every anchor
       target keeps its own headroom. Without this, "خدماتنا" landed the heading
       underneath the masthead. A jump from the top compacts the bar on the way
       and the page rises by the difference, so the headroom clears the TOP bar
       (158px here), not the compact one (106): 158 + 24, rounded up to 184 */
    :target, section[id], h2.section[id] { scroll-margin-top: 184px; }
    html { scroll-behavior: smooth; }

    /* a phone on its side is short, not narrow: the desktop bar would take
       two thirds of an 844×390 screen. It takes the phone's own sizes and
       shrinks further once scrolled, as it does at 640px */
    @media (max-height: 500px) {
      header { padding: 8px 20px; }
      .brand .logo { width: 200px; --glow: 6px; }
      :target, section[id], h2.section[id] { scroll-margin-top: 158px; }   /* the 134px top bar + 24 */
    }
    /* below 360px the four links measured 324px in 296: النوخذة wrapped to a
       second row and the bar took 45% of the screen. With the 16px phone gutter
       the row holds 288px: 8px sides keep it to one row, each still 44px tall */
    @media (max-width: 359px) { header nav.site a { padding: 12px 8px; } }   /* outranks the 640px block below */

    /* ═══════ mobile ═══════ */
    @media (max-width: 640px) {
      header { padding: 8px 16px; }   /* the side gutter is 16 on every phone */
      .brand .logo { width: 220px; --glow: 6px; }
      nav.site a, .btn { padding: 12px 16px; min-height: 44px; display: inline-flex; align-items: center; }
      main { padding: 16px 16px 40px; }
      .card { padding: 16px; }
      .hero { padding: 16px 0 24px; min-height: 0; }
      h2.section { margin-top: 24px; }
      .hero .lead { font-size: 16px; }
      /* The hero has no min-height on a phone, so everything in it pushes the
         scroll cue down. Measured: at 236px the drawing put the cue 28px below
         a 390×844 fold, which is the one thing the cue must never be. It is
         sized against the viewport instead, and its margin comes off. */
      .claimart { max-width: min(236px, 44vw); margin-bottom: 8px; }
      .hero .actions .btn { flex: 1 1 100%; justify-content: center; }
      .stats { gap: 16px; }
      .stat { min-width: 40%; }
      /* a phone slides by thumb — the arrows would only crowd the heading */
      .railnav { display: none !important; }
      .rowhead { align-items: stretch; }





      .channels { flex-direction: column; }
      /* in a column the 240px flex-basis meant as a width becomes each pill's
         height: three 240px pills holding 58px of content each */
      .channel { flex: none; }
      .fcols { gap: 24px 20px; padding: 24px 16px 20px; }
      /* the company keeps a full row; الشركة and الخدمات share one — their
         longest label is 125px, and a full row each left them 17% filled */
      .fcols .fbrand { flex: 1 1 100%; }
      .fcols > div:not(.fbrand) { flex: 1 1 40%; }
      .fcontact a { min-height: 44px; }
      .base { flex-direction: column; gap: 12px; text-align: center; }
      :target, section[id], h2.section[id] { scroll-margin-top: 162px; }   /* the 138px top bar + 24 */
      .qform { grid-template-columns: 1fr; padding: 16px; }
      /* a phone's text runs to within a few pixels of the edge, so there is
         no margin for the rain to fall in: measured at 390 and 320, every
         visible column crossed a line of the heading. Phones go without it;
         the masthead's logo and terminal line carry the look there */
      .heroart { display: none; }
    }
    /* one fold for every short or narrow bar — a phone, or a phone on its
       side — so the two can never drift apart */
    @media (max-width: 640px), (max-height: 500px) {
      /* scrolled, the logo steps down to a size that leaves the nav its row,
         and the collapsed terminal line gives back its height entirely */
      html.scrolled .brand .logo { width: 140px; --glow: 4px; }
      html.scrolled .brand .term { display: none; }
    }

    /* A visitor who asks the OS for less motion gets none of it: no entrance,
       no reveal, no sheen, no pulse — and, critically, no element left at
       opacity 0 waiting for an observer that will never move it. */
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation: none !important;
        transition: none !important;
      }
      html { scroll-behavior: auto; }
      html.motion [data-reveal] { opacity: 1 !important; transform: none !important; }
      html.motion [data-reveal] ol.flow::before { transform: none !important; }
      html.motion [data-reveal] ol.flow li { opacity: 1 !important; transform: none !important; }
    }
