/* Component kit. Reuse these before writing page-specific styles; colours come only from tokens.css.

   CLASS INDEX  (class → purpose; [base] = defined in base.css; [ui] = HTML built by a ui.js helper)
   Layout [base]   .app-main (= <main id="app">) .page (padded content-width wrapper) .page-reading (narrow)
                   .page-header (title row) .page-eyebrow .page-title .page-subtitle .page-actions .back-link
                   .section (vertical rhythm) .section-header .section-title .section-sub
                   .grid + .grid-3 (responsive cols) .grid-auto .stack/.stack-sm (vertical gap) .row (wrap row) .grow
   Text [base]     .text-2 .text-3 .bold .tnum (tabular numbers) .nowrap .mt-4 .sr-only
                   .hide-sm (<640 hidden) .show-sm (only <640) .hide-md (<1024) .show-md (only <1024)
                   .skip-link; html.scroll-locked [ui lockScroll]
   Shell           .splash .splash-mark .splash-text .app-header .app-header-inner .brand .brand-mark .brand-name
                   .app-nav .nav-link ([aria-current=page] = active) .header-actions .avatar-btn .avatar
   Buttons         .btn (neutral) .btn-primary .btn-secondary .btn-ghost .btn-danger .btn-link (text button)
                   .btn-sm .btn-lg .btn-icon (square; needs aria-label) .btn-block .is-loading (spinner, hides label)
   Cards           .card .card-pad .card-hover (lift on hover; use on a.card) .card-accent (accent-soft)
                   .card-header .card-title .card-sub .stretched-link (whole card clickable) .raise
                   .error-card [ui errorState]
   Icon tile       .icon-tile (accent; + -success/-warning/-neutral, .icon-tile-sm)
   Badge           .badge (+ .badge-accent/-success/-danger/-warning/-neutral, .badge-outline)  [ui badge]
   Chip            .chip (static meta pill); button.chip / a.chip (tappable); .chip-accent; .is-active or [aria-pressed=true]
   Callout         .callout (+ .callout-success) .callout-title .callout-body
   Disclosure      details.disclosure > summary (chevron rotates when open)
   Progress        .progress > .progress-fill (+ .progress-marker threshold line), .progress-success/-warning/-danger,
                   .progress-sm, .progress-head (label/value row above a bar)  [ui progressBar]
   Ring            .ring .ring-track .ring-fill .ring-label .ring-value .ring-sub (+ .ring-success/-warning/-danger) [ui ring]
   Stat tile       .stat-grid (2 → 4 cols) .stat .stat-label .stat-value (.is-empty for '—') .stat-unit .stat-sub .stat-seg
   Segmented       .segmented > button[aria-pressed] (or [aria-selected] / .is-active) .segmented-count
   Skeleton        .skeleton + .skeleton-text/-title/-heading/-value/-pill/-bar/-option/-chart/-circle  [ui skeleton]
   Empty state     .empty-state .empty-state-compact .empty-icon .empty-title .empty-body .empty-actions  [ui emptyState]
   List            .list (bordered, divided) .list-item (a/button = interactive)
                   .list-item-main .list-item-title .list-item-sub .list-item-meta
   Table           .table-wrap .table (th/td) .num (right-aligned tabular cell)
   Menu            .menu-wrap .menu (dropdown; toggle with hidden) .menu-header .menu-title .menu-sub .menu-item
                   (button[aria-pressed] = toggle, stays open; .menu-item-state for its On/Off) .menu-sep  [ui bindMenu]
   Toast           .toast-stack .toast-region .toast (+ .toast-success/-error; info is the default) .toast-icon .toast-msg .toast-close [ui toast]
   Dialog          dialog.dialog > form .dialog-body .dialog-icon(.dialog-icon-danger) .dialog-title .dialog-text
                   .dialog-actions  [ui confirmDialog]
   Sheet           dialog.sheet (bottom sheet < 640px, centred panel above) .sheet-handle .sheet-header .sheet-title
                   .sheet-body .sheet-footer  [ui openSheet]
   Forms           .input .input-group (leading .icon)
   Prose           .prose (renderMarkdown output; also .md-h, .md-table) .prose-sm (tighter spacing)
   Misc            .icon [ui icon] .kbd .spinner .legend .legend-item .legend-marker [ui markerKey]

   Z-order tokens: --z-sticky < --z-header < --z-fab < --z-menu < --z-panel < --z-toast; <dialog> uses the top layer.
   Pages with a sticky bottom bar on mobile set --fab-bottom on <html> so the tutor FAB clears it. */

