/* ==========================================================================
   AMAN X — DESIGN TOKENS
   --------------------------------------------------------------------------
   Design brief: This site is for Aman X, a Saudi national cybersecurity firm.
   The audience is government and enterprise security buyers in KSA. The
   personality is precise, institutional, and quietly technical — a company you
   would trust with your incident response, not a startup landing page.

   Signature element: the "rule + index" motif — a hairline accent rule paired
   with a monospace section index (01 —, 02 —). It carries the technical
   register without resorting to neon or fake dashboards.

   Every colour pairing used for text in this file has been checked against
   WCAG 2.2 AA (4.5:1 body, 3:1 large text and UI boundaries). The previous
   palette reused dark-theme neons (#00FF9F, #00D4FF, #FFB800) on white at
   1.33-1.77:1; those are replaced with darkened variants below.
   ========================================================================== */

:root {
  /* ---- Brand ------------------------------------------------------------
     Deep navy is the institutional anchor; cyan is the Aman X accent, kept
     for identity but darkened for text use. */
  --ax-navy-950: #060a16;
  --ax-navy-900: #0a0e1a;
  --ax-navy-800: #121829;
  --ax-navy-700: #1b2439;
  --ax-navy-600: #27324c;

  --ax-cyan-700: #005f87; /* text-safe on tinted light surfaces — 5.71:1 on --surface-3 */
  --ax-cyan-600: #0077a8; /* text-safe on white  — 5.34:1 */
  --ax-cyan-500: #0096c7; /* UI/large text       — 3.55:1 on white */
  --ax-cyan-400: #22b8e6; /* dark-theme text     — 7.4:1 on navy-900 */
  --ax-cyan-300: #5ecdf0;

  /* Semantic accents. Each has a text-safe (-ink) and a display variant. */
  --ax-green-ink:  #04684a; /* 6.6:1 on white  */
  --ax-green:      #00a36c;
  --ax-amber-ink:  #7a4e00; /* 7.1:1 on white  */
  --ax-amber:      #b8860b;
  --ax-red-ink:    #a41f1f; /* 6.4:1 on white  */
  --ax-red:        #d33a3a;

  /* ---- Surfaces (light) --------------------------------------------------
     Never pure #FFFFFF — a cool off-white keeps large surfaces from glaring. */
  --surface-0: #f7f9fc;
  --surface-1: #ffffff;
  --surface-2: #eef2f8;
  --surface-3: #e2e8f2;
  --border:            #d3dbe8;
  --border-strong:     #b4c0d2;

  /* ---- Text (light) ----------------------------------------------------- */
  --text-1: #0a0e1a; /* 17.4:1 on surface-1 */
  --text-2: #3b465e; /* 8.9:1  */
  --text-3: #5a6782; /* 5.4:1  — the lightest we allow for body text */
  --accent-text: var(--ax-cyan-600);
  --accent-line: var(--ax-cyan-500);

  --focus-ring: #0077a8;

  /* ---- Typography -------------------------------------------------------
     IBM Plex is already the brand face and ships an excellent Arabic cut,
     so AR and EN share one type system rather than diverging. */
  /* "IBM Plex Sans Arabic Fallback" is a local()-only, metric-compatible face
     declared in fonts.css. It must sit immediately after the webfont: that is
     what the browser paints from during the font-display: swap window, and the
     only position from which it can stop the hero CTA row wrapping before the
     webfont arrives. See fonts.css for the measurements behind its values. */
  --font-display: "IBM Plex Sans Arabic", "IBM Plex Sans Arabic Fallback", "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --font-body:    "IBM Plex Sans Arabic", "IBM Plex Sans Arabic Fallback", "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* Fluid scale. Minimum body size is 16px — the old site used 10-11px. */
  --fs-xs:   0.8125rem;                               /* 13px, labels only  */
  --fs-sm:   0.875rem;                                /* 14px               */
  --fs-base: 1rem;                                    /* 16px               */
  --fs-lg:   1.125rem;                                /* 18px               */
  --fs-xl:   clamp(1.25rem, 1.1rem + 0.5vw,  1.5rem);
  --fs-2xl:  clamp(1.5rem,  1.3rem + 1vw,    2rem);
  --fs-3xl:  clamp(1.875rem,1.5rem + 1.8vw,  2.75rem);
  --fs-4xl:  clamp(2.25rem, 1.7rem + 2.8vw,  3.75rem);
  --fs-5xl:  clamp(2.75rem, 1.9rem + 4.2vw,  5rem);

  --lh-tight: 1.15;
  --lh-head:  1.25;
  --lh-body:  1.65;

  /* Arabic needs a little more leading — the script has taller ascenders and
     deeper descenders than Latin at the same optical size. */
  --lh-body-ar: 1.8;
  --lh-head-ar: 1.4;

  /* ---- Spacing (4px base) ----------------------------------------------- */
  --sp-1:  0.25rem;  --sp-2:  0.5rem;   --sp-3:  0.75rem;  --sp-4: 1rem;
  --sp-5:  1.25rem;  --sp-6:  1.5rem;   --sp-8:  2rem;     --sp-10: 2.5rem;
  --sp-12: 3rem;     --sp-16: 4rem;     --sp-20: 5rem;     --sp-24: 6rem;
  --sp-32: 8rem;

  --section-y: clamp(3.5rem, 2rem + 6vw, 7rem);

  /* ---- Radius — one decision, applied consistently ----------------------- */
  --r-sm:  4px;
  --r-md:  8px;
  --r-lg:  12px;
  --r-xl:  16px;
  --r-full: 999px;

  /* ---- Elevation — a single, restrained scale ---------------------------- */
  --shadow-1: 0 1px 2px rgba(10, 14, 26, 0.06), 0 1px 3px rgba(10, 14, 26, 0.04);
  --shadow-2: 0 2px 6px rgba(10, 14, 26, 0.07), 0 6px 16px rgba(10, 14, 26, 0.06);
  --shadow-3: 0 8px 24px rgba(10, 14, 26, 0.10), 0 2px 6px rgba(10, 14, 26, 0.06);

  /* ---- Layout ------------------------------------------------------------ */
  --container:      1200px;
  --container-wide: 1400px;
  --container-prose: 68ch;
  --gutter: clamp(1rem, 0.5rem + 2.5vw, 2.5rem);

  --header-h: 72px;

  /* ---- Motion (legacy aliases, kept so existing components keep working) --- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-fast: 120ms;
  --dur:      200ms;
  --dur-slow: 360ms;

  /* ==========================================================================
     MOTION TOKENS
     --------------------------------------------------------------------------
     Every duration, easing curve, and movement distance in the site resolves to
     one of these. No component may write a timing value inline — that is how a
     motion system drifts into 40 slightly-different transitions.

     Rationale for the core 160/240ms band: measured on Darktrace and CrowdStrike,
     both of which run interaction feedback at 200-300ms. It reads as responsive
     without feeling abrupt.

     See review/MOTION-DIRECTION.md for the full system.
     ========================================================================== */

  /* ---- Duration ---------------------------------------------------------- */
  --motion-instant:      80ms;   /* press feedback, active states            */
  --motion-fast:        160ms;   /* hover, focus rings, icon shifts          */
  --motion-standard:    240ms;   /* buttons, cards, drawer items, fields     */
  --motion-slow:        420ms;   /* section reveals, mask wipes              */
  --motion-deliberate:  680ms;   /* hero headline, topology resolve          */
  --motion-page:        320ms;   /* view transitions                         */
  --motion-ambient:      24s;    /* grid drift, gradient light               */
  --motion-ambient-slow: 48s;    /* slowest background layer                 */

  /* ---- Stagger ------------------------------------------------------------ */
  --stagger-tight:       40ms;   /* nav items, list rows                     */
  --stagger-base:        70ms;   /* card grids, feature lists                */
  --stagger-loose:      120ms;   /* hero beats, timeline phases              */

  /* ---- Easing -------------------------------------------------------------
     No spring, bounce, or overshoot anywhere: overshoot reads as playful, and
     Aman X is not playful. */
  --ease-enter:      cubic-bezier(0.16, 1, 0.3, 1);   /* arriving, long settle */
  --ease-exit:       cubic-bezier(0.7, 0, 0.84, 0);   /* leaving, quick        */
  --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);      /* signature curve       */
  --ease-linear:     linear;                          /* ambient + scroll-linked */

  /* ---- Spatial ------------------------------------------------------------
     Reveal travel never exceeds --move-lg. Long travel reads cheap and costs
     more to composite. --move-sm matches the original site's well-judged 8px
     magnetic maximum. */
  --move-xs:   4px;
  --move-sm:   8px;
  --move-md:  16px;
  --move-lg:  28px;
  --scale-press: 0.98;
  --scale-lift:  1.02;

  /* ---- Logical motion direction -------------------------------------------
     THE single source of truth for which way inline-axis motion travels.

     transform, clip-path and transform-origin have no logical-property form:
     translateX is always physically X, and `inset()` corners are always
     physical. So direction has to be resolved once, here, and consumed as a
     variable everywhere else.

     Why variables rather than per-rule `[dir="rtl"]` overrides: these are
     declared ON :root, so `:root[dir="rtl"]` matches the element itself and the
     value inherits to every descendant. An override rule instead has to *reach*
     the target, and the previous ones were written as
     `:root[dir="rtl"] .js-motion [data-reveal="start"]` — a descendant
     combinator between :root and .js-motion, which both live on <html>. That
     selector could never match, so Arabic silently used the English direction.
     Variables remove the whole class of bug: there is no selector to get wrong.

     LTR: inline-start is the left edge. RTL: inline-start is the right edge.
     Content therefore always enters from the reading origin — arriving with the
     reader rather than against them. */
  --motion-inline-start-x: calc(var(--move-lg) * -1);  /* enters from the left  */
  --motion-inline-end-x:   var(--move-lg);             /* enters from the right */
  --motion-origin-inline-start: left;
  --motion-origin-inline-end:   right;
  /* ---- Section scroll motion ----------------------------------------------
     Timings for section-level choreography, kept here so a section cannot
     invent its own numbers. The whole sequence for one chapter — atmosphere,
     eyebrow, heading, copy, visual — is budgeted to land inside ~900ms, which
     is the point past which a reader notices they are waiting.

     Distances are deliberately small. The research measurement across nine
     enterprise security sites found transform and opacity to be ~99% of all
     animated properties; none of it needs to travel far to read as intentional. */
  --section-enter-duration:  620ms;   /* a section establishing itself        */
  --section-title-duration:  760ms;   /* heading mask, slower than the body   */
  --section-stagger:          90ms;   /* between siblings in a cascade        */
  --section-stagger-tight:    55ms;   /* dense grids, so the last card is not
                                         still waiting when the eye arrives   */
  --section-distance-block:   24px;   /* vertical rise                        */
  --section-distance-inline:  32px;   /* inline-axis pair entrance            */
  --connector-draw-duration: 900ms;   /* stroke-dashoffset to 0               */
  --scroll-progress-ease:    cubic-bezier(0.33, 0, 0.2, 1);
  --motion-depth-subtle:     0.965;   /* depth-resolve start scale            */

  /* ---- Pop-out ------------------------------------------------------------
     "Pop-out" here means an element resolves FORWARD out of the composition:
     a small scale toward 1, a short travel, and — the part that carries most
     of the perceived quality — its frame resolving a beat before its content.

     A card whose border arrives first reads as a considered object. One whose
     border and text arrive together reads as a rectangle that faded in. The
     difference costs nothing: border-color and opacity on a layer that is
     already composited.

     Scale floors are deliberately shallow. Anything below ~0.96 stops reading
     as depth and starts reading as a zoom, which is the failure mode this
     brief names explicitly. */
  --pop-scale-card:   0.975;   /* cards in a grid                      */
  --pop-scale-panel:  0.985;   /* large panels — less, because bigger  */
  --pop-scale-row:    0.99;    /* list rows — barely there by design   */
  --pop-lift:         10px;    /* card travel                          */
  --pop-lift-panel:   14px;
  --pop-lift-row:      6px;

  --pop-duration-card:  460ms;
  --pop-duration-panel: 560ms;
  --pop-duration-row:   380ms;
  --pop-frame-lead:     120ms;  /* how far the frame leads its content */
  --pop-cta-settle:     420ms;

  /* Mobile: shorter travel, quicker, less overlap. Not "motion off" — a
     lighter dialect of the same language. */
  --section-distance-block-sm:  16px;
  --section-distance-inline-sm: 18px;
  --section-stagger-sm:         55ms;
  --section-enter-duration-sm: 480ms;
  --pop-lift-sm:                6px;
  --pop-duration-card-sm:     360ms;

  /* Sign multiplier for one-off inline offsets that are not a full reveal.
     +1 means "forward is toward the right". Multiply any --move-* by this. */
  --motion-inline-dir: 1;
  /* Mask closed-state: hides everything from the inline-end side, so the reveal
     opens from inline-start toward inline-end. inset() order is T R B L. */
  --motion-mask-closed: inset(0 100% 0 0);
}

