/* ==========================================================================
   APEXVYRA — main stylesheet
   ==========================================================================
   Layers, in order: SETTINGS, RESET, BASE, LAYOUT, COMPONENTS, UTILITIES, PAGES.
   Every colour, size, radius, shadow, duration and font resolves to a token
   defined in SETTINGS. To re-skin the template, edit SETTINGS only — see
   documentation/index.html Section 6 ("How to change colours").
   Naming: BEM-ish, prefixed `av-` (av-card, av-card__header, av-card--elevated).
   ========================================================================== */


/* ==========================================================================
   1. SETTINGS — design tokens
   ========================================================================== */

@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-ext-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-ext-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-ext-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter/inter-latin-ext-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-ext-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-ext-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/space-grotesk/space-grotesk-latin-ext-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light;

  /* ---- COLOR: neutral ramp (hue 255, low chroma) ---- */
  --av-neutral-0:   oklch(99% 0.002 255);
  --av-neutral-20:  oklch(96% 0.004 255);
  --av-neutral-20:  oklch(91% 0.006 255);
  --av-neutral-30:  oklch(84% 0.008 255);
  --av-neutral-40:  oklch(74% 0.010 255);
  --av-neutral-50:  oklch(62% 0.012 255);
  --av-neutral-60:  oklch(50% 0.012 255);
  --av-neutral-70:  oklch(40% 0.012 255);
  --av-neutral-80:  oklch(30% 0.012 255);
  --av-neutral-90:  oklch(22% 0.010 255);
  --av-neutral-95:  oklch(18% 0.008 255);
  --av-neutral-200: oklch(14% 0.006 255);

  /* ---- COLOR: role mapping, light theme (default) ---- */
  --av-bg:                 var(--av-neutral-20);
  --av-surface:             var(--av-neutral-0);
  --av-surface-raised:      var(--av-neutral-0);
  --av-border:              var(--av-neutral-20);
  --av-border-interactive:  var(--av-neutral-50);
  --av-text:                var(--av-neutral-90);
  --av-text-muted:          var(--av-neutral-60);
  --av-text-disabled:       var(--av-neutral-40);
  --av-placeholder:         var(--av-neutral-40);

  /* ---- COLOR: brand ---- */
  /* Deep, deliberately desaturated navy — not the vivid 45%L/0.14C blue this
     started as. Three near-identical-but-not-quite blues (nav CTA, hero CTA,
     Router hub) read as sloppiness once seen in one viewport; this is now
     the ONE primary, used everywhere, with no scoped per-section override.
     11.44:1 as white-on-primary and as primary-on-paper — the darkening was
     free from a contrast standpoint, and it also reads calmer next to the
     accent amber, matching the "precision console" restraint of Signal Path
     better than the original louder blue did. */
  /* --av-primary-fill / --av-primary-text: split from --av-primary after
     axe-core found real contrast failures rendering --av-primary directly
     as both a solid button background (needs to stay dark enough for white
     text) and as foreground text/icon color on --av-primary-soft (needs to
     stay far enough from that soft background) — two opposite lightness
     requirements the base token can't satisfy everywhere at once. Light
     theme's own --av-primary (34% L) already clears both roles comfortably
     (11.44:1 as white-on-primary, and as primary-on-paper), so both new
     tokens simply equal it here; only the dark-theme values differ. */
  --av-primary-fill:   oklch(34% 0.07 255);
  --av-primary-text:   oklch(34% 0.07 255);
  --av-primary:        oklch(34% 0.07 255);
  --av-primary-strong: oklch(27% 0.06 255);
  --av-primary-soft:   oklch(92% 0.03 255);
  --av-accent:         oklch(72% 0.19 55);
  /* --av-accent-text: darkened from 55% to 50% — axe-core found the
     original only cleared 4.98:1 against --av-surface (the plain paper
     card background DECISIONS.md computed against) but the hero's actual
     backdrop is --av-bg (--av-neutral-20, a darker 91%-lightness gray, not
     --av-surface's 99%), where it measured 3.92:1. 50% clears 4.5:1 against
     the darker --av-bg too. */
  --av-accent-text:    oklch(50% 0.18 55);
  /* --av-accent-soft: a solid, pre-computed tint — .av-badge--accent used
     to compute its background live as `oklch(from var(--av-accent) l c h /
     0.14)`, a translucent overlay whose EFFECTIVE color depends on whatever
     surface sits behind it. Two real instances of the same badge measured
     two different (and both failing) contrast ratios depending on section
     background. Every other badge variant already uses a solid, opaque
     `--av-X-soft` token; accent now matches that pattern instead of being
     the one variant with an unpredictable backdrop. */
  --av-accent-soft:    oklch(93% 0.05 55);

  /* ---- COLOR: semantic ---- */
  --av-success:       oklch(65% 0.15 145);
  /* -text values below darkened from their originals (53/55/58/54%) after
     axe-core measured each one's REAL contrast against its own -soft badge
     background (93% L) at 3.8-4.1:1 — all four were tuned by eye close to
     the 4.5:1 line and landed just under it once actually rendered. */
  --av-success-text:  oklch(50% 0.15 145);
  --av-success-soft:  oklch(93% 0.04 145);
  --av-warning:       oklch(75% 0.16 80);
  --av-warning-text:  oklch(51% 0.16 80);
  --av-warning-soft:  oklch(93% 0.05 80);
  --av-danger:        oklch(58% 0.20 25);
  /* --av-danger-text: previously aliased to raw --av-danger (58%, the same
     value used for icons/borders) instead of getting its own dedicated
     text-safe value like the other three semantic colors already had —
     the one inconsistency in this set, and the reason it measured the
     worst (3.80:1) of the four. */
  --av-danger-text:   oklch(53% 0.20 25);
  --av-danger-soft:   oklch(93% 0.04 25);
  --av-info:          oklch(60% 0.12 235);
  --av-info-text:     oklch(50% 0.12 235);
  --av-info-soft:     oklch(93% 0.03 235);

  /* ---- TYPE ---- */
  --av-font-display: 'Space Grotesk', system-ui, sans-serif;
  --av-font-ui:      'Inter', system-ui, sans-serif;
  --av-font-code:    ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  --av-text-xs:   clamp(0.75rem, 0.72rem + 0.1vw, 0.8rem);
  --av-text-sm:   clamp(0.875rem, 0.85rem + 0.1vw, 0.925rem);
  --av-text-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --av-text-md:   clamp(1.25rem, 1.18rem + 0.35vw, 1.375rem);
  --av-text-lg:   clamp(1.5625rem, 1.45rem + 0.6vw, 1.75rem);
  --av-text-xl:   clamp(1.953rem, 1.75rem + 1vw, 2.25rem);
  --av-text-2xl:  clamp(2.441rem, 2.1rem + 1.7vw, 3rem);
  --av-text-3xl:  clamp(3.052rem, 2.5rem + 2.7vw, 4rem);
  --av-leading-tight: 1.1;
  --av-leading-snug: 1.3;
  --av-leading-normal: 1.6;
  --av-tracking-tight: -0.02em;
  --av-tracking-normal: 0;
  --av-tracking-wide: 0.04em;

  /* ---- SPACING (4px base) ---- */
  --av-space-1: 0.25rem;  --av-space-2: 0.5rem;   --av-space-3: 0.75rem;
  --av-space-4: 1rem;     --av-space-5: 1.25rem;  --av-space-6: 1.5rem;
  --av-space-8: 2rem;     --av-space-10: 2.5rem;  --av-space-12: 3rem;
  --av-space-16: 4rem;    --av-space-20: 5rem;    --av-space-24: 6rem;
  --av-space-32: 8rem;    --av-space-40: 10rem;
  --av-container-max: 80rem;
  --av-container-wide: 82.5rem;
  --av-section-space: var(--av-space-24);
  --av-section-space-tablet: var(--av-space-16);
  --av-section-space-mobile: var(--av-space-12);

  /* ---- RADIUS ---- */
  --av-radius-sm: 0.375rem;
  --av-radius-lg: 0.875rem;
  --av-radius-full: 999px;

  /* ---- ELEVATION (sparing — floating layers only) ---- */
  --av-shadow-sm: 0 1px 2px oklch(14% 0.006 255 / 0.06);
  --av-shadow-md: 0 4px 12px oklch(14% 0.006 255 / 0.10);
  --av-shadow-lg: 0 12px 32px oklch(14% 0.006 255 / 0.14);

  /* ---- MOTION ---- */
  --av-duration-micro: 100ms;
  --av-duration-feedback: 150ms;
  --av-duration-entrance: 250ms;
  --av-duration-panel: 400ms;
  --av-ease-entrance: cubic-bezier(0.16, 1, 0.3, 1);
  --av-ease-feedback: cubic-bezier(0.4, 0, 0.2, 1);

  /* ---- Z-INDEX scale (documented so buyers don't guess) ---- */
  --av-z-dropdown: 300;
  --av-z-sticky: 400;
  --av-z-drawer: 500;
  --av-z-modal: 600;
  --av-z-toast: 700;
  --av-z-command-palette: 800;
  --av-z-tooltip: 900;
}

[data-theme='dark'] {
  color-scheme: dark;

  --av-bg:                 var(--av-neutral-95);
  --av-surface:             var(--av-neutral-90);
  --av-surface-raised:      var(--av-neutral-80);
  --av-border:              var(--av-neutral-80);
  --av-border-interactive:  oklch(66% 0.012 255); /* dedicated value: neutral-60 only cleared 2.89:1 against --av-surface (lighter than --av-bg) — caught by tools/qa.mjs contrast check, see DECISIONS.md */
  --av-text:                var(--av-neutral-20);
  /* --av-text-muted: dedicated value, no longer aliased to --av-neutral-50
     (62% L) — axe-core measured it at 3.75:1 against --av-surface-raised
     (--av-neutral-80, 30% L; cards are "raised" via lightness in dark mode,
     so muted text on a card sits on a lighter background than --av-surface
     itself). 68% clears 4.5:1 against the raised surface too. */
  --av-text-muted:          oklch(68% 0.012 255);
  --av-text-disabled:       var(--av-neutral-70);
  --av-placeholder:         var(--av-neutral-70);

  /* --av-primary-fill: dedicated darker value for solid button/badge fills
     that carry white text — axe-core measured the base --av-primary
     (62% L) at only 3.57:1 against white. 54% clears 4.5:1. */
  --av-primary-fill:   oklch(54% 0.14 255);
  /* --av-primary-text: dedicated lighter value for text/icon color ON
     --av-primary-soft (avatars, mega-menu icons, pills) — axe-core measured
     the base --av-primary at only 3.95:1 against --av-primary-soft (28% L).
     68% clears 4.5:1 with margin for the slightly-varied custom avatar
     background hues that reuse this same role. */
  --av-primary-text:   oklch(68% 0.14 255);
  --av-primary:        oklch(62% 0.14 255);
  --av-primary-strong: oklch(70% 0.13 255);
  --av-primary-soft:   oklch(28% 0.05 255);
  --av-accent:         oklch(72% 0.19 55);
  --av-accent-text:    var(--av-accent);
  /* --av-accent-soft: solid tint, matching every other badge variant —
     see the light-theme definition above for why the old translucent
     overlay was replaced. */
  --av-accent-soft:    oklch(25% 0.05 55);

  --av-success-text:  var(--av-success);
  --av-success-soft:  oklch(25% 0.04 145);
  --av-warning-text:  var(--av-warning);
  --av-warning-soft:  oklch(25% 0.05 80);
  /* --av-danger-text / --av-info-text: nudged 1 point lighter (64->65,
     62->63) — axe-core measured both just under 4.5:1 (4.43 / 4.47) once
     .av-badge's dark-mode specificity bug (see the ".av-badge.av-badge--X"
     comment in the badge component) stopped silently overriding their
     --X-soft background with plain neutral-80 gray and they actually
     rendered against their intended --danger-soft / --info-soft. */
  --av-danger-text:   oklch(65% 0.18 25);
  --av-danger-soft:   oklch(25% 0.04 25);
  --av-info-text:     oklch(63% 0.12 235);
  --av-info-soft:     oklch(25% 0.03 235);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --av-duration-micro: 0ms;
    --av-duration-feedback: 0ms;
    --av-duration-entrance: 0ms;
    --av-duration-panel: 0ms;
  }
}


/* ==========================================================================
   2. RESET — modern, minimal
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* [hidden] has the same specificity (0,1,0) as any class selector, so a
   component that sets its own `display` (e.g. .av-empty-state { display:
   flex }) silently defeats the browser's default [hidden]{display:none} —
   the author rule loads after the UA stylesheet and wins the tie. This is
   the one deliberate !important in the stylesheet: [hidden] must always
   mean not displayed, full stop, for every current and future component. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scrollbar-gutter: stable;
}

body { min-height: 100svh; }

img, picture, svg, video, canvas { display: block; max-width: 100%; }

input, button, textarea, select { font: inherit; color: inherit; }

button { background: none; border: none; cursor: pointer; }

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; padding: 0; }

table { border-collapse: collapse; border-spacing: 0; }

p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

#av-root, #root { isolation: isolate; }


/* ==========================================================================
   3. BASE — element defaults, typography, focus, selection, scrollbar
   ========================================================================== */

body {
  font-family: var(--av-font-ui);
  font-size: var(--av-text-base);
  line-height: var(--av-leading-normal);
  color: var(--av-text);
  background: var(--av-bg);
  transition: background-color var(--av-duration-entrance) var(--av-ease-feedback),
              color var(--av-duration-entrance) var(--av-ease-feedback);
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--av-font-display);
  font-weight: 600;
  line-height: var(--av-leading-tight);
  letter-spacing: var(--av-tracking-tight);
  color: var(--av-text);
  text-wrap: balance;
}

