/* OLED True-Black · components · 26.11.13-Alpha
   Loads after tokens.css (generated from tokens.json). Every color, space, radius, size,
   duration and easing below is a token from tokens.json; this file adds what tokens cannot
   hold: fluid type, gradients, compensated weights and the components. Class prefix: o-
   Themes: Violet (default, no attribute needed), Amethyst, Sunset, Gold, Emerald, Graphite and Tide
   (<html data-theme="sunset">). Every color follows the theme except black and the grays, status, focus, the rainbow, the chart
   series and the diverging ramp, and the app icon (test_theme_colors.py); the gradients below are
   declared on every [data-theme] element too, so a subtree can carry its own theme (the picker's swatches do). */

/* ---------- foundations ---------- */

[hidden]:not([hidden="until-found"]) { display: none !important; }   /* components set display; the hidden attribute must still win */
:root {
  color-scheme: dark;

  /* Weights compensated for light-on-black (irradiation): the stem change of Google's
     grade -25, measured on Roboto Flex and matched on Inter. */
  --w-regular: 380;
  --w-medium: 480;
  --w-semibold: 580;
  --w-bold: 680;
  --w-label: 580;              /* button, tab and chip labels (14-15 px) */
  --w-field-label: var(--w-medium);   /* labels above fields: plain, not bold (Penzo 2006: bold labels slowed saccades 50 -> 80 ms) */

  /* Fluid type: 360 px -> 2560 px viewport, rem + vw so zoom and OS text size still work */
  --fs-caption: clamp(0.75rem, 0.7398rem + 0.0455vw, 0.8125rem);
  --fs-label: clamp(0.875rem, 0.8648rem + 0.0455vw, 0.9375rem);
  --fs-dense: clamp(0.9375rem, 0.9273rem + 0.0455vw, 1rem);
  --fs-code: clamp(0.875rem, 0.8648rem + 0.0455vw, 0.9375rem);
  --fs-body: clamp(1rem, 0.9693rem + 0.1364vw, 1.1875rem);
  --fs-title-s: clamp(1.1875rem, 1.1364rem + 0.2273vw, 1.5rem);
  --fs-title: clamp(1.4375rem, 1.3711rem + 0.2955vw, 1.8438rem);
  --fs-headline: clamp(1.7188rem, 1.6216rem + 0.4318vw, 2.3125rem);
  --fs-display-s: clamp(2.0625rem, 1.9244rem + 0.6136vw, 2.9063rem);
  --fs-display: clamp(2.5rem, 2.3159rem + 0.8182vw, 3.625rem);


  /* Input-dependent sizes: fine pointer by default, touch below */
  --control: var(--control-md);
  --target: var(--target-min);
  --row: 48px;
}
/* Gradients: sRGB fallback with the midpoint as a middle stop, then real OKLCH (OKLab where an end is white or gray:
   a white end has no hue, so OKLCH would invent one; Tide and Graphite set --g-space: oklab).
   Declared on :root and on every [data-theme] element, because a custom property resolves its var()s
   where it is declared: a subtree with its own data-theme must recompute them. */
:root, [data-theme] { --g-space: oklch; }
[data-theme="tide"], [data-theme="graphite"] { --g-space: oklab; }
:root, [data-theme] {
  --g-brand: linear-gradient(135deg, var(--brand-a), var(--brand-mid), var(--brand-b));
  --g-button: linear-gradient(135deg, var(--button-a), var(--button-mid), var(--button-b));
  --g-metric: linear-gradient(90deg, var(--metric-a), var(--metric-mid), var(--metric-b));
  --g-warm: var(--g-brand);   /* retired in 26.11.9: the warm gradient did not follow the theme; kept as the brand gradient */
}
@supports (background: linear-gradient(in oklch, red, blue)) {
  :root, [data-theme] {
    --g-brand: linear-gradient(135deg in var(--g-space), var(--brand-a), var(--brand-b));
    --g-button: linear-gradient(135deg in var(--g-space), var(--button-a), var(--button-b));
    --g-metric: linear-gradient(90deg in var(--g-space), var(--metric-a), var(--metric-b));
  }
}
@media (pointer: coarse) {
  :root { --control: var(--control-lg); --target: var(--target-touch); --row: 56px; }
}

