/* @bydefaultstudio/design-system v2.2.1 */
/* ─────────────────────────────
   DESIGN SYSTEM FRAMEWORK
   ───────────────────────────── */


/* ------ 1. BRAND TOKENS ------ */

/*
 * Neutral engine defaults. A brand expresses itself by overriding these
 * primitives in its theme.css (cms/brands/<brand>/assets/theme.css);
 * the §2 semantic layer resolves through them, so a theme never restates
 * semantics it can reach through a primitive. Instance 0 (By Default)
 * loads cms/brands/bydefault/assets/theme.css like any other brand.
 * Neutralize values here, never delete token names: core components and
 * docs-site.css consume them by name.
 */

:root {
  /* -- Typography (neutral system stacks) -- */
  --font-primary: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-secondary: Georgia, "Times New Roman", serif;
  --font-tertiary: system-ui, sans-serif;
  --font-quaternary: ui-monospace, "SF Mono", Menlo, monospace;

  /* Accent + semantic aliases. Editorial + code alias the existing slots
     so call sites can stay role-named even if the underlying face is
     swapped later. */
  --font-display:   system-ui, sans-serif;
  --font-playful:   system-ui, sans-serif;
  --font-script:    cursive;
  --font-editorial: var(--font-secondary);
  --font-code:      var(--font-quaternary);

  /* -- Palette -- */
  --off-white: var(--neutral-50);
  --warm-white: var(--neutral-100);
  --warm-black: var(--neutral-950);
  --off-black: var(--neutral-900);

  /* -- Accent colours (generic, semantically hued) -- */
  --red-lighter: #FEE2E2;
  --red-light: #FECACA;
  --red: #DC2626;
  --red-dark: #7F1D1D;
  --blue-lighter: #DBEAFE;
  --blue-light: #BFDBFE;
  --blue: #2563EB;
  --blue-dark: #1E3A8A;
  --yellow-lighter: #FEF3C7;
  --yellow-light: #FDE68A;
  --yellow: #D97706;
  --yellow-dark: #78350F;
  --green-lighter: #DCFCE7;
  --green-light: #BBF7D0;
  --green: #16A34A;
  --green-dark: #14532D;
  --purple-lighter: #F3E8FF;
  --purple-light: #E9D5FF;
  --purple: #9333EA;
  --purple-dark: #581C87;
  /* -- Base font sizes (rem-based, progressive step scale: +2px body, +4px heading, +8px display) -- */
  --font-3xs: 0.625rem;  /* 10px */
  --font-2xs: 0.75rem;   /* 12px */
  --font-xs: 0.875rem;   /* 14px */
  --font-s: 1rem;        /* 16px */
  --font-m: 1.125rem;    /* 18px */
  --font-l: 1.25rem;     /* 20px */
  --font-xl: 1.375rem;   /* 22px */
  --font-2xl: 1.5rem;    /* 24px */
  --font-3xl: 1.75rem;   /* 28px */
  --font-4xl: 2rem;      /* 32px */
  --font-5xl: 2.25rem;   /* 36px */
  --font-6xl: 2.5rem;    /* 40px */
  --font-7xl: 3rem;      /* 48px */
  --font-8xl: 3.5rem;    /* 56px */
  --font-9xl: 4rem;      /* 64px */
  --font-10xl: 4.5rem;   /* 72px */


  /* -- UI font sizes -- */

  /* -- Line height tokens -- */
  --line-height-xs: 0.7;
  --line-height-s: 1;
  --line-height-m: 1.2;
  --line-height-l: 1.4;
  --line-height-xl: 1.6;
  --line-height-2xl: 1.8;

  /* -- Font weight tokens -- */
  --font-weight-light: 300;
  --font-weight-regular: 400;
  --font-weight-book: 450;
  --font-weight-medium: 500;
  --font-weight-semi-bold: 600;
  --font-weight-bold: 700;
  --font-weight-extra-bold: 800;
  --font-weight-black: 900;

  /* -- Font width tokens (wdth axis, applied via font-stretch) -- */
  --font-condensed: 75%;
  --font-narrow:    87.5%;
  --font-normal:    100%;
  --font-wide:      112.5%;
  --font-expanded:  125%;

  /* -- Letter spacing tokens (em-based for proportional scaling) -- */
  --letter-spacing-xs: -0.03em;
  --letter-spacing-s: 0.03em;
  --letter-spacing-m: 0.06em;
  --letter-spacing-l: 0.12em;
  --letter-spacing-xl: 0.24em;

  /* -- Type roles — semantic tokens composing the primitives into four
     role-based building blocks (headline, title, label, body). Each role
     covers four dimensions: size, weight, leading (line-height), and
     tracking (letter-spacing).

     Sizes are stepped rem, never clamp() with a vw term: a vw component in
     font-size doesn't track browser zoom or user font-size preferences
     (WCAG 1.4.4 Resize Text). Each role steps down through the width tiers
     below this block. -- */

  /* Headline — the biggest thing on a page; one per page (h1). */
  --headline-size:     var(--font-8xl);  /* 56px · 48px ≤1439 · 28px ≤959 */
  --headline-weight:   400;
  --headline-leading:  var(--line-height-s);
  --headline-tracking: -0.04em;
  --headline-width: var(--font-condensed);

  /* Subline — sub-heading scale, sits between title and body. Independent
     of --text-size-l so it can be tuned without dragging modifier text. */
  --subline-size:    var(--font-2xl);    /* 24px · 20px ≤1439 */
  --subline-weight:  300;


  /* Title — section heads and recurring labels within a page (h2). */
  --title-size:     var(--font-6xl);     /* 40px · 36px ≤1439 · 24px ≤959 */
  --title-weight:   400;
  --title-leading:  var(--line-height-m);
  --title-tracking: -0.04em;
  --title-family: var(--font-primary);


  /* Label — meta rows, eyebrows, captions */
  --label-size:     var(--font-2xs);
  --label-weight:   500;
  --label-leading:  var(--line-height-s);
  --label-tracking: var(--letter-spacing-m);

  /* Body — running text. One size at every width: the old fluid ceiling
     (18px) only engaged beyond ~1900px viewports, so 16px is the honest
     static value. */
  --body-size:     var(--font-s);
  --body-weight:   var(--font-weight-regular);
  --body-leading:  var(--line-height-xl);
  --body-tracking: 0;

  /* Text size utility scale — stepped tokens consumed by .text-size-* utilities.
     Use these on any selector when you want a utility-style size without the class. */
  --text-size-xl: var(--font-3xl);       /* 28px · 24px ≤959 */
  --text-size-l:  var(--font-l);         /* 20px */
  --text-size-m:  var(--body-size);
  --text-size-s:  var(--font-xs);        /* 14px — the old fluid ceiling (16px)
                                            only engaged beyond ~1400px */
  --text-size-xs: var(--font-xs);

  /* Icon Size */
  --icon-size: 1.3rem;

}

/* Laptop typography tier — the top-of-scale sizes are reserved for wide
   screens; below 1440 the three heading roles step down one rung. */
@media (max-width: 1439px) {
  :root {
    --headline-size:  var(--font-7xl);   /* 48px */
    --title-size:     var(--font-5xl);   /* 36px */
    --subline-size:   var(--font-l);     /* 20px */
  }
}

/* Mobile typography tier — static rem values for the single-column range.
   Tablet uses mobile typography because the layout is also single-column
   at that width (see [data-grid] collapse at the same breakpoint).

   --label-size is bumped from --font-2xs (12px) to --font-xs (14px) on
   mobile — 12px is below the practitioner floor for body-adjacent text
   and tap-target-adjacent labels. */
@media (max-width: 959px) {
  :root {
    --headline-size:  var(--font-3xl);   /* 28px */
    --title-size:     var(--font-2xl);   /* 24px */
    --subline-size:   var(--font-l);     /* 20px */
    --label-size:     var(--font-xs);    /* 14px (a11y floor) */

    --text-size-xl:   var(--font-2xl);   /* 24px */
    --text-size-l:    var(--font-l);     /* 20px */
    /* --body-size/--text-size-m (16px) and --text-size-s/-xs (14px)
       hold their size at every width */
  }
}

/* ------ 2. SYSTEM TOKENS - COLORS ------ */

:root {
  /* -- Neutrals -- */
  --neutral-50:  #fafafa;
  --neutral-100: #e5e5e5;
  --neutral-150: #d4d4d4;
  --neutral-200: #c4c4c4;
  --neutral-300: #a3a3a3;
  --neutral-400: #8a8a8a;
  --neutral-500: #737373;
  --neutral-600: #5c5c5c;
  --neutral-700: #474747;
  --neutral-800: #333333;
  --neutral-900: #1f1f1f;
  --neutral-950: #141414;
  --neutral-990: #0a0a0a;

  /* -- Black & White Alpha Tokens -- */
  --black: #000000;
  --black-alpha-3: #00000008;
  --black-alpha-5: #0000000d;
  --black-alpha-7: #00000012;
  --black-alpha-10: #0000001a;
  --black-alpha-15: #00000026;
  --black-alpha-20: #00000033;
  --black-alpha-30: #0000004d;
  --black-alpha-40: #00000066;
  --black-alpha-50: #00000080;
  --black-alpha-60: #00000099;
  --black-alpha-70: #000000b3;
  --black-alpha-80: #000000cc;
  --black-alpha-90: #000000e6;
  --black-alpha-95: #000000f2;

  --white: #ffffff;
  --white-alpha-3: #ffffff08;
  --white-alpha-5: #ffffff0d;
  --white-alpha-7: #ffffff12;
  --white-alpha-10: #ffffff1a;
  --white-alpha-15: #ffffff26;
  --white-alpha-20: #ffffff33;
  --white-alpha-30: #ffffff4d;
  --white-alpha-40: #ffffff66;
  --white-alpha-50: #ffffff80;
  --white-alpha-60: #ffffff99;
  --white-alpha-70: #ffffffb3;
  --white-alpha-80: #ffffffcc;
  --white-alpha-90: #ffffffe6;
  --white-alpha-95: #fffffff2;

  --transparent: transparent;

  /* -- Color-Mix Alpha Scale -- */
  --alpha-5: transparent 95%;
  --alpha-10: transparent 90%;
  --alpha-15: transparent 85%;
  --alpha-20: transparent 80%;
  --alpha-25: transparent 75%;
  --alpha-30: transparent 70%;
  --alpha-35: transparent 65%;
  --alpha-40: transparent 60%;
  --alpha-45: transparent 55%;
  --alpha-50: transparent 50%;
  --alpha-55: transparent 45%;
  --alpha-60: transparent 40%;
  --alpha-65: transparent 35%;
  --alpha-70: transparent 30%;
  --alpha-75: transparent 25%;
  --alpha-80: transparent 20%;
  --alpha-85: transparent 15%;
  --alpha-90: transparent 10%;
  --alpha-95: transparent 5%;

  /* -- Semantic colours -- */
  --text-primary: var(--off-black);
  --text-secondary: var(--neutral-700);
  --text-plain: var(--black);
  /* a11y: alpha-60 → 5.7:1 on white; alpha-50 computed to 3.9:1, below the
     4.5:1 WCAG AA minimum for the body copy this token is used on */
  --text-faded: var(--black-alpha-60);
  --text-accent: var(--blue);
  --text-link: var(--text-accent);
  --text-inverted: var(--off-white);
  --text-sidebar: var(--text-primary);
  --text-top-nav: var(--text-primary);

    /* -- Text with Opacity -- */
  --text-alpha-5: color-mix(in srgb, var(--text-primary), var(--alpha-5));
  --text-alpha-10: color-mix(in srgb, var(--text-primary), var(--alpha-10));
  --text-alpha-15: color-mix(in srgb, var(--text-primary), var(--alpha-15));
  --text-alpha-20: color-mix(in srgb, var(--text-primary), var(--alpha-20));
  --text-alpha-30: color-mix(in srgb, var(--text-primary), var(--alpha-30));
  --text-alpha-40: color-mix(in srgb, var(--text-primary), var(--alpha-40));
  --text-alpha-50: color-mix(in srgb, var(--text-primary), var(--alpha-50));



  --background-primary: var(--white);
  --background-secondary: var(--neutral-100);
  --background-plain: var(--white);
  --background-faded: var(--black-alpha-5);
  --background-darker: var(--black-alpha-10);
  --background-lighter: var(--white-alpha-10);
  --bg-faded-3: var(--black-alpha-3);
  --bg-faded-5: var(--black-alpha-5);
  --bg-faded-7: var(--black-alpha-7);
  --bg-faded-10: var(--black-alpha-10);
  --bg-faded-15: var(--black-alpha-15);
  --background-modal: rgba(0, 0, 0, 0.75);
  --background-sidebar: var(--background-primary);
  --background-top-nav: var(--background-primary);

  /* -- Solid colour backgrounds — for hero blocks, callouts, ad units, etc. -- */
  --background-accent: var(--text-accent);
  --background-black: var(--black);
  --background-white: var(--white);
  --background-blue: var(--blue);
  --background-red: var(--red);
  --background-green: var(--green);

  --border-primary: var(--text-primary);
  --border-secondary: var(--neutral-300);
  --border-faded: var(--black-alpha-15);


  /* -- Status colours (from brand book or defaults) -- */
  --status-info: var(--blue);
  --status-info-bg: var(--blue-lighter);
  --status-success: var(--green);
  --status-success-bg: var(--green-lighter);
  --status-warning: var(--yellow-dark);
  --status-warning-bg: var(--yellow-lighter);
  --status-danger: var(--red);
  --status-danger-bg: var(--red-lighter);
  /* -- Form semantic tokens -- */
  --input-border: var(--border-secondary);
  --input-background: var(--black-alpha-5);
  --input-text: var(--text-plain);
  --input-placeholder: var(--text-faded);
  --input-focus: var(--text-accent);
  --input-disabled-bg: var(--background-faded);
  --input-disabled-text: var(--text-faded);
  --checkbox-background: var(--neutral-100);
  --checkbox-selected: var(--text-primary);
  --checkbox-border: var(--border-faded);
  --checkbox-checkmark: var(--off-white);
  /* -- Toggle color tokens removed — uses values directly on component -- */

  /* -- Selection -- */
  --selection-text: var(--background-primary);
  --selection-background: var(--text-primary);

  /* -- Card tokens removed — uses semantic tokens directly -- */

  /* -- Tooltip tokens removed — uses values directly on component -- */

  /* -- Toast tokens removed — uses values directly on component -- */

  /* -- Tab tokens removed — uses semantic tokens directly -- */

  /* -- Progress tokens removed — uses semantic tokens directly -- */

  /* -- Divider tokens -- */
  --divider-color: var(--border-faded);
  --divider-thickness: var(--border-s);
  --divider-spacing: var(--space-xl);

  /* -- Dropdown tokens -- */
  --dropdown-background: var(--background-primary);
  --dropdown-border: var(--border-faded);
  --dropdown-item-hover: var(--background-faded);

  /* -- Tag tokens removed — uses semantic tokens directly -- */

  /* -- Dialog tokens -- */
  --dialog-max-width: 560px;

  /* -- Slider tokens removed — uses semantic tokens directly -- */

  /* -- Rating tokens -- */
  --rating-size: 1.5rem;
  /* -- Rating color tokens removed — uses values directly on component -- */

  /* -- Mark tokens removed — uses values directly on component -- */

  color-scheme: light;
}

/* ------ 2b. THEME TOKENS - DARK MODE ------ */
/* Set data-theme="dark" on <html> for page-level, or on any element for scoped theming */

