/* Generated by ui::theme::css() from the palettes in src/theme.rs. */

:root, [data-theme="default"] {
  --ui-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-font-head: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-text-xs: 0.75rem;
  --ui-text-sm: 0.8125rem;
  --ui-text-base: 0.9375rem;
  --ui-text-lg: 1.125rem;
  --ui-text-xl: 1.625rem;
  --ui-leading: 1.5;
  --ui-heading-weight: 620;
  --ui-heading-tracking: -0.01em;
  --ui-eyebrow-font: var(--ui-font-sans);
  --ui-eyebrow-size: var(--ui-text-xs);
  --ui-eyebrow-weight: 560;
  --ui-eyebrow-tracking: 0.04em;
  --ui-eyebrow-case: uppercase;
  --ui-eyebrow-style: normal;
  --ui-eyebrow-color: var(--ui-text-muted);
  --ui-radius-sm: 0.3rem;
  --ui-radius-md: 0.5rem;
  --ui-radius-lg: 0.75rem;
  --ui-btn-radius: var(--ui-radius-md);
  --ui-badge-radius: 999px;
  --ui-card-radius: var(--ui-radius-lg);
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2.25rem;
  --ui-control-h-sm: 2rem;
  --ui-control-h-lg: 2.75rem;
  --ui-control-px: 1rem;
  --ui-control-weight: 560;
  --ui-card-pad: 1rem;
  --ui-card-shadow: var(--ui-shadow-sm);
  --ui-card-border: var(--ui-border);
  --ui-input-shadow: none;
  --ui-ring: 0 0 0 2px var(--ui-bg), 0 0 0 4px var(--ui-ring-color);
  --ui-badge-tint: 12%;
  --ui-badge-border: transparent;
  --ui-alert-tint: 8%;
  --ui-cell-py: 0.5rem;
  --ui-cell-px: 0.75rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(240 20% 99%);
  --ui-bg-card: hsl(0 0% 100%);
  --ui-bg-subtle: hsl(240 20% 97.5%);
  --ui-bg-muted: hsl(240 4.8% 95.9%);
  --ui-bg-hover: hsl(240 4.8% 95.5%);
  --ui-border: hsl(240 6% 92.5%);
  --ui-border-strong: hsl(240 6% 85%);
  --ui-border-control: hsl(240 5% 55%);
  --ui-text: hsl(240 10% 3.9%);
  --ui-text-muted: hsl(240 4% 43.5%);
  --ui-accent: hsl(238 72% 56%);
  --ui-accent-hover: hsl(238 72% 50%);
  --ui-accent-fg: hsl(0 0% 100%);
  --ui-accent-muted: hsl(238 60% 96%);
  --ui-ring-color: hsl(238 72% 56%);
  --ui-success: hsl(145 55% 29%);
  --ui-warning: hsl(32 90% 32.5%);
  --ui-danger: hsl(0 72% 46%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="journal"] {
  --ui-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-font-head: "Newsreader", Georgia, "Times New Roman", serif;
  --ui-text-xs: 0.8125rem;
  --ui-text-sm: 0.875rem;
  --ui-text-base: 1rem;
  --ui-text-lg: 1.25rem;
  --ui-text-xl: 1.875rem;
  --ui-leading: 1.7;
  --ui-heading-weight: 560;
  --ui-heading-tracking: -0.008em;
  --ui-eyebrow-font: "Newsreader", Georgia, "Times New Roman", serif;
  --ui-eyebrow-size: var(--ui-text-sm);
  --ui-eyebrow-weight: 500;
  --ui-eyebrow-tracking: 0;
  --ui-eyebrow-case: none;
  --ui-eyebrow-style: italic;
  --ui-eyebrow-color: var(--ui-text-muted);
  --ui-radius-sm: 0.3rem;
  --ui-radius-md: 0.5rem;
  --ui-radius-lg: 0.7rem;
  --ui-btn-radius: 999px;
  --ui-badge-radius: 999px;
  --ui-card-radius: var(--ui-radius-lg);
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2.5rem;
  --ui-control-h-sm: 2.125rem;
  --ui-control-h-lg: 3rem;
  --ui-control-px: 1.125rem;
  --ui-control-weight: 600;
  --ui-card-pad: 1.25rem;
  --ui-card-shadow: none;
  --ui-card-border: var(--ui-border);
  --ui-input-shadow: none;
  --ui-ring: 0 0 0 2px var(--ui-bg), 0 0 0 4px var(--ui-ring-color);
  --ui-badge-tint: 12%;
  --ui-badge-border: transparent;
  --ui-alert-tint: 8%;
  --ui-cell-py: 0.625rem;
  --ui-cell-px: 0.75rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(38 30% 98.5%);
  --ui-bg-card: hsl(38 30% 99.3%);
  --ui-bg-subtle: hsl(38 22% 96.5%);
  --ui-bg-muted: hsl(38 18% 95.5%);
  --ui-bg-hover: hsl(38 22% 94%);
  --ui-border: hsl(34 16% 88%);
  --ui-border-strong: hsl(34 16% 80%);
  --ui-border-control: hsl(34 10% 55%);
  --ui-text: hsl(30 12% 14%);
  --ui-text-muted: hsl(34 8% 40%);
  --ui-accent: hsl(8 56% 44%);
  --ui-accent-hover: hsl(8 56% 38%);
  --ui-accent-fg: hsl(38 30% 98%);
  --ui-accent-muted: hsl(8 50% 95%);
  --ui-ring-color: hsl(8 56% 44%);
  --ui-success: hsl(145 55% 29%);
  --ui-warning: hsl(32 90% 32%);
  --ui-danger: hsl(0 72% 45.5%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: hsl(28 22% 16%);
  --ui-btn-bg-hover: hsl(28 22% 16%);
  --ui-btn-fg: hsl(38 30% 97%);
  --ui-btn-shadow: var(--ui-shadow-sm);
  --ui-btn-hover-filter: brightness(1.3);
}
[data-theme="studio"] {
  --ui-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-font-head: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-text-xs: 0.6875rem;
  --ui-text-sm: 0.8125rem;
  --ui-text-base: 0.875rem;
  --ui-text-lg: 1rem;
  --ui-text-xl: 1.375rem;
  --ui-leading: 1.5;
  --ui-heading-weight: 650;
  --ui-heading-tracking: -0.02em;
  --ui-eyebrow-font: var(--ui-font-sans);
  --ui-eyebrow-size: 0.6875rem;
  --ui-eyebrow-weight: 650;
  --ui-eyebrow-tracking: 0.08em;
  --ui-eyebrow-case: uppercase;
  --ui-eyebrow-style: normal;
  --ui-eyebrow-color: var(--ui-text-muted);
  --ui-radius-sm: 0.25rem;
  --ui-radius-md: 0.375rem;
  --ui-radius-lg: 0.5rem;
  --ui-btn-radius: var(--ui-radius-md);
  --ui-badge-radius: var(--ui-radius-sm);
  --ui-card-radius: var(--ui-radius-lg);
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2rem;
  --ui-control-h-sm: 1.75rem;
  --ui-control-h-lg: 2.5rem;
  --ui-control-px: 0.75rem;
  --ui-control-weight: 560;
  --ui-card-pad: 0.875rem;
  --ui-card-shadow: none;
  --ui-card-border: var(--ui-border);
  --ui-input-shadow: none;
  --ui-ring: 0 0 0 2px var(--ui-bg), 0 0 0 4px var(--ui-ring-color);
  --ui-badge-tint: 12%;
  --ui-badge-border: transparent;
  --ui-alert-tint: 6%;
  --ui-cell-py: 0.375rem;
  --ui-cell-px: 0.625rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(240 12% 96.5%);
  --ui-bg-card: hsl(0 0% 100%);
  --ui-bg-subtle: hsl(250 14% 94%);
  --ui-bg-muted: hsl(250 13% 94%);
  --ui-bg-hover: hsl(250 13% 92%);
  --ui-border: hsl(246 14% 89%);
  --ui-border-strong: hsl(247 11% 80%);
  --ui-border-control: hsl(247 8% 55%);
  --ui-text: hsl(250 17% 13%);
  --ui-text-muted: hsl(247 9% 42%);
  --ui-accent: hsl(327 74% 42%);
  --ui-accent-hover: hsl(327 77% 38%);
  --ui-accent-fg: hsl(0 0% 100%);
  --ui-accent-muted: hsl(327 62% 95%);
  --ui-ring-color: hsl(327 74% 48%);
  --ui-success: hsl(150 45% 29%);
  --ui-warning: hsl(32 90% 31%);
  --ui-danger: hsl(0 72% 44%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="console"] {
  --ui-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-font-head: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-text-xs: 0.75rem;
  --ui-text-sm: 0.8125rem;
  --ui-text-base: 0.9375rem;
  --ui-text-lg: 1.125rem;
  --ui-text-xl: 1.75rem;
  --ui-leading: 1.5;
  --ui-heading-weight: 720;
  --ui-heading-tracking: -0.03em;
  --ui-eyebrow-font: var(--ui-font-sans);
  --ui-eyebrow-size: var(--ui-text-xs);
  --ui-eyebrow-weight: 700;
  --ui-eyebrow-tracking: 0.1em;
  --ui-eyebrow-case: uppercase;
  --ui-eyebrow-style: normal;
  --ui-eyebrow-color: var(--ui-accent);
  --ui-radius-sm: 0.5rem;
  --ui-radius-md: 0.75rem;
  --ui-radius-lg: 1rem;
  --ui-btn-radius: var(--ui-radius-md);
  --ui-badge-radius: 999px;
  --ui-card-radius: var(--ui-radius-lg);
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2.5rem;
  --ui-control-h-sm: 2.125rem;
  --ui-control-h-lg: 3rem;
  --ui-control-px: 1.125rem;
  --ui-control-weight: 620;
  --ui-card-pad: 1.25rem;
  --ui-card-shadow: 0 1px 2px hsl(255 40% 20% / 0.06), 0 12px 32px -12px hsl(255 80% 45% / 0.28);
  --ui-card-border: var(--ui-border);
  --ui-input-shadow: none;
  --ui-ring: 0 0 0 3px color-mix(in srgb, var(--ui-ring-color) 45%, transparent);
  --ui-badge-tint: 16%;
  --ui-badge-border: transparent;
  --ui-alert-tint: 10%;
  --ui-cell-py: 0.625rem;
  --ui-cell-px: 0.75rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(240 20% 98.5%);
  --ui-bg-card: hsl(0 0% 100%);
  --ui-bg-subtle: hsl(240 22% 97%);
  --ui-bg-muted: hsl(240 8% 95%);
  --ui-bg-hover: hsl(240 8% 95%);
  --ui-border: hsl(240 8% 90%);
  --ui-border-strong: hsl(240 8% 84%);
  --ui-border-control: hsl(240 6% 55%);
  --ui-text: hsl(240 14% 12%);
  --ui-text-muted: hsl(240 6% 42.5%);
  --ui-accent: hsl(255 82% 58.5%);
  --ui-accent-hover: hsl(255 82% 54%);
  --ui-accent-fg: hsl(0 0% 100%);
  --ui-accent-muted: hsl(255 70% 96%);
  --ui-ring-color: hsl(255 82% 60%);
  --ui-success: hsl(145 55% 29%);
  --ui-warning: hsl(32 90% 31%);
  --ui-danger: hsl(0 72% 43.5%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-bg-hover: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-fg: hsl(0 0% 100%);
  --ui-btn-shadow: 0 4px 14px hsl(255 90% 55% / .35), inset 0 1px 0 hsl(0 0% 100% / .2);
  --ui-btn-hover-filter: brightness(1.07);
}
[data-theme="tailwind"] {
  --ui-font-sans: "InterVariable", Inter, ui-sans-serif, system-ui, sans-serif;
  --ui-font-head: "InterVariable", Inter, ui-sans-serif, system-ui, sans-serif;
  --ui-text-xs: 0.75rem;
  --ui-text-sm: 0.875rem;
  --ui-text-base: 0.875rem;
  --ui-text-lg: 1rem;
  --ui-text-xl: 1.875rem;
  --ui-leading: 1.5;
  --ui-heading-weight: 700;
  --ui-heading-tracking: -0.025em;
  --ui-eyebrow-font: var(--ui-font-sans);
  --ui-eyebrow-size: var(--ui-text-sm);
  --ui-eyebrow-weight: 600;
  --ui-eyebrow-tracking: 0;
  --ui-eyebrow-case: none;
  --ui-eyebrow-style: normal;
  --ui-eyebrow-color: var(--ui-text);
  --ui-radius-sm: 0.25rem;
  --ui-radius-md: 0.375rem;
  --ui-radius-lg: 0.5rem;
  --ui-btn-radius: var(--ui-radius-md);
  --ui-badge-radius: var(--ui-radius-md);
  --ui-card-radius: var(--ui-radius-lg);
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2.25rem;
  --ui-control-h-sm: 2rem;
  --ui-control-h-lg: 2.75rem;
  --ui-control-px: 0.875rem;
  --ui-control-weight: 600;
  --ui-card-pad: 1.5rem;
  --ui-card-shadow: 0 1px 3px 0 hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
  --ui-card-border: color-mix(in srgb, var(--ui-text) 6%, transparent);
  --ui-input-shadow: 0 1px 2px 0 hsl(0 0% 0% / 0.05);
  --ui-ring: 0 0 0 2px var(--ui-ring-color);
  --ui-badge-tint: 10%;
  --ui-badge-border: color-mix(in srgb, currentColor 22%, transparent);
  --ui-alert-tint: 8%;
  --ui-cell-py: 0.875rem;
  --ui-cell-px: 0.75rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(210 20% 98%);
  --ui-bg-card: hsl(0 0% 100%);
  --ui-bg-subtle: hsl(220 14% 96%);
  --ui-bg-muted: hsl(220 14% 96%);
  --ui-bg-hover: hsl(226 71% 96%);
  --ui-border: hsl(220 13% 91%);
  --ui-border-strong: hsl(216 12% 84%);
  --ui-border-control: hsl(216 10% 55%);
  --ui-text: hsl(221 39% 11%);
  --ui-text-muted: hsl(220 9% 44%);
  --ui-accent: hsl(243 75% 59%);
  --ui-accent-hover: hsl(244 65% 52%);
  --ui-accent-fg: hsl(0 0% 100%);
  --ui-accent-muted: hsl(226 71% 96%);
  --ui-ring-color: hsl(243 75% 59%);
  --ui-success: hsl(145 55% 29%);
  --ui-warning: hsl(32 90% 32.5%);
  --ui-danger: hsl(0 72% 46%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="shadcn"] {
  --ui-font-sans: "Geist", Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-font-head: "Geist", Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ui-text-xs: 0.75rem;
  --ui-text-sm: 0.875rem;
  --ui-text-base: 0.875rem;
  --ui-text-lg: 1rem;
  --ui-text-xl: 1.875rem;
  --ui-leading: 1.5;
  --ui-heading-weight: 600;
  --ui-heading-tracking: -0.025em;
  --ui-eyebrow-font: var(--ui-font-sans);
  --ui-eyebrow-size: var(--ui-text-sm);
  --ui-eyebrow-weight: 400;
  --ui-eyebrow-tracking: 0;
  --ui-eyebrow-case: none;
  --ui-eyebrow-style: normal;
  --ui-eyebrow-color: var(--ui-text-muted);
  --ui-radius-sm: 0.375rem;
  --ui-radius-md: 0.5rem;
  --ui-radius-lg: 0.625rem;
  --ui-btn-radius: var(--ui-radius-md);
  --ui-badge-radius: var(--ui-radius-md);
  --ui-card-radius: 0.875rem;
  --ui-input-radius: var(--ui-radius-md);
  --ui-control-h: 2.25rem;
  --ui-control-h-sm: 2rem;
  --ui-control-h-lg: 2.5rem;
  --ui-control-px: 1rem;
  --ui-control-weight: 500;
  --ui-card-pad: 1.5rem;
  --ui-card-shadow: 0 1px 3px 0 hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
  --ui-card-border: var(--ui-border);
  --ui-input-shadow: 0 1px 2px 0 hsl(0 0% 0% / 0.05);
  --ui-ring: 0 0 0 3px color-mix(in srgb, var(--ui-ring-color) 50%, transparent);
  --ui-badge-tint: 0%;
  --ui-badge-border: var(--ui-border);
  --ui-alert-tint: 0%;
  --ui-cell-py: 0.5rem;
  --ui-cell-px: 0.5rem;
  --ui-space-xs: calc(var(--ui-card-pad) * 0.25);
  --ui-space-sm: calc(var(--ui-card-pad) * 0.5);
  --ui-space-md: calc(var(--ui-card-pad) * 0.75);
  --ui-space-lg: var(--ui-card-pad);
  --ui-bg: hsl(0 0% 100%);
  --ui-bg-card: hsl(0 0% 100%);
  --ui-bg-subtle: hsl(0 0% 98%);
  --ui-bg-muted: hsl(0 0% 96.1%);
  --ui-bg-hover: hsl(0 0% 96.1%);
  --ui-border: hsl(0 0% 89.8%);
  --ui-border-strong: hsl(0 0% 83%);
  --ui-border-control: hsl(0 0% 56%);
  --ui-text: hsl(0 0% 3.9%);
  --ui-text-muted: hsl(0 0% 44.1%);
  --ui-accent: hsl(0 0% 9%);
  --ui-accent-hover: hsl(0 0% 20%);
  --ui-accent-fg: hsl(0 0% 98.5%);
  --ui-accent-muted: hsl(0 0% 96.1%);
  --ui-ring-color: hsl(0 0% 45.1%);
  --ui-success: hsl(145 55% 29%);
  --ui-warning: hsl(32 90% 32.5%);
  --ui-danger: hsl(357 100% 45%);
  --ui-danger-fg: hsl(0 0% 100%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}

:root[data-mode="dark"], [data-theme="default"][data-mode="dark"] {
  --ui-bg: hsl(240 10% 3.9%);
  --ui-bg-card: hsl(240 10% 6.5%);
  --ui-bg-subtle: hsl(240 10% 8.5%);
  --ui-bg-muted: hsl(240 3.7% 15.9%);
  --ui-bg-hover: hsl(240 3.7% 15.9%);
  --ui-border: hsl(240 4% 18%);
  --ui-border-strong: hsl(240 4% 26%);
  --ui-border-control: hsl(240 4% 45%);
  --ui-text: hsl(0 0% 98%);
  --ui-text-muted: hsl(240 5% 65%);
  --ui-accent: hsl(234 89% 74%);
  --ui-accent-hover: hsl(234 89% 80%);
  --ui-accent-fg: hsl(240 10% 8%);
  --ui-accent-muted: hsl(234 40% 22%);
  --ui-ring-color: hsl(234 89% 74%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 62.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="journal"][data-mode="dark"] {
  --ui-bg: hsl(28 14% 10%);
  --ui-bg-card: hsl(28 13% 13%);
  --ui-bg-subtle: hsl(28 12% 16.5%);
  --ui-bg-muted: hsl(28 10% 17%);
  --ui-bg-hover: hsl(28 10% 18%);
  --ui-border: hsl(30 9% 23%);
  --ui-border-strong: hsl(30 9% 32%);
  --ui-border-control: hsl(30 8% 45%);
  --ui-text: hsl(38 22% 89%);
  --ui-text-muted: hsl(34 10% 63%);
  --ui-accent: hsl(8 72% 65%);
  --ui-accent-hover: hsl(8 72% 71%);
  --ui-accent-fg: hsl(12 30% 11%);
  --ui-accent-muted: hsl(8 45% 21%);
  --ui-ring-color: hsl(8 72% 65%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 68%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: hsl(38 32% 90%);
  --ui-btn-bg-hover: hsl(38 32% 90%);
  --ui-btn-fg: hsl(28 24% 12%);
  --ui-btn-shadow: var(--ui-shadow-sm);
  --ui-btn-hover-filter: brightness(1.08);
}
[data-theme="studio"][data-mode="dark"] {
  --ui-bg: hsl(240 16% 6%);
  --ui-bg-card: hsl(246 17% 11%);
  --ui-bg-subtle: hsl(250 16% 14%);
  --ui-bg-muted: hsl(250 15% 15%);
  --ui-bg-hover: hsl(248 14% 19%);
  --ui-border: hsl(250 14% 17%);
  --ui-border-strong: hsl(248 12% 27%);
  --ui-border-control: hsl(248 10% 45%);
  --ui-text: hsl(250 14% 91%);
  --ui-text-muted: hsl(247 8% 60%);
  --ui-accent: hsl(330 82% 66%);
  --ui-accent-hover: hsl(330 88% 73%);
  --ui-accent-fg: hsl(335 30% 11%);
  --ui-accent-muted: hsl(328 38% 20%);
  --ui-ring-color: hsl(330 82% 66%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 64%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="console"][data-mode="dark"] {
  --ui-bg: hsl(240 14% 8%);
  --ui-bg-card: hsl(240 12% 11%);
  --ui-bg-subtle: hsl(240 12% 13.5%);
  --ui-bg-muted: hsl(240 10% 16%);
  --ui-bg-hover: hsl(240 10% 16%);
  --ui-border: hsl(240 10% 20%);
  --ui-border-strong: hsl(240 10% 28%);
  --ui-border-control: hsl(240 8% 45%);
  --ui-text: hsl(240 20% 96%);
  --ui-text-muted: hsl(240 8% 62%);
  --ui-accent: hsl(255 90% 74%);
  --ui-accent-hover: hsl(255 90% 80%);
  --ui-accent-fg: hsl(255 30% 11%);
  --ui-accent-muted: hsl(255 55% 22%);
  --ui-ring-color: hsl(255 90% 74%);
  --ui-success: hsl(145 60% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 78% 66.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-bg-hover: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-fg: hsl(0 0% 100%);
  --ui-btn-shadow: 0 4px 14px hsl(255 90% 55% / .35), inset 0 1px 0 hsl(0 0% 100% / .2);
  --ui-btn-hover-filter: brightness(1.07);
}
[data-theme="tailwind"][data-mode="dark"] {
  --ui-bg: hsl(222 47% 8%);
  --ui-bg-card: hsl(222 39% 11%);
  --ui-bg-subtle: hsl(222 33% 14%);
  --ui-bg-muted: hsl(222 30% 16%);
  --ui-bg-hover: hsl(226 40% 20%);
  --ui-border: hsl(222 24% 20%);
  --ui-border-strong: hsl(222 20% 28%);
  --ui-border-control: hsl(222 15% 45%);
  --ui-text: hsl(210 40% 96%);
  --ui-text-muted: hsl(215 16% 65%);
  --ui-accent: hsl(234 89% 74%);
  --ui-accent-hover: hsl(234 89% 80%);
  --ui-accent-fg: hsl(240 10% 8%);
  --ui-accent-muted: hsl(234 40% 22%);
  --ui-ring-color: hsl(234 89% 74%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 62.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="shadcn"][data-mode="dark"] {
  --ui-bg: hsl(0 0% 3.9%);
  --ui-bg-card: hsl(0 0% 9%);
  --ui-bg-subtle: hsl(0 0% 7%);
  --ui-bg-muted: hsl(0 0% 14.9%);
  --ui-bg-hover: hsl(0 0% 14.9%);
  --ui-border: hsl(0 0% 13.7%);
  --ui-border-strong: hsl(0 0% 20%);
  --ui-border-control: hsl(0 0% 42%);
  --ui-text: hsl(0 0% 98.5%);
  --ui-text-muted: hsl(0 0% 63.1%);
  --ui-accent: hsl(0 0% 89.8%);
  --ui-accent-hover: hsl(0 0% 98%);
  --ui-accent-fg: hsl(0 0% 9%);
  --ui-accent-muted: hsl(0 0% 14.9%);
  --ui-ring-color: hsl(0 0% 45.1%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(359 100% 70%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}

@media (prefers-color-scheme: dark) {
:root[data-mode="system"], [data-theme="default"][data-mode="system"] {
  --ui-bg: hsl(240 10% 3.9%);
  --ui-bg-card: hsl(240 10% 6.5%);
  --ui-bg-subtle: hsl(240 10% 8.5%);
  --ui-bg-muted: hsl(240 3.7% 15.9%);
  --ui-bg-hover: hsl(240 3.7% 15.9%);
  --ui-border: hsl(240 4% 18%);
  --ui-border-strong: hsl(240 4% 26%);
  --ui-border-control: hsl(240 4% 45%);
  --ui-text: hsl(0 0% 98%);
  --ui-text-muted: hsl(240 5% 65%);
  --ui-accent: hsl(234 89% 74%);
  --ui-accent-hover: hsl(234 89% 80%);
  --ui-accent-fg: hsl(240 10% 8%);
  --ui-accent-muted: hsl(234 40% 22%);
  --ui-ring-color: hsl(234 89% 74%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 62.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="journal"][data-mode="system"] {
  --ui-bg: hsl(28 14% 10%);
  --ui-bg-card: hsl(28 13% 13%);
  --ui-bg-subtle: hsl(28 12% 16.5%);
  --ui-bg-muted: hsl(28 10% 17%);
  --ui-bg-hover: hsl(28 10% 18%);
  --ui-border: hsl(30 9% 23%);
  --ui-border-strong: hsl(30 9% 32%);
  --ui-border-control: hsl(30 8% 45%);
  --ui-text: hsl(38 22% 89%);
  --ui-text-muted: hsl(34 10% 63%);
  --ui-accent: hsl(8 72% 65%);
  --ui-accent-hover: hsl(8 72% 71%);
  --ui-accent-fg: hsl(12 30% 11%);
  --ui-accent-muted: hsl(8 45% 21%);
  --ui-ring-color: hsl(8 72% 65%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 68%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: hsl(38 32% 90%);
  --ui-btn-bg-hover: hsl(38 32% 90%);
  --ui-btn-fg: hsl(28 24% 12%);
  --ui-btn-shadow: var(--ui-shadow-sm);
  --ui-btn-hover-filter: brightness(1.08);
}
[data-theme="studio"][data-mode="system"] {
  --ui-bg: hsl(240 16% 6%);
  --ui-bg-card: hsl(246 17% 11%);
  --ui-bg-subtle: hsl(250 16% 14%);
  --ui-bg-muted: hsl(250 15% 15%);
  --ui-bg-hover: hsl(248 14% 19%);
  --ui-border: hsl(250 14% 17%);
  --ui-border-strong: hsl(248 12% 27%);
  --ui-border-control: hsl(248 10% 45%);
  --ui-text: hsl(250 14% 91%);
  --ui-text-muted: hsl(247 8% 60%);
  --ui-accent: hsl(330 82% 66%);
  --ui-accent-hover: hsl(330 88% 73%);
  --ui-accent-fg: hsl(335 30% 11%);
  --ui-accent-muted: hsl(328 38% 20%);
  --ui-ring-color: hsl(330 82% 66%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 64%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="console"][data-mode="system"] {
  --ui-bg: hsl(240 14% 8%);
  --ui-bg-card: hsl(240 12% 11%);
  --ui-bg-subtle: hsl(240 12% 13.5%);
  --ui-bg-muted: hsl(240 10% 16%);
  --ui-bg-hover: hsl(240 10% 16%);
  --ui-border: hsl(240 10% 20%);
  --ui-border-strong: hsl(240 10% 28%);
  --ui-border-control: hsl(240 8% 45%);
  --ui-text: hsl(240 20% 96%);
  --ui-text-muted: hsl(240 8% 62%);
  --ui-accent: hsl(255 90% 74%);
  --ui-accent-hover: hsl(255 90% 80%);
  --ui-accent-fg: hsl(255 30% 11%);
  --ui-accent-muted: hsl(255 55% 22%);
  --ui-ring-color: hsl(255 90% 74%);
  --ui-success: hsl(145 60% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 78% 66.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-bg-hover: linear-gradient(135deg, hsl(258 90% 62%), hsl(240 90% 58%));
  --ui-btn-fg: hsl(0 0% 100%);
  --ui-btn-shadow: 0 4px 14px hsl(255 90% 55% / .35), inset 0 1px 0 hsl(0 0% 100% / .2);
  --ui-btn-hover-filter: brightness(1.07);
}
[data-theme="tailwind"][data-mode="system"] {
  --ui-bg: hsl(222 47% 8%);
  --ui-bg-card: hsl(222 39% 11%);
  --ui-bg-subtle: hsl(222 33% 14%);
  --ui-bg-muted: hsl(222 30% 16%);
  --ui-bg-hover: hsl(226 40% 20%);
  --ui-border: hsl(222 24% 20%);
  --ui-border-strong: hsl(222 20% 28%);
  --ui-border-control: hsl(222 15% 45%);
  --ui-text: hsl(210 40% 96%);
  --ui-text-muted: hsl(215 16% 65%);
  --ui-accent: hsl(234 89% 74%);
  --ui-accent-hover: hsl(234 89% 80%);
  --ui-accent-fg: hsl(240 10% 8%);
  --ui-accent-muted: hsl(234 40% 22%);
  --ui-ring-color: hsl(234 89% 74%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(0 72% 62.5%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
[data-theme="shadcn"][data-mode="system"] {
  --ui-bg: hsl(0 0% 3.9%);
  --ui-bg-card: hsl(0 0% 9%);
  --ui-bg-subtle: hsl(0 0% 7%);
  --ui-bg-muted: hsl(0 0% 14.9%);
  --ui-bg-hover: hsl(0 0% 14.9%);
  --ui-border: hsl(0 0% 13.7%);
  --ui-border-strong: hsl(0 0% 20%);
  --ui-border-control: hsl(0 0% 42%);
  --ui-text: hsl(0 0% 98.5%);
  --ui-text-muted: hsl(0 0% 63.1%);
  --ui-accent: hsl(0 0% 89.8%);
  --ui-accent-hover: hsl(0 0% 98%);
  --ui-accent-fg: hsl(0 0% 9%);
  --ui-accent-muted: hsl(0 0% 14.9%);
  --ui-ring-color: hsl(0 0% 45.1%);
  --ui-success: hsl(145 55% 58%);
  --ui-warning: hsl(38 92% 62%);
  --ui-danger: hsl(359 100% 70%);
  --ui-danger-fg: hsl(0 30% 10%);
  --ui-btn-bg: var(--ui-accent);
  --ui-btn-bg-hover: var(--ui-accent-hover);
  --ui-btn-fg: var(--ui-accent-fg);
  --ui-btn-shadow: none;
  --ui-btn-hover-filter: none;
}
}

/* Tokens no theme changes, and the few page-level rules the components lean
   on. Colours and every style token a theme can change are generated per
   theme and mode (src/theme.rs) and must not be set here: this file comes
   after them, with the same specificity, and would win. A test holds that. */

:root {
  --ui-radius-full: 999px;
  --ui-space-xl: 1.5rem;
  --ui-space-xxl: 2rem;
  --ui-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --ui-shadow-sm: 0 1px 2px hsl(240 8% 12% / 0.05);
  --ui-shadow-md: 0 4px 12px hsl(240 8% 12% / 0.08), 0 1px 3px hsl(240 8% 12% / 0.05);

  --ui-transition: 140ms cubic-bezier(0.4, 0, 0.2, 1);
  /* WCAG 2.5.5: 44px for anything a thumb has to hit. */
  --ui-touch: 2.75rem;
}

[data-mode="dark"] {
  --ui-shadow-sm: 0 1px 2px hsl(0 0% 0% / 0.5);
  --ui-shadow-md: 0 2px 6px hsl(0 0% 0% / 0.55), 0 8px 24px hsl(0 0% 0% / 0.35);
}
@media (prefers-color-scheme: dark) {
  [data-mode="system"] {
    --ui-shadow-sm: 0 1px 2px hsl(0 0% 0% / 0.5);
    --ui-shadow-md: 0 2px 6px hsl(0 0% 0% / 0.55), 0 8px 24px hsl(0 0% 0% / 0.35);
  }
}

[data-mode="light"] { color-scheme: light; }
[data-mode="dark"] { color-scheme: dark; }
[data-mode="system"] { color-scheme: light dark; }

/* Sizes include padding and border, everywhere in a library page: a tile
   with padding must fit the column it is given. metrics' tiles spilled out
   of their grid without it; journal had set it itself. */
.ui-page, .ui-page *, .ui-page *::before, .ui-page *::after { box-sizing: border-box; }

/* Opt-in: an app that has not migrated keeps its own body styles. */
.ui-page {
  margin: 0;
  background: var(--ui-bg);
  color: var(--ui-text);
  font-family: var(--ui-font-sans);
  font-size: var(--ui-text-base);
  line-height: var(--ui-leading);
  -webkit-font-smoothing: antialiased;
}

/* The small label over a figure, a table header, a group heading: one
   recipe, set per theme (uppercase in default, italic serif in journal,
   plain muted text in shadcn). */
.ui-eyebrow,
.ui-stat__label,
.ui-chart__label,
.ui-table th,
.ui-drawer__heading,
.ui-tabs__fallback-title {
  font-family: var(--ui-eyebrow-font);
  font-size: var(--ui-eyebrow-size);
  font-weight: var(--ui-eyebrow-weight);
  font-style: var(--ui-eyebrow-style);
  letter-spacing: var(--ui-eyebrow-tracking);
  text-transform: var(--ui-eyebrow-case);
  color: var(--ui-eyebrow-color);
}

/* Every component sets its own `display`, which would beat the browser's
   `[hidden] { display: none }`; a component rendered hidden stays hidden. */
[class^="ui-"][hidden], [class*=" ui-"][hidden] { display: none !important; }

.ui-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  [class^="ui-"], [class*=" ui-"] {
    transition: none !important;
    animation: none !important;
  }
}

/* Focus in forced colours (Windows high contrast). The components draw
   their focus ring as a box-shadow with the outline removed, and forced
   colours drops box-shadows, so without this a keyboard user there sees no
   focus at all (WCAG 2.4.7). The system's text colour is the one colour
   guaranteed to show against the system's background. */
@media (forced-colors: active) {
  :focus-visible { outline: 2px solid CanvasText !important; outline-offset: 2px; }
}

/* A fixed element at the bottom (the floating action button, toasts) must
   not hide the control that has focus (WCAG 2.4.11): scrolling to a focused
   element stops this far short of the edge. A sticky bar takes the same
   room at the top. */
html { scroll-padding-bottom: calc(var(--ui-touch) + 1.5rem); }
html:has(.ui-topbar--sticky) { scroll-padding-top: calc(var(--ui-control-h) + 1.5rem); }

.ui-container { width: 100%; margin-inline: auto; }
.ui-container--prose { max-width: 46rem; }
.ui-container--form { max-width: 42rem; }
.ui-container--wide { max-width: 76rem; }
.ui-container--full { max-width: none; }
/* Fields: as many columns as fit, each at least a comfortable form width. */
.ui-container--fields { max-width: 76rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(22rem, 100%), 1fr)); gap: var(--ui-card-pad); align-items: start; }

.ui-grid { --ui-grid-gap: calc(var(--ui-card-pad) * 0.75); }
.ui-grid--gap-sm { --ui-grid-gap: calc(var(--ui-card-pad) * 0.35); }
.ui-grid--gap-lg { --ui-grid-gap: var(--ui-card-pad); }

/* Bricks: columns of at least the minimum, each filled to the bottom before
   the next, so short panels follow one another with no holes. */
.ui-grid--bricks { columns: var(--ui-grid-min); column-gap: var(--ui-grid-gap); }
.ui-grid--bricks > .ui-grid__item { break-inside: avoid; margin-bottom: var(--ui-grid-gap); }
.ui-grid--bricks > .ui-grid__item > * { width: 100%; }

.ui-grid--fill { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(var(--ui-grid-min), 100%), 1fr)); gap: var(--ui-grid-gap); align-items: start; }

.ui-grid--split { display: grid; gap: var(--ui-grid-gap); align-items: start; }
@media (min-width: 1280px) { .ui-grid--split { grid-template-columns: var(--ui-grid-split); } }

.ui-grid__item { min-width: 0; }
.ui-grid__item > .ui-stat, .ui-grid__item > .ui-card { height: 100%; }
.ui-grid--bricks .ui-grid__item > .ui-stat, .ui-grid--bricks .ui-grid__item > .ui-card { height: auto; }

/* Stack: blocks in a column, the space between them the stack's own. A
   child's margins are dropped, so a paragraph's default margin does not add
   to the gap. */
.ui-stack { display: flex; flex-direction: column; gap: calc(var(--ui-card-pad) * 0.75); min-width: 0; }
.ui-stack--gap-sm { gap: calc(var(--ui-card-pad) * 0.35); }
.ui-stack--gap-lg { gap: var(--ui-card-pad); }
.ui-stack > * { margin-block: 0; min-width: 0; }

/* Layouts: the skip link, the content area, and the centred card page. */

.ui-skip {
  position: absolute;
  z-index: 100;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.5rem 0.875rem;
  font-weight: var(--ui-control-weight);
  color: var(--ui-accent-fg);
  background: var(--ui-accent);
  border-radius: var(--ui-radius-md);
  transform: translateY(-200%);
}
.ui-skip:focus { transform: none; outline: none; box-shadow: var(--ui-ring); }

.ui-main { display: block; padding: 1.5rem 1rem 5rem; }
.ui-main:focus { outline: none; }
/* The same for a docs page's content, the skip link's target there. */
.ui-docs__content:focus { outline: none; }
@media (min-width: 641px) { .ui-main { padding: 2rem 1.5rem 4rem; } }

.ui-main--centered { min-height: 100dvh; display: grid; place-items: center; padding-bottom: 1.5rem; }
.ui-centered { width: min(100%, 24rem); margin-inline: auto; display: grid; gap: 1rem; justify-items: center; }
.ui-centered__brand { font-family: var(--ui-font-head); font-size: var(--ui-text-lg); }
.ui-centered__card {
  width: 100%;
  padding: calc(var(--ui-card-pad) * 1.25);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
}
.ui-centered__card > .ui-heading { margin-bottom: 1rem; }
.ui-centered__footer { font-size: var(--ui-text-sm); color: var(--ui-text-muted); text-align: center; }

.ui-heading { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0.5rem 1rem; }
.ui-heading--h1 { margin: 0 0 1.25rem; }
.ui-heading--h2 { margin: 2rem 0 0.75rem; }
.ui-heading--h3 { margin: 1.25rem 0 0.5rem; }
.ui-heading__text { min-width: 0; }
.ui-heading__title {
  margin: 0;
  font-family: var(--ui-font-head);
  font-weight: var(--ui-heading-weight);
  letter-spacing: var(--ui-heading-tracking);
  line-height: 1.15;
  color: var(--ui-text);
  text-wrap: balance;
}
.ui-heading__title--h1 { font-size: clamp(calc(var(--ui-text-xl) * 0.9), 1rem + 2.2vw, calc(var(--ui-text-xl) * 1.3)); }
.ui-heading__title--h2 { font-size: var(--ui-text-lg); }
.ui-heading__title--h3 { font-size: var(--ui-text-base); }
/* An eyebrow heading: the label recipe from base.css, restated because
   .ui-heading__title above comes later and would win. */
.ui-heading__title.ui-eyebrow {
  font-family: var(--ui-eyebrow-font);
  font-size: var(--ui-eyebrow-size);
  font-weight: var(--ui-eyebrow-weight);
  font-style: var(--ui-eyebrow-style);
  letter-spacing: var(--ui-eyebrow-tracking);
  text-transform: var(--ui-eyebrow-case);
  color: var(--ui-eyebrow-color);
  line-height: 1.4;
}
.ui-heading__lead { margin: 0.375rem 0 0; font-size: var(--ui-text-base); color: var(--ui-text-muted); }
.ui-heading__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.ui-topbar {
  display: flex;
  align-items: center;
  gap: 0.25rem 1rem;
  min-height: calc(var(--ui-control-h) + 1rem);
  padding: 0.375rem 1rem;
  padding-top: max(0.375rem, env(safe-area-inset-top));
  background: color-mix(in srgb, var(--ui-bg) 88%, transparent);
  border-bottom: 1px solid var(--ui-border);
}
.ui-topbar--sticky { position: sticky; top: 0; z-index: 30; backdrop-filter: blur(10px); }

.ui-topbar__brand { display: inline-flex; align-items: center; gap: 0.5rem; flex-shrink: 0; color: var(--ui-text); text-decoration: none; border-radius: var(--ui-radius-md); }
.ui-topbar__brand:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-topbar__mark { display: inline-grid; place-items: center; font-size: 1.25rem; color: var(--ui-accent); }
.ui-topbar__name { font-family: var(--ui-font-head); font-weight: var(--ui-heading-weight); letter-spacing: var(--ui-heading-tracking); font-size: var(--ui-text-base); }

.ui-topbar__sections, .ui-topbar__secondary { display: flex; align-items: center; gap: 0.125rem; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.ui-topbar__secondary { padding-left: 0.75rem; border-left: 1px solid var(--ui-border); }
.ui-topbar__link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  min-height: var(--ui-control-h);
  padding: 0 calc(var(--ui-control-px) * 0.7);
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  white-space: nowrap;
  color: var(--ui-text-muted);
  text-decoration: none;
  border-radius: var(--ui-radius-md);
}
.ui-topbar__link .ui-icon { font-size: 1.125em; }
.ui-topbar__link:hover { color: var(--ui-text); background: var(--ui-bg-hover); }
.ui-topbar__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
/* The current page in full, the section it is under at half: neither by
   colour alone, since aria-current says which is which. */
.ui-topbar__link[aria-current="page"] { color: var(--ui-text); background: var(--ui-bg-muted); }
.ui-topbar__link[aria-current="true"] { color: var(--ui-text); background: color-mix(in srgb, var(--ui-bg-muted) 50%, transparent); }

.ui-topbar__current { display: none; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--ui-heading-weight); }
.ui-topbar__aside { display: none; flex-shrink: 0; font-size: var(--ui-text-sm); color: var(--ui-text-muted); }
.ui-topbar__end { display: flex; align-items: center; gap: 0.375rem; flex-shrink: 0; margin-left: auto; }

@media (min-width: 1280px) {
  .ui-topbar__aside { display: block; margin-left: auto; }
  .ui-topbar__aside + .ui-topbar__end { margin-left: 0; }
}
@media (max-width: 640px), (max-height: 520px) {
  .ui-topbar { padding-inline: 0.75rem; gap: 0.25rem 0.5rem; }
  /* The mark alone stands for the name; the name stays for screen readers. */
  .ui-topbar__mark + .ui-topbar__name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .ui-topbar__secondary { display: none; }
  .ui-topbar--narrow-icons .ui-topbar__link:has(.ui-icon) .ui-topbar__label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0);
  }
  .ui-topbar--narrow-icons .ui-topbar__link:has(.ui-icon) { padding: 0; width: var(--ui-control-h); justify-content: center; }
  .ui-topbar--narrow-title .ui-topbar__sections { display: none; }
  .ui-topbar--narrow-title .ui-topbar__current { display: block; }
}
/* The same phone shape from 1100px down, for a bar that folds at tablet
   width. Written out again because a media query cannot read a class. */
@media (max-width: 1100px) {
  .ui-topbar--fold-tablet { padding-inline: 0.75rem; gap: 0.25rem 0.5rem; }
  .ui-topbar--fold-tablet .ui-topbar__secondary { display: none; }
  .ui-topbar--fold-tablet.ui-topbar--narrow-icons .ui-topbar__link:has(.ui-icon) .ui-topbar__label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0);
  }
  .ui-topbar--fold-tablet.ui-topbar--narrow-icons .ui-topbar__link:has(.ui-icon) { padding: 0; width: var(--ui-control-h); justify-content: center; }
  .ui-topbar--fold-tablet.ui-topbar--narrow-title .ui-topbar__sections { display: none; }
  .ui-topbar--fold-tablet.ui-topbar--narrow-title .ui-topbar__current { display: block; }
}

/* Icon: 1em square, so it takes the size of its text; nudged onto the
   text's centre line. */
.ui-icon { flex-shrink: 0; vertical-align: -0.125em; }

/* Button. Size, weight and corners come from the theme; the primary
   variant also reads --ui-btn-* so a theme can dress it (journal's ink pill,
   console's gradient). */

.ui-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  height: var(--ui-control-h);
  padding: 0 var(--ui-control-px);
  font: inherit;
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--ui-btn-radius);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--ui-transition), border-color var(--ui-transition),
    color var(--ui-transition), filter var(--ui-transition), box-shadow var(--ui-transition);
}
.ui-btn:focus-visible {
  outline: none;
  box-shadow: var(--ui-ring);
}
.ui-btn:disabled,
.ui-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.ui-btn--sm { height: var(--ui-control-h-sm); padding: 0 calc(var(--ui-control-px) * 0.75); font-size: var(--ui-text-xs); }
.ui-btn--md { height: var(--ui-control-h); }
.ui-btn--lg { height: var(--ui-control-h-lg); padding: 0 calc(var(--ui-control-px) * 1.25); font-size: var(--ui-text-base); }

.ui-btn--icon-only { padding: 0; aspect-ratio: 1; }
.ui-btn--icon-only .ui-btn__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }

@media (max-width: 640px) {
  .ui-btn--collapse { padding: 0; aspect-ratio: 1; }
  .ui-btn--collapse:has(.ui-btn__icon) .ui-btn__label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0);
  }
}

.ui-btn__icon { display: inline-flex; flex-shrink: 0; }
.ui-btn__icon svg { width: 1.1em; height: 1.1em; }

.ui-btn--primary {
  background: var(--ui-btn-bg);
  color: var(--ui-btn-fg);
  box-shadow: var(--ui-btn-shadow);
}
.ui-btn--primary:hover {
  background: var(--ui-btn-bg-hover);
  filter: var(--ui-btn-hover-filter);
}

.ui-btn--secondary {
  background: var(--ui-bg-card);
  color: var(--ui-text);
  border-color: var(--ui-border-control);
  box-shadow: var(--ui-input-shadow);
}
.ui-btn--secondary:hover { background: var(--ui-bg-hover); }

.ui-btn--ghost {
  background: transparent;
  color: var(--ui-text);
}
.ui-btn--ghost:hover { background: var(--ui-bg-hover); }

.ui-btn--danger {
  background: var(--ui-danger);
  color: var(--ui-danger-fg);
}
.ui-btn--danger:hover { filter: brightness(0.92); }

/* Busy: a spinner takes the icon's place (or leads the label when there is
   no icon), and the button stops taking presses. */
.ui-btn--busy { pointer-events: none; }
.ui-btn--busy .ui-btn__icon { visibility: hidden; position: relative; }
.ui-btn--busy .ui-btn__icon::after,
.ui-btn--busy:not(:has(.ui-btn__icon))::before {
  content: "";
  visibility: visible;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ui-spin 0.7s linear infinite;
}
.ui-btn--busy .ui-btn__icon::after { position: absolute; inset: 0; margin: auto; }
@keyframes ui-spin { to { transform: rotate(360deg); } }

/* A toggle that is on: pressed in, and in the accent, so it reads as on
   without the colour alone (aria-pressed says it too). */
.ui-btn[aria-pressed="true"]:not(.ui-btn--primary) {
  color: var(--ui-accent);
  background: var(--ui-accent-muted);
  border-color: color-mix(in srgb, var(--ui-accent) 40%, var(--ui-border-control));
}

/* Spinner: the busy button's ring (button.css), on its own. Its colour is
   the text around it, so it follows any theme and tone. */
.ui-spinner { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--ui-text-muted); font-size: var(--ui-text-sm); }
.ui-spinner__ring {
  flex: none;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ui-spin 0.7s linear infinite;
}
.ui-spinner--sm { font-size: var(--ui-text-xs); }
.ui-spinner--lg .ui-spinner__ring { width: 2rem; height: 2rem; border-width: 3px; }
/* Reduced motion: base.css stops every animation, which would leave a
   still ring that looks finished. A slow fade instead (no movement), so
   the wait still shows. */
@media (prefers-reduced-motion: reduce) {
  .ui-spinner .ui-spinner__ring { animation: ui-spinner-pulse 2s ease-in-out infinite !important; border-right-color: currentColor; }
}
@keyframes ui-spinner-pulse { 50% { opacity: 0.35; } }

/* Copy button: the library button; its two icons swap with its state. */
.ui-copy__idle, .ui-copy__done { display: inline-flex; }
.ui-copy[data-state="copied"] .ui-copy__idle,
.ui-copy:not([data-state="copied"]) .ui-copy__done { display: none; }
.ui-copy[data-state="copied"] { color: var(--ui-success); }

/* A form that is only a button: no box of its own, so it sits in a row
   of buttons as one of them. */
.ui-action-form { display: inline-flex; margin: 0; }

.ui-btn-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.ui-btn-group__end { display: inline-flex; flex-wrap: wrap; gap: 0.5rem; margin-left: auto; }
/* Attached: one strip, the inner corners squared and the borders shared. */
.ui-btn-group--attached { gap: 0; flex-wrap: nowrap; }
.ui-btn-group--attached > .ui-btn { border-radius: 0; }
.ui-btn-group--attached > .ui-btn + .ui-btn { margin-left: -1px; }
.ui-btn-group--attached > .ui-btn:first-child { border-radius: var(--ui-radius-md) 0 0 var(--ui-radius-md); }
.ui-btn-group--attached > .ui-btn:last-child { border-radius: 0 var(--ui-radius-md) var(--ui-radius-md) 0; }
.ui-btn-group--attached > .ui-btn:focus-visible { position: relative; z-index: 1; }

/* On a very narrow screen an attached group that cannot wrap would push the
   page sideways (WCAG 1.4.10, reflow at 320px). There it comes apart into
   separate buttons that wrap. */
@media (max-width: 24rem) {
  .ui-btn-group--attached { flex-wrap: wrap; gap: 0.375rem; }
  .ui-btn-group--attached > .ui-btn,
  .ui-btn-group--attached > .ui-btn:first-child,
  .ui-btn-group--attached > .ui-btn:last-child { border-radius: var(--ui-btn-radius); }
  .ui-btn-group--attached > .ui-btn + .ui-btn { margin-left: 0; }
}

/* Badge. The tone's colour is the text; the theme decides how much of it
   tints the ground (none in shadcn, which outlines instead), the border,
   and the corners (pills by default, rounded-md in shadcn and tailwind).
   The tint does lower the tone's contrast, by up to half a point: the
   palettes are measured on the badge's own ground over a card and over the
   page (`theme::checks_for`), so every tone clears 4.5:1 there. */

.ui-badge {
  --ui-badge-color: var(--ui-text-muted);
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.125rem 0.5rem;
  font-size: var(--ui-text-xs);
  font-weight: 560;
  line-height: 1.4;
  white-space: nowrap;
  color: var(--ui-badge-color);
  background: color-mix(in srgb, var(--ui-badge-color) var(--ui-badge-tint), transparent);
  border: 1px solid var(--ui-badge-border);
  border-radius: var(--ui-badge-radius);
}
.ui-badge--neutral { --ui-badge-color: var(--ui-text); background: var(--ui-bg-muted); }
.ui-badge--accent { --ui-badge-color: var(--ui-accent); }
.ui-badge--success { --ui-badge-color: var(--ui-success); }
.ui-badge--warning { --ui-badge-color: var(--ui-warning); }
.ui-badge--danger { --ui-badge-color: var(--ui-danger); }

.ui-badge__dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: currentColor;
}

/* A badge that does something: a link to the thing it names, or the submit
   button of a small form ("no MD — convert"). Same look, plus what a control
   needs: a pointer, a hover, and a focus ring a keyboard can see. */
a.ui-badge, button.ui-badge { text-decoration: none; cursor: pointer; font-family: inherit; }
button.ui-badge { appearance: none; margin: 0; }
a.ui-badge:hover, button.ui-badge:hover { border-color: var(--ui-badge-color); }
a.ui-badge:focus-visible, button.ui-badge:focus-visible { outline: none; box-shadow: var(--ui-ring); }

/* Forced colours paint backgrounds away: the dot keeps its shape in the
   text colour, and the word still says the state. */
@media (forced-colors: active) {
  .ui-badge__dot { background: CanvasText; forced-color-adjust: none; }
}

.ui-card {
  display: flex;
  flex-direction: column;
  gap: calc(var(--ui-card-pad) * 0.75);
  padding: var(--ui-card-pad) 0;
  background: var(--ui-bg-card);
  color: var(--ui-text);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
}

.ui-card--link {
  text-decoration: none;
  transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}
.ui-card--link:hover { border-color: var(--ui-border-strong); }
.ui-card--link:focus-visible { outline: none; box-shadow: var(--ui-ring); }

.ui-card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ui-space-md);
  padding: 0 var(--ui-card-pad);
}
.ui-card__heading { display: grid; gap: 0.375rem; min-width: 0; }
.ui-card__title {
  margin: 0;
  font-family: var(--ui-font-head);
  font-size: var(--ui-text-base);
  font-weight: var(--ui-heading-weight);
  letter-spacing: var(--ui-heading-tracking);
  line-height: 1.25;
}
.ui-card__description {
  margin: 0;
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
}
.ui-card__actions { display: flex; flex-shrink: 0; gap: var(--ui-space-sm); }