html {
  background: var(--bg);
  color: var(--text-1);
  scrollbar-color: var(--line) transparent;   /* width stays auto: thin thumbs are too small to grab */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: var(--w-regular);
  line-height: var(--lh-body);
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: anywhere;
}
::selection { background: var(--selection); color: #fff; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
h1, h2, h3, h4 { text-wrap: balance; margin: 0; color: var(--text-1); }
p, li { text-wrap: pretty; }
img, video, svg { max-inline-size: 100%; }
a { color: var(--accent-text); text-decoration-line: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
a:hover { text-decoration-thickness: 2px; }
code, kbd, samp, pre { font-family: var(--font-mono); }


/* ---------- world scripts and direction ----------
   Inter covers Latin (Vietnamese, Turkish, Hausa…), Cyrillic (Serbian too) and Greek. Other scripts fall
   back per character to Noto families (self-host with Fontsource or load from Google Fonts), then to the OS.
   Line heights measured from shaped text (HarfBuzz): the same gap above the ink as Latin at 1.5. */
:root {
  --font-sans: Inter, "Noto Sans Arabic", "Noto Sans Devanagari", "Noto Sans Bengali", "Noto Sans Telugu", "Noto Sans Tamil",
               "Noto Sans Gujarati", "Noto Sans Kannada", "Noto Sans Thai", "Noto Sans Hebrew", "Noto Sans Ethiopic", "Noto Sans SC",
               system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --lh-body: 1.5;
}
:lang(zh) { --font-sans: Inter, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif; --lh-body: 1.7; }
:lang(zh-Hant), :lang(zh-TW), :lang(zh-HK), :lang(zh-MO) { --font-sans: Inter, "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", system-ui, sans-serif; --lh-body: 1.7; }
:lang(ja) { --font-sans: Inter, "Noto Sans JP", "Hiragino Sans", "Yu Gothic UI", Meiryo, system-ui, sans-serif; --lh-body: 1.7; }
:lang(ko) { --font-sans: Inter, "Noto Sans KR", "Apple SD Gothic Neo", "Malgun Gothic", system-ui, sans-serif; --lh-body: 1.7; }
/* CJK 1.7 = a 0.7 em line gap: W3C jlreq sets the body gap between 0.5 and 1 em (1 em for lines over 35 characters) */
:lang(ur) { --font-sans: Inter, "Noto Nastaliq Urdu", "Noto Sans Arabic", system-ui, sans-serif; --lh-body: 2.25; }
:lang(vi) { --lh-body: 1.6; }
:lang(th) { --lh-body: 1.55; }
/* Identifiers keep left-to-right order inside right-to-left text (IPs, hosts, commands) */
code, kbd, samp, .code, .o-code-inline, .o-codeblock, .o-input--mono { direction: ltr; unicode-bidi: isolate; }
/* Direction-bearing icons (arrows, chevrons, back/forward) mirror in RTL; others never do */
:dir(rtl) .o-icon--dir { scale: -1 1; }
:dir(rtl) .o-switch > input:checked::after { translate: -20px 0; }
:dir(rtl) .o-select { background-position: 15px 50%, 20px 50%; }

/* Type styles (tokens.css sets the 360 px sizes; these make them fluid) */
.display, .o-display { font-size: var(--fs-display); line-height: 1.1; font-weight: var(--w-semibold); letter-spacing: -0.01em; color: var(--text-huge); }
.display-s { font-size: var(--fs-display-s); line-height: 1.15; font-weight: var(--w-semibold); letter-spacing: -0.01em; color: var(--text-huge); }
.headline, h1 { font-size: var(--fs-headline); line-height: 1.2; font-weight: var(--w-semibold); }
.title, h2 { font-size: var(--fs-title); line-height: 1.3; font-weight: var(--w-semibold); }
.title-s, h3 { font-size: var(--fs-title-s); line-height: 1.35; font-weight: var(--w-semibold); }
.body { font-size: var(--fs-body); line-height: var(--lh-body); font-weight: var(--w-regular); }
.dense { font-size: var(--fs-dense); line-height: var(--lh-body); font-weight: var(--w-regular); }
.label { font-size: var(--fs-label); line-height: 1.4; font-weight: var(--w-label); }
.caption { font-size: var(--fs-caption); line-height: 1.5; font-weight: var(--w-medium); color: var(--text-2); }
.code { font-family: var(--font-mono); font-size: var(--fs-code); line-height: 1.5; font-weight: var(--w-medium); }
.metric { font-size: var(--fs-display); line-height: 1; font-weight: var(--w-semibold); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.text-2 { color: var(--text-2); }
.text-3 { color: var(--text-3); }
.num { font-variant-numeric: tabular-nums; }
.gradient-text {                               /* 24 px and larger only */
  background: var(--g-metric);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
@media (forced-colors: active) { .gradient-text { color: CanvasText; background: none; } }
.prose { max-inline-size: var(--measure); }
.visually-hidden { position: absolute !important; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Icons: Lucide, 24 grid, stroke 1.75 (2 px x the grade -25 ratio 0.875) */
.o-icon { inline-size: var(--icon-md); block-size: var(--icon-md); flex: none; stroke: currentColor; stroke-width: 1.75; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.o-icon--sm { inline-size: var(--icon-sm); block-size: var(--icon-sm); stroke-width: 2; }   /* 16 px: dots and gaps need 2 units (2026 icon rule) */
.o-icon--lg { inline-size: var(--icon-lg); block-size: var(--icon-lg); }
/* Weight matching (SF Symbols principle): icons next to 580-weight labels take stroke 2, matching Inter's 1.7-1.8 px stems */
.o-btn .o-icon, .o-chip .o-icon, .o-tab .o-icon, .o-field__error .o-icon { stroke-width: 2; }

/* ---------- buttons ---------- */

.o-btn {
  --_bg: transparent; --_fg: var(--text-1); --_bd: transparent;
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-8);
  min-block-size: var(--control); min-inline-size: var(--target);
  padding-inline: var(--space-20); border-radius: var(--radius-full);   /* capsule: M3 Expressive round default, Apple capsule */
  border: 1px solid var(--_bd); background: var(--_bg); color: var(--_fg);
  font: var(--w-label) var(--fs-label)/1.2 var(--font-sans);
  text-decoration: none; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dur-fast-effects) var(--spring-fast-effects),
              border-color var(--dur-fast-effects) var(--spring-fast-effects),
              color var(--dur-fast-effects) var(--spring-fast-effects),
              scale var(--dur-fast-spatial) var(--spring-fast-spatial);
}
.o-btn::before { content: ""; position: absolute; inset: -1px; z-index: -1; border-radius: inherit; background: #fff; opacity: 0; transition: opacity var(--dur-fast-effects) var(--spring-fast-effects); }
.o-btn:hover::before { opacity: 0.06; }
.o-btn:active::before { opacity: 0.12; }
.o-btn:active { scale: 0.98; }
@media (prefers-reduced-motion: reduce) { .o-btn:active { scale: none; } }
.o-btn--primary { --_bg: var(--g-button); --_fg: var(--on-button); background: var(--g-button); border: 0; }
.o-btn--secondary { --_bd: var(--border-input); }
.o-btn--secondary:hover { --_bd: var(--border-hover); }
.o-btn--ghost { --_fg: var(--text-1); }
.o-btn--danger { --_fg: var(--err); --_bd: var(--border-danger); }
.o-btn--sm { min-block-size: var(--control-sm); padding-inline: var(--space-12); }
/* Main bottom action on phones: 56 px = 9.3-10.2 mm (Parhi 2006: 9.2-9.6 mm for one-thumb taps), full width, in the thumb zone */
@media (pointer: coarse) { .o-btn--cta { min-block-size: var(--control-xl); inline-size: 100%; font-size: var(--fs-dense); } }
@media (pointer: coarse) { .o-btn--sm { min-block-size: var(--target-touch); } }
.o-btn--block { inline-size: 100%; }
.o-btn:disabled, .o-btn[aria-disabled="true"] {
  background: transparent; color: var(--text-off); border: 1px solid var(--border-disabled); cursor: not-allowed; scale: none;
}
.o-btn:disabled::before { display: none; }
.o-btn[aria-busy="true"] { cursor: progress; pointer-events: none; }
.o-btn[aria-busy="true"] > .o-spinner { --size: 18px; }

.o-icon-btn {
  position: relative; display: inline-grid; place-items: center;
  inline-size: var(--control); block-size: var(--control);
  border: 0; border-radius: var(--radius-full); background: transparent; color: var(--text-1); cursor: pointer;
  transition: background-color var(--dur-fast-effects) var(--spring-fast-effects);
}
.o-icon-btn:hover { background: var(--surface-raised); }
.o-icon-btn:active { background: var(--surface-overlay); }
.o-icon-btn[aria-pressed="true"] { background: var(--g-button); color: var(--on-button); }   /* a toggle that is on: the button gradient with its label color, as every selected control (his rule, 12 Nov 2026) */
.o-icon-btn--sm { inline-size: var(--control-sm); block-size: var(--control-sm); }
.o-icon-btn--sm::after { content: ""; position: absolute; inset: min(0px, calc((var(--control-sm) - var(--target)) / 2)); }

/* ---------- form fields ---------- */

.o-field { display: grid; gap: var(--space-6); min-inline-size: 0; }
.o-field > label, .o-field > .o-field__label { font: var(--w-field-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-1); }
.o-field__hint { font: var(--w-regular) var(--fs-dense)/1.45 var(--font-sans); color: var(--text-2); margin: 0; }
.o-field__error { display: none; align-items: center; gap: var(--space-6); font: var(--w-medium) var(--fs-label)/1.4 var(--font-sans); color: var(--err); margin: 0; }
.o-input, .o-select, .o-textarea {
  box-sizing: border-box; inline-size: 100%; min-inline-size: 0;
  min-block-size: var(--control); padding: 0 var(--space-12);
  border: 1px solid var(--border-input); border-radius: var(--radius-md);
  background: var(--bg); color: var(--text-1);
  font: var(--w-regular) var(--fs-body)/1.4 var(--font-sans);
  transition: border-color var(--dur-fast-effects) var(--spring-fast-effects);
}
.o-textarea { padding-block: var(--space-8); min-block-size: calc(var(--control) * 2.5); resize: vertical; }
.o-input::placeholder, .o-textarea::placeholder { color: var(--text-3); opacity: 1; }
.o-input:hover, .o-select:hover, .o-textarea:hover { border-color: var(--border-hover); }
.o-input:focus-visible, .o-select:focus-visible, .o-textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--focus); }
.o-input:user-invalid, .o-textarea:user-invalid, .o-field--error .o-input { border-color: var(--err); }
.o-field:has(:user-invalid) .o-field__error, .o-field--error .o-field__error { display: flex; }
.o-input:disabled, .o-select:disabled { color: var(--text-off); border-color: var(--border-disabled); cursor: not-allowed; }
/* Field + button in one row (search, coupon, invite): same height, 8 px apart, bottoms aligned */
.o-field-row { display: flex; align-items: end; gap: var(--space-8); }
.o-field-row > .o-field { flex: 1; }
.o-field-row > .o-btn { flex: none; min-block-size: var(--control); }
/* Form: one column, label above, helper below, primary action left-aligned with the fields (Wroblewski 2008) */
.o-form { display: grid; gap: var(--space-20); max-inline-size: 36rem; }
.o-form__actions { display: flex; flex-wrap: wrap; gap: var(--space-12); padding-block-start: var(--space-4); }
.o-input--mono { font-family: var(--font-mono); font-size: var(--fs-code); }
.o-input-wrap { position: relative; display: flex; align-items: center; }
.o-input-wrap > .o-icon { position: absolute; inset-inline-start: var(--space-12); color: var(--text-3); pointer-events: none; }
.o-input-wrap > .o-input { padding-inline-start: calc(var(--space-12) + var(--icon-md) + var(--space-8)); }

/* Select: native, chevron drawn in CSS; customizable select where supported */
.o-select {
  appearance: none; padding-inline-end: var(--space-40); cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-2) 50%), linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 15px) 50%;
  background-size: 5px 5px; background-repeat: no-repeat;
}
@supports (appearance: base-select) {
  .o-select, .o-select::picker(select) { appearance: base-select; }
  .o-select { background-image: none; display: flex; align-items: center; }
  .o-select::picker-icon { color: var(--text-2); }
  .o-select::picker(select) {
    border: 0; border-radius: var(--radius-lg); background: var(--surface-raised); box-shadow: var(--ring-raised);
    padding: var(--space-4); margin-block: var(--space-4); color: var(--text-1);
    opacity: 0; translate: 0 -4px;
    transition: opacity var(--dur-default-effects) var(--spring-default-effects), translate var(--dur-fast-spatial) var(--spring-fast-spatial),
                display var(--dur-default-effects), overlay var(--dur-default-effects);
    transition-behavior: allow-discrete;
  }
  .o-select:open::picker(select) { opacity: 1; translate: 0 0; }
  @starting-style { .o-select:open::picker(select) { opacity: 0; translate: 0 -4px; } }
  .o-select option { min-block-size: var(--control); padding-inline: var(--space-12); border-radius: var(--radius-sm); font-size: var(--fs-body); }
  .o-select option:hover, .o-select option:focus-visible { background: var(--surface-overlay); }
  .o-select option:checked { font-weight: var(--w-medium); }
  .o-select option::checkmark { color: var(--text-1); }
}