[data-theme="dark"] {
  /* -- Text -- */
  --text-primary: #e8e6e3;
  --text-secondary: #a8a5a2;
  --text-plain: #f0eeeb;
  /* a11y: 0.5 → ~5.0:1 on --neutral-900; 0.45 was 4.4:1, marginal for AA */
  --text-faded: rgba(255, 255, 255, 0.5);
  --text-accent: var(--yellow);
  --text-link: var(--text-accent);
  --text-inverted: #1a1a1a;
  --text-sidebar: var(--text-primary);
  --text-top-nav: var(--text-primary);

  /* -- Background -- */
  --background-primary: var(--neutral-900);
  --background-secondary: #222222;
  --background-plain: #2a2a2a;
  --background-faded: rgba(255, 255, 255, 0.06);
  --background-darker: rgba(255, 255, 255, 0.12);
  --background-modal: var(--black-alpha-50);
  --background-sidebar: var(--background-primary);
  --background-top-nav: var(--background-primary);
  --bg-faded-3: var(--white-alpha-3);
  --bg-faded-5: var(--white-alpha-5);
  --bg-faded-7: var(--white-alpha-7);
  --bg-faded-10: var(--white-alpha-10);
  --bg-faded-15: var(--white-alpha-15);

  /* -- Border -- */
  --border-primary: #e8e6e3;
  --border-secondary: #3a3a3a;
  --border-faded: var(--white-alpha-20);

  /* -- Status -- */
  --status-info: var(--blue-light);
  --status-success: var(--green-light);
  --status-warning: var(--yellow-light);
  --status-danger: var(--red-light);

  /* -- Form -- */
  --input-border: #3a3a3a;
  --input-background: rgba(255, 255, 255, 0.08);
  --input-text: #f0eeeb;
  --input-placeholder: rgba(255, 255, 255, 0.45);
  --input-focus: var(--text-accent);
  --input-disabled-bg: rgba(255, 255, 255, 0.06);
  --input-disabled-text: rgba(255, 255, 255, 0.3);
  --checkbox-background: #3a3a3a;
  --checkbox-selected: #e8e6e3;
  --checkbox-border: #555;
  --checkbox-checkmark: #1a1a1a;
  /* -- Toggle/Card/Tooltip/Toast/Dialog/Mark color tokens removed — dark mode handled on components -- */

  /* -- Dropdown -- */
  --dropdown-background: var(--background-plain);

  color-scheme: dark;
}

/* ------ 2c. SYSTEM PREFERENCE FALLBACK (no-JS) ------ */
/* Applies dark tokens when the user's OS prefers dark and no data-theme is set */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --text-primary: #e8e6e3;
    --text-secondary: #a8a5a2;
    --text-plain: #f0eeeb;
    --text-faded: rgba(255, 255, 255, 0.5); /* AA — see [data-theme="dark"] above */
    --text-accent: var(--yellow);
    --text-link: var(--text-accent);
    --text-inverted: #1a1a1a;
    --text-sidebar: var(--text-primary);
    --text-top-nav: var(--text-primary);

    --background-primary: var(--neutral-900);
    --background-secondary: #222222;
    --background-plain: #2a2a2a;
    --background-faded: rgba(255, 255, 255, 0.06);
    --background-darker: rgba(255, 255, 255, 0.12);
    --background-modal: var(--black-alpha-50);
    --background-sidebar: var(--background-primary);
    --background-top-nav: var(--background-primary);
    --bg-faded-3: var(--white-alpha-3);
    --bg-faded-5: var(--white-alpha-5);
    --bg-faded-7: var(--white-alpha-7);
    --bg-faded-10: var(--white-alpha-10);
    --bg-faded-15: var(--white-alpha-15);

    --border-primary: #e8e6e3;
    --border-secondary: #3a3a3a;
    --border-faded: var(--white-alpha-20);

    --status-info: var(--blue-light);
    --status-success: var(--green-light);
    --status-warning: var(--yellow-light);
    --status-danger: var(--red-light);

    --input-border: #3a3a3a;
    --input-background: rgba(255, 255, 255, 0.08);
    --input-text: #f0eeeb;
    --input-placeholder: rgba(255, 255, 255, 0.45);
    --input-focus: var(--text-accent);
    --input-disabled-bg: rgba(255, 255, 255, 0.06);
    --input-disabled-text: rgba(255, 255, 255, 0.3);
    --checkbox-background: #3a3a3a;
    --checkbox-selected: #e8e6e3;
    --checkbox-border: #555;
    --checkbox-checkmark: #1a1a1a;
    /* -- Toggle/Card/Tooltip/Toast/Dialog/Mark color tokens removed — dark mode handled on components -- */

    /* -- Dropdown -- */
    --dropdown-background: var(--background-plain);

    color-scheme: dark;
  }
}

/* -- Selection highlight -- */
::selection {
  color: var(--selection-text);
  background-color: var(--selection-background);
}

/* ------ 3. SYSTEM TOKENS - SPACING & TYPOGRAPHY ------ */

:root {
  /* -- Unit tokens -- */
  --none: 0;
  --2xs: 0.125rem;
  /* 2px */
  --xs: 0.25rem;
  /* 4px */
  --s: 0.5rem;
  /* 8px */
  --m: 0.75rem;
  /* 12px */
  --l: 1rem;
  /* 16px */
  --xl: 1.5rem;
  /* 24px */
  --2xl: 2rem;
  /* 32px */
  --3xl: 2.5rem;
  /* 40px */
  --4xl: 3rem;
  /* 48px */
  --5xl: 3.5rem;
  /* 56px */
  --6xl: 4rem;
  /* 64px */
  --7xl: 4.5rem;
  /* 72px */
  --8xl: 5rem;
  /* 80px */
  --9xl: 5.5rem;
  /* 88px */
  --10xl: 6rem;
  /* 96px */
  --11xl: 6.5rem;
  /* 104px */
  --12xl: 7rem;
  /* 112px */
  --13xl: 7.5rem;
  /* 120px */
  --14xl: 10rem;
  /* 160px */

  /* -- Spacing scale -- */
  --space-none: var(--none); /* 0 */
  --space-2xs: var(--2xs); /* 2px */
  --space-xs: var(--xs); /* 4px */
  --space-s: var(--s); /* 8px */
  --space-m: var(--m); /* 12px */
  --space-l: var(--l); /* 16px */
  --space-xl: var(--xl); /* 24px */
  --space-2xl: var(--2xl); /* 32px */
  --space-3xl: var(--3xl); /* 40px */
  --space-4xl: var(--4xl); /* 48px */
  --space-5xl: var(--5xl); /* 56px */
  --space-6xl: var(--6xl); /* 64px */
  --space-7xl: var(--7xl); /* 72px */
  --space-8xl: var(--8xl); /* 80px */
  --space-9xl: var(--9xl); /* 88px */
  --space-10xl: var(--10xl); /* 96px */
  --space-11xl: var(--11xl); /* 104px */
  --space-12xl: var(--12xl); /* 112px */
  --space-13xl: var(--13xl); /* 120px */
  --space-14xl: var(--14xl); /* 160px */

  /* -- Container widths -- */
  --container-xs: 480px;
  --container-s: 640px;
  --container-m: 960px;
  --container-l: 1200px;
  --container-xl: 1440px;

  /* -- Max-widths -- */
  --max-width-xs: 480px;
  --max-width-s: 640px;
  --max-width-m: 960px;
  --max-width-l: 1200px;
  --max-width-xl: 1440px;

  /* -- Line length (typographic readability, 45–75ch range) -- */
  --line-length-headline: 22ch;
  --line-length-body: 55ch;

  --line-length-xsmall: 35ch;
  --line-length-small: 45ch;
  --line-length-medium: 65ch;
  --line-length-wide: 75ch;

  /* -- Section spacing variables -- */
  --section-xs: var(--space-xl);
  --section-s: var(--space-2xl);
  --section-m: var(--space-6xl);
  --section-l: var(--space-10xl);
  --section-xl: var(--space-14xl);


  /* -- Accordion spacing variables -- */
  --accordion-padding-x: var(--space-l);
  --accordion-padding-y: var(--space-l);

  /* -- Border width tokens -- */
  --border-s: 0.0625rem;  /* 1px */
  --border-m: 0.125rem;   /* 2px */
  --border-l: 0.25rem;    /* 4px */

  /* -- Border composition variables -- */
  --border-width: var(--border-s);
  --border-style: solid;
  --border-color: var(--border-primary);

  /* -- Border radius tokens -- */
  --radius-2xs: 2px;
  --radius-xs: 4px;
  --radius-s: 6px;
  --radius-m: 10px;
  --radius-l: 16px;
  --radius-xl: 24px;
  --radius-pill: 999px;
}

/* ------ 4. SYSTEM TOKENS - MOTION ------ */
/*
 * Motion design tokens. Two layers, same model as color and spacing:
 *
 *   1. Primitives (--ease-*, --duration-*) — raw building blocks. Same
 *      t-shirt scale as the rest of the design system. Easing names match
 *      the standard CSS keywords (in / out / in-out) so anyone with web
 *      experience already knows what shape they have; the cubic-bezier
 *      values are our refined replacements for the defaults.
 *
 *   2. Semantic tokens (--motion-*) — named by intent ("page-open",
 *      "page-close"). These compose primitives. Consumers (CSS components,
 *      JS code) only ever read the semantic layer.
 *
 * Naming convention for new semantic tokens:
 *   --motion-{scope}-{event}-{property}
 *   scope    = page | surface | element | feedback
 *   event    = open | close | swap | enter | exit | fade | hover | press
 *   property = duration | easing
 *
 * See cms/motion.md for the full reference and demos.
 */

:root {
  /* -- Easing primitives -- */
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  /* fast start, slow end. for exits. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  /* slow start, slow end with long tail. for entrances. */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  /* symmetric. for swaps and continuous motion. */
  --ease-emphasized: cubic-bezier(0.86, 0, 0.07, 1);
  /* steeper symmetric curve — near-still start and end, fast middle.
     for large layout shifts that should feel decisive (panel collapse,
     sidebar toggle, stage transforms). */

  /* -- Duration primitives -- */
  --duration-2xs: 100ms;
  --duration-xs: 200ms;
  --duration-s: 400ms;
  --duration-m: 600ms;
  --duration-l: 800ms;
  --duration-xl: 1200ms;
  --duration-2xl: 1500ms;
  --duration-3xl: 1800ms;
  --duration-4xl: 2000ms;
  --duration-5xl: 2500ms;
  --duration-6xl: 3000ms;
  --duration-7xl: 4000ms;
  --duration-8xl: 6000ms;

  /* -- Stagger offset — per-item delay step for sequenced groups (list
     items, grid cards). A delay increment, not an animation duration. -- */
  --duration-stagger: 30ms;


  /* -- Page-level semantic motion -- */
  --motion-page-open-duration: var(--duration-xl);
  /* 1200ms */
  --motion-page-open-easing: var(--ease-in-out);

  --motion-page-close-duration: var(--duration-xl);
  /* 1200ms */
  --motion-page-close-easing: var(--ease-in-out);

  --motion-page-swap-duration: var(--duration-xl);
  /* 1200ms */
  --motion-page-swap-easing: var(--ease-in-out);

  --motion-page-fade-duration: var(--duration-m);
  /* 600ms */
  --motion-page-fade-easing: var(--ease-in-out);
}

/* ------ 5. LAYOUT PRIMITIVES ------ */

/* -- Global horizontal padding -- */
.padding-global {
  padding-left: var(--space-xl);
  padding-right: var(--space-xl);
}

/* -- Padding utilities -- */
.padding-s {
  padding: var(--space-s);
}

.padding-m {
  padding: var(--space-m);
}

.padding-l {
  padding: var(--space-l);
}

.padding-xl {
  padding: var(--space-xl);
}

.padding-2xl {
  padding: var(--space-2xl);
}

.padding-3xl {
  padding: var(--space-3xl);
}