h1 { font-size: var(--av-text-3xl); }
h2 { font-size: var(--av-text-2xl); }
h3 { font-size: var(--av-text-xl); }
h4 { font-size: var(--av-text-lg); font-family: var(--av-font-ui); font-weight: 600; letter-spacing: var(--av-tracking-normal); }
h5 { font-size: var(--av-text-md); font-family: var(--av-font-ui); font-weight: 600; letter-spacing: var(--av-tracking-normal); }
h6 { font-size: var(--av-text-base); font-family: var(--av-font-ui); font-weight: 600; letter-spacing: var(--av-tracking-normal); }

p { text-wrap: pretty; }
small { font-size: var(--av-text-sm); }

::selection {
  background: oklch(34% 0.07 255);
  color: oklch(0% 0 0);
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--av-border-interactive); border-radius: var(--av-radius-full); border: 2px solid var(--av-bg); }
* { scrollbar-width: thin; scrollbar-color: var(--av-border-interactive) transparent; }

:focus-visible {
  outline: 2px solid var(--av-primary);
  outline-offset: 2px;
  border-radius: var(--av-radius-sm);
}

.av-skip-link {
  position: absolute;
  left: var(--av-space-4);
  top: -100px;
  background: var(--av-surface);
  color: var(--av-text);
  padding: var(--av-space-3) var(--av-space-4);
  border-radius: var(--av-radius-sm);
  border: 1px solid var(--av-border);
  box-shadow: var(--av-shadow-md);
  z-index: var(--av-z-toast);
  transition: top var(--av-duration-feedback) var(--av-ease-feedback);
}
.av-skip-link:focus { top: var(--av-space-4); }


/* ==========================================================================
   4. LAYOUT — container, grid utilities, section spacing, stack/cluster
   ========================================================================== */

.av-container {
  width: 100%;
  max-width: var(--av-container-max);
  margin-inline: auto;
  padding-inline: var(--av-space-6);
}
.av-container--wide { max-width: var(--av-container-wide); }
.av-container--narrow { max-width: 48rem; }

.av-section {
  padding-block: var(--av-section-space-mobile);
}
@media (min-width: 48rem) {
  .av-section { padding-block: var(--av-section-space-tablet); }
}
@media (min-width: 64rem) {
  .av-section { padding-block: var(--av-section-space); }
}

/* Stack: vertical rhythm with a single gap value */
.av-stack { display: flex; flex-direction: column; }
.av-stack--1 { gap: var(--av-space-1); }
.av-stack--2 { gap: var(--av-space-2); }
.av-stack--3 { gap: var(--av-space-3); }
.av-stack--4 { gap: var(--av-space-4); }
.av-stack--6 { gap: var(--av-space-6); }
.av-stack--8 { gap: var(--av-space-8); }

/* Cluster: horizontal grouping, wraps */
.av-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--av-space-3);
}

/* Grid: simple responsive column system */
.av-grid { display: grid; gap: var(--av-space-6); }
.av-grid > * { min-width: 0; } /* same overflow gotcha as .av-split — see its comment */
.av-grid--2 { grid-template-columns: repeat(1, 1fr); }
.av-grid--3 { grid-template-columns: repeat(1, 1fr); }
.av-grid--4 { grid-template-columns: repeat(1, 1fr); }
@media (min-width: 40rem) {
  .av-grid--2 { grid-template-columns: repeat(2, 1fr); }
  .av-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .av-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 64rem) {
  .av-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .av-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.av-split {
  display: grid;
  gap: var(--av-space-8);
  grid-template-columns: 1fr;
  align-items: center;
}
.av-split > * { min-width: 0; } /* grid items default to min-width:auto — without this, a <pre> or other intrinsically-wide child (e.g. an unwrapped code line) refuses to shrink below its content width and blows out the track on narrow viewports, even though .av-code__pre itself has overflow-x:auto to handle exactly this */
@media (min-width: 64rem) {
  .av-split { grid-template-columns: 1fr 1fr; }
  /* Visually swap columns while keeping DOM/reading order intact (so screen
     readers and keyboard tab order stay logical) — used to alternate which
     side the text sits on across repeated .av-split rows, e.g. a zigzag
     "how it works" sequence, without duplicating markup per direction. */
  .av-split--reverse > *:first-child { order: 2; }
  .av-split--reverse > *:last-child { order: 1; }
}


/* ==========================================================================
   5. COMPONENTS
   One block per component, alphabetical. Each header states the markup
   contract. Components auto-init from data-av-* attributes (see
   assets/js/components/) — no JS edits needed to reuse a component.
   ========================================================================== */

/* ---- Accordion --------------------------------------------------------
   <div class="av-accordion" data-av-accordion>
     <div class="av-accordion__item">
       <h3><button class="av-accordion__trigger" aria-expanded="false" aria-controls="id">Q</button></h3>
       <div class="av-accordion__panel" id="id" role="region" hidden>...</div>
     </div>
   </div>
   Add `data-av-accordion="single"` to close other items when one opens.
-------------------------------------------------------------------------- */
.av-accordion { display: flex; flex-direction: column; }
.av-accordion__item { border-bottom: 1px solid var(--av-border); }
.av-accordion__item:first-child { border-top: 1px solid var(--av-border); }
.av-accordion__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--av-space-4);
  width: 100%;
  padding: var(--av-space-5) var(--av-space-2);
  text-align: left;
  font-weight: 600;
  font-size: var(--av-text-base);
  color: var(--av-text);
}
.av-accordion__trigger:hover { color: var(--av-primary); }
.av-accordion__icon {
  flex-shrink: 0;
  width: 1.125rem;
  height: 1.125rem;
  transition: transform var(--av-duration-feedback) var(--av-ease-feedback);
}
.av-accordion__trigger[aria-expanded='true'] .av-accordion__icon { transform: rotate(180deg); }
.av-accordion__panel {
  padding: 0 var(--av-space-2) var(--av-space-5);
  color: var(--av-text-muted);
}
.av-accordion__panel[hidden] { display: none; }

/* ---- Alert -------------------------------------------------------------
   <div class="av-alert av-alert--info" role="status">
     <svg class="av-alert__icon"><use href="#av-icon-info"/></svg>
     <div class="av-alert__body"><p class="av-alert__title">Title</p><p>Message</p></div>
     <button class="av-alert__close" aria-label="Dismiss">...</button>
   </div>
   Variants: --info (default), --success, --warning, --danger.
-------------------------------------------------------------------------- */
.av-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--av-space-3);
  padding: var(--av-space-4);
  border-radius: var(--av-radius-lg);
  border: 1px solid var(--av-border);
  background: var(--av-surface);
  font-size: var(--av-text-sm);
}
.av-alert[hidden] { display: none; } /* without this, the native [hidden] default loses to .av-alert's own `display: flex` at equal specificity — every demo-form success alert (av-form-success) sitewide was rendering visible on load despite hidden="true" */
.av-alert__icon { width: 1.25rem; height: 1.25rem; flex-shrink: 0; margin-top: 0.125rem; }
.av-alert__body { flex: 1; }
.av-alert__title { font-weight: 600; margin-bottom: var(--av-space-1); }
.av-alert__close { flex-shrink: 0; width: 1.25rem; height: 1.25rem; color: var(--av-text-muted); }
.av-alert__close:hover { color: var(--av-text); }
.av-alert--info { background: var(--av-info-soft); border-color: transparent; color: var(--av-info-text); }
.av-alert--success { background: var(--av-success-soft); border-color: transparent; color: var(--av-success-text); }
.av-alert--warning { background: var(--av-warning-soft); border-color: transparent; color: var(--av-warning-text); }
.av-alert--danger { background: var(--av-danger-soft); border-color: transparent; color: var(--av-danger-text); }
.av-alert--info .av-alert__title,
.av-alert--success .av-alert__title,
.av-alert--warning .av-alert__title,
.av-alert--danger .av-alert__title { color: var(--av-text); }

/* ---- Auth (split layout: brand panel + form, login/register/forgot) ------
   <div class="av-auth">
     <div class="av-auth__panel">
       <a class="av-nav__brand" href="index.html">APEXVYRA</a>
       <blockquote class="av-auth__quote">...</blockquote>
     </div>
     <div class="av-auth__form"><div class="av-auth__form-inner">...</div></div>
   </div>
   Brand panel is hidden below 64rem — on mobile the form is the whole
   screen, which is the right tradeoff for a task-focused auth flow.
-------------------------------------------------------------------------- */
.av-auth { min-height: 100svh; display: grid; grid-template-columns: 1fr; }
@media (min-width: 64rem) { .av-auth { grid-template-columns: 5fr 7fr; } }
.av-auth__panel {
  display: none;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--av-space-12);
  background: var(--av-neutral-95);
  color: var(--av-neutral-20);
}
@media (min-width: 64rem) { .av-auth__panel { display: flex; } }
.av-auth__panel .av-nav__brand { color: var(--av-neutral-0); }
.av-auth__quote { font-family: var(--av-font-display); font-size: var(--av-text-lg); line-height: var(--av-leading-snug); max-width: 32ch; }
.av-auth__quote-by { margin-top: var(--av-space-5); display: flex; align-items: center; gap: var(--av-space-3); font-family: var(--av-font-ui); font-size: var(--av-text-sm); color: var(--av-neutral-40); }
.av-auth__form { display: flex; align-items: center; justify-content: center; padding: var(--av-space-8); }
.av-auth__form-inner { width: 100%; max-width: 26rem; }
.av-auth__form-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--av-space-10); }
.av-auth__form-header .av-nav__brand { font-size: var(--av-text-base); }
@media (min-width: 64rem) { .av-auth__form-header .av-nav__brand { display: none; } } /* already shown in the panel at this width */
.av-auth__divider { display: flex; align-items: center; gap: var(--av-space-3); color: var(--av-text-muted); font-size: var(--av-text-xs); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); margin: var(--av-space-6) 0; }
.av-auth__divider::before, .av-auth__divider::after { content: ''; flex: 1; height: 1px; background: var(--av-border); }
.av-auth__step { display: none; }
.av-auth__step.is-active { display: block; }
.av-auth__steps-indicator { display: flex; gap: var(--av-space-2); margin-bottom: var(--av-space-8); }
.av-auth__steps-indicator span { height: 4px; flex: 1; border-radius: var(--av-radius-full); background: var(--av-neutral-20); }
[data-theme='dark'] .av-auth__steps-indicator span { background: var(--av-neutral-80); }
.av-auth__steps-indicator span.is-done, .av-auth__steps-indicator span.is-active { background: var(--av-primary); }

/* ---- Avatar --------------------------------------------------------------
   <span class="av-avatar" style="--av-avatar-bg: oklch(...)"><span class="av-avatar__initials">MT</span></span>
   Group: <div class="av-avatar-group"><span class="av-avatar">...</span>...</div>
-------------------------------------------------------------------------- */
.av-avatar {
  --av-avatar-bg: var(--av-primary-soft);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--av-radius-full);
  background: var(--av-avatar-bg);
  color: var(--av-primary-text);
  font-weight: 600;
  font-size: var(--av-text-sm);
  flex-shrink: 0;
  border: 2px solid var(--av-surface);
}
.av-avatar--sm { width: 2rem; height: 2rem; font-size: var(--av-text-xs); }
.av-avatar--lg { width: 3.5rem; height: 3.5rem; font-size: var(--av-text-md); }
.av-avatar-group { display: flex; }
.av-avatar-group .av-avatar { margin-left: -0.625rem; }
.av-avatar-group .av-avatar:first-child { margin-left: 0; }

/* ---- Back-to-top -----------------------------------------------------
   <button class="av-back-to-top" data-av-back-to-top aria-label="Back to top">
     <svg><use href="#av-icon-arrow-up-right"/></svg>
   </button>
   JS toggles `is-visible` after scroll threshold.
-------------------------------------------------------------------------- */
.av-back-to-top {
  position: fixed;
  right: var(--av-space-6);
  bottom: var(--av-space-6);
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--av-radius-full);
  background: var(--av-surface);
  border: 1px solid var(--av-border);
  box-shadow: var(--av-shadow-md);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: translateY(0.5rem);
  pointer-events: none;
  transition: opacity var(--av-duration-entrance) var(--av-ease-entrance),
              transform var(--av-duration-entrance) var(--av-ease-entrance);
  z-index: var(--av-z-sticky);
}
.av-back-to-top.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.av-back-to-top svg { width: 1.125rem; height: 1.125rem; transform: rotate(-45deg); }

/* ---- Badge (badges / tags / status pills) -------------------------------
   <span class="av-badge av-badge--success">Active</span>
   <span class="av-badge av-badge--dot av-badge--success"><i class="av-badge__dot"></i>Live</span>
-------------------------------------------------------------------------- */
.av-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--av-space-1);
  padding: 0.1875rem var(--av-space-2);
  border-radius: var(--av-radius-full);
  font-size: var(--av-text-xs);
  font-weight: 600;
  letter-spacing: var(--av-tracking-wide);
  text-transform: uppercase;
  background: var(--av-neutral-20);
  color: var(--av-text-muted);
}
[data-theme='dark'] .av-badge { background: var(--av-neutral-80); }
/* Selectors below are deliberately ".av-badge.av-badge--X" (two classes),
   matching the specificity of "[data-theme='dark'] .av-badge" above (an
   attribute selector + a class both count as one specificity component).
   With a single class, ".av-badge--success" tied on specificity and LOST
   in dark theme because the dark-mode base rule is a stronger selector —
   every variant silently fell back to plain neutral-80 gray, losing its
   color coding and its intended text/background contrast pairing. */
.av-badge.av-badge--success { background: var(--av-success-soft); color: var(--av-success-text); }
.av-badge.av-badge--warning { background: var(--av-warning-soft); color: var(--av-warning-text); }
.av-badge.av-badge--danger { background: var(--av-danger-soft); color: var(--av-danger-text); }
.av-badge.av-badge--info { background: var(--av-info-soft); color: var(--av-info-text); }
.av-badge.av-badge--accent { background: var(--av-accent-soft); color: var(--av-accent-text); }
.av-badge__dot {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: var(--av-radius-full);
  background: currentColor;
}
.av-badge--dot.av-badge--success .av-badge__dot { box-shadow: 0 0 0 3px oklch(from var(--av-success) l c h / 0.25); }

