/* ============================================================================
   SPARRAPS · DESIGN TOKENS
   Single source of truth. Authored for the marketing site, but deliberately
   scoped so the customer app, customer web, vendor app, vendor portal and
   admin portal can all consume this same package later.

   Spec: ../../../../CLAUDE.md  ·  ../../../../docs/02-design-system.md

   ⚠ READ BEFORE CHANGING ANY COLOUR
   White on #FF6B1A measures 2.85:1 and FAILS WCAG.
   Customer fills therefore take near-black #1A0B02 → 6.74:1.
   Blue is the opposite: white on #1B62D6 PASSES at 5.58:1.
   Same component, different token. This asymmetry is deliberate and gets
   "corrected" by people who don't know why it exists. It is encoded below as
   a token PAIR (--accent-fill / --on-accent) so it cannot be got wrong.

   Every ratio in this file is MEASURED, not quoted from the design docs —
   `pnpm --filter @sparraps/tokens check` recomputes them and fails the build
   on any regression. Three documented values did not survive that audit; see
   CONTRAST-AUDIT.md for what changed and why.
   ========================================================================= */

@layer sparraps.tokens {
  :root {
    /* ---------------------------------------------------------------
       1 · RAW PALETTE — never referenced directly by a component.
       Components use the semantic layer in §2 onward.
       --------------------------------------------------------------- */

    /* Neutrals — shared by all five products */
    --sp-paper: #f6f8fa;
    --sp-card: #ffffff;
    --sp-sunk: #edf1f5;
    --sp-line: #e2e8ef;
    --sp-ink: #13181f;
    --sp-ink-2: #57626f;
    --sp-ink-3: #8a94a1; /* ⚠ 3.07:1 on white — LARGE TEXT ONLY */
    --sp-ink-3-aa: #636d7a; /* white 5.25 · paper 4.93 · sunk 4.63 — safe at 12.5px */
    --sp-night: #0b0e13;

    /* Customer — Ignition Orange */
    --sp-orange-wash: #fff2e8;
    --sp-orange-core: #ff6b1a;
    --sp-orange-icon: #e85d04;
    --sp-orange-text: #d14700; /* ⚠ 4.55:1 on WHITE ONLY. Fails on paper/sunk. */
    --sp-orange-text-aa: #c34200; /* Safe on white 5.12 · paper 4.81 · sunk 4.51 */
    --sp-on-orange: #1a0b02; /* Measured 6.74:1 on orange-core. NEVER #ffffff (2.85:1) */

    /* Vendor / partner — Signal Blue */
    --sp-blue-wash: #eaf1fd;
    --sp-blue-core: #1b62d6;
    --sp-blue-text: #0f4399;
    --sp-on-blue: #ffffff; /* 5.5:1 — passes */

    /* Admin — Graphite (unused by marketing, kept for cross-product reuse) */
    --sp-admin-ground: #f8fafc;
    --sp-admin-accent: #475569;
    --sp-admin-action: #d14700;

    /* Semantic — never decorative.
       The -aa variants are the ones components use: the documented values
       fail 4.5:1 on the paper/sunk grounds. See CONTRAST-AUDIT.md. */
    --sp-success: #12854a; /* ⚠ 4.40:1 on paper — fails */
    --sp-success-aa: #0f7a43; /* white 5.41 · paper 5.08 */
    --sp-warning: #a96a00; /* ⚠ 4.42:1 on white — fails */
    --sp-warning-aa: #9c6200; /* white 5.05 · paper 4.74 */
    --sp-error: #c0281e; /* white 5.89 · paper 5.54 — passes */
    --sp-info: #1863c8; /* white 5.74 · paper 5.39 — passes */

    /* Condition grades — never red. Grade C is worn, not broken.
       The base values are the documented ladder, used for FILLS and DOTS.
       The -ink variants are for grade text on a tinted background, where the
       tint lifts the ground and the base values drop below 4.5:1. */
    --sp-grade-new: #1863c8;
    --sp-grade-a: #12854a;
    --sp-grade-b: #a96a00;
    --sp-grade-c: #5f6b79;

    --sp-grade-new-ink: #1558b4; /* 6.04 on its own 8% tint */
    --sp-grade-a-ink: #0f7a43; /* 4.83 */
    --sp-grade-b-ink: #8f5a00; /* 5.18 */
    --sp-grade-c-ink: #525c69; /* 6.06 */

    /* Feedback — resolved semantic values. Components use THESE. */
    --feedback-success: var(--sp-success-aa);
    --feedback-warning: var(--sp-warning-aa);
    --feedback-error: var(--sp-error);
    --feedback-info: var(--sp-info);

    /* ---------------------------------------------------------------
       2 · SEMANTIC SURFACES — light context (the default, 60% of the page)
       --------------------------------------------------------------- */
    --surface-ground: var(--sp-paper);
    --surface-raised: var(--sp-card);
    --surface-sunk: var(--sp-sunk);
    --surface-border: var(--sp-line);

    --text-primary: var(--sp-ink);
    --text-secondary: var(--sp-ink-2);
    /* Tertiary is used for 12.5px uppercase labels, placeholders and captions —
       small text, so it needs 4.5:1, not the 3:1 large-text threshold. The
       documented --sp-ink-3 fails there; the -aa variant is what components
       resolve to. See CONTRAST-AUDIT.md. */
    --text-tertiary: var(--sp-ink-3-aa);
    --text-inverse: var(--sp-card);

    /* ---------------------------------------------------------------
       3 · ACCENT — the funnel pair.
       Default is the CUSTOMER funnel. The partner funnel swaps both
       halves together via [data-funnel="partner"] in §4, which is what
       makes the contrast asymmetry structurally safe.
       --------------------------------------------------------------- */
    --accent-fill: var(--sp-orange-core); /* button / active backgrounds  */
    --on-accent: var(--sp-on-orange); /* text ON that fill — 7.1:1     */
    --accent-text: var(--sp-orange-text-aa); /* AA on white, paper AND sunk   */
    --accent-icon: var(--sp-orange-icon); /* icons on light                */
    --accent-wash: var(--sp-orange-wash); /* selected rows, tinted fills   */

    /* ---------------------------------------------------------------
       4 · TYPOGRAPHY
       Hanken Grotesk + IBM Plex Mono, both self-hosted and subset.
       Noto Sans Devanagari joins the stack when Hindi ships — the
       renderer picks per glyph, so the stack is declared now.
       --------------------------------------------------------------- */
    --font-sans:
      "Hanken Grotesk Variable", "Hanken Grotesk", "Noto Sans Devanagari",
      ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-mono:
      "IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

    /* Fluid scale — clamp() avoids breakpoint jumps and font-size CLS.
       Marketing runs larger than the app: a landing page may shout,
       a tool may not. */
    --text-display: clamp(2.5rem, 1.6rem + 4.2vw, 4.5rem); /* 40 → 72 */
    --text-h1: clamp(2rem, 1.4rem + 2.8vw, 3.25rem); /* 32 → 52 */
    --text-h2: clamp(1.625rem, 1.25rem + 1.8vw, 2.5rem); /* 26 → 40 */
    --text-h3: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem); /* 20 → 26 */
    --text-lead: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem); /* 17 → 20 */
    --text-body: 1.0625rem; /* 17 */
    --text-small: 0.9375rem; /* 15 */
    --text-label: 0.78125rem; /* 12.5 — uppercase, tracked */
    --text-mono: 0.9375rem; /* 15 tabular */

    /* Body text never below 11.5px on mobile — see docs/02 */
    --text-min: 0.71875rem; /* 11.5 — hard floor, do not go under */

    --weight-regular: 400;
    --weight-medium: 500;
    --weight-semibold: 650;
    --weight-bold: 750;
    --weight-black: 800;

    --leading-tight: 1.1;
    --leading-snug: 1.25;
    --leading-normal: 1.4; /* Latin */
    --leading-indic: 1.575; /* Devanagari matras sit above and below */
    --leading-prose: 1.65;

    --tracking-display: -0.028em;
    --tracking-title: -0.02em;
    --tracking-normal: 0;
    --tracking-label: 0.1em;

    /* ---------------------------------------------------------------
       5 · SPACING — 4px base grid.
       Marketing runs the SPACIOUS scale (density 3). The app runs
       4/8/12/16/24/32; a landing page needs room to breathe.
       --------------------------------------------------------------- */
    --space-1: 0.25rem; /*  4 */
    --space-2: 0.5rem; /*  8 */
    --space-3: 0.75rem; /* 12 */
    --space-4: 1rem; /* 16 */
    --space-5: 1.5rem; /* 24 */
    --space-6: 2rem; /* 32 */
    --space-7: 3rem; /* 48 */
    --space-8: 4rem; /* 64 */
    --space-9: 6rem; /* 96 */
    --space-10: 8rem; /* 128 — section rhythm on desktop */

    --gutter: var(--space-4);
    --section-y: clamp(var(--space-7), 5vw, var(--space-10));

    /* ---------------------------------------------------------------
       6 · LAYOUT
       --------------------------------------------------------------- */
    --width-content: 75rem; /* 1200 */
    --width-prose: 68ch; /* readable measure  */
    --width-narrow: 44rem; /* 704 — centred copy */

    --radius-sm: 0.375rem; /*  6 */
    --radius: 0.6875rem; /* 11 — the card radius from docs/02 */
    --radius-lg: 1rem; /* 16 */
    --radius-pill: 999px;

    /* Cards carry a 1px line border and NO drop shadow at rest.
       Shadow is reserved for genuinely raised/floating surfaces. */
    --shadow-none: none;
    --shadow-raised: 0 1px 2px rgb(19 24 31 / 0.04), 0 8px 24px -12px rgb(19 24 31 / 0.12);
    --shadow-float: 0 2px 4px rgb(19 24 31 / 0.05), 0 16px 40px -16px rgb(19 24 31 / 0.2);

    /* ---------------------------------------------------------------
       7 · TOUCH & FOCUS — 44×44 minimum, non-negotiable.
       Users have greasy or gloved hands.
       --------------------------------------------------------------- */
    --tap-min: 2.75rem; /* 44 */
    --tap-row: 3.5rem; /* 56 — action rows */

    --focus-width: 2px;
    --focus-offset: 2px;
    /**
     * ⚠ THE FOCUS RING IS TWO-TONE, AND NOT AN ACCENT COLOUR.
     *
     * It was var(--accent-fill) = #FF6B1A. Two separate failures:
     *   - 2.85:1 on white, under the 3:1 minimum for a non-text indicator
     *   - identical to the primary button's own fill, so a focused CTA drew an
     *     orange ring around an orange button at 1.80:1 and keyboard users
     *     could not see what was focused
     *
     * An accent colour can never satisfy this, because the ring has to be
     * visible against BOTH the page ground AND the accent-filled controls
     * sitting on it. So the ring is ink with a light halo behind it: the ink
     * carries contrast against every light ground and against the orange fill
     * (6.74:1), and the halo separates it from dark ones. `.on-night` inverts
     * the pair.
     *
     * Neither Lighthouse nor axe checks focus-ring contrast — this is asserted
     * in contrast.check.ts instead.
     */
    --focus-color: var(--sp-ink);
    --focus-halo: var(--sp-card);

    /* ---------------------------------------------------------------
       8 · MOTION — 180–220ms ease-out for everything.
       The sourcing pulse (~3.4s) is the only ambient animation.
       --------------------------------------------------------------- */
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --duration-fast: 140ms;
    --duration: 190ms;
    --duration-slow: 220ms;
    --duration-pulse: 3400ms; /* the sourcing pulse */

    color-scheme: light;
  }

  /* =========================================================================
     DARK SECTION CONTEXT — the 30% graphite anchor.
     Applied to a <Section tone="night">. Remaps the semantic layer rather
     than restating colours, so any component dropped inside is correct with
     no per-component dark variant.
     ====================================================================== */
  .on-night {
    /* Redeclared here rather than inherited: var() is substituted where it is
       DECLARED, so a :root reference to --accent-text does not re-resolve in
       this context. Every context that changes the accent must restate this. */
    --focus-color: #f4f7fa;
    --focus-halo: var(--sp-night);

    --surface-ground: var(--sp-night);
    --surface-raised: #131922;
    --surface-sunk: #090c10;
    --surface-border: #232b36;

    --text-primary: #f4f7fa;
    --text-secondary: #a9b4c0;
    --text-tertiary: #77828f;
    --text-inverse: var(--sp-ink);

    /* Orange as TEXT needs to lighten on night — #D14700 is tuned for
       white grounds and drops below 4.5:1 on #0B0E13. */
    --accent-text: #ff8a45;
    --accent-icon: #ff8a45;
    --accent-wash: #1f1409;

    color-scheme: dark;
  }

  .on-night[data-funnel="partner"] {
    --focus-color: #7aa9f0; /* 8.06:1 on #0B0E13 */
    --accent-text: #7aa9f0;
    --accent-icon: #7aa9f0;
    --accent-wash: #0d1929;
  }

  /* =========================================================================
     PARTNER FUNNEL — the /partner/ path runs Signal Blue.
     Both halves of the pair swap together, so white-on-blue (5.5:1, passes)
     is applied automatically and near-black-on-orange can never leak in.
     ====================================================================== */
  [data-funnel="partner"] {
    --focus-color: var(--sp-blue-text); /* 9.20:1 on white */
    --accent-fill: var(--sp-blue-core);
    --on-accent: var(--sp-on-blue);
    --accent-text: var(--sp-blue-text);
    --accent-icon: var(--sp-blue-core);
    --accent-wash: var(--sp-blue-wash);
  }

  /* =========================================================================
     REDUCED MOTION — collapse every duration to a near-zero value so
     transitions resolve instantly instead of being removed (which would
     lose end states). The sourcing pulse is disabled at its source.
     ====================================================================== */
  @media (prefers-reduced-motion: reduce) {
    :root {
      --duration-fast: 1ms;
      --duration: 1ms;
      --duration-slow: 1ms;
      --duration-pulse: 1ms;
    }
  }
}
/* ============================================================================
   SPARRAPS · BASE RESET
   Deliberately small. Every rule here either prevents a layout shift, fixes a
   cross-browser inconsistency, or enforces a rule from docs/02-design-system.md.
   Nothing decorative lives in this file.
   ========================================================================= */