/* -- Containers -- */
.container-xs {
  display: block;
  max-width: var(--container-xs);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container-s {
  display: block;
  max-width: var(--container-s);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container-m {
  display: block;
  max-width: var(--container-m);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container-l {
  display: block;
  max-width: var(--container-l);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container-xl {
  display: block;
  max-width: var(--container-xl);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* -- Max-width utilities -- */
.max-width-xs {
  max-width: var(--max-width-xs);
}

.max-width-s {
  max-width: var(--max-width-s);
}

.max-width-m {
  max-width: var(--max-width-m);
}

.max-width-l {
  max-width: var(--max-width-l);
}

.max-width-xl {
  max-width: var(--max-width-xl);
}

.max-width-full {
  max-width: 100%;
}

/* -- Section spacing -- */

section {
  display: block;
}

.padding-section {
  display: block;
}

/* -- Top spacing combo classes -- */
.top-small {
  padding-top: var(--section-s);
}

.top-medium {
  padding-top: var(--section-m);
}

.top-large {
  padding-top: var(--section-l);
}

.top-xl {
  padding-top: var(--section-xl);
}

/* -- Bottom spacing combo classes -- */
.bottom-small {
  padding-bottom: var(--section-s);
}

.bottom-medium {
  padding-bottom: var(--section-m);
}

.bottom-large {
  padding-bottom: var(--section-l);
}

.bottom-xl {
  padding-bottom: var(--section-xl);
}

/* ------ 6. BLOCKS ------ */

.block {
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
}

/* -- Child margin reset --
   gap-* is the sole source of vertical spacing inside a block: element
   defaults (headings, p, lists, figure…) are zeroed so gap and margin never
   compound — flex gap does not collapse with margins, it adds to them.
   margin-block only: margin-inline auto must survive for data-align="center".
   Component classes that set their own root margins (e.g. .callout) are
   declared later in the cascade and keep them inside blocks. */
.block > * {
  margin-block: 0;
}

/* -- Gap modifiers -- */
.gap-none {
  gap: var(--space-none);
}

.gap-xs {
  gap: var(--space-xs) !important;
}

.gap-s {
  gap: var(--space-s) !important;
}

.gap-m {
  gap: var(--space-m) !important;
}

.gap-l {
  gap: var(--space-l) !important;
}

.gap-xl {
  gap: var(--space-xl) !important;
}

.gap-2xl {
  gap: var(--space-2xl) !important;
}

.gap-3xl {
  gap: var(--space-3xl) !important;
}


/* -- Layout modifiers -- */
.row {
  flex-direction: row;
}

.row-reverse {
  flex-direction: row-reverse;
}

.align-start {
  align-items: flex-start;
}

.align-center {
  align-items: center;
}

.align-end {
  align-items: flex-end;
}

.align-stretch {
  align-items: stretch;
}

.justify-center {
  justify-content: center;
}

.justify-end {
  justify-content: flex-end;
}

.overflow-hidden {
  overflow: hidden;
}


/* -- Self alignment -- */
[data-align="center"] {
  margin-inline: auto;
  justify-self: center;
}


/* ------ 7. GRID ------ */

/* -- Grid -- */
.grid {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: 1fr 1fr;
  grid-auto-columns: 1fr;
}

/* -- Grid column modifiers -- */
.cols-2 {
  grid-template-columns: 1fr 1fr;
}

.cols-3 {
  grid-template-columns: 1fr 1fr 1fr;
}

.cols-4 {
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

/* -- Responsive collapse -- */
@media (max-width: 768px) {
  .grid {
    grid-template-columns: 1fr;
  }
}

.token-col {
  grid-template-columns: 1fr auto;
  padding: var(--space-m);
}

/* -- Grid item width modifiers -- */
.fit-content {
  width: fit-content;
}

/* ------ 8. BORDER UTILITIES ------ */

/* -- Structural classes -- */
.border {
  border: var(--border-width) var(--border-style) var(--border-color);
}

.border-top {
  border-top: var(--border-width) var(--border-style) var(--border-color);
}

.border-bottom {
  border-bottom: var(--border-width) var(--border-style) var(--border-color);
}

.border-left {
  border-left: var(--border-width) var(--border-style) var(--border-color);
}

.border-right {
  border-right: var(--border-width) var(--border-style) var(--border-color);
}

/* -- Width combo classes -- */
.border-s {
  --border-width: var(--border-s);
}

.border-m {
  --border-width: var(--border-m);
}

.border-l {
  --border-width: var(--border-l);
}

/* -- Style combo classes -- */
.border-solid {
  --border-style: solid;
}

.border-dashed {
  --border-style: dashed;
}

.border-dotted {
  --border-style: dotted;
}

/* -- Color combo classes -- */
.border-primary {
  --border-color: var(--border-primary);
}

.border-secondary {
  --border-color: var(--border-secondary);
}

.border-faded {
  --border-color: var(--border-faded);
}

/* ------ 9. TYPOGRAPHY UTILITIES ------ */

/* -- Font size utilities -- */

.font-primary {
font-family: var(--font-primary);
}

.font-secondary {
font-family: var(--font-secondary);
}

/* -- Accent font treatments --
   Apply on spans inside prose, or to retreat a heading into a different
   voice. Each sets family + sensible companion properties (weight,
   tracking, leading where the face needs it). Size stays whatever the
   host element controls. */

.accent-display {
  font-family: var(--font-display);
  letter-spacing: 0;
  text-transform: uppercase;
}

.accent-playful {
  font-family: var(--font-playful);
  font-weight: 700;
  font-style: normal;
}

.accent-script {
  font-family: var(--font-script);
  font-weight: 400;
  line-height: 1.1;
}

.accent-editorial {
  font-family: var(--font-editorial);
  font-weight: 400;
  font-style: italic;
}

.accent-code {
  font-family: var(--font-code);
  font-weight: 400;
}

.font-2xs {
  font-size: var(--font-2xs);
}

.font-xs {
  font-size: var(--font-xs);
}

.font-s {
  font-size: var(--font-s);
}

.font-m {
  font-size: var(--font-m);
}

.font-l {
  font-size: var(--font-l);
}

.font-xl {
  font-size: var(--font-xl);
}

.font-2xl {
  font-size: var(--font-2xl);
}

.font-3xl {
  font-size: var(--font-3xl);
}

.font-4xl {
  font-size: var(--font-4xl);
}

.font-5xl {
  font-size: var(--font-5xl);
}

.font-6xl {
  font-size: var(--font-6xl);
}

.font-7xl {
  font-size: var(--font-7xl);
}

.font-8xl {
  font-size: var(--font-8xl);
}

.font-9xl {
  font-size: var(--font-9xl);
}

.font-10xl {
  font-size: var(--font-10xl);
}

/* -- Text size utilities -- */
/* Each class consumes its matching --text-size-* token (defined in :root). */
/* xs stays fixed at the a11y floor; m reuses --body-size for clean reset.  */

.text-size-xl {
  font-size: var(--text-size-xl);
  line-height: var(--line-height-m);
}

.text-size-l {
  font-size: var(--text-size-l);
  line-height: var(--line-height-l);
}

.text-size-m {
  font-size: var(--text-size-m);
  line-height: var(--line-height-l);
}

.text-size-s {
  font-size: var(--text-size-s);
  line-height: var(--line-height-xl);
}

.text-size-xs {
  font-size: var(--text-size-xs);
  line-height: var(--line-height-xl);
}

/* -- Text wrap utilities -- */
[data-text-wrap="balance"] {
  text-wrap: balance;
}

[data-text-wrap="pretty"] {
  text-wrap: pretty;
}

/* -- Font width utilities -- */
[data-font-width="condensed"] { font-stretch: var(--font-condensed); }
[data-font-width="narrow"]    { font-stretch: var(--font-narrow); }
[data-font-width="normal"]    { font-stretch: var(--font-normal); }
[data-font-width="wide"]      { font-stretch: var(--font-wide); }
[data-font-width="expanded"]  { font-stretch: var(--font-expanded); }

/* -- Text alignment utilities -- */
.text-left   { text-align: left; }
.text-center { text-align: center; }
.text-right  { text-align: right; }

/* -- Eyebrow text -- */
.eyebrow {
  font-size: var(--font-xs);
  line-height: var(--line-height-m);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--letter-spacing-l);
  text-transform: uppercase;
}

/* -- Button reset (bare element) -- */
button {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  cursor: pointer;
  border: none;
  background: none;
  padding: 0;
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: var(--space-s);
  transition: transform var(--duration-2xs) var(--ease-out);
}

/* -- Button component (CUBE pattern) -- */
/* All tokens live at component level. data-* exceptions override them. */

.button,
button.button {
  /* -- Component tokens (overridable by exceptions + role classes) -- */
  --button-color: var(--text-primary);
  --button-faded: color-mix(in srgb, var(--button-color), var(--alpha-10));
  --button-bg: var(--button-color);
  --button-border: var(--button-color);
  --button-text-color: var(--text-inverted);
  --button-font: var(--font-primary);
  --button-text-size: var(--font-m);
  --button-padding-y: var(--space-l);
  --button-padding-x: var(--space-xl);
  --button-gap: var(--space-m);

  /* -- Layout -- */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--button-gap);

  /* -- Box model -- */
  padding: var(--button-padding-y) var(--button-padding-x);

  /* -- Visual -- */
  background-color: var(--button-bg);
  border: var(--border-s) solid var(--button-border);
  border-radius: var(--radius-s);
  

  /* -- Typography -- */
  font-family: var(--button-font);
  font-size: var(--button-text-size);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-xs);
  /* letter-spacing: var(--letter-spacing-s); */
  text-transform: none;
  text-decoration: none;
  color: var(--button-text-color);

  /* -- Icon -- */
  --icon-size: 0.9em;


  /* -- Other -- */
  cursor: pointer;
  transition: background-color var(--duration-m) var(--ease-out), color var(--duration-2xs) var(--ease-out), border-color var(--duration-2xs) var(--ease-out), opacity var(--duration-2xs) var(--ease-out), transform var(--duration-2xs) var(--ease-out);
}

/* -- Hover -- */
.button:hover {
  --button-color: color-mix(in srgb, var(--text-primary), var(--background-primary) 10%)
}

/* -- Active (press) -- */
.button:active {
  transform: scale(0.98);
}

/* -- Variant exceptions -- */

.button[data-variant="outline"] {
  --button-bg: transparent;
  --button-text-color: var(--button-color);
}

.button[data-variant="faded"] {
  --button-bg: var(--button-faded);
  --button-border: transparent;
  --button-text-color: var(--button-color);
}

.button[data-variant="outline-faded"] {
  --button-bg: transparent;
  --button-border: var(--button-faded);
  --button-text-color: var(--button-color);
}

.button[data-variant="transparent"] {
  --button-bg: transparent;
  --button-border: transparent;
  --button-text-color: var(--button-color);
}

.button[data-variant="text"] {
  --button-bg: transparent;
  --button-border: transparent;
  --button-text-color: var(--button-color);
  --button-padding-x: 0;
  --button-padding-y: 0;
}
.button[data-variant="text"]:hover {
  text-decoration: underline;
  text-underline-offset: 2.5px;
}
.button[data-variant="text"]:active {
  transform: none;
}

/* Unfilled variants: subtle fill on hover instead of darkening transparent */
.button[data-variant="outline"]:hover,
.button[data-variant="faded"]:hover,
.button[data-variant="outline-faded"]:hover,
.button[data-variant="transparent"]:hover {
  background-color: color-mix(in srgb, var(--button-color), var(--alpha-5));
}

/* -- Size exceptions -- */

.button[data-size="small"] {
  --button-padding-y: var(--space-s);
  --button-padding-x: var(--space-m);
  --button-text-size: var(--font-xs);
}

.button[data-size="xsmall"] {
  --button-padding-y: var(--space-xs);
  --button-padding-x: var(--space-s);
  --button-text-size: var(--font-2xs);
}

/* -- Boolean modifiers -- */

.button[data-icon-only] {
  --button-padding-x: var(--button-padding-y);
  --icon-size: 1.3rem;
}

.button[data-full-width] {
  width: 100%;
}

/* -- Colour exceptions -- */
/* Semantic names and brand aliases produce identical output.
   --button-color drives bg, border, and faded automatically.

   A colour sets --button-color and nothing else: the text colour belongs to
   the variant. The base already declares --button-text-color: var(--text-inverted),
   which is what a filled button wants, and every unfilled variant re-points it to
   var(--button-color). Restating it here tied those variant rules at (0,2,0) and
   won on source order, so an unfilled button was painted with text meant to sit
   on a fill it does not have — inverted text on a transparent surface, i.e.
   invisible. The role classes below are unaffected either way: .button.close-btn
   re-points --button-text-color itself, and does so later still. */

.button[data-color="danger"],
.button[data-color="red"] {
  --button-color: var(--status-danger);
}

.button[data-color="danger"]:hover,
.button[data-color="red"]:hover {
  --button-color: color-mix(in srgb, var(--status-danger), var(--text-primary) 15%);
}

.button[data-color="success"],
.button[data-color="green"] {
  --button-color: var(--status-success);
}

.button[data-color="success"]:hover,
.button[data-color="green"]:hover {
  --button-color: color-mix(in srgb, var(--status-success), var(--text-primary) 15%);
}

/* -- Role classes -- */
/* Role classes override component tokens only. They never redeclare the base
   structure, so padding, focus ring, sizes and states are inherited intact.
   Must come after the base :hover rule to win on equal specificity.
   Qualified with .button because the base also matches as `button.button`
   (0,1,1) — a bare `.close-btn` (0,1,0) would lose to it on <button>. */

.button.close-btn {
  --button-bg: transparent;
  --button-border: transparent;
  --button-color: var(--text-faded);
  --button-text-color: var(--button-color);
  flex-shrink: 0;
}

.button.close-btn:hover {
  --button-color: var(--text-primary);
  background-color: color-mix(in srgb, var(--button-color), var(--alpha-5));
}

/* data-color has to be re-stated here: .button[data-color] and .button.close-btn
   tie at (0,2,0), and the role class is declared later, so it would win. */
.button.close-btn[data-color="danger"],
.button.close-btn[data-color="red"] {
  --button-color: var(--status-danger);
}

.button.close-btn[data-color="danger"]:hover,
.button.close-btn[data-color="red"]:hover {
  --button-color: var(--status-danger);
  background-color: color-mix(in srgb, var(--status-danger), var(--alpha-10));
}

/* -- States -- */

.button:disabled,
.button.is-disabled {
  opacity: 0.4;
  pointer-events: none;
  cursor: not-allowed;
}

.button.is-loading {
  pointer-events: none;
  opacity: 0.6;
}

/* -- Reduced motion -- */
@media (prefers-reduced-motion: reduce) {
  .button:active {
    transform: none;
  }
}


.svg-icn {
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: var(--icon-size);
  height: var(--icon-size);
  display: flex;
  aspect-ratio: 1 / 1;
  transition: color var(--duration-m) var(--ease-out);
  margin: -0.175em
}

.svg-icn svg,
.svg-icn path {
  transition: fill var(--duration-m) var(--ease-out);
}

.svg-icn.is-preview {
  width: 2.5rem;
  height: 2.5rem;
}

.svg-logo {
  width: 100%;
  max-width: 300px;
  aspect-ratio: 210 / 101;
}

.svg-logo {
  transition: color var(--duration-m) var(--ease-out);
}

.svg-logo svg,
.svg-logo path {
  transition: fill var(--duration-m) var(--ease-out);
}

.button-group {
  grid-column-gap: var(--space-m);
  grid-row-gap: var(--space-m);
  flex-wrap: wrap;
  align-items: center;
  display: flex;
}

/* ------ 10. BACKGROUND UTILITIES ------ */

/* -- Background utilities -- */
.bg-primary {
  background-color: var(--background-primary);
}

.bg-secondary {
  background-color: var(--background-secondary);
}

.bg-plain {
  background-color: var(--background-plain);
}

.bg-faded {
  background-color: var(--background-faded);
}

/* -- Text color utilities -- */
.text-primary {
  color: var(--text-primary);
}

.text-secondary {
  color: var(--text-secondary);
}

.text-plain {
  color: var(--text-plain);
}

.text-faded {
  color: var(--text-faded);
}

.text-accent {
  color: var(--text-accent);
}

.text-link {
  color: var(--text-link);
}


/* -- Global state utilities -- */
.is-hidden {
  display: none !important;
}

/* ------ BASE ELEMENTS ------ */

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

html {
  font-size: 16px;
}

body {
  margin: 0;
  font-family: var(--font-primary);
  color: var(--text-primary);
  font-size: var(--body-size);
  font-weight: var(--body-weight);
  line-height: var(--body-leading);
  letter-spacing: var(--body-tracking);
  background-color: var(--background-primary);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* -- Headings --
   Shared base style for h1–h6: weight, tracking, margins, title family.
   Sizes follow in the editorial scale below. */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-weight: 400;
  letter-spacing: -0.04em;
  margin-top: var(--space-xl);
  margin-bottom: var(--space-l);
  font-family: var(--title-family);
  line-height: var(--line-height-m);

}

/* Progressive editorial scale. Each level is a foundation --font-*
   primitive, one step up from the next level, stepped at the 959px
   breakpoint rather than clamp() so type tracks browser zoom and user
   font-size (WCAG 1.4.4). For hero-scale display type, set font-size to
   --headline-size / --title-size on your own display class instead of
   restyling the elements. */
h1 {
  font-size: var(--font-7xl);  /* 48px · 36px ≤959 */
  line-height: var(--line-height-m);
}

h2 {
  font-size: var(--font-6xl);  /* 40px · 32px ≤959 */
}

h3 {
  font-size: var(--font-5xl);  /* 36px · 28px ≤959 */
}

h4 {
  font-size: var(--font-4xl);  /* 32px · 24px ≤959 */
}

h5 {
  font-size: var(--font-3xl);  /* 28px · 22px ≤959 */
}

h6 {
  font-size: var(--font-2xl);  /* 24px · 20px ≤959 */
  line-height: var(--line-height-l);
}

@media (max-width: 959px) {
  h1 { font-size: var(--font-5xl); }
  h2 { font-size: var(--font-4xl); }
  h3 { font-size: var(--font-3xl); }
  h4 { font-size: var(--font-2xl); }
  h5 { font-size: var(--font-xl); }
  h6 { font-size: var(--font-l); }
}

/* -- Paragraphs -- */
p {
  margin-top: 0;
  margin-bottom: var(--space-m);
}

/* -- Links -- */
a {
  color: var(--text-plain);
  /* text-underline-offset: 0.2em; */
  text-decoration: underline;
  -webkit-text-decoration-color: var(--text-link);
  text-decoration-color: var(--text-link);
  text-decoration-thickness: 0.01em;
  transition: color var(--duration-m) var(--ease-out),
              text-decoration-color var(--duration-m) var(--ease-out),
              text-underline-offset var(--duration-m) var(--ease-out);
}

a:not(.button):hover {
  color: var(--text-link);
  

}

/* The glyph warns that an underlined run of text leaves the site. A button is
   already a distinct affordance and carries its own icon slot, so it is excluded
   — on an icon-only button the mark would trail the icon as a second glyph. */
a[target="_blank"]:not(.button)::after {
  content: "";
  display: inline-block;
  width: 0.75em;
  height: 0.75em;
  margin-left: 0.2em;
  vertical-align: baseline;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3 21V3H9V5H7C5.89543 5 5 5.89543 5 7V17C5 18.1046 5.89543 19 7 19H17C18.1046 19 19 18.1046 19 17V15H21V21H3ZM9.7 15.7L8.3 14.3L15.8929 6.70711C16.5229 6.07714 16.0767 5 15.1858 5H12V3H21V12H19V8.81421C19 7.92331 17.9229 7.47714 17.2929 8.10711L9.7 15.7Z' fill='black'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3 21V3H9V5H7C5.89543 5 5 5.89543 5 7V17C5 18.1046 5.89543 19 7 19H17C18.1046 19 19 18.1046 19 17V15H21V21H3ZM9.7 15.7L8.3 14.3L15.8929 6.70711C16.5229 6.07714 16.0767 5 15.1858 5H12V3H21V12H19V8.81421C19 7.92331 17.9229 7.47714 17.2929 8.10711L9.7 15.7Z' fill='black'/%3E%3C/svg%3E");
  mask-size: contain;
  mask-repeat: no-repeat;
}

/* -- Lists -- */
ul,
ol {
  margin-top: 0;
  margin-bottom: var(--space-m);
  padding-left: var(--space-2xl);
}

li {
  margin-top: var(--space-s);
  margin-bottom: 0;
}

li:first-child {
  margin-top: 0;
}

/* Nested lists */
ul ul,
ul ol,
ol ul,
ol ol {
  margin-top: var(--space-s);
  margin-bottom: 0;
}

ol ol,
ul ol {
  list-style-type: lower-roman;
}

ul ul ol,
ul ol ol,
ol ul ol,
ol ol ol {
  list-style-type: lower-alpha;
}

/* GFM task lists (- [ ]) render a checkbox inside the list item. Drop the
   disc bullet so the checkbox is the only marker, and pull the list flush
   since there's no bullet to indent against. */
li:has(> input[type="checkbox"]) {
  list-style: none;
}

ul:has(> li > input[type="checkbox"]) {
  padding-left: 0;
}

li > input[type="checkbox"] {
  margin-right: var(--space-xs);
}

/* List items with paragraphs */
li > p {
  margin-top: var(--space-l);
  margin-bottom: 0;
}

li > p:first-child {
  margin-top: 0;
}

/* -- Blockquotes -- */
blockquote {
  position: relative;
  margin: var(--space-xl) 0;
  padding-left: var(--space-xl);
  /* border-left: var(--border-m) solid var(--border-secondary); */
  font-family: var(--font-secondary);
  color: var(--text-primary);
  font-size: calc(var(--body-size) + 0.5rem);
  font-style: italic;
  hanging-punctuation: first;
  text-wrap: balance;
}

blockquote::before {
  content: "\201C";          /* “ — left double quotation mark */
  position: absolute;
  left: var(--space-l);      /* line up with the text edge... */
  top: 0;
  transform: translateX(-100%);
  font-size: 2em;            
  line-height: 1;
  font-family: var(--font-secondary);
}

blockquote p {
  margin-top: 0;
  margin-bottom: var(--space-m);
}

blockquote p:last-child {
  margin-bottom: 0;
}

/* -- Bold -- */
b,
strong {
  font-weight: var(--font-weight-semi-bold);
}

/* -- Images -- */
img {
  border-style: none;
  max-width: 100%;
  box-sizing: content-box;
}

/* -- Definition lists -- */
dl {
  padding: 0;
}

dl dt {
  padding: 0;
  font-size: var(--font-s);
  font-style: italic;
  font-weight: var(--font-weight-semi-bold);
}

dl dd {
  padding: 0 var(--space-l);
}

dd {
  margin-left: 0;
}

/* -- Focus styles -- */
/* `button` is included so .button and every bare button share one ring
   instead of falling back to the browser default. */
a:focus,
button:focus,
[role=button]:focus,
input[type=radio]:focus,
input[type=checkbox]:focus {
  outline: 2px solid var(--status-info);
  outline-offset: -2px;
  box-shadow: none;
}

a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
[role=button]:focus:not(:focus-visible),
input[type=radio]:focus:not(:focus-visible),
input[type=checkbox]:focus:not(:focus-visible) {
  outline: solid 1px transparent;
}

a:focus-visible,
button:focus-visible,
[role=button]:focus-visible,
input[type=radio]:focus-visible,
input[type=checkbox]:focus-visible {
  outline: 2px solid var(--status-info);
  outline-offset: -2px;
  box-shadow: none;
}

/* The inset offset above assumes the control has padding to draw into.
   Zero-padding buttons need the ring outside, or it strikes through the label. */
.button[data-variant="text"]:focus-visible,
.dialog-close:focus-visible,
.toast-close:focus-visible {
  outline-offset: 2px;
}

a:not([href]) {
  color: inherit;
  text-decoration: none;
}





/* ------ 11. CALLOUTS & ALERTS ------ */

/* -- Base callout -- */
.callout {
  padding: var(--space-m) var(--space-l);
  margin-top: var(--space-l);
  margin-bottom: var(--space-l);
  background-color: var(--background-faded);
  border: var(--border-s) solid var(--border-faded);
}

.callout > *:first-child {
  margin-top: 0;
}

.callout > *:last-child {
  margin-bottom: 0;
}

/* -- Callout title -- */
.callout-title {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  font-weight: var(--font-weight-semi-bold);
  font-size: var(--font-s);
  line-height: var(--line-height-s);
}

/* -- Callout icon layout -- */
.callout[data-icon] {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-m);
}

.callout[data-icon] > .svg-icn {
  grid-column: 1;
  grid-row: 1;
  width: 1.25rem;
  height: 1.25rem;
  align-self: center;
}

.callout[data-icon] > :not(.svg-icn) {
  grid-column: 2;
}

/* -- Callout description -- */
.callout-description {
  margin-top: var(--space-xs);
  font-size: var(--font-s);
}

/* -- Callout type variants -- */
.callout[data-type="info"] {
  background-color: var(--status-info-bg);
}

.callout[data-type="info"] .callout-title,
.callout[data-type="info"] > .svg-icn {
  color: var(--status-info);
}

.callout[data-type="success"] {
  background-color: var(--status-success-bg);
}

.callout[data-type="success"] .callout-title,
.callout[data-type="success"] > .svg-icn {
  color: var(--status-success);
}

.callout[data-type="warning"] {
  background-color: var(--status-warning-bg);
}

.callout[data-type="warning"] .callout-title,
.callout[data-type="warning"] > .svg-icn {
  color: var(--status-warning);
}

.callout[data-type="danger"] {
  background-color: var(--status-danger-bg);
}

.callout[data-type="danger"] .callout-title,
.callout[data-type="danger"] > .svg-icn {
  color: var(--status-danger);
}

/* ------ 12. FORM ELEMENTS ------ */

/* -- Labels -- */
label {
  display: block;
  font-size: var(--font-s);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  margin-bottom: var(--space-xs);
}

/* -- Text inputs & textarea -- */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
input[type="url"],
input[type="tel"],
textarea,
select {
  font-family: var(--font-primary);
  font-size: var(--body-size);
  line-height: var(--line-height-l);
  color: var(--input-text);
  background-color: var(--input-background);
  border: var(--border-s) solid var(--input-border);
  padding: var(--space-m) var(--space-l);
  min-height: 44px;
  width: 100%;
  display: block;
  transition: border-color 0.2s ease;
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
input[type="tel"]:focus,
textarea:focus,
select:focus {
  outline: 1px solid var(--input-focus);
  outline-offset: 2px;
  box-shadow: none;
}

/* -- Input error state -- */
input.is-error,
textarea.is-error,
select.is-error {
  border-color: var(--status-danger);
}

input.is-error:focus,
textarea.is-error:focus,
select.is-error:focus {
  outline-color: var(--status-danger);
}

/* -- Disabled inputs -- */
input:disabled,
textarea:disabled,
select:disabled {
  background-color: var(--input-disabled-bg);
  color: var(--input-disabled-text);
  cursor: not-allowed;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

input::placeholder,
textarea::placeholder {
  color: var(--input-placeholder);
}

/* -- Textarea -- */
textarea {
  min-height: 120px;
  resize: vertical;
}

/* -- Colour input -- */
input[type="color"] {
  appearance: none;
  -webkit-appearance: none;
  border: var(--border-s) solid var(--input-border);
  background-color: var(--input-background);
  padding: 0;
  width: auto;
  aspect-ratio: 1 / 1;
  align-self: stretch;
  cursor: pointer;
  transition: border-color 0.2s ease;
}

input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
}

input[type="color"]::-webkit-color-swatch {
  border: none;
}

input[type="color"]::-moz-color-swatch {
  border: none;
}

input[type="color"]:focus {
  outline: none;
  border-color: var(--input-focus);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

/* -- Select -- */
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M1.41 0L6 4.58 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-m) center;
  padding-right: var(--space-2xl);
  cursor: pointer;
}

/* -- Disabled states -- */
input:disabled,
textarea:disabled,
select:disabled {
  background-color: var(--input-disabled-bg);
  color: var(--input-disabled-text);
  cursor: not-allowed;
  border: none;
}

/* -- Fieldset & legend -- */
fieldset {
  border: var(--border-s) solid var(--border-secondary);
  padding: var(--space-l);
  margin: 0 0 var(--space-l) 0;
}

legend {
  font-size: var(--font-s);
  font-weight: var(--font-weight-semi-bold);
  padding: 0 var(--space-s);
  color: var(--text-primary);
}

/* -- Checkbox & radio -- */
input[type="checkbox"],
input[type="radio"] {
  -webkit-appearance: none;
  appearance: none;
  width: var(--space-xl);
  height: var(--space-xl);
  margin: 0;
  cursor: pointer;
  background-color: var(--checkbox-background);
  border: var(--border-s) solid var(--checkbox-border);
  transition: background-color 0.15s ease, border-color 0.15s ease;
  flex-shrink: 0;
  position: relative;
}

input[type="radio"] {
  border-radius: 50%;
}

input[type="checkbox"]:checked {
  background-color: var(--checkbox-selected);
  border-color: var(--checkbox-selected);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 12 10 18 20 6'/%3E%3C/svg%3E");
  background-size: 14px 14px;
  background-position: center;
  background-repeat: no-repeat;
}

input[type="radio"]:checked {
  background-color: var(--checkbox-selected);
  border-color: var(--checkbox-selected);
}

input[type="radio"]:checked::after {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background-color: var(--checkbox-checkmark);
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
  background-color: var(--input-disabled-bg);
  border-color: var(--input-disabled-bg);
  cursor: not-allowed;
  opacity: 0.5;
}

input[type="checkbox"]:disabled:checked {
  background-color: var(--input-disabled-text);
  border-color: var(--input-disabled-text);
}

input[type="radio"]:disabled:checked {
  background-color: var(--input-disabled-text);
  border-color: var(--input-disabled-text);
}

/* Dark mode checkmark */
[data-theme="dark"] input[type="checkbox"]:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a1a1a' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 12 10 18 20 6'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) input[type="checkbox"]:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a1a1a' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 12 10 18 20 6'/%3E%3C/svg%3E");
  }
}