/* ---- Bento (asymmetric feature/value-prop grid — deliberately not N equal
   cards) -----------------------------------------------------------------
   <div class="av-bento">
     <div class="av-card av-bento__item--wide">...</div>
     <div class="av-card">...</div>
   </div>
   `.av-bento--dense` + `.av-bento__item--large` (span 2x2) for a 1-large
   + N-small tile grid (feature grid); plain `.av-bento` + `--wide` (span 2
   cols, same row) for a 1-wide + N-narrow grid (value props).
-------------------------------------------------------------------------- */
.av-bento { display: grid; grid-template-columns: 1fr; gap: var(--av-space-6); }
.av-bento > * { min-width: 0; } /* same overflow gotcha as .av-split — see its comment */
@media (min-width: 48rem) {
  .av-bento { grid-template-columns: repeat(3, 1fr); }
  .av-bento__item--wide { grid-column: span 2; }
  .av-bento--dense { grid-auto-flow: dense; }
  .av-bento--dense .av-bento__item--large { grid-column: span 2; grid-row: span 2; }
}
.av-bento .av-card { height: 100%; display: flex; flex-direction: column; gap: var(--av-space-3); }
.av-bento__icon { width: 2.5rem; height: 2.5rem; border-radius: var(--av-radius-sm); background: var(--av-primary-soft); color: var(--av-primary-text); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.av-bento__icon svg { width: 1.25rem; height: 1.25rem; }
.av-bento__item--large .av-bento__icon { width: 3rem; height: 3rem; }
.av-bento__item--large .av-bento__icon svg { width: 1.5rem; height: 1.5rem; }

/* ---- Breadcrumbs ---------------------------------------------------------
   <nav class="av-breadcrumbs" aria-label="Breadcrumb">
     <ol><li><a href="...">Home</a></li><li aria-current="page">Page</li></ol>
   </nav>
-------------------------------------------------------------------------- */
.av-breadcrumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--av-space-2); }
.av-breadcrumbs li { display: flex; align-items: center; gap: var(--av-space-2); font-size: var(--av-text-sm); color: var(--av-text-muted); }
.av-breadcrumbs li:not(:last-child)::after { content: ''; width: 1rem; height: 1rem; background: var(--av-text-disabled); mask: var(--av-chevron-mask, none); }
.av-breadcrumbs a:hover { color: var(--av-primary); }
.av-breadcrumbs li[aria-current='page'] { color: var(--av-text); font-weight: 500; }
.av-breadcrumbs__sep { width: 0.875rem; height: 0.875rem; color: var(--av-text-disabled); }


/* ---- Button ----------------------------------------------------------
   <button class="av-btn av-btn--primary av-btn--md">Label</button>
   Variants: --primary, --secondary, --outline, --ghost, --danger.
   Sizes: --sm, --md (default), --lg. Icon-only: add --icon + aria-label.
   Loading: add [data-loading] (keeps width, swaps label for spinner).
   Disabled: native [disabled].
-------------------------------------------------------------------------- */
.av-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--av-space-2);
  font-weight: 600;
  font-size: var(--av-text-sm);
  line-height: 1;
  padding: 0.625rem var(--av-space-4);
  border-radius: var(--av-radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background-color var(--av-duration-feedback) var(--av-ease-feedback),
              border-color var(--av-duration-feedback) var(--av-ease-feedback),
              color var(--av-duration-feedback) var(--av-ease-feedback),
              transform var(--av-duration-micro) var(--av-ease-feedback);
}
.av-btn:active { transform: translateY(1px); }
.av-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

.av-btn--primary { background: var(--av-primary-fill); color: var(--av-neutral-0); }
.av-btn--primary:hover:not(:disabled) { background: var(--av-primary-strong); }

.av-btn--secondary { background: var(--av-neutral-20); color: var(--av-text); }
[data-theme='dark'] .av-btn--secondary { background: var(--av-neutral-80); }
.av-btn--secondary:hover:not(:disabled) { background: var(--av-neutral-30); }
[data-theme='dark'] .av-btn--secondary:hover:not(:disabled) { background: var(--av-neutral-70); }

.av-btn--outline { background: transparent; border-color: var(--av-border-interactive); color: var(--av-text); }
.av-btn--outline:hover:not(:disabled) { border-color: var(--av-primary); color: var(--av-primary); }

.av-btn--ghost { background: transparent; color: var(--av-text); }
.av-btn--ghost:hover:not(:disabled) { background: var(--av-neutral-20); }
[data-theme='dark'] .av-btn--ghost:hover:not(:disabled) { background: var(--av-neutral-80); }

.av-btn--danger { background: var(--av-danger); color: var(--av-neutral-0); }
.av-btn--danger:hover:not(:disabled) { filter: brightness(0.92); }

.av-btn--sm { padding: 0.4375rem var(--av-space-3); font-size: var(--av-text-xs); }
.av-btn--lg { padding: var(--av-space-3) var(--av-space-6); font-size: var(--av-text-base); }

.av-btn--icon { padding: 0.625rem; width: 2.5rem; height: 2.5rem; }
.av-btn--icon.av-btn--sm { padding: 0.4375rem; width: 2rem; height: 2rem; }
.av-btn--icon.av-btn--lg { padding: var(--av-space-3); width: 3rem; height: 3rem; }

.av-btn__icon { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.av-btn--sm .av-btn__icon { width: 1rem; height: 1rem; }

.av-btn__spinner { display: none; width: 1rem; height: 1rem; animation: av-spin 0.7s linear infinite; }
.av-btn[data-loading] .av-btn__label { visibility: hidden; }
.av-btn[data-loading] .av-btn__spinner { display: block; position: absolute; }
.av-btn[data-loading] { position: relative; }

@keyframes av-spin { to { transform: rotate(360deg); } }

/* ---- Card ----------------------------------------------------------------
   <div class="av-card">
     <div class="av-card__header"><h3>Title</h3></div>
     <div class="av-card__body">...</div>
     <div class="av-card__footer">...</div>
   </div>
   Modifiers: --interactive (hover affordance for a clickable card),
   --elevated (one of the few places shadow is used deliberately), --bordered.
-------------------------------------------------------------------------- */
.av-card {
  background: var(--av-surface);
  border: 1px solid var(--av-border);
  border-radius: var(--av-radius-lg);
  padding: var(--av-space-6);
}
.av-card__header { margin-bottom: var(--av-space-4); display: flex; align-items: center; justify-content: space-between; gap: var(--av-space-3); }
.av-card__footer { margin-top: var(--av-space-4); padding-top: var(--av-space-4); border-top: 1px solid var(--av-border); }
.av-card--elevated { border-color: transparent; box-shadow: var(--av-shadow-md); }
.av-card--interactive { cursor: pointer; transition: border-color var(--av-duration-feedback) var(--av-ease-feedback), transform var(--av-duration-feedback) var(--av-ease-feedback); }
.av-card--interactive:hover { border-color: var(--av-border-interactive); transform: translateY(-2px); }
.av-card--flush { padding: 0; }

/* ---- Chart (shared container/axis/legend chrome for hand-built SVG charts) --
   <div class="av-chart" data-av-chart>
     <div class="av-chart__legend">...</div>
     <svg class="av-chart__svg" role="img" aria-label="...">...</svg>
     <table class="av-chart__table av-sr-only-focusable">...fallback data table...</table>
   </div>
-------------------------------------------------------------------------- */
.av-chart { display: flex; flex-direction: column; gap: var(--av-space-4); }
.av-chart__legend { display: flex; flex-wrap: wrap; gap: var(--av-space-4); font-size: var(--av-text-xs); color: var(--av-text-muted); }
.av-chart__legend-item { display: flex; align-items: center; gap: var(--av-space-2); }
.av-chart__legend-swatch { width: 0.625rem; height: 0.625rem; border-radius: var(--av-radius-full); }
.av-chart__svg { width: 100%; height: auto; overflow: visible; }
.av-chart__svg text { fill: var(--av-text-muted); font-family: var(--av-font-ui); font-size: 0.6875rem; font-variant-numeric: tabular-nums; }
.av-chart__grid-line { stroke: var(--av-border); stroke-width: 1; }
.av-chart__axis-line { stroke: var(--av-border-interactive); stroke-width: 1; }
.av-chart__series--primary { stroke: var(--av-primary); fill: none; }
.av-chart__series--accent { stroke: var(--av-accent-text); fill: none; } /* accent-text: a chart line is meaningful content, not decoration — same 3:1 reasoning as .av-signal-trace above */
.av-chart__area--primary { fill: var(--av-primary); opacity: 0.12; }
.av-chart__point { fill: var(--av-surface); stroke: var(--av-primary); stroke-width: 2; }
.av-chart__point:focus-visible { outline: 2px solid var(--av-primary); outline-offset: 2px; }
.av-chart__bar { fill: var(--av-primary); }
.av-chart__bar:hover, .av-chart__bar:focus-visible { fill: var(--av-primary-strong); }
.av-chart__table-toggle { align-self: flex-start; }
.av-chart__table { margin-top: calc(-1 * var(--av-space-2)); }
.av-chart__xaxis text { cursor: default; }
.av-chart__tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--av-neutral-90);
  color: var(--av-neutral-0);
  font-size: var(--av-text-xs);
  padding: var(--av-space-2) var(--av-space-3);
  border-radius: var(--av-radius-sm);
  box-shadow: var(--av-shadow-md);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--av-duration-feedback) var(--av-ease-feedback);
  z-index: var(--av-z-tooltip);
}
[data-theme='dark'] .av-chart__tooltip { background: var(--av-neutral-20); color: var(--av-neutral-200); }
.av-chart__tooltip.is-visible { opacity: 1; }