@layer sparraps.reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  * {
    margin: 0;
  }

  html {
    -webkit-text-size-adjust: 100%;
    /* Never disable zoom. Never set user-scalable=no. */

    /* Safety net only — the real fix is always to remove the element that
       overflows. `clip` rather than `hidden` because `hidden` would turn the
       root into a scroll container and break position: sticky. */
    overflow-x: clip;
  }

  /* The UA rule for [hidden] is `display: none` at the lowest specificity, so
     ANY author `display:` on the same element beats it and the element stays
     visible. That is a real bug generator — it is how the 3D loader ended up
     painted on top of the finished model. Force it. */
  [hidden] {
    display: none !important;
  }

  body {
    min-height: 100dvh;
    background: var(--surface-raised);
    color: var(--text-primary);
    font-family: var(--font-sans);
    /* Global guard against sideways scroll. `clip` rather than `hidden`:
       `hidden` makes the body a scroll container, which silently breaks
       position: sticky on the header. */
    overflow-x: clip;
    font-size: var(--text-body);
    font-weight: var(--weight-regular);
    line-height: var(--leading-prose);
    font-synthesis-weight: none;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  /* Media never overflows and always reserves its box, so images cannot
     contribute to CLS. Explicit width/height still required on every <img>. */
  img,
  picture,
  video,
  canvas,
  svg {
    display: block;
    max-width: 100%;
  }

  img,
  video {
    height: auto;
  }

  /* Inputs do not inherit type by default in any browser. */
  input,
  button,
  textarea,
  select {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
  }

  /* Long part numbers and OEM codes must not blow out a container. */
  p,
  h1,
  h2,
  h3,
  h4,
  li,
  figcaption {
    overflow-wrap: break-word;
  }

  /* Headings inherit weight/tracking from component classes, not from here. */
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    font-size: inherit;
    font-weight: inherit;
    line-height: var(--leading-tight);
    text-wrap: balance; /* prevents orphan words in headlines */
  }

  p {
    text-wrap: pretty;
  }

  ul[role="list"],
  ol[role="list"] {
    list-style: none;
    padding: 0;
  }

  a {
    color: var(--accent-text);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
  }

  /* Every interactive element has a visible focus state. Never remove this.
     :focus-visible so mouse users do not see a ring, keyboard users always do. */
  :where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
    /* Two-tone: an ink outline for contrast against light grounds AND against
       accent-filled controls, plus a halo that separates it from dark ones.
       A single accent-coloured ring cannot do both — around the orange primary
       button it measured 1.80:1 and was effectively invisible. */
    outline: var(--focus-width) solid var(--focus-color);
    outline-offset: var(--focus-offset);
    box-shadow: 0 0 0 calc(var(--focus-width) + var(--focus-offset)) var(--focus-halo);
    border-radius: var(--radius-sm);
  }

  /* Tabular numerals everywhere a number is data: prices, part numbers,
     ASC codes, timers, counters. Digits align in columns and a running
     timer does not jitter its row. */
  .mono,
  code,
  kbd,
  samp {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
  }

  /* Tables scroll inside their own container; the page body never scrolls
     sideways. Wrap every table in .table-scroll. */
  .table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Visually hidden but available to screen readers. */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* Skip link — first focusable element on every page. */
  .skip-link {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 100;
    padding: var(--space-3) var(--space-4);
    background: var(--accent-fill);
    color: var(--on-accent);
    border-radius: var(--radius-sm);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    transform: translateY(-200%);
  }

  .skip-link:focus {
    transform: translateY(0);
  }

  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}
