/* SPDX-License-Identifier: MIT OR Apache-2.0
   flowRS's component kit: flowRS's own work, under MIT OR Apache-2.0 (at your option), the licence
   of the runtime crates. Every exported app ships a copy (ui/kit.css); the root NOTICE says so. */
/* ============================================================================
   The component kit (crates/flowrs-ui/src/kit): app blocks, charts, controls and
   instruments, every value a token from styles/tokens.css, so the same markup wears
   Instrument and Paper.

   House rules, checked by e2e/kit-polish.spec.js and js-test/tokens.test.mjs:
   - space from the 4 px scale (--fr-space-*), type from the ramp (12/14/18/28; 24 for
     the display sizes on a phone), weights 400/500/600, three radii on a screen;
   - colours only through var(--fr-*); motion only through the duration tokens, which
     fall to zero under prefers-reduced-motion;
   - nothing sets a width the content cannot shrink to: min-width: 0 on flex and grid
     children, and wide content (tables, registers) scrolls inside itself.
   ============================================================================ */

/* ---- Utilities ------------------------------------------------------------ */
.fr-sr {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.fr-mono {
  font-family: var(--fr-font-mono);
  font-variant-numeric: tabular-nums;
}
.fr-btn:focus-visible,
.fr-tab:focus-visible,
.fr-tabpanel:focus-visible,
.fr-seg:focus-visible,
.fr-toggle:focus-visible,
.fr-input:focus-visible,
.fr-number-step:focus-visible,
.fr-slider-input:focus-visible,
.fr-knob:focus-visible,
.fr-th-sort:focus-visible,
.fr-table-scroll:focus-visible,
.fr-reg-scroll:focus-visible,
.fr-chart-data > summary:focus-visible,
.fr-gallery a:focus-visible {
  outline: 2px solid var(--fr-focus);
  outline-offset: 2px;
  box-shadow: none;
}

/* Fills and strokes by meaning (SVG). Used by the kit and by the Front Panel's
   instruments (crate::instruments), which draw the same way. */
.fr-f-none { fill: none; }
.fr-s-none { stroke: none; }
.fr-f-ink { fill: var(--fr-text); }
.fr-s-ink { stroke: var(--fr-text); }
.fr-f-muted { fill: var(--fr-text-3); }
.fr-s-muted { stroke: var(--fr-text-3); }
.fr-f-accent { fill: var(--fr-accent); }
.fr-s-accent { stroke: var(--fr-accent); }
.fr-f-accent-2 { fill: var(--fr-accent-2); }
.fr-s-accent-2 { stroke: var(--fr-accent-2); }
.fr-f-good { fill: var(--fr-good); }
.fr-s-good { stroke: var(--fr-good); }
.fr-f-warn { fill: var(--fr-warn); }
.fr-s-warn { stroke: var(--fr-warn); }
.fr-f-crit { fill: var(--fr-crit); }
.fr-s-crit { stroke: var(--fr-crit); }
.fr-f-track { fill: var(--fr-track); }
.fr-s-track { stroke: var(--fr-track); }
.fr-f-needle { fill: var(--fr-needle); }
.fr-s-needle { stroke: var(--fr-needle); }
.fr-f-card { fill: var(--fr-surface-2); }
.fr-f-cat-1 { fill: var(--fr-cat-1); }
.fr-s-cat-1 { stroke: var(--fr-cat-1); }
.fr-f-cat-2 { fill: var(--fr-cat-2); }
.fr-s-cat-2 { stroke: var(--fr-cat-2); }
.fr-f-cat-3 { fill: var(--fr-cat-3); }
.fr-s-cat-3 { stroke: var(--fr-cat-3); }
.fr-f-cat-4 { fill: var(--fr-cat-4); }
.fr-s-cat-4 { stroke: var(--fr-cat-4); }
.fr-f-cat-5 { fill: var(--fr-cat-5); }
.fr-s-cat-5 { stroke: var(--fr-cat-5); }
.fr-f-cat-6 { fill: var(--fr-cat-6); }
.fr-s-cat-6 { stroke: var(--fr-cat-6); }
.fr-f-cat-other { fill: var(--fr-cat-other); }
.fr-s-cat-other { stroke: var(--fr-cat-other); }
.fr-f-seq-1 { fill: var(--fr-seq-1); }
.fr-f-seq-2 { fill: var(--fr-seq-2); }
.fr-f-seq-3 { fill: var(--fr-seq-3); }
.fr-f-seq-4 { fill: var(--fr-seq-4); }
.fr-f-seq-5 { fill: var(--fr-seq-5); }
.fr-f-seq-6 { fill: var(--fr-seq-6); }
.fr-f-seq-7 { fill: var(--fr-seq-7); }
.fr-f-seq-8 { fill: var(--fr-seq-8); }
.fr-f-seq-9 { fill: var(--fr-seq-9); }
.fr-dashed { stroke-dasharray: 4 4; }

/* Front Panel instrument parts (crate::instruments) */
.fr-stop-from { stop-color: var(--fr-accent-2); }
.fr-stop-to { stop-color: var(--fr-accent); }
.fr-stop-liquid-top { stop-color: color-mix(in srgb, var(--fr-accent-2) 70%, var(--fr-white)); }
.fr-stop-liquid { stop-color: var(--fr-accent-2); }
.fr-i-vessel { fill: var(--fr-surface-sunk); stroke: var(--fr-track); }
.fr-i-band-2 { fill: var(--fr-border-2); }
.fr-i-band-3 { fill: var(--fr-border-3); }
.fr-i-area { fill: color-mix(in srgb, var(--fr-accent-2) 30%, transparent); stroke: var(--fr-accent-2); }
.fr-i-up { fill: var(--fr-good); stroke: var(--fr-good); }
.fr-i-down { fill: var(--fr-crit); stroke: var(--fr-crit); }
.fr-i-cellgap { stroke: var(--fr-surface-2); }
.fr-i-geo-sea { fill: var(--fr-surface-sunk); }
.fr-i-geo-grid { stroke: var(--fr-border-2); }
.fr-i-geo-equator { stroke: var(--fr-border-3); }
.fr-i-geo-pt { fill: var(--fr-accent-2); fill-opacity: 0.85; }

/* ---- Text ----------------------------------------------------------------- */
.fr-heading-block { display: flex; flex-direction: column; gap: var(--fr-space-1); min-width: 0; }
.fr-heading {
  margin: 0;
  color: var(--fr-text);
  font-weight: var(--fr-fw-strong);
  overflow-wrap: break-word;
}
.fr-h1 {
  font-size: var(--fr-fs-2xl);
  line-height: var(--fr-lh-display);
  letter-spacing: var(--fr-tracking-display);
}
.fr-h2 { font-size: var(--fr-fs-lg); line-height: var(--fr-lh-heading); letter-spacing: var(--fr-tracking); }
.fr-h3,
.fr-h4 { font-size: var(--fr-fs-sm); line-height: var(--fr-lh-heading); }
.fr-heading-sub {
  margin: 0;
  color: var(--fr-text-2);
  font-size: var(--fr-fs-sm);
  line-height: var(--fr-lh-body);
}
.fr-text {
  margin: 0;
  max-width: 68ch;
  color: var(--fr-text);
  font-size: var(--fr-fs-sm);
  line-height: var(--fr-lh-body);
  overflow-wrap: break-word;
}
.fr-text-sm { font-size: var(--fr-fs-xs); }
.fr-text-lead { line-height: 1.6; }
.fr-text-secondary { color: var(--fr-text-2); }
.fr-text-muted { color: var(--fr-text-3); }

.fr-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--fr-space-1);
  min-height: 24px;
  padding: var(--fr-space-half) var(--fr-space-2);
  border-radius: var(--fr-radius-full);
  font-size: var(--fr-fs-xs);
  font-weight: var(--fr-fw-medium);
  line-height: var(--fr-lh-heading);
  white-space: nowrap;
  background: var(--fr-layer-pressed);
  color: var(--fr-text-2);
}
.fr-badge-dot { width: 8px; height: 8px; border-radius: var(--fr-radius-full); background: currentColor; flex: none; }
.fr-badge.fr-tone-good { background: var(--fr-good-soft); color: var(--fr-good-text); }
.fr-badge.fr-tone-warn { background: var(--fr-warn-soft); color: var(--fr-warn-text); }
.fr-badge.fr-tone-crit { background: var(--fr-crit-soft); color: var(--fr-crit-text); }
.fr-badge.fr-tone-info { background: var(--fr-info-soft); color: var(--fr-info-text); }
.fr-badge.fr-tone-accent { background: var(--fr-accent-soft); color: var(--fr-accent-text); }