/* -- Inline label + checkbox/radio pattern -- */
.form-check {
  display: flex;
  align-items: center;
  gap: var(--space-s);
}

.form-check label {
  display: inline;
  margin-bottom: 0;
  font-weight: var(--font-weight-regular);
  cursor: pointer;
}

/* -- Segmented control (single-select button group) -- */
.segmented-control {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
}

.segmented-control-btn {
  padding: var(--space-s) var(--space-l);
  font-size: var(--font-s);
  font-weight: var(--font-weight-regular);
  border-radius: 0;
  border: none;
  background: transparent;
  color: var(--text-faded);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
  white-space: nowrap;
  font-family: inherit;
}

.segmented-control-btn:hover {
  color: var(--text-primary);
  background-color: color-mix(in srgb, var(--background-primary), var(--alpha-50));
}

.segmented-control-btn.is-active {
  color: var(--text-primary);
}

.segmented-control-btn:focus-visible {
  outline: 2px solid var(--text-primary);
  outline-offset: 2px;
}

.segmented-control-btn.is-icon {
  padding: var(--space-s);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* -- Toggle / switch -- */
.form-toggle {
  --toggle-width: 44px;
  --toggle-height: var(--space-xl);
  --toggle-knob-size: 18px;
  --toggle-knob-offset: 3px;

  display: flex;
  align-items: center;
  gap: var(--space-s);
}

.form-toggle label {
  display: inline;
  margin-bottom: 0;
  font-weight: var(--font-weight-regular);
  cursor: pointer;
  order: -1;
  white-space: nowrap;
}

.form-toggle.is-label-right label {
  order: 1;
}

.form-toggle input[type="checkbox"] {
  width: var(--toggle-width);
  height: var(--toggle-height);
  background-color: var(--black-alpha-3);
  border: var(--border-s) solid var(--border-faded);
  border-radius: var(--radius-pill);
  position: relative;
  transition: background-color 0.2s ease;
}

.form-toggle input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 50%;
  left: var(--toggle-knob-offset);
  transform: translateY(-50%);
  width: var(--toggle-knob-size);
  height: var(--toggle-knob-size);
  border-radius: 50%;
  background-color: var(--neutral-500);
  transition: transform 0.2s ease, background-color 0.2s ease;
}

.form-toggle input[type="checkbox"]:checked {
  background-color: var(--text-accent);
  background-image: none;
}

.form-toggle input[type="checkbox"]:checked::after {
  transform: translateY(-50%) translateX(calc(var(--toggle-width) - var(--toggle-knob-size) - var(--toggle-knob-offset) * 2 - var(--border-s) * 2));
  background-color: var(--off-white);
}

.form-toggle input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.form-toggle input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.form-toggle input[type="checkbox"]:disabled + label {
  cursor: not-allowed;
}

/* -- Toggle dark mode -- */
[data-theme="dark"] .form-toggle input[type="checkbox"] {
  background-color: #444;
}

[data-theme="dark"] .form-toggle input[type="checkbox"]::after {
  background-color: #888;
}

[data-theme="dark"] .form-toggle input[type="checkbox"]:checked {
  background-color: #e8e6e3;
}

[data-theme="dark"] .form-toggle input[type="checkbox"]:checked::after {
  background-color: #1a1a1a;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .form-toggle input[type="checkbox"] {
    background-color: #444;
  }

  :root:not([data-theme]) .form-toggle input[type="checkbox"]::after {
    background-color: #888;
  }

  :root:not([data-theme]) .form-toggle input[type="checkbox"]:checked {
    background-color: #e8e6e3;
  }

  :root:not([data-theme]) .form-toggle input[type="checkbox"]:checked::after {
    background-color: #1a1a1a;
  }
}

/* -- Form group (label + input pair) -- */
.form-group {
  margin-bottom: var(--space-l);
}

/* -- Form hint text -- */
.form-hint {
  font-size: var(--font-s);
  color: var(--text-secondary);
  margin-top: var(--space-xs);
}

/* -- Form error message -- */
.form-error {
  font-size: var(--font-s);
  color: var(--status-danger);
  margin-top: var(--space-xs);
}

/* -- Skeleton loading -- */
.skeleton-line {
  background-color: var(--background-faded);
  border-radius: 4px;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}

.skeleton-label {
  height: 14px;
  width: 30%;
  margin-bottom: var(--space-xs);
}

.skeleton-input {
  height: 44px;
  width: 100%;
}

@keyframes skeleton-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* -- Access support form states -- */
.access-support-success {
  text-align: center;
  padding: var(--space-3xl) 0;
}

.access-support-success p {
  font-size: var(--body-size);
  color: var(--text-secondary);
}

.access-support-error {
  font-size: var(--font-s);
  color: var(--status-danger);
  margin-top: var(--space-s);
}

/* -- Password field -- */
/* Behaviour ships as password-toggle.js; these styles ship with it so a
   package consumer gets a working control, not a bare button. */
.password-field {
  position: relative;
}

.password-field input {
  padding-right: var(--space-4xl);
}

.password-toggle {
  position: absolute;
  right: var(--space-m);
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-faded);
  padding: var(--space-xs);
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color var(--duration-xs) var(--ease-out);
}

.password-toggle:hover {
  color: var(--text-primary);
}

.password-toggle .svg-icn {
  width: 1.25rem;
  height: 1.25rem;
}

/* ------ 13. DISCLOSURE (details / summary) ------ */

/* -- Base disclosure -- */


summary {
  display: flex;
  align-items: center;
  gap: var(--space-m);
  font-family: var(--font-primary);
  font-size: var(--body-size);
  color: var(--text-primary);
  padding: var(--space-s) var(--space-m);
  cursor: pointer;
  user-select: none;
  list-style: none;
}

summary::-webkit-details-marker {
  display: none;
}

summary::before {
  content: "";
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

details[open] > summary::before {
  transform: rotate(45deg);
}

summary:hover {
  color: var(--text-secondary);
}

summary:focus-visible {
  outline: 2px solid var(--input-focus);
  outline-offset: -2px;
}

/* -- Disclosure content -- */
details .disclosure-content {
  padding: var(--space-s) var(--space-m) var(--space-m) calc(0.5em + var(--space-s) + var(--space-m));
  font-family: var(--font-primary);
  font-size: var(--body-size);
  line-height: var(--line-height-xl);
  color: var(--text-secondary);
}

/* -- Disclosure table (key-value pairs) -- */
.disclosure-table {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2xs) var(--space-l);
  align-items: baseline;
  margin: 0;
}

.disclosure-table dt {
  color: var(--text-faded);
  white-space: nowrap;
}

.disclosure-table dd {
  color: var(--text-primary);
  margin: 0;
}


/* ------ 16. BADGE ------ */

.badge {
  --badge-case: uppercase;
  --badge-tracking: var(--letter-spacing-l);

  display: inline-flex;
  align-items: center;
  font-family: var(--font-tertiary);
  font-size: var(--font-2xs);
  font-weight: var(--font-weight-bold);
  text-transform: var(--badge-case);
  letter-spacing: var(--badge-tracking);
  padding: var(--space-2xs) var(--space-s);
  border-radius: 0;
  background-color: var(--background-darker);
  color: var(--text-primary);
  white-space: nowrap;
  line-height: var(--line-height-m);
}

/* Sentence-case variant — customize case via the tokens above or this
   attribute, never by overriding the class (Layer Rule 3) */
.badge[data-case="none"] {
  --badge-case: none;
  --badge-tracking: normal;
}

.badge[data-color="success"],
.badge[data-color="green"] {
  background-color: var(--status-success-bg);
  color: var(--status-success);
}

.badge[data-color="warning"],
.badge[data-color="yellow"] {
  background-color: var(--status-warning-bg);
  color: var(--status-warning);
}