/* Checkbox, radio, switch: native inputs, drawn on black */
.o-check { display: inline-flex; align-items: center; gap: var(--space-12); min-block-size: var(--target); cursor: pointer; font: var(--w-regular) var(--fs-body)/1.4 var(--font-sans); }
.o-check > input {
  appearance: none; margin: 0; flex: none; inline-size: 20px; block-size: 20px;
  border: 1.5px solid var(--border-input); border-radius: 6px; background: var(--bg); display: grid; place-content: center; cursor: pointer;
  transition: background-color var(--dur-fast-effects) var(--spring-fast-effects), border-color var(--dur-fast-effects) var(--spring-fast-effects);
}
.o-check > input[type="radio"] { border-radius: 50%; }
.o-check > input::after { content: ""; inline-size: 12px; block-size: 12px; scale: 0; background: var(--on-button); transition: scale var(--dur-fast-spatial) var(--spring-fast-spatial);
  clip-path: polygon(14% 52%, 0 66%, 38% 100%, 100% 26%, 86% 12%, 38% 72%); }
.o-check > input[type="radio"]::after { inline-size: 8px; block-size: 8px; clip-path: circle(50%); }
.o-check > input:checked { background: var(--g-button); border-color: transparent; }
.o-check > input:checked::after { scale: 1; }
.o-check > input:indeterminate { background: var(--g-button); border-color: transparent; }
.o-check > input:indeterminate::after { scale: 1; block-size: 2px; clip-path: none; }
.o-check > input:disabled { border-color: var(--border-disabled); background: var(--bg); cursor: not-allowed; }
.o-check:has(input:disabled) { color: var(--text-off); cursor: not-allowed; }

.o-switch { display: inline-flex; align-items: center; gap: var(--space-12); min-block-size: var(--target); cursor: pointer; font: var(--w-regular) var(--fs-body)/1.4 var(--font-sans); }
.o-switch > input {
  appearance: none; margin: 0; flex: none; position: relative; inline-size: 52px; block-size: 32px; border-radius: var(--radius-full);
  background: var(--track); box-shadow: inset 0 0 0 1.5px var(--border-input); cursor: pointer;
  transition: background-color var(--dur-fast-effects) var(--spring-fast-effects), box-shadow var(--dur-fast-effects) var(--spring-fast-effects);
}
.o-switch > input::after {
  content: ""; position: absolute; inset-block-start: 8px; inset-inline-start: 8px; inline-size: 16px; block-size: 16px; border-radius: 50%; background: var(--text-3);
  transition: translate var(--dur-fast-spatial) var(--spring-fast-spatial), inline-size var(--dur-fast-spatial) var(--spring-fast-spatial),
              block-size var(--dur-fast-spatial) var(--spring-fast-spatial), inset var(--dur-fast-spatial) var(--spring-fast-spatial), background-color var(--dur-fast-effects) linear;
}
.o-switch > input:checked { background: var(--g-button); box-shadow: none; }
.o-switch > input:checked::after { background: var(--on-button); inline-size: 24px; block-size: 24px; inset-block-start: 4px; inset-inline-start: 4px; translate: 20px 0; }
.o-switch > input:disabled { opacity: 0.4; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) { .o-switch > input::after { transition-duration: 0s; } }

/* ---------- containers ---------- */

.o-card { container: card / inline-size; background: var(--surface); border-radius: var(--radius-lg); padding: var(--space-20); min-inline-size: 0; }
.o-card--outlined { border: 1px solid var(--line); }
.o-card--raised { background: var(--surface-raised); box-shadow: var(--ring-raised); }   /* small, static tiles only */
/* A fill never crosses its frame (his rule, 12 Nov 2026): a box with rounded corners and an edge, a ring or a fill of its own clips
   what it holds, so a row's hover, selected or striped fill follows the frame's corners whatever the markup. Rows that can touch
   the frame draw their focus ring inward, where the clip cannot cut it. `o-frame` does the same for any framed box of your own;
   `o-card--flush` takes the padding away for a list or table that runs to the card's edges. Check with fillcheck.py. */
.o-card--outlined, .o-card--raised, .o-frame { overflow: clip; }
.o-card--flush { padding: 0; }
:is(.o-card--outlined, .o-card--raised, .o-frame) :is(.o-list__row, tr, [role="row"], [role="option"]):focus-visible { outline-offset: -2px; }
.o-card__title { font: var(--w-semibold) var(--fs-title-s)/1.35 var(--font-sans); margin: 0 0 var(--space-4); }
.o-card__meta { font: var(--w-medium) var(--fs-caption)/1.5 var(--font-sans); color: var(--text-2); }
@container card (inline-size < 320px) { .o-card__body { font-size: var(--fs-dense); } }

.o-divider { border: 0; border-block-start: 1px solid var(--line); margin-block: var(--space-16); }

.o-stat { display: grid; gap: var(--space-8); align-content: start; }
.o-stat__label { font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-2); }
.o-stat__value { font: var(--w-semibold) clamp(2rem, 1.6rem + 2cqi, 3.625rem)/1 var(--font-sans); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; color: var(--text-huge); }
.o-stat__value.gradient-text { color: transparent; }
.o-stat__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-8); font: var(--w-medium) var(--fs-caption)/1.5 var(--font-sans); color: var(--text-2); }
.o-stat__spark { block-size: 40px; inline-size: 100%; }

/* Chips and status: color + icon + word, never color alone */
.o-chip {
  --_fg: var(--text-1); --_bg: var(--surface-raised);
  display: inline-flex; align-items: center; gap: var(--space-6); max-inline-size: 100%;
  padding-block: var(--space-4); padding-inline: var(--space-8) var(--space-12); border-radius: var(--radius-full);
  background: var(--_bg); color: var(--_fg); font: var(--w-label) var(--fs-label)/1.3 var(--font-sans); white-space: nowrap;
}
.o-chip > .o-icon { inline-size: var(--icon-sm); block-size: var(--icon-sm); }
.o-chip--ok { --_fg: var(--ok); --_bg: var(--ok-bg); }
.o-chip--warn { --_fg: var(--warn); --_bg: var(--warn-bg); }
.o-chip--err { --_fg: var(--err); --_bg: var(--err-bg); }
.o-chip--info { --_fg: var(--info); --_bg: var(--info-bg); }
.o-chip--outline { --_bg: transparent; box-shadow: inset 0 0 0 1px var(--border-input); }
button.o-chip { border: 0; cursor: pointer; }
.o-chip[aria-pressed="true"] { --_bg: var(--g-button); --_fg: var(--on-button); box-shadow: none; }   /* a filter chip that is on */
.o-badge { display: inline-grid; place-items: center; min-inline-size: 18px; block-size: 18px; padding-inline: 5px; box-sizing: border-box; border-radius: var(--radius-full);
  background: var(--selection); color: #fff; font: var(--w-semibold) 0.6875rem/1 var(--font-sans); font-variant-numeric: tabular-nums; }
/* A count is a solid dot of the theme, never a gradient (his rule, 12 Nov 2026): `selection` is the theme's deepest saturated fill,
   white numbers Lc 85+ and 6:1 in every theme, and 36+ ΔE from every status color, so a count never reads as ok, warning or error.
   The button color would not do: in Gold it is the warning yellow (ΔE 3.3), in Emerald the ok green (ΔE 4.0). */
.o-nav-item .o-badge { position: absolute; inset-block-start: 4px; inset-inline-start: calc(50% + 4px); pointer-events: none; }   /* on the icon's top right */
.o-icon-btn .o-badge { position: absolute; inset-block-start: 0; inset-inline-end: 0; pointer-events: none; }

/* ---------- lists and tables ---------- */

.o-list { list-style: none; margin: 0; padding: 0; }
.o-list__row {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; column-gap: var(--space-16);
  min-block-size: var(--row); padding: var(--space-8) var(--space-16); border-radius: var(--radius-md); color: inherit; text-decoration: none;
}
.o-list__row + .o-list__row { box-shadow: 0 -1px 0 0 var(--line); border-start-start-radius: 0; border-start-end-radius: 0; }
.o-list__row > .o-icon { color: var(--text-2); }
.o-list__text { display: grid; min-inline-size: 0; }
.o-list__title { font-size: var(--fs-dense); font-weight: var(--w-regular); color: var(--text-1); }
.o-list__sub { font-size: var(--fs-dense); font-weight: var(--w-regular); color: var(--text-2); }
.o-list__meta { font: var(--w-medium) var(--fs-caption)/1.5 var(--font-sans); color: var(--text-2); text-align: end; }
a.o-list__row:hover, button.o-list__row:hover { background: var(--surface-raised); box-shadow: none; }
a.o-list__row:hover + .o-list__row { box-shadow: none; }
button.o-list__row { inline-size: 100%; border: 0; background: none; font: inherit; text-align: start; cursor: pointer; }

.o-table-wrap { overflow-x: auto; overscroll-behavior-x: contain; border-radius: var(--radius-lg); border: 1px solid var(--line); }
.o-table { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-dense); font-variant-numeric: tabular-nums; }
.o-table caption { text-align: start; padding: var(--space-12) var(--space-16); font: var(--w-semibold) var(--fs-title-s)/1.35 var(--font-sans); }
.o-table th { position: sticky; top: 0; background: var(--bg); text-align: start; font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-1); white-space: nowrap; }
.o-table th, .o-table td { padding: var(--space-12) var(--space-16); border-block-end: 1px solid var(--line); vertical-align: middle; }
.o-table tr:last-child td { border-block-end: 0; }
.o-table td.num, .o-table th.num { text-align: end; }
.o-table tbody tr:hover { background: var(--surface-raised); }
.o-table .code { font-size: var(--fs-code); }