.fr-tone-text-neutral { color: var(--fr-text-2); }
.fr-tone-text-accent { color: var(--fr-accent-text); }
.fr-tone-text-good { color: var(--fr-good-text); }
.fr-tone-text-warn { color: var(--fr-warn-text); }
.fr-tone-text-crit { color: var(--fr-crit-text); }
.fr-tone-text-info { color: var(--fr-info-text); }

.fr-callout {
  display: flex;
  align-items: flex-start;
  gap: var(--fr-space-3);
  padding: var(--fr-space-3) var(--fr-space-4);
  border-radius: var(--fr-radius-control);
  background: var(--fr-layer-hover);
}
.fr-callout-mark {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: var(--fr-radius-full);
  font-size: var(--fr-fs-xs);
  font-weight: var(--fr-fw-strong);
  background: var(--fr-layer-pressed);
  color: var(--fr-text);
}
.fr-callout-body { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
.fr-callout-title { margin: 0; font-weight: var(--fr-fw-strong); font-size: var(--fr-fs-sm); color: var(--fr-text); }
.fr-callout-text { margin: 0; font-size: var(--fr-fs-sm); color: var(--fr-text-2); overflow-wrap: break-word; }
.fr-callout.fr-tone-good { background: var(--fr-good-soft); }
.fr-callout.fr-tone-good .fr-callout-mark { background: var(--fr-good-text); color: var(--fr-surface-2); }
.fr-callout.fr-tone-good .fr-callout-title { color: var(--fr-good-text); }
.fr-callout.fr-tone-warn { background: var(--fr-warn-soft); }
.fr-callout.fr-tone-warn .fr-callout-mark { background: var(--fr-warn-text); color: var(--fr-surface-2); }
.fr-callout.fr-tone-warn .fr-callout-title { color: var(--fr-warn-text); }
.fr-callout.fr-tone-crit { background: var(--fr-crit-soft); }
.fr-callout.fr-tone-crit .fr-callout-mark { background: var(--fr-crit-text); color: var(--fr-surface-2); }
.fr-callout.fr-tone-crit .fr-callout-title { color: var(--fr-crit-text); }
.fr-callout.fr-tone-info { background: var(--fr-info-soft); }
.fr-callout.fr-tone-info .fr-callout-mark { background: var(--fr-info-text); color: var(--fr-surface-2); }
.fr-callout.fr-tone-info .fr-callout-title { color: var(--fr-info-text); }

/* Text on a soft tint reads in the text colour, not the tint's own: keep body copy legible. */
.fr-callout.fr-tone-good .fr-callout-text,
.fr-callout.fr-tone-warn .fr-callout-text,
.fr-callout.fr-tone-crit .fr-callout-text,
.fr-callout.fr-tone-info .fr-callout-text { color: var(--fr-text-soft); }

.fr-kv { margin: 0; display: flex; flex-direction: column; }
.fr-kv-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--fr-space-4);
  padding: var(--fr-space-2) 0;
  border-bottom: 1px solid var(--fr-border);
}
.fr-kv-row:last-child { border-bottom: 0; }
.fr-kv-label { color: var(--fr-text-2); min-width: 0; }
.fr-kv-value {
  margin: 0;
  color: var(--fr-text);
  font-variant-numeric: tabular-nums;
  text-align: right;
  overflow-wrap: anywhere;
}
.fr-kv-value.fr-tone-text-neutral { color: var(--fr-text); }

/* ---- States --------------------------------------------------------------- */
.fr-skeleton { display: flex; flex-direction: column; gap: var(--fr-space-2); padding: var(--fr-space-1) 0; }
.fr-skel {
  display: block;
  border-radius: var(--fr-space-1);
  background: var(--fr-layer-pressed);
  animation: fr-pulse 1.2s ease-in-out infinite;
}
.fr-skel-line { height: 12px; width: 100%; }
.fr-skel-short { width: 60%; }
.fr-skel-tiny { width: 32%; }
.fr-skel-figure { height: 32px; width: 48%; }
.fr-skel-block { width: 100%; border-radius: var(--fr-radius-control); }
.fr-skel-row { height: 40px; width: 100%; }
@keyframes fr-pulse {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 0.85; }
}

.fr-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--fr-space-2);
  padding: var(--fr-space-6) var(--fr-space-4);
}
.fr-empty-mark {
  width: 32px;
  height: 32px;
  border-radius: var(--fr-radius-full);
  border: 2px dashed var(--fr-border-3);
}
.fr-empty-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); }
.fr-empty-reason { margin: 0; max-width: 40ch; color: var(--fr-text-2); }

.fr-error {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--fr-space-3);
  padding: var(--fr-space-4);
  border-radius: var(--fr-radius-control);
  background: var(--fr-crit-soft);
}
.fr-error-mark {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: var(--fr-radius-full);
  background: var(--fr-crit-text);
  color: var(--fr-surface-2);
  font-weight: var(--fr-fw-strong);
  font-size: var(--fr-fs-xs);
}
.fr-error-body { flex: 1 1 160px; min-width: 0; display: flex; flex-direction: column; gap: var(--fr-space-half); }
.fr-error-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-crit-text); }
.fr-error-cause { margin: 0; color: var(--fr-text-soft); overflow-wrap: break-word; }

/* ---- Layout --------------------------------------------------------------- */
.fr-stack { display: flex; min-width: 0; }
.fr-stack-col { flex-direction: column; }
.fr-stack-row { flex-direction: row; flex-wrap: wrap; }
.fr-stack-row.fr-nowrap { flex-wrap: nowrap; }
.fr-stack > * { min-width: 0; }
.fr-gap-none { gap: 0; }
.fr-gap-inner { gap: var(--fr-space-2); }
.fr-gap-group { gap: var(--fr-gap-stack); }
.fr-gap-section { gap: var(--fr-space-6); }
.fr-gap-card { gap: var(--fr-gap-card); }
.fr-align-start { align-items: flex-start; }
.fr-align-center { align-items: center; }
.fr-align-end { align-items: flex-end; }
.fr-align-baseline { align-items: baseline; }
.fr-justify-center { justify-content: center; }
.fr-justify-end { justify-content: flex-end; }
.fr-justify-between { justify-content: space-between; }

.fr-grid { display: grid; min-width: 0; }
.fr-grid > * { min-width: 0; }
.fr-grid-narrow { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.fr-grid-medium { grid-template-columns: repeat(auto-fit, minmax(min(100%, 248px), 1fr)); }
.fr-grid-wide { grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); }
.fr-span-all { grid-column: 1 / -1; min-width: 0; display: flex; flex-direction: column; }
.fr-span-all > * { flex: 1; }