.ui-card__body { padding: 0 var(--ui-card-pad); font-size: var(--ui-text-sm); }
.ui-card__body > :first-child { margin-top: 0; }
.ui-card__body > :last-child { margin-bottom: 0; }

.ui-card__footer {
  padding: var(--ui-space-md) var(--ui-card-pad) 0;
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
  border-top: 1px solid var(--ui-border);
}

/* Accordion: a card's surface, the items divided by its hairline. */
.ui-accordion {
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
  overflow: hidden;
}
.ui-accordion__item + .ui-accordion__item { border-top: 1px solid var(--ui-border); }
.ui-accordion__summary {
  display: flex;
  align-items: center;
  gap: var(--ui-space-md);
  min-height: var(--ui-touch);
  padding: var(--ui-space-sm) var(--ui-card-pad);
  font-weight: var(--ui-control-weight);
  cursor: pointer;
  list-style: none;
}
.ui-accordion__summary::-webkit-details-marker { display: none; }
.ui-accordion__summary:hover { background: var(--ui-bg-hover); }
.ui-accordion__summary:focus-visible { outline: 2px solid var(--ui-ring-color); outline-offset: -2px; }
.ui-accordion__title { flex: 1; min-width: 0; }
.ui-accordion__marker { display: inline-flex; flex: none; color: var(--ui-text-muted); transition: transform var(--ui-transition); }
.ui-accordion__item[open] > .ui-accordion__summary .ui-accordion__marker { transform: rotate(90deg); }
.ui-accordion__body { padding: 0 var(--ui-card-pad) var(--ui-card-pad); color: var(--ui-text-muted); }
.ui-accordion__body > :first-child { margin-top: 0; }
.ui-accordion__body > :last-child { margin-bottom: 0; }