.badge[data-color="danger"],
.badge[data-color="red"] {
  background-color: var(--status-danger-bg);
  color: var(--status-danger);
}

.badge[data-color="info"],
.badge[data-color="blue"] {
  background-color: var(--status-info-bg);
  color: var(--status-info);
}


/* ------ 17. CARD ------ */

.card {
  background-color: var(--background-primary);
  border: var(--border-s) solid var(--border-faded);
  padding: var(--space-xl);
  transition: border 0.3s, background-color 0.3s, box-shadow 0.15s;
}

.card--flush {
  padding: 0;
}

.card--interactive {
  display: block;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  transition: border 0.3s, background-color 0.3s, box-shadow 0.15s;
}

.card--interactive:hover {
  background-color: var(--background-faded);
  box-shadow: 0 4px 12px var(--black-alpha-10);
  /* border-color: var(--border-primary); */
}

.card--interactive:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}
/* -- Card inner elements -- */
.card-title {
  margin-top: 0;
  margin-bottom: var(--space-s);
  font-size: var(--font-3xl);
  line-height: var(--line-height-m);
}

.card-description {
  color: var(--text-secondary);
  font-size: var(--body-size);
  margin-bottom: 0;

}

.card-image {
  border-radius: var(--radius-m) var(--radius-m) 0 0;
}

/* -- Card dark mode -- */
[data-theme="dark"] .card {
  background-color: var(--background-secondary);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .card {
    background-color: var(--background-secondary);
  }
}



/* ------ 18. BREADCRUMB ------ */

.breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-xs);
  font-size: var(--font-xs);
  color: var(--text-faded);
}

.breadcrumb a {
  color: var(--text-faded);
  text-decoration: none;
  transition: color 0.15s ease-in-out;
}

.breadcrumb a:hover {
  color: var(--text-primary);
  text-decoration: underline;
}

.breadcrumb [aria-current="page"] {
  color: var(--text-primary);
  font-weight: var(--font-weight-medium);
}

.breadcrumb-separator {
  color: var(--text-faded);
  user-select: none;
}


/* ------ 14. ACCORDION ------ */

.accordion {
  border-top: var(--border-s) solid var(--border-faded);
}

.accordion-item {
  border-bottom: var(--border-s) solid var(--border-faded);
}



.accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  text-align: left;
  gap: var(--space-m);
  padding: var(--accordion-padding-y) var(--accordion-padding-x);
  color: var(--text-primary);
  z-index: 10;
  position: relative;
}

.accordion-header .svg-icn {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  transition: transform var(--duration-m) var(--ease-out);
}

.accordion-item.is-open > .accordion-header .svg-icn {
  transform: rotate(180deg);
}

.accordion-content {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-m) var(--ease-out);
  z-index: 5;
  position: relative;
}

.accordion-item.is-open > .accordion-content {
  grid-template-rows: 1fr;
}

.accordion-header:focus:not(:focus-visible) {
  outline: solid 1px transparent;
}

.accordion-header:focus-visible {
  outline: 2px solid var(--status-info);
  outline-offset: -2px;
  box-shadow: none;
}

.accordion-inner {
  overflow: hidden;
  min-height: 0;
}

.accordion-body {
  padding:  0 var(--accordion-padding-x) var(--accordion-padding-y) var(--accordion-padding-x);
}


/* ------ 19. TABS ------ */

.tabs {
  display: flex;
  border-bottom: var(--border-s) solid var(--border-faded);
  gap: var(--space-none);
}

.tab {
  position: relative;
  background: none;
  border: none;
  padding: var(--space-m) var(--space-l);
  color: var(--text-faded);
  font-weight: var(--font-weight-medium);
  font-size: var(--font-s);
  cursor: pointer;
  transition: color 0.15s ease-in-out;
}

.tab:hover {
  color: var(--text-secondary);
}

.tab.is-active {
  color: var(--text-primary);
}

.tab.is-active::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background-color: var(--text-primary);
}

.tab:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.tab-panel {
  padding-top: var(--space-m);
}

a.tab {
    text-decoration: none;
}

a.tab:hover {
  background-color: var(--background-faded);
}


/* ------ 20. PROGRESS ------ */

progress.progress-bar {
  width: 100%;
  height: var(--space-s);
  border-radius: 0;
  border: none;
  overflow: hidden;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

progress.progress-bar::-webkit-progress-bar {
  background-color: var(--background-darker);
  border-radius: 0;
}

progress.progress-bar::-webkit-progress-value {
  background-color: var(--text-primary);
  border-radius: 0;
  transition: width 0.3s ease-in-out;
}

progress.progress-bar::-moz-progress-bar {
  background-color: var(--text-primary);
  border-radius: 0;
}

/* -- Progress status variants -- */
progress.progress-bar--success::-webkit-progress-value { background: var(--status-success); }
progress.progress-bar--success::-moz-progress-bar { background: var(--status-success); }

progress.progress-bar--warning::-webkit-progress-value { background: var(--status-warning); }
progress.progress-bar--warning::-moz-progress-bar { background: var(--status-warning); }

progress.progress-bar--danger::-webkit-progress-value { background: var(--status-danger); }
progress.progress-bar--danger::-moz-progress-bar { background: var(--status-danger); }

/* -- Progress wrapper with tooltip -- */
.progress-wrapper {
  position: relative;
  width: 100%;
}

.progress-tooltip {
  position: absolute;
  bottom: calc(100% + var(--space-xs));
  background-color: var(--warm-black);
  color: var(--off-white);
  border-radius: var(--radius-s);
  padding: var(--space-xs) var(--space-s);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%);
  transition: opacity 0.15s ease-in-out;
  z-index: 800;
}

.progress-wrapper:hover .progress-tooltip {
  opacity: 1;
}


/* ------ 21. TOOLTIP ------ */

[data-tooltip] {
  position: relative;
  cursor: help;
}

[data-tooltip]::before {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + var(--space-xs));
  left: 50%;
  transform: translateX(-50%);
  background-color: var(--warm-black);
  color: var(--off-white);
  border-radius: var(--radius-s);
  padding: var(--space-xs) var(--space-s);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease-in-out;
  z-index: 800;
}

/* Bubble typography pinned in full. A pseudo-element inherits from its
   trigger and .progress-tooltip from its wrapper, so an unpinned bubble
   renders per-host: a .button trigger collapses leading to 0.7, a .badge
   would uppercase and letterspace it, a condensed ancestor narrows the face. */
[data-tooltip]::before,
.progress-tooltip {
  font-family: var(--font-primary);
  font-size: var(--font-xs);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-m);
  letter-spacing: 0;
  text-transform: none;
  font-style: normal;
  font-stretch: var(--font-normal);
}

[data-tooltip]:hover::before,
[data-tooltip]:focus-visible::before {
  opacity: 1;
}

/* -- Tooltip positions -- */
[data-tooltip-position="bottom"]::before {
  bottom: auto;
  top: calc(100% + var(--space-xs));
}

[data-tooltip-position="left"]::before {
  bottom: auto;
  top: 50%;
  left: auto;
  right: calc(100% + var(--space-xs));
  transform: translateY(-50%);
}

[data-tooltip-position="right"]::before {
  bottom: auto;
  top: 50%;
  left: calc(100% + var(--space-xs));
  transform: translateY(-50%);
}

/* -- Interactive elements override cursor -- */
button[data-tooltip],
a[data-tooltip],
.button[data-tooltip] {
  cursor: pointer;
}

/* -- Tooltip dark mode -- */
[data-theme="dark"] [data-tooltip]::before,
[data-theme="dark"] .progress-tooltip {
  background-color: var(--neutral-100);
  color: var(--warm-black);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) [data-tooltip]::before,
  :root:not([data-theme]) .progress-tooltip {
    background-color: var(--neutral-100);
    color: var(--warm-black);
  }
}


/* ------ 22. TOAST ------ */

.toast-container {
  position: fixed;
  bottom: var(--space-xl);
  right: var(--space-xl);
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  pointer-events: none;
}

.toast {
  --toast-exit-duration: var(--duration-xs);
  pointer-events: all;
  background-color: var(--warm-black);
  color: var(--off-white);
  padding: var(--space-m) var(--space-l);
  border: var(--border-s) solid var(--border-faded);
  display: flex;
  align-items: center;
  gap: var(--space-m);
  max-width: 360px;
  font-size: var(--font-s);
  /* toast.js reads the computed duration before removing the node, so the
     fade length lives here only. */
  transition: opacity var(--toast-exit-duration) var(--ease-in-out);
}

.toast[data-type="success"],
.toast[data-type="green"] { background: var(--status-success-bg); color: var(--status-success); }

.toast[data-type="warning"],
.toast[data-type="yellow"] { background: var(--status-warning-bg); color: var(--status-warning); }

.toast[data-type="danger"],
.toast[data-type="red"] { background: var(--status-danger-bg); color: var(--status-danger); }

.toast[data-type="info"],
.toast[data-type="blue"] { background: var(--status-info-bg); color: var(--status-info); }

.toast-message {
  flex: 1;
}

/* The toast paints its own surface colour, so the close button follows
   currentColor instead of the page-level text tokens. No opacity dimming:
   at 0.7 the icon fails 1.4.11 non-text contrast on the success, danger
   and info surfaces. */
.toast .button.close-btn {
  --button-text-color: currentColor;
}

.toast .button.close-btn:hover {
  background-color: color-mix(in srgb, currentColor, var(--alpha-5));
}

/* Deprecated — use <button class="button close-btn" data-icon-only data-size="small">.
   Kept so existing markup keeps its styling; remove at the next major. */
.toast-close {
  color: inherit;
  line-height: 1;
  opacity: 0.7;
  transition: opacity var(--duration-2xs) var(--ease-out);
}

.toast-close:hover {
  opacity: 1;
}

/* -- Reduced motion -- */
/* Re-points the exit token so dismissal is effectively immediate. */
@media (prefers-reduced-motion: reduce) {
  .toast {
    --toast-exit-duration: var(--duration-2xs);
  }
}

/* -- Toast dark mode -- */
/* Only the neutral toast inverts its surface. A typed toast keeps its status
   colour as text in both themes.

   Scoped on the presence or absence of data-type, which matches what toast.js
   emits: it sets dataset.type only when the type is not 'default' (toast.js:65),
   so a neutral toast carries no attribute at all. Selecting on that makes these
   rules mutually exclusive with the .toast[data-type] rules above rather than
   competing with them on specificity and source order. Previously they matched
   every .toast and won — (0,2,0) tying with the typed rules and beating them on
   source order, (0,3,0) beating them outright — which flattened success,
   warning, danger and info to the same grey the moment dark mode was on.

   The typed surface has to be re-derived here rather than left to the tokens.
   --status-* flips to a light tint in dark mode but --status-*-bg stays at its
   light pastel, so the authored pair lands light-on-light: measured at 1.1:1,
   a worse failure than the flattening this fixes. Mixing the status colour into
   the dark surface instead keeps the type legible and holds every variant above
   9:1. The underlying --status-*-bg token gap is real and tracked separately;
   this only stops the toast depending on it. */
[data-theme="dark"] .toast:not([data-type]) {
  background-color: var(--neutral-100);
  color: var(--warm-black);
}

[data-theme="dark"] .toast[data-type] {
  background-color: color-mix(in srgb, currentColor, var(--warm-black) 85%);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .toast:not([data-type]) {
    background-color: var(--neutral-100);
    color: var(--warm-black);
  }

  :root:not([data-theme]) .toast[data-type] {
    background-color: color-mix(in srgb, currentColor, var(--warm-black) 85%);
  }
}


/* ------ 23. CODE ------ */

/* -- Inline code -- */
code {
  font-family: var(--font-quaternary);
  font-size: calc(var(--body-size) - .2em);
  background-color: color-mix(in srgb, var(--text-primary), var(--alpha-5));
  padding: var(--space-2xs) var(--space-xs);
  border-radius: var(--radius-xs);
  color: var(--text-primary);
  white-space: nowrap;
}

/* -- Code block -- */
pre {
  background-color: var(--background-secondary);
  border: var(--border-s) solid var(--border-faded);
  padding: var(--space-l);
  overflow-x: auto;
  font-family: var(--font-quaternary);
  font-size: calc(var(--body-size) - 2px);
  line-height: var(--line-height-xl);
}

pre code {
  background: none;
  padding: 0;
  border-radius: 0;
  font-size: inherit;
  word-break: normal;
}

/* -- Keyboard shortcut -- */
kbd {
  display: inline-block;
  padding: var(--space-xs) var(--space-s);
  font-family: var(--font-quaternary);
  font-size: var(--font-2xs);
  line-height: var(--line-height-m);
  color: var(--text-secondary);
  vertical-align: middle;
  background-color: var(--background-faded);
  border: var(--border-s) solid var(--border-secondary);
  border-radius: var(--radius-xs);
  box-shadow: 0 1px 0 var(--border-secondary);
  white-space: nowrap;
}

/* -- Highlighted text -- */
mark {
  background-color: var(--yellow-light);
  color: var(--warm-black);
  padding: 0 var(--space-2xs);
}

/* -- Mark dark mode -- */
[data-theme="dark"] mark {
  background-color: color-mix(in srgb, var(--yellow), var(--alpha-60));
  color: var(--off-white);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) mark {
    background-color: color-mix(in srgb, var(--yellow), var(--alpha-60));
    color: var(--off-white);
  }
}

/* -- Figure / Figcaption -- */
figure {
  margin: var(--space-xl) 0;
  padding: 0;
}

figcaption {
  font-size: var(--font-xs);
  color: var(--text-faded);
  margin-top: var(--space-s);
  line-height: var(--line-height-xl);
  font-style: italic;
}

/* -- Abbreviation -- */
abbr[title] {
  text-decoration: underline dotted var(--text-faded);
  text-underline-offset: 2px;
  cursor: help;
}




/* ------ 24. IMAGE ------ */

/* -- Base image -- */
.img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}

/* -- Aspect ratio combos -- */
.img-1x1  { aspect-ratio: 1 / 1; }
.img-3x2  { aspect-ratio: 3 / 2; }
.img-4x3  { aspect-ratio: 4 / 3; }
.img-16x9 { aspect-ratio: 16 / 9; }
.img-21x9 { aspect-ratio: 21 / 9; }


/* NOTE: .sticky-bar moved to docs-site.css — see CLAUDE.md §17 (Layer Discipline) */


/* ------ 25. TABLE ------ */