/* ============================================================================
   SPARRAPS · SELF-HOSTED FONTS

   Written by hand rather than importing @fontsource's stylesheets, for three
   reasons:

   1. @fontsource's top-level entry ships cyrillic and vietnamese subsets we
      will never render. They are gated by unicode-range so a browser would not
      download them — but they still land in dist/ and confuse an audit.

   2. @fontsource's PER-SUBSET files (latin-400.css, latin-ext-400.css) carry
      NO unicode-range at all. Importing two of them would make the browser
      fetch both unconditionally — worse than the thing we were avoiding.

   3. ⚠ The rupee sign ₹ (U+20B9) is in the latin-ext subset, NOT latin.
      Dropping latin-ext to "save bytes" would silently fall every price on the
      site back to a system font. Both subsets are required.

   woff2 only. woff adds ~40KB per family for browsers that no longer matter.
   ========================================================================= */

/**
 * ⚠ font-display is "optional", NOT "swap".
 *
 * "swap" paints a fallback first and re-lays the text out when the real font
 * arrives. On the hero headline that re-wrap moved every section below it and
 * produced a 0.22 CLS on mobile — a failing Core Web Vital caused entirely by
 * the font strategy, not by anything on the page.
 *
 * A metric-matched fallback is the usual answer, but matching a VARIABLE face
 * across weights is guesswork unless every weight is measured, and a wrong
 * adjustment makes the shift bigger rather than smaller. That is exactly what
 * happened on the first attempt here: correcting size-adjust from a guessed
 * 97% to a measured 82.6% took CLS from 0.12 to 0.22.
 *
 * "optional" removes the failure mode by construction. The browser uses the
 * real font if it is ready within a short window, and otherwise keeps the
 * fallback for the whole page load — it never swaps, so it can never reflow.
 * The body face is preloaded and 34KB, so it wins that race on any normal
 * connection. The trade — a genuinely slow first visit renders in the system
 * font — is far cheaper than a guaranteed layout shift on every mobile visit,
 * on a site whose primary audience is on patchy mobile connections.
 */