.ui-stat {
  --ui-stat-tone: var(--ui-text);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: var(--ui-card-pad);
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
  text-decoration: none;
}
.ui-stat--accent { --ui-stat-tone: var(--ui-accent); }
.ui-stat--success { --ui-stat-tone: var(--ui-success); }
.ui-stat--warning { --ui-stat-tone: var(--ui-warning); }
.ui-stat--danger { --ui-stat-tone: var(--ui-danger); }

.ui-stat--link { transition: border-color var(--ui-transition), box-shadow var(--ui-transition); }
.ui-stat--link:hover { border-color: var(--ui-border-strong); }
.ui-stat--link:focus-visible { outline: none; box-shadow: var(--ui-ring); }

.ui-stat__value {
  font-family: var(--ui-font-head);
  font-size: var(--ui-text-xl);
  font-weight: var(--ui-heading-weight);
  line-height: 1.15;
  letter-spacing: var(--ui-heading-tracking);
  /* journal's serif defaults to old-style figures, which drop below the
     line: right in prose, wrong for a number that is the whole point. */
  font-variant-numeric: lining-nums;
  color: var(--ui-stat-tone);
}
.ui-stat--live .ui-stat__value { font-variant-numeric: lining-nums tabular-nums; }
.ui-stat__status {
  font-size: var(--ui-text-xs);
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ui-stat-tone);
}
.ui-stat__sub { font-size: var(--ui-text-sm); color: var(--ui-text-muted); }
.ui-stat__trend { display: block; margin-top: 0.375rem; color: var(--ui-stat-tone); }
/* A meter or sparkline in the trend slot may cut its label short. */
.ui-stat__trend > * { min-width: 0; }