/* -- Table scroll wrapper -- */
.table-scroll {
  position: relative;
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* -- Scroll hint: fade on right edge when overflowing -- */
.table-scroll.is-overflowing {
  display: flex;
}

.table-scroll.is-overflowing::after {
  content: "";
  position: sticky;
  right: 0;
  flex-shrink: 0;
  width: var(--space-2xl);
  margin-left: calc(-1 * var(--space-2xl));
  background: linear-gradient(to right, transparent, var(--background-primary));
  pointer-events: none;
}

.table-scroll.is-scrolled-end::after {
  display: none;
}

/* -- Base table -- */
.table {
  border-spacing: 0;
  border-collapse: collapse;
  width: fit-content;
  max-width: 100%;
  /* font-variant: tabular-nums; */
  font-size: var(--body-size);
  margin-bottom: var(--space-2xl);
}

.table th {
  font-weight: var(--font-weight-bold);
  text-align: left;
  min-width: 130px;
}

.table th,
.table td {
  padding: var(--space-m) var(--space-l);
  border: none;
}

.table thead {
  background-color: transparent;
}

.table thead tr {
  border-bottom: var(--border-s) solid var(--border-secondary);
}

.table tbody tr {
  border-bottom: var(--border-s) solid var(--border-faded);
}

/* -- Table modifier: full width -- */
.table-full {
  width: 100%;
}

/* -- Table modifier: hoverable rows -- */
.table-hover tbody tr:hover {
  background-color: var(--background-faded);
}

/* -- Table modifier: header background -- */
.table-header-filled th {
  background-color: var(--background-faded);
  font-weight: var(--font-weight-semi-bold);
  color: var(--text-primary);
}

/* -- Table footer -- */
.table tfoot tr {
  border-top: var(--border-m) solid var(--border-primary);
}

.table tfoot th {
  font-weight: var(--font-weight-bold);
}

.table tfoot td {
  font-weight: var(--font-weight-semi-bold);
}

td .svg-icn {
  display: inline-flex;
}

/* -- Condensed table on mobile -- */
@media (max-width: 768px) {
  .table th,
  .table td {
    padding: var(--space-s) var(--space-m);
  }
}


/* ------ 26. DIVIDER ------ */

.divider {
  border: none;
  border-top: var(--divider-thickness) solid var(--divider-color);
  margin: var(--divider-spacing) 0;
}

.divider--vertical {
  border-top: none;
  border-left: var(--divider-thickness) solid var(--divider-color);
  height: auto;
  align-self: stretch;
  margin: 0 var(--divider-spacing);
  display: inline-block;
}

.divider--subtle {
  --divider-color: var(--black-alpha-10);
}

.divider--strong {
  --divider-color: var(--border-primary);
  border-top-width: var(--border-m);
}

hr {
  border: none;
  border-top: var(--divider-thickness) solid var(--divider-color, var(--border-faded));
  margin: var(--divider-spacing) 0;
}

hr.xl {
  border: none;
  margin: var(--space-2xl) 0;
}


/* ------ 27. DROPDOWN ------ */

/* inline-flex, not flex: this element is the menu's containing block, so a
   block-level box would stretch to its parent's full width and `right: 0`
   would pin the menu to the far side of the page rather than to the trigger.
   The wider the window, the further it flew — which is why it looked correct
   in a narrow preview pane and broke when maximised.
   In a flex or grid parent (the sticky bar, tool toolbars) display is
   blockified back to flex, so those layouts are unaffected. */
.dropdown {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
  align-items: stretch;
}

/* -- Trigger -- */
.dropdown-trigger {
  display: flex;
  align-items: center;
  align-self: stretch;
  gap: var(--space-s);
  padding: var(--space-l) var(--space-m);
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--font-primary);
  font-size: var(--font-s);
  line-height: var(--line-height-m);
  text-decoration: none;
  transition: color var(--duration-2xs) var(--ease-out),
              background-color var(--duration-2xs) var(--ease-out);
}

.dropdown-trigger:hover {
  background-color: var(--dropdown-item-hover);
  color: var(--text-plain);
}

.dropdown-trigger .svg-icn {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
}

.dropdown.is-open > .dropdown-trigger {
  background-color: var(--background-faded);
}

/* -- Chevron (rotates on open) -- */
.dropdown-chevron {
  width: 1rem;
  height: 1rem;
  color: var(--text-faded);
  transition: transform var(--duration-xs) var(--ease-out);
  flex-shrink: 0;
}

.dropdown.is-open .dropdown-chevron {
  transform: rotate(180deg);
}

/* -- Menu -- */
.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 250px;
  background-color: var(--dropdown-background);
  border: var(--border-s) solid var(--dropdown-border);
  /* border-top: none; */
  z-index: 1000;
  flex-direction: column;
}

/* -- Placement --
   Authored intent goes on the dropdown as data-placement; dropdown.js measures
   on open and writes the placement it actually resolved to into
   data-resolved-placement, flipping whichever axis would overflow. Styling the
   resolved value rather than the requested one keeps one source of truth — the
   menu cannot be told to open upward and then paint downward.
   .is-right predates this and still works; the script reads it as bottom-end. */
.dropdown-menu.is-right,
.dropdown[data-resolved-placement$="-end"] .dropdown-menu {
  left: auto;
  right: 0;
}

.dropdown[data-resolved-placement^="top"] .dropdown-menu {
  top: auto;
  bottom: 100%;
}

/* A flip beats the legacy class, or a right-aligned menu near the right edge
   could never be pushed back inward. */
.dropdown[data-resolved-placement$="-start"] .dropdown-menu.is-right {
  left: 0;
  right: auto;
}

.dropdown.is-open .dropdown-menu {
  display: flex;
}

/* -- Items -- */
.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  padding: var(--space-l) var(--space-m);
  font-size: var(--font-s);
  color: var(--text-primary);
  text-decoration: none;
  background: none;
  border: none;
  width: 100%;
  cursor: pointer;
  transition: background-color var(--duration-2xs) var(--ease-out);
  font-family: var(--font-primary);
  line-height: var(--line-height-m);
  text-align: left;
}

.dropdown-item:hover {
  background-color: var(--dropdown-item-hover);
  color: var(--text-plain);
}

/* Only the row tint belongs here. The ring itself comes from the global
   button/link rule — this used to override it with `outline: none` plus an
   inset box-shadow, which forced-colors modes strip entirely (leaving no
   focus indicator at all) and which drew in --input-focus, an amber in dark
   mode that fell below the 3:1 non-text contrast floor against this tint. */
.dropdown-item:focus-visible {
  background-color: var(--dropdown-item-hover);
}

.dropdown-item .svg-icn {
  width: 1.25rem;
  height: 1.25rem;
}

/* aria-disabled is the supported form — it keeps the item focusable so a
   keyboard user finds the same options a mouse user can see, and dropdown.js
   refuses the activation. `pointer-events: none` used to sit here, which both
   cancelled the not-allowed cursor on the line above and left keyboard
   activation fully live while only blocking the mouse. Opacity is raised off
   0.4, which put item text at 2.45:1. */
.dropdown-item.is-disabled,
.dropdown-item[aria-disabled="true"] {
  color: var(--text-faded);
  cursor: not-allowed;
}

/* Dimmed with colour, not opacity. `opacity` renders the focus outline into
   the same group and drops it to 2.34:1 — and these items stay focusable by
   design, so their focus indicator still has to clear 3:1. Scoping the fade
   to the icon keeps the visual weight without touching anything focusable. */
.dropdown-item.is-disabled .svg-icn,
.dropdown-item[aria-disabled="true"] .svg-icn {
  opacity: 0.55;
}

.dropdown-item--danger {
  color: var(--status-danger);
}

/* --alpha-10 is `transparent 90%`, giving a 10% tint. The rule previously
   read --alpha-90, which is `transparent 10%` — a 90% opaque red fill that
   put the label at 1.49:1 in dark mode. Every other status tint in this file
   uses --alpha-10; this was the only --alpha-90 in the stylesheet. */
.dropdown-item--danger:hover {
  background-color: color-mix(in srgb, var(--status-danger), var(--alpha-10));
}

/* -- Divider -- */
.dropdown-divider {
  border: none;
  border-top: var(--border-s) solid var(--dropdown-border);
  margin: 0;
}

/* -- Label (section header) -- */
.dropdown-label {
  padding: var(--space-s) var(--space-m);
  font-size: var(--font-2xs);
  font-weight: var(--font-weight-semi-bold);
  color: var(--text-faded);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* -- Description (under item text) -- */
.dropdown-desc {
  font-size: var(--font-2xs);
  color: var(--text-faded);
  white-space: normal;
}

/* -- Trailing content (pushes to right edge) -- */
.dropdown-item-end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  color: var(--text-faded);
  flex-shrink: 0;
  font-size: var(--font-2xs);
}

/* -- Group (role="group") --
   role="menu" may only own menuitems, groups and separators, so a section
   label has to sit inside a group rather than loose in the menu. The group
   re-declares the column layout because it becomes a single flex child of
   .dropdown-menu and would otherwise lay its items out in a row.
   `display: contents` would avoid that but has a history of dropping
   elements from the accessibility tree — not a risk worth taking on the
   element carrying the role. */
.dropdown-group {
  display: flex;
  flex-direction: column;
}

/* -- Header (non-interactive identity row) --
   For content that belongs in the panel but not in the menu, such as the
   signed-in user. It sits OUTSIDE the role="menu" element; it is not an item
   and must never be given a menuitem role. */
.dropdown-header {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  padding: var(--space-l) var(--space-m);
}

/* -- Checkable items --
   The checkmark is what conveys selection: colour alone would fail 1.4.1.
   Its space is reserved in both states so toggling cannot reflow the row,
   which is why this hides with visibility rather than display. */
.dropdown-checkmark {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  visibility: hidden;
}

/* Keyed on aria-checked alone, deliberately. Accepting .is-selected here too
   would let class-only markup show a checkmark that assistive tech never
   reports — a visible state with no announced counterpart. The class is still
   applied alongside for consistency with the shared state-class convention,
   but the ARIA state is the single source of truth. */
.dropdown-item[aria-checked="true"] .dropdown-checkmark {
  visibility: visible;
}


/* ------ 28. TAG ------ */

.tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-primary);
  font-size: var(--font-2xs);
  font-weight: var(--font-weight-regular);
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: var(--space-s) var(--space-s);
  background-color: var(--bg-faded-5);
  color: var(--text-secondary);
  white-space: nowrap;
  line-height: var(--line-height-xs);
  border-radius: 3px;
}

.tag[data-color="success"],
.tag[data-color="green"] {
  background-color: var(--status-success-bg);
  border-color: var(--green-light);
  color: var(--status-success);
}

.tag[data-color="warning"],
.tag[data-color="yellow"] {
  background-color: var(--status-warning-bg);
  border-color: var(--yellow-light);
  color: var(--status-warning);
}

.tag[data-color="danger"],
.tag[data-color="red"] {
  background-color: var(--status-danger-bg);
  border-color: var(--red-light);
  color: var(--status-danger);
}

.tag[data-color="info"],
.tag[data-color="blue"] {
  background-color: var(--status-info-bg);
  border-color: var(--blue-light);
  color: var(--status-info);
}

.tag-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  opacity: 0.6;
  padding: var(--space-2xs);
  transition: opacity 0.15s ease, background-color 0.15s ease;
  flex-shrink: 0;
  border-radius: var(--radius-pill);
}

.tag-remove .svg-icn {
  width: 0.625rem;
  height: 0.625rem;
}

.tag-remove:hover {
  opacity: 1;
  background-color: var(--black-alpha-10);
}

.tag-remove:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.tag-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  align-items: center;
}

/* ------ 29. DIALOG ------ */

.dialog {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --dialog-background: var(--background-primary);
  --dialog-shadow: 0 8px 32px var(--black-alpha-20);
  --dialog-radius: 0;
  --dialog-padding: var(--space-xl);
  --dialog-backdrop: var(--background-modal);

  /* -- Motion -- */
  /* Enters from below and settles upward; exits back down. Entrance is the
     slower half, which is why the two directions have their own tokens. */
  --dialog-offset: var(--space-l);
  --dialog-enter-duration: var(--duration-m);
  --dialog-enter-easing: var(--ease-out);
  --dialog-exit-duration: var(--duration-s);
  --dialog-exit-easing: var(--ease-in);

  background-color: var(--dialog-background);
  border: none;
  border-radius: var(--dialog-radius);
  box-shadow: var(--dialog-shadow);
  padding: var(--dialog-padding);
  max-width: var(--dialog-max-width);
  width: min(var(--dialog-max-width), calc(100vw - var(--space-2xl) * 2));
  max-height: 85vh;
  max-height: 85dvh; /* dvh accounts for mobile browser chrome; vh is the fallback */
  margin: auto;

  /* Layout lives here, not on [open]. Only `display` is discretely transitioned
     on exit, so any layout property left on [open] would snap back the instant
     the attribute is removed — reflowing the dialog mid-animation. */
  flex-direction: column;
  gap: var(--space-l);

  /* Closed / exit state. See the entrance-exit note below. */
  opacity: 0;
  translate: 0 var(--dialog-offset);
  transition:
    opacity var(--dialog-exit-duration) var(--dialog-exit-easing),
    translate var(--dialog-exit-duration) var(--dialog-exit-easing),
    display var(--dialog-exit-duration) allow-discrete,
    overlay var(--dialog-exit-duration) allow-discrete;
}

.dialog::backdrop {
  /* ::backdrop inherits from the dialog in current engines, which is what makes
     a scoped [data-theme] region theme its own backdrop. Engines predating that
     inherit from nothing, so --dialog-backdrop is unset there and the fallback
     picks up the root-level token instead. */
  background-color: var(--dialog-backdrop, var(--background-modal));

  opacity: 0;
  transition:
    opacity var(--dialog-exit-duration) var(--dialog-exit-easing),
    display var(--dialog-exit-duration) allow-discrete,
    overlay var(--dialog-exit-duration) allow-discrete;
}

/* -- Entrance / exit --
   A top-layer element can only transition out of display:none with
   allow-discrete, and can only transition *in* with @starting-style. The
   `overlay` property is what keeps the dialog painted in the top layer for
   the duration of the exit — without it the close is instant.
   Engines missing either feature show and hide the dialog with no animation,
   which is a clean degradation rather than a broken state. */

.dialog[open] {
  display: flex;

  opacity: 1;
  translate: 0 0;
  transition:
    opacity var(--dialog-enter-duration) var(--dialog-enter-easing),
    translate var(--dialog-enter-duration) var(--dialog-enter-easing),
    display var(--dialog-enter-duration) allow-discrete,
    overlay var(--dialog-enter-duration) allow-discrete;
}

.dialog[open]::backdrop {
  opacity: 1;
  transition:
    opacity var(--dialog-enter-duration) var(--dialog-enter-easing),
    display var(--dialog-enter-duration) allow-discrete,
    overlay var(--dialog-enter-duration) allow-discrete;
}

/* Must follow the [open] rules — this supplies the "before open" state only. */
@starting-style {
  .dialog[open] {
    opacity: 0;
    translate: 0 var(--dialog-offset);
  }

  .dialog[open]::backdrop {
    opacity: 0;
  }
}

/* -- Reduced motion -- */
/* Drops the travel and shortens to a plain fade. Re-points tokens rather than
   disabling the transition, so the discrete display/overlay steps still run
   and the dialog can't get stuck mid-exit. */
@media (prefers-reduced-motion: reduce) {
  .dialog {
    --dialog-offset: 0px;
    --dialog-enter-duration: var(--duration-2xs);
    --dialog-exit-duration: var(--duration-2xs);
  }
}

.dialog-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-l);
}

.dialog-title {
  font-size: var(--font-3xl);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-m);
  color: var(--text-primary);
  margin: 0;
}

/* Deprecated — use <button class="button close-btn" data-icon-only data-size="small">.
   Kept so existing markup keeps its styling; remove at the next major. */
.dialog-close {
  flex-shrink: 0;
  color: var(--text-faded);
  transition: color var(--duration-2xs) var(--ease-out);
}

.dialog-close:hover {
  color: var(--text-primary);
}

.dialog-body {
  overflow-y: auto;
  flex: 1;
  /* Column flex items default to min-height: auto, which stops the body
     shrinking and pushes the footer actions out of the dialog. */
  min-height: 0;
  overscroll-behavior: contain;
}

.dialog-body > *:first-child {
  margin-top: 0;
}

.dialog-body > *:last-child {
  margin-bottom: 0;
}

.dialog-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-m);
  flex-wrap: wrap;
}

/* -- Dialog dark mode -- */
/* Re-points tokens rather than redeclaring rules, so a brand override of
   --dialog-background survives the theme switch. */
[data-theme="dark"] .dialog {
  --dialog-background: var(--background-secondary);
  --dialog-shadow: 0 8px 40px var(--black-alpha-60);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .dialog {
    --dialog-background: var(--background-secondary);
    --dialog-shadow: 0 8px 40px var(--black-alpha-60);
  }
}


/* ------ 30. DRAWER ------ */

/* A drawer is a dialog docked to an edge of the viewport. It shares the native
   <dialog> element, the modal machinery in dialog.js (showModal, native Escape,
   native focus trapping) and the same top-layer entrance/exit technique as
   section 29 — @starting-style to transition in, allow-discrete + overlay to
   transition out. Only the docking geometry and the slide axis differ, so read
   the transition comments in section 29 first; they are not repeated here.

   Nothing in this section duplicates .dialog: a drawer is <dialog class="drawer">
   and never carries both classes. */