/* ---- Icons --------------------------------------------------------------------- */
.icon { display: inline-block; vertical-align: -0.22em; flex-shrink: 0; max-width: none; } /* base caps svg at 100%; icons keep their size in narrow cells */

/* ---- Splash -------------------------------------------------------------------- */
.splash {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-6) max(var(--gutter), env(safe-area-inset-left, 0px));
  text-align: center;
}
.splash-mark {
  width: 56px; height: 56px;
  display: grid; place-items: center;
  border-radius: 16px;
  background: var(--accent); color: var(--on-accent);
  box-shadow: var(--shadow-md);
  animation: splash-breathe 1.8s var(--ease) infinite;
}
.splash-text { color: var(--text-2); font-size: var(--fs-sm); font-weight: 550; }
.splash .card { width: min(440px, 100%); text-align: left; }
@keyframes splash-breathe { 50% { transform: scale(1.05); box-shadow: var(--shadow-lg); } }

/* ---- App header ------------------------------------------------------------------ */
.app-header {
  position: sticky; top: 0; z-index: var(--z-header);
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--header-bg);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border);
}
.app-header-inner {
  height: var(--header-h);
  display: flex; align-items: center; gap: var(--sp-1);
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin-inline: auto;
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(calc(var(--gutter) - 6px), env(safe-area-inset-right, 0px));
}
.brand {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: var(--tap); padding-right: 6px; margin-right: var(--sp-2);
  border-radius: var(--btn-radius);
  color: var(--text); font-weight: 700; font-size: var(--fs-base); letter-spacing: -0.01em; white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: 9px;
  background: var(--accent); color: var(--on-accent);
  box-shadow: var(--shadow-sm), inset 0 0 0 1px rgba(255,255,255,.08);
}
@media (max-width: 399.98px) { .brand-name { display: none; } .brand { margin-right: var(--sp-1); } }

.app-nav { display: flex; align-items: center; gap: 2px; min-width: 0; }
.nav-link {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 0 12px;
  border-radius: var(--btn-radius);
  color: var(--text-2); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-link:hover { color: var(--text); background: var(--surface-2); text-decoration: none; }
.nav-link[aria-current="page"] { color: var(--accent-text); background: var(--accent-soft); }
@media (max-width: 479.98px) { .nav-link .icon { display: none; } .nav-link { padding: 0 11px; } }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 2px; flex: none; }

.avatar {
  width: 34px; height: 34px; flex: none;
  display: inline-grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--accent-soft); color: var(--accent-text);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .02em; line-height: 1;
  user-select: none;
}
.avatar-btn {
  width: var(--tap); height: var(--tap);
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
}
.avatar-btn:hover .avatar, .avatar-btn[aria-expanded="true"] .avatar { box-shadow: 0 0 0 2px var(--border-strong); }
.avatar-btn:focus-visible { box-shadow: none; }
.avatar-btn:focus-visible .avatar { box-shadow: var(--focus); }

@media (pointer: coarse) { .nav-link { min-height: var(--tap); } }