:root[dir="rtl"] {
  --motion-inline-start-x: var(--move-lg);             /* enters from the right */
  --motion-inline-end-x:   calc(var(--move-lg) * -1);  /* enters from the left  */
  --motion-origin-inline-start: right;
  --motion-origin-inline-end:   left;
  --motion-mask-closed: inset(0 0 0 100%);
  --motion-inline-dir: -1;                             /* forward is leftward   */
}

:root {

  /* ---- Ambient limits -----------------------------------------------------
     Opacity ceiling for Level 3 motion. Never exceed --ambient-max behind text. */
  --ambient-min:  0.05;
  --ambient-mid:  0.09;
  --ambient-max:  0.14;
  --ambient-text: 0.06;  /* hard ceiling when layered behind body copy */

  /* Ambient run-state. Flipped to `paused` by JS when the tab is hidden, which
     serves WCAG 2.2.2 and saves battery. One property controls every loop. */
  --ambient-play: running;
}

/* ==========================================================================
   DARK THEME
   The brand's native register. Cyan is lightened here because the contrast
   requirement inverts on a dark surface.
   ========================================================================== */
:root[data-theme="dark"] {
  --surface-0: #060a16;
  --surface-1: #0a0e1a;
  --surface-2: #121829;
  --surface-3: #1b2439;
  --border:        #232d45;
  --border-strong: #35415f;

  --text-1: #f2f5fa; /* 16.8:1 on surface-1 */
  --text-2: #b9c3d6; /* 9.1:1  */
  --text-3: #8c99b3; /* 5.2:1  */

  --accent-text: var(--ax-cyan-400);
  --accent-line: var(--ax-cyan-500);
  --focus-ring:  #5ecdf0;

  --ax-green-ink: #34d399;
  --ax-amber-ink: #fbbf24;
  --ax-red-ink:   #f87171;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-2: 0 2px 8px rgba(0, 0, 0, 0.45);
  --shadow-3: 0 12px 32px rgba(0, 0, 0, 0.5);
}