.fr-box { min-width: 0; border-radius: var(--fr-radius-control); }
.fr-pad-none { padding: 0; }
.fr-pad-inner { padding: var(--fr-space-2); }
.fr-pad-group { padding: var(--fr-space-4); }
.fr-pad-section { padding: var(--fr-space-6); }
.fr-box.fr-raised { background: var(--fr-surface-2); border: 1px solid var(--fr-border); }
.fr-box.fr-sunk { background: var(--fr-layer-hover); }

.fr-card {
  display: flex;
  flex-direction: column;
  gap: var(--fr-gap-stack);
  min-width: 0;
  padding: var(--fr-pad-card);
  border-radius: var(--fr-radius-card);
}
.fr-card.fr-raised {
  background: var(--fr-surface-2);
  border: 1px solid var(--fr-border);
  box-shadow: var(--fr-shadow-card);
}
.fr-card.fr-sunk { background: var(--fr-layer-hover); }
.fr-card.fr-clear { padding: 0; }
.fr-card-head { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
.fr-card-title { margin: 0; font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-strong); line-height: var(--fr-lh-heading); color: var(--fr-text); }
.fr-card-sub { margin: 0; font-size: var(--fr-fs-xs); color: var(--fr-text-2); }
.fr-card-body { display: flex; flex-direction: column; gap: var(--fr-gap-stack); min-width: 0; }

.fr-tabs { display: flex; flex-direction: column; gap: var(--fr-space-4); min-width: 0; }
.fr-tablist {
  display: flex;
  gap: var(--fr-space-4);
  border-bottom: 1px solid var(--fr-border);
  overflow-x: auto;
  scrollbar-width: none;
}
.fr-tab {
  appearance: none;
  border: 0;
  background: none;
  padding: var(--fr-space-2) 0;
  min-height: 40px;
  font: inherit;
  font-weight: var(--fr-fw-medium);
  color: var(--fr-text-2);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--fr-dur-fast) var(--fr-ease-out), border-color var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-tab:hover { color: var(--fr-text); }
.fr-tab[aria-selected="true"] { color: var(--fr-text); border-bottom-color: var(--fr-accent); }
.fr-tabpanel { min-width: 0; border-radius: var(--fr-space-1); }
.fr-tabpanel[hidden] { display: none; }

.fr-divider { width: 100%; height: 1px; border: 0; margin: 0; background: var(--fr-border); }

/* ---- Data ----------------------------------------------------------------- */
.fr-stat { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-stat-label { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-sm); line-height: var(--fr-lh-heading); overflow-wrap: break-word; }
.fr-stat-value {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--fr-space-1);
  min-width: 0;
}
.fr-stat-figure {
  font-size: var(--fr-fs-2xl);
  font-weight: var(--fr-fw-strong);
  line-height: var(--fr-lh-display);
  letter-spacing: var(--fr-tracking-display);
  font-variant-numeric: tabular-nums;
  color: var(--fr-text);
  overflow-wrap: anywhere;
}
.fr-stat-unit { color: var(--fr-text-2); font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-medium); }
.fr-stat-delta {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--fr-space-1) var(--fr-space-2);
  font-size: var(--fr-fs-xs);
}
.fr-delta { display: inline-flex; align-items: baseline; gap: var(--fr-space-1); font-weight: var(--fr-fw-medium); font-variant-numeric: tabular-nums; }
.fr-delta-arrow { font-size: var(--fr-fs-xs); }
.fr-stat-cmp { color: var(--fr-text-3); }
/* The line stretches with the tile; its end marker sits over it in pixels, so it is round
   at any width. */
.fr-spark-wrap { position: relative; display: block; width: 100%; min-width: 0; }
.fr-spark { display: block; width: 100%; height: 28px; overflow: visible; }
.fr-spark-end {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: var(--fr-radius-full);
  transform: translate(-50%, -50%);
  background: var(--fr-accent);
  pointer-events: none;
}
.fr-spark-line { fill: none; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.fr-spark-area { stroke: none; opacity: 0.12; }
.fr-tone-mark-accent .fr-spark-line { stroke: var(--fr-accent); }
.fr-tone-mark-accent .fr-spark-area { fill: var(--fr-accent); }
.fr-tone-mark-accent .fr-spark-end { background: var(--fr-accent); }
.fr-spark-none { color: var(--fr-text-3); }

.fr-progress-block { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--fr-space-1) var(--fr-space-3); align-items: center; }
.fr-progress-label { grid-column: 1; color: var(--fr-text); font-size: var(--fr-fs-sm); }
.fr-progress-value { grid-column: 2; grid-row: 1; color: var(--fr-text-2); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; text-align: right; }
.fr-progress { grid-column: 1 / -1; }
.fr-progress-track {
  display: block;
  height: 8px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-layer-track);
  overflow: hidden;
}
.fr-progress-fill {
  display: block;
  height: 100%;
  border-radius: var(--fr-radius-full);
  background: var(--fr-accent);
  transition: width var(--fr-dur-slow) var(--fr-ease-out);
}
.fr-tone-mark-good .fr-progress-fill { background: var(--fr-good); }
.fr-tone-mark-warn .fr-progress-fill { background: var(--fr-warn); }
.fr-tone-mark-crit .fr-progress-fill { background: var(--fr-crit); }
.fr-tone-mark-info .fr-progress-fill { background: var(--fr-info); }