.drawer {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --drawer-background: var(--background-primary);
  --drawer-shadow: 0 8px 32px var(--black-alpha-20);
  --drawer-radius: 0;
  --drawer-padding: var(--space-xl);
  --drawer-backdrop: var(--background-modal);
  /* Width when docked to an inline edge, height when docked to a block edge.
     One token covers both because only one axis is ever free. */
  --drawer-size: 25rem;

  /* -- Motion -- */
  /* Faster than a dialog in both directions: a drawer travels the full width of
     its own box, so the same duration would read as sluggish. */
  --drawer-enter-duration: var(--duration-s);
  --drawer-enter-easing: var(--ease-out);
  --drawer-exit-duration: var(--duration-xs);
  --drawer-exit-easing: var(--ease-in);
  /* How far the drawer travels when closed. Percentages resolve against its
     own border box, so 100% parks it exactly off-screen whatever
     --drawer-size is.

     Magnitude and direction are deliberately split. The placement rules below
     are more specific than `.drawer`, so if they carried the magnitude too,
     the reduced-motion block — which can only reach `.drawer` — would lose the
     cascade and leave reduced-motion users with the full slide crammed into a
     shorter duration. Placement sets direction only; magnitude stays here,
     declared exactly once, where the media query can reach it. */
  --drawer-travel: 100%;
  --drawer-offset: 0 0;

  background-color: var(--drawer-background);
  border: none;
  border-radius: var(--drawer-radius);
  box-shadow: var(--drawer-shadow);
  padding: var(--drawer-padding);
  /* The UA stylesheet centres a dialog with margin:auto — that would undo the
     docking insets below. */
  margin: 0;

  /* Layout lives here, not on [open] — see the note in section 29. */
  flex-direction: column;
  gap: var(--space-l);

  /* Closed / exit state. */
  opacity: 0;
  translate: var(--drawer-offset);
  transition:
    opacity var(--drawer-exit-duration) var(--drawer-exit-easing),
    translate var(--drawer-exit-duration) var(--drawer-exit-easing),
    display var(--drawer-exit-duration) allow-discrete,
    overlay var(--drawer-exit-duration) allow-discrete;
}

.drawer::backdrop {
  /* Fallback rationale as section 29. */
  background-color: var(--drawer-backdrop, var(--background-modal));

  opacity: 0;
  transition:
    opacity var(--drawer-exit-duration) var(--drawer-exit-easing),
    display var(--drawer-exit-duration) allow-discrete,
    overlay var(--drawer-exit-duration) allow-discrete;
}

/* -- Placement --
   Two placements dock to the inline edges and take a width; two dock to the
   block edges and take a height. In each pair the free axis is stretched with
   a paired inset and the docked axis is pinned, with the opposite inset reset
   to auto so the UA's `inset: 0` cannot stretch the drawer across the viewport.
   `end` is the default, so an omitted attribute matches it. */

/* Inline-edge sizing. Written as "anything that is not an explicit block-edge
   placement" so a typo (data-placement="left") degrades to a working end-docked
   drawer. Matching only the known values would leave an unrecognised one with
   no placement rule at all — the UA's `inset: 0` would then stretch it edge to
   edge with no slide and no warning. */
.drawer:not([data-placement="top"]):not([data-placement="bottom"]) {
  inset-block: 0;
  block-size: auto;
  max-block-size: none;
  inline-size: var(--drawer-size);
  max-inline-size: 100%;
}

.drawer[data-placement="start"] {
  inset-inline-start: 0;
  inset-inline-end: auto;
  --drawer-offset: calc(var(--drawer-travel) * -1) 0;
}

/* `end` is the default, and the landing place for an unrecognised value. */
.drawer:not([data-placement="start"]):not([data-placement="top"]):not([data-placement="bottom"]) {
  inset-inline-end: 0;
  inset-inline-start: auto;
  --drawer-offset: var(--drawer-travel) 0;
}

.drawer[data-placement="top"],
.drawer[data-placement="bottom"] {
  inset-inline: 0;
  inline-size: auto;
  max-inline-size: none;
  block-size: var(--drawer-size);
  max-block-size: 100%;
}

.drawer[data-placement="top"] {
  inset-block-start: 0;
  inset-block-end: auto;
  --drawer-offset: 0 calc(var(--drawer-travel) * -1);
}

.drawer[data-placement="bottom"] {
  inset-block-end: 0;
  inset-block-start: auto;
  --drawer-offset: 0 var(--drawer-travel);
}

/* The insets above are logical and follow the element's own direction, but
   `translate` has no logical form — its first value is always physical X. In
   RTL the inline placements dock to the opposite side, so the slide direction
   must flip with them or the drawer animates away from its own edge.
   `:dir()` rather than `[dir="rtl"] &` so that dir set on the drawer itself
   counts, not only dir on an ancestor. */
.drawer[data-placement="start"]:dir(rtl) {
  --drawer-offset: var(--drawer-travel) 0;
}

.drawer:not([data-placement="start"]):not([data-placement="top"]):not([data-placement="bottom"]):dir(rtl) {
  --drawer-offset: calc(var(--drawer-travel) * -1) 0;
}

/* -- Entrance / exit -- */

.drawer[open] {
  display: flex;

  opacity: 1;
  translate: 0 0;
  transition:
    opacity var(--drawer-enter-duration) var(--drawer-enter-easing),
    translate var(--drawer-enter-duration) var(--drawer-enter-easing),
    display var(--drawer-enter-duration) allow-discrete,
    overlay var(--drawer-enter-duration) allow-discrete;
}

.drawer[open]::backdrop {
  opacity: 1;
  transition:
    opacity var(--drawer-enter-duration) var(--drawer-enter-easing),
    display var(--drawer-enter-duration) allow-discrete,
    overlay var(--drawer-enter-duration) allow-discrete;
}

/* Must follow the [open] rules — supplies the "before open" state only. */
@starting-style {
  .drawer[open] {
    opacity: 0;
    translate: var(--drawer-offset);
  }

  .drawer[open]::backdrop {
    opacity: 0;
  }
}

/* showModal() makes the rest of the page inert but does not stop it scrolling.
   Behind a full-height drawer that reads as the drawer itself scrolling, so
   pin the page while one is open. Scoped to .drawer deliberately — .dialog has
   never locked scroll and changing that belongs with a dialog change.

   Both elements are targeted because which one scrolls depends on the document.
   This only reaches a page whose scroller IS the root: an app that scrolls a
   container div, or drives scrolling through a library, has to lock its own
   scroller (noted in cms/drawer.md). Pages without a stable scrollbar gutter
   will shift by the scrollbar width on open — set `scrollbar-gutter: stable`
   on :root in the consuming product if that matters there. */
html:has(.drawer[open]),
body:has(.drawer[open]) {
  overflow: hidden;
}

/* -- Blocked-close feedback --
   A cancelled close (see drawer-hide / dialog-hide in dialog.js) leaves the
   surface open with nothing to show for the click. The pulse says "heard you,
   not closing" — without it a guarded surface reads as a broken close button.
   Axis-agnostic, so one animation serves all four drawer placements and the
   centred dialog. Shared because dialog.js pulses BOTH: styling only .drawer
   would leave a guarded dialog with a state class and no feedback. */
.dialog.is-pulsing,
.drawer.is-pulsing {
  animation: surface-pulse var(--duration-xs) var(--ease-in-out);
}

@keyframes surface-pulse {
  50% {
    scale: 1.008;
  }
}

/* -- Reduced motion -- */
/* Drops the travel and shortens to a plain fade, re-pointing tokens rather than
   disabling the transition so the discrete display/overlay steps still run and
   the drawer cannot get stuck mid-exit (same reasoning as section 29). The
   pulse becomes a backdrop flash: scale is exactly the kind of motion the
   preference asks us to drop, but silent failure is worse than no feedback. */
@media (prefers-reduced-motion: reduce) {
  .drawer {
    /* Zeroing the magnitude is what actually drops the travel — the placement
       rules only carry direction, so they cannot override this. */
    --drawer-travel: 0%;
    --drawer-enter-duration: var(--duration-2xs);
    --drawer-exit-duration: var(--duration-2xs);
  }

  .dialog.is-pulsing,
  .drawer.is-pulsing {
    animation: none;
  }

  .dialog.is-pulsing::backdrop,
  .drawer.is-pulsing::backdrop {
    animation: surface-backdrop-flash var(--duration-xs) var(--ease-in-out);
  }

  @keyframes surface-backdrop-flash {
    50% {
      opacity: 0.7;
    }
  }
}

/* -- Structure -- */

.drawer-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-l);
}

.drawer-title {
  font-size: var(--font-2xl);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-m);
  color: var(--text-primary);
  margin: 0;
}

/* Supplementary controls sitting beside the close button. */
.drawer-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
}

.drawer-body {
  overflow-y: auto;
  flex: 1;
  /* Column flex items default to min-height:auto, which stops the body
     shrinking and pushes the footer out of the drawer. */
  min-height: 0;
  overscroll-behavior: contain;
}

.drawer-body > *:first-child {
  margin-top: 0;
}

.drawer-body > *:last-child {
  margin-bottom: 0;
}

.drawer-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-m);
  flex-wrap: wrap;
}

/* -- Drawer dark mode -- */
/* Re-points tokens rather than redeclaring rules, so a brand override of
   --drawer-background survives the theme switch. */
[data-theme="dark"] .drawer {
  --drawer-background: var(--background-secondary);
  --drawer-shadow: 0 8px 40px var(--black-alpha-60);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .drawer {
    --drawer-background: var(--background-secondary);
    --drawer-shadow: 0 8px 40px var(--black-alpha-60);
  }
}


/* ------ 31. SLIDER ------ */

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  background-color: var(--background-darker);
  border-radius: var(--radius-pill);
  outline: none;
  cursor: pointer;
  border: none;
  padding: 0;
  display: block;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-color: var(--text-primary);
  border: 2px solid var(--background-primary);
  cursor: pointer;
  box-shadow: 0 1px 4px var(--black-alpha-20);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}

input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-color: var(--text-primary);
  border: 2px solid var(--background-primary);
  cursor: pointer;
  box-shadow: 0 1px 4px var(--black-alpha-20);
}

input[type="range"]:hover::-webkit-slider-thumb {
  transform: scale(1.1);
  box-shadow: 0 2px 8px var(--black-alpha-20);
}

input[type="range"]:focus-visible {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
  border-radius: var(--radius-pill);
}

input[type="range"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

input[type="range"]:disabled::-webkit-slider-thumb {
  cursor: not-allowed;
}

.slider-wrapper {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.slider-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: var(--font-s);
  color: var(--text-primary);
}

.slider-value {
  font-family: var(--font-quaternary);
  font-size: var(--font-xs);
  color: var(--text-faded);
}


/* ------ 32. RATING ------ */

.rating {
  display: inline-flex;
  gap: var(--space-xs);
  align-items: center;
}

.rating-star {
  width: var(--rating-size);
  height: var(--rating-size);
  cursor: pointer;
  color: var(--background-faded);
  transition: color 0.1s ease, transform 0.1s ease;
  flex-shrink: 0;
}

.rating-star svg path {
  stroke: var(--text-faded);
  stroke-width: var(--border-m);
}

.rating-star.is-filled,
.rating-star.is-hovered {
  color: var(--yellow);
}


.rating-star.is-filled svg path,
.rating-star.is-hovered svg path {
  stroke: var(--text-primary);
}


.rating-star:hover {
  transform: scale(1.1);
}

.rating-star:focus-visible {
  outline: none;
  border-radius: var(--radius-xs);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.rating.is-readonly .rating-star {
  cursor: default;
  pointer-events: none;
}

.rating.is-readonly .rating-star:hover {
  transform: none;
}

.rating--sm { --rating-size: 1rem; }
.rating--lg { --rating-size: 2rem; }


/* ------ 33. COPY BUTTON ------ */

.copy-btn {
  position: relative;
}

/* -- State: default -- */
.copy-btn .copy-btn-default { display: inline-flex; align-items: center; gap: var(--space-s); }
.copy-btn .copy-btn-copied  { display: none; }

/* -- State: copied -- */
.copy-btn.is-copied .copy-btn-default { display: none; }
.copy-btn.is-copied .copy-btn-copied  { display: inline-flex; align-items: center; gap: var(--space-s); }

.copy-btn.is-copied {
  color: var(--status-success);
  border-color: var(--status-success);
  background-color: color-mix(in srgb, var(--status-success), var(--alpha-10));
}

/* -- Variant: icon only -- */
.copy-btn.is-icon-only {
  padding: var(--space-s);
}

/* -- Variant: ghost (no background, no border) -- */
.copy-btn.is-ghost {
  background: none;
  border: none;
  padding: var(--space-xs);
  color: var(--text-primary);
}

.copy-btn.is-ghost:hover {
  color: var(--text-faded);
}

.copy-btn.is-ghost.is-copied {
  background: none;
  border: none;
  color: var(--status-success);
}

/* -- Tooltip: force visible on copied state -- */
.copy-btn.is-copied[data-tooltip]::before {
  opacity: 1;
}


/* ------ 34. NUMBER INPUT ------ */

.number-input {
  display: inline-flex;
  align-items: stretch;
  width: fit-content;
  border: var(--border-s) solid var(--input-border);
  overflow: hidden;
  background-color: var(--input-background);
}

.number-input:focus-within {
  border-color: var(--input-focus);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.number-input input[type="number"] {
  border: none;
  background: transparent;
  text-align: center;
  width: 4rem;
  padding: var(--space-m) var(--space-xs);
  box-shadow: none;
  -moz-appearance: textfield;
  appearance: textfield;
}

.number-input input[type="number"]:focus {
  outline: none;
  border: none;
  box-shadow: none;
}

.number-input input[type="number"]::-webkit-outer-spin-button,
.number-input input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
}

.number-input-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  background-color: var(--background-faded);
  border: none;
  border-radius: 0;
  color: var(--text-primary);
  cursor: pointer;
  font-size: var(--font-xl);
  line-height: 1;
  transition: background-color 0.1s ease;
  flex-shrink: 0;
}

.number-input-btn:hover {
  background-color: var(--background-darker);
}

.number-input-btn:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

.number-input-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}


/* ------ 35. RADIO GROUP ------ */

.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
}

.radio-group.is-horizontal {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--space-m) var(--space-xl);
}

.radio-group-label {
  font-size: var(--font-s);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  margin-bottom: var(--space-xs);
  display: block;
}

.radio-group-hint {
  font-size: var(--font-xs);
  color: var(--text-faded);
  margin-top: var(--space-2xs);
  display: block;
}


/* ------ 36. DROP CAP ------ */

/*
 * Apply .drop-cap or data-drop-cap to a <p> element to style its first
 * letter as a large decorative initial. Use on long paragraphs only —
 * the text must wrap alongside the letter for at least 3 lines.
 */

.drop-cap::first-letter,
[data-drop-cap]::first-letter {
  float: left;
  font-family: var(--font-secondary);
  font-size: 3.2rem;
  font-weight: var(--font-weight-regular);
  line-height: 0.94;
  color: var(--text-primary);
  padding-right: var(--space-s);
  margin-top: 0.06em;
  text-transform: uppercase;
}

.drop-cap::after,
[data-drop-cap]::after {
  content: "";
  display: table;
  clear: both;
}


/* NOTE: .token-copy, .token-swatch, .asset-card, .dont-card moved to docs-site.css
 * — see CLAUDE.md §17 (Layer Discipline) */


/* ------ 37. BOOK ------
 * The navigation surfaces of a documentation space, modelled as a book:
 *
 *   .book-shelf          L0 — a grid of books to choose from
 *   .book-cover          L0 — one closed book
 *   .book-contents       L1 — the table of contents of an opened book
 *   .book-contents-item  L1 — one line in that contents list
 *
 * The row is a contents *item*, not a page. In a book the thing you click
 * in the contents is an entry; the thing you land on is the page. Moving
 * sideways between pages is .page-nav (section 38); moving back up is
 * .breadcrumb (section 18).
 *
 * TWO KINDS OF SLOT, named on two different principles:
 *
 *   leading / trailing  — position. They frame the surface and hold an icon.
 *                         Generic on purpose: another product's trailing icon
 *                         might be a chevron, an arrow, or a download glyph.
 *   byline / meta       — content type. They carry text about the item, so
 *                         naming them by position would say nothing useful.
 *
 * On a cover, leading/trailing are the header's two ends; the footer's two
 * ends are byline and meta, because what belongs there is text rather than
 * icons. On a row there is only one line, so leading and trailing are
 * unambiguous and meta moves inside the body, under the description.
 *
 * Neither slot may hold an interactive control. The surface is already a
 * link, so a nested button is invalid HTML and unreachable in several
 * screen-reader modes. `trailing` holds an icon that *hints* at what
 * clicking does — it is not an action control.
 *
 *   <div class="book-shelf">
 *     <a href="/brand/" class="book-cover">
 *       <header class="book-cover-header">
 *         <div class="book-cover-leading">…</div>    ← optional, varies
 *         <div class="book-cover-trailing">…</div>   ← open-full
 *       </header>
 *       <div class="book-cover-body">
 *         <h3 class="book-cover-title">Brand Book</h3>
 *         <p class="book-cover-description">Brand identity, values…</p>
 *       </div>
 *       <footer class="book-cover-footer">
 *         <span class="book-cover-byline"><em>by</em> Studio</span>
 *         <span class="book-cover-meta">…</span>     ← optional metadata
 *       </footer>
 *     </a>
 *   </div>
 *
 * ENGINE vs INSTANCE: the component guarantees the slots. Which icon goes in
 * `trailing`, and whether it stays the same across a shelf, is an instance
 * decision. By Default keeps it constant, because constancy is what signals
 * "this opens" — but that is a usage rule, not a property of the component.
 *
 * Re-skin by re-pointing the component tokens. Never override the rules.
 */