/* ---- Buttons ----------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--surface); --btn-fg: var(--text); --btn-border: var(--border-strong); --btn-bg-hover: var(--surface-2);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--tap); padding: 0 18px;
  border: 1px solid var(--btn-border); border-radius: var(--btn-radius);
  background: var(--btn-bg); color: var(--btn-fg);
  font-size: var(--fs-sm); font-weight: 600; line-height: 1.2; text-align: center;
  white-space: nowrap; text-decoration: none; user-select: none; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
/* Touch screens keep :hover after a tap, so hover fills only apply where hover is real. */
@media (hover: hover) {
  .btn:hover { background: var(--btn-bg-hover); }
  .btn:disabled:hover, .btn[aria-disabled="true"]:hover { background: var(--btn-bg); }
}
.btn:hover { text-decoration: none; }
.btn:active:not(:disabled):not([aria-disabled="true"]) { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.btn .icon { margin-inline: -2px; }

.btn-primary { --btn-bg: var(--accent); --btn-fg: var(--on-accent); --btn-border: transparent; --btn-bg-hover: var(--accent-hover); box-shadow: var(--shadow-sm); }
.btn-primary:focus-visible { box-shadow: var(--focus), var(--shadow-sm); } /* the shadow above would otherwise replace the base ring */
.btn-secondary { --btn-bg: var(--surface); --btn-fg: var(--text); --btn-border: var(--border-strong); --btn-bg-hover: var(--surface-2); }
.btn-ghost { --btn-bg: transparent; --btn-fg: var(--text-2); --btn-border: transparent; --btn-bg-hover: var(--surface-2); }
.btn-ghost:hover { color: var(--text); }
.btn-danger { --btn-bg: var(--danger); --btn-fg: var(--on-danger); --btn-border: transparent; --btn-bg-hover: color-mix(in srgb, var(--danger) 86%, var(--text)); }
.btn-ghost.btn-danger { --btn-bg: transparent; --btn-fg: var(--danger); --btn-bg-hover: var(--danger-soft); }
.btn-link {
  --btn-bg: transparent; --btn-bg-hover: transparent; --btn-border: transparent; --btn-fg: var(--accent);
  min-height: 36px; padding: 0 4px; border-radius: 6px;
}
.btn-link:hover { text-decoration: underline; text-underline-offset: 3px; }

.btn-sm { min-height: 36px; padding: 0 12px; gap: 6px; font-size: var(--fs-xs); border-radius: var(--radius-sm); }
.btn-lg { min-height: 52px; padding: 0 24px; font-size: var(--fs-base); border-radius: var(--radius); }
.btn-icon { width: var(--tap); padding: 0; }
.btn-icon.btn-sm { width: 36px; }
.btn-icon.btn-lg { width: 52px; }
.btn-block { display: flex; width: 100%; }
@media (pointer: coarse) {
  .btn-sm, .btn-link { min-height: var(--tap); }
  .btn-icon.btn-sm { width: var(--tap); }
}

.btn.is-loading { position: relative; color: transparent !important; pointer-events: none; }
.btn.is-loading > * { visibility: hidden; }
.btn.is-loading::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--btn-fg); border-right-color: transparent;
  animation: spin .7s linear infinite;
}

/* ---- Cards ------------------------------------------------------------------------- */
.card {
  position: relative;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
a.card { display: block; color: inherit; text-decoration: none; }
.card-pad { padding: var(--sp-5); }
@media (min-width: 768px) { .card-pad { padding: var(--sp-6); } }
.card-hover { transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); }
.card-hover:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.card-hover:active { transform: translateY(0); }
.card-accent {
  background: linear-gradient(var(--accent-soft), var(--accent-soft)), var(--surface);
  border-color: var(--accent-border);
}
.card-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.card-title { font-size: var(--fs-base); font-weight: 650; line-height: 1.35; letter-spacing: -0.005em; }
.card-sub { margin-top: 2px; font-size: var(--fs-sm); color: var(--text-2); }
.stretched-link::after { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit; }
.stretched-link:focus-visible { box-shadow: none; }
.stretched-link:focus-visible::after { box-shadow: var(--focus); border-radius: var(--radius-lg); }
.stretched-link:hover { text-decoration: none; }
.raise { position: relative; z-index: 1; }
.error-card { width: 100%; max-width: 560px; margin-inline: auto; }
.error-card .empty-icon { background: var(--danger-soft); color: var(--danger); }