.ui-empty { color: var(--ui-text-muted); font-size: var(--ui-text-sm); }
.ui-empty__message { margin: 0; }
.ui-empty__detail { margin: 0.25rem 0 0; font-size: var(--ui-text-xs); }
.ui-empty__action { margin-top: var(--ui-space-md); }

.ui-empty--boxed {
  padding: var(--ui-space-xl) var(--ui-space-lg);
  text-align: center;
  border: 1px dashed var(--ui-border-strong);
  border-radius: var(--ui-card-radius);
}
.ui-empty--boxed .ui-empty__message { color: var(--ui-text); font-weight: var(--ui-heading-weight); }

/* Note: a muted aside. `--ui-text-muted` clears 4.5:1 on the page in every
   theme, so it stays readable at the small size; a toned note takes the
   status colour, which clears the same bar. */
.ui-note {
  margin: 0;
  font-size: var(--ui-text-sm);
  line-height: 1.5;
  color: var(--ui-text-muted);
  overflow-wrap: anywhere;
}
.ui-note code { font-family: var(--ui-font-mono); font-size: 0.92em; }
.ui-note--accent { color: var(--ui-accent); }
.ui-note--success { color: var(--ui-success); }
.ui-note--warning { color: var(--ui-warning); }
.ui-note--danger { color: var(--ui-danger); }

/* Kbd: a key as a small raised cap. A combination is a row of caps; the
   outer element of a combination draws nothing itself. */
.ui-kbd {
  display: inline-block;
  min-width: 1.6em;
  padding: 0.0625rem 0.375rem;
  font-family: var(--ui-font-mono);
  font-size: var(--ui-text-xs);
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  color: var(--ui-text);
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--ui-radius-sm);
}
.ui-kbd--combo {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
  padding: 0;
  background: none;
  border: 0;
}
.ui-kbd__joint { font-size: var(--ui-text-xs); color: var(--ui-text-muted); }

/* Shortcuts: keys on the left, what they do on the right; on a phone the
   pair stacks. Groups are spaced apart and headed in the theme's label
   style. */
