/* Uhambo Atlas Academy — unified experience layer stylesheet.
   House CSP is default-src 'self' / style-src 'self': ALL styling lives here.
   No inline style= attributes anywhere in the pages.

   ============================================================
   TENANT THEME HOOK (§12 white-label)
   ------------------------------------------------------------
   Every colour, radius and type decision below reads from the
   custom properties in this single :root block. A tenant theme
   is a later stylesheet that re-declares any subset of these
   tokens (e.g. web/tenant/<slug>.css) — no other selector in
   this file needs to change for a full re-brand.
   ============================================================ */
:root {
  /* ground + ink */
  --uaa-paper: #FAF8F4;
  --uaa-surface: #FFFFFF;
  --uaa-surface-2: #F3EFE7;
  --uaa-ink: #26221C;
  --uaa-ink-soft: #6B6254;
  --uaa-line: #E5DFD2;
  /* Brand accent — the oxblood of the logo, measured off the artwork
     (web/site/brand/logo-source.jpg): the ACADEMY stroke core is #5D1B1B.
     It replaced a burnt copper that clashed with the mark AND failed contrast:
     #B4651E scored 4.11:1 on the paper ground, under the 4.5 minimum for text.
     This scores 12.09:1. --uaa-amber below is SEMANTIC (warning) and stays amber;
     collapsing it into the brand colour would destroy the signal. */
  --uaa-accent: #5D1B1B;
  --uaa-accent-soft: #EAE2DE;
  --uaa-on-accent: #FFFFFF;
  /* semantic compliance states */
  --uaa-pass: #2E7D46;
  --uaa-pass-bg: #E2F0E6;
  --uaa-amber: #A26E0A;
  --uaa-amber-bg: #F7ECD4;
  --uaa-fail: #B3261E;
  --uaa-fail-bg: #F9E2E0;
  /* shape + type */
  --uaa-radius: 10px;
  --uaa-radius-sm: 6px;
  --uaa-shadow: 0 1px 2px rgba(38, 34, 28, 0.06), 0 4px 14px rgba(38, 34, 28, 0.05);
  --uaa-font: "Avenir Next", Avenir, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --uaa-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --uaa-paper: #191611;
    --uaa-surface: #221E17;
    --uaa-surface-2: #2B261D;
    --uaa-ink: #F0EAE0;
    --uaa-ink-soft: #A79C8A;
    --uaa-line: #3A342A;
    /* Lifted for the dark ground: 5.34:1 on #221E17. Same hue, not a new colour. */
    --uaa-accent: #D07B72;
    --uaa-accent-soft: #341D18;
    --uaa-on-accent: #191611;
    --uaa-pass: #6FBF88;
    --uaa-pass-bg: #1E3226;
    --uaa-amber: #D9AC4E;
    --uaa-amber-bg: #383019;
    --uaa-fail: #E5867F;
    --uaa-fail-bg: #3D211F;
    --uaa-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.3);
  }
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { font-size: 16px; }
body {
  margin: 0;
  background: var(--uaa-paper);
  color: var(--uaa-ink);
  font-family: var(--uaa-font);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--uaa-accent); text-decoration: none; }
a:hover, a:focus { text-decoration: underline; }

/* iOS 12 REACH (see scripts/lint-legacy-css.mjs)
   `:focus-visible` is Safari 15.4+ / Chrome 86+. On an iOS 12-class device the
   whole ring disappears — a control with no visible focus state. Plain `:focus`
   is supported everywhere back to Safari 3, so it is the baseline here. The cost
   is that pointer users also see the ring on click; a missing ring on a learner's
   phone is the worse of the two failures. */
:focus { outline: 2px solid var(--uaa-accent); outline-offset: 2px; }

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--uaa-accent);
  color: var(--uaa-on-accent);
  padding: 0.5rem 1rem;
  border-radius: var(--uaa-radius-sm);
  z-index: 10;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