/* ---- Icon tile ------------------------------------------------------------------- */
.icon-tile {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius);
  background: var(--accent-soft); color: var(--accent);
}
.icon-tile-sm { width: 32px; height: 32px; border-radius: 10px; }
.icon-tile-success { background: var(--success-soft); color: var(--success); }
.icon-tile-warning { background: var(--warning-soft); color: var(--warning); }
.icon-tile-neutral { background: var(--surface-2); color: var(--text-2); }

/* ---- Badge ------------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 9px;
  border-radius: var(--radius-pill);
  background: var(--surface-3); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.badge .icon { width: 14px; height: 14px; }
.badge-neutral { background: var(--surface-3); color: var(--text-2); }
.badge-accent { background: var(--accent-soft); color: var(--accent-text); }
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-danger { background: var(--danger-soft); color: var(--danger); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-outline { background: transparent; box-shadow: inset 0 0 0 1px var(--border-strong); }

/* ---- Chip -------------------------------------------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; min-height: 28px; padding: 3px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface-2); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 550; line-height: 1.3;
}
.chip .icon { width: 14px; height: 14px; }
button.chip, a.chip {
  min-height: 36px; padding: 6px 14px;
  background: var(--surface); border-color: var(--border-strong); color: var(--text);
  font-size: var(--fs-sm); text-align: left; text-decoration: none; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
@media (hover: hover) { button.chip:hover, a.chip:hover { background: var(--surface-2); } }
button.chip:hover, a.chip:hover { text-decoration: none; }
button.chip:disabled { opacity: .5; cursor: not-allowed; }
.chip-accent, button.chip-accent, a.chip-accent { background: var(--accent-soft); border-color: transparent; color: var(--accent-text); }
.chip.is-active, .chip[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent-text); }
@media (pointer: coarse) { button.chip, a.chip { min-height: var(--tap); } }

/* ---- Callout ----------------------------------------------------------------------- */
.callout {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: 14px 16px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); color: var(--text);
  font-size: var(--fs-sm);
}
.callout > .icon { color: var(--text-2); margin-top: 1px; }
.callout-title { font-weight: 650; }
.callout-body { color: var(--text-2); }
.callout-title + .callout-body { margin-top: 2px; }
.callout-success { background: var(--success-soft); border-color: color-mix(in srgb, var(--success) 30%, var(--border)); }
.callout-success > .icon { color: var(--success); }

/* ---- Disclosure ------------------------------------------------------------------ */
details.disclosure > summary {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--tap);
  list-style: none; cursor: pointer; user-select: none;
  border-radius: var(--radius-sm);
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::after {
  content: ""; width: 18px; height: 18px; margin-left: auto; flex: none;
  background: currentColor; color: var(--text-3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--dur) var(--ease);
}
details.disclosure[open] > summary::after { transform: rotate(180deg); }