/* ---------- navigation ---------- */

.o-tabs { display: flex; gap: var(--space-4); overflow-x: auto; scrollbar-width: none; padding: var(--space-4) var(--space-4) var(--space-8); border-block-end: 1px solid var(--line); scroll-snap-type: x proximity; }   /* the padding keeps focus rings inside the scroller */
.o-tab {
  position: relative; flex: none; scroll-snap-align: start;
  min-block-size: var(--control); padding-inline: var(--space-16); border: 0; border-radius: var(--radius-full); background: none; cursor: pointer;
  font: var(--w-label) var(--fs-label)/1.2 var(--font-sans); color: var(--text-2);
  transition: color var(--dur-fast-effects) var(--spring-fast-effects), background-color var(--dur-fast-effects) var(--spring-fast-effects);
}
.o-tab:hover { color: var(--text-1); background: var(--surface-raised); }
.o-tab[aria-selected="true"] { color: var(--on-button); background: var(--g-button); }   /* the selected tab is a control: the button gradient with its label color (his rule, 12 Nov 2026) */
.o-tabpanel { padding-block: var(--space-16); }

/* App shell: floating glass menu (compact) -> rail (medium, expanded) -> sidebar (large+).
   Driven by the shell's own width, so it also works inside a pane. */
.o-shell { container: shell / inline-size; display: grid; min-block-size: 100%; }   /* grid: the inner grid stretches to the shell's full height */
.o-shell__grid { display: grid; grid-template: "main" 1fr "nav" auto / minmax(0, 1fr); min-block-size: inherit; }
.o-shell__main { grid-area: main; min-inline-size: 0; padding: var(--space-16); padding-block-end: var(--space-24); }
.o-shell__nav { grid-area: nav; z-index: 2; display: flex; }
.o-nav-item {
  position: relative; display: grid; justify-items: center; align-content: center; gap: var(--space-4); min-inline-size: 0;
  color: var(--text-2); text-decoration: none; border-radius: var(--radius-md); background: none; border: 0; cursor: pointer;
  font: var(--w-medium) var(--fs-caption)/1.3 var(--font-sans);
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.o-nav-item__icon { display: grid; place-items: center; border-radius: var(--radius-full); transition: background-color var(--dur-fast-effects) var(--spring-fast-effects); }
/* Selected = the button gradient behind the icon (the droplet on phones, the tile on the rail, the whole row in the sidebar)
   with the button's label color (on-button), a heavier icon (stroke 2), and the screen title names the place: never color
   alone. Controls and their states take the button family only, never accent-text, the brand gradient or a status color
   (his rule, 12 Nov 2026: buttons are gradient, never green). */
.o-nav-item[aria-current="page"] { color: var(--text-1); font-weight: var(--w-semibold); }
.o-nav-item[aria-current="page"] .o-icon { stroke-width: 2; }
.o-nav-item:is([aria-current="page"], [aria-expanded="true"]) .o-badge { box-shadow: 0 0 0 2px var(--bg); }   /* a count keeps its edge on the gradient */
.o-nav-item__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 100%; }
.o-shell__brand, .o-shell__navfoot, .o-shell__pin { display: none; }
::view-transition-group(o-nav-pill) { animation-duration: var(--dur-fast-spatial); animation-timing-function: var(--spring-fast-spatial); }
::view-transition-image-pair(o-nav-pill) { animation: o-liquid var(--dur-fast-spatial) var(--spring-fast-spatial); }   /* the droplet stretches as it slides, like liquid */
@keyframes o-liquid { 45% { scale: 1.16 0.9; } }

/* Liquid glass, the material of everything that floats over content (the menu on phones, the review dock).
   Apple's Liquid Glass on true black is mostly light, not blur: a specular rim that is brightest where light falls on the
   edge (top left) and where it leaves (bottom right), a sheen inside the top edge, and a droplet of lighter glass under the
   chosen item. Clearer than a tint: the content behind keeps its colour, dimmed to half (brightness 0.5) and saturated,
   under a 45 % fill, so inactive icons keep Lc 59 and 5.0:1 even over white content (combos.py, both polarities). The rim is light, not
   color: white at changing strength, so the no-gradient-borders rule (colored outlines) does not apply.
   Glass blurs only what its backdrop root holds. No ancestor of a glass element may be one: no view-transition-name (not even
   one left over after a transition), opacity under 1, filter, mask, clip-path, mix-blend-mode, backdrop-filter or will-change
   of these. On such an ancestor the glass shows the content behind it sharp, only dimmed (test_glass.py; the review dock warns).
   To keep glass still during a transition, name the glass element itself and remove the name when the transition ends.
   It never changes size (his rule, 12 Nov 2026): no settling or hiding while scrolling. */
:root {
  --glass-fill: rgb(28 28 30 / 0.45);
  --glass-filter: blur(20px) saturate(180%) brightness(0.5);
  --glass-rim: linear-gradient(135deg, rgb(255 255 255 / 0.55), rgb(255 255 255 / 0) 30%, rgb(255 255 255 / 0) 70%, rgb(255 255 255 / 0.38)), linear-gradient(rgb(255 255 255 / 0.24), rgb(255 255 255 / 0.06) 55%, rgb(255 255 255 / 0.14));
  --glass-sheen: inset 0 0 12px rgb(255 255 255 / 0.07), inset 0 1px 1px rgb(255 255 255 / 0.18), inset 0 -1px 1px rgb(255 255 255 / 0.06), inset 0 14px 20px -16px rgb(255 255 255 / 0.3), 0 12px 32px rgb(0 0 0 / 0.5);
  --glass-drop: rgb(255 255 255 / 0.13);
  --glass-drop-edge: inset 0 1px 0 rgb(255 255 255 / 0.22), inset 0 -1px 0 rgb(255 255 255 / 0.05), inset 0 0 0 0.5px rgb(255 255 255 / 0.12);
}

/* Phones: menus always float. A capsule of dark glass 12 px from the sides and 8 px above the safe area,
   icon-only buttons (48 x 48 px, 8 px apart); the label becomes a tooltip (hover after 500 ms, focus at once,
   500 ms long-press) and stays in the accessibility tree as the item's name. */