.ui-shortcuts { display: grid; gap: var(--ui-space-lg); width: 100%; }
.ui-shortcuts__heading { margin: 0 0 var(--ui-space-sm); }
.ui-shortcuts__list { display: grid; margin: 0; }
.ui-shortcuts__row {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: 0.25rem 1rem;
  align-items: baseline;
  padding: var(--ui-space-xs) 0;
  border-top: 1px solid var(--ui-border);
}
.ui-shortcuts__row:first-child { border-top: 0; }
.ui-shortcuts__keys { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem; margin: 0; }
.ui-shortcuts__or { font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-shortcuts__action { margin: 0; font-size: var(--ui-text-sm); color: var(--ui-text); }
.ui-shortcuts__scope { display: block; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
@media (max-width: 480px) {
  .ui-shortcuts__row { grid-template-columns: minmax(0, 1fr); }
}

/* Prose: rendered markdown. Spacing flows from one element to the next, so
   the first and last carry no margin against their container. Everything is
   a token: the theme's faces, sizes, colours and corners. */
.ui-prose {
  font-size: var(--ui-text-base);
  line-height: var(--ui-leading);
  color: var(--ui-text);
  overflow-wrap: break-word;
}
.ui-prose--lg { font-size: var(--ui-text-lg); }
.ui-prose--measure { max-width: 70ch; }
.ui-prose > :first-child { margin-top: 0; }
.ui-prose > :last-child { margin-bottom: 0; }
.ui-prose :is(p, ul, ol, dl, blockquote, pre, table, figure, hr) { margin: 0 0 1em; }

/* Headings: the theme's heading face, weight and tracking; a sticky bar
   must not cover one that a link jumped to. */
.ui-prose :is(h1, h2, h3, h4, h5, h6) {
  margin: 1.75em 0 0.5em;
  font-family: var(--ui-font-head);
  font-weight: var(--ui-heading-weight);
  letter-spacing: var(--ui-heading-tracking);
  line-height: 1.25;
  text-wrap: balance;
  scroll-margin-top: calc(var(--ui-control-h) + 2rem);
}
.ui-prose h1 { font-size: calc(var(--ui-text-xl) * 1.2); margin-top: 0; }
.ui-prose h2 { font-size: var(--ui-text-xl); }
.ui-prose h3 { font-size: var(--ui-text-lg); }
.ui-prose :is(h4, h5, h6) { font-size: 1em; }
.ui-prose h6 { color: var(--ui-text-muted); }
/* A heading's own anchor link: there for the pointer and the keyboard,
   quiet otherwise, and hung in the margin so the heading does not move
   when it shows. */
.ui-prose :is(h1, h2, h3, h4, h5, h6):has(> .ui-prose__anchor) { position: relative; }
.ui-prose__anchor { position: absolute; right: 100%; padding-right: 0.25em; color: var(--ui-text-muted); text-decoration: none; opacity: 0; }
.ui-prose :is(h1, h2, h3, h4, h5, h6):hover .ui-prose__anchor,
.ui-prose__anchor:focus-visible { opacity: 1; }

.ui-prose a { color: var(--ui-accent); text-decoration: underline; text-underline-offset: 0.15em; }
.ui-prose a:hover { color: var(--ui-accent-hover); }
.ui-prose a:focus-visible { outline: none; box-shadow: var(--ui-ring); border-radius: var(--ui-radius-sm); }
.ui-prose :is(strong, b) { font-weight: 650; }
.ui-prose mark { color: inherit; background: color-mix(in srgb, var(--ui-warning) 22%, transparent); border-radius: var(--ui-radius-sm); padding: 0 0.125em; }
.ui-prose del { color: var(--ui-text-muted); }
.ui-prose small { font-size: var(--ui-text-sm); }

/* Lists, nested ones flush with their item's text; task lists draw the
   box instead of a bullet. */
.ui-prose :is(ul, ol) { padding-left: 1.5em; }
.ui-prose li + li, .ui-prose li > :is(ul, ol) { margin-top: 0.25em; }
.ui-prose li > :is(ul, ol) { margin-bottom: 0; }
.ui-prose li::marker { color: var(--ui-text-muted); }
.ui-prose .contains-task-list, .ui-prose ul:has(> .task-list-item) { padding-left: 0.25em; list-style: none; }
.ui-prose .task-list-item input { margin: 0 0.5em 0 0; accent-color: var(--ui-accent); vertical-align: -0.1em; }
.ui-prose dt { font-weight: 600; }
.ui-prose dd { margin: 0 0 0.5em 1.5em; }

.ui-prose blockquote {
  padding: 0.125em 0 0.125em 1em;
  color: var(--ui-text-muted);
  border-left: 3px solid var(--ui-border-strong);
}
.ui-prose blockquote > :last-child { margin-bottom: 0; }
.ui-prose hr { height: 0; border: 0; border-top: 1px solid var(--ui-border); margin: 2em 0; }
.ui-prose :is(img, video) { max-width: 100%; height: auto; border-radius: var(--ui-radius-md); }
.ui-prose figcaption { margin-top: 0.5em; font-size: var(--ui-text-sm); color: var(--ui-text-muted); }

/* Code: inline on a muted ground, blocks on the subtle surface with their
   own scroll, never the page's. */
.ui-prose code, .ui-prose kbd, .ui-prose samp { font-family: var(--ui-font-mono); font-size: 0.875em; }
.ui-prose :not(pre) > code {
  padding: 0.1em 0.35em;
  background: var(--ui-bg-muted);
  border-radius: var(--ui-radius-sm);
  overflow-wrap: anywhere;
}
.ui-prose pre {
  padding: 0.875em 1em;
  overflow-x: auto;
  font-size: var(--ui-text-sm);
  line-height: 1.6;
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
}
.ui-prose pre code { padding: 0; font-size: inherit; background: none; }
.ui-prose kbd:not(.ui-kbd) {
  padding: 0.0625em 0.375em;
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--ui-radius-sm);
}

/* Tables and code scroll inside the column instead of widening the page.
   prose.js puts each in a `.ui-prose__scroll` box, which scrolls and, when
   it has to, is a focusable named region; the table inside stays a table
   for assistive technology. Without the script the table itself scrolls,
   which some browsers no longer report as a table. */
.ui-prose__scroll { max-width: 100%; overflow-x: auto; margin: 0 0 1em; border-radius: var(--ui-radius-md); }
.ui-prose__scroll:focus-visible { outline: 2px solid transparent; box-shadow: var(--ui-ring); }
.ui-prose__scroll > :is(table, pre) { margin: 0; }
.ui-prose table {
  border-collapse: collapse;
  font-size: var(--ui-text-sm);
}
.ui-prose table:not(.ui-prose__scroll > table) { display: block; max-width: 100%; overflow-x: auto; }
.ui-prose__scroll > pre { overflow-x: visible; width: max-content; min-width: 100%; }
.ui-prose :is(th, td) { padding: var(--ui-cell-py) var(--ui-cell-px); text-align: left; vertical-align: top; border-bottom: 1px solid var(--ui-border); }
.ui-prose th { font-weight: 600; background: var(--ui-bg-subtle); white-space: nowrap; }
.ui-prose tbody tr:last-child td { border-bottom: 0; }

/* Footnotes: smaller and muted, under a rule. pulldown-cmark's markup. */
.ui-prose sup { line-height: 0; }
.ui-prose .footnote-definition {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  margin-top: 0.5em;
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
}
.ui-prose :not(.footnote-definition) + .footnote-definition { padding-top: 1em; border-top: 1px solid var(--ui-border); }
.ui-prose .footnote-definition > p { margin: 0; }

.ui-confirm { max-width: 36rem; }
.ui-confirm .ui-heading { margin-top: 0; }
.ui-confirm__subject { font-size: var(--ui-text-base); }
.ui-confirm__consequence { margin: 0.5rem 0 1.25rem; font-size: var(--ui-text-sm); color: var(--ui-text-muted); }

/* Dialog. The browser centres a modal `<dialog>` and draws `::backdrop`;
   this sizes the box, keeps it inside a phone's screen, and lets the body
   scroll when the content is taller than the viewport. */
.ui-dialog {
  width: min(32rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  padding: 0;
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-shadow-md);
}
.ui-dialog[open] { display: flex; flex-direction: column; }
.ui-dialog--wide { width: min(56rem, calc(100vw - 2rem)); }
.ui-dialog--full { width: calc(100vw - 2rem); height: calc(100dvh - 2rem); }
.ui-dialog::backdrop { background: color-mix(in srgb, black 45%, transparent); }
.ui-dialog__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-md);
  padding: calc(var(--ui-card-pad) * 0.6) var(--ui-card-pad);
  border-bottom: 1px solid var(--ui-border);
}
.ui-dialog__title {
  margin: 0;
  font-family: var(--ui-font-head);
  font-size: var(--ui-text-base);
  font-weight: var(--ui-heading-weight);
  letter-spacing: var(--ui-heading-tracking);
}
.ui-dialog__close-form { margin: 0; }
.ui-dialog__body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: var(--ui-card-pad); }
.ui-dialog__body > :first-child { margin-top: 0; }
.ui-dialog__body > :last-child { margin-bottom: 0; }
.ui-dialog__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--ui-space-sm);
  padding: calc(var(--ui-card-pad) * 0.6) var(--ui-card-pad);
  border-top: 1px solid var(--ui-border);
}
.ui-dialog__actions form { margin: 0; }

/* Search: a trigger shaped like the library's input, and inside the dialog
   a field over a list of results, the marked one in the hover fill. */
.ui-search-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  height: var(--ui-control-h);
  margin: 0;
  padding: 0 calc(var(--ui-control-px) * 0.75);
  font: inherit;
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-input-radius);
  box-shadow: var(--ui-input-shadow);
  cursor: pointer;
}
button.ui-search-trigger:hover { border-color: var(--ui-border-strong); }
.ui-search-trigger:focus-within, button.ui-search-trigger:focus-visible { outline: none; border-color: var(--ui-ring-color); box-shadow: var(--ui-ring); }
.ui-search-trigger__text { flex: 1; text-align: left; }
.ui-search-trigger__input { flex: 1; min-width: 0; padding: 0; font: inherit; color: var(--ui-text); background: none; border: 0; outline: none; }
.ui-search-trigger__input::placeholder { color: var(--ui-text-muted); opacity: 1; }
.ui-search-trigger__keys {
  flex: none;
  padding: 0 0.375rem;
  font-family: var(--ui-font-mono);
  font-size: var(--ui-text-xs);
  color: var(--ui-text-muted);
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-sm);
}
@media (max-width: 640px) { .ui-search-trigger__keys { display: none; } }

.ui-search { display: flex; flex-direction: column; gap: var(--ui-space-sm); }
.ui-search__field { position: relative; display: flex; align-items: center; }
.ui-search__field > .ui-icon { position: absolute; left: 0.75rem; color: var(--ui-text-muted); pointer-events: none; }
/* Two classes, to outrank `.ui-input`'s own padding (field.css comes later). */
.ui-search__field .ui-search__input { padding-left: 2.25rem; }
.ui-search__status { margin: 0; min-height: 1.25em; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-search__results { margin: 0; padding: 0; list-style: none; }
.ui-search__result + .ui-search__result { border-top: 1px solid var(--ui-border); }
/* An option holds its title and snippet itself: a link inside an option
   would be content a screen reader cannot reach. */
.ui-search__result {
  display: grid;
  gap: 0.125rem;
  padding: var(--ui-cell-py) var(--ui-cell-px);
  color: var(--ui-text);
  border-radius: var(--ui-radius-md);
  cursor: pointer;
}
/* The marked option: a fill and an edge bar, and an outline that forced
   colours paints where the fill is dropped. */
.ui-search__result[aria-selected="true"] { background: var(--ui-bg-hover); box-shadow: inset 3px 0 0 var(--ui-accent); outline: 2px solid transparent; outline-offset: -2px; }
.ui-search__section { font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-search__title { font-weight: var(--ui-control-weight); overflow-wrap: anywhere; }
.ui-search__snippet { margin: 0; font-size: var(--ui-text-sm); color: var(--ui-text-muted); overflow-wrap: anywhere; }
.ui-search__snippet mark { color: var(--ui-text); background: var(--ui-accent-muted); border-radius: var(--ui-radius-sm); }

.ui-alert {
  --ui-alert-tone: var(--ui-text-muted);
  display: flex;
  gap: var(--ui-space-md);
  padding: var(--ui-space-md) var(--ui-card-pad);
  color: var(--ui-text);
  background: color-mix(in srgb, var(--ui-alert-tone) var(--ui-alert-tint), var(--ui-bg-card));
  border: 1px solid color-mix(in srgb, var(--ui-alert-tone) calc(var(--ui-alert-tint) * 4), var(--ui-border));
  border-radius: var(--ui-radius-lg);
}
.ui-alert--accent { --ui-alert-tone: var(--ui-accent); }
.ui-alert--success { --ui-alert-tone: var(--ui-success); }
.ui-alert--warning { --ui-alert-tone: var(--ui-warning); }
.ui-alert--danger { --ui-alert-tone: var(--ui-danger); }
/* Without a tint (shadcn) the tone shows in the icon and, for danger, the
   title, as shadcn's destructive alert does. */
.ui-alert--danger .ui-alert__title { color: color-mix(in srgb, var(--ui-danger) calc(100% - var(--ui-alert-tint) * 12.5), var(--ui-text)); }

.ui-alert__icon { display: inline-flex; flex-shrink: 0; padding-top: 0.125rem; color: var(--ui-alert-tone); }
.ui-alert__icon svg { width: 1rem; height: 1rem; }
.ui-alert__content { min-width: 0; }
.ui-alert__title { margin: 0; font-weight: var(--ui-heading-weight); letter-spacing: var(--ui-heading-tracking); font-size: var(--ui-text-sm); }
.ui-alert__detail { margin-top: 0.25rem; font-size: var(--ui-text-sm); color: var(--ui-text-muted); }

/* Toasts: the alert's look (alert.css), stacked in a corner over the page,
   lifted by the theme's own shadow. On a phone they span the width at the
   bottom, above where a thumb rests on the page. */
.ui-toasts {
  position: fixed;
  right: var(--ui-space-lg);
  bottom: var(--ui-space-lg);
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--ui-space-sm);
  width: min(24rem, calc(100vw - 2 * var(--ui-space-lg)));
  pointer-events: none;
}
/* The toasts you see. The live regions beside it hold their words only, and
   are visually hidden by clipping, never `display: none`: a live region
   must stay in the accessibility tree to be read out. */
.ui-toasts__stack { display: flex; flex-direction: column; gap: var(--ui-space-sm); width: 100%; }
.ui-toast {
  width: 100%;
  align-items: center;
  box-shadow: var(--ui-shadow-md);
  pointer-events: auto;
}
.ui-toast .ui-alert__content { flex: 1; }
.ui-toast__action, .ui-toast__close { flex: none; }
@media (max-width: 640px) {
  .ui-toasts { right: var(--ui-space-md); left: var(--ui-space-md); bottom: var(--ui-space-md); width: auto; }
}

.ui-field { display: flex; flex-direction: column; gap: 0.375rem; }
.ui-field__label { font-size: var(--ui-text-sm); font-weight: var(--ui-control-weight); color: var(--ui-text); }
.ui-field__description { margin: 0; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-field__error { margin: 0; font-size: var(--ui-text-xs); font-weight: 560; color: var(--ui-danger); }

.ui-input {
  width: 100%;
  height: var(--ui-control-h);
  padding: 0 calc(var(--ui-control-px) * 0.75);
  font: inherit;
  font-size: var(--ui-text-sm);
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-input-radius);
  box-shadow: var(--ui-input-shadow);
  transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}
.ui-input::placeholder { color: var(--ui-text-muted); opacity: 1; }
.ui-input:focus-visible { outline: none; border-color: var(--ui-ring-color); box-shadow: var(--ui-ring); }
.ui-input[aria-invalid="true"] { border-color: var(--ui-danger); }
.ui-input:disabled { opacity: 0.5; cursor: not-allowed; }

.ui-field--check { gap: 0.125rem; }
.ui-check {
  display: inline-flex;
  align-items: flex-start;
  gap: 0.5rem;
  min-height: 1.5rem;
  font-size: var(--ui-text-sm);
  cursor: pointer;
}
.ui-check__box {
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  margin: 0.125rem 0 0;
  accent-color: var(--ui-accent);
}
.ui-check__box:focus-visible { outline: 2px solid var(--ui-ring-color); outline-offset: 2px; }
.ui-field--check .ui-field__description { padding-left: 1.5rem; }

/* The small size: as tall as `ui-btn--sm`, for a control that sits beside
   one (a filter select and its button, a quick-add box). Its own width
   rather than the row's, since it shares the row. */
.ui-input--sm {
  width: auto;
  max-width: 100%;
  height: var(--ui-control-h-sm);
  padding: 0 calc(var(--ui-control-px) * 0.5);
  font-size: var(--ui-text-xs);
}
.ui-select.ui-input--sm { padding-right: 0.25rem; }

/* A select is an input with the browser's own arrow, which follows
   `color-scheme` into dark mode. */
.ui-select { padding-right: 0.5rem; cursor: pointer; }

.ui-textarea {
  height: auto;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  line-height: var(--ui-leading);
  resize: vertical;
}
/* Grows with its text where the browser can size a field to its content. */
.ui-textarea--grow { field-sizing: content; min-height: calc(var(--ui-control-h) * 2); }

/* A bare control an app writes straight into a field, rather than through
   `field::input`, is drawn the same: it would otherwise be the browser's. */
.ui-field > :is(input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="range"], [type="file"]), select, textarea):not(.ui-input) {
  width: 100%;
  min-height: var(--ui-control-h);
  padding: 0 calc(var(--ui-control-px) * 0.75);
  font: inherit;
  font-size: var(--ui-text-sm);
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-input-radius);
  box-shadow: var(--ui-input-shadow);
}
.ui-field > textarea:not(.ui-input) { padding-block: 0.5rem; line-height: var(--ui-leading); }
.ui-field > :is(input, select, textarea):not(.ui-input):focus-visible { outline: none; border-color: var(--ui-ring-color); box-shadow: var(--ui-ring); }