/* ---- Chat (AI Chat dashboard page — conversation list + thread + params) --
   <div class="av-chat" data-av-chat>
     <div class="av-chat__toolbar-mobile">...two [data-av-chat-aside-toggle] buttons...</div>
     <nav class="av-chat__aside av-chat__conversations" data-av-chat-aside="conversations">
       <div class="av-chat__aside-header">...[data-av-chat-aside-close]...</div>
       <div class="av-chat__conv-search"><input class="av-input" type="search"></div>
       <ul class="av-chat__conv-list"><li><button class="av-chat__conv" data-av-chat-conv="key" aria-current="true">
         <span class="av-avatar av-avatar--sm">RT</span>
         <span class="av-chat__conv-body"><span class="av-chat__conv-name">...</span><span class="av-chat__conv-snippet">...</span></span>
         <span class="av-chat__conv-time">10:42</span>
       </button></li></ul>
     </nav>
     <section class="av-chat__thread">
       <header class="av-chat__thread-header">...</header>
       <div class="av-chat__messages" data-av-chat-messages aria-live="polite">
         <div class="av-chat__message av-chat__message--assistant">
           <span class="av-avatar av-avatar--sm">...</span>
           <div><div class="av-chat__bubble">...</div>
             <div class="av-chat__meta">...</div>
             <div class="av-chat__actions">...copy/regenerate/branch buttons...</div>
           </div>
         </div>
       </div>
       <form class="av-chat__composer" data-av-chat-composer>
         <div class="av-chat__attachments" data-av-chat-attachments hidden></div>
         <div class="av-chat__composer-row">
           <button type="button" data-av-chat-attach>...</button>
           <textarea class="av-chat__input" data-av-chat-input></textarea>
           <input type="file" data-av-chat-file hidden>
           <button type="submit" data-av-chat-send>...</button>
         </div>
         <div class="av-chat__composer-meta"><span data-av-chat-token-count>...</span></div>
       </form>
     </section>
     <aside class="av-chat__aside av-chat__params" data-av-chat-aside="params">...model/temperature/prompt library, see chat-demo.js header...</aside>
     <div class="av-chat__backdrop" data-av-chat-backdrop hidden></div>
   </div>
   Below 1024px the two `.av-chat__aside` panels become off-canvas drawers
   (same idiom as `.av-sidebar`'s mobile mode) opened by the mobile toolbar
   buttons; `chat-demo.js` wires open/close + backdrop + Escape.
-------------------------------------------------------------------------- */
.av-chat { display: grid; grid-template-columns: 17rem minmax(0, 1fr) 18rem; gap: var(--av-space-6); height: min(46rem, calc(100vh - 14rem)); min-height: 32rem; position: relative; }
.av-chat__toolbar-mobile { display: none; }
.av-chat__aside { display: flex; flex-direction: column; min-width: 0; background: var(--av-surface); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg); overflow: hidden; }
.av-chat__aside-header { display: none; }
.av-chat__conv-search { padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); }
.av-chat__conv-list { list-style: none; margin: 0; padding: var(--av-space-2); overflow-y: auto; flex: 1; }
.av-chat__conv { display: flex; align-items: center; gap: var(--av-space-3); width: 100%; text-align: left; padding: var(--av-space-3); border-radius: var(--av-radius-md); background: transparent; border: none; cursor: pointer; color: inherit; font: inherit; }
.av-chat__conv:hover { background: var(--av-neutral-20); }
[data-theme='dark'] .av-chat__conv:hover { background: var(--av-neutral-80); }
.av-chat__conv[aria-current='true'] { background: var(--av-primary-soft); }
.av-chat__conv-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.125rem; }
.av-chat__conv-name { font-weight: 600; font-size: var(--av-text-sm); }
.av-chat__conv-snippet { font-size: var(--av-text-xs); color: var(--av-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.av-chat__conv-time { font-size: var(--av-text-xs); color: var(--av-text-muted); flex-shrink: 0; align-self: flex-start; }
.av-chat__thread { display: flex; flex-direction: column; min-width: 0; background: var(--av-surface); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg); overflow: hidden; }
.av-chat__thread-header { display: flex; align-items: center; justify-content: space-between; gap: var(--av-space-3); padding: var(--av-space-4) var(--av-space-6); border-bottom: 1px solid var(--av-border); flex-wrap: wrap; }
.av-chat__thread-header-title { display: flex; align-items: center; gap: var(--av-space-3); }
.av-chat__thread-title { font-size: var(--av-text-base); margin: 0; }
.av-chat__messages { flex: 1; overflow-y: auto; padding: var(--av-space-6); display: flex; flex-direction: column; gap: var(--av-space-5); }
.av-chat__message { display: flex; gap: var(--av-space-3); max-width: 36rem; }
.av-chat__message--user { flex-direction: row-reverse; margin-left: auto; }
.av-chat__message--assistant { margin-right: auto; }
.av-chat__bubble { background: var(--av-neutral-20); border-radius: var(--av-radius-lg); padding: var(--av-space-3) var(--av-space-4); font-size: var(--av-text-sm); white-space: pre-wrap; }
[data-theme='dark'] .av-chat__bubble { background: var(--av-neutral-80); }
.av-chat__message--user .av-chat__bubble { background: var(--av-primary-fill); color: var(--av-neutral-0); }
.av-chat__meta { font-size: var(--av-text-xs); color: var(--av-text-muted); margin-top: var(--av-space-1); display: flex; gap: var(--av-space-2); align-items: center; }
.av-chat__message--user .av-chat__meta { justify-content: flex-end; }
.av-chat__actions { display: flex; gap: var(--av-space-1); margin-top: var(--av-space-2); }
.av-chat__typing .av-chat__bubble { display: inline-flex; align-items: center; }
.av-chat__typing-dots { display: inline-flex; gap: 3px; }
.av-chat__typing-dots span { width: 5px; height: 5px; border-radius: var(--av-radius-full); background: var(--av-text-muted); animation: av-chat-typing 1s infinite ease-in-out; }
.av-chat__typing-dots span:nth-child(2) { animation-delay: 0.15s; }
.av-chat__typing-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes av-chat-typing { 0%, 80%, 100% { opacity: 0.3; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .av-chat__typing-dots span { animation: none; opacity: 1; } }
.av-chat__composer { border-top: 1px solid var(--av-border); padding: var(--av-space-4) var(--av-space-6); }
.av-chat__composer-row { display: flex; align-items: flex-end; gap: var(--av-space-2); }
.av-chat__input { flex: 1; resize: none; max-height: 8rem; border: 1px solid var(--av-border); border-radius: var(--av-radius-md); padding: var(--av-space-3); background: var(--av-bg); color: var(--av-text); font: inherit; }
.av-chat__input:focus-visible { outline: 2px solid var(--av-primary); outline-offset: 1px; }
.av-chat__composer-meta { display: flex; justify-content: space-between; align-items: center; gap: var(--av-space-3); margin-top: var(--av-space-2); font-size: var(--av-text-xs); color: var(--av-text-muted); flex-wrap: wrap; }
.av-chat__composer-meta [data-av-chat-token-count] { font-variant-numeric: tabular-nums; }
.av-chat__attachments { display: flex; flex-wrap: wrap; gap: var(--av-space-2); margin-bottom: var(--av-space-3); }
.av-chat__attachments[hidden] { display: none; }
.av-chat__attachment-chip { display: inline-flex; align-items: center; gap: var(--av-space-2); background: var(--av-neutral-20); border-radius: var(--av-radius-full); padding: var(--av-space-1) var(--av-space-3); font-size: var(--av-text-xs); }
[data-theme='dark'] .av-chat__attachment-chip { background: var(--av-neutral-80); }
.av-chat__attachment-chip button { display: inline-flex; background: none; border: none; color: inherit; cursor: pointer; padding: 0; }
.av-chat__attachment-chip svg { width: 0.875rem; height: 0.875rem; }
.av-chat__params-body { padding: var(--av-space-5); overflow-y: auto; display: flex; flex-direction: column; gap: var(--av-space-5); flex: 1; }
.av-chat__prompt-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--av-space-2); }
.av-chat__prompt-list button { width: 100%; text-align: left; }
.av-chat__backdrop { display: none; }
@media (max-width: 1023px) {
  .av-chat { grid-template-columns: minmax(0, 1fr); height: min(40rem, calc(100vh - 16rem)); }
  .av-chat__toolbar-mobile { display: flex; gap: var(--av-space-2); margin-bottom: var(--av-space-4); }
  .av-chat__aside { position: fixed; inset-block: 0; width: 85vw; max-width: 22rem; z-index: var(--av-z-modal); border-radius: 0; transition: transform var(--av-duration-panel) var(--av-ease-entrance); }
  .av-chat__aside-header { display: flex; align-items: center; justify-content: space-between; padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); }
  .av-chat__conversations { inset-inline-start: 0; transform: translateX(-100%); }
  .av-chat__params { inset-inline-end: 0; transform: translateX(100%); }
  .av-chat__aside.is-open { transform: translateX(0); }
  .av-chat__backdrop { display: block; position: fixed; inset: 0; background: oklch(0% 0 0 / 0.4); z-index: calc(var(--av-z-modal) - 1); }
  .av-chat__backdrop[hidden] { display: none; }
}
@media (prefers-reduced-motion: reduce) { .av-chat__aside { transition: none; } }

/* ---- Chip (integration/category tag — icon + label, not a full card) -----
   <span class="av-chip"><svg><use href="#av-icon-database"/></svg>Databases</span>
-------------------------------------------------------------------------- */
.av-chip { display: inline-flex; align-items: center; gap: var(--av-space-2); padding: var(--av-space-2) var(--av-space-4); border-radius: var(--av-radius-full); border: 1px solid var(--av-border); background: var(--av-surface); font-size: var(--av-text-sm); font-weight: 500; }
.av-chip svg { width: 1rem; height: 1rem; color: var(--av-text-muted); flex-shrink: 0; }
button.av-chip { cursor: pointer; border-color: var(--av-border-interactive); }
button.av-chip[aria-pressed='true'] { background: var(--av-primary-soft); border-color: var(--av-primary); color: var(--av-primary-text); }
button.av-chip[aria-pressed='true'] svg { color: var(--av-primary-text); }

/* ---- Code Block ------------------------------------------------------
   <div class="av-code" data-av-code>
     <div class="av-code__bar"><span class="av-code__lang">bash</span>
       <button class="av-code__copy" data-av-code-copy>Copy</button></div>
     <pre class="av-code__pre"><code>...</code></pre>
   </div>
-------------------------------------------------------------------------- */
.av-code {
  background: var(--av-neutral-90);
  color: var(--av-neutral-20);
  border-radius: var(--av-radius-lg);
  overflow: hidden;
  font-size: var(--av-text-sm);
}
[data-theme='dark'] .av-code { background: var(--av-neutral-200); }
.av-code__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--av-space-2) var(--av-space-4);
  border-bottom: 1px solid oklch(100% 0 0 / 0.08);
}
.av-code__lang { font-family: var(--av-font-code); font-size: var(--av-text-xs); color: var(--av-neutral-40); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); }
.av-code__copy {
  display: flex; align-items: center; gap: var(--av-space-1);
  font-size: var(--av-text-xs); color: var(--av-neutral-30);
  padding: var(--av-space-1) var(--av-space-2); border-radius: var(--av-radius-sm);
}
.av-code__copy:hover { color: var(--av-neutral-0); background: oklch(96% 0.002 255 / 0.08); }
.av-code__copy svg { width: 0.875rem; height: 0.875rem; }
.av-code__pre { padding: var(--av-space-4); overflow-x: auto; }
.av-code__pre code { font-family: var(--av-font-code); line-height: var(--av-leading-normal); white-space: pre; }
.av-code__token--key { color: oklch(75% 0.12 235); }
.av-code__token--string { color: oklch(75% 0.13 145); }
.av-code__token--comment { color: var(--av-neutral-50); font-style: italic; }
.av-code__token--keyword { color: oklch(75% 0.16 55); }

/* ---- Command Palette (⌘K) ----------------------------------------------
   <div class="av-command-palette" data-av-command-palette hidden role="dialog" aria-modal="true" aria-label="Command palette">
     <div class="av-command-palette__backdrop"></div>
     <div class="av-command-palette__panel">
       <div class="av-command-palette__search"><input type="text" placeholder="Search..." aria-label="Search"></div>
       <ul class="av-command-palette__list" role="listbox">
         <li class="av-command-palette__item" role="option">...</li>
       </ul>
     </div>
   </div>
   Opened via a trigger with [data-av-command-palette-trigger]. Toggle: Cmd/Ctrl+K.
-------------------------------------------------------------------------- */
.av-command-palette { position: fixed; inset: 0; z-index: var(--av-z-command-palette); }
.av-command-palette[hidden] { display: none; }
.av-command-palette__backdrop { position: absolute; inset: 0; background: oklch(14% 0.006 255 / 0.5); }
.av-command-palette__panel {
  position: relative;
  max-width: 36rem;
  margin: 12vh auto 0;
  background: var(--av-surface-raised);
  border-radius: var(--av-radius-lg);
  box-shadow: var(--av-shadow-lg);
  overflow: hidden;
  border: 1px solid var(--av-border);
}
.av-command-palette__search { display: flex; align-items: center; gap: var(--av-space-3); padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); }
.av-command-palette__search svg { width: 1.125rem; height: 1.125rem; color: var(--av-text-muted); flex-shrink: 0; }
.av-command-palette__search input { flex: 1; background: none; border: none; font-size: var(--av-text-base); color: var(--av-text); }
.av-command-palette__search input::placeholder { color: var(--av-placeholder); }
.av-command-palette__search input:focus-visible { outline: none; }
.av-command-palette__hint { font-size: var(--av-text-xs); color: var(--av-text-muted); border: 1px solid var(--av-border); border-radius: var(--av-radius-sm); padding: 0.125rem 0.375rem; }
.av-command-palette__list { max-height: 20rem; overflow-y: auto; padding: var(--av-space-2); }
.av-command-palette__item {
  display: flex; align-items: center; gap: var(--av-space-3);
  padding: var(--av-space-3); border-radius: var(--av-radius-sm);
  font-size: var(--av-text-sm); cursor: pointer;
}
.av-command-palette__item svg { width: 1rem; height: 1rem; color: var(--av-text-muted); }
.av-command-palette__item[aria-selected='true'] { background: var(--av-primary-soft); }
.av-command-palette__empty { padding: var(--av-space-8); text-align: center; color: var(--av-text-muted); font-size: var(--av-text-sm); }

/* ---- Cookie Consent (demo, no tracking set) ------------------------------
   <div class="av-cookie-bar" data-av-cookie-bar hidden>
     <p>We use only functional storage...</p>
     <div class="av-cookie-bar__actions"><button data-av-cookie-accept>Accept</button>
       <button data-av-cookie-decline>Decline</button></div>
   </div>
-------------------------------------------------------------------------- */
.av-cookie-bar {
  position: fixed;
  left: var(--av-space-4);
  right: var(--av-space-4);
  bottom: var(--av-space-4);
  max-width: 34rem;
  margin-inline: auto;
  background: var(--av-surface-raised);
  border: 1px solid var(--av-border);
  border-radius: var(--av-radius-lg);
  box-shadow: var(--av-shadow-lg);
  padding: var(--av-space-5);
  z-index: var(--av-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--av-space-4);
}
.av-cookie-bar[hidden] { display: none; }
.av-cookie-bar p { font-size: var(--av-text-sm); color: var(--av-text-muted); }
.av-cookie-bar__actions { display: flex; gap: var(--av-space-3); }


/* ---- Dashboard Shell (sidebar + topbar + content, dashboard/*.html only) -
   <div class="av-dashboard">
     <!-- @include dashboard-sidebar -->
     <div class="av-dashboard__main">
       <!-- @include dashboard-topbar -->
       <main class="av-dashboard__content">...</main>
     </div>
   </div>
-------------------------------------------------------------------------- */
.av-dashboard { display: flex; min-height: 100svh; }
.av-dashboard__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.av-dashboard__topbar {
  position: sticky; top: 0; z-index: var(--av-z-sticky);
  display: flex; align-items: center; gap: var(--av-space-4);
  padding: var(--av-space-4) var(--av-space-6);
  border-bottom: 1px solid var(--av-border); background: var(--av-bg);
}
.av-dashboard__content { flex: 1; min-width: 0; padding: var(--av-space-6); max-width: 90rem; width: 100%; margin-inline: auto; }
@media (min-width: 48rem) { .av-dashboard__content { padding: var(--av-space-8); } }
.av-sidebar__backdrop { display: none; position: fixed; inset: 0; background: oklch(14% 0.006 255 / 0.5); z-index: calc(var(--av-z-drawer) - 1); }
[data-av-sidebar-open] .av-sidebar__backdrop { display: block; }
@media (min-width: 64rem) { .av-sidebar__backdrop { display: none !important; } }