/* ---------- shell ----------
   iOS 12 REACH: flexbox `gap` is Safari 14.5+. Every flex row in this file spaces
   its children with margins instead. Two patterns are used:
     * single-line rows  -> `> * + * { margin-left: G }`  (exact, no outdent)
     * wrapping rows     -> container `margin: -G/2` + children `margin: G/2`
       (the negative-margin wrapper: reproduces BOTH the column and the row gap and
       keeps the container's outer box identical).
   Grid `gap` is untouched — it shipped in Safari 10.1 and is safe. */
.site-header {
  display: flex;
  align-items: center;
  padding: 0.85rem 1.5rem;
  background: var(--uaa-surface);
  border-bottom: 1px solid var(--uaa-line);
  position: sticky;
  top: 0;
  z-index: 5;
}
.site-header > * + * { margin-left: 1.5rem; }
.wordmark {
  font-weight: 700;
  letter-spacing: 0.14em;
  font-size: 0.95rem;
  white-space: nowrap;
  color: var(--uaa-ink);
}
.wordmark .wm-academy { color: var(--uaa-accent); }
/* Wrapping row: negative-margin wrapper. The -0.5rem block margins cancel the
   children's 0.5rem exactly, so the nav's margin box is the same height it was
   under `gap` and `align-items: center` still centres it in the header. The
   left margin is 1.5rem (header step) − 0.5rem (child outdent) = 1rem. */
.site-nav { display: flex; flex-wrap: wrap; margin: -0.5rem; }
.site-nav > * { margin: 0.5rem; }
.site-header > .site-nav { margin-left: 1rem; }
.site-nav a {
  color: var(--uaa-ink-soft);
  padding: 0.25rem 0.5rem;
  border-radius: var(--uaa-radius-sm);
  font-size: 0.9rem;
}
.site-nav a[aria-current="page"] {
  color: var(--uaa-accent);
  background: var(--uaa-accent-soft);
  font-weight: 600;
}
.header-spacer { flex: 1; }
.session-chip {
  font-size: 0.8rem;
  color: var(--uaa-ink-soft);
  border: 1px solid var(--uaa-line);
  border-radius: 999px;
  padding: 0.2rem 0.75rem;
  max-width: 18rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

main { max-width: 78rem; margin: 0 auto; padding: 1.5rem; }
.page-title { font-size: 1.5rem; margin: 0 0 0.25rem; }
.page-sub { color: var(--uaa-ink-soft); margin: 0 0 1.5rem; font-size: 0.95rem; }

.site-footer {
  max-width: 78rem;
  margin: 2rem auto 0;
  padding: 1rem 1.5rem 2rem;
  color: var(--uaa-ink-soft);
  font-size: 0.8rem;
  border-top: 1px solid var(--uaa-line);
}

/* ---------- cards + grid ---------- */
.grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(12, 1fr); }
.card {
  grid-column: span 12;
  background: var(--uaa-surface);
  border: 1px solid var(--uaa-line);
  border-radius: var(--uaa-radius);
  box-shadow: var(--uaa-shadow);
  padding: 1.1rem 1.25rem;
}
@media (min-width: 860px) {
  .card.half { grid-column: span 6; }
  .card.third { grid-column: span 4; }
  .card.two-thirds { grid-column: span 8; }
}
.card > h2 {
  margin: 0 0 0.2rem;
  font-size: 1.02rem;
  display: flex;
  align-items: baseline;
}
.card > h2 > * + * { margin-left: 0.5rem; }
.card-hint { color: var(--uaa-ink-soft); font-size: 0.82rem; margin: 0 0 0.85rem; }