/* Date range: one bordered group, its two inputs borderless inside it, so it
   reads as one control. Wraps on a narrow screen rather than overflowing:
   two date inputs, a dash and a button do not fit 360px side by side. */
.ui-date-range {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.375rem;
  max-width: 100%;
  min-height: var(--ui-control-h);
  padding: 0.125rem 0.25rem;
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-input-radius);
  box-shadow: var(--ui-input-shadow);
}
.ui-date-range:focus-within { border-color: var(--ui-ring-color); }
.ui-date-range__input {
  min-width: 0;
  height: calc(var(--ui-control-h) - 0.5rem);
  padding: 0 0.375rem;
  font: inherit;
  font-size: var(--ui-text-sm);
  color: var(--ui-text);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--ui-radius-sm);
}
/* The focused end gets the ring every other control gets, not a 1px border
   change; the transparent outline is what forced-colours mode paints. */
.ui-date-range__input:focus-visible { outline: 2px solid transparent; border-color: var(--ui-ring-color); box-shadow: var(--ui-ring); }
/* The browser's calendar glyph ships near-black; tone it to the text. */
.ui-date-range__input::-webkit-calendar-picker-indicator { opacity: 0.55; cursor: pointer; }
.ui-date-range__input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
.ui-date-range__end { display: inline-flex; align-items: center; gap: 0.25rem; }
.ui-date-range__label { padding-left: 0.25rem; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-date-range__sep { color: var(--ui-text-muted); }

.ui-date-range--sm { min-height: var(--ui-control-h-sm); padding-block: 0; }
.ui-date-range--sm .ui-date-range__input { height: calc(var(--ui-control-h-sm) - 0.25rem); font-size: var(--ui-text-xs); }
.ui-date-range--sm .ui-btn--sm { height: calc(var(--ui-control-h-sm) - 0.25rem); }

.ui-filter-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0 0 1rem; }
.ui-filter-bar > .ui-input[type="search"] { flex: 1 1 14rem; width: auto; }
.ui-filter-bar > .ui-select { width: auto; }
/* Under a sticky topbar, with the page behind it blurred away. */
.ui-filter-bar--sticky {
  position: sticky;
  z-index: 20;
  top: var(--ui-sticky-top, calc(var(--ui-control-h) + 1rem));
  padding: 0.5rem 0;
  background: color-mix(in srgb, var(--ui-bg) 92%, transparent);
  backdrop-filter: blur(8px);
}

.ui-segmented {
  flex-wrap: wrap;
  max-width: 100%;
  display: inline-flex;
  gap: 0.125rem;
  padding: 0.1875rem;
  background: var(--ui-bg-muted);
  border-radius: calc(var(--ui-radius-md) + 0.1875rem);
}
.ui-segmented__item {
  display: inline-flex;
  align-items: center;
  height: calc(var(--ui-control-h) - 0.375rem);
  padding: 0 calc(var(--ui-control-px) * 0.75);
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  color: var(--ui-text-muted);
  text-decoration: none;
  border-radius: var(--ui-radius-md);
  transition: background-color var(--ui-transition), color var(--ui-transition);
}
.ui-segmented__item:hover { color: var(--ui-text); }
.ui-segmented__item:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-segmented__item--current {
  color: var(--ui-text);
  background: var(--ui-bg-card);
  box-shadow: var(--ui-shadow-sm);
}
.ui-segmented__count { margin-left: 0.125rem; font-variant-numeric: tabular-nums; color: var(--ui-text-muted); }

.ui-breadcrumb { font-size: var(--ui-text-sm); color: var(--ui-text-muted); }
.ui-breadcrumb__list { display: flex; flex-wrap: wrap; align-items: center; margin: 0; padding: 0; list-style: none; }
.ui-breadcrumb__item { display: inline-flex; align-items: center; min-width: 0; }
/* The separator is drawn, not written, and its alternative text is empty
   (`content: "/" / ""`): generated content is read aloud otherwise, "slash"
   between every step. The first declaration is for a browser that does not
   know the alternative-text syntax and drops the second. */
.ui-breadcrumb__item + .ui-breadcrumb__item::before { content: "/"; content: "/" / ""; margin: 0 0.4rem; color: var(--ui-border-strong); }
.ui-breadcrumb__link { color: inherit; text-decoration: none; border-radius: var(--ui-radius-sm); }
.ui-breadcrumb__link:hover { color: var(--ui-text); text-decoration: underline; }
.ui-breadcrumb__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-breadcrumb [aria-current="page"] { color: var(--ui-text); font-weight: 560; }

.ui-pager { display: inline-flex; align-items: center; gap: 0.25rem; }
.ui-pager__status { padding: 0 0.5rem; font-size: var(--ui-text-sm); color: var(--ui-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

.ui-menu { position: relative; display: inline-block; }
.ui-menu__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: var(--ui-control-h);
  padding: 0 var(--ui-control-px);
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-btn-radius);
  box-shadow: var(--ui-input-shadow);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.ui-menu__trigger::-webkit-details-marker { display: none; }
.ui-menu__trigger:hover { background: var(--ui-bg-hover); }
.ui-menu__trigger:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-menu__trigger--icon { width: var(--ui-control-h); padding: 0; justify-content: center; }
.ui-menu__trigger--icon .ui-menu__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
/* While open, the summary stretches an invisible layer over the page: a
   click anywhere outside lands on the summary and closes the menu. */
.ui-menu[open] > .ui-menu__trigger::before { content: ""; position: fixed; inset: 0; z-index: 40; cursor: default; }
.ui-menu__panel {
  position: absolute;
  z-index: 41;
  top: calc(100% + 0.375rem);
  left: 0;
  min-width: 12rem;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-md);
}
.ui-menu--end .ui-menu__panel { left: auto; right: 0; }
.ui-menu__item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  font-size: var(--ui-text-sm);
  color: var(--ui-text);
  text-decoration: none;
  border-radius: var(--ui-radius-sm);
}
.ui-menu__item:hover { background: var(--ui-bg-hover); }
.ui-menu__item:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-menu__item .ui-icon { color: var(--ui-text-muted); }

.ui-menu__trigger--ghost { background: transparent; border-color: transparent; box-shadow: none; }
.ui-menu__trigger--ghost:hover { background: var(--ui-bg-hover); }
.ui-menu__trigger--plain {
  height: auto;
  padding: 0.375rem 0.625rem;
  color: var(--ui-text-muted);
  background: transparent;
  border-color: transparent;
  border-radius: var(--ui-radius-md);
  box-shadow: none;
}
.ui-menu__trigger--plain:hover, .ui-menu[open] > .ui-menu__trigger--plain { color: var(--ui-text); background: var(--ui-bg-hover); }
.ui-menu__caret { width: 0; height: 0; border: 0.25em solid transparent; border-top-color: currentColor; margin-top: 0.25em; }
/* A submit entry looks exactly like a link entry. */
button.ui-menu__item { width: 100%; font: inherit; font-size: var(--ui-text-sm); text-align: left; background: none; border: 0; cursor: pointer; }

/* On a phone a trigger with an icon is its icon, like a collapsing button;
   the label stays as the accessible name. */
@media (max-width: 640px) {
  .ui-menu__trigger:has(.ui-icon):not(.ui-menu__trigger--plain) { width: var(--ui-control-h); padding: 0; justify-content: center; }
  .ui-menu__trigger:has(.ui-icon):not(.ui-menu__trigger--plain) .ui-menu__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
}

/* The menu holding the page being shown, and that page's entry: marked as a
   nav bar marks its current link, in the accent's pale wash. */
.ui-menu__trigger--current, .ui-menu__trigger--plain.ui-menu__trigger--current { color: var(--ui-text); background: var(--ui-accent-muted); }
.ui-menu__item--current { font-weight: 600; background: var(--ui-accent-muted); }

/* Tooltip: the page's colours turned round (text on a text-coloured
   ground), so it reads over any surface in any theme without a colour of
   its own. Shown on hover and on keyboard focus; the script's Escape adds
   `--dismissed` until the pointer or focus leaves. */
.ui-tooltip { position: relative; display: inline-flex; }
.ui-tooltip__bubble {
  position: absolute;
  left: 50%;
  z-index: 60;
  width: max-content;
  max-width: min(16rem, 80vw);
  padding: 0.25rem 0.5rem;
  font-size: var(--ui-text-xs);
  font-weight: 500;
  line-height: 1.4;
  color: var(--ui-bg);
  background: var(--ui-text);
  border-radius: var(--ui-radius-sm);
  box-shadow: var(--ui-shadow-sm);
  transform: translateX(calc(-50% + var(--ui-tooltip-shift, 0px)));
  /* Not `visibility: hidden`: a hidden bubble near the screen's edge would
     still widen the page. */
  display: none;
}
.ui-tooltip--top .ui-tooltip__bubble { bottom: calc(100% + 0.375rem); }
.ui-tooltip--bottom .ui-tooltip__bubble { top: calc(100% + 0.375rem); }
/* A bridge over the gap between the element and the hint, so the pointer can
   move onto the hint without it vanishing on the way (WCAG 1.4.13: content
   shown on hover can itself be hovered). It is part of the bubble, so the
   tooltip stays `:hover` across it. */
.ui-tooltip__bubble::before { content: ""; position: absolute; left: 0; right: 0; height: 0.5rem; }
.ui-tooltip--top .ui-tooltip__bubble::before { top: 100%; }
.ui-tooltip--bottom .ui-tooltip__bubble::before { bottom: 100%; }
.ui-tooltip:is(:hover, :focus-within):not(.ui-tooltip--dismissed) .ui-tooltip__bubble { display: block; }

.ui-drawer { display: inline-block; }
/* A floating drawer is all overlay: in the flow it must take no room, not
   even the empty line an inline-block would leave between header and page. */
.ui-drawer--floating { display: block; height: 0; }
.ui-drawer__trigger {
  display: inline-grid;
  place-items: center;
  width: var(--ui-touch);
  height: var(--ui-touch);
  font-size: 1.25rem;
  color: var(--ui-text);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border-control);
  border-radius: var(--ui-radius-md);
  cursor: pointer;
  list-style: none;
}
.ui-drawer__trigger::-webkit-details-marker { display: none; }
.ui-drawer__trigger:hover { background: var(--ui-bg-hover); }
.ui-drawer__trigger:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-drawer__close-icon, .ui-drawer[open] .ui-drawer__open-icon { display: none; }
.ui-drawer[open] .ui-drawer__close-icon { display: inline; }

/* Floating: a round thumb button, clear of the home indicator. */
.ui-drawer--floating > .ui-drawer__trigger {
  position: fixed;
  z-index: 52;
  right: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom));
  width: 3.25rem;
  height: 3.25rem;
  color: var(--ui-accent-fg);
  background: var(--ui-accent);
  border: 0;
  border-radius: 50%;
  box-shadow: var(--ui-shadow-md);
}
.ui-drawer--floating > .ui-drawer__trigger:hover { background: var(--ui-accent-hover); }

/* Open: a scrim over the page — tapping it lands on the summary and closes
   the drawer — and the panel against the right edge. */
.ui-drawer[open] > .ui-drawer__trigger::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--ui-text) 35%, transparent);
  cursor: default;
}
/* While open the button becomes the close button, just outside the panel's
   edge on the scrim: above the scrim, never under the panel. */
.ui-drawer[open] > .ui-drawer__trigger {
  position: fixed;
  z-index: 52;
  top: calc(0.75rem + env(safe-area-inset-top));
  right: calc(min(20rem, 86vw) + 0.75rem);
  bottom: auto;
}
.ui-drawer__panel {
  position: fixed;
  z-index: 53;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(20rem, 86vw);
  overflow-y: auto;
  padding: 1rem 0.75rem calc(5rem + env(safe-area-inset-bottom));
  background: var(--ui-bg-card);
  border-left: 1px solid var(--ui-border);
  box-shadow: var(--ui-shadow-md);
}
.ui-drawer[open] .ui-drawer__panel { animation: ui-drawer-in var(--ui-transition) both; }
@keyframes ui-drawer-in { from { transform: translateX(100%); } }

.ui-drawer__title { margin: 0.25rem 0.5rem 0.75rem; font-family: var(--ui-font-head); font-size: var(--ui-text-lg); font-weight: var(--ui-heading-weight); letter-spacing: var(--ui-heading-tracking); }
.ui-drawer__heading { margin: 1rem 0.5rem 0.25rem; }
.ui-drawer__list { margin: 0; padding: 0; list-style: none; }
.ui-drawer__link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--ui-touch);
  padding: 0 0.625rem;
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  color: var(--ui-text);
  text-decoration: none;
  border-radius: var(--ui-radius-md);
}
.ui-drawer__link .ui-icon { font-size: 1.125rem; color: var(--ui-text-muted); }
.ui-drawer__link:hover { background: var(--ui-bg-hover); }
.ui-drawer__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
/* Current: a bar at the edge as well as the tint, so it is not colour alone. */
.ui-drawer__link[aria-current="page"] { background: var(--ui-accent-muted); box-shadow: inset 3px 0 0 var(--ui-accent); font-weight: 650; }
.ui-drawer__link[aria-current="page"] .ui-icon { color: var(--ui-accent); }
.ui-drawer__footer { display: grid; gap: 0.75rem; margin-top: 1rem; padding: 1rem 0.5rem 0; border-top: 1px solid var(--ui-border); }

@media (min-width: 641px) and (min-height: 521px) { .ui-drawer--phone { display: none; } }
@media (min-width: 1101px) { .ui-drawer--tablet { display: none; } }
.ui-drawer__top { display: grid; gap: 0.5rem; margin: 0 0.5rem 0.75rem; }

/* Side nav: quiet links in a column; the current one tinted with a bar at
   its edge, as the drawer marks it, so not by colour alone. */