/* ---- Hanken Grotesk Variable — display and body ------------------------- */

@font-face {
  font-family: "Hanken Grotesk Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: optional;
  src: url("/fonts/hanken-grotesk-latin-wght-normal.woff2") format("woff2-variations");
  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: "Hanken Grotesk Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: optional;
  src: url("/fonts/hanken-grotesk-latin-ext-wght-normal.woff2") format("woff2-variations");
  /* U+20AD-20C0 contains ₹ U+20B9. Do not remove this subset. */
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---- IBM Plex Mono 400 — every part number, code, price and timer ------- */

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: optional;
  src: url("/fonts/ibm-plex-mono-latin-400-normal.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: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: optional;
  src: url("/fonts/ibm-plex-mono-latin-ext-400-normal.woff2") format("woff2");
  /* ₹ lives here too — prices are set in mono. */
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------------
   NO SYNTHETIC FALLBACK FACE.

   There was a "Hanken Fallback" @font-face here with size-adjust and metric
   overrides. It has been removed deliberately.

   Under "optional" the fallback is only ever used when the real font missed
   its window — and then it is used for the ENTIRE page load, with no swap.
   A size-adjust tuned to match Hanken would, in that case, simply render all
   the text 17% smaller than designed, for no benefit: there is no swap left
   to smooth over. The system stack at its natural size is the better outcome.

   For the record, the measurement that produced 82.6% was real — at 100px/800
   the same string sets to 2520px in Hanken and 3051px in Arial. Kept here in
   case a future change reintroduces "swap" and needs the number.
   ------------------------------------------------------------------------ */
/* ============================================================================
   SPARRAPS · UTILITIES
   Scroll choreography, emphasis and hover treatments.

   ALL CSS. No AOS library, no GSAP, no IntersectionObserver, no JavaScript of
   any kind. AOS is ~14KB plus a scroll listener on the main thread; native
   scroll-driven animations run on the compositor and cost nothing.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   CROSS-DOCUMENT VIEW TRANSITIONS

   ⚠ Deliberately NOT Astro's <ClientRouter>. That ships a client-side router
   (~8KB of JS) to every page and would end the zero-JS property this site is
   built around. The native `@view-transition` rule does cross-document
   transitions with NO JavaScript at all — the browser handles it.

   Unsupported browsers simply navigate normally, which is the correct
   fallback. Must live OUTSIDE the cascade layers: @view-transition is an
   at-rule, not a style rule, and is ignored inside @layer.
   ------------------------------------------------------------------------ */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-out 130ms cubic-bezier(0.4, 0, 1, 1) both;
  }
  ::view-transition-new(root) {
    animation: vt-in 190ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }
}

/* Exit faster than enter — the outgoing page should get out of the way
   rather than linger. */
@keyframes vt-out {
  to {
    opacity: 0;
  }
}
@keyframes vt-in {
  from {
    opacity: 0;
    transform: translateY(0.5rem);
  }
}