/* ---------- KPI strip ---------- */
.kpi-strip {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  margin-bottom: 1.25rem;
}
.kpi {
  background: var(--uaa-surface);
  border: 1px solid var(--uaa-line);
  border-left: 4px solid var(--uaa-accent);
  border-radius: var(--uaa-radius);
  padding: 0.8rem 1rem;
}
.kpi .kpi-value {
  font-size: 1.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.kpi .kpi-label { color: var(--uaa-ink-soft); font-size: 0.78rem; letter-spacing: 0.04em; text-transform: uppercase; }
.kpi.kpi-pass { border-left-color: var(--uaa-pass); }
.kpi.kpi-amber { border-left-color: var(--uaa-amber); }
.kpi.kpi-fail { border-left-color: var(--uaa-fail); }

/* ---------- badges (compliance states) ---------- */
.badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  padding: 0.12rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
  border: 1px solid transparent;
}
.badge-pass { background: var(--uaa-pass-bg); color: var(--uaa-pass); border-color: var(--uaa-pass); }
.badge-amber { background: var(--uaa-amber-bg); color: var(--uaa-amber); border-color: var(--uaa-amber); }
.badge-fail { background: var(--uaa-fail-bg); color: var(--uaa-fail); border-color: var(--uaa-fail); }
.badge-neutral { background: var(--uaa-surface-2); color: var(--uaa-ink-soft); border-color: var(--uaa-line); }
.badge-accent { background: var(--uaa-accent-soft); color: var(--uaa-accent); border-color: var(--uaa-accent); }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.88rem; }
caption { text-align: left; color: var(--uaa-ink-soft); font-size: 0.8rem; padding-bottom: 0.4rem; }
th, td { text-align: left; padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--uaa-line); vertical-align: top; }
th { color: var(--uaa-ink-soft); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.06em; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tbody tr:hover { background: var(--uaa-surface-2); }

/* ---------- meters / progress ---------- */
.meter {
  background: var(--uaa-surface-2);
  border: 1px solid var(--uaa-line);
  border-radius: 999px;
  height: 0.6rem;
  overflow: hidden;
  min-width: 6rem;
}
.meter > span { display: block; height: 100%; background: var(--uaa-accent); border-radius: 999px; }
.meter.meter-pass > span { background: var(--uaa-pass); }
.meter.meter-amber > span { background: var(--uaa-amber); }
.meter.meter-fail > span { background: var(--uaa-fail); }
.meter-row { display: flex; align-items: center; margin: 0.35rem 0; }
.meter-row > * + * { margin-left: 0.6rem; }
.meter-row .meter { flex: 1; }
.meter-row .meter-label { min-width: 9rem; font-size: 0.85rem; }
.meter-row .meter-value { font-variant-numeric: tabular-nums; font-size: 0.85rem; min-width: 3.5rem; text-align: right; }

/* ---------- forms + buttons ---------- */
label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 0.2rem; }
input, select, textarea {
  font: inherit;
  color: var(--uaa-ink);
  background: var(--uaa-surface);
  border: 1px solid var(--uaa-line);
  border-radius: var(--uaa-radius-sm);
  padding: 0.45rem 0.6rem;
  width: 100%;
}
input:focus, select:focus, textarea:focus { border-color: var(--uaa-accent); outline: none; }
.field { margin-bottom: 0.85rem; }
/* Wrapping row. Only the inline axis needs a wrapper here: the children are
   `.field`s, which already carry their own 0.85rem block margin, so wrapped
   rows stay separated without a block-axis compensation. */
.field-row { display: flex; flex-wrap: wrap; margin-left: -0.375rem; margin-right: -0.375rem; }
.field-row > * { margin-left: 0.375rem; margin-right: 0.375rem; }
.field-row .field { flex: 1; min-width: 9rem; }