/* ---- Dropdown ------------------------------------------------------------
   <div class="av-dropdown" data-av-dropdown>
     <button class="av-btn av-btn--outline" aria-haspopup="true" aria-expanded="false">Menu</button>
     <div class="av-dropdown__menu" role="menu" hidden>
       <a class="av-dropdown__item" role="menuitem" href="...">Item</a>
       <div class="av-dropdown__divider"></div>
     </div>
   </div>
-------------------------------------------------------------------------- */
.av-dropdown { position: relative; display: inline-block; }
.av-dropdown__menu {
  position: absolute;
  top: calc(100% + var(--av-space-2));
  left: 0;
  min-width: 12rem;
  background: var(--av-surface-raised);
  border: 1px solid var(--av-border);
  border-radius: var(--av-radius-lg);
  box-shadow: var(--av-shadow-md);
  padding: var(--av-space-2);
  z-index: var(--av-z-dropdown);
}
.av-dropdown__menu[hidden] { display: none; }
.av-dropdown__menu--right { left: auto; right: 0; }
.av-dropdown__item {
  display: flex; align-items: center; gap: var(--av-space-3);
  padding: var(--av-space-2) var(--av-space-3);
  border-radius: var(--av-radius-sm);
  font-size: var(--av-text-sm);
  color: var(--av-text);
}
.av-dropdown__item svg { width: 1rem; height: 1rem; color: var(--av-text-muted); }
.av-dropdown__item:hover, .av-dropdown__item:focus-visible { background: var(--av-neutral-20); }
[data-theme='dark'] .av-dropdown__item:hover, [data-theme='dark'] .av-dropdown__item:focus-visible { background: var(--av-neutral-80); }
.av-dropdown__item--danger { color: var(--av-danger-text); }
.av-dropdown__divider { height: 1px; background: var(--av-border); margin: var(--av-space-2) 0; }

/* ---- Empty State -----------------------------------------------------
   <div class="av-empty-state">
     <svg class="av-empty-state__icon">...</svg>
     <h3>No projects yet</h3><p>...</p>
     <button class="av-btn av-btn--primary">Create project</button>
   </div>
-------------------------------------------------------------------------- */
.av-empty-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--av-space-3);
  padding: var(--av-space-16) var(--av-space-6);
  color: var(--av-text-muted);
}
.av-empty-state__icon { width: 3rem; height: 3rem; color: var(--av-text-disabled); margin-bottom: var(--av-space-2); }
.av-empty-state h3 { color: var(--av-text); }

/* ---- Error State (inline, e.g. failed widget/chart load) -----------------
   <div class="av-error-state" role="alert">
     <svg class="av-error-state__icon">...</svg>
     <p>Couldn't load this data.</p>
     <button class="av-btn av-btn--outline av-btn--sm">Retry</button>
   </div>
-------------------------------------------------------------------------- */
.av-error-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--av-space-3);
  padding: var(--av-space-12) var(--av-space-6);
}
.av-error-state__icon { width: 2.5rem; height: 2.5rem; color: var(--av-danger-text); }

/* ---- Form ------------------------------------------------------------
   <div class="av-field">
     <label class="av-field__label" for="id">Label</label>
     <input class="av-input" id="id" aria-describedby="id-help">
     <p class="av-field__help" id="id-help">Helper text</p>
     <p class="av-field__error" id="id-error" role="alert" hidden>Error text</p>
   </div>
   Error state: add [data-state="error"] to .av-field, aria-invalid to control.
   Controls: .av-input, .av-textarea, .av-select, .av-checkbox, .av-radio,
   .av-switch, .av-file, .av-range, .av-search.
-------------------------------------------------------------------------- */
.av-field { display: flex; flex-direction: column; gap: var(--av-space-2); }
.av-field__label { font-size: var(--av-text-sm); font-weight: 600; color: var(--av-text); }
.av-field__label--optional::after { content: ' (optional)'; font-weight: 400; color: var(--av-text-muted); }
.av-field__help { font-size: var(--av-text-xs); color: var(--av-text-muted); }
.av-field__error { font-size: var(--av-text-xs); color: var(--av-danger-text); display: flex; align-items: center; gap: var(--av-space-1); }
.av-field__error[hidden] { display: none; }
.av-field[data-state='error'] .av-input,
.av-field[data-state='error'] .av-textarea,
.av-field[data-state='error'] .av-select { border-color: var(--av-danger); }
.av-field[data-state='success'] .av-input,
.av-field[data-state='success'] .av-textarea { border-color: var(--av-success); }

.av-input, .av-textarea, .av-select {
  width: 100%;
  font-size: var(--av-text-sm);
  color: var(--av-text);
  background: var(--av-surface);
  border: 1px solid var(--av-border-interactive);
  border-radius: var(--av-radius-sm);
  padding: 0.625rem var(--av-space-3);
  transition: border-color var(--av-duration-feedback) var(--av-ease-feedback), box-shadow var(--av-duration-feedback) var(--av-ease-feedback);
}
.av-input::placeholder, .av-textarea::placeholder { color: var(--av-placeholder); }
.av-input:focus-visible, .av-textarea:focus-visible, .av-select:focus-visible {
  outline: none; border-color: var(--av-primary); box-shadow: 0 0 0 3px var(--av-primary-soft);
}
.av-input:disabled, .av-textarea:disabled, .av-select:disabled { background: var(--av-neutral-20); color: var(--av-text-disabled); cursor: not-allowed; }
[data-theme='dark'] .av-input:disabled, [data-theme='dark'] .av-textarea:disabled, [data-theme='dark'] .av-select:disabled { background: var(--av-neutral-90); }
.av-textarea { resize: vertical; min-height: 6rem; font-family: var(--av-font-ui); }
.av-select { appearance: none; background-image: none; padding-right: var(--av-space-8); }

.av-search { position: relative; }
.av-search input { padding-left: var(--av-space-10); }
.av-search svg { position: absolute; left: var(--av-space-3); top: 50%; transform: translateY(-50%); width: 1rem; height: 1rem; color: var(--av-text-muted); }

.av-password { position: relative; }
.av-password input { padding-right: var(--av-space-10); }
.av-password__toggle { position: absolute; right: var(--av-space-3); top: 50%; transform: translateY(-50%); color: var(--av-text-muted); }
.av-password__toggle svg { width: 1.125rem; height: 1.125rem; }

.av-checkbox, .av-radio { display: flex; align-items: center; gap: var(--av-space-3); font-size: var(--av-text-sm); cursor: pointer; }
.av-checkbox input, .av-radio input {
  appearance: none; width: 1.125rem; height: 1.125rem; flex-shrink: 0;
  border: 1px solid var(--av-border-interactive); background: var(--av-surface);
  display: grid; place-content: center;
}
.av-checkbox input { border-radius: 0.25rem; }
.av-radio input { border-radius: var(--av-radius-full); }
.av-checkbox input::before {
  content: ''; width: 0.65rem; height: 0.65rem;
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
  background: var(--av-neutral-0); transform: scale(0); transition: transform var(--av-duration-micro) var(--av-ease-feedback);
}
.av-radio input::before { content: ''; width: 0.55rem; height: 0.55rem; border-radius: var(--av-radius-full); background: var(--av-neutral-0); transform: scale(0); transition: transform var(--av-duration-micro) var(--av-ease-feedback); }
.av-checkbox input:checked, .av-radio input:checked { background: var(--av-primary); border-color: var(--av-primary); }
.av-checkbox input:checked::before, .av-radio input:checked::before { transform: scale(1); }
.av-checkbox input:focus-visible, .av-radio input:focus-visible { outline: 2px solid var(--av-primary); outline-offset: 2px; }
.av-checkbox input:disabled, .av-radio input:disabled { opacity: 0.5; cursor: not-allowed; }

.av-switch { display: inline-flex; align-items: center; gap: var(--av-space-3); cursor: pointer; }
.av-switch input { appearance: none; width: 2.5rem; height: 1.5rem; border-radius: var(--av-radius-full); background: var(--av-neutral-30); position: relative; transition: background-color var(--av-duration-feedback) var(--av-ease-feedback); flex-shrink: 0; }
[data-theme='dark'] .av-switch input { background: var(--av-neutral-70); }
.av-switch input::before {
  content: ''; position: absolute; top: 2px; left: 2px; width: 1.25rem; height: 1.25rem;
  border-radius: var(--av-radius-full); background: var(--av-neutral-0); box-shadow: var(--av-shadow-sm);
  transition: transform var(--av-duration-feedback) var(--av-ease-feedback);
}
.av-switch input:checked { background: var(--av-primary); }
.av-switch input:checked::before { transform: translateX(1rem); }
.av-switch input:focus-visible { outline: 2px solid var(--av-primary); outline-offset: 2px; }

.av-file {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--av-space-2);
  border: 1px dashed var(--av-border-interactive); border-radius: var(--av-radius-lg);
  padding: var(--av-space-8); text-align: center; color: var(--av-text-muted); font-size: var(--av-text-sm);
  cursor: pointer; transition: border-color var(--av-duration-feedback) var(--av-ease-feedback);
}
.av-file:hover, .av-file.is-dragover { border-color: var(--av-primary); color: var(--av-primary); }
.av-file svg { width: 1.75rem; height: 1.75rem; }
.av-file input[type='file'] { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }

.av-range { width: 100%; }
.av-range input {
  appearance: none; width: 100%; height: 4px; border-radius: var(--av-radius-full);
  background: var(--av-neutral-20);
}
[data-theme='dark'] .av-range input { background: var(--av-neutral-80); }
.av-range input::-webkit-slider-thumb {
  appearance: none; width: 1.125rem; height: 1.125rem; border-radius: var(--av-radius-full);
  background: var(--av-primary); border: 2px solid var(--av-neutral-0); box-shadow: var(--av-shadow-sm); cursor: pointer;
}
.av-range input::-moz-range-thumb {
  width: 1.125rem; height: 1.125rem; border-radius: var(--av-radius-full);
  background: var(--av-primary); border: 2px solid var(--av-neutral-0); box-shadow: var(--av-shadow-sm); cursor: pointer;
}

.av-strength-meter { display: flex; gap: var(--av-space-1); }
.av-strength-meter__bar { height: 4px; flex: 1; border-radius: var(--av-radius-full); background: var(--av-neutral-20); }
[data-theme='dark'] .av-strength-meter__bar { background: var(--av-neutral-80); }
.av-strength-meter[data-strength='1'] .av-strength-meter__bar:nth-child(1) { background: var(--av-danger); }
.av-strength-meter[data-strength='2'] .av-strength-meter__bar:nth-child(-n+2) { background: var(--av-warning); }
.av-strength-meter[data-strength='3'] .av-strength-meter__bar:nth-child(-n+3) { background: var(--av-info); }
.av-strength-meter[data-strength='4'] .av-strength-meter__bar { background: var(--av-success); }


/* ---- Hero (marketing page opener) ----------------------------------------
   <section class="av-hero">
     <div class="av-container"><div class="av-split">
       <div>...eyebrow/h1/lead/CTAs...</div>
       <div class="av-hero__visual">...svg...</div>
     </div></div>
     <a class="av-hero__scroll-cue" href="#next-section">Explore the platform <svg>...</svg></a>
   </section>
   One per homepage variant; each home gets its own visual treatment inside
   .av-hero__visual (see Signal Trace for Home 1's). Deliberately fills one
   viewport (minus the nav) so the fold reads as a designed choice rather
   than the page trailing off into blank space — the scroll cue signals
   there's more below.
-------------------------------------------------------------------------- */
.av-hero {
  min-height: calc(100svh - 4.5rem);
  display: flex;
  align-items: center;
  position: relative;
  padding-block: var(--av-space-12);
}
.av-hero__visual { width: 100%; max-width: 42rem; margin-inline: auto; padding-top: var(--av-space-10); }
.av-hero__scroll-cue {
  position: absolute;
  left: 50%;
  bottom: var(--av-space-8);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--av-space-2);
  color: var(--av-text-muted);
  font-size: var(--av-text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--av-tracking-wide);
}
.av-hero__scroll-cue:hover { color: var(--av-text); }
.av-hero__scroll-cue svg { width: 1rem; height: 1rem; animation: av-scroll-cue-bounce 1.8s var(--av-ease-feedback) infinite; }
@keyframes av-scroll-cue-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .av-hero__scroll-cue svg { animation: none; } }
@media (max-width: 63.99rem) { .av-hero__scroll-cue { display: none; } } /* stacked mobile layout already shows the next section on scroll with no ambiguity */

/* ---- KPI / Stat Widget ---------------------------------------------------
   <div class="av-kpi">
     <p class="av-kpi__label">Active agents</p>
     <p class="av-kpi__value">128</p>
     <p class="av-kpi__delta av-kpi__delta--up">+12% <span>vs last week</span></p>
     <svg class="av-kpi__sparkline">...</svg>
   </div>
-------------------------------------------------------------------------- */
.av-kpi { background: var(--av-surface); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg); padding: var(--av-space-5); display: flex; flex-direction: column; gap: var(--av-space-2); }
.av-kpi__label { font-size: var(--av-text-xs); color: var(--av-text-muted); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); }
.av-kpi__value { font-family: var(--av-font-display); font-size: var(--av-text-xl); font-variant-numeric: tabular-nums; color: var(--av-text); }
.av-kpi__delta { font-size: var(--av-text-xs); font-weight: 600; display: flex; align-items: center; gap: var(--av-space-1); font-variant-numeric: tabular-nums; }
.av-kpi__delta span { font-weight: 400; color: var(--av-text-muted); }
.av-kpi__delta--up { color: var(--av-success-text); }
.av-kpi__delta--down { color: var(--av-danger-text); }
.av-kpi__sparkline { width: 100%; height: 2.5rem; margin-top: var(--av-space-2); }
.av-kpi__live { display: inline-flex; align-items: center; gap: var(--av-space-1); font-size: var(--av-text-xs); color: var(--av-accent-text); }
.av-kpi__live-dot { width: 0.375rem; height: 0.375rem; border-radius: var(--av-radius-full); background: var(--av-accent); animation: av-pulse 2s var(--av-ease-feedback) infinite; }
@media (prefers-reduced-motion: reduce) { .av-kpi__live-dot { animation: none; } }
@keyframes av-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---- Link (inline text link styling beyond the base <a> reset) ----------- */
.av-link { color: var(--av-primary); text-decoration: underline; text-underline-offset: 0.15em; text-decoration-thickness: 1px; }
.av-link:hover { color: var(--av-primary-strong); }
.av-link--muted { color: var(--av-text-muted); text-decoration: none; }
.av-link--muted:hover { color: var(--av-text); }
.av-link--icon { display: inline-flex; align-items: center; gap: var(--av-space-1); text-decoration: none; font-weight: 600; }
.av-link--icon svg { width: 0.9rem; height: 0.9rem; transition: transform var(--av-duration-feedback) var(--av-ease-feedback); }
.av-link--icon:hover svg { transform: translateX(2px); }