.fr-table-block { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
.fr-table-tools { display: flex; flex-direction: column; gap: var(--fr-space-1); max-width: 320px; }
.fr-table-scroll {
  overflow: auto;
  min-width: 0;
  border: 1px solid var(--fr-border);
  border-radius: var(--fr-radius-control);
}
.fr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fr-fs-sm);
  font-variant-numeric: tabular-nums;
}
.fr-table th,
.fr-table td {
  padding: var(--fr-space-3) var(--fr-space-4);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--fr-border);
  white-space: nowrap;
  color: var(--fr-text);
}
.fr-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--fr-surface-2);
  color: var(--fr-text-2);
  font-size: var(--fr-fs-xs);
  font-weight: var(--fr-fw-strong);
}
.fr-table tbody th { font-weight: var(--fr-fw-medium); }
.fr-table tbody tr:last-child > * { border-bottom: 0; }
.fr-table tbody tr:hover > * { background: var(--fr-layer-hover); }
.fr-table .fr-num { text-align: right; }
.fr-th-sort {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: var(--fr-space-1);
  cursor: pointer;
  min-height: 24px;
  border-radius: var(--fr-space-1);
}
.fr-num .fr-th-sort { flex-direction: row-reverse; }
.fr-th-sort:hover { color: var(--fr-text); }
.fr-sort-mark { color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
.fr-table-nomatch td { white-space: normal; color: var(--fr-text-2); }
.fr-table-nomatch td > * + * { margin-left: var(--fr-space-3); }
.fr-table-count { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }

/* ---- Charts --------------------------------------------------------------- */
.fr-chart { margin: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-chart-head { display: flex; flex-direction: column; gap: var(--fr-space-half); }
.fr-chart-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); line-height: var(--fr-lh-heading); }
.fr-chart-sub { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
.fr-axis-caption { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
.fr-axis-caption-x { text-align: center; }
.fr-chart-plot { position: relative; width: 100%; min-width: 0; }
.fr-chart-svg { display: block; max-width: 100%; height: auto; overflow: visible; }
.fr-chart-fail { margin: 0; color: var(--fr-text-2); }
.fr-chart-gridline { stroke: var(--fr-chart-grid); stroke-width: 1; }
.fr-chart-baseline { stroke: var(--fr-chart-axis); stroke-width: 1; }
.fr-chart-tick {
  fill: var(--fr-text-3);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-xs);
  font-variant-numeric: tabular-nums;
}
.fr-chart-endlabel { fill: var(--fr-text-2); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
.fr-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.fr-area { stroke: none; opacity: 0.22; }
.fr-line-dot { stroke: var(--fr-surface-2); stroke-width: 1.5; }
.fr-bar,
.fr-cell,
.fr-point { stroke: none; }
.fr-point { fill-opacity: 0.85; }
.fr-hit { fill: transparent; stroke: none; }
.fr-crosshair { stroke: var(--fr-border-3); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.fr-point-ring { fill: none; stroke: var(--fr-text); stroke-width: 1.5; pointer-events: none; }
.fr-end-dot { stroke: none; }

/* The categorical slots and the ramp, as stroke for lines and fill for everything else. */
.fr-line.fr-cat-1, .fr-scope-trace.fr-cat-1, .fr-wave-trace.fr-cat-1 { stroke: var(--fr-cat-1); }
.fr-line.fr-cat-2, .fr-scope-trace.fr-cat-2, .fr-wave-trace.fr-cat-2 { stroke: var(--fr-cat-2); }
.fr-line.fr-cat-3, .fr-scope-trace.fr-cat-3, .fr-wave-trace.fr-cat-3 { stroke: var(--fr-cat-3); }
.fr-line.fr-cat-4, .fr-scope-trace.fr-cat-4, .fr-wave-trace.fr-cat-4 { stroke: var(--fr-cat-4); }
.fr-line.fr-cat-5, .fr-scope-trace.fr-cat-5, .fr-wave-trace.fr-cat-5 { stroke: var(--fr-cat-5); }
.fr-line.fr-cat-6, .fr-scope-trace.fr-cat-6, .fr-wave-trace.fr-cat-6 { stroke: var(--fr-cat-6); }
.fr-line.fr-cat-other { stroke: var(--fr-cat-other); }
.fr-cat-1:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-1); background: var(--fr-cat-1); }
.fr-cat-2:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-2); background: var(--fr-cat-2); }
.fr-cat-3:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-3); background: var(--fr-cat-3); }
.fr-cat-4:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-4); background: var(--fr-cat-4); }
.fr-cat-5:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-5); background: var(--fr-cat-5); }
.fr-cat-6:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-6); background: var(--fr-cat-6); }
.fr-cat-other:not(.fr-line) { fill: var(--fr-cat-other); background: var(--fr-cat-other); }
.fr-seq-1 { fill: var(--fr-seq-1); background: var(--fr-seq-1); }
.fr-seq-2 { fill: var(--fr-seq-2); background: var(--fr-seq-2); }
.fr-seq-3 { fill: var(--fr-seq-3); background: var(--fr-seq-3); }
.fr-seq-4 { fill: var(--fr-seq-4); background: var(--fr-seq-4); }
.fr-seq-5 { fill: var(--fr-seq-5); background: var(--fr-seq-5); }
.fr-seq-6 { fill: var(--fr-seq-6); background: var(--fr-seq-6); }
.fr-seq-7 { fill: var(--fr-seq-7); background: var(--fr-seq-7); }
.fr-seq-8 { fill: var(--fr-seq-8); background: var(--fr-seq-8); }
.fr-seq-9 { fill: var(--fr-seq-9); background: var(--fr-seq-9); }

.fr-legend {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--fr-space-1) var(--fr-space-4);
  font-size: var(--fr-fs-xs);
  color: var(--fr-text-2);
}
.fr-legend-item { display: inline-flex; align-items: center; gap: var(--fr-space-2); }
.fr-legend-swatch { width: 12px; height: 12px; border-radius: var(--fr-radius-mark); flex: none; }

.fr-tip {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 3;
  pointer-events: none;
  transition: transform var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-tip-card {
  transform: translateY(-100%);
  min-width: 160px;
  max-width: 240px;
  padding: var(--fr-space-2) var(--fr-space-3);
  border-radius: var(--fr-radius-control);
  background: var(--fr-surface-3);
  border: 1px solid var(--fr-border-2);
  box-shadow: var(--fr-shadow-2);
  font-size: var(--fr-fs-xs);
  color: var(--fr-text);
}
.fr-tip-flip .fr-tip-card { transform: translate(-100%, -100%); }
.fr-tip-head { margin: 0 0 var(--fr-space-1); font-weight: var(--fr-fw-strong); }
.fr-tip-rows { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--fr-space-1); }
.fr-tip-row { display: flex; align-items: center; gap: var(--fr-space-2); }
.fr-tip-name { color: var(--fr-text-2); flex: 1; min-width: 0; }
.fr-tip-value { font-variant-numeric: tabular-nums; font-weight: var(--fr-fw-medium); }

.fr-chart-data > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--fr-space-2);
  list-style: none;
  min-height: 24px;
  color: var(--fr-text-2);
  font-size: var(--fr-fs-xs);
  cursor: pointer;
  border-radius: var(--fr-space-1);
}
.fr-chart-data > summary::-webkit-details-marker { display: none; }
.fr-chart-data > summary::before {
  content: "";
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-chart-data[open] > summary::before { transform: rotate(90deg); }
.fr-chart-data > summary:hover { color: var(--fr-text); }

/* A heatmap's scale: its nine steps between the lowest and highest value. */
.fr-scale { display: flex; align-items: center; gap: var(--fr-space-2); font-size: var(--fr-fs-xs); color: var(--fr-text-2); font-variant-numeric: tabular-nums; }
.fr-scale-steps { display: flex; gap: var(--fr-space-half); }
.fr-scale-step { width: 16px; height: 12px; border-radius: var(--fr-radius-mark); }
.fr-chart-data[open] > summary { margin-bottom: var(--fr-space-2); }

.fr-donut { display: flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-6); }
.fr-donut-figure { position: relative; width: 180px; height: 180px; flex: none; }
.fr-donut-svg { display: block; width: 100%; height: 100%; }
.fr-slice { stroke: var(--fr-surface-2); stroke-width: 2; transition: opacity var(--fr-dur-fast) var(--fr-ease-out); }
.fr-slice-dim { opacity: 0.35; }
/* The hole is its own disc in the card's colour, so the total reads against the card and
   never against a slice under its box. */
.fr-donut-centre {
  position: absolute;
  inset: 32px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-surface-2);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  padding: 0 var(--fr-space-2);
}
.fr-donut-centre-value { font-size: var(--fr-fs-lg); font-weight: var(--fr-fw-strong); font-variant-numeric: tabular-nums; color: var(--fr-text); line-height: var(--fr-lh-heading); }
.fr-donut-centre-label { font-size: var(--fr-fs-xs); color: var(--fr-text-2); line-height: var(--fr-lh-heading); }
.fr-donut-legend { flex: 1 1 200px; min-width: 0; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.fr-donut-item {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--fr-space-2);
  padding: var(--fr-space-1) 0;
  font-size: var(--fr-fs-xs);
  color: var(--fr-text-2);
}
.fr-donut-name { color: var(--fr-text); overflow-wrap: anywhere; }
.fr-donut-val,
.fr-donut-share { font-variant-numeric: tabular-nums; text-align: right; }
.fr-donut-share { min-width: 48px; color: var(--fr-text); font-weight: var(--fr-fw-medium); }
.fr-donut-item-on .fr-donut-name { font-weight: var(--fr-fw-strong); }