/* The header is continuous across navigations, so it must not cross-fade
   with itself — that reads as a flicker. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-group(hdr) {
    animation-duration: 0ms;
  }
}

@layer sparraps.utilities {
  /* ---------------------------------------------------------------------
     SCROLL REVEAL

     Progressive enhancement done properly: the RESTING STATE IS VISIBLE, and
     the animation only runs where the feature is supported and the user has
     not asked for reduced motion. A browser without support simply shows the
     content. Nothing is ever hidden by default, so content can never be
     trapped behind a broken animation — the failure mode that makes most
     scroll-animation libraries an accessibility problem.
     ------------------------------------------------------------------ */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .reveal,
      .reveal-up,
      .reveal-left,
      .reveal-right,
      .reveal-scale {
        animation: linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 55%;
      }

      .reveal,
      .reveal-up {
        animation-name: reveal-up;
      }
      .reveal-left {
        animation-name: reveal-left;
      }
      .reveal-right {
        animation-name: reveal-right;
      }
      .reveal-scale {
        animation-name: reveal-scale;
      }

      /* Children lift in sequence as the group scrolls through. Each child
         gets its own timeline, so the effect is positional rather than
         time-based — it stays correct at any scroll speed. */
      .reveal-stagger > * {
        animation: reveal-up linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 45%;
      }
    }
  }

  @keyframes reveal-up {
    from {
      opacity: 0;
      transform: translateY(1.5rem);
    }
  }
  @keyframes reveal-left {
    from {
      opacity: 0;
      transform: translateX(-1.5rem);
    }
  }
  @keyframes reveal-right {
    from {
      opacity: 0;
      transform: translateX(1.5rem);
    }
  }
  @keyframes reveal-scale {
    from {
      opacity: 0;
      transform: scale(0.96);
    }
  }

  /* ---------------------------------------------------------------------
     HOVER

     .lift    — for cards and tiles
     .arrow   — a link whose chevron slides on hover
     ------------------------------------------------------------------ */
  .lift {
    transition:
      transform var(--duration) var(--ease-out),
      box-shadow var(--duration) var(--ease-out),
      border-color var(--duration) var(--ease-out);
  }
  .lift:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-raised);
    border-color: var(--accent-fill);
  }

  .arrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
  }
  .arrow::after {
    content: "→";
    transition: transform var(--duration) var(--ease-out);
  }
  .arrow:hover::after,
  a:hover > .arrow::after {
    transform: translateX(0.25rem);
  }

  /* ---------------------------------------------------------------------
     EMPHASIS — for the phrase in a paragraph that carries the point.

     Draws a thick accent underline behind the descenders rather than
     highlighting the whole line, so it reads as deliberate emphasis instead
     of a marker pen. box-decoration-break keeps it correct across a line
     wrap, which matters because Hindi runs 20–30% longer than English.
     ------------------------------------------------------------------ */
  .hl {
    background-image: linear-gradient(
      to top,
      var(--accent-wash) 0,
      var(--accent-wash) 0.32em,
      transparent 0.32em
    );
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    font-weight: var(--weight-semibold);
    color: var(--text-primary);
  }

  /* On night the wash is nearly black, so emphasis switches to the accent
     itself — a wash would be invisible. */
  .on-night .hl {
    background-image: none;
    color: var(--accent-text);
  }

  /* ---------------------------------------------------------------------
     DISPLAY NUMERALS — the facts are the graphics.
     Tabular mono at display scale, so figures align and read as data.
     ------------------------------------------------------------------ */
  .numeral {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    font-size: clamp(2.75rem, 1.5rem + 5.4vw, 5.5rem);
    font-weight: 400;
    line-height: 0.92;
    letter-spacing: -0.045em;
    color: var(--text-primary);
  }
  .numeral--accent {
    color: var(--accent-text);
  }

  /* -------------------------------------------------------------------
     COUNTING NUMERALS — the figure ticks up as it scrolls into view.

     ⚠ THE REAL NUMBER IS ALWAYS IN THE HTML. The animated value is an
     ADDITIONAL pseudo-element that only appears where @property and
     scroll-driven animations both exist. Anywhere else — and under
     prefers-reduced-motion — the plain text number is what shows.

     Building it the other way round (animating a counter as the only
     source of the value) renders "0" in every unsupported browser and
     leaves screen readers with nothing. The number is content, not
     decoration, so it is never allowed to depend on an animation.
     ------------------------------------------------------------------ */
  /**
   * ⚠ THE COUNT-UP ANIMATION HAS BEEN REMOVED. DO NOT REINSTATE IT.
   *
   * It worked like this: hide the real number with `visibility: hidden`, and
   * paint a CSS counter over it driven by an @property on a view() timeline.
   *
   * It shipped broken. The minifier folded the timeline into the `animation`
   * shorthand, Chrome rejected the declaration, the animation never ran, and
   * `--tick` sat at its initial value — so `content: counter(tick)` rendered
   * "0" while the true figure stayed hidden underneath. Every headline number
   * on the homepage read ZERO: 0 partner godowns, 0 cities, 0 parts sourced,
   * and both manufacturer exit years as 0.
   *
   * The minifier is now off and a build check guards against the collapse, but
   * the deeper fault was the design: a NUMBER IS CONTENT, and content must
   * never be contingent on an animation running. Any failure — an unsupported
   * browser, a minifier, a typo in a keyframe — turned a factual claim into a
   * false one, silently, on the page investors see first.
   *
   * The figures are already the strongest graphic on the page: display-scale
   * IBM Plex Mono, tabular. They do not need to tick to land. `.count` and
   * `.count__v` are kept as no-op hooks so existing markup stays valid.
   */
  .count {
    position: relative;
  }

  /* ---------------------------------------------------------------------
     LAYOUT HELPERS
     ------------------------------------------------------------------ */
  /* ⚠ NOT 100vw. On a desktop browser with a classic scrollbar, 100vw is the
     viewport INCLUDING the scrollbar, so a 100vw element overflows by its
     width and produces a horizontal scrollbar. 100% of the containing block
     plus symmetric negative margins achieves the same bleed safely. */
  .bleed {
    width: auto;
    margin-inline: calc(-50vw + 50%);
    max-width: none;
  }

  /* A single soft accent radial. One gradient, no image, and no blur filter —
     a filter would force a compositing layer and cost paint time. */
  .glow {
    position: relative;
    isolation: isolate;
  }
  /* ⚠ Horizontal inset must stay 0. `inset: ... -10% ...` pushed this 10% past
     each edge and was the sole cause of horizontal scroll on every page that
     used .glow — the overflow measured exactly 10% of the viewport at every
     width. The gradient is shaped to bleed visually without the box doing so. */
  .glow::before {
    content: "";
    position: absolute;
    inset: -20% 0 auto 0;
    height: 70%;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(
      78% 60% at 28% 0%,
      color-mix(in oklab, var(--sp-orange-core) 22%, transparent) 0%,
      transparent 72%
    );
  }
  [data-funnel="partner"].glow::before {
    background: radial-gradient(
      78% 60% at 28% 0%,
      color-mix(in oklab, var(--sp-blue-core) 24%, transparent) 0%,
      transparent 72%
    );
  }

  /* Centres a section's intro block above full-width content below it. */
  .centred {
    text-align: center;
    max-width: 60ch;
    margin-inline: auto;
  }
  .centred > * {
    margin-inline: auto;
  }
}
/* ============================================================================
   SPARRAPS · PROSE
   Shared typography for the deep content pages. Defined once here rather than
   repeated in every page's scoped <style>, so the reading experience cannot
   drift between /how-it-works/ and /partner/.
   ========================================================================= */