/* ---- Meter / Progress ------------------------------------------------
   <div class="av-meter" role="progressbar" aria-valuenow="72" aria-valuemin="0" aria-valuemax="100">
     <div class="av-meter__fill" style="width:72%"></div>
   </div>
-------------------------------------------------------------------------- */
.av-meter { width: 100%; height: 0.5rem; border-radius: var(--av-radius-full); background: var(--av-neutral-20); overflow: hidden; }
[data-theme='dark'] .av-meter { background: var(--av-neutral-80); }
.av-meter__fill { height: 100%; background: var(--av-primary); border-radius: var(--av-radius-full); transition: width var(--av-duration-panel) var(--av-ease-entrance); }
.av-meter--warning .av-meter__fill { background: var(--av-warning); }
.av-meter--danger .av-meter__fill { background: var(--av-danger); }
.av-meter-row { display: flex; align-items: center; justify-content: space-between; font-size: var(--av-text-xs); color: var(--av-text-muted); margin-bottom: var(--av-space-2); }

/* ---- Modal / Drawer (focus-trapped) ---------------------------------------
   <div class="av-modal" data-av-modal hidden role="dialog" aria-modal="true" aria-labelledby="id">
     <div class="av-modal__backdrop" data-av-modal-close></div>
     <div class="av-modal__panel">
       <div class="av-modal__header"><h3 id="id">Title</h3><button data-av-modal-close>...</button></div>
       <div class="av-modal__body">...</div>
       <div class="av-modal__footer">...</div>
     </div>
   </div>
   Drawer variant: add `av-modal--drawer` (slides from the right, full height).
   Focus is trapped inside .av-modal__panel while open; Escape closes; focus
   returns to the trigger element on close.
-------------------------------------------------------------------------- */
.av-modal { position: fixed; inset: 0; z-index: var(--av-z-modal); display: flex; }
.av-modal[hidden] { display: none; }
.av-modal__backdrop { position: absolute; inset: 0; background: oklch(14% 0.006 255 / 0.5); }
.av-modal__panel {
  position: relative; margin: auto; width: 100%; max-width: 32rem; max-height: calc(100svh - var(--av-space-8));
  background: var(--av-surface-raised); border-radius: var(--av-radius-lg); box-shadow: var(--av-shadow-lg);
  display: flex; flex-direction: column; overflow: hidden;
  animation: av-modal-in var(--av-duration-entrance) var(--av-ease-entrance);
}
@keyframes av-modal-in { from { opacity: 0; transform: translateY(0.75rem) scale(0.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .av-modal__panel { animation: none; } }
.av-modal__header { display: flex; align-items: center; justify-content: space-between; padding: var(--av-space-5) var(--av-space-6); border-bottom: 1px solid var(--av-border); }
.av-modal__body { padding: var(--av-space-6); overflow-y: auto; }
.av-modal__footer { padding: var(--av-space-5) var(--av-space-6); border-top: 1px solid var(--av-border); display: flex; justify-content: flex-end; gap: var(--av-space-3); }
.av-modal--drawer { justify-content: flex-end; }
.av-modal--drawer .av-modal__panel { margin: 0; max-width: 26rem; max-height: 100svh; height: 100svh; border-radius: 0; animation: av-drawer-in var(--av-duration-panel) var(--av-ease-entrance); }
@keyframes av-drawer-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
@media (prefers-reduced-motion: reduce) { .av-modal--drawer .av-modal__panel { animation: none; } }
.av-modal--danger .av-modal__header svg { color: var(--av-danger); }

/* ---- Navigation (desktop + mega-menu + mobile drawer) ---------------------
   <header class="av-nav" data-av-nav>
     <div class="av-container av-nav__bar">
       <a class="av-nav__brand" href="index.html">APEXVYRA</a>
       <nav class="av-nav__links" aria-label="Primary">
         <div class="av-nav__item" data-av-nav-item>
           <button aria-expanded="false">Product</button>
           <div class="av-nav__mega" hidden>...</div>
         </div>
       </nav>
       <div class="av-nav__actions">...theme toggle, buttons...</div>
       <button class="av-nav__toggle" data-av-nav-toggle aria-expanded="false" aria-controls="mobile-nav">...</button>
     </div>
     <nav id="mobile-nav" class="av-nav__mobile" hidden aria-label="Mobile">...</nav>
   </header>
   `data-av-nav="sticky"` keeps the bar fixed with a scrolled-state background.
-------------------------------------------------------------------------- */
.av-nav { position: sticky; top: 0; z-index: var(--av-z-sticky); background: var(--av-bg); border-bottom: 1px solid transparent; transition: border-color var(--av-duration-feedback) var(--av-ease-feedback), background-color var(--av-duration-feedback) var(--av-ease-feedback); }
.av-nav.is-scrolled { background: var(--av-surface); border-color: var(--av-border); box-shadow: var(--av-shadow-sm); }
.av-nav__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--av-space-6); height: 4.5rem; }
.av-nav__brand { font-family: var(--av-font-display); font-weight: 600; font-size: var(--av-text-md); display: flex; align-items: center; gap: var(--av-space-2); }
.av-nav__links { display: none; align-items: center; gap: var(--av-space-1); }
@media (min-width: 64rem) { .av-nav__links { display: flex; } }
.av-nav__item { position: static; }
.av-nav__item > button, .av-nav__link {
  display: flex; align-items: center; gap: var(--av-space-1); padding: var(--av-space-2) var(--av-space-3);
  border-radius: var(--av-radius-sm); font-size: var(--av-text-sm); font-weight: 500; color: var(--av-text);
}
.av-nav__item > button:hover, .av-nav__link:hover { color: var(--av-primary); }
.av-nav__link[aria-current='page'] { color: var(--av-primary); }
.av-nav__item > button svg { width: 0.875rem; height: 0.875rem; transition: transform var(--av-duration-feedback) var(--av-ease-feedback); }
.av-nav__item > button[aria-expanded='true'] svg { transform: rotate(180deg); }
.av-nav__mega {
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--av-surface-raised); border-bottom: 1px solid var(--av-border); box-shadow: var(--av-shadow-md);
  z-index: var(--av-z-dropdown);
}
.av-nav__mega[hidden] { display: none; }
.av-nav__mega-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--av-space-6); padding: var(--av-space-8) 0; }
.av-nav__mega-item { display: flex; gap: var(--av-space-3); padding: var(--av-space-2); border-radius: var(--av-radius-sm); }
.av-nav__mega-item:hover { background: var(--av-neutral-20); }
[data-theme='dark'] .av-nav__mega-item:hover { background: var(--av-neutral-90); }
.av-nav__mega-icon { width: 2.25rem; height: 2.25rem; border-radius: var(--av-radius-sm); background: var(--av-primary-soft); color: var(--av-primary-text); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.av-nav__mega-icon svg { width: 1.125rem; height: 1.125rem; }
.av-nav__mega-item h4 { font-size: var(--av-text-sm); }
.av-nav__mega-item p { font-size: var(--av-text-xs); color: var(--av-text-muted); }
.av-nav__actions { display: flex; align-items: center; gap: var(--av-space-3); }
.av-nav__toggle { display: flex; width: 2.5rem; height: 2.5rem; align-items: center; justify-content: center; }
@media (min-width: 64rem) { .av-nav__toggle { display: none; } }
.av-nav__toggle svg { width: 1.375rem; height: 1.375rem; }
.av-nav__mobile {
  position: fixed; inset: 4.5rem 0 0 0; background: var(--av-bg); z-index: var(--av-z-drawer);
  overflow-y: auto; padding: var(--av-space-6);
}
.av-nav__mobile[hidden] { display: none; }
@media (min-width: 64rem) { .av-nav__mobile { display: none !important; } }
.av-nav__mobile-link { display: flex; align-items: center; justify-content: space-between; padding: var(--av-space-4) 0; border-bottom: 1px solid var(--av-border); font-size: var(--av-text-base); font-weight: 500; }


/* ---- Notification Panel ---------------------------------------------
   <div class="av-notif-panel" data-av-notif-panel hidden role="region" aria-label="Notifications">
     <div class="av-notif-panel__header"><h3>Notifications</h3><button>Mark all read</button></div>
     <ul class="av-notif-panel__list">
       <li class="av-notif-panel__item" data-unread>
         <span class="av-notif-panel__icon">...</span>
         <div><p>Message</p><time>2h ago</time></div>
       </li>
     </ul>
   </div>
-------------------------------------------------------------------------- */
.av-notif-panel {
  position: absolute; top: calc(100% + var(--av-space-2)); right: 0; width: 22rem; max-width: 90vw;
  background: var(--av-surface-raised); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg);
  box-shadow: var(--av-shadow-md); z-index: var(--av-z-dropdown); overflow: hidden;
}
.av-notif-panel[hidden] { display: none; }
.av-notif-panel__header { display: flex; align-items: center; justify-content: space-between; padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); }
.av-notif-panel__header button { font-size: var(--av-text-xs); color: var(--av-primary); font-weight: 600; }
.av-notif-panel__list { max-height: 22rem; overflow-y: auto; }
.av-notif-panel__item { display: flex; gap: var(--av-space-3); padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); font-size: var(--av-text-sm); position: relative; }
.av-notif-panel__item:last-child { border-bottom: none; }
.av-notif-panel__item[data-unread]::before { content: ''; position: absolute; left: var(--av-space-2); top: var(--av-space-5); width: 0.375rem; height: 0.375rem; border-radius: var(--av-radius-full); background: var(--av-primary); }
.av-notif-panel__icon { width: 2rem; height: 2rem; border-radius: var(--av-radius-full); background: var(--av-primary-soft); color: var(--av-primary-text); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.av-notif-panel__icon svg { width: 1rem; height: 1rem; }
.av-notif-panel__item time { color: var(--av-text-muted); font-size: var(--av-text-xs); }

/* ---- Pagination --------------------------------------------------------
   <nav class="av-pagination" aria-label="Pagination">
     <button class="av-pagination__btn" aria-label="Previous page">...</button>
     <button class="av-pagination__btn" aria-current="page">1</button>
     <button class="av-pagination__btn">2</button>
     <span class="av-pagination__ellipsis">…</span>
     <button class="av-pagination__btn" aria-label="Next page">...</button>
   </nav>
-------------------------------------------------------------------------- */
.av-pagination { display: flex; align-items: center; gap: var(--av-space-2); }
.av-pagination__btn {
  min-width: 2.25rem; height: 2.25rem; padding: 0 var(--av-space-2);
  border-radius: var(--av-radius-sm); font-size: var(--av-text-sm); color: var(--av-text-muted);
  display: flex; align-items: center; justify-content: center;
}
.av-pagination__btn:hover { background: var(--av-neutral-20); color: var(--av-text); }
[data-theme='dark'] .av-pagination__btn:hover { background: var(--av-neutral-80); }
.av-pagination__btn[aria-current='page'] { background: var(--av-primary-fill); color: var(--av-neutral-0); }
.av-pagination__btn:disabled { opacity: 0.4; cursor: not-allowed; }
.av-pagination__btn svg { width: 1rem; height: 1rem; }
.av-pagination__ellipsis { color: var(--av-text-disabled); padding: 0 var(--av-space-1); }

/* ---- Pricing Card ------------------------------------------------------
   <div class="av-pricing-card av-pricing-card--featured">
     <p class="av-pricing-card__eyebrow">Starter</p>
     <p class="av-pricing-card__price">$49<span>/mo</span></p>
     <p class="av-pricing-card__desc">...</p>
     <ul class="av-pricing-card__features"><li>...</li></ul>
     <button class="av-btn av-btn--primary">Get started</button>
   </div>
-------------------------------------------------------------------------- */
.av-pricing-card {
  background: var(--av-surface); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg);
  padding: var(--av-space-8); display: flex; flex-direction: column; gap: var(--av-space-5);
}
.av-pricing-card--featured { border-color: var(--av-primary); box-shadow: var(--av-shadow-lg); position: relative; }
.av-pricing-card__badge { position: absolute; top: -0.75rem; left: var(--av-space-8); background: var(--av-primary-fill); color: var(--av-neutral-0); font-size: var(--av-text-xs); font-weight: 600; padding: 0.25rem var(--av-space-3); border-radius: var(--av-radius-full); }
.av-pricing-card__eyebrow { font-size: var(--av-text-sm); font-weight: 600; color: var(--av-text-muted); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); }
.av-pricing-card__price { font-family: var(--av-font-display); font-size: var(--av-text-2xl); font-variant-numeric: tabular-nums; }
.av-pricing-card__price span { font-family: var(--av-font-ui); font-size: var(--av-text-sm); font-weight: 400; color: var(--av-text-muted); }
.av-pricing-card__desc { color: var(--av-text-muted); font-size: var(--av-text-sm); }
.av-pricing-card__features { display: flex; flex-direction: column; gap: var(--av-space-3); flex: 1; }
.av-pricing-card__features li { display: flex; align-items: flex-start; gap: var(--av-space-2); font-size: var(--av-text-sm); }
.av-pricing-card__features svg { width: 1rem; height: 1rem; color: var(--av-success-text); flex-shrink: 0; margin-top: 0.15em; }

/* ---- Section, forced-dark band (deliberate tonal break within a page) ----
   <section class="av-section av-section--dark">...</section>
   Re-declares the full dark-theme token set as local custom properties, so
   every component placed inside (tabs, badges, tables, KPI tiles, ...)
   picks up correct dark colors via the SAME variable names they always use
   — regardless of the page's actual light/dark theme setting. Used once
   per page, for content that should read as "the product," not for
   decoration.
-------------------------------------------------------------------------- */
.av-section--tint { background: var(--av-surface); }