/* ---- Controls ------------------------------------------------------------- */
.fr-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--fr-space-2);
  min-height: 40px;
  padding: 0 var(--fr-space-4);
  border-radius: var(--fr-radius-control);
  border: 1px solid transparent;
  font: inherit;
  font-weight: var(--fr-fw-medium);
  line-height: var(--fr-lh-heading);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--fr-dur-press) var(--fr-ease-out), border-color var(--fr-dur-press) var(--fr-ease-out),
    transform var(--fr-dur-press) var(--fr-ease-out);
}
.fr-btn:active:not(:disabled) { transform: translateY(1px); }
.fr-btn:disabled { cursor: not-allowed; opacity: 0.55; }
.fr-btn-sm { min-height: 32px; padding: 0 var(--fr-space-3); font-size: var(--fr-fs-xs); }
.fr-btn-primary { background: var(--fr-primary-fill); color: var(--fr-accent-ink); }
.fr-btn-primary:hover:not(:disabled) { filter: brightness(1.06); }
.fr-btn-secondary { background: var(--fr-surface-2); color: var(--fr-text); border-color: var(--fr-border-3); }
.fr-btn-secondary:hover:not(:disabled) { background: var(--fr-surface-3); }
.fr-btn-ghost { background: transparent; color: var(--fr-text-2); }
.fr-btn-ghost:hover:not(:disabled) { background: var(--fr-layer-hover); color: var(--fr-text); }
.fr-btn-danger { background: var(--fr-crit-soft); color: var(--fr-crit-text); border-color: color-mix(in srgb, var(--fr-crit) 45%, transparent); }
.fr-btn-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--fr-crit) 22%, transparent); }

.fr-field { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
/* A field reads at a field's width, not a page's: a number or a line of text in a wide card
   stops at 480 px (P4's measure, for inputs). */
.fr-card-body > .fr-field,
.fr-section-body > .fr-field,
.fr-form > .fr-field,
.fr-grid > .fr-field { max-width: 480px; }
.fr-field-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--fr-space-3); }
.fr-field-label { color: var(--fr-text); font-weight: var(--fr-fw-medium); font-size: var(--fr-fs-sm); }
.fr-field-value { color: var(--fr-text-2); font-variant-numeric: tabular-nums; font-size: var(--fr-fs-sm); white-space: nowrap; }
.fr-field-hint { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
.fr-field-hint:empty { display: none; }
.fr-field-error { margin: 0; color: var(--fr-crit-text); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
.fr-field-error[hidden] { display: none; }
.fr-field-invalid .fr-input { border-color: var(--fr-crit); }

.fr-input {
  width: 100%;
  min-width: 0;
  height: 40px;
  padding: 0 var(--fr-space-3);
  border: 1px solid var(--fr-border-control);
  border-radius: var(--fr-radius-control);
  background: var(--fr-surface-sunk);
  color: var(--fr-text);
  font: inherit;
  transition: border-color var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-input::placeholder { color: var(--fr-text-3); }
.fr-input:hover { border-color: var(--fr-text-3); }

.fr-slider { position: relative; height: 24px; }
.fr-slider-track {
  position: absolute;
  left: 0;
  right: 0;
  top: 8px;
  height: 8px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-layer-track);
  overflow: hidden;
}
.fr-slider-fill { display: block; height: 100%; background: var(--fr-accent); }
.fr-slider-input {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
  border-radius: var(--fr-radius-full);
}
.fr-slider-input::-webkit-slider-runnable-track { height: 24px; background: transparent; }
.fr-slider-input::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-surface-2);
  border: 2px solid var(--fr-accent);
  box-shadow: var(--fr-shadow-1);
}
.fr-slider-input::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-surface-2);
  border: 2px solid var(--fr-accent);
}
.fr-slider-scale { display: flex; justify-content: space-between; color: var(--fr-text-3); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; }

.fr-number { display: flex; align-items: stretch; gap: var(--fr-space-2); }
.fr-number-input { flex: 1; text-align: right; font-variant-numeric: tabular-nums; }
.fr-number-unit { align-self: center; color: var(--fr-text-2); min-width: 24px; }
.fr-number-step {
  appearance: none;
  width: 40px;
  flex: none;
  border: 1px solid var(--fr-border-control);
  border-radius: var(--fr-radius-control);
  background: var(--fr-surface-2);
  color: var(--fr-text);
  font: inherit;
  font-size: var(--fr-fs-lg);
  cursor: pointer;
}
.fr-number-step:hover { background: var(--fr-surface-3); }

.fr-toggle-field { display: flex; align-items: center; justify-content: space-between; gap: var(--fr-space-4); }
.fr-toggle-text { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
.fr-toggle-desc { color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
.fr-toggle {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--fr-space-2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--fr-text-2);
  font: inherit;
  font-size: var(--fr-fs-xs);
  font-weight: var(--fr-fw-medium);
  cursor: pointer;
  flex: none;
  border-radius: var(--fr-radius-full);
}
.fr-toggle-knob {
  position: relative;
  width: 44px;
  height: 24px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-layer-track);
  border: 1px solid var(--fr-border-control);
  transition: background var(--fr-dur-fast) var(--fr-ease-out), border-color var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-toggle-knob::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: var(--fr-radius-full);
  background: var(--fr-text-2);
  transition: transform var(--fr-dur-slow) var(--fr-ease-out), background var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-toggle[aria-checked="true"] .fr-toggle-knob { background: var(--fr-accent); border-color: var(--fr-accent); }
.fr-toggle[aria-checked="true"] .fr-toggle-knob::after { transform: translateX(20px); background: var(--fr-accent-ink); }
.fr-toggle[aria-checked="true"] .fr-toggle-state { color: var(--fr-text); }
.fr-toggle-state { min-width: 24px; text-align: left; }

.fr-select { position: relative; }
.fr-select-input { appearance: none; padding-right: var(--fr-space-8); cursor: pointer; }
.fr-select-chevron {
  position: absolute;
  right: var(--fr-space-3);
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--fr-text-2);
  border-bottom: 2px solid var(--fr-text-2);
  transform: translateY(-75%) rotate(45deg);
  pointer-events: none;
}

.fr-seg-field { display: flex; flex-direction: column; align-items: flex-start; gap: var(--fr-space-2); min-width: 0; }
.fr-gallery-tools .fr-seg-field { flex-direction: row; align-items: center; }
.fr-segmented {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--fr-space-half);
  padding: var(--fr-space-half);
  border-radius: var(--fr-radius-control);
  background: var(--fr-layer-pressed);
  max-width: 100%;
}
.fr-seg {
  appearance: none;
  border: 0;
  min-height: 32px;
  padding: 0 var(--fr-space-3);
  border-radius: var(--fr-space-2);
  background: transparent;
  color: var(--fr-text-2);
  font: inherit;
  font-weight: var(--fr-fw-medium);
  cursor: pointer;
  transition: background var(--fr-dur-fast) var(--fr-ease-out), color var(--fr-dur-fast) var(--fr-ease-out);
}
.fr-seg:hover { color: var(--fr-text); }
.fr-seg[aria-checked="true"] { background: var(--fr-surface-2); color: var(--fr-text); box-shadow: var(--fr-shadow-1); }

@media (pointer: coarse) {
  .fr-btn, .fr-input, .fr-number-step { min-height: 44px; }
  .fr-seg, .fr-tab { min-height: 44px; }
}