.ui-side-nav { display: grid; gap: 1.25rem; font-size: var(--ui-text-sm); }
.ui-side-nav__top { display: grid; gap: 0.5rem; }
.ui-side-nav__heading { margin: 0 0 0.375rem 0.625rem; }
.ui-side-nav__list { display: grid; gap: 0.125rem; margin: 0; padding: 0; list-style: none; }
.ui-side-nav__link {
  display: block;
  padding: 0.375rem 0.625rem;
  color: var(--ui-text-muted);
  text-decoration: none;
  border-radius: var(--ui-radius-md);
}
.ui-side-nav__link:hover { color: var(--ui-text); background: var(--ui-bg-hover); }
.ui-side-nav__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-side-nav__link[aria-current="page"] {
  color: var(--ui-text);
  font-weight: 650;
  background: var(--ui-accent-muted);
  box-shadow: inset 3px 0 0 var(--ui-accent);
}

/* Table of contents: small links under the theme's label; nested ones
   indented; the section being read marked by the scroll script. */
.ui-toc { font-size: var(--ui-text-sm); }
.ui-toc__title { margin: 0 0 0.5rem; }
.ui-toc__list { display: grid; gap: 0.125rem; margin: 0; padding: 0; list-style: none; }
.ui-toc__list--nested { margin-top: 0.125rem; padding-left: 0.75rem; }
.ui-toc__link {
  display: block;
  padding: 0.25rem 0.5rem;
  color: var(--ui-text-muted);
  text-decoration: none;
  border-left: 2px solid transparent;
  border-radius: 0 var(--ui-radius-sm) var(--ui-radius-sm) 0;
}
.ui-toc__link:hover { color: var(--ui-text); }
.ui-toc__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-toc__link[aria-current="location"] { color: var(--ui-text); font-weight: 600; border-left-color: var(--ui-accent); }

/* Folded: a card-like disclosure above the content. */
.ui-toc-fold {
  margin-bottom: 1.5rem;
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
}
.ui-toc-fold__summary {
  display: flex;
  align-items: center;
  min-height: var(--ui-touch);
  padding: 0 var(--ui-card-pad);
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  cursor: pointer;
  list-style: none;
}
.ui-toc-fold__summary::-webkit-details-marker { display: none; }
.ui-toc-fold__summary::after { content: "▾"; margin-left: auto; color: var(--ui-text-muted); }
.ui-toc-fold[open] > .ui-toc-fold__summary::after { content: "▴"; }
.ui-toc-fold__summary:focus-visible { outline: none; box-shadow: var(--ui-ring); border-radius: var(--ui-card-radius); }
.ui-toc-fold > .ui-toc { padding: 0 var(--ui-card-pad) var(--ui-card-pad); }

/* Footer: link columns over a hairline, then the brand and the small print.
   It sits on the page's subtle surface, apart from the content above. */
.ui-footer {
  margin-top: auto;
  padding: 2.5rem 1rem calc(2rem + env(safe-area-inset-bottom));
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
  background: var(--ui-bg-subtle);
  border-top: 1px solid var(--ui-border);
}
@media (min-width: 641px) { .ui-footer { padding-inline: 1.5rem; } }
.ui-footer__inner { max-width: 76rem; margin-inline: auto; display: grid; gap: 2rem; }
.ui-footer__nav { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(10rem, 100%), 1fr)); gap: 1.5rem; }
.ui-footer__heading { margin: 0 0 0.5rem; }
.ui-footer__list { display: grid; gap: 0.375rem; margin: 0; padding: 0; list-style: none; }
.ui-footer__link { color: var(--ui-text-muted); text-decoration: none; border-radius: var(--ui-radius-sm); }
.ui-footer__link:hover { color: var(--ui-text); text-decoration: underline; }
.ui-footer__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--ui-border);
}
.ui-footer__nav + .ui-footer__bottom { margin-top: 0; }
.ui-footer__brand { color: var(--ui-text); }
.ui-footer__legal a { color: inherit; }
/* A floating drawer button sits over the bottom corner wherever it shows;
   the footer's last line keeps clear of it. */
@media (max-width: 1100px) {
  .ui-page:has(.ui-drawer--floating) > .ui-footer { padding-bottom: calc(5rem + env(safe-area-inset-bottom)); }
}

/* Docs layout: sidebar | page | table of contents. The columns give way as
   the window narrows: the table of contents folds above the page under
   1280px, the sidebar moves into the drawer at 1100px and under (when there
   is a drawer to take it). The side columns stay in view while the page
   scrolls, clear of a sticky bar. */
.ui-docs {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2rem;
  max-width: 90rem;
  margin-inline: auto;
}
.ui-docs__main { min-width: 0; width: 100%; max-width: 48rem; justify-self: center; }
.ui-docs__nav, .ui-docs__toc { min-width: 0; }
.ui-docs__toc { display: none; }
.ui-docs__pager { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--ui-border); }

@media (max-width: 1100px) { .ui-docs--folds > .ui-docs__nav { display: none; } }
@media (min-width: 1101px) {
  .ui-docs { grid-template-columns: 15rem minmax(0, 1fr); }
  .ui-docs__nav {
    position: sticky;
    top: calc(var(--ui-control-h) + 2rem);
    align-self: start;
    max-height: calc(100dvh - var(--ui-control-h) - 3rem);
    overflow-y: auto;
  }
}
@media (min-width: 1280px) {
  .ui-docs--toc { grid-template-columns: 15rem minmax(0, 1fr) 13rem; }
  .ui-docs__toc {
    display: block;
    position: sticky;
    top: calc(var(--ui-control-h) + 2rem);
    align-self: start;
    max-height: calc(100dvh - var(--ui-control-h) - 3rem);
    overflow-y: auto;
  }
  .ui-docs__toc-fold { display: none; }
}

/* A site's page is at least a window tall, so a short page's footer sits at
   the bottom of the window rather than under the last paragraph. */
.ui-page:has(> .ui-footer) { display: flex; flex-direction: column; min-height: 100dvh; }
.ui-page:has(> .ui-footer) > .ui-main { flex: 1 0 auto; width: 100%; }

/* Floating action buttons stack up from the bottom right by slot; a
   floating nav drawer's button is slot 0. */
.ui-fab {
  position: fixed;
  z-index: 50;
  right: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom) + var(--ui-fab-slot, 0) * 4rem);
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  font-size: 1.25rem;
  color: var(--ui-btn-fg);
  background: var(--ui-btn-bg);
  border: 0;
  border-radius: 50%;
  box-shadow: var(--ui-shadow-md);
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--ui-transition), filter var(--ui-transition);
}
.ui-fab:hover { filter: var(--ui-btn-hover-filter); background: var(--ui-btn-bg-hover); }
.ui-fab:active { transform: scale(0.96); }
.ui-fab:focus-visible { outline: none; box-shadow: var(--ui-ring), var(--ui-shadow-md); }
@media (min-width: 641px) and (min-height: 521px) { .ui-fab--phone { display: none; } }
@media (min-width: 1101px) { .ui-fab--tablet { display: none; } }

.ui-tabs__list {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1rem;
  padding-bottom: 0.25rem;
  overflow-x: auto;
  border-bottom: 1px solid var(--ui-border);
}
.ui-tabs__list[hidden] { display: none; }
.ui-tabs__tab {
  flex-shrink: 0;
  min-height: var(--ui-touch);
  padding: 0 0.875rem;
  font: inherit;
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  white-space: nowrap;
  color: var(--ui-text-muted);
  background: transparent;
  border: 0;
  border-radius: var(--ui-radius-md);
  cursor: pointer;
}
.ui-tabs__tab:hover { color: var(--ui-text); background: var(--ui-bg-hover); }
.ui-tabs__tab:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-tabs__tab[aria-selected="true"] { color: var(--ui-text); background: var(--ui-bg-muted); }
.ui-tabs__panel:focus-visible { outline: none; box-shadow: var(--ui-ring); border-radius: var(--ui-radius-sm); }
/* Without the script every panel shows, each under its own title. */
.ui-tabs:not(.ui-tabs--ready) .ui-tabs__panel + .ui-tabs__panel { margin-top: 1.5rem; }
.ui-tabs__fallback-title { margin: 0 0 0.5rem; }
.ui-tabs--ready .ui-tabs__fallback-title { display: none; }

/* Tab bar: link tabs in a row. Without the script the row scrolls sideways
   on a narrow screen; with it (`--js`) the row stays one line and what does
   not fit moves into the "…" menu, whose panel must not be clipped, so the
   row stops being a scroll container. */
.ui-tab-bar { min-width: 0; max-width: 100%; }
.ui-tab-bar__list {
  display: flex;
  align-items: center;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.ui-tab-bar--js .ui-tab-bar__list { overflow: visible; }
.ui-tab-bar__item, .ui-tab-bar__more { flex: none; }
.ui-tab-bar__tab {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: var(--ui-control-h);
  padding: 0 calc(var(--ui-control-px) * 0.75);
  font-size: var(--ui-text-sm);
  font-weight: var(--ui-control-weight);
  color: var(--ui-text-muted);
  text-decoration: none;
  white-space: nowrap;
  border-radius: var(--ui-radius-md);
}
.ui-tab-bar__tab:hover { color: var(--ui-text); background: var(--ui-bg-hover); }
.ui-tab-bar__tab:focus-visible { outline: none; box-shadow: var(--ui-ring); }
/* The current tab: a filled ground and the text colour, not colour alone. */
.ui-tab-bar__tab[aria-current="page"] { color: var(--ui-text); background: var(--ui-bg-muted); }
.ui-tab-bar__tab--icon { width: var(--ui-control-h); padding: 0; justify-content: center; }
.ui-tab-bar__tab--icon .ui-tab-bar__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }

.ui-tab-bar__more-trigger { height: var(--ui-control-h); }
.ui-tab-bar__more-trigger .ui-menu__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
/* A tab moved into the menu reads as a menu entry. */
.ui-tab-bar__overflow .ui-tab-bar__item { display: block; }
.ui-tab-bar__overflow .ui-tab-bar__tab { display: flex; width: 100%; height: auto; padding: 0.5rem 0.625rem; color: var(--ui-text); border-radius: var(--ui-radius-sm); }
.ui-tab-bar__overflow .ui-tab-bar__tab--icon .ui-tab-bar__label { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
.ui-tab-bar__overflow .ui-tab-bar__tab--icon { justify-content: flex-start; }

/* Stepper. Each step is its marker and its name; a line joins it to the
   next. The state shows in the marker's shape as well as its colour: a tick
   for done, a filled dot for current, a hollow ring for to come, a dash for
   skipped. Wraps onto further lines on a narrow screen rather than
   scrolling, so every stage stays in view. */
.ui-stepper {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-space-sm) 0;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--ui-text-sm);
}
.ui-stepper__step {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--ui-text-muted);
}
.ui-stepper__step + .ui-stepper__step::before {
  content: "";
  width: 1.5rem;
  height: 1px;
  margin: 0 0.5rem;
  background: var(--ui-border-strong);
}
.ui-stepper__marker {
  position: relative;
  flex: none;
  width: 1rem;
  height: 1rem;
  border: 1.5px solid currentColor;
  border-radius: var(--ui-radius-full);
}
.ui-stepper__step--done { color: var(--ui-text); }
.ui-stepper__step--done .ui-stepper__marker { background: var(--ui-success); border-color: var(--ui-success); }
.ui-stepper__step--done .ui-stepper__marker::after {
  content: "";
  position: absolute;
  left: 0.3rem;
  top: 0.12rem;
  width: 0.25rem;
  height: 0.5rem;
  border: solid var(--ui-bg-card);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.ui-stepper__step--current { color: var(--ui-text); font-weight: 600; }
.ui-stepper__step--current .ui-stepper__marker { border-color: var(--ui-accent); }
.ui-stepper__step--current .ui-stepper__marker::after {
  content: "";
  position: absolute;
  inset: 0.2rem;
  background: var(--ui-accent);
  border-radius: var(--ui-radius-full);
}
.ui-stepper__step--skipped .ui-stepper__label { text-decoration: line-through; }
.ui-stepper__step--skipped .ui-stepper__marker { border-style: dashed; }
.ui-stepper__step--skipped .ui-stepper__marker::after {
  content: "";
  position: absolute;
  left: 0.2rem;
  right: 0.2rem;
  top: calc(50% - 0.75px);
  height: 1.5px;
  background: currentColor;
}

.ui-list { margin: 0; padding: 0; list-style: none; }
.ui-list__item + .ui-list__item { border-top: 1px solid var(--ui-border); }
.ui-list__link {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  min-height: var(--ui-touch);
  padding: var(--ui-cell-py) var(--ui-cell-px);
  color: var(--ui-text);
  text-decoration: none;
  border-radius: var(--ui-radius-md);
}
.ui-list__link:hover { background: var(--ui-bg-hover); }
.ui-list__link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-list__lead {
  flex: 0 0 4.5rem;
  font-size: var(--ui-text-sm);
  color: var(--ui-text-muted);
  font-variant-numeric: tabular-nums;
}
.ui-list--wide-lead .ui-list__lead { flex-basis: 7.5rem; }
.ui-list__title { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ui-list__trail { flex: 0 0 auto; align-self: center; font-size: var(--ui-text-sm); color: var(--ui-text-muted); }

/* Grid rows: the title wrapper steps aside so its children are the cells. */
.ui-list--grid .ui-list__link { display: grid; grid-template-columns: var(--ui-list-grid); align-items: baseline; }
.ui-list--grid .ui-list__title { display: contents; }
.ui-list--grid .ui-list__title > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 640px) {
  .ui-list--grid .ui-list__link { grid-template-columns: 1fr; gap: 0.125rem; }
}
.ui-list__muted { color: var(--ui-text-muted); font-size: var(--ui-text-sm); }
/* A row with an action: the link takes the room, the control keeps its own
   width beside it, centred on the row. */
.ui-list__item--control { display: flex; align-items: center; gap: 0.25rem; }
.ui-list__item--control > .ui-list__link { flex: 1 1 auto; min-width: 0; }
.ui-list__control { flex: none; display: flex; align-items: center; gap: 0.25rem; padding-right: 0.25rem; }

.ui-table-wrap {
  /* The containing block for what the table holds out of sight (the sort
     announcement): positioned elsewhere, it would widen the page. */
  position: relative;
  overflow-x: auto;
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
}
.ui-table-wrap:focus-visible { outline: none; box-shadow: var(--ui-ring); }
/* A table that scrolls says so: the edge fades where the content goes on. */
.ui-table-wrap--scroll {
  background:
    linear-gradient(to right, var(--ui-bg-card) 30%, transparent) left / 2rem 100% no-repeat local,
    linear-gradient(to left, var(--ui-bg-card) 30%, transparent) right / 2rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--ui-text) 14%, transparent), transparent) left / 0.75rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--ui-text) 14%, transparent), transparent) right / 0.75rem 100% no-repeat scroll,
    var(--ui-bg-card);
}
.ui-table { width: 100%; border-collapse: collapse; font-size: var(--ui-text-sm); }
.ui-table tbody tr:hover { background: color-mix(in srgb, var(--ui-bg-muted) 50%, transparent); }
.ui-table--wide { min-width: 30rem; }
.ui-table th {
  padding: var(--ui-cell-py) var(--ui-cell-px);
  text-align: left;
  background: var(--ui-bg-subtle);
  border-bottom: 1px solid var(--ui-border);
  white-space: nowrap;
}
.ui-table td { padding: var(--ui-cell-py) var(--ui-cell-px); border-bottom: 1px solid var(--ui-border); vertical-align: top; }
.ui-table tbody tr:last-child td { border-bottom: 0; }
.ui-table .ui-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ui-table__sort { display: inline-flex; align-items: center; gap: 0.25rem; color: inherit; text-decoration: none; border-radius: var(--ui-radius-sm); }
.ui-table__sort:hover { color: var(--ui-text); text-decoration: underline; }
.ui-table__sort:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-table__sort--active { color: var(--ui-text); }