.btn {
  font: inherit;
  font-weight: 600;
  border: 1px solid var(--uaa-line);
  background: var(--uaa-surface);
  color: var(--uaa-ink);
  border-radius: var(--uaa-radius-sm);
  padding: 0.5rem 1rem;
  cursor: pointer;
}
.btn:hover { border-color: var(--uaa-accent); color: var(--uaa-accent); }
.btn-primary { background: var(--uaa-accent); border-color: var(--uaa-accent); color: var(--uaa-on-accent); }
.btn-primary:hover { filter: brightness(1.08); color: var(--uaa-on-accent); }
.btn-danger { background: var(--uaa-fail); border-color: var(--uaa-fail); color: #fff; }
.btn-ghost { background: transparent; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Wrapping row. The row gap is carried entirely on the children's BLOCK-END
   margin, never the block-start one: a block-start margin on the children would
   sit below the container's collapsed margin and push the row down (adjacent
   siblings collapse, so a reduced positive container margin cannot absorb it —
   `max(0.85rem, 0.2rem)` is still 0.85rem). Block-end only is exact whatever the
   neighbours declare. The container keeps its original 0.5rem block-start margin
   and gives back the 0.6rem the children add at the bottom. */
.btn-row { display: flex; flex-wrap: wrap; margin: 0.5rem -0.3rem -0.6rem; }
.btn-row > * { margin: 0 0.3rem 0.6rem; }

/* ---------- empty / status states ---------- */
.empty-state {
  border: 1px dashed var(--uaa-line);
  border-radius: var(--uaa-radius);
  background: var(--uaa-surface-2);
  color: var(--uaa-ink-soft);
  padding: 1.1rem;
  text-align: center;
  font-size: 0.88rem;
}
.empty-state strong { display: block; color: var(--uaa-ink); margin-bottom: 0.2rem; }
.status-line { font-size: 0.85rem; margin-top: 0.5rem; min-height: 1.2rem; }
.status-line.is-error { color: var(--uaa-fail); }
.status-line.is-ok { color: var(--uaa-pass); }

/* ---------- landing / login ---------- */
.hero { padding: 3rem 0 1.5rem; max-width: 44rem; }
.hero h1 { font-size: 2rem; margin: 0 0 0.5rem; }
.hero .accent-rule { width: 4.5rem; height: 4px; background: var(--uaa-accent); border-radius: 2px; margin: 1rem 0; }
.hero p { color: var(--uaa-ink-soft); font-size: 1.05rem; }
.login-panel { max-width: 26rem; }
.pillar-list { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); padding: 0; margin: 1.5rem 0 0; list-style: none; }
.pillar-list li {
  background: var(--uaa-surface);
  border: 1px solid var(--uaa-line);
  border-radius: var(--uaa-radius);
  padding: 0.9rem 1rem;
  font-size: 0.9rem;
}
.pillar-list li strong { display: block; margin-bottom: 0.2rem; }