/* -- Book shelf (L0 index) --
 * Owns its grid rather than composing .grid.cols-2.gap-xl: a component that
 * depends on the consumer applying the right utility combo is not portable.
 * It carries its own breakpoint for the same reason — .grid's collapse would
 * not follow it into another codebase.
 */
.book-shelf {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --book-shelf-columns: 2;
  --book-shelf-gap: var(--space-xl);

  display: grid;
  grid-template-columns: repeat(var(--book-shelf-columns), minmax(0, 1fr));
  gap: var(--book-shelf-gap);
}

.book-shelf[data-cols="3"] {
  --book-shelf-columns: 3;
}

/* Both selectors are listed because a media query adds no specificity: the
   (0,2,0) attribute rule above would otherwise keep three columns on mobile. */
@media (max-width: 768px) {
  .book-shelf,
  .book-shelf[data-cols="3"] {
    --book-shelf-columns: 1;
  }
}

/* Group headings above a shelf or a contents list. Same treatment as
   .eyebrow, declared rather than composed, so the heading stays restylable
   independently of the utility. */
.book-shelf-title,
.book-contents-title {
  font-size: var(--font-xs);
  line-height: var(--line-height-m);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--letter-spacing-l);
  text-transform: uppercase;
}


/* -- Book cover (L0 tile) -- */
.book-cover {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --book-cover-min-height: 250px;
  --book-cover-title-size: var(--font-5xl);
  --book-cover-background: var(--background-primary);
  --book-cover-background-hover: var(--background-faded);
  --book-cover-border: var(--border-s) solid var(--border-faded);
  --book-cover-bar-padding: var(--space-m) var(--space-l);
  --book-cover-body-padding: var(--space-2xl);
  --book-cover-lift: -2px;
  --book-cover-shadow-hover: 0 7px 1px -3px var(--black-alpha-10);

  display: flex;
  flex-direction: column;
  min-height: var(--book-cover-min-height);
  background: var(--book-cover-background);
  border: var(--book-cover-border);
  color: inherit;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  text-wrap: pretty;
  transition:
    border var(--duration-xs) var(--ease-out),
    background-color var(--duration-xs) var(--ease-out),
    box-shadow var(--duration-xs) var(--ease-out),
    transform var(--duration-xs) var(--ease-out);
}

/* Size re-points height, title and inset together — a short cover with a
   full-size title reads as a mistake rather than a variant. */
.book-cover[data-size="small"] {
  --book-cover-min-height: 170px;
  --book-cover-title-size: var(--font-3xl);
  --book-cover-body-padding: var(--space-l);
}

.book-cover[data-size="large"] {
  --book-cover-min-height: 340px;
  --book-cover-title-size: var(--font-6xl);
  --book-cover-body-padding: var(--space-3xl);
}

/* The heading scale steps by restating font-size on the element, not by
   re-pointing a token — so a class that sets its own size has to carry the
   step itself, or it stays at desktop size on every phone. Every step drops
   two rungs, matching h1-h6.

   This block must stay BELOW the size variants: the bare .book-cover rule
   here is (0,1,0) against their (0,2,0), so the variants' own steps only win
   on source order. Move it above them and both sizes silently revert to
   desktop type. */
@media (max-width: 959px) {
  .book-cover {
    --book-cover-title-size: var(--font-3xl);
  }

  .book-cover[data-size="small"] {
    --book-cover-title-size: var(--font-2xl);
  }

  .book-cover[data-size="large"] {
    --book-cover-title-size: var(--font-4xl);
  }
}

/* Header and footer are the same shape: a full-width strip carrying a start
   slot and an end slot. Empty slots are simply absent; the end slot's auto
   margin holds its side either way, so no spacer elements are needed. */
.book-cover-header,
.book-cover-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  flex-shrink: 0;
  padding: var(--book-cover-bar-padding);
}

.book-cover-leading,
.book-cover-trailing,
.book-cover-meta {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  flex-shrink: 0;
}

/* End-of-strip slots hold their side whether or not a start slot sits
   beside them. Action lives in the header, meta in the footer, so the two
   auto margins never compete inside one strip. */
.book-cover-trailing,
.book-cover-meta {
  margin-inline-start: auto;
}

.book-cover-trailing .svg-icn {
  opacity: 0;
  transition: opacity var(--duration-xs) var(--ease-out);
}

/* Focus reveals the affordance too — a keyboard user tabbing a shelf should
   see what a mouse user sees. */
a.book-cover:hover .book-cover-trailing .svg-icn,
a.book-cover:focus-visible .book-cover-trailing .svg-icn {
  opacity: 1;
}

.book-cover-byline,
.book-cover-meta {
  font-size: var(--font-s);
  color: var(--text-secondary);
}

/* A byline is the general case of "by X" — an author, a maintainer, whoever
   last touched it. Naming it for the concept rather than for `author` keeps
   it usable where the thing has no author. */
.book-cover-byline em,
.book-contents-item-byline em {
  font-style: italic;
}

.book-cover-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--book-cover-body-padding);
}

.book-cover-title {
  margin-top: 0;
  margin-bottom: var(--space-s);
  font-size: var(--book-cover-title-size);
  line-height: var(--title-leading);
  font-weight: var(--font-weight-regular);
}

.book-cover-description {
  color: var(--text-secondary);
  font-size: var(--body-size);
  margin-bottom: 0;
}

a.book-cover:hover {
  color: var(--text-primary);
  background: var(--book-cover-background-hover);
  transform: translateY(var(--book-cover-lift));
  box-shadow: var(--book-cover-shadow-hover);
}

a.book-cover:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

/* -- Book cover dark mode -- */
[data-theme="dark"] .book-cover {
  --book-cover-background: var(--background-secondary);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .book-cover {
    --book-cover-background: var(--background-secondary);
  }
}

/* Re-point the travel token rather than blanket-disabling the transition,
   matching how .dialog and .drawer handle reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .book-cover {
    --book-cover-lift: 0;
  }
}


/* -- Book contents (L1 index) --
 * Entries stack vertically as wide horizontal rows, rather than the tall
 * centred covers used on the shelf. Same slot vocabulary as the cover:
 * identity leads, action trails.
 *
 *   <div class="book-contents">
 *     <a class="book-contents-item">
 *       <div class="book-contents-item-leading">…</div>   ← optional, varies
 *       <div class="book-contents-item-body">
 *         <h3 class="book-contents-item-title">Colour</h3>
 *         <p class="book-contents-item-description">Palette, tokens…</p>
 *       </div>
 *       <span class="book-contents-item-meta">…</span>     ← optional status
 *       <div class="book-contents-item-trailing">…</div>
 *     </a>
 *   </div>
 */
.book-contents {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --book-contents-border: var(--border-s) solid var(--border-faded);

  display: flex;
  flex-direction: column;
  border: var(--book-contents-border);
}

.book-contents-item {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --book-contents-item-padding: var(--space-xl);
  --book-contents-item-gap: var(--space-xl);
  --book-contents-item-title-size: var(--font-4xl);
  --book-contents-item-background-hover: var(--background-faded);

  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--book-contents-item-gap);
  padding: var(--book-contents-item-padding);
  border-bottom: var(--border-s) solid var(--border-faded);
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duration-xs) var(--ease-out);
}

.book-contents-item:hover {
  background: var(--book-contents-item-background-hover);
}

.book-contents-item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus), var(--alpha-75));
}

/* Content grows so identity stays left and meta/action stay right, whatever
   combination of slots is present. flex-basis stays auto so text wraps
   exactly as it did before the slots existed. */
.book-contents-item-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--space-2xs);
  min-width: 0;
}

/* A row is one horizontal line, so it has no header or footer strip to hang
   slots off — identity leads and action trails. That is why the cover's
   separate author and meta slots collapse into meta here: on a row they would
   be two arbitrary adjacent boxes rather than two ends of a strip. */
.book-contents-item-leading,
.book-contents-item-trailing {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  flex-shrink: 0;
}

/* Meta sits INSIDE the content column, under the description, rather than as
   a fourth item on the row. On the cover, meta lives in the footer strip and
   so gets a line of its own; a row has no strip, so trailing meta would be
   the one slot competing for horizontal space with the title. Identity and
   action refuse to shrink, so everything a trailing meta took would come out
   of the title — worst exactly where space is tightest. Under the
   description it wraps instead of squeezing, and reads as belonging to the
   item rather than floating at the far edge. */
.book-contents-item-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-m);
  margin-top: var(--space-2xs);
  font-size: var(--font-s);
  color: var(--text-secondary);
  padding-top: var(--space-s);
}

/* On a row the byline lives inside meta rather than in a slot of its own —
   a row has no footer strip with two ends to separate them. */
.book-contents-item-byline {
  white-space: nowrap;
}

.book-contents-item-title {
  margin: 0;
  font-size: var(--book-contents-item-title-size);
  line-height: var(--title-leading);
  font-weight: var(--title-weight);
}

/* Same reason as the cover title: a class that sets its own size has to
   carry the heading scale's breakpoint step itself. */
@media (max-width: 959px) {
  .book-contents-item {
    --book-contents-item-title-size: var(--font-2xl);
  }
}

.book-contents-item-description {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--body-size);
}

.book-contents-item-trailing .svg-icn {
  opacity: 0;
  flex-shrink: 0;
  transition: opacity var(--duration-xs) var(--ease-out);
}

a.book-contents-item:hover .book-contents-item-trailing .svg-icn,
a.book-contents-item:focus-visible .book-contents-item-trailing .svg-icn {
  opacity: 1;
}


/* ------ 38. PAGE NAVIGATION (PREV / NEXT) ------
 * Prev/next across any ordered sequence of pages. It knows nothing about
 * what the sequence is — pair it with .book-contents (section 37) for a
 * documentation space, or with anything else that has an order.
 *
 * Both directions render from identical markup and are flipped by
 * data-direction, so this is one component with a variant rather than two
 * that share class names.
 *
 *   <nav class="page-nav" aria-label="Page navigation">
 *     <div class="page-nav-inner">
 *       <a class="page-nav-link" data-direction="prev" rel="prev">
 *         <div class="svg-icn page-nav-arrow">…</div>
 *         <span class="page-nav-text">
 *           <span class="page-nav-label">Previous</span>
 *           <span class="page-nav-section">Brand Book</span>  ← only when crossing
 *           <span class="page-nav-title">4.4 Iconography</span>
 *         </span>
 *       </a>
 *       <a class="page-nav-link" data-direction="next" rel="next">…</a>
 *     </div>
 *   </nav>
 *
 * The section line appears only when the neighbour sits in a different
 * section — it marks leaving one book for the next, so showing it on every
 * page would turn a signpost into chrome.
 *
 * With no neighbour in a direction, nothing renders for that side.
 * grid-column pins each link to its own half, so the survivor keeps its
 * side without a placeholder element to hide.
 *
 * Re-skin by re-pointing the component tokens. Never override the rules.
 */

.page-nav {
  /* -- Component tokens (re-point these to re-skin; never override the rules) -- */
  --page-nav-background: var(--background-primary);
  --page-nav-background-hover: var(--background-faded);
  --page-nav-border: var(--border-s) solid var(--border-faded);
  --page-nav-link-padding: var(--space-xl) var(--space-2xl);
  --page-nav-link-gap: var(--space-m);
  --page-nav-title-size: var(--font-5xl);
  --page-nav-arrow-color: var(--text-secondary);
  --page-nav-arrow-color-hover: var(--text-link);

  border-top: var(--page-nav-border);
}

/* The heading scale steps by restating font-size on the elements rather than
   re-pointing a token, so a component replacing a heading has to carry the
   step itself. Mirrors the h3 step at the same breakpoint. */
@media (max-width: 959px) {
  .page-nav {
    --page-nav-title-size: var(--font-3xl);
  }
}

.page-nav-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}

.page-nav-link {
  display: flex;
  align-items: center;
  gap: var(--page-nav-link-gap);
  padding: var(--page-nav-link-padding);
  border: none;
  background: var(--page-nav-background);
  text-decoration: none;
  color: var(--text-primary);
  transition: background-color var(--duration-xs) var(--ease-out);
}

.page-nav-link[data-direction="prev"] {
  grid-column: 1;
}

/* A reversed row packs to the right and puts the arrow outermost, which is
   what lets both directions share one markup shape. */
.page-nav-link[data-direction="next"] {
  grid-column: 2;
  flex-direction: row-reverse;
  text-align: right;
}

.page-nav-link:hover {
  background-color: var(--page-nav-background-hover);
  color: var(--text-primary);
}

.page-nav-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  min-width: 0;
}

.page-nav-label {
  font-size: var(--font-xs);
  font-family: var(--font-primary);
  color: var(--text-secondary);
  font-weight: var(--font-weight-semi-bold);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-l);
}

.page-nav-section {
  font-size: var(--font-2xs);
  color: var(--text-faded);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-m);
  font-weight: var(--font-weight-medium);
}

/* Sized here rather than inherited from a heading element: the title labels
   a link, it does not open a section, so it renders as a span. */
.page-nav-title {
  margin: 0;
  font-family: var(--font-primary);
  font-size: var(--page-nav-title-size);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--title-tracking);
  line-height: var(--title-leading);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.page-nav-arrow {
  flex-shrink: 0;
  color: var(--page-nav-arrow-color);
  transition: color var(--duration-xs) var(--ease-out);
}

.page-nav-link:hover .page-nav-arrow {
  color: var(--page-nav-arrow-color-hover);
}

/* Single column: both directions collapse into column 1 and stack as rows.
   Without resetting grid-column, next would address an implicit second
   column and the collapse would not take. The breakpoint travels with the
   component rather than living in a shared responsive section. */
@media (max-width: 768px) {
  .page-nav-inner {
    grid-template-columns: 1fr;
  }

  .page-nav-link[data-direction="prev"],
  .page-nav-link[data-direction="next"] {
    grid-column: 1;
  }

  .page-nav-link[data-direction="prev"] {
    border-bottom: var(--page-nav-border);
  }

  /* Keep the base row-reverse: the DOM order is [arrow, text], so a plain
     `row` would put the right-chevron on the left. */
  .page-nav-link[data-direction="next"] {
    text-align: left;
  }
}


/* ------ 15. COMPONENTS IN PROGRESS ------ */
/*
 * The following components are actively being built.
 * Remove each item from this list as it is implemented above.
 * See cms/components.md for the full component spec and build rules.
 *
 * REMAINING:
 * (all components implemented)
 *
 * IMPLEMENTED IN THIS FILE:
 * - [x] Button (.button)
 * - [x] Form elements (inputs, select, textarea, checkbox, radio, toggle, segmented control)
 * - [x] Callout (.callout)
 * - [x] Disclosure (details/summary)
 * - [x] Badge (.badge)
 * - [x] Card (.card)
 * - [x] Tabs (.tabs)
 * - [x] Progress (.progress-bar)
 * - [x] Tooltip (data-tooltip)
 * - [x] Toast (.toast)
 * - [x] Breadcrumb (.breadcrumb)
 * - [x] code / pre / kbd / mark / abbr / figure
 * - [x] Scrollbar
 * - [x] Divider (.divider)
 * - [x] Dropdown (.dropdown)
 * - [x] Tag (.tag)
 * - [x] Dialog (.dialog)
 * - [x] Slider (input[type="range"])
 * - [x] Rating (.rating)
 * - [x] Number Input (.number-input)
 * - [x] Radio Group (.radio-group)
 * - [x] Drop Cap (.drop-cap)
 * - [x] Book (.book-shelf, .book-cover, .book-contents)
 * - [x] Page Navigation (.page-nav)
 */