@container shell (inline-size < 600px) {
  .o-shell__nav {
    position: sticky; inset-block-end: calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
    margin: 0 var(--space-12) calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
    gap: var(--space-8); padding: var(--space-8); border-radius: var(--radius-full);
    background: var(--surface-raised);                                    /* solid fallback */
    box-shadow: var(--glass-sheen);
  }
  .o-shell__nav::before {   /* the specular rim: a 1 px ring cut out of the rim light with a mask */
    content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none; background: var(--glass-rim);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .o-shell__nav { background: var(--glass-fill); -webkit-backdrop-filter: var(--glass-filter); backdrop-filter: var(--glass-filter); }
  }
  @media (prefers-reduced-transparency: reduce) { .o-shell__nav { background: var(--surface-raised); -webkit-backdrop-filter: none; backdrop-filter: none; } }
  .o-nav-item { flex: 1 1 0; min-inline-size: 48px; max-inline-size: 88px; block-size: 48px; align-content: stretch; }   /* stretch: the droplet fills the whole 48 px target, as Apple's does */
  .o-nav-item__icon { inline-size: 100%; block-size: 100%; }
  .o-nav-item:hover .o-nav-item__icon { background: rgb(255 255 255 / 0.06); }
  .o-nav-item[aria-current="page"] .o-nav-item__icon { background: var(--g-button); box-shadow: var(--glass-drop-edge); color: var(--on-button); }   /* the droplet: the button gradient under the glass highlight */
  /* One droplet at a time (his rule, 12 Nov 2026): a button that opens a sheet over the screen (Menu, More) takes it while the
     sheet is open (aria-expanded="true"); the current page's item gives it up meanwhile and keeps aria-current. The insets of a
     phone on its side move the capsule (its side offsets), never its 8 px padding. */
  .o-nav-item[aria-expanded="true"] { color: var(--text-1); font-weight: var(--w-semibold); }
  .o-nav-item[aria-expanded="true"] .o-icon { stroke-width: 2; }
  .o-nav-item[aria-expanded="true"] .o-nav-item__icon { background: var(--g-button); box-shadow: var(--glass-drop-edge); color: var(--on-button); }
  .o-shell__nav:has(> .o-nav-item[aria-expanded="true"]) > .o-nav-item[aria-current="page"]:not([aria-expanded="true"]) { color: var(--text-2); font-weight: var(--w-medium); }
  .o-shell__nav:has(> .o-nav-item[aria-expanded="true"]) > .o-nav-item[aria-current="page"]:not([aria-expanded="true"]) .o-icon { stroke-width: 1.75; color: inherit; }
  .o-shell__nav:has(> .o-nav-item[aria-expanded="true"]) > .o-nav-item[aria-current="page"]:not([aria-expanded="true"]) .o-nav-item__icon { background: none; box-shadow: none; color: inherit; }
  .o-nav-item__label {
    --_tx: -50%;   /* centred over its item; the first and last items align to their outer edge, so a tooltip never leaves the screen */
    position: absolute; inset-block-end: calc(100% + var(--space-12)); inset-inline-start: 50%; translate: var(--_tx) 4px; max-inline-size: none; overflow: visible;
    padding: var(--space-6) var(--space-8); border-radius: var(--radius-sm); background: var(--surface-overlay); color: var(--text-1);
    font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); pointer-events: none; opacity: 0;
    transition: opacity var(--dur-fast-effects) var(--spring-fast-effects), translate var(--dur-fast-effects) var(--spring-fast-effects);
  }
  .o-nav-item:nth-child(1 of .o-nav-item) .o-nav-item__label { --_tx: 0%; inset-inline-start: 0; }
  .o-nav-item:nth-last-child(1 of .o-nav-item) .o-nav-item__label { --_tx: 0%; inset-inline-start: auto; inset-inline-end: 0; }
  .o-nav-item__label::after { content: ""; position: absolute; inset-inline: 0; inset-block-start: 100%; block-size: var(--space-12); }   /* hover bridge (WCAG 1.4.13) */
  .o-nav-item:focus-visible .o-nav-item__label, .o-nav-item[data-tip] .o-nav-item__label { opacity: 1; translate: var(--_tx) 0; }
  @media (hover: hover) { .o-nav-item:hover .o-nav-item__label { opacity: 1; translate: var(--_tx) 0; pointer-events: auto; transition-delay: 500ms; } }
  .o-shell__nav[data-tip-off] .o-nav-item__label { opacity: 0; pointer-events: none; }   /* Esc dismisses */
  @media (forced-colors: active) { .o-shell__nav { border: 1px solid CanvasText; } .o-shell__nav::before { display: none; }
    .o-nav-item[aria-expanded="true"] .o-nav-item__icon { background: Highlight; color: HighlightText; } }   /* high contrast: the pill follows the droplet to the open button (26.11.13) */
  /* Focus never lands under the floating menu (WCAG 2.4.11): content keeps a scroll margin the size of the menu.
     Not scroll-padding on the scroller: that would also apply to the menu's own buttons and make the page jump when they get focus. */
  .o-shell__main * { scroll-margin-block-end: calc(var(--navbar-height) + var(--space-16) + env(safe-area-inset-bottom, 0px)); }
}

@container shell (inline-size >= 600px) {
  .o-shell__grid { grid-template: "nav main" 1fr / var(--rail-width) minmax(0, 1fr); }
  .o-shell__nav {
    position: sticky; inset-block: 0 auto; box-sizing: border-box; block-size: var(--o-vh, 100dvh); max-block-size: 100%; flex-direction: column; justify-content: flex-start; align-items: center;
    padding: var(--space-16) 0; background: var(--bg); border-inline-end: 1px solid #2c2c2e; gap: var(--space-12);
  }
  .o-nav-item { inline-size: 100%; max-inline-size: 120px; padding-block: var(--space-4); }
  .o-nav-item__icon { inline-size: min(56px, 100%); block-size: 32px; }
  .o-nav-item:hover .o-nav-item__icon { background: var(--surface-raised); }
  .o-nav-item[aria-current="page"] .o-nav-item__icon { background: var(--g-button); color: var(--on-button); }
  .o-shell__main { padding: var(--space-24); }
}
@container shell (inline-size >= 1200px) {
  .o-shell__grid { grid-template-columns: var(--sidebar-width) minmax(0, 1fr); }
  .o-shell__nav { align-items: stretch; padding: var(--space-16) var(--space-12); gap: var(--space-2); }
  .o-shell__brand { display: flex; align-items: center; gap: var(--space-12); font: var(--w-semibold) var(--fs-title-s)/1.2 var(--font-sans);
    padding-block: var(--space-8) var(--space-16); padding-inline: calc(var(--rail-width) / 2 - var(--space-12) - 14px) var(--space-12); }   /* a 28 px logo centred on the rail's axis */
  .o-shell__navfoot { display: block; margin-block-start: auto; padding: var(--space-12); color: var(--text-2); font: var(--w-medium) var(--fs-caption)/1.5 var(--font-sans); }
  .o-shell__nav > * { box-sizing: border-box; }   /* rows stay inside the sidebar, padding included */
  .o-nav-item { grid-template-columns: auto 1fr auto; justify-items: start; align-items: center; gap: var(--space-12); inline-size: auto; max-inline-size: none;
    min-block-size: var(--control); padding: 0 var(--space-16); font-size: var(--fs-label); }   /* icons on the rail's axis (40 px), so nothing jumps when the sidebar collapses */
  .o-nav-item .o-badge { position: static; justify-self: end; }   /* the count ends the row, as in a mail sidebar */
  .o-nav-item__icon { inline-size: auto; block-size: auto; background: none !important; }
  .o-nav-item:hover { background: var(--surface-raised); }
  .o-nav-item[aria-current="page"] { background: var(--g-button); color: var(--on-button); }
  .o-nav-item[aria-current="page"] .o-badge { background: none; color: inherit; box-shadow: none; }   /* on the gradient row the count is plain label text, as in a mail sidebar */
  .o-shell__main { padding: var(--space-32); }

  /* Pin (his rule, 12 Nov 2026). The button at the bottom of the sidebar pins it (in the layout, the default) or unpins it:
     then it is an 80 px rail that opens over the content on mouse hover (after 200 ms, so passing over it does nothing) or
     keyboard focus, and closes 300 ms after the pointer leaves, or at once on Esc. Ctrl+\ (Cmd+\ on a Mac) does the same.
     The content keeps its place while the sidebar opens over it; it moves only when the sidebar is pinned or unpinned. */
  .o-shell__grid { transition: grid-template-columns var(--dur-default-spatial) var(--spring-default-spatial); }
  .o-shell__pin {
    position: relative; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-12); min-block-size: var(--control);
    padding: 0 var(--space-16); border: 0; border-radius: var(--radius-md); background: none; color: var(--text-2); cursor: pointer;
    font: var(--w-medium) var(--fs-label)/1.3 var(--font-sans); text-align: start; white-space: nowrap;
  }
  .o-shell__pin:hover { background: var(--surface-raised); color: var(--text-1); }
  .o-shell__pin kbd { color: var(--text-2); font: var(--w-medium) var(--fs-caption)/1 var(--font-sans); }
  .o-shell__pin-on, .o-shell__pin-off { display: contents; }
  :root:not([data-sidebar="unpinned"]) .o-shell__pin-off, :root[data-sidebar="unpinned"] .o-shell__pin-on { display: none; }
  :root[data-sidebar="unpinned"] .o-shell__grid { grid-template-columns: var(--rail-width) minmax(0, 1fr); }
  :root[data-sidebar="unpinned"] .o-shell__nav {
    z-index: 3; inline-size: var(--rail-width); overflow-x: clip;
    transition: inline-size var(--dur-default-spatial) var(--spring-default-spatial) 300ms, box-shadow var(--dur-default-effects) var(--spring-default-effects) 300ms;
  }
  :root[data-sidebar="unpinned"] .o-shell__nav > * { min-inline-size: calc(var(--sidebar-width) - 2 * var(--space-12) - 1px); }   /* laid out at full width and only revealed: no text reflows */
  :root[data-sidebar="unpinned"] .o-shell__nav :is(.o-nav-item__label, .o-shell__brand-name, .o-shell__navfoot, .o-shell__pin-label, .o-shell__pin kbd) {
    opacity: 0; transition: opacity var(--dur-fast-effects) var(--spring-fast-effects) 300ms;
  }
  /* hover and current: a 56 px tile on the rail that widens to the whole row as the sidebar opens */
  :root[data-sidebar="unpinned"] :is(.o-nav-item, .o-shell__pin) { background: none; }
  :root[data-sidebar="unpinned"] :is(.o-nav-item, .o-shell__pin)::before {
    content: ""; position: absolute; z-index: -1; inset-block: 0; inset-inline-start: 0; inline-size: calc(var(--rail-width) - 2 * var(--space-12));
    border-radius: var(--radius-md); transition: inline-size var(--dur-default-spatial) var(--spring-default-spatial) 300ms;
  }
  :root[data-sidebar="unpinned"] :is(.o-nav-item, .o-shell__pin):hover::before { background: var(--surface-raised); }
  :root[data-sidebar="unpinned"] .o-nav-item[aria-current="page"]::before { background: var(--g-button); }
  :root[data-sidebar="unpinned"] .o-nav-item[aria-current="page"] .o-badge { background: var(--selection); color: #fff; box-shadow: 0 0 0 2px var(--bg); }   /* back on its icon: the pill again */
  :root[data-sidebar="unpinned"] .o-nav-item .o-badge { position: absolute; inset-block-start: 2px; inset-inline-start: calc(var(--space-16) + 14px); }   /* the count on its icon */
  /* open over the content: a black shadow fades the content along its edge, so it reads as a layer */
  :root[data-sidebar="unpinned"] .o-shell__nav { --_peek: 16px 0 32px rgb(0 0 0 / 0.85); }
  :root[data-sidebar="unpinned"] .o-shell__nav:dir(rtl) { --_peek: -16px 0 32px rgb(0 0 0 / 0.85); }
  @media (hover: hover) {
    :root[data-sidebar="unpinned"] .o-shell__nav:hover:not([data-peek-off]) { inline-size: var(--sidebar-width); box-shadow: var(--_peek); transition-delay: 200ms; }
    :root[data-sidebar="unpinned"] .o-shell__nav:hover:not([data-peek-off]) :is(.o-nav-item__label, .o-shell__brand-name, .o-shell__navfoot, .o-shell__pin-label, .o-shell__pin kbd) { opacity: 1; transition-delay: 200ms; }
    :root[data-sidebar="unpinned"] .o-shell__nav:hover:not([data-peek-off]) :is(.o-nav-item, .o-shell__pin)::before { inline-size: 100%; transition-delay: 200ms; }
  }
  /* keyboard focus opens it at once; a mouse click on the button does not (focus-visible), so unpinning with the mouse lets it close */
  :root[data-sidebar="unpinned"] .o-shell__nav:has(:focus-visible):not([data-peek-off]) { inline-size: var(--sidebar-width); box-shadow: var(--_peek); transition-delay: 0s; }
  :root[data-sidebar="unpinned"] .o-shell__nav:has(:focus-visible):not([data-peek-off]) :is(.o-nav-item__label, .o-shell__brand-name, .o-shell__navfoot, .o-shell__pin-label, .o-shell__pin kbd) { opacity: 1; transition-delay: 0s; }
  :root[data-sidebar="unpinned"] .o-shell__nav:has(:focus-visible):not([data-peek-off]) :is(.o-nav-item, .o-shell__pin)::before { inline-size: 100%; transition-delay: 0s; }
}
@media (prefers-reduced-motion: reduce) {   /* the delays stay (they are not motion); the change is instant */
  .o-shell__grid, .o-shell__nav, .o-shell__nav :is(.o-nav-item__label, .o-shell__brand-name, .o-shell__navfoot, .o-shell__pin-label, .o-shell__pin kbd),
  .o-shell__nav :is(.o-nav-item, .o-shell__pin)::before { transition-duration: 0s !important; }
}
@container shell (inline-size >= 1600px) { .o-shell__main { padding-inline: var(--space-40); } }
.o-content { max-inline-size: var(--content-max); margin-inline: auto; }