.av-section--dark {
  --av-bg: var(--av-neutral-95);
  --av-surface: var(--av-neutral-90);
  --av-surface-raised: var(--av-neutral-80);
  --av-border: var(--av-neutral-80);
  --av-border-interactive: oklch(66% 0.012 255);
  --av-text: var(--av-neutral-20);
  --av-text-muted: oklch(68% 0.012 255);
  --av-text-disabled: var(--av-neutral-70);
  --av-placeholder: var(--av-neutral-70);
  /* --av-primary / --av-primary-strong / --av-primary-fill / --av-primary-text
     were missing here despite the comment above claiming "the full
     dark-theme token set" — on a light-theme page, anything inside this
     band using --av-primary fell through to the LIGHT theme's dark-navy
     value (34% L), rendered on this band's actual dark background.
     axe-core caught it directly: a demo tab's text measured 1.47:1.
     Re-declared with the same dark-theme values as [data-theme='dark']. */
  --av-primary: oklch(62% 0.14 255);
  --av-primary-strong: oklch(70% 0.13 255);
  --av-primary-fill: oklch(54% 0.14 255);
  --av-primary-text: oklch(68% 0.14 255);
  --av-primary-soft: oklch(28% 0.05 255);
  --av-accent-text: var(--av-accent);
  --av-accent-soft: oklch(25% 0.05 55);
  /* The four --av-X-soft tokens below were also missing — any badge placed
     inside this band kept the PAGE theme's light --av-X-soft (93% L,
     near-white) while getting this band's dark-tuned --av-X-text (meant to
     read against a 25%-L dark background), an unreadable combination.
     axe-core caught a live instance: a badge measured 2.51:1. */
  --av-success-text: var(--av-success);
  --av-success-soft: oklch(25% 0.04 145);
  --av-warning-text: var(--av-warning);
  --av-warning-soft: oklch(25% 0.05 80);
  --av-danger-text: oklch(65% 0.18 25);
  --av-danger-soft: oklch(25% 0.04 25);
  --av-info-text: oklch(63% 0.12 235);
  --av-info-soft: oklch(25% 0.03 235);
  background: var(--av-bg);
  color: var(--av-text);
}

/* ---- Article Layout (blog-single: sticky TOC + prose column) -------------
   <div class="av-article-layout">
     <nav class="av-toc av-hidden-mobile" data-av-toc style="position:sticky; top:6rem; align-self:start;">...</nav>
     <div class="av-prose">...</div>
   </div>
-------------------------------------------------------------------------- */
.av-article-layout { display: grid; grid-template-columns: 1fr; gap: var(--av-space-12); }
.av-article-layout > * { min-width: 0; }
@media (min-width: 64rem) { .av-article-layout { grid-template-columns: 14rem 1fr; } }

/* ---- Reading Progress (blog-single) ---------------------------------------
   <div class="av-reading-progress" data-av-reading-progress aria-hidden="true"></div>
   Fixed thin bar, width set by article.js as a scroll percentage.
-------------------------------------------------------------------------- */
.av-reading-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%;
  background: var(--av-primary); z-index: var(--av-z-sticky);
  transition: width 100ms linear;
}
@media (prefers-reduced-motion: reduce) { .av-reading-progress { transition: none; } }

/* ---- Table of Contents (blog-single, sticky) ------------------------------
   <nav class="av-toc" data-av-toc aria-label="Table of contents">
     <p class="av-toc__label">On this page</p>
     <a class="av-toc__link" href="#section-id">Section title</a>
   </nav>
   Position it sticky in the page (inline style or a page-level rule), e.g.
   `style="position:sticky; top:6rem;"` on the parent grid cell.
-------------------------------------------------------------------------- */
.av-toc { display: flex; flex-direction: column; }
.av-toc__label { font-size: var(--av-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--av-tracking-wide); color: var(--av-text-muted); margin-bottom: var(--av-space-3); }
.av-toc__link { display: block; padding: var(--av-space-2) 0; font-size: var(--av-text-sm); color: var(--av-text-muted); border-left: 2px solid transparent; padding-left: var(--av-space-3); }
.av-toc__link:hover { color: var(--av-text); }
.av-toc__link[aria-current='true'] { color: var(--av-primary); border-left-color: var(--av-primary); font-weight: 600; }

/* ---- Sidebar (dashboard, collapsible + mobile) ----------------------------
   <aside class="av-sidebar" data-av-sidebar>
     <div class="av-sidebar__brand">APEXVYRA</div>
     <nav class="av-sidebar__nav">
       <a class="av-sidebar__link av-sidebar__link--active" href="#"><svg/><span>Overview</span></a>
     </nav>
     <button class="av-sidebar__collapse" data-av-sidebar-collapse>...</button>
   </aside>
   `data-av-sidebar-collapsed` on the root shrinks to icon-only rail.
-------------------------------------------------------------------------- */
.av-sidebar {
  width: 16rem; flex-shrink: 0; background: var(--av-surface); border-right: 1px solid var(--av-border);
  display: flex; flex-direction: column; height: 100svh; position: sticky; top: 0;
  transition: width var(--av-duration-panel) var(--av-ease-entrance);
}
[data-av-sidebar-collapsed] .av-sidebar { width: 4.5rem; }
.av-sidebar__brand { padding: var(--av-space-5); font-family: var(--av-font-display); font-weight: 600; }
.av-sidebar__nav { flex: 1; overflow-y: auto; padding: var(--av-space-3); display: flex; flex-direction: column; gap: var(--av-space-1); }
.av-sidebar__link { display: flex; align-items: center; gap: var(--av-space-3); padding: var(--av-space-3); border-radius: var(--av-radius-sm); font-size: var(--av-text-sm); font-weight: 500; color: var(--av-text-muted); white-space: nowrap; overflow: hidden; }
.av-sidebar__link svg { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.av-sidebar__link:hover { background: var(--av-neutral-20); color: var(--av-text); }
[data-theme='dark'] .av-sidebar__link:hover { background: var(--av-neutral-90); }
.av-sidebar__link--active, .av-sidebar__link[aria-current='page'] { background: var(--av-primary-soft); color: var(--av-primary-text); }
[data-av-sidebar-collapsed] .av-sidebar__link span { display: none; }
.av-sidebar__collapse { padding: var(--av-space-4); border-top: 1px solid var(--av-border); color: var(--av-text-muted); display: flex; align-items: center; gap: var(--av-space-2); font-size: var(--av-text-xs); }
.av-sidebar__mobile-toggle { display: flex; }
@media (min-width: 64rem) { .av-sidebar { display: flex; } .av-sidebar__mobile-toggle { display: none; } }
@media (max-width: 63.99rem) {
  .av-sidebar { position: fixed; left: 0; top: 0; z-index: var(--av-z-drawer); transform: translateX(-100%); transition: transform var(--av-duration-panel) var(--av-ease-entrance); width: 16rem; }
  [data-av-sidebar-open] .av-sidebar { transform: translateX(0); }
}

/* ---- Skeleton loading states ---------------------------------------------
   <div class="av-skeleton av-skeleton--text"></div>
   <div class="av-skeleton av-skeleton--avatar"></div>
   <div class="av-skeleton av-skeleton--card"></div>
-------------------------------------------------------------------------- */
.av-skeleton {
  background: linear-gradient(90deg, var(--av-neutral-20) 25%, var(--av-neutral-20) 50%, var(--av-neutral-20) 75%);
  background-size: 200% 100%;
  border-radius: var(--av-radius-sm);
  animation: av-skeleton-sweep 1.6s ease-in-out infinite;
}
[data-theme='dark'] .av-skeleton { background: linear-gradient(90deg, var(--av-neutral-80) 25%, var(--av-neutral-90) 50%, var(--av-neutral-80) 75%); background-size: 200% 100%; }
@keyframes av-skeleton-sweep { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .av-skeleton { animation: none; } }
.av-skeleton--text { height: 0.875rem; width: 100%; }
.av-skeleton--text:not(:last-child) { margin-bottom: var(--av-space-2); }
.av-skeleton--avatar { width: 2.5rem; height: 2.5rem; border-radius: var(--av-radius-full); }
.av-skeleton--card { height: 8rem; border-radius: var(--av-radius-lg); }


/* ---- Stat Row (typographic metrics band — no card borders, no icons) -----
   <div class="av-stat-row">
     <div class="av-stat-row__item"><p class="av-stat-row__value">12+</p><p class="av-stat-row__label">Model providers</p></div>
   </div>
-------------------------------------------------------------------------- */
.av-stat-row { display: flex; flex-direction: column; }
.av-stat-row__item { padding: var(--av-space-6) 0; border-top: 1px solid var(--av-border); text-align: center; }
.av-stat-row__item:first-child { border-top: none; }
.av-stat-row__value { font-family: var(--av-font-display); font-size: var(--av-text-2xl); font-variant-numeric: tabular-nums; color: var(--av-text); }
.av-stat-row__label { font-size: var(--av-text-sm); color: var(--av-text-muted); margin-top: var(--av-space-2); }
@media (min-width: 48rem) {
  .av-stat-row { flex-direction: row; flex-wrap: wrap; justify-content: center; }
  .av-stat-row__item { flex: 1 1 0; border-top: none; border-left: 1px solid var(--av-border); }
  .av-stat-row__item:first-child { border-left: none; }
}

/* ---- Table (sortable, sticky header, responsive) -------------------------
   <div class="av-table-wrap" data-av-table>
     <table class="av-table">
       <thead><tr><th data-sort="name" aria-sort="none">Name</th></tr></thead>
       <tbody><tr><td data-label="Name">...</td></tr></tbody>
     </table>
   </div>
   Mobile strategy: below 640px, rows become stacked cards using `data-label`
   as the printed field name (see UTILITIES / media query below).
-------------------------------------------------------------------------- */
.av-table-wrap { overflow-x: auto; contain: layout; border: 1px solid var(--av-border); border-radius: var(--av-radius-lg); } /* contain:layout stops a wide <table>'s intrinsic width from leaking into the document's scrollWidth through this already-clipping overflow-x:auto box — seen on team.html's role-permissions table at 390px, real horizontal scroll into dead space despite nothing visibly overflowing */
.av-table { width: 100%; font-size: var(--av-text-sm); }
.av-table thead { position: sticky; top: 0; background: var(--av-surface); z-index: 1; }
.av-table th { text-align: left; font-weight: 600; color: var(--av-text-muted); font-size: var(--av-text-xs); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); padding: var(--av-space-3) var(--av-space-4); border-bottom: 1px solid var(--av-border); white-space: nowrap; }
.av-table th[data-sort] { cursor: pointer; user-select: none; }
.av-table th[data-sort] .av-table__sort-icon { width: 0.75rem; height: 0.75rem; display: inline-block; margin-left: var(--av-space-1); opacity: 0.5; }
.av-table th[aria-sort='ascending'] .av-table__sort-icon,
.av-table th[aria-sort='descending'] .av-table__sort-icon { opacity: 1; color: var(--av-primary); }
.av-table th[aria-sort='descending'] .av-table__sort-icon { transform: rotate(180deg); }
.av-table td { padding: var(--av-space-4); border-bottom: 1px solid var(--av-border); color: var(--av-text); font-variant-numeric: tabular-nums; }
.av-table tbody tr:last-child td { border-bottom: none; }
.av-table tbody tr:hover { background: var(--av-neutral-20); }
[data-theme='dark'] .av-table tbody tr:hover { background: var(--av-neutral-90); }
.av-table--zebra tbody tr:nth-child(even) { background: var(--av-neutral-20); }
[data-theme='dark'] .av-table--zebra tbody tr:nth-child(even) { background: var(--av-neutral-90); }

@media (max-width: 40rem) {
  .av-table--responsive-cards thead { display: none; }
  .av-table--responsive-cards, .av-table--responsive-cards tbody, .av-table--responsive-cards tr, .av-table--responsive-cards td { display: block; width: 100%; }
  .av-table--responsive-cards tr { border-bottom: 1px solid var(--av-border); padding: var(--av-space-4); }
  .av-table--responsive-cards td { display: flex; justify-content: space-between; gap: var(--av-space-4); border-bottom: none; padding: var(--av-space-1) 0; text-align: right; }
  .av-table--responsive-cards td::before { content: attr(data-label); font-weight: 600; color: var(--av-text-muted); text-align: left; }
}

/* ---- Tabs (keyboard-accessible) -------------------------------------------
   <div class="av-tabs" data-av-tabs>
     <div class="av-tabs__list" role="tablist">
       <button class="av-tabs__tab" role="tab" aria-selected="true" aria-controls="p1" id="t1">One</button>
     </div>
     <div class="av-tabs__panel" role="tabpanel" id="p1" aria-labelledby="t1">...</div>
   </div>
   Arrow keys move focus between tabs; Home/End jump to first/last.
-------------------------------------------------------------------------- */
.av-tabs__list { display: flex; gap: var(--av-space-2); border-bottom: 1px solid var(--av-border); overflow-x: auto; }
.av-tabs__tab { padding: var(--av-space-3) var(--av-space-4); font-size: var(--av-text-sm); font-weight: 500; color: var(--av-text-muted); border-bottom: 2px solid transparent; white-space: nowrap; }
.av-tabs__tab:hover { color: var(--av-text); }
.av-tabs__tab[aria-selected='true'] { color: var(--av-primary); border-color: var(--av-primary); }
.av-tabs__panel { padding-top: var(--av-space-6); }
.av-tabs__panel[hidden] { display: none; }
.av-tabs--pills .av-tabs__list { border-bottom: none; gap: var(--av-space-1); }
.av-tabs--pills .av-tabs__tab { border-radius: var(--av-radius-full); border-bottom: none; }
.av-tabs--pills .av-tabs__tab[aria-selected='true'] { background: var(--av-primary-soft); }