/* ---- Progress bar ---------------------------------------------------------------- */
.progress {
  position: relative;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--track);
}
.progress-fill {
  display: block; height: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: width var(--dur-slow) var(--ease-out);
}
.progress-sm { height: 4px; }
.progress-success { --track: color-mix(in srgb, var(--success) 16%, transparent); }
.progress-success .progress-fill { background: var(--success); }
.progress-warning { --track: color-mix(in srgb, var(--warning) 18%, transparent); }
.progress-warning .progress-fill { background: var(--warning); }
.progress-danger { --track: color-mix(in srgb, var(--danger) 16%, transparent); }
.progress-danger .progress-fill { background: var(--danger); }
.progress-marker {
  position: absolute; top: -4px; bottom: -4px;
  width: 2px; margin-left: -1px;
  border-radius: 1px;
  background: var(--text-3);
  box-shadow: 0 0 0 2px var(--surface);
}
.progress-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3);
  margin-bottom: 6px;
  font-size: var(--fs-sm);
}
.progress-head > :first-child { min-width: 0; }
.progress-head > :last-child { flex: none; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* ---- Score ring -------------------------------------------------------------------- */
.ring {
  --ring-size: 132px;
  position: relative; flex: none;
  width: var(--ring-size); height: var(--ring-size);
  display: inline-grid; place-items: center;
}
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.ring-track { fill: none; stroke: var(--track); }
.ring-fill {
  fill: none; stroke: var(--accent); stroke-linecap: round;
  animation: ring-in 900ms var(--ease-out) both;
}
.ring-success { --track: color-mix(in srgb, var(--success) 16%, transparent); }
.ring-success .ring-fill { stroke: var(--success); }
.ring-warning { --track: color-mix(in srgb, var(--warning) 18%, transparent); }
.ring-warning .ring-fill { stroke: var(--warning); }
.ring-danger { --track: color-mix(in srgb, var(--danger) 16%, transparent); }
.ring-danger .ring-fill { stroke: var(--danger); }
.ring-label {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; line-height: 1.1;
}
.ring-value { font-size: calc(var(--ring-size) * .22); font-weight: 700; letter-spacing: -0.02em; color: var(--text); }
.ring-sub { margin-top: 4px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
@keyframes ring-in { from { stroke-dashoffset: var(--ring-c); } }

/* ---- Stat tiles -------------------------------------------------------------------- */
.stat-grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 900px) { .stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); } }
.stat {
  min-width: 0;
  display: flex; flex-direction: column; gap: 4px;
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
@media (min-width: 768px) { .stat { padding: var(--sp-5); } }
.stat-label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 550; color: var(--text-2); }
.stat-label .icon { width: 16px; height: 16px; color: var(--text-3); }
.stat-value { font-size: var(--fs-xl); font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; color: var(--text); overflow-wrap: anywhere; }
.stat-value.is-empty { color: var(--text-3); font-weight: 500; }
@media (min-width: 640px) { .stat-value { font-size: var(--fs-2xl); } }
.stat-unit { margin-left: 2px; font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0; color: var(--text-3); }
.stat-sub { font-size: var(--fs-xs); color: var(--text-3); }
/* One segment of a sub-line ("47/60", "Mock Exam 7"): wraps as a unit instead of mid-name. */
.stat-seg { display: inline-block; max-width: 100%; }

/* ---- Segmented control ------------------------------------------------------------- */
.segmented {
  display: inline-flex; gap: 2px; align-self: flex-start;
  max-width: 100%; padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow-x: auto; scrollbar-width: none;
}
.segmented::-webkit-scrollbar { display: none; }
.segmented > button, .segmented > a {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex: 1 0 auto;
  min-height: 36px; padding: 0 14px;
  border-radius: 9px;
  color: var(--text-2); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.segmented > :hover { color: var(--text); text-decoration: none; }
.segmented > [aria-pressed="true"], .segmented > [aria-selected="true"], .segmented > .is-active {
  background: var(--surface); color: var(--text);
  box-shadow: var(--shadow-sm), 0 0 0 1px var(--border);
}
.segmented > :focus-visible { position: relative; z-index: 1; } /* ring paints over the neighbouring segment */
.segmented > [aria-pressed="true"]:focus-visible, .segmented > [aria-selected="true"]:focus-visible, .segmented > .is-active:focus-visible { box-shadow: var(--focus); }
.segmented-count {
  min-width: 22px; padding: 2px 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-3); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; text-align: center;
}
@media (max-width: 479.98px) {
  .segmented > button, .segmented > a { padding: 0 10px; gap: 5px; }
  .segmented-count { padding: 2px 5px; min-width: 20px; }
}
@media (pointer: coarse) { .segmented > button, .segmented > a { min-height: var(--tap); } }