/* ---------- chips / definition rows ---------- */
.chip-row { display: flex; flex-wrap: wrap; margin: 0.4rem -0.2rem 0; }
.chip-row > * { margin: 0 0.2rem 0.4rem; }
.chip {
  background: var(--uaa-surface-2);
  border: 1px solid var(--uaa-line);
  border-radius: 999px;
  font-size: 0.78rem;
  padding: 0.15rem 0.6rem;
  font-variant-numeric: tabular-nums;
}
.def-list { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 1rem; font-size: 0.88rem; }
.def-list dt { color: var(--uaa-ink-soft); }
.def-list dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ---------- assessor stepper ---------- */
.stepper { display: flex; flex-wrap: wrap; margin: 0 -0.25rem 0.75rem; padding: 0; list-style: none; counter-reset: step; }
.stepper > li { margin: 0 0.25rem 0.5rem; }
.stepper li {
  counter-increment: step;
  display: flex;
  align-items: center;
  font-size: 0.82rem;
  color: var(--uaa-ink-soft);
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--uaa-line);
  border-radius: 999px;
  background: var(--uaa-surface);
}
.stepper li::before {
  content: counter(step);
  display: inline-grid;
  place-items: center;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: var(--uaa-surface-2);
  color: var(--uaa-ink-soft);
  font-weight: 700;
  font-size: 0.72rem;
  /* stands in for the removed `gap: 0.45rem` — the ::before counter and the
     step label are the only two flex items in the li. */
  margin-right: 0.45rem;
}
.stepper li.is-active { border-color: var(--uaa-accent); color: var(--uaa-accent); font-weight: 600; }
.stepper li.is-active::before { background: var(--uaa-accent); color: var(--uaa-on-accent); }
.stepper li.is-done { color: var(--uaa-pass); border-color: var(--uaa-pass); }
.stepper li.is-done::before { background: var(--uaa-pass); color: #fff; content: "\2713"; }

.step-panel[hidden] { display: none; }
.qr-frame {
  border: 2px dashed var(--uaa-accent);
  border-radius: var(--uaa-radius);
  background: var(--uaa-accent-soft);
  padding: 1.25rem;
  text-align: center;
  font-size: 0.85rem;
  color: var(--uaa-ink-soft);
  margin-bottom: 0.85rem;
}
.criterion-list { list-style: none; margin: 0; padding: 0; }
.criterion-list li {
  display: flex;
  align-items: flex-start;
  padding: 0.55rem 0.2rem;
  border-bottom: 1px solid var(--uaa-line);
  font-size: 0.9rem;
}
.criterion-list li > * + * { margin-left: 0.6rem; }
.criterion-list li .crit-id { font-family: var(--uaa-mono); font-size: 0.75rem; color: var(--uaa-ink-soft); min-width: 5.5rem; }
.criterion-list input[type="checkbox"] { width: 1.1rem; height: 1.1rem; margin-top: 0.15rem; }
.verdict-toggle { display: flex; }
.verdict-toggle > * + * { margin-left: 0.75rem; }
.verdict-toggle label {
  flex: 1;
  border: 1px solid var(--uaa-line);
  border-radius: var(--uaa-radius);
  padding: 0.8rem;
  text-align: center;
  cursor: pointer;
  font-weight: 600;
  /* clips the checked radio's spread shadow to this tile — see below */
  position: relative;
  overflow: hidden;
}
.verdict-toggle input { width: auto; margin-right: 0.4rem; accent-color: var(--uaa-accent); }

/* iOS 12 REACH: `:has()` is Safari 15.4+, and there is no other parent selector.
   The markup is `<label><input type="radio">Competent</label>` — the label text is
   an anonymous text node, so there is no element sibling to hang the state on.
   Instead the checked radio paints the tile itself: a spread box-shadow large
   enough to cover any tile, clipped by the label's `overflow: hidden` to the
   rounded padding box. The radio is inline content that precedes the text, so its
   shadow paints beneath the label text, not over it. Supported since Safari 5.1.
   Known, deliberate difference from the `:has()` version: the tile's 1px border
   stays --uaa-line instead of turning accent. The accent-soft fill is the load-
   bearing signal and it is reproduced exactly; the radio dot is also kept, which
   the alternative (an absolutely-positioned appearance:none overlay) would lose. */
.verdict-toggle input:checked { box-shadow: 0 0 0 100vmax var(--uaa-accent-soft); }

/* `input:focus` below sets `outline: none` for text fields; radios and checkboxes
   have no border to recolour, so they need the ring restored explicitly. */
input[type="checkbox"]:focus, input[type="radio"]:focus {
  outline: 2px solid var(--uaa-accent);
  outline-offset: 2px;
}

.sig-pad {
  border: 1px solid var(--uaa-line);
  border-radius: var(--uaa-radius);
  background: var(--uaa-surface);
  width: 100%;
  height: 9rem;
  touch-action: none;
  display: block;
}
.queue-list { list-style: none; margin: 0; padding: 0; font-size: 0.88rem; }
.queue-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.2rem;
  border-bottom: 1px solid var(--uaa-line);
}
.queue-list li > * + * { margin-left: 0.6rem; }

/* ---------- misc ---------- */
.mono { font-family: var(--uaa-mono); font-size: 0.82em; }
.tnum { font-variant-numeric: tabular-nums; }
.muted { color: var(--uaa-ink-soft); }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   TENANT ADMINISTRATION (tenant-admin.html)
   ------------------------------------------------------------
   Forms, findings and the branding preview. The preview reads
   its colours from --tp-* custom properties that tenant-admin.js
   sets on the container from the RESOLVED theme the server
   returned — not from the form fields, so what is shown is what
   a learner will actually get, defaults and all.

   No `gap` in any flex container here: gate G6 holds the floor
   at iOS 12 / Android 23, where flex-gap is unsupported and
   silently collapses the layout. Margins do the spacing.
   ============================================================ */