.o-appbar { display: flex; align-items: center; gap: var(--space-12); min-block-size: var(--appbar-height); padding-block-start: env(safe-area-inset-top, 0px); }
.o-appbar__title { flex: 1; min-inline-size: 0; font: var(--w-semibold) var(--fs-headline)/1.2 var(--font-sans); }

.o-grid { display: grid; gap: var(--space-16); grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
@container shell (inline-size >= 600px) { .o-grid { gap: var(--space-24); } }

/* ---------- overlays ---------- */

.o-dialog, .o-sheet {
  border: 0; padding: 0; color: var(--text-1); background: var(--surface-raised); box-shadow: var(--ring-raised);
  overscroll-behavior: contain;
  opacity: 0;
  transition: opacity var(--dur-default-effects) var(--spring-default-effects), translate var(--dur-default-spatial) var(--spring-default-spatial),
              display var(--dur-default-effects), overlay var(--dur-default-effects);
  transition-behavior: allow-discrete;
}
.o-dialog { inline-size: min(560px, var(--o-vw, 100%) - 2 * var(--space-16)); max-block-size: min(720px, var(--o-vh, 100dvh) - 2 * var(--space-16)); border-radius: var(--radius-xl); translate: 0 8px; }
.o-dialog[open]:where(:not([data-closing])), .o-sheet[open]:where(:not([data-closing])) { opacity: 1; translate: 0 0; }
@starting-style { .o-dialog[open] { opacity: 0; translate: 0 8px; } .o-sheet[open] { opacity: 1; translate: 0 100%; } }
.o-dialog::backdrop, .o-sheet::backdrop {
  background: var(--scrim); overflow: hidden; overscroll-behavior: contain; opacity: 0;
  transition: opacity var(--dur-default-effects) linear, display var(--dur-default-effects), overlay var(--dur-default-effects);
  transition-behavior: allow-discrete;
}
.o-dialog[open]:where(:not([data-closing]))::backdrop, .o-sheet[open]:where(:not([data-closing]))::backdrop { opacity: 1; }
@starting-style { .o-dialog[open]::backdrop, .o-sheet[open]::backdrop { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .o-dialog, .o-sheet { translate: none !important; } }
.o-dialog__inner { display: grid; gap: var(--space-16); padding: var(--space-24); }
.o-dialog__title { font: var(--w-semibold) var(--fs-title)/1.3 var(--font-sans); margin: 0; }
.o-dialog__body { color: var(--text-1); margin: 0; }
.o-dialog__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-12); padding-block-start: var(--space-8); }

.o-sheet { margin: auto auto 0; inline-size: var(--o-vw, 100%); max-inline-size: 100%; max-block-size: calc(0.9 * var(--o-vh, 100dvh)); border-radius: var(--radius-xl) var(--radius-xl) 0 0; translate: 0 100%;
  padding-block-end: env(safe-area-inset-bottom, 0px); }