/* ---- Instruments ---------------------------------------------------------- */
.fr-instrument { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
.fr-instrument-label { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-strong); }

.fr-gauge { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-1); }
.fr-gauge-svg { display: block; width: 100%; max-width: 200px; height: auto; overflow: visible; }
.fr-gauge-track { fill: none; stroke: var(--fr-track); stroke-width: 8; stroke-linecap: round; }
.fr-gauge-value { fill: none; stroke-width: 8; stroke-linecap: round; }
.fr-gauge-zone { fill: none; stroke-width: 3; stroke-linecap: butt; }
.fr-gauge-tick { stroke: var(--fr-text-3); stroke-width: 1.2; }
.fr-gauge-needle { stroke: var(--fr-needle); stroke-width: 2.5; stroke-linecap: round; }
.fr-gauge-hub { fill: var(--fr-needle); }
.fr-tone-stroke-accent { stroke: var(--fr-accent); }
.fr-tone-stroke-neutral { stroke: var(--fr-text-3); }
.fr-tone-stroke-good { stroke: var(--fr-good); }
.fr-tone-stroke-warn { stroke: var(--fr-warn); }
.fr-tone-stroke-crit { stroke: var(--fr-crit); }
.fr-tone-stroke-info { stroke: var(--fr-info); }
.fr-gauge-readout { margin: 0; display: flex; align-items: baseline; gap: var(--fr-space-1); }
.fr-gauge-figure { font-family: var(--fr-font-mono); font-size: var(--fr-fs-2xl); font-weight: var(--fr-fw-medium); font-variant-numeric: tabular-nums; line-height: var(--fr-lh-display); color: var(--fr-text); }
.fr-gauge-unit { color: var(--fr-text-2); font-weight: var(--fr-fw-medium); }
.fr-gauge-range { margin: 0; width: 100%; max-width: 200px; display: flex; justify-content: space-between; color: var(--fr-text-3); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; }

.fr-scope { display: flex; flex-direction: column; gap: var(--fr-space-3); }
.fr-scope-screen {
  position: relative;
  aspect-ratio: 5 / 3;
  max-height: 320px;
  border-radius: var(--fr-radius-control);
  background: var(--fr-surface-sunk);
  border: 1px solid var(--fr-border);
  overflow: hidden;
}
.fr-scope-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.fr-scope-div { stroke: var(--fr-chart-grid); stroke-width: 1; vector-effect: non-scaling-stroke; }
.fr-scope-axis { stroke: var(--fr-border-3); }
.fr-scope-trace { fill: none; stroke-width: 2; stroke-linejoin: round; }
.fr-scope-scale,
.fr-scope-time {
  position: absolute;
  bottom: var(--fr-space-2);
  padding: var(--fr-space-half) var(--fr-space-2);
  border-radius: var(--fr-space-1);
  background: var(--fr-surface-2);
  color: var(--fr-text-2);
  font-family: var(--fr-font-mono);
  font-size: var(--fr-fs-xs);
}
.fr-scope-scale { left: var(--fr-space-2); }
.fr-scope-time { right: var(--fr-space-2); }
.fr-scope-chs { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--fr-space-2) var(--fr-space-6); }
.fr-scope-ch { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-2); font-size: var(--fr-fs-xs); }
.fr-scope-ch-name { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
.fr-scope-meas { color: var(--fr-text-2); font-family: var(--fr-font-mono); font-variant-numeric: tabular-nums; }

.fr-wave { display: flex; flex-direction: column; gap: var(--fr-space-1); }
.fr-wave-lane {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) 48px;
  align-items: center;
  gap: var(--fr-space-3);
  padding: var(--fr-space-1) var(--fr-space-2);
  border-radius: var(--fr-space-2);
  background: var(--fr-surface-sunk);
}
.fr-wave-name { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); color: var(--fr-text); }
.fr-wave-svg { display: block; width: 100%; height: 24px; }
.fr-wave-trace { fill: none; stroke-width: 2; }
.fr-wave-level { font-size: var(--fr-fs-xs); color: var(--fr-text-2); text-align: right; }
.fr-wave-ruler {
  margin: 0;
  display: flex;
  justify-content: space-between;
  padding: 0 64px 0 72px;
  color: var(--fr-text-3);
  font-size: var(--fr-fs-xs);
  font-variant-numeric: tabular-nums;
}

.fr-led {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--fr-space-3);
  min-height: 32px;
}
.fr-led-lamp {
  width: 16px;
  height: 16px;
  border-radius: var(--fr-radius-full);
  border: 2px solid var(--fr-text-3);
  background: transparent;
  transition: background var(--fr-dur-base) var(--fr-ease-out), box-shadow var(--fr-dur-base) var(--fr-ease-out);
}
.fr-led-unknown .fr-led-lamp { border-style: dashed; }
.fr-led-on.fr-tone-mark-good .fr-led-lamp { background: var(--fr-good); border-color: var(--fr-good); box-shadow: 0 0 10px -1px var(--fr-good); }
.fr-led-on.fr-tone-mark-warn .fr-led-lamp { background: var(--fr-warn); border-color: var(--fr-warn); box-shadow: 0 0 10px -1px var(--fr-warn); }
.fr-led-on.fr-tone-mark-crit .fr-led-lamp { background: var(--fr-crit); border-color: var(--fr-crit); box-shadow: 0 0 10px -1px var(--fr-crit); }
.fr-led-on.fr-tone-mark-info .fr-led-lamp,
.fr-led-on.fr-tone-mark-accent .fr-led-lamp { background: var(--fr-info); border-color: var(--fr-info); box-shadow: 0 0 10px -1px var(--fr-info); }
.fr-led-label { color: var(--fr-text); }
.fr-led-word { color: var(--fr-text-2); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
.fr-led-on .fr-led-word { color: var(--fr-text); }
/* A verdict says itself three ways: the lamp's colour, a mark and its word. A failure is
   the loudest thing on the card: a filled --crit lamp with a glow and a --crit badge. */
.fr-led-verdict .fr-led-word { font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-strong); }
.fr-led-verdict.fr-verdict-pass .fr-led-lamp { background: var(--fr-good); border-color: var(--fr-good); }
.fr-led-verdict.fr-verdict-fail .fr-led-lamp { background: var(--fr-crit); border-color: var(--fr-crit); box-shadow: 0 0 10px -1px var(--fr-crit); }
.fr-led-verdict.fr-verdict-warn .fr-led-lamp { background: var(--fr-warn); border-color: var(--fr-warn); }
.fr-led-verdict.fr-verdict-unknown .fr-led-lamp { border-style: dashed; }
.fr-verdict-mark { margin-right: var(--fr-space-1); }
/* A readout's verdict in its tone: the value's own colour would otherwise win. */
.fr-kv-value.fr-tone-text-crit { color: var(--fr-crit-text); font-weight: var(--fr-fw-strong); }
.fr-kv-value.fr-tone-text-good { color: var(--fr-good-text); font-weight: var(--fr-fw-strong); }
.fr-kv-value.fr-tone-text-warn { color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }

.fr-knob-field { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-2); }
.fr-knob {
  width: 112px;
  height: 112px;
  border-radius: var(--fr-radius-full);
  cursor: ns-resize;
  touch-action: none;
}
.fr-knob-svg { display: block; width: 100%; height: 100%; }
.fr-knob-track { fill: none; stroke: var(--fr-track); stroke-width: 4; stroke-linecap: round; }
.fr-knob-fill { fill: none; stroke: var(--fr-accent); stroke-width: 4; stroke-linecap: round; }
.fr-knob-body {
  fill: var(--fr-knob-lo);
  stroke: var(--fr-knob-hi);
  stroke-width: 2;
}
.fr-knob-pointer { stroke: var(--fr-accent); stroke-width: 3; stroke-linecap: round; }
.fr-knob-value { font-family: var(--fr-font-mono); font-size: var(--fr-fs-lg); font-variant-numeric: tabular-nums; color: var(--fr-text); }