/* ---- Skeletons --------------------------------------------------------------------- */
.skeleton {
  position: relative; overflow: hidden;
  background: var(--surface-3);
  border-radius: 6px;
}
.skeleton::after {
  content: ""; position: absolute; inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--shimmer), transparent);
  animation: shimmer 1.4s ease-in-out infinite;
}
.skeleton-text { height: 12px; margin: 8px 0; }
.skeleton-title { height: 28px; margin-bottom: 12px; border-radius: var(--radius-sm); }
.skeleton-heading { height: 18px; margin: 4px 0 16px; }
.skeleton-value { height: 28px; margin-top: 2px; }
.skeleton-pill { height: 22px; border-radius: var(--radius-pill); }
.skeleton-bar { height: 8px; border-radius: var(--radius-pill); }
.skeleton-option { height: 58px; border-radius: var(--radius); }
.skeleton-chart { height: 220px; border-radius: var(--radius); }
.skeleton-circle { border-radius: 50%; }
@keyframes shimmer { to { transform: translateX(100%); } }

/* ---- Empty state ------------------------------------------------------------------- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-10) var(--sp-5);
  text-align: center;
}
.empty-state-compact { padding: var(--sp-6) var(--sp-4); }
.empty-icon {
  width: 48px; height: 48px; margin-bottom: var(--sp-2);
  display: grid; place-items: center;
  border-radius: 14px;
  background: var(--accent-soft); color: var(--accent);
}
.empty-title { font-size: var(--fs-lg); font-weight: 650; }
.empty-body { max-width: 46ch; color: var(--text-2); font-size: var(--fs-sm); }
.empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); margin-top: var(--sp-3); }

/* ---- List -------------------------------------------------------------------------- */
.list {
  margin: 0; padding: 0; list-style: none;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.list > li { list-style: none; }
.list > * + * { border-top: 1px solid var(--border); }
.list-item {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; min-height: 56px; padding: 12px 16px;
  color: inherit; text-align: left; text-decoration: none;
}
a.list-item, button.list-item { cursor: pointer; transition: background-color var(--dur-fast) var(--ease); }
@media (hover: hover) { a.list-item:hover, button.list-item:hover { background: var(--surface-2); } }
a.list-item:hover, button.list-item:hover { text-decoration: none; }
a.list-item:focus-visible, button.list-item:focus-visible { box-shadow: none; outline: 2px solid var(--accent); outline-offset: -2px; }
.list-item-main { flex: 1 1 auto; min-width: 0; }
.list-item-title { font-weight: 600; color: var(--text); line-height: 1.35; }
.list-item-sub { margin-top: 2px; font-size: var(--fs-sm); color: var(--text-2); }
.list-item-meta {
  flex: none;
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--text-2); font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
}
.list-item > .icon:last-child { color: var(--text-3); }

/* ---- Table ------------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  -webkit-overflow-scrolling: touch;
}
.table { width: 100%; font-size: var(--fs-sm); }
.table th {
  padding: 10px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  color: var(--text-2); font-size: var(--fs-xs); font-weight: 600; text-align: left; white-space: nowrap;
}
.table td { padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background-color var(--dur-fast) var(--ease); }
@media (hover: hover) { .table tbody tr:hover { background: var(--surface-2); } }
.table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ---- Menu (dropdown) ----------------------------------------------------------------- */
.menu-wrap { position: relative; }
.menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: var(--z-menu);
  min-width: 232px; max-width: min(320px, calc(100vw - 24px));
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  transform-origin: top right;
  animation: menu-in var(--dur) var(--ease-out);
}
.menu-header { padding: 10px 10px 8px; min-width: 0; }
.menu-title { font-weight: 650; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-sub { font-size: var(--fs-xs); color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-sep { height: 1px; margin: 6px -6px; background: var(--border); }
.menu-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 40px; padding: 0 10px;
  border-radius: var(--radius-sm);
  color: var(--text); font-size: var(--fs-sm); font-weight: 550; text-align: left; text-decoration: none;
}
.menu-item .icon { color: var(--text-2); }
.menu-item-state { margin-left: auto; font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); }
.menu-item[aria-pressed="true"] .menu-item-state { color: var(--accent-text); }
.menu-item:hover, .menu-item:focus-visible { background: var(--surface-2); text-decoration: none; box-shadow: none; }
.menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (pointer: coarse) { .menu-item { min-height: var(--tap); } }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px) scale(.98); } }