.form-grid {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -0.5rem;
}
.form-grid .field,
.form-inline .field {
  flex: 1 1 14rem;
  margin: 0 0.5rem 1rem;
  display: block;
}
.form-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  margin: 0 -0.5rem 1rem;
}
.form-inline .btn { margin: 0 0.5rem 1rem; }

.field label {
  display: block;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--uaa-ink-soft);
  margin-bottom: 0.3rem;
}
.field-hint {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--uaa-ink-soft);
}
.field input,
.field select {
  width: 100%;
  box-sizing: border-box;
  padding: 0.5rem 0.6rem;
  font: inherit;
  color: var(--uaa-ink);
  background: var(--uaa-surface);
  border: 1px solid var(--uaa-line);
  border-radius: 4px;
}
.field input:focus,
.field select:focus {
  outline: 2px solid var(--uaa-accent);
  outline-offset: 1px;
}
.field-help {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.8rem;
  color: var(--uaa-ink-soft);
}

.form-actions {
  flex: 1 1 100%;
  margin: 0 0.5rem 0.5rem;
}
.form-actions .btn { margin-right: 0.5rem; }

.btn-secondary {
  background: var(--uaa-surface-2);
  color: var(--uaa-ink);
  border: 1px solid var(--uaa-line);
}
.btn-small { padding: 0.25rem 0.6rem; font-size: 0.85rem; margin-right: 0.35rem; }
.btn-danger { background: var(--uaa-surface-2); color: var(--uaa-ink); border: 1px solid var(--uaa-line); }

/* --- findings ------------------------------------------------ */

.findings { margin-top: 1rem; }
.finding {
  margin: 0 0 0.5rem;
  padding: 0.55rem 0.7rem;
  border-left: 3px solid var(--uaa-line);
  background: var(--uaa-surface-2);
  font-size: 0.92rem;
  line-height: 1.5;
}
.finding code { word-break: break-all; }
/* Severity is carried by a border AND a word ("Refused —" / "Warning —") that the script
   writes, never by colour alone. A finding a colour-blind administrator cannot classify is
   a finding they will misread — the same argument the theme engine makes about semantics. */
.finding-ok { border-left-color: #0B5B30; }
.finding-warn { border-left-color: #9E6A00; }
.finding-block { border-left-color: #B3261E; }

/* --- branding preview ---------------------------------------- */

.theme-preview {
  --tp-primary: #1F5C4A;
  --tp-on-primary: #FFFFFF;
  --tp-surface: #FFFFFF;
  --tp-on-surface: #16191A;
  --tp-muted: #5B615C;
  --tp-success: #0B5B30;
  --tp-warning: #9E6A00;
  --tp-danger: #B3261E;
  --tp-border: #BFC5BD;
  --tp-radius: 6px;
  padding: 1rem;
  border: 1px solid var(--tp-border);
  border-radius: var(--tp-radius);
  background: var(--tp-surface);
  color: var(--tp-on-surface);
}
.theme-preview .tp-body { margin: 0 0 0.4rem; color: var(--tp-on-surface); }
.theme-preview .tp-muted { margin: 0 0 0.8rem; color: var(--tp-muted); font-size: 0.9rem; }
.theme-preview .tp-btn {
  display: inline-block;
  margin: 0 0.5rem 0.5rem 0;
  padding: 0.45rem 0.9rem;
  background: var(--tp-primary);
  color: var(--tp-on-primary);
  border-radius: var(--tp-radius);
  font-weight: 600;
}
.theme-preview .tp-good,
.theme-preview .tp-warn,
.theme-preview .tp-bad {
  display: inline-block;
  margin: 0 0.5rem 0.5rem 0;
  font-size: 0.9rem;
  font-weight: 600;
}
.theme-preview .tp-good { color: var(--tp-success); }
.theme-preview .tp-warn { color: var(--tp-warning); }
.theme-preview .tp-bad { color: var(--tp-danger); }

.panel-note {
  margin: 0 0 1rem;
  color: var(--uaa-ink-soft);
  font-size: 0.92rem;
  max-width: 62ch;
}
.table-scroll { overflow-x: auto; }
.muted { color: var(--uaa-ink-soft); }