.o-sheet__handle { display: block; inline-size: 36px; block-size: 4px; margin: var(--space-8) auto 0; border-radius: var(--radius-full); background: #48484a; }
/* Side sheet from 840 px: measured on the window, or on the review dock's device when the page has one (Mobile shows a phone) */
@media (min-width: 840px) {
  :where(:root:not([data-o-fit])) .o-sheet { margin: 0; margin-inline-start: auto; block-size: var(--o-vh, 100dvh); max-block-size: var(--o-vh, 100dvh); inline-size: min(400px, var(--o-vw, 100%)); border-start-start-radius: var(--radius-xl); border-end-start-radius: var(--radius-xl); border-start-end-radius: 0; border-end-end-radius: 0; translate: 100% 0; }
  :where(:root:not([data-o-fit])) .o-sheet:dir(rtl):where(:not([open]), [data-closing]) { translate: -100% 0; }
  :where(:root:not([data-o-fit])) .o-sheet__handle { display: none; }
  @starting-style { :where(:root:not([data-o-fit])) .o-sheet[open] { translate: 100% 0; } :where(:root:not([data-o-fit])) .o-sheet[open]:dir(rtl) { translate: -100% 0; } }
}
@container device (width >= 840px) {
  .o-sheet { margin: 0; margin-inline-start: auto; block-size: var(--o-vh, 100dvh); max-block-size: var(--o-vh, 100dvh); inline-size: min(400px, var(--o-vw, 100%)); border-start-start-radius: var(--radius-xl); border-end-start-radius: var(--radius-xl); border-start-end-radius: 0; border-end-end-radius: 0; translate: 100% 0; }
  .o-sheet:dir(rtl):where(:not([open]), [data-closing]) { translate: -100% 0; }
  .o-sheet__handle { display: none; }
  @starting-style { .o-sheet[open] { translate: 100% 0; } .o-sheet[open]:dir(rtl) { translate: -100% 0; } }
}

/* Menu and popover: top layer, anchored where supported */
.o-menu {
  border: 0; padding: var(--space-4); min-inline-size: 200px; max-inline-size: min(320px, 100vw - 32px);
  border-radius: var(--radius-lg); background: var(--surface-raised); color: var(--text-1); box-shadow: var(--shadow-overlay);
  opacity: 0; translate: 0 -4px;
  transition: opacity var(--dur-default-effects) var(--spring-default-effects), translate var(--dur-fast-spatial) var(--spring-fast-spatial),
              display var(--dur-default-effects), overlay var(--dur-default-effects);
  transition-behavior: allow-discrete;
}
.o-menu:popover-open { opacity: 1; translate: 0 0; }
@starting-style { .o-menu:popover-open { opacity: 0; translate: 0 -4px; } }
@supports (position-area: bottom) {
  .o-menu[popover] { margin: 0; margin-block: var(--space-4); position-area: block-end span-inline-end; position-try-fallbacks: flip-block, flip-inline; }
}
/* No anchor positioning (Safari before 26, Firefox before 147): open at the bottom, centred, instead of the top-left corner */
@supports not (position-area: bottom) {
  .o-menu[popover] { position: fixed; inset: auto 0 calc(var(--space-8) + env(safe-area-inset-bottom, 0px)) 0; margin: 0 auto; inline-size: fit-content; }
}
.o-menu__item {
  display: flex; align-items: center; gap: var(--space-12); inline-size: 100%; min-block-size: var(--control);
  padding-inline: var(--space-12); border: 0; border-radius: var(--radius-md); background: none; color: var(--text-1);
  font: var(--w-regular) var(--fs-dense)/1.3 var(--font-sans); text-align: start; cursor: pointer;
}
.o-menu__item > .o-icon { color: var(--text-2); }
.o-menu__item:hover, .o-menu__item:focus-visible { background: var(--surface-overlay); outline-offset: -2px; }
.o-menu__item--danger { color: var(--err); }
.o-menu__item--danger > .o-icon { color: var(--err); }
.o-menu__sep { block-size: 1px; margin: var(--space-4) var(--space-8); background: var(--line); border: 0; }
.o-menu__kbd { margin-inline-start: auto; color: var(--text-2); font-size: var(--fs-caption); }

.o-tip {
  border: 0; padding: var(--space-6) var(--space-8); max-inline-size: 240px; border-radius: var(--radius-sm);
  background: var(--surface-overlay); color: var(--text-1); font: var(--w-label) var(--fs-label)/1.4 var(--font-sans);
  opacity: 0; transition: opacity var(--dur-fast-effects) var(--spring-fast-effects), display var(--dur-fast-effects), overlay var(--dur-fast-effects);
  transition-behavior: allow-discrete;
}
.o-tip:popover-open { opacity: 1; }
@starting-style { .o-tip:popover-open { opacity: 0; } }
@supports (position-area: top) { .o-tip[popover] { margin: 0; margin-block: var(--space-6); position-area: block-start; position-try-fallbacks: flip-block; } }
@supports not (position-area: top) { .o-tip[popover] { position: fixed; inset: auto 0 calc(var(--space-16) + env(safe-area-inset-bottom, 0px)) 0; margin: 0 auto; inline-size: fit-content; } }

/* Toasts: one region, bottom-right on wide, bottom on compact, above the floating menu */
.o-toasts {
  position: fixed; z-index: 10; inset-inline: var(--space-16); inset-block-end: calc(var(--space-16) + env(safe-area-inset-bottom, 0px));
  display: grid; gap: var(--space-8); justify-items: center; pointer-events: none;
}
@media (max-width: 599.98px) { :root:has(.o-shell__nav) .o-toasts { inset-block-end: calc(var(--navbar-height) + var(--space-16) + env(safe-area-inset-bottom, 0px)); } }   /* clear the floating menu */
@media (min-width: 600px) { .o-toasts { inset-inline: auto var(--space-24); inset-block-end: var(--space-24); justify-items: end; } }
/* Inside the review dock's device the toasts follow the device, not the window */
@container device (width < 600px) {
  .o-toasts { inset-inline: var(--space-16); inset-block-end: calc(var(--space-16) + env(safe-area-inset-bottom, 0px)); justify-items: center; }
  .o-device:has(.o-shell__nav) .o-toasts { inset-block-end: calc(var(--navbar-height) + var(--space-16) + env(safe-area-inset-bottom, 0px)); }
}
@container device (width >= 600px) { .o-toasts { inset-inline: auto var(--space-24); inset-block-end: var(--space-24); justify-items: end; } }
.o-toast {
  pointer-events: auto; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-12);
  inline-size: min(420px, 100%); box-sizing: border-box; padding-block: var(--space-12); padding-inline: var(--space-16) var(--space-8);
  border-radius: var(--radius-lg); background: var(--surface-raised); box-shadow: var(--ring-raised); color: var(--text-1);
  font: var(--w-regular) var(--fs-dense)/1.4 var(--font-sans);
  animation: o-toast-in var(--dur-default-spatial) var(--spring-default-spatial);
}
.o-toast > .o-icon { color: var(--_tone, var(--accent-text)); }
.o-toast--ok { --_tone: var(--ok); } .o-toast--warn { --_tone: var(--warn); } .o-toast--err { --_tone: var(--err); }
.o-toast__action { color: var(--accent-text); font-weight: var(--w-medium); }
@keyframes o-toast-in { from { opacity: 0; translate: 0 12px; } }
@media (prefers-reduced-motion: reduce) { .o-toast { animation-name: o-fade-in; } }
@keyframes o-fade-in { from { opacity: 0; } }

/* ---------- feedback ---------- */

.o-progress { appearance: none; display: block; inline-size: 100%; block-size: 8px; border: 0; border-radius: var(--radius-full); background: var(--track); overflow: hidden; color: var(--brand-a); }
.o-progress::-webkit-progress-bar { background: var(--track); border-radius: inherit; }
.o-progress::-webkit-progress-value { background: var(--g-brand); border-radius: inherit; transition: inline-size var(--dur-default-spatial) var(--spring-default-spatial); }
.o-progress::-moz-progress-bar { background: var(--g-brand); border-radius: inherit; }
.o-progress:indeterminate { background: var(--track) linear-gradient(90deg, transparent, var(--brand-a), var(--brand-b), transparent) no-repeat; background-size: 40% 100%; animation: o-indeterminate 1.4s var(--ease-standard) infinite; }
.o-progress:indeterminate::-webkit-progress-bar { background: transparent; }
.o-progress:indeterminate::-moz-progress-bar { background: transparent; }
@keyframes o-indeterminate { from { background-position: -60% 0; } to { background-position: 160% 0; } }
@media (prefers-reduced-motion: reduce) { .o-progress:indeterminate { animation-duration: 3s; } }
.o-progress-row { display: grid; grid-template-columns: 1fr auto; gap: var(--space-8) var(--space-12); align-items: center; font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); }
.o-progress-row > .o-progress { grid-column: 1 / -1; }