/* ---- Toasts ------------------------------------------------------------------------ */
.toast-stack {
  position: fixed; z-index: var(--z-toast);
  left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  width: min(420px, calc(100vw - 32px));
  display: flex; flex-direction: column; gap: var(--sp-2);
  pointer-events: none;
}
.toast-region { display: flex; flex-direction: column; gap: var(--sp-2); }
@media (max-width: 639.98px) {
  .toast-stack { bottom: auto; top: calc(var(--header-h) + env(safe-area-inset-top, 0px) + 8px); }
}
.toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 8px 12px 14px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-sm); line-height: 1.45;
  animation: toast-in var(--dur-slow) var(--ease-out);
}
.toast-icon { display: flex; color: var(--accent); }
.toast-success .toast-icon { color: var(--success); }
.toast-error { border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }
.toast-error .toast-icon { color: var(--danger); }
.toast-msg { flex: 1 1 auto; min-width: 0; padding-top: 1px; }
.toast-close {
  flex: none; width: 30px; height: 30px; margin: -4px 0;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  color: var(--text-3);
}
.toast-close:hover { background: var(--surface-2); color: var(--text); }
@media (pointer: coarse) { .toast-close { width: 40px; height: 40px; margin: -9px -2px -9px 0; } }
.toast.is-leaving { animation: toast-out 180ms var(--ease) forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
@keyframes toast-out { to { opacity: 0; transform: scale(.97); } }

/* ---- Dialog ------------------------------------------------------------------------ */
dialog.dialog {
  width: min(440px, calc(100vw - 32px));
  max-width: none;
  max-height: calc(100dvh - 48px);
  margin: auto;
  padding: 0;
  overflow: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
dialog.dialog[open] { animation: dialog-in var(--dur-slow) var(--ease-out); }
dialog.dialog::backdrop, dialog.sheet::backdrop {
  background: var(--overlay, rgba(15, 23, 42, .45));
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  animation: fade-in var(--dur, 180ms) ease;
}
.dialog-body { padding: var(--sp-6) var(--sp-6) var(--sp-2); }
.dialog-icon {
  width: 44px; height: 44px; margin-bottom: var(--sp-4);
  display: grid; place-items: center;
  border-radius: var(--radius);
  background: var(--accent-soft); color: var(--accent);
}
.dialog-icon-danger { background: var(--danger-soft); color: var(--danger); }
.dialog-title { font-size: var(--fs-lg); font-weight: 650; }
.dialog-text { margin-top: var(--sp-2); color: var(--text-2); }
.dialog-text > * + * { margin-top: var(--sp-2); }
.dialog-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--sp-2); padding: var(--sp-4) var(--sp-6) var(--sp-6); }
@media (max-width: 479.98px) {
  .dialog-actions { flex-direction: column-reverse; }
  .dialog-actions .btn { width: 100%; }
}
@keyframes dialog-in { from { opacity: 0; transform: translateY(8px) scale(.97); } }