/* A row header reads as the row's name: the cell's weight and colour, not
   the column header's small-label recipe. */
.ui-table tbody th {
  padding: var(--ui-cell-py) var(--ui-cell-px);
  text-align: left;
  font: inherit;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ui-text);
  background: transparent;
  border-bottom: 1px solid var(--ui-border);
  vertical-align: top;
  white-space: normal;
}
.ui-table tbody tr:last-child th { border-bottom: 0; }

/* Sorting in the browser: the script wraps each header's text in this
   button and keeps `aria-sort` on the header, which is what a screen reader
   announces; the arrow is drawn from it. */
button.ui-table__sort {
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}
th[aria-sort="ascending"] > button.ui-table__sort::after { content: "▲"; font-size: 0.7em; }
th[aria-sort="descending"] > button.ui-table__sort::after { content: "▼"; font-size: 0.7em; }
th[aria-sort="ascending"] > button.ui-table__sort,
th[aria-sort="descending"] > button.ui-table__sort { color: var(--ui-text); }

/* Stacked on a phone: each row a card of label/value pairs, the first cell
   its title. The table stops being a scroll region there, since nothing in
   it is wider than the screen any more. */
@media (max-width: 640px) {
  .ui-table-wrap:has(> .ui-table--stack) {
    overflow: visible;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  .ui-table--stack { display: block; min-width: 0; }
  .ui-table--stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .ui-table--stack tbody { display: grid; gap: var(--ui-space-sm); }
  .ui-table--stack tbody tr {
    display: grid;
    gap: 0.25rem;
    padding: var(--ui-space-md);
    background: var(--ui-bg-card);
    border: 1px solid var(--ui-card-border);
    border-radius: var(--ui-card-radius);
    box-shadow: var(--ui-card-shadow);
  }
  .ui-table--stack tbody tr:hover { background: var(--ui-bg-card); }
  .ui-table--stack tbody :is(td, th) {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.25rem 1rem;
    padding: 0;
    border: 0;
    text-align: left;
    overflow-wrap: anywhere;
  }
  .ui-table--stack tbody :is(td, th)::before {
    content: attr(data-label);
    flex: none;
    font-size: var(--ui-text-xs);
    font-weight: 560;
    color: var(--ui-text-muted);
  }
  /* The row's name is its title: on its own line, without a label. */
  .ui-table--stack tbody th { display: block; font-size: var(--ui-text-base); }
  .ui-table--stack tbody th::before { content: none; }
  .ui-table--stack tbody td:empty { display: none; }
  /* A sortable stacked table keeps its headers, as a wrapping bar of chips
     above the cards: sorting is no less useful on a phone. */
  .ui-table--stack[data-ui-table-sort] thead { position: static; width: auto; height: auto; overflow: visible; clip: auto; display: block; margin-bottom: var(--ui-space-sm); }
  .ui-table--stack[data-ui-table-sort] thead tr { display: flex; flex-wrap: wrap; gap: 0.3rem; }
  .ui-table--stack[data-ui-table-sort] thead th { display: inline-flex; padding: 0; background: none; border: 0; }
  .ui-table--stack[data-ui-table-sort] thead button.ui-table__sort { padding: 0.2rem 0.6rem; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-full); }
  .ui-table--stack[data-ui-table-sort] thead th[aria-sort="ascending"] > button.ui-table__sort,
  .ui-table--stack[data-ui-table-sort] thead th[aria-sort="descending"] > button.ui-table__sort { background: var(--ui-accent-muted); color: var(--ui-accent); border-color: transparent; }
}

/* Key/value list. One grid with `subgrid` rows, so every label column lines
   up across rows at the width of the longest label; `minmax(0, …)` on both
   tracks so neither can push the list past its container. Values are often
   one unbreakable token (a URL, a DOI), so they wrap anywhere. */
.ui-kv {
  display: grid;
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
  gap: var(--ui-space-sm) var(--ui-space-lg);
  margin: 0;
  font-size: var(--ui-text-sm);
}
.ui-kv__row { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: baseline; }
.ui-kv__label { color: var(--ui-text-muted); font-weight: 560; }
.ui-kv__value { margin: 0; color: var(--ui-text); overflow-wrap: anywhere; }
.ui-kv__value :is(ul, ol) { margin: 0; padding-left: 1.1rem; }

/* On a phone the label sits above its value. */
@media (max-width: 640px) {
  .ui-kv { grid-template-columns: minmax(0, 1fr); row-gap: var(--ui-space-md); }
  .ui-kv__row { gap: 0.125rem; }
  .ui-kv__label { font-size: var(--ui-text-xs); }
}

.ui-meter { --ui-meter-tone: var(--ui-accent); display: grid; gap: 0.25rem; }
.ui-meter--success { --ui-meter-tone: var(--ui-success); }
.ui-meter--warning { --ui-meter-tone: var(--ui-warning); }
.ui-meter--danger { --ui-meter-tone: var(--ui-danger); }
.ui-meter--neutral { --ui-meter-tone: var(--ui-text-muted); }
.ui-meter__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; font-size: var(--ui-text-sm); }
/* The label wraps rather than being cut off: an ellipsis hides text a
   sighted reader then cannot get back at a narrow width (WCAG 1.4.10). */
.ui-meter__label { min-width: 0; overflow-wrap: anywhere; color: var(--ui-text); }
.ui-meter__value { flex-shrink: 0; font-variant-numeric: tabular-nums; color: var(--ui-meter-tone); }
.ui-meter--accent .ui-meter__value { color: var(--ui-text-muted); }
.ui-meter__status { margin-left: 0.375rem; font-size: var(--ui-text-xs); font-weight: 650; letter-spacing: 0.04em; text-transform: uppercase; }
.ui-meter__track {
  height: 0.5rem;
  overflow: hidden;
  border-radius: var(--ui-radius-full);
  background: color-mix(in srgb, var(--ui-meter-tone) 18%, var(--ui-bg-muted));
}
.ui-meter__fill { height: 100%; background: var(--ui-meter-tone); border-radius: 0 var(--ui-radius-full) var(--ui-radius-full) 0; }
.ui-meter__detail { font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-meter-link { display: block; margin: -0.25rem; padding: 0.25rem; color: inherit; text-decoration: none; border-radius: var(--ui-radius-md); }
.ui-meter-link:hover { background: var(--ui-bg-hover); }
.ui-meter-link:focus-visible { outline: none; box-shadow: var(--ui-ring); }

/* Forced colours paint backgrounds away, which would leave an empty meter:
   the track gets an outline and the fill the system's text colour. */
@media (forced-colors: active) {
  .ui-meter__fill { background: CanvasText; forced-color-adjust: none; }
  .ui-meter__track { border: 1px solid CanvasText; }
}

.ui-sparkline { display: block; width: 100%; height: 1.5rem; overflow: visible; }

.ui-bars { display: grid; gap: 0.125rem; margin: 0; padding: 0; list-style: none; }
.ui-bars__row { display: grid; gap: 0.25rem; padding: 0.375rem 0.5rem; margin: 0 -0.5rem; color: var(--ui-text); text-decoration: none; border-radius: var(--ui-radius-md); }
.ui-bars__row--link:hover { background: var(--ui-bg-hover); }
.ui-bars__row--link:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-bars__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; font-size: var(--ui-text-sm); }
.ui-bars__name { display: flex; align-items: baseline; gap: 0.375rem; min-width: 0; }
/* Wraps rather than being cut off, as the meter's label does (1.4.10). */
.ui-bars__label { min-width: 0; overflow-wrap: anywhere; }
.ui-bars__note { flex-shrink: 0; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-bars__value { display: inline-flex; align-items: center; gap: 0.25rem; flex-shrink: 0; font-variant-numeric: tabular-nums; }
.ui-bars__chevron { color: var(--ui-text-muted); }
.ui-bars__track { display: block; height: 0.5rem; overflow: hidden; border-radius: var(--ui-radius-full); background: color-mix(in srgb, var(--ui-accent) 16%, var(--ui-bg-muted)); }
.ui-bars__fill { display: block; height: 100%; background: var(--ui-accent); border-radius: 0 var(--ui-radius-full) var(--ui-radius-full) 0; }

/* Forced colours paint backgrounds away, which would leave empty bars: the
   track gets an outline and the fill the system's text colour. */
@media (forced-colors: active) {
  .ui-bars__fill { background: CanvasText; forced-color-adjust: none; }
  .ui-bars__track { border: 1px solid CanvasText; }
}

.ui-chart {
  padding: var(--ui-card-pad);
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-card-border);
  border-radius: var(--ui-card-radius);
  box-shadow: var(--ui-card-shadow);
}
.ui-chart__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.ui-chart__value { font-family: var(--ui-font-head); font-size: var(--ui-text-lg); font-weight: var(--ui-heading-weight); letter-spacing: var(--ui-heading-tracking); font-variant-numeric: lining-nums tabular-nums; }
.ui-chart__caption { display: flex; justify-content: space-between; gap: 0.5rem; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-chart__caption:first-of-type { margin-top: 0.5rem; }
.ui-chart__plot { display: block; width: 100%; height: 5.5rem; margin: 0.25rem 0; }
.ui-chart__grid { stroke: var(--ui-border-strong); stroke-width: 1; }
.ui-chart__line { fill: none; stroke: var(--ui-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ui-chart__empty { margin: 0.5rem 0 0; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
/* The values behind the line, folded away under the plot. */
.ui-chart__values { margin-top: 0.5rem; font-size: var(--ui-text-sm); }
.ui-chart__values > summary { cursor: pointer; color: var(--ui-text-muted); border-radius: var(--ui-radius-sm); }
.ui-chart__values > summary:focus-visible { outline: 2px solid transparent; box-shadow: var(--ui-ring); }
.ui-chart__values[open] > summary { margin-bottom: 0.5rem; }

.ui-code { margin: 0; }
.ui-code__label { margin-bottom: 0.375rem; font-size: var(--ui-text-xs); font-weight: var(--ui-control-weight); color: var(--ui-text-muted); }
.ui-code__block {
  margin: 0;
  padding: 0.75rem 0.875rem;
  overflow: auto;
  font-family: var(--ui-font-mono);
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--ui-text);
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  tab-size: 4;
}
.ui-code__block:focus-visible { outline: none; box-shadow: var(--ui-ring); }
.ui-code__block--wrap { white-space: pre-wrap; overflow-wrap: anywhere; }

/* A head over the block: its name, its language, and its controls at the
   end (a copy button, a "Run" link), in the label's quiet type. */
.ui-code__head { display: flex; align-items: center; gap: 0.5rem; min-height: var(--ui-control-h-sm); margin-bottom: 0.375rem; }
.ui-code__head .ui-code__label { margin: 0; }
.ui-code__lang { font-family: var(--ui-font-mono); font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
.ui-code__actions { display: flex; align-items: center; gap: 0.375rem; margin-left: auto; }
.ui-code__label { font-size: var(--ui-text-xs); font-weight: var(--ui-control-weight); color: var(--ui-text-muted); }

/* Terminal. The screen's colours are the theme's; the script reads them
   from here and hands them to xterm.js, which draws its own canvas. */

.ui-terminal {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: var(--ui-space-sm);
  min-width: 0;
}
.ui-terminal__screen {
  height: var(--ui-terminal-height, 70vh);
  min-height: 10rem;
  padding: 0.5rem;
  overflow: hidden;
  font-family: var(--ui-font-mono);
  color: var(--ui-text);
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
}
.ui-terminal__screen:focus-within { border-color: var(--ui-ring-color); }
/* xterm sizes its viewport to the screen; its scrollbar takes the page's. */
.ui-terminal__screen .xterm,
.ui-terminal__screen .xterm-viewport { height: 100%; background: transparent !important; }

.ui-terminal--embedded { height: 100%; gap: 0; }
.ui-terminal--embedded .ui-terminal__screen { flex: 1; height: auto; min-height: 0; border: 0; border-radius: 0; }
.ui-terminal--embedded .ui-terminal__bar { padding: var(--ui-space-sm); }

.ui-terminal__bar { display: flex; align-items: center; gap: var(--ui-space-sm); }
.ui-terminal__bar > [data-ui-terminal-full] { margin-left: auto; }
/* How to leave the screen by keyboard: quiet, but there, as WCAG 2.1.2 asks. */
.ui-terminal__hint { margin: 0; font-size: var(--ui-text-xs); color: var(--ui-text-muted); }
/* Fullscreen keeps the line for screen readers (the screen is described by
   it) but gives the window its whole height. */
.ui-terminal--full .ui-terminal__hint { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
.ui-terminal__keys { display: none; flex-wrap: wrap; gap: 0.375rem; }
.ui-terminal__keys--always { display: flex; }
.ui-terminal__keys .ui-btn { min-width: 2.75rem; font-family: var(--ui-font-mono); }
@media (pointer: coarse) {
  .ui-terminal__keys { display: flex; }
  .ui-terminal__keys .ui-btn { height: 2.75rem; }
}

/* Fullscreen is this class, not the browser's mode, which would take
   Escape. dvh, so a phone's own bars and keyboard are not under it. */
.ui-terminal--full {
  position: fixed;
  inset: 0;
  z-index: 90;
  height: 100dvh;
  padding: 0;
  background: var(--ui-bg);
}
/* The window is the frame: no border, corners or inset around the screen,
   only enough padding that text does not touch the window's edge. */
.ui-terminal--full .ui-terminal__screen { flex: 1; height: auto; min-height: 0; padding: 0.25rem; border: 0; border-radius: 0; }
/* The key row, where it shows, keeps its own inset from the window edge. */
.ui-terminal--full .ui-terminal__bar { padding: var(--ui-space-sm); }

.ui-terminal__enter, .ui-terminal__leave { display: inline-flex; }
[aria-pressed="true"] > .ui-btn__icon > .ui-terminal__enter,
[aria-pressed="false"] > .ui-btn__icon > .ui-terminal__leave { display: none; }

/* In fullscreen the bar holds only the way back, unless a key row is shown:
   a whole row for one button would take a line from the terminal. So it
   floats over the screen's corner instead, quiet until it is pointed at.
   Where the key row shows (a touch screen, or `Keys::Always`) the button
   already shares that row and stays in it. */
@media not (pointer: coarse) {
  .ui-terminal--full .ui-terminal__bar:not(:has(.ui-terminal__keys--always)) {
    position: absolute;
    right: calc(var(--ui-space-sm) + 0.5rem);
    bottom: calc(var(--ui-space-sm) + 0.5rem);
    z-index: 1;
  }
  .ui-terminal--full .ui-terminal__bar:not(:has(.ui-terminal__keys--always)) [data-ui-terminal-full] {
    background: var(--ui-bg-card);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow-sm);
    opacity: 0.6;
  }
  .ui-terminal--full .ui-terminal__bar:not(:has(.ui-terminal__keys--always)) [data-ui-terminal-full]:is(:hover, :focus-visible) { opacity: 1; }
}