@layer sparraps.prose {
  /**
   * A reading column, CENTRED in its container.
   *
   * ⚠ Do not remove `margin-inline: auto`. Without it a 68ch column sits hard
   * left inside a 1200px container and roughly half the page is empty — which
   * reads as a broken layout rather than a deliberate measure.
   *
   * 68ch is the readable line length; the container stays wide so individual
   * elements can break out of it (see .breakout below).
   */
  .prose-page {
    max-width: var(--width-prose);
    margin-inline: auto;
  }

  /**
   * Escape the reading column for something that needs the room — a
   * comparison table, a card grid, a full-width figure. Keeps the prose
   * measure readable without trapping wide content inside it.
   */
  .prose-page > .breakout {
    width: min(var(--width-content), 100%);
    margin-inline: calc(50% - min(var(--width-content), 100%) / 2);
  }

  .prose-page > * + * {
    margin-top: var(--space-5);
  }

  .prose-page p,
  .prose-page li {
    color: var(--text-secondary);
    line-height: var(--leading-prose);
  }

  .prose-page strong {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
  }

  .prose-page h2 {
    margin-top: var(--space-8);
    font-size: var(--text-h2);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-title);
    line-height: 1.1;
    color: var(--text-primary);
    max-width: 24ch;
    text-wrap: balance;
  }

  .prose-page h3 {
    margin-top: var(--space-7);
    font-size: var(--text-h3);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-title);
    color: var(--text-primary);
    text-wrap: balance;
  }

  .prose-page h2 + p,
  .prose-page h3 + p {
    margin-top: var(--space-4);
  }

  .prose-page ul,
  .prose-page ol {
    padding-left: var(--space-5);
  }

  .prose-page li + li {
    margin-top: var(--space-3);
  }

  .prose-page a {
    color: var(--accent-text);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
  }

  /* Section rule — a quiet divider between major topics on a long page. */
  .prose-page hr {
    margin-block: var(--space-8);
    border: 0;
    border-top: 1px solid var(--surface-border);
  }

  /* ---------------------------------------------------------------------
     KEY POINT — a boxed statement for the thing on the page that must not
     be missed. Distinct from Quote, which carries principles.
     ------------------------------------------------------------------ */
  .keypoint {
    margin-top: var(--space-6);
    padding: var(--space-5);
    background: var(--accent-wash);
    border-left: 3px solid var(--accent-fill);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  }

  .keypoint p {
    color: var(--text-primary);
    font-weight: var(--weight-medium);
  }

  .keypoint > * + * {
    margin-top: var(--space-3);
  }

  .on-night .keypoint {
    background: color-mix(in oklab, var(--accent-fill) 12%, transparent);
  }

  /* ---------------------------------------------------------------------
     DEFINITION ROWS — a two-column term/description list used heavily on
     the explainer pages. Collapses to stacked on mobile.
     ------------------------------------------------------------------ */
  .deflist {
    margin-top: var(--space-6);
    border-top: 1px solid var(--surface-border);
  }

  .deflist > div {
    display: grid;
    gap: var(--space-2);
    padding-block: var(--space-5);
    border-bottom: 1px solid var(--surface-border);
  }

  .deflist dt {
    font-weight: var(--weight-semibold);
    color: var(--text-primary);
  }

  .deflist dd {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--text-small);
    line-height: var(--leading-prose);
  }

  @media (min-width: 48rem) {
    .deflist > div {
      grid-template-columns: 15rem 1fr;
      gap: var(--space-6);
    }
  }

  /* ---------------------------------------------------------------------
     COMPARISON TABLE — scrolls inside its own container so the page body
     never scrolls sideways.
     ------------------------------------------------------------------ */
  .table-scroll {
    margin-top: var(--space-6);
    border: 1px solid var(--surface-border);
    border-radius: var(--radius);
  }

  .table-scroll table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-small);
    min-width: 34rem;
  }

  .table-scroll th,
  .table-scroll td {
    padding: var(--space-4);
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--surface-border);
  }

  .table-scroll th {
    font-size: var(--text-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--text-tertiary);
    background: var(--surface-ground);
  }

  .table-scroll td {
    color: var(--text-secondary);
  }

  .table-scroll tbody tr:last-child td {
    border-bottom: 0;
  }

  .table-scroll td strong {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
  }
}
.btn[data-astro-cid-sc6obj6y] {
  min-height: var(--tap-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding-inline: var(--space-5);
  border: 1px solid #0000;
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  line-height: 1;
  letter-spacing: .005em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--duration) var(--ease-out),
      border-color var(--duration) var(--ease-out),
      color var(--duration) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
}

.btn__label[data-astro-cid-sc6obj6y] {
  display: inline-block;
}

.btn--primary[data-astro-cid-sc6obj6y] {
  background: var(--accent-fill);
  color: var(--on-accent);
}

.btn--primary[data-astro-cid-sc6obj6y]:hover {
  background: color-mix(in oklab, var(--accent-fill) 88%, black);
}

.btn--secondary[data-astro-cid-sc6obj6y] {
  background: var(--surface-raised);
  color: var(--text-primary);
  border-color: var(--surface-border);
}

.btn--secondary[data-astro-cid-sc6obj6y]:hover {
  background: var(--surface-sunk);
  border-color: var(--text-tertiary);
}

.btn--ghost[data-astro-cid-sc6obj6y] {
  background: none;
  color: var(--accent-text);
  border-color: currentColor;
}

.btn--ghost[data-astro-cid-sc6obj6y]:hover {
  background: var(--accent-wash);
}

.btn--sm[data-astro-cid-sc6obj6y] {
  min-height: var(--tap-min);
  padding-inline: var(--space-4);
  font-size: var(--text-label);
}

.btn--lg[data-astro-cid-sc6obj6y] {
  min-height: var(--tap-row);
  padding-inline: var(--space-6);
  font-size: var(--text-body);
}

.btn--block[data-astro-cid-sc6obj6y] {
  display: flex;
  width: 100%;
}

.btn[data-astro-cid-sc6obj6y]:active {
  transform: translateY(1px);
}

.btn[data-astro-cid-sc6obj6y]:disabled, .btn[data-astro-cid-sc6obj6y][aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: none;
}

.btn__ext[data-astro-cid-sc6obj6y] {
  flex: none;
  opacity: .7;
}

@media (prefers-reduced-motion: reduce) {
  .btn[data-astro-cid-sc6obj6y]:active {
    transform: none;
  }
}
.hdr[data-astro-cid-nen7h5rs] {
  view-transition-name: hdr;
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--sp-card);
  border-bottom: 1px solid #0000;
}