/* ==========================================================================
   FOOTER AND PRE-FOOTER CTA

   These two bands were the only surfaces on the site painted with hardcoded
   colour literals (--ax-navy-950, #b9c3d6, #fff, #6f7c96) instead of theme
   tokens, so they stayed dark in light mode no matter what the visitor chose.

   Worse, the one block inside the footer that DID use theme tokens — the legal
   identity disclosure — then rendered light-theme dark text on that hardcoded
   dark surface, measuring 2.09:1. The registered name, national address,
   unified national number and privacy email were effectively unreadable in
   light mode on every route, in both locales.

   Both themes are therefore declared explicitly below. Neither inherits from
   the other: an implicit fallback is what produced the defect in the first
   place, and a token that is only defined for one theme is a token that will
   silently do the wrong thing in the other.
   ========================================================================== */
:root {
  /* ---- Light ---- */
  --footer-bg:            var(--surface-2);
  --footer-heading:       var(--text-1);
  --footer-text:          var(--text-2);
  /* The legal disclosure sits one step quieter than body text but never below
     the 4.5:1 floor — it is the most consequential text in the footer. */
  --footer-text-muted:    var(--text-3);
  /* Column titles, brand tag and copyright: the quietest role. In light mode it
     resolves to the same value as muted, because anything quieter drops under
     4.5:1 on this surface. Hierarchy is carried by size and letter-spacing
     instead of by pushing contrast below the floor. */
  --footer-text-faint:    var(--text-3);
  --footer-link:          var(--text-2);
  --footer-link-hover:    var(--text-1);
  /* Interactive boundary (the social buttons). WCAG 1.4.11 wants 3:1 for the
     visible edge of a control, and neither --border nor --border-strong reaches
     that on this surface, so this is a dedicated value: 3.28:1 on --surface-2. */
  --footer-border:        #7a8699;
  /* Decorative dividers. Not UI boundaries, so 1.4.11 does not apply; kept
     subtle on purpose. Two values because the footer genuinely has two: the
     rule above the legal identity block was always a touch stronger than the
     one above the copyright bar, and unifying them would have changed the dark
     footer for cosmetic reasons rather than to fix a defect. */
  --footer-rule:          var(--border);
  --footer-rule-strong:   var(--border-strong);
  --footer-icon:          var(--text-2);
  --footer-icon-hover-bg: var(--surface-3);
  --footer-accent:        var(--accent-text);

  --cta-bg:                 var(--surface-3);
  --cta-heading:            var(--text-1);
  --cta-text:               var(--text-2);
  /* NOT --accent-text. Cyan-600 is calibrated against white and drops to
     4.06:1 on the tinted CTA surface, under the 4.5:1 floor for this small
     uppercase text. The deeper cyan restores the margin at 5.71:1. */
  --cta-accent:             var(--ax-cyan-700);
  /* A solid navy button on a light panel: the restrained dark brand accent,
     confined to a control rather than spread across the whole band. */
  --cta-btn-bg:             var(--ax-navy-900);
  --cta-btn-fg:             #ffffff;
  --cta-btn-bd:             var(--ax-navy-900);
  --cta-btn-ghost-fg:       var(--text-1);
  --cta-btn-ghost-bd:       var(--border-strong);
  --cta-btn-ghost-hover-bg: rgba(10, 14, 26, 0.06);
  --cta-btn-ghost-hover-bd: var(--text-3);
}