.fr-reg { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
.fr-reg-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--fr-space-2) var(--fr-space-4); }
.fr-reg-name { font-weight: var(--fr-fw-strong); color: var(--fr-text); }
.fr-reg-addr { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); color: var(--fr-text-2); }
.fr-reg-value { margin-left: auto; font-family: var(--fr-font-mono); font-size: var(--fr-fs-lg); color: var(--fr-text); font-variant-numeric: tabular-nums; }
.fr-reg-scroll { overflow-x: auto; min-width: 0; padding-bottom: var(--fr-space-1); border-radius: var(--fr-space-1); }
.fr-reg-grid { display: grid; gap: var(--fr-space-half); }
.fr-reg-8 { grid-template-columns: repeat(8, minmax(40px, 1fr)); min-width: 336px; }
.fr-reg-16 { grid-template-columns: repeat(16, minmax(36px, 1fr)); min-width: 608px; }
.fr-reg-32 { grid-template-columns: repeat(32, minmax(32px, 1fr)); min-width: 1088px; }
.fr-reg-bit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fr-space-half);
  padding: var(--fr-space-1) 0;
  border-radius: var(--fr-space-1);
  background: var(--fr-surface-sunk);
  font-family: var(--fr-font-mono);
}
.fr-reg-bitno { font-size: var(--fr-fs-xs); color: var(--fr-text-3); }
.fr-reg-bitval { font-size: var(--fr-fs-sm); color: var(--fr-text-2); }
.fr-reg-set { background: var(--fr-accent-soft); }
.fr-reg-set .fr-reg-bitval { color: var(--fr-accent-text); font-weight: var(--fr-fw-strong); }
.fr-reg-field {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fr-space-half);
  min-width: 0;
  padding: var(--fr-space-1);
  border-top: 2px solid var(--fr-border-3);
  font-size: var(--fr-fs-xs);
}
.fr-reg-field-name { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
.fr-reg-field-val { color: var(--fr-text-2); font-family: var(--fr-font-mono); }

.fr-svg { display: block; width: 100%; height: auto; max-width: 480px; }
.fr-svg-text { font-family: var(--fr-font-ui); font-size: var(--fr-fs-sm); }
.fr-svg-text-sm { font-size: var(--fr-fs-xs); }

/* ---- The gallery page ----------------------------------------------------- */
.fr-gallery {
  min-height: 100vh;
  background: var(--fr-bg);
  color: var(--fr-text);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-sm);
  line-height: var(--fr-lh-body);
  letter-spacing: var(--fr-tracking);
}
.fr-gallery-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--fr-space-3) var(--fr-space-6);
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--fr-space-6) var(--fr-space-6) 0;
}
.fr-gallery-brand { display: inline-flex; align-items: center; gap: var(--fr-space-2); }
.fr-gallery-mark { width: 16px; height: 16px; border-radius: var(--fr-space-1); background: var(--fr-flow); }
.fr-gallery-kicker { color: var(--fr-text-2); font-weight: var(--fr-fw-medium); }
.fr-gallery-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-3); }
.fr-gallery-main {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--fr-space-8) var(--fr-space-6) var(--fr-space-12);
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-12);
}
.fr-gallery-section { display: flex; flex-direction: column; gap: var(--fr-space-6); min-width: 0; scroll-margin-top: var(--fr-space-6); }
.fr-gallery-hero { gap: var(--fr-space-4); }
.fr-gallery-said { margin: 0; color: var(--fr-text-2); min-height: 24px; }


/* ---- Section, code, text input, progress range (kit) ---------------------- */
.fr-section { display: flex; flex-direction: column; gap: var(--fr-space-4); min-width: 0; }
.fr-section-head { display: flex; flex-direction: column; gap: var(--fr-space-1); min-width: 0; }
.fr-section-title {
  margin: 0;
  color: var(--fr-text);
  font-size: var(--fr-fs-lg);
  font-weight: var(--fr-fw-strong);
  line-height: var(--fr-lh-heading);
  letter-spacing: var(--fr-tracking);
}
.fr-section-desc { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-sm); }
.fr-section-body { display: flex; flex-direction: column; gap: var(--fr-gap-card); min-width: 0; }
.fr-code {
  margin: 0;
  max-height: 320px;
  overflow: auto;
  padding: var(--fr-space-3);
  border: 1px solid var(--fr-border);
  border-radius: var(--fr-radius-control);
  background: var(--fr-surface-sunk);
  color: var(--fr-text);
  font-family: var(--fr-font-mono);
  font-size: var(--fr-fs-xs);
  line-height: var(--fr-lh-body);
  white-space: pre;
}
.fr-code:focus-visible { outline: 2px solid var(--fr-focus); outline-offset: 2px; }
.fr-textarea { height: auto; min-height: 96px; padding: var(--fr-space-2) var(--fr-space-3); resize: vertical; line-height: var(--fr-lh-body); }
.fr-input-swatch { width: 64px; padding: var(--fr-space-1); }
.fr-progress-track { position: relative; }
.fr-progress-target {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--fr-text);
}
.fr-progress-vertical { display: flex; justify-content: flex-start; }
.fr-progress-vertical .fr-progress-track { width: 16px; height: 120px; display: flex; flex-direction: column; justify-content: flex-end; }
.fr-progress-vertical .fr-progress-fill { width: 100%; transition: height var(--fr-dur-slow) var(--fr-ease-out); }
.fr-progress-vertical .fr-progress-target { top: auto; left: 0; right: 0; width: auto; height: 2px; }

/* ---- The app view --------------------------------------------------------- */
.fr-app {
  background: var(--fr-bg);
  color: var(--fr-text);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-sm);
  line-height: var(--fr-lh-body);
  letter-spacing: var(--fr-tracking);
  padding: var(--fr-space-6);
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-4);
  min-width: 0;
}
.fr-app-body { min-width: 0; max-width: 1280px; width: 100%; margin: 0 auto; }
/* A reading alone in its section is a tile, not a banner: on a wide page a KPI tile, a lamp
   or a gauge keeps about the width it has in a row of four (OpenUI's KPI row), never the
   page's. On a phone every card is the column's width, so their edges line up. */
@media (min-width: 600px) {
  .fr-app .fr-section-body > .fr-card:only-child:has(.fr-stat, .fr-led, .fr-gauge) {
    width: 100%;
    max-width: 20rem;
  }
  .fr-app .fr-section-body > .fr-card:only-child:has(.fr-image) {
    width: 100%;
    max-width: 36rem;
  }
}
/* An image in an app is a figure, not a wallpaper: its title above it, as a card's head,
   and at most 32 rem wide however few pixels it has (a 64 px test pattern stays crisp). */
.fr-app .fr-image-img { width: 100%; max-width: 32rem; }
.fr-app .fr-image-caption {
  order: -1;
  color: var(--fr-text);
  font-size: var(--fr-fs-sm);
  font-weight: var(--fr-fw-strong);
  line-height: var(--fr-lh-heading);
}
/* Everything an app can focus shows the kit's ring, the editor's own drawings (a test
   report's controls) included. */