.hdr--overlay[data-astro-cid-nen7h5rs] {
  position: fixed;
  left: 0;
  right: 0;
  background: var(--sp-card);
  border-bottom-color: var(--sp-line);
  box-shadow: 0 1px 2px #13181f0a, 0 8px 24px -16px #13181f3d;
  transition: background-color .26s var(--ease-out),
      box-shadow .26s var(--ease-out),
      border-color .26s var(--ease-out);
}

.hdr--overlay[data-astro-cid-nen7h5rs].is-clear {
  background: none;
  border-bottom-color: #0000;
  box-shadow: none;
  --text-primary: #f4f7fa;
  --text-secondary: #c2ccd6;
  --text-tertiary: #97a2ae;
  --accent-text: #ff8a45;
  --surface-border: #ffffff24;
}

@supports (animation-timeline: scroll()) {
  .hdr[data-astro-cid-nen7h5rs]:not(.hdr--overlay) {
    animation: linear both hdr-lift;
    animation-timeline: scroll(root);
    animation-range: 0 5rem;
  }
}

@keyframes hdr-lift {
  to {
    border-bottom-color: var(--sp-line);
    box-shadow: 0 1px 2px #13181f0a, 0 8px 24px -16px #13181f3d;
  }
}

@supports not (animation-timeline: scroll()) {
  .hdr[data-astro-cid-nen7h5rs] {
    border-bottom-color: var(--sp-line);
  }
}

.hdr__inner[data-astro-cid-nen7h5rs] {
  max-width: var(--width-content);
  margin-inline: auto;
  padding-inline: var(--gutter);
  min-height: 4.5rem;
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.mark[data-astro-cid-nen7h5rs] {
  display: grid;
  flex: none;
  min-height: var(--tap-min);
  align-items: center;
  transition: transform var(--duration) var(--ease-out);
  transform-origin: 0;
}

.mark[data-astro-cid-nen7h5rs]:hover {
  transform: scale(1.04);
}

.mark__img[data-astro-cid-nen7h5rs] {
  grid-area: 1 / 1;
  width: auto;
  height: 2.75rem;
  display: block;
  object-fit: contain;
  transition: opacity .2s var(--ease-out);
}

.mark__img--light[data-astro-cid-nen7h5rs] {
  opacity: 0;
}

.hdr--overlay[data-astro-cid-nen7h5rs].is-clear .mark__img--dark[data-astro-cid-nen7h5rs] {
  opacity: 0;
}

.hdr--overlay[data-astro-cid-nen7h5rs].is-clear .mark__img--light[data-astro-cid-nen7h5rs] {
  opacity: 1;
}

@media (width <= 26rem) {
  .mark__img[data-astro-cid-nen7h5rs] {
    height: 2.5rem;
    object-fit: cover;
    object-position: left center;
    width: 3.25rem;
  }
}

.nav[data-astro-cid-nen7h5rs] {
  display: none;
  margin-inline-end: auto;
}

.nav__list[data-astro-cid-nen7h5rs] {
  display: flex;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
}

.nav__link[data-astro-cid-nen7h5rs] {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding-inline: var(--space-3);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: color var(--duration) var(--ease-out);
}

.nav__link[data-astro-cid-nen7h5rs]:after {
  content: "";
  position: absolute;
  left: var(--space-3);
  right: var(--space-3);
  bottom: .5rem;
  height: 2px;
  border-radius: 2px;
  background: var(--accent-fill);
  transform: scaleX(0);
  transition: transform var(--duration) var(--ease-out);
}

.nav__link[data-astro-cid-nen7h5rs]:hover {
  color: var(--text-primary);
}

.nav__link[data-astro-cid-nen7h5rs]:hover:after {
  transform: scaleX(1);
}

.nav__link[data-astro-cid-nen7h5rs][aria-current="page"] {
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
}

.nav__link[data-astro-cid-nen7h5rs][aria-current="page"]:after {
  transform: scaleX(1);
}

.hdr__actions[data-astro-cid-nen7h5rs] {
  display: none;
  align-items: center;
  gap: var(--space-2);
}

.menu[data-astro-cid-nen7h5rs] {
  position: relative;
}

.menu__trigger[data-astro-cid-nen7h5rs] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap-min);
  padding-inline: var(--space-3);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-sm);
  transition: color var(--duration) var(--ease-out);
}

.menu__trigger[data-astro-cid-nen7h5rs]::-webkit-details-marker {
  display: none;
}

.menu__trigger[data-astro-cid-nen7h5rs]:hover {
  color: var(--text-primary);
}

.menu__trigger[data-astro-cid-nen7h5rs] svg[data-astro-cid-nen7h5rs] {
  transition: transform var(--duration) var(--ease-out);
}

.menu[data-astro-cid-nen7h5rs][open] .menu__trigger[data-astro-cid-nen7h5rs] svg[data-astro-cid-nen7h5rs] {
  transform: rotate(180deg);
}

.menu__panel[data-astro-cid-nen7h5rs], .burger__panel[data-astro-cid-nen7h5rs] {
  --text-primary: #13181f;
  --text-secondary: #57626f;
}

.menu__panel[data-astro-cid-nen7h5rs] {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  width: 18rem;
  padding: var(--space-2);
  background: var(--sp-card);
  border: 1px solid var(--sp-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-float);
  animation: menu-in var(--duration) var(--ease-out) both;
}

@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(-.375rem);
  }
}

.menu__item[data-astro-cid-nen7h5rs] {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--sp-ink);
  transition: background-color var(--duration) var(--ease-out);
}

.menu__item[data-astro-cid-nen7h5rs]:hover {
  background: var(--accent-wash);
}

.menu__text[data-astro-cid-nen7h5rs] strong[data-astro-cid-nen7h5rs] {
  display: block;
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
}

.menu__text[data-astro-cid-nen7h5rs] small[data-astro-cid-nen7h5rs] {
  display: block;
  font-size: var(--text-label);
  color: var(--sp-ink-2);
  margin-top: 2px;
}

.menu__dot[data-astro-cid-nen7h5rs] {
  width: .625rem;
  height: .625rem;
  border-radius: 50%;
  margin-top: .3rem;
  flex: none;
}

.menu__dot--customer[data-astro-cid-nen7h5rs] {
  background: var(--sp-orange-core);
}