:root[data-theme="dark"] {
  /* ---- Dark: the values the footer already shipped, now named ----
     Every literal here is what the hardcoded rule used before this change, so
     the premium dark footer is preserved pixel-for-pixel. */
  --footer-bg:            var(--ax-navy-950);
  --footer-heading:       #ffffff;
  --footer-text:          #b9c3d6;
  --footer-text-muted:    #8c99b3;
  --footer-text-faint:    #6f7c96;
  --footer-link:          #b9c3d6;
  --footer-link-hover:    #ffffff;
  /* Was #232d45, which measured 1.44:1 against --ax-navy-950 — under the 3:1
     WCAG 1.4.11 floor for the visible edge of a control. That is a pre-existing
     dark-mode defect the contrast audit surfaced, so it is corrected here
     rather than preserved. 3.14:1, the least change that clears the floor. */
  --footer-border:        #55607a;
  --footer-rule:          #1b2439;
  --footer-rule-strong:   #232d45;
  --footer-icon:          #b9c3d6;
  --footer-icon-hover-bg: #121829;
  --footer-accent:        var(--accent-text);

  --cta-bg:                 var(--ax-navy-900);
  --cta-heading:            #ffffff;
  --cta-text:               #b9c3d6;
  --cta-accent:             var(--ax-cyan-400);
  --cta-btn-bg:             #ffffff;
  --cta-btn-fg:             var(--ax-navy-900);
  --cta-btn-bd:             #ffffff;
  --cta-btn-ghost-fg:       #ffffff;
  --cta-btn-ghost-bd:       rgba(255, 255, 255, 0.45);
  --cta-btn-ghost-hover-bg: rgba(255, 255, 255, 0.1);
  --cta-btn-ghost-hover-bd: #ffffff;
}