/* ---- Testimonial (grid + slider) ------------------------------------------
   <figure class="av-testimonial">
     <blockquote>"Quote"</blockquote>
     <figcaption><span class="av-avatar">...</span><div><p>Name</p><p>Role, Company</p></div></figcaption>
   </figure>
   Slider: wrap testimonials in <div class="av-slider" data-av-slider>
     <div class="av-slider__track">...<figure class="av-testimonial">...</figure></div>
   </div> with .av-slider__controls (prev/next + dots).
-------------------------------------------------------------------------- */
.av-testimonial { background: var(--av-surface); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg); padding: var(--av-space-8); display: flex; flex-direction: column; gap: var(--av-space-6); height: 100%; }
.av-testimonial blockquote { font-size: var(--av-text-md); line-height: var(--av-leading-snug); color: var(--av-text); }
.av-testimonial figcaption { display: flex; align-items: center; gap: var(--av-space-3); margin-top: auto; }
.av-testimonial figcaption p:first-child { font-weight: 600; font-size: var(--av-text-sm); }
.av-testimonial figcaption p:last-child { font-size: var(--av-text-xs); color: var(--av-text-muted); }

.av-slider { position: relative; overflow: hidden; }
.av-slider__track { display: flex; transition: transform var(--av-duration-panel) var(--av-ease-entrance); }
.av-slider__slide { flex: 0 0 100%; padding: 0 var(--av-space-2); }
.av-slider__controls { display: flex; align-items: center; justify-content: center; gap: var(--av-space-4); margin-top: var(--av-space-6); }
.av-slider__dots { display: flex; gap: var(--av-space-2); }
.av-slider__dot { width: 0.5rem; height: 0.5rem; border-radius: var(--av-radius-full); background: var(--av-neutral-30); }
[data-theme='dark'] .av-slider__dot { background: var(--av-neutral-70); }
.av-slider__dot[aria-current='true'] { background: var(--av-primary); }

/* ---- Theme Toggle ----------------------------------------------------
   <button class="av-theme-toggle" data-av-theme-toggle aria-label="Switch to dark theme">
     <svg class="av-theme-toggle__sun"><use href="#av-icon-sun"/></svg>
     <svg class="av-theme-toggle__moon"><use href="#av-icon-moon"/></svg>
   </button>
   The actual pre-paint theme decision happens in an inline <head> script (see
   documentation) — this component only reflects and toggles it after paint.
-------------------------------------------------------------------------- */
.av-theme-toggle { width: 2.5rem; height: 2.5rem; display: flex; align-items: center; justify-content: center; border-radius: var(--av-radius-sm); color: var(--av-text-muted); flex-shrink: 0; }
.av-theme-toggle:hover { background: var(--av-neutral-20); color: var(--av-text); }
[data-theme='dark'] .av-theme-toggle:hover { background: var(--av-neutral-80); }
.av-theme-toggle svg { width: 1.125rem; height: 1.125rem; }
.av-theme-toggle__moon { display: none; }
[data-theme='dark'] .av-theme-toggle__sun { display: none; }
[data-theme='dark'] .av-theme-toggle__moon { display: block; }

/* ---- Timeline ----------------------------------------------------------
   <ol class="av-timeline">
     <li class="av-timeline__item"><span class="av-timeline__dot"></span>
       <time>2024</time><h3 class="av-timeline__title">Title</h3><p>...</p></li>
   </ol>
   Heading level on the title is the page author's choice (h3, h4, ...) —
   pick whatever is correct for that page's outline; the class carries the
   styling so no heading level is hardwired into the component.
-------------------------------------------------------------------------- */
.av-timeline { position: relative; display: flex; flex-direction: column; gap: var(--av-space-8); padding-left: var(--av-space-8); }
.av-timeline::before { content: ''; position: absolute; left: 0.28rem; top: 0.4rem; bottom: 0.4rem; width: 1px; background: var(--av-border); }
.av-timeline__item { position: relative; }
.av-timeline__dot { position: absolute; left: calc(-1 * var(--av-space-8) + 0.03rem); top: 0.3rem; width: 0.5625rem; height: 0.5625rem; border-radius: var(--av-radius-full); background: var(--av-primary); }
.av-timeline__item time { font-size: var(--av-text-xs); color: var(--av-text-muted); text-transform: uppercase; letter-spacing: var(--av-tracking-wide); font-weight: 600; }
.av-timeline__title { margin-top: var(--av-space-1); font-size: var(--av-text-lg); }
.av-timeline__item p { margin-top: var(--av-space-2); color: var(--av-text-muted); font-size: var(--av-text-sm); }

/* ---- Toast (transient notification) ---------------------------------
   <div class="av-toast-region" data-av-toast-region aria-live="polite" aria-atomic="true"></div>
   JS injects: <div class="av-toast av-toast--success" role="status">
     <svg/><p>Message</p><button aria-label="Dismiss">...</button></div>
-------------------------------------------------------------------------- */
.av-toast-region { position: fixed; right: var(--av-space-6); bottom: var(--av-space-6); z-index: var(--av-z-toast); display: flex; flex-direction: column; gap: var(--av-space-3); width: 22rem; max-width: calc(100vw - var(--av-space-8)); }
.av-toast {
  display: flex; align-items: flex-start; gap: var(--av-space-3);
  background: var(--av-surface-raised); border: 1px solid var(--av-border); border-radius: var(--av-radius-lg);
  box-shadow: var(--av-shadow-lg); padding: var(--av-space-4); font-size: var(--av-text-sm);
  animation: av-toast-in var(--av-duration-entrance) var(--av-ease-entrance);
}
@keyframes av-toast-in { from { opacity: 0; transform: translateY(0.5rem); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .av-toast { animation: none; } }
.av-toast svg { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.av-toast--success svg { color: var(--av-success-text); }
.av-toast--danger svg { color: var(--av-danger-text); }
.av-toast--warning svg { color: var(--av-warning-text); }
.av-toast--info svg { color: var(--av-info-text); }
.av-toast p { flex: 1; }
.av-toast button { color: var(--av-text-muted); flex-shrink: 0; }

/* ---- Tooltip -----------------------------------------------------------
   <span class="av-tooltip" data-av-tooltip="Copy to clipboard">
     <button aria-describedby="generated-id">...</button>
   </span>
   JS generates the bubble + id on first hover/focus for perf.
-------------------------------------------------------------------------- */
.av-tooltip { position: relative; display: inline-flex; }
.av-tooltip__bubble {
  position: absolute; bottom: calc(100% + var(--av-space-2)); left: 50%; transform: translateX(-50%) translateY(2px);
  background: var(--av-neutral-90); color: var(--av-neutral-0); font-size: var(--av-text-xs);
  padding: var(--av-space-2) var(--av-space-3); border-radius: var(--av-radius-sm); white-space: nowrap;
  box-shadow: var(--av-shadow-md); pointer-events: none; opacity: 0;
  transition: opacity var(--av-duration-feedback) var(--av-ease-feedback), transform var(--av-duration-feedback) var(--av-ease-feedback);
  z-index: var(--av-z-tooltip);
}
[data-theme='dark'] .av-tooltip__bubble { background: var(--av-neutral-20); color: var(--av-neutral-200); }
.av-tooltip__bubble.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- Typography set (utility classes for one-off copy blocks) ----------- */
.av-eyebrow { font-size: var(--av-text-xs); font-weight: 700; letter-spacing: var(--av-tracking-wide); text-transform: uppercase; color: var(--av-text-muted); }
.av-eyebrow--accent { color: var(--av-accent-text); } /* reserved for the ONE deliberate highlight per hero (see ART-DIRECTION.md) — never the default, so reusing .av-eyebrow on ordinary section labels doesn't silently spread amber across the page */
.av-lead { font-size: var(--av-text-md); color: var(--av-text-muted); line-height: var(--av-leading-snug); }
.av-text-muted { color: var(--av-text-muted); }
.av-text-display { font-family: var(--av-font-display); }
/* Visual-only heading swatches for documentation (e.g. a type-scale sample)
   where a real <h1>-<h6> would create a second, out-of-order heading in the
   page's actual document outline. Same look, no heading semantics. */
.av-heading-sample { display: block; font-weight: 600; line-height: var(--av-leading-tight); letter-spacing: var(--av-tracking-tight); color: var(--av-text); }
.av-heading-sample--1, .av-heading-sample--2, .av-heading-sample--3 { font-family: var(--av-font-display); }
.av-heading-sample--1 { font-size: var(--av-text-3xl); }
.av-heading-sample--2 { font-size: var(--av-text-2xl); }
.av-heading-sample--3 { font-size: var(--av-text-xl); }
.av-heading-sample--4 { font-size: var(--av-text-lg); font-family: var(--av-font-ui); letter-spacing: var(--av-tracking-normal); }
.av-prose { max-width: 68ch; color: var(--av-text); }
.av-prose > * + * { margin-top: var(--av-space-4); }
.av-prose h2 { margin-top: var(--av-space-10); }
.av-prose h3 { margin-top: var(--av-space-8); }
.av-prose ul, .av-prose ol { padding-left: var(--av-space-6); list-style: disc; }
.av-prose ol { list-style: decimal; }
.av-prose a { color: var(--av-primary); text-decoration: underline; text-underline-offset: 0.15em; }
.av-prose blockquote { border-left: 3px solid var(--av-primary); padding-left: var(--av-space-4); color: var(--av-text-muted); font-style: italic; }
.av-code-inline { font-family: var(--av-font-code); font-size: 0.9em; background: var(--av-neutral-20); padding: 0.1em 0.4em; border-radius: var(--av-radius-sm); }
[data-theme='dark'] .av-code-inline { background: var(--av-neutral-80); }


/* ---- Signal Trace (signature element) -------------------------------
   <svg class="av-signal-trace" data-av-signal-trace viewBox="0 0 400 200" aria-hidden="true">
     <path class="av-signal-trace__path" d="..." />
     <circle class="av-signal-trace__node" cx="..." cy="..." r="4" />
   </svg>
   The recurring motif: a hairline path that "draws in" once on scroll into
   view, then a node pulses to mark something live. Always aria-hidden
   (decorative) — the content it accompanies carries the real information.
-------------------------------------------------------------------------- */
.av-signal-trace { overflow: visible; color: var(--av-accent-text); } /* accent-text, not accent: this stroke IS the content, and bright --av-accent only clears 2.55:1 on light surfaces — below the 3:1 non-text-contrast bar for meaningful graphics (WCAG 1.4.11). --av-accent stays reserved for small decorative fills paired with a legible text label (e.g. .av-kpi__live-dot). */
.av-signal-trace__path {
  fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round;
  stroke-dasharray: var(--av-trace-length, 1000);
  stroke-dashoffset: var(--av-trace-length, 1000);
  transition: stroke-dashoffset 1.4s var(--av-ease-entrance);
}
.av-signal-trace.is-visible .av-signal-trace__path { stroke-dashoffset: 0; }
@media (prefers-reduced-motion: reduce) {
  .av-signal-trace__path { transition: none; stroke-dashoffset: 0; }
}
.av-signal-trace__node { fill: currentColor; animation: av-pulse 2.4s var(--av-ease-feedback) infinite; }
@media (prefers-reduced-motion: reduce) { .av-signal-trace__node { animation: none; } }
.av-signal-trace__muted { color: var(--av-border-interactive); }

/* ---- Signal Trace: node-graph composition (hero-scale, richer than a
   single path) — multiple candidate routes fading into the "network",
   one live route in full accent color threading through the nodes it
   actually visited. Same base classes above, plus: ---- */
.av-signal-trace__path--candidate {
  stroke: var(--av-border-interactive);
  stroke-width: 1.5;
  stroke-dasharray: 5 6;
  opacity: 0.6;
}
.av-signal-trace__path--live { stroke-width: 2.5; }
.av-signal-trace__node-group circle { fill: var(--av-surface); stroke-width: 2; }
.av-signal-trace__node-group.is-hub circle { fill: var(--av-primary); stroke: var(--av-primary); }
.av-signal-trace__node-group.is-hub .av-signal-trace__icon { color: var(--av-neutral-0); }
.av-signal-trace__node-group.is-live circle { stroke: var(--av-accent-text); }
.av-signal-trace__node-group.is-live .av-signal-trace__icon { color: var(--av-accent-text); }
.av-signal-trace__node-group.is-candidate circle { stroke: var(--av-border-interactive); opacity: 0.7; }
.av-signal-trace__node-group.is-candidate .av-signal-trace__icon { color: var(--av-text-muted); opacity: 0.7; }
.av-signal-trace__icon { color: var(--av-text-muted); pointer-events: none; }
.av-signal-trace__grid-dot { fill: var(--av-border); }
.av-signal-trace__label {
  font-family: var(--av-font-ui); font-size: 11px; font-weight: 600;
  fill: var(--av-text-muted); text-anchor: middle; text-transform: uppercase; letter-spacing: 0.04em;
}
.av-signal-trace__node-group.is-hub .av-signal-trace__label,
.av-signal-trace__node-group.is-live .av-signal-trace__label { fill: var(--av-text); }


/* ==========================================================================
   6. UTILITIES — small, documented set. Not a utility framework.
   ========================================================================== */

.av-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.av-sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.av-text-center { text-align: center; }
.av-hidden { display: none; }
@media (min-width: 48rem) { .av-hidden-tablet-up { display: none; } }
@media (max-width: 47.99rem) { .av-hidden-mobile { display: none; } }
.av-visually-hide-until-js .av-js-only { display: none; }
html.js .av-visually-hide-until-js .av-js-only { display: revert; }
.av-tabular-nums { font-variant-numeric: tabular-nums; }


/* ==========================================================================
   7. PAGES — page-specific overrides only where genuinely unavoidable.
   Kept intentionally empty at Phase 1: no pages exist yet. If this section
   grows large during later phases, that's a signal a component is missing
   a variant rather than that the page needs a one-off override.
   ========================================================================== */