.menu__dot--partner[data-astro-cid-nen7h5rs] {
  background: var(--sp-blue-core);
}

.burger[data-astro-cid-nen7h5rs] {
  margin-inline-start: auto;
}

.burger__trigger[data-astro-cid-nen7h5rs] {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-sm);
}

.burger__trigger[data-astro-cid-nen7h5rs]::-webkit-details-marker {
  display: none;
}

.burger__bars[data-astro-cid-nen7h5rs] {
  display: grid;
  gap: 4px;
  width: 20px;
}

.burger__bars[data-astro-cid-nen7h5rs] i[data-astro-cid-nen7h5rs] {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: var(--text-primary);
  transition: transform var(--duration) var(--ease-out), opacity var(--duration) var(--ease-out);
}

.burger[data-astro-cid-nen7h5rs][open] .burger__bars[data-astro-cid-nen7h5rs] i[data-astro-cid-nen7h5rs]:first-child {
  transform: translateY(6px) rotate(45deg);
}

.burger[data-astro-cid-nen7h5rs][open] .burger__bars[data-astro-cid-nen7h5rs] i[data-astro-cid-nen7h5rs]:nth-child(2) {
  opacity: 0;
}

.burger[data-astro-cid-nen7h5rs][open] .burger__bars[data-astro-cid-nen7h5rs] i[data-astro-cid-nen7h5rs]:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.burger__panel[data-astro-cid-nen7h5rs] {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  padding: var(--space-4) var(--gutter) var(--space-6);
  background: var(--sp-card);
  border-bottom: 1px solid var(--sp-line);
  box-shadow: var(--shadow-float);
  max-height: calc(100dvh - 4.5rem);
  overflow-y: auto;
  animation: menu-in var(--duration) var(--ease-out) both;
}

.burger__list[data-astro-cid-nen7h5rs] {
  margin: 0 0 var(--space-4);
  padding: 0;
}

.burger__link[data-astro-cid-nen7h5rs] {
  display: flex;
  align-items: center;
  min-height: var(--tap-row);
  font-size: var(--text-lead);
  font-weight: var(--weight-semibold);
  color: var(--sp-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--sp-line);
}

.burger__link[data-astro-cid-nen7h5rs][aria-current="page"] {
  color: var(--accent-text);
}

.burger__actions[data-astro-cid-nen7h5rs] {
  display: grid;
  gap: var(--space-3);
}

@media (width >= 64rem) {
  .nav[data-astro-cid-nen7h5rs], .hdr__actions[data-astro-cid-nen7h5rs] {
    display: flex;
  }

  .burger[data-astro-cid-nen7h5rs] {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mark[data-astro-cid-nen7h5rs]:hover {
    transform: none;
  }

  .nav__link[data-astro-cid-nen7h5rs]:after {
    transition: none;
  }
}
.ft[data-astro-cid-jo6i4kqk] {
  background: var(--sp-night);
  color: var(--text-primary);
  padding-block: var(--space-8) var(--space-5);
}

.ft__inner[data-astro-cid-jo6i4kqk], .ft__base[data-astro-cid-jo6i4kqk] {
  max-width: var(--width-content);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.ft__inner[data-astro-cid-jo6i4kqk] {
  display: grid;
  gap: var(--space-7);
}

.mark[data-astro-cid-jo6i4kqk] {
  display: inline-block;
  text-decoration: none;
}

.mark__img[data-astro-cid-jo6i4kqk] {
  width: 13.5rem;
  height: auto;
  aspect-ratio: 248 / 62;
}

.ft__line[data-astro-cid-jo6i4kqk] {
  margin-top: var(--space-3);
  max-width: 34ch;
  color: var(--text-secondary);
  font-size: var(--text-small);
}

.ft__cols[data-astro-cid-jo6i4kqk] {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(2, 1fr);
}

.ft__title[data-astro-cid-jo6i4kqk] {
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: var(--space-3);
}

.ft__col[data-astro-cid-jo6i4kqk] ul[data-astro-cid-jo6i4kqk] {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ft__col[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk], .ft__legal[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk] {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  font-size: var(--text-small);
  color: var(--text-secondary);
  text-decoration: none;
  transition: color var(--duration) var(--ease-out);
}

.ft__col[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk]:hover, .ft__legal[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk]:hover {
  color: var(--text-primary);
}

.ft__base[data-astro-cid-jo6i4kqk] {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--surface-border);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

.ft__copy[data-astro-cid-jo6i4kqk] {
  font-size: var(--text-label);
  color: var(--text-tertiary);
}

.ft__attr[data-astro-cid-jo6i4kqk] {
  flex-basis: 100%;
  order: 3;
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .2rem;
  font-size: .6875rem;
  line-height: 1.5;
  color: var(--text-tertiary);
}

.ft__attr[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk] {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}

.ft__attr[data-astro-cid-jo6i4kqk] a[data-astro-cid-jo6i4kqk]:hover {
  color: var(--text-secondary);
}

.ft__legal[data-astro-cid-jo6i4kqk] {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
}

@media (width >= 48rem) {
  .ft__cols[data-astro-cid-jo6i4kqk] {
    grid-template-columns: repeat(4, 1fr);
  }
}

@media (width >= 64rem) {
  .ft__inner[data-astro-cid-jo6i4kqk] {
    grid-template-columns: 1fr 2.2fr;
    gap: var(--space-9);
  }
}
.container[data-astro-cid-a2ejnpan] {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--content[data-astro-cid-a2ejnpan] {
  max-width: var(--width-content);
}

.container--narrow[data-astro-cid-a2ejnpan] {
  max-width: var(--width-narrow);
}

.container--prose[data-astro-cid-a2ejnpan] {
  max-width: var(--width-prose);
}
.section[data-astro-cid-rnebiyh6] {
  padding-block: var(--section-y);
  background: var(--section-bg);
  color: var(--text-primary);
}

.section--flush[data-astro-cid-rnebiyh6] {
  padding-block: 0;
}

.section--card[data-astro-cid-rnebiyh6] {
  --section-bg: var(--sp-card);
}

.section--paper[data-astro-cid-rnebiyh6] {
  --section-bg: var(--sp-paper);
}

.section--night[data-astro-cid-rnebiyh6] {
  --section-bg: var(--sp-night);
}