/* ---- Bottom sheet ------------------------------------------------------------------- */
dialog.sheet {
  width: 100%; max-width: none;
  max-height: 85vh; max-height: 85dvh;
  margin: auto 0 0;
  padding: 0 0 env(safe-area-inset-bottom, 0px);
  background: var(--surface); color: var(--text);
  border: 0; border-radius: 20px 20px 0 0;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
dialog.sheet[open] { display: flex; flex-direction: column; animation: sheet-in var(--dur-slow) var(--ease-out); }
.sheet-handle { flex: none; width: 36px; height: 4px; margin: 8px auto 0; border-radius: var(--radius-pill); background: var(--border-strong); }
.sheet-header {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: 6px 10px 10px 20px;
  border-bottom: 1px solid var(--border);
}
.sheet-title { font-size: var(--fs-base); font-weight: 650; }
.sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: var(--sp-4) var(--sp-5) var(--sp-5); }
.sheet-footer { flex: none; display: flex; gap: var(--sp-2); padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--border); }
@keyframes sheet-in { from { transform: translateY(100%); } }
@media (min-width: 640px) {
  dialog.sheet {
    width: min(520px, calc(100vw - 48px));
    max-height: min(720px, calc(100dvh - 64px));
    margin: auto;
    padding-bottom: 0;
    border: 1px solid var(--border); border-radius: var(--radius-lg);
  }
  dialog.sheet[open] { animation-name: dialog-in; }
  .sheet-handle { display: none; }
  .sheet-header { padding: 12px 12px 12px 24px; }
  .sheet-body { padding: var(--sp-5) var(--sp-6) var(--sp-6); }
}

/* ---- Forms ------------------------------------------------------------------------- */
.input {
  width: 100%; min-height: var(--tap);
  padding: 10px 12px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--btn-radius);
  font-size: var(--fs-base); line-height: 1.4; /* 16px stops iOS zooming on focus */
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.input::placeholder { color: var(--text-3); opacity: 1; }
.input:hover { border-color: color-mix(in srgb, var(--text-3) 60%, var(--border-strong)); }
.input:focus { border-color: var(--accent); box-shadow: var(--focus); }
.input[aria-invalid="true"] { border-color: var(--danger); }
.input-group { position: relative; }
.input-group > .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-3); pointer-events: none; }
.input-group > .input { padding-left: 40px; }
input[type="checkbox"], input[type="radio"], progress { accent-color: var(--accent); }

/* ---- Prose (renderMarkdown output) -------------------------------------------------- */
.prose { line-height: 1.6; color: var(--text); overflow-wrap: break-word; }
.prose > * + * { margin-top: .75em; }
.prose ul, .prose ol { padding-left: 1.35em; }
.prose li + li { margin-top: .3em; }
.prose li > ul, .prose li > ol, .prose li > p + * { margin-top: .3em; }
.prose li > p + p { margin-top: .5em; }
.prose li::marker { color: var(--text-3); }
.prose ol > li::marker { font-variant-numeric: tabular-nums; }
.prose blockquote { padding: 2px 0 2px 14px; border-left: 3px solid var(--border-strong); color: var(--text-2); }
.prose blockquote > * + * { margin-top: .5em; }
.prose .md-h { font-size: 1em; font-weight: 650; letter-spacing: 0; }
.prose * + .md-h { margin-top: 1.1em; }
.prose a { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); text-underline-offset: 2px; }
.prose a:hover { text-decoration-color: currentColor; }
.prose hr { margin: 1.1em 0; }
.prose pre { font-size: var(--fs-xs); }
.prose .md-table { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.prose table { width: 100%; font-size: .9375em; }
.prose th, .prose td { padding: 6px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
.prose th { background: var(--surface-2); font-weight: 600; }
.prose tr:last-child td { border-bottom: 0; }
.prose-sm { line-height: 1.55; }
.prose-sm > * + * { margin-top: .6em; }

/* ---- Misc -------------------------------------------------------------------------- */
.kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  background: var(--surface); color: var(--text-2);
  border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: 6px;
  font-family: var(--mono); font-size: 12px; font-weight: 600; line-height: 1;
}
.spinner {
  display: inline-block; flex: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 22%, transparent);
  border-top-color: currentColor;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); color: var(--text-2); font-size: var(--fs-xs); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-marker { flex: none; width: 2px; height: 12px; border-radius: 1px; background: var(--text-3); }