.fr-app :focus-visible,
.fr-runonly :focus-visible {
  outline: 2px solid var(--fr-focus);
  outline-offset: 2px;
  box-shadow: none;
}
.fr-app-note { margin: 0; color: var(--fr-text-2); }
.fr-app-skeleton { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-problems {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: var(--fr-space-3) var(--fr-space-4);
  border: 1px solid var(--fr-warn);
  border-radius: var(--fr-radius-control);
  background: var(--fr-warn-soft);
}
.fr-problems-title { margin: 0; color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }
.fr-problems-list { margin: var(--fr-space-2) 0 0; padding-left: var(--fr-space-5); color: var(--fr-text); }
.fr-problem-at { font-family: var(--fr-font-mono); color: var(--fr-text-soft); }
.fr-problem-hint { display: block; color: var(--fr-text-soft); }
.fr-error-hint { margin: 0; color: var(--fr-text-soft); font-size: var(--fr-fs-xs); overflow-wrap: break-word; }
.fr-figure,
.fr-image { margin: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-figure-title { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-medium); font-size: var(--fr-fs-sm); }
.fr-figure-body svg { width: 100%; height: 160px; display: block; }
.fr-image-img { max-width: 100%; height: auto; display: block; border-radius: var(--fr-radius-mark); image-rendering: pixelated; }
.fr-image-caption { color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
.fr-kv-block { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-kv-title { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-medium); }
.fr-gauge-block { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
.fr-led-block.fr-lamp .fr-led-lamp { width: 24px; height: 24px; }
.fr-spacer { height: 0; }
.fr-spacer-inner { height: var(--fr-space-2); }
.fr-spacer-group { height: var(--fr-space-4); }
.fr-spacer-section { height: var(--fr-space-6); }
.fr-form { display: flex; flex-direction: column; gap: var(--fr-space-4); align-items: flex-start; min-width: 0; }
.fr-form > * { align-self: stretch; }
.fr-form > .fr-btn { align-self: flex-start; }
.fr-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); }
.fr-range-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--fr-space-3); }
.fr-multi { display: flex; flex-direction: column; gap: var(--fr-space-2); }
.fr-empty-block { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-3); }
.fr-app-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--fr-space-3) var(--fr-space-6);
  padding: var(--fr-space-3) var(--fr-space-6);
  border-bottom: 1px solid var(--fr-border);
  background: var(--fr-surface-1);
  color: var(--fr-text);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-sm);
}
.fr-app-toolbar .fr-seg-field,
.fr-app-toolbar .fr-toggle-field { flex-direction: row; align-items: center; gap: var(--fr-space-3); }
.fr-app-actions { display: flex; flex-wrap: wrap; gap: var(--fr-space-2); align-items: center; }
.fr-app-runonly { text-decoration: none; }

/* ---- The agent's app: its reply streaming in, and the host's confirmations ----- */
.fr-app-streaming {
  margin: 0;
  padding: var(--fr-space-2) var(--fr-space-6);
  color: var(--fr-text-2);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-sm);
}
.fr-confirm {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: var(--fr-space-3) var(--fr-space-4);
  border: 1px solid var(--fr-warn);
  border-radius: var(--fr-radius-control);
  background: var(--fr-warn-soft);
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-2);
}
.fr-confirm-title { margin: 0; color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }
.fr-confirm-body { margin: 0; color: var(--fr-text); overflow-wrap: anywhere; }
.fr-confirm-list {
  margin: 0;
  padding-left: var(--fr-space-5);
  color: var(--fr-text);
  font-family: var(--fr-font-mono);
  font-size: var(--fr-fs-xs);
  overflow-wrap: anywhere;
}
.fr-confirm-actions { display: flex; flex-wrap: wrap; gap: var(--fr-space-2); }
.fr-share,
.fr-app-editor {
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-2);
  padding: var(--fr-space-3) var(--fr-space-6);
  border-bottom: 1px solid var(--fr-border);
  background: var(--fr-surface-1);
  color: var(--fr-text);
  font-family: var(--fr-font-ui);
  font-size: var(--fr-fs-sm);
}
.fr-share-note { margin: 0; color: var(--fr-text-2); }
.fr-app-passes .fr-field { max-width: 360px; }
.fr-share-note code { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); font-variant-ligatures: none; color: var(--fr-text); overflow-wrap: anywhere; }
.fr-share-refused { margin: 0; color: var(--fr-crit-text); font-weight: var(--fr-fw-medium); white-space: pre-line; }
.fr-app-source { min-height: 200px; font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); }
/* ---- Why each component, the checks the app keeps, and the two layouts --------- */
.fr-app-why > summary { cursor: pointer; font-weight: var(--fr-fw-medium); color: var(--fr-text); }
.fr-why-list {
  margin: var(--fr-space-2) 0 0;
  padding-left: var(--fr-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-1);
  color: var(--fr-text-2);
}
.fr-why-list b { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
.fr-why-off { color: var(--fr-warn-text); }
.fr-check-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); }
.fr-check { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--fr-space-1) var(--fr-space-3); }
.fr-check code { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); font-variant-ligatures: none; color: var(--fr-text); overflow-wrap: anywhere; }
.fr-check-why { color: var(--fr-text-2); }
.fr-check-broken code { color: var(--fr-crit-text); }
.fr-check-summary { margin: 0; font-weight: var(--fr-fw-medium); color: var(--fr-text); }
.fr-check-summary-broken { color: var(--fr-crit-text); }
.fr-app-ab { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--fr-space-4); }
.fr-app-ab-col {
  display: flex;
  flex-direction: column;
  gap: var(--fr-space-2);
  min-width: 0;
  padding: var(--fr-space-3);
  border: 1px solid var(--fr-border);
  border-radius: var(--fr-radius-card);
  background: var(--fr-surface-sunk);
}
.fr-app-ab-col .fr-app { padding: var(--fr-space-3); }
.fr-app-ab-name { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); }
/* Run-only mode is the page: in flow, so the page (not a box in it) scrolls, and the
   editor behind it is hidden rather than covered. */
.fr-runonly {
  min-height: 100vh;
  background: var(--fr-bg);
  color: var(--fr-text);
  font-family: var(--fr-font-ui);
}
.fr-runonly-bar {
  display: flex;
  justify-content: flex-end;
  max-width: 1328px;
  margin: 0 auto;
  padding: var(--fr-space-3) var(--fr-space-6) 0;
}
.fr-runonly-bar .fr-btn { text-decoration: none; }
.fr-runonly > .fr-placeholder { max-width: 1280px; margin: var(--fr-space-4) auto 0; }

@media (max-width: 479px) {
  .fr-grid-narrow,
  .fr-grid-medium,
  .fr-grid-wide { grid-template-columns: minmax(0, 1fr); }
  .fr-h1,
  .fr-stat-figure,
  .fr-gauge-figure { font-size: var(--fr-fs-xl); }
  .fr-gallery-head { padding: var(--fr-space-4) var(--fr-space-4) 0; }
  .fr-gallery-main { padding: var(--fr-space-6) var(--fr-space-4) var(--fr-space-10); gap: var(--fr-space-10); }
  .fr-card { padding: var(--fr-space-4); }
  .fr-donut { justify-content: center; }
  .fr-app { padding: var(--fr-space-4); }
  .fr-app-toolbar,
  .fr-share,
  .fr-app-editor { padding-left: var(--fr-space-4); padding-right: var(--fr-space-4); }
  .fr-runonly-bar { padding: var(--fr-space-3) var(--fr-space-4) 0; }
  .fr-app-ab { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .fr-skel { animation: none; opacity: 0.6; }
  .fr-tip { transition: none; }
}