.o-ring { --value: 0; --size: 64px; inline-size: var(--size); block-size: var(--size); rotate: -90deg; }
.o-ring circle { fill: none; stroke-width: 6; }
.o-ring .o-ring__track { stroke: var(--track); }
.o-ring .o-ring__value { stroke: url(#o-ring-gradient); stroke-linecap: round; stroke-dasharray: calc(var(--value) * 1.759px) 175.9px; transition: stroke-dasharray var(--dur-default-spatial) var(--spring-default-spatial); }

.o-spinner { --size: 24px; inline-size: var(--size); block-size: var(--size); border-radius: 50%; flex: none;
  background: conic-gradient(from 0turn, transparent 10%, var(--brand-a), var(--brand-b));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
  animation: o-spin 0.9s linear infinite; }
@keyframes o-spin { to { rotate: 1turn; } }
@media (prefers-reduced-motion: reduce) { .o-spinner { animation-duration: 2.4s; } }

.o-skeleton { display: block; border-radius: var(--radius-xs); background: var(--surface-raised); animation: o-pulse 1.6s ease-in-out infinite; }
.o-skeleton--text { block-size: 0.9em; margin-block: 0.3em; }
.o-skeleton--circle { border-radius: 50%; }
@keyframes o-pulse { 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) { .o-skeleton { animation: none; } }

.o-empty { display: grid; justify-items: center; gap: var(--space-12); padding: var(--space-48) var(--space-24); text-align: center; }
.o-empty > .o-icon { inline-size: 48px; block-size: 48px; color: var(--text-3); stroke-width: 1.5; }
.o-empty__title { font: var(--w-semibold) var(--fs-title-s)/1.35 var(--font-sans); margin: 0; }
.o-empty__text { color: var(--text-2); margin: 0; max-inline-size: 36ch; }

.o-kbd { display: inline-block; min-inline-size: 1.6em; padding: 0 var(--space-6); border-radius: var(--radius-xs); box-shadow: inset 0 -1px 0 #48484a, inset 0 0 0 1px #3a3a3c;
  background: var(--surface-raised); font: var(--w-medium) var(--fs-caption)/1.7 var(--font-mono); text-align: center; }
.o-code-inline { padding: 0.1em 0.35em; border-radius: var(--radius-xs); background: var(--surface-raised); font-family: var(--font-mono); font-size: 0.9em; }
.o-codeblock { margin: 0; padding: var(--space-16); border-radius: var(--radius-lg); background: var(--surface-raised); box-shadow: var(--ring-raised);
  overflow-x: auto; font: var(--w-regular) var(--fs-code)/1.6 var(--font-mono); color: var(--text-1); tab-size: 2; }

/* ---------- charts ---------- */

.o-chart { position: relative; display: grid; gap: var(--space-12); }
.o-chart svg { display: block; inline-size: 100%; block-size: auto; overflow: visible; }
.o-chart__grid { stroke: var(--chart-grid); stroke-width: 1; shape-rendering: crispEdges; }
.o-chart__axis { stroke: var(--chart-axis); stroke-width: 1; shape-rendering: crispEdges; }
.o-chart__tick { fill: var(--text-2); font: var(--w-medium) 12px/1 var(--font-sans); font-variant-numeric: tabular-nums; }
.o-chart__line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.o-chart__legend { display: flex; flex-wrap: wrap; gap: var(--space-6) var(--space-16); margin: 0; padding: 0; list-style: none; font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-1); }
.o-chart__legend li { display: inline-flex; align-items: center; gap: var(--space-8); }
.o-chart__key { inline-size: 12px; block-size: 12px; border-radius: 3px; background: var(--_c); }
.o-chart__tooltip { position: absolute; pointer-events: none; padding: var(--space-8) var(--space-12); border-radius: var(--radius-sm); background: var(--surface-overlay);
  font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-1); white-space: nowrap; translate: -50% calc(-100% - 12px); }
.o-chart__tooltip[hidden] { display: none; }

/* ---------- theme picker (Settings): radio cards, each previewing its own theme ---------- */
.o-theme-picker { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 148px), 1fr)); gap: var(--space-12); margin: 0; padding: 0; border: 0; min-inline-size: 0; }
.o-theme-picker > legend { padding: 0; margin-block-end: var(--space-8); font: var(--w-field-label) var(--fs-label)/1.4 var(--font-sans); color: var(--text-1); }
.o-theme-option { display: grid; gap: var(--space-12); padding: var(--space-12); border: 1px solid var(--border-input); border-radius: var(--radius-lg); background: var(--bg); color: var(--text-1); cursor: pointer; min-block-size: var(--target); }
.o-theme-option:hover { border-color: var(--border-hover); }
.o-theme-option:has(input:checked) { border-color: var(--text-1); box-shadow: inset 0 0 0 1px var(--text-1); }
.o-theme-option:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.o-theme-option__swatch { display: grid; grid-template-columns: 2fr 1fr; gap: var(--space-6); block-size: 40px; }
.o-theme-option__swatch::before { content: ""; border-radius: var(--radius-full); background: var(--g-button); }
.o-theme-option__swatch::after { content: ""; border-radius: var(--radius-full); background: var(--g-brand); }
.o-theme-option > .o-check { min-block-size: 0; font: var(--w-label) var(--fs-label)/1.4 var(--font-sans); }
.o-theme-option > .o-check > input:focus-visible { outline: none; }

/* ---------- motion utilities (Foundations -> Motion has a live example of each) ---------- */

/* Rows added or removed: expand and collapse in place with grid rows 0fr <-> 1fr (no height measuring).
   Markup: <li class="o-collapse"><div><div class="o-list__row">…</div></div></li>: the plain wrapper is what shrinks, so the row keeps its own min-height.
   New rows get data-enter (so rows present at load do not animate); removing sets data-collapsed, then the row is removed on transitionend. */
.o-collapse { display: grid; grid-template-rows: 1fr; opacity: 1;
  transition: grid-template-rows var(--dur-default-spatial) var(--spring-default-spatial), opacity var(--dur-default-effects) var(--spring-default-effects); }
.o-collapse > * { min-block-size: 0; overflow: hidden; }
.o-collapse[data-collapsed] { grid-template-rows: 0fr; opacity: 0; }
@starting-style { .o-collapse[data-enter] { grid-template-rows: 0fr; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .o-collapse { transition-property: opacity; } }

/* A number that changes counts to its new value: <span class="o-count" style="--o-num: 67" aria-hidden="true"></span> plus the real value as text for assistive tech */
@property --o-num { syntax: '<integer>'; inherits: false; initial-value: 0; }
.o-count { counter-reset: o-num var(--o-num); font-variant-numeric: tabular-nums; transition: --o-num var(--dur-slow-effects) var(--spring-slow-effects); }
.o-count::after { content: counter(o-num); }
@media (prefers-reduced-motion: reduce) { .o-count { transition: none; } }

/* Screen push and back: a same-document view transition on the element named o-screen; <html data-vt="push|back"> sets the direction.
   Black screens slide over black without smear; reduced motion cross-fades. */
::view-transition-image-pair(o-screen) { overflow: clip; }
html:is(:active-view-transition-type(push, back), [data-vt])::view-transition-old(o-screen), html:is(:active-view-transition-type(push, back), [data-vt])::view-transition-new(o-screen) { mix-blend-mode: normal; animation-duration: var(--dur-slow-spatial); animation-timing-function: var(--spring-slow-spatial); animation-fill-mode: both; }
html:is(:active-view-transition-type(push), [data-vt="push"])::view-transition-old(o-screen) { animation-name: o-out-start; }
html:is(:active-view-transition-type(push), [data-vt="push"])::view-transition-new(o-screen) { animation-name: o-in-end; }
html:is(:active-view-transition-type(back), [data-vt="back"])::view-transition-old(o-screen) { animation-name: o-out-end; z-index: 1; }
html:is(:active-view-transition-type(back), [data-vt="back"])::view-transition-new(o-screen) { animation-name: o-in-start; }
@keyframes o-out-start { to { translate: -30% 0; opacity: 0; } }
@keyframes o-in-end { from { translate: 100% 0; } }
@keyframes o-out-end { to { translate: 100% 0; } }
@keyframes o-in-start { from { translate: -30% 0; opacity: 0; } }
@keyframes o-fade-out { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  html:is(:active-view-transition-type(push, back), [data-vt])::view-transition-old(o-screen) { animation: o-fade-out var(--dur-default-effects) linear both; }
  html:is(:active-view-transition-type(push, back), [data-vt])::view-transition-new(o-screen) { animation: o-fade-in var(--dur-default-effects) linear both; }
  ::view-transition-group(o-nav-pill), ::view-transition-image-pair(o-nav-pill) { animation-duration: 0s; }
}

@media (forced-colors: active) {
  .o-btn--primary, .o-check > input:checked, .o-switch > input:checked { background: Highlight; }
  .o-btn--primary { color: HighlightText; }
  .o-card, .o-dialog, .o-menu, .o-toast, .o-sheet, .o-tip, .o-nav-item__label, .o-badge { border: 1px solid CanvasText; }
  /* states drawn with gradients, fills or shadows: forced colors removes those, so draw them in system colors */
  .o-tab[aria-selected="true"], .o-icon-btn[aria-pressed="true"], .o-chip[aria-pressed="true"] { background: Highlight; color: HighlightText; }
  .o-nav-item[aria-current="page"] .o-nav-item__icon { background: Highlight; color: HighlightText; }
  .o-progress { border: 1px solid CanvasText; }
  .o-progress::-webkit-progress-value { background: Highlight; }
  .o-progress::-moz-progress-bar { background: Highlight; }
  .o-progress:indeterminate { forced-color-adjust: none; background: Canvas linear-gradient(90deg, transparent, Highlight, transparent) no-repeat; background-size: 40% 100%; }
  .o-spinner { forced-color-adjust: none; background: conic-gradient(from 0turn, transparent 10%, CanvasText); }
  .o-ring { forced-color-adjust: none; }
  .o-ring .o-ring__track { stroke: GrayText; }
  .o-ring .o-ring__value { stroke: Highlight; }
}