/* Respect the OS preference when the visitor has not chosen explicitly.

   color-scheme alone was not enough. It tells the UA to paint its own surfaces
   dark — canvas, scrollbars, form controls — but it does not touch a single
   custom property, so the theme tokens stayed on their light values. With
   JavaScript enabled this never showed, because the inline script in head.php
   sets data-theme="dark" before first paint and the dark block above applies.
   With JavaScript disabled the attribute is never set, so the page rendered
   dark UA chrome over a light token set: measured, --text-1 resolved to #0a0e1a
   against a #060a16 surface — near-invisible body text.

   The declarations below are mirrored from :root[data-theme="dark"] so the
   no-JS fallback is that same theme rather than a second approximation of it.
   No new value is introduced here.

   Scoped to :not([data-theme]) so an explicit choice always wins: a visitor who
   picked light keeps light even on a dark-preferring OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;

    --surface-0:               #060a16;
    --surface-1:               #0a0e1a;
    --surface-2:               #121829;
    --surface-3:               #1b2439;
    --border:                  #232d45;
    --border-strong:           #35415f;
    --text-1:                  #f2f5fa;
    --text-2:                  #b9c3d6;
    --text-3:                  #8c99b3;
    --accent-text:             var(--ax-cyan-400);
    --accent-line:             var(--ax-cyan-500);
    --focus-ring:              #5ecdf0;
    --ax-green-ink:            #34d399;
    --ax-amber-ink:            #fbbf24;
    --ax-red-ink:              #f87171;
    --shadow-1:                0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-2:                0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow-3:                0 12px 32px rgba(0, 0, 0, 0.5);
    --footer-bg:               var(--ax-navy-950);
    --footer-heading:          #ffffff;
    --footer-text:             #b9c3d6;
    --footer-text-muted:       #8c99b3;
    --footer-text-faint:       #6f7c96;
    --footer-link:             #b9c3d6;
    --footer-link-hover:       #ffffff;
    --footer-border:           #55607a;
    --footer-rule:             #1b2439;
    --footer-rule-strong:      #232d45;
    --footer-icon:             #b9c3d6;
    --footer-icon-hover-bg:    #121829;
    --footer-accent:           var(--accent-text);
    --cta-bg:                  var(--ax-navy-900);
    --cta-heading:             #ffffff;
    --cta-text:                #b9c3d6;
    --cta-accent:              var(--ax-cyan-400);
    --cta-btn-bg:              #ffffff;
    --cta-btn-fg:              var(--ax-navy-900);
    --cta-btn-bd:              #ffffff;
    --cta-btn-ghost-fg:        #ffffff;
    --cta-btn-ghost-bd:        rgba(255, 255, 255, 0.45);
    --cta-btn-ghost-hover-bg:  rgba(255, 255, 255, 0.1);
    --cta-btn-ghost-hover-bd:  #ffffff;
  }
}
