/*
 * PCR Lab web UI.
 *
 * Styled entirely on the lab's own first-party design tokens (`lab-tokens.css`) - a dense
 * analytical tool's visual system, not a copy of any other app's theme. Every color, space,
 * radius, and font value below is a `--lab-*` custom property; no hex literals, no ad hoc
 * pixel values for anything the token set already names. Light and dark both resolve through
 * `lab-tokens.css`'s `prefers-color-scheme` swap - nothing in this file branches on theme.
 */

/* Every toggled shell element below sets its own `display: flex` at the same specificity as the
   UA's `[hidden] { display: none }` rule. At equal specificity, any author declaration beats a
   UA declaration regardless of source order, so `!important` is required here - reordering the
   rule would not help. Without it, `lab.js` would still set `hidden` but it would have no visual
   effect. */
[hidden] {
  display: none !important;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--lab-font);
  font-size: var(--lab-text-3);
  line-height: 1.45;
  background: var(--lab-page);
  color: var(--lab-ink);
}

a,
a:visited {
  color: var(--lab-accent-strong);
}

a {
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

:focus-visible {
  outline: 2px solid var(--lab-accent);
  outline-offset: -1px;
}

/* ---- shell layout ---------------------------------------------------------
   Below 1024px the rail collapses into a horizontal top strip; at 1024px and
   up #lab-shell becomes a two-column grid with the rail spanning the full
   height of the left column. */
#lab-shell {
  min-height: 100vh;
  background: var(--lab-page);
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "rail"
    "banner"
    "signin"
    "main";
}

@media (min-width: 1024px) {
  #lab-shell {
    grid-template-columns: 280px 1fr;
    grid-template-rows: auto auto 1fr;
    grid-template-areas:
      "rail banner"
      "rail signin"
      "rail main";
  }

  /* Signed out, `lab.js` sets `hidden` on the rail but the 280px column it occupies stays in
     the grid, so the sign-in card centers itself on the remaining column instead of on the
     page. Collapse back to one column for exactly that state. */
  #lab-shell:has(> #lab-nav[hidden]) {
    grid-template-columns: 1fr;
    grid-template-areas:
      "banner"
      "signin"
      "main";
  }
}

/* ---- rail ------------------------------------------------------------- */
.lab-rail {
  grid-area: rail;
  display: flex;
  flex-direction: column;
  gap: var(--lab-space-2);
  padding: var(--lab-space-2);
  background: var(--lab-page);
  border-bottom: 1px solid var(--lab-hairline);
}

@media (min-width: 1024px) {
  .lab-rail {
    border-bottom: 0;
    border-right: 1px solid var(--lab-hairline);
    /* Pin the rail to the viewport. Without this the rail stretches to the full document
       height and `.lab-user`'s `margin-top: auto` lands the Sign out button at the very
       BOTTOM of the page - thousands of pixels below the fold on a chart-heavy run page,
       which reads as the button having disappeared. Sticky + own scrollbar keeps the whole
       rail (nav, gate chip, sign out) in view no matter how tall #lab-main gets. */
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
  }
}

.lab-rail-brand {
  display: flex;
  align-items: center;
  gap: var(--lab-space-2);
  padding: var(--lab-space-3);
}

.lab-rail-brand img {
  width: 120px;
  display: block;
  filter: var(--lab-logo-filter);
}

.lab-rail-appname {
  font-size: var(--lab-text-1);
  font-weight: var(--lab-weight-medium);
  color: var(--lab-ink-2);
}

.lab-shell-indicator {
  margin-left: auto;
}

.lab-rail-links {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

@media (max-width: 1023px) {
  .lab-rail-links {
    flex-direction: row;
    flex-wrap: wrap;
  }
}

.lab-rail-link {
  display: flex;
  align-items: center;
  gap: var(--lab-space-3);
  padding: var(--lab-space-2) var(--lab-space-3);
  border-radius: var(--lab-radius-3);
  color: var(--lab-ink);
  font-weight: var(--lab-weight-medium);
  text-decoration: none;
}

.lab-rail-link:hover {
  color: var(--lab-accent);
  background: var(--lab-wash);
}

.lab-rail-link.active {
  background: var(--lab-wash);
  color: var(--lab-accent-strong);
}

.lab-rail-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--lab-ink-muted);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}

.lab-rail-link:hover .lab-rail-icon,
.lab-rail-link.active .lab-rail-icon {
  color: currentColor;
}

.lab-user {
  display: flex;
  align-items: center;
  gap: var(--lab-space-3);
  padding: var(--lab-space-3);
  margin-top: auto;
  font-size: var(--lab-text-1);
  color: var(--lab-ink-2);
}

.lab-user #lab-user-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lab-user #sign-out {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

/* The theme toggle reads as rail chrome (quiet icon button), not a primary action. */
.lab-theme-toggle {
  background: none;
  padding: 0 var(--lab-space-1);
  color: var(--lab-ink-muted);
}

.lab-theme-toggle:hover {
  color: var(--lab-accent);
  background: var(--lab-wash);
}

/* Same trick as the nav links above: the icon sets its own `color`, so the hover accent
   only reaches it through an explicit currentColor hand-off. */
.lab-theme-toggle:hover .lab-rail-icon {
  color: currentColor;
}

/* ---- plate / main ------------------------------------------------------ */
#lab-error-banner {
  grid-area: banner;
}

.lab-main {
  grid-area: main;
  padding: var(--lab-space-5);
  background: var(--lab-wash);
  min-width: 0;
}

.lab-page > h1 {
  margin: 0 0 var(--lab-space-4);
  font-size: var(--lab-text-6);
  line-height: 1.3;
  font-weight: var(--lab-weight-bold);
}

/* ---- cards -------------------------------------------------------------- */
/* Shared surface treatment with .sign-in (see that rule below). */
.lab-card,
.sign-in {
  border: 1px solid var(--lab-hairline);
  border-radius: var(--lab-radius-3);
  background-color: var(--lab-surface);
}

.lab-card {
  margin: var(--lab-space-4) 0;
  padding: var(--lab-space-4);
  background-clip: padding-box;
}

.lab-card > :first-child {
  margin-top: 0;
}

.lab-card > :last-child {
  margin-bottom: 0;
}

/* ---- typography ---------------------------------------------------------- */
/* Section headings were demoted h3->h2 and h4->h3 to fix a heading-order skip
   (h1 straight to h3/h4). These pin the rendered sizes to what the UA gave the
   pre-demotion tags, so the a11y fix keeps the rendered sizes unchanged. */
.lab-page h2 {
  font-size: var(--lab-text-4);
  line-height: 1.3;
}

.lab-page h3 {
  font-size: var(--lab-text-3);
  line-height: 1.3;
}

.lab-muted {
  color: var(--lab-ink-2);
  font-size: var(--lab-text-1);
}

/* `.lab-warning` / `.lab-status*` lived here until the status vocabulary below replaced
   every one of their uses with a badge or a callout; they are gone rather than left as
   two ways to say the same thing. */
.lab-unavailable {
  color: var(--lab-ink-muted);
  font-style: italic;
}

code {
  font-family: var(--lab-mono);
  font-size: var(--lab-text-1);
  color: var(--lab-accent-strong);
  background: var(--lab-accent-wash);
  padding: 2px 5px;
  border-radius: var(--lab-radius-1);
}

/* ---- fact lists / plain lists -------------------------------------------- */
.lab-fact-list {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--lab-space-2) var(--lab-space-4);
  margin: var(--lab-space-4) 0;
}

.lab-fact-list dt {
  font-weight: var(--lab-weight-bold);
  color: var(--lab-ink-2);
}

.lab-fact-list dd {
  margin: 0;
}

.lab-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--lab-space-2);
}

/* ---- tables --------------------------------------------------------------- */
.lab-table-scroll {
  overflow-x: auto;
}

.lab-table {
  border-collapse: collapse;
  width: 100%;
  margin: var(--lab-space-2) 0 var(--lab-space-4);
  font-size: var(--lab-text-1);
}

.lab-table th,
.lab-table td {
  text-align: left;
  padding: var(--lab-space-2);
  box-shadow: inset 0 -1px var(--lab-hairline);
}

.lab-table th {
  font-weight: var(--lab-weight-bold);
  color: var(--lab-ink);
}

.lab-table tbody tr:last-child > * {
  box-shadow: none;
}

/* Multi-level overrides (e.g. match_level_factors' "L3: 10 -> 15" lines,
   routes_analysis._format_match_level_factor_override) render one level per line - every other
   override value is a single line, so pre-line is a no-op for those rows. */
.lab-changed-param-value {
  white-space: pre-line;
}

/* ---- lab-specific layout --------------------------------------------------- */
.lab-variant-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--lab-space-3);
}

.lab-run-panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--lab-space-3);
}

.lab-param-row {
  padding: var(--lab-space-3) 0;
  border-bottom: 1px solid var(--lab-hairline);
}

.lab-param-row label {
  font-weight: var(--lab-weight-bold);
}

.lab-param-row input[type="text"] {
  margin-top: var(--lab-space-2);
  width: 12rem;
}

/* The `match_level_factors` row's five L1..L5 inputs (_param_sliders.html) - one label+input
   pair per overridable level, laid out inline instead of the single wide input every other
   row's `.lab-param-row input[type="text"]` gets. */
.lab-param-row-levels {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lab-space-3);
  margin-top: var(--lab-space-2);
}

.lab-param-row-levels label {
  margin-bottom: var(--lab-space-1);
}

.lab-param-row-levels input[type="text"] {
  width: 5rem;
}

/* The advisory caution note `lab.js` shows/hides under a slider whose typed value sits outside
   its `data-caution-below`/`data-caution-above` band - reuses the callout/badge system's own
   warning color rather than a second visual language for "this looks off". */
.lab-input-caution {
  margin: var(--lab-space-1) 0 0;
  color: var(--lab-warn-text);
  font-size: var(--lab-text-1);
}

.lab-analysis-links {
  display: flex;
  gap: var(--lab-space-4);
}

.lab-degraded {
  max-width: 32rem;
}

.lab-diff {
  overflow-x: auto;
  padding: var(--lab-space-3);
  border: 1px solid var(--lab-hairline);
  border-radius: var(--lab-radius-3);
  font-family: var(--lab-mono);
  font-size: var(--lab-text-1);
}

/* ---- scorecard dashboard (family accent-bar cards + stat tiles) ----------- */
/* The 3px left accent bar is the identity's signature device for family provenance - the same
   fixed family->hue mapping (backtest/pool/stability) reappears wherever these families show
   up. Color carries family identity only, never a value judgment about the numbers inside. */
.lab-scorecard-card {
  border-left: 3px solid var(--lab-hairline);
}

.lab-scorecard-card[data-family="backtest"] {
  border-left-color: var(--lab-series-1);
}

.lab-scorecard-card[data-family="pool"] {
  border-left-color: var(--lab-series-3);
}

.lab-scorecard-card[data-family="stability"] {
  border-left-color: var(--lab-series-7);
}

.lab-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--lab-space-4);
  margin: var(--lab-space-2) 0 var(--lab-space-3);
}

.lab-stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--lab-space-1);
}

.lab-stat-value {
  font-family: var(--lab-mono);
  font-size: var(--lab-text-5);
  font-variant-numeric: tabular-nums;
  color: var(--lab-ink);
}

.lab-stat-label {
  font-size: var(--lab-text-1);
  color: var(--lab-ink-2);
}

/* ---- lineage sparkline (stat tile, re-run history) ------------------------ */
/* Reuses each family's own accent-bar hue (`--lab-series-1`/`-3`/`-7`) for the sparkline's
   stroke/dot - never a new color - so the sparkline reads as belonging to the card it sits in,
   the same rule the accent bar itself follows. */
.lab-stat-spark {
  display: block;
  margin-top: calc(-1 * var(--lab-space-1));
}

.lab-stat-spark svg {
  display: block;
  width: 100%;
  max-width: 6rem;
  height: auto;
}

.lab-spark-line {
  fill: none;
  stroke: var(--lab-ink-2);
}

.lab-spark-dot {
  fill: var(--lab-ink-2);
}

.lab-scorecard-card[data-family="backtest"] .lab-spark-line,
.lab-scorecard-card[data-family="backtest"] .lab-spark-dot {
  stroke: var(--lab-series-1);
  fill: var(--lab-series-1);
}

.lab-scorecard-card[data-family="pool"] .lab-spark-line,
.lab-scorecard-card[data-family="pool"] .lab-spark-dot {
  stroke: var(--lab-series-3);
  fill: var(--lab-series-3);
}

.lab-scorecard-card[data-family="stability"] .lab-spark-line,
.lab-scorecard-card[data-family="stability"] .lab-spark-dot {
  stroke: var(--lab-series-7);
  fill: var(--lab-series-7);
}

/* The raw table's `<details>` wrapper - "every visual has its numbers one click away". */
.lab-scorecard-table summary {
  cursor: pointer;
  color: var(--lab-ink-2);
  font-size: var(--lab-text-1);
}

.lab-scorecard-table[open] summary {
  margin-bottom: var(--lab-space-2);
}

/* ---- tooltip (legend-backed inline definitions, CSS-only) ----------------- */
/* `.lab-tip` wraps a short trigger; `.lab-tip-bubble` is inert markup shown only via `:hover`/
   `:focus-visible` (keyboard accessible), never JS-positioned - see `_macros.html`'s `tip()`
   macro. `left: 0` inside the tile's own `position: relative` stacking context is the accepted
   simple positioning; no viewport-edge JS clamp. */
.lab-tip {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted var(--lab-ink-muted);
}

.lab-tip-bubble {
  display: none;
  position: absolute;
  left: 0;
  bottom: calc(100% + var(--lab-space-1));
  z-index: 20;
  max-width: 36ch;
  padding: var(--lab-space-2) var(--lab-space-3);
  background: var(--lab-surface);
  color: var(--lab-ink);
  border: 1px solid var(--lab-border);
  border-radius: var(--lab-radius-2);
  font-size: var(--lab-text-1);
  font-weight: normal;
  line-height: 1.45;
  box-shadow: 0 2px 8px var(--lab-wash);
}

.lab-tip:hover .lab-tip-bubble,
.lab-tip:focus-visible .lab-tip-bubble {
  display: block;
}

/* ---- charts (lab-charts.js mounts ECharts canvases here) ------------------ */
.lab-chart {
  min-height: 220px;
  margin: var(--lab-space-4) 0;
}

/* A mount whose renderer no-opped (absent/empty payload) has no canvas child - collapse it
   rather than reserving a 220px hole. */
.lab-chart:empty {
  display: none;
}

/* ---- golden-key trajectory filter (`_macros.html`'s trajectory_charts_section) ------------ */
.lab-traj-filter {
  width: auto;
  min-width: 12rem;
  margin-bottom: var(--lab-space-4);
}

.lab-traj-block {
  margin-bottom: var(--lab-space-5);
}

/* ---- rating-pool distribution charts (run_detail.html, one block per bucket) -------------- */
.lab-dist-block {
  margin-bottom: var(--lab-space-5);
}

/* ---- N-way compare (compare_picker.html / compare_nway.html) -------------------------------- */
/* One card per selected run, side by side up to the 4-run cap - narrower than .lab-run-panels'
   cards since an N-way column carries scorecard families only, never leaderboards/movers. */
.lab-nway-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--lab-space-3);
}

/* ---- forms / buttons / fields ---------------------------------------------- */
label {
  display: block;
  font-size: var(--lab-text-2);
  font-weight: var(--lab-weight-bold);
  margin-bottom: var(--lab-space-1);
}

input[type="text"],
input[type="email"],
input[type="password"],
textarea {
  width: 100%;
  padding: 0 var(--lab-space-2);
  height: var(--lab-space-6);
  border-radius: var(--lab-radius-2);
  border: 1px solid var(--lab-hairline);
  background-color: var(--lab-surface);
  color: var(--lab-ink);
  font-family: inherit;
  font-size: var(--lab-text-2);
}

textarea,
.lab-spec-editor {
  height: auto;
  padding: var(--lab-space-2);
  font-family: var(--lab-mono);
  font-size: var(--lab-text-1);
}

/* House button = "secondary soft": every plain <button> (Sign out, Refresh, the
   experiment-run submit buttons) gets this treatment. `.lab-button-solid` is the one
   primary exception (the sign-in submit).
   `min-height` (not `height`) sizes the box intrinsically: one-line labels still land at
   exactly 32px because their content never exceeds the floor, but multi-line content -
   the wizard question cards (`.lab-wizard-card` resets `display` to `block`) and
   `.lab-button-solid` labels that wrap on narrow viewports - grows the box to fit instead
   of clipping it. */
button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--lab-space-2);
  min-height: var(--lab-space-6);
  padding: 0 var(--lab-space-3);
  border: 0;
  border-radius: var(--lab-radius-2);
  font-family: var(--lab-font);
  font-size: var(--lab-text-2);
  font-weight: var(--lab-weight-medium);
  background-color: var(--lab-accent-wash);
  color: var(--lab-accent-strong);
  cursor: pointer;
}

button:active {
  background-color: var(--lab-accent-wash);
}

.lab-button-solid {
  background-color: var(--lab-accent);
  color: var(--lab-accent-contrast);
}

.lab-button-solid:active {
  background-color: var(--lab-accent);
}

/* ---- sign-in card ---------------------------------------------------------- */
/* Surface treatment (border/radius/background) is shared with .lab-card above; only this
   card's layout lives here. */
.sign-in {
  grid-area: signin;
  width: 100%;
  max-width: 24rem;
  margin: var(--lab-space-8) auto;
  padding: var(--lab-space-5);
}

.sign-in form {
  display: flex;
  flex-direction: column;
  gap: var(--lab-space-2);
}

.sign-in-logo {
  width: 140px;
  align-self: center;
  filter: var(--lab-logo-filter);
}

.sign-in-heading {
  margin: var(--lab-space-2) 0 0;
  font-size: var(--lab-text-5);
  line-height: 1.3;
  font-weight: var(--lab-weight-bold);
  text-align: center;
}

.sign-in-subtitle {
  margin: 0 0 var(--lab-space-3);
  text-align: center;
}

/* Mirrors the main app's sign-in: the primary action spans the card. */
.sign-in .lab-button-solid {
  width: 100%;
  margin-top: var(--lab-space-3);
}

.sign-in .lab-button-solid:disabled {
  opacity: 0.6;
  cursor: default;
}

.sign-in-error {
  color: var(--lab-critical-text);
  font-size: var(--lab-text-1);
}

/* ---- error banner ------------------------------------------------------- */
.lab-error-banner {
  margin: 0;
  padding: var(--lab-space-3) var(--lab-space-5);
  color: var(--lab-accent-contrast);
  background: var(--lab-critical);
  font-size: var(--lab-text-2);
}

/* ---- status vocabulary (PR 2: comp-05 status-line idiom) ------------------
   Soft badges + callouts built from the token scales. Semantic colors follow
   the lab's own conventions: green = pass/success, red = fail/error,
   amber = warning/pending, blue = running/informational, gray = neutral. */
.lab-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--lab-space-1);
  padding: 0 var(--lab-space-2);
  border-radius: var(--lab-radius-2);
  font-size: var(--lab-text-1);
  line-height: 1.3;
  font-weight: var(--lab-weight-medium);
  white-space: nowrap;
}

.lab-badge-green {
  background: var(--lab-wash);
  color: var(--lab-good-text);
}

.lab-badge-red {
  background: var(--lab-wash);
  color: var(--lab-critical-text);
}

.lab-badge-amber {
  background: var(--lab-wash);
  color: var(--lab-warn-text);
}

.lab-badge-blue {
  background: var(--lab-accent-wash);
  color: var(--lab-accent-strong);
}

.lab-badge-gray {
  background: var(--lab-wash);
  color: var(--lab-ink-2);
}

.lab-callout {
  display: flex;
  /* Wrap so a callout's action (the re-run form) drops to its own full-width row instead of
     being squeezed into a shrunken flex column beside a long paragraph on narrow screens. */
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--lab-space-2);
  padding: var(--lab-space-3) var(--lab-space-4);
  border-radius: var(--lab-radius-3);
  margin: var(--lab-space-3) 0;
  font-size: var(--lab-text-2);
}

.lab-callout > form {
  flex: 1 0 100%;
}

.lab-callout-green {
  background: var(--lab-wash);
  color: var(--lab-good-text);
}

.lab-callout-red {
  background: var(--lab-wash);
  color: var(--lab-critical-text);
}

.lab-callout-amber {
  background: var(--lab-wash);
  color: var(--lab-warn-text);
}

/* ---- numeric + identifier conventions ------------------------------------ */
/* Figures line up column-wise by digit width. Alignment is deliberately NOT set here: the
   class also marks member ids and rank cells, which read better left-aligned with the rest of
   the table, and `.lab-table td` would out-specify a `text-align` on this class anyway. */
.lab-num {
  font-variant-numeric: tabular-nums;
}

.lab-delta-up {
  color: var(--lab-delta-up);
}

.lab-delta-down {
  color: var(--lab-delta-down);
}

.lab-delta-none {
  color: var(--lab-ink-2);
}

/* Full string stays in the DOM (find-in-page and copy keep working); only the
   rendering is clipped. One click selects the whole value. */
.lab-fingerprint {
  display: inline-block;
  max-width: 14ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
  user-select: all;
}

.lab-timestamp-exact {
  color: var(--lab-ink-2);
  background: var(--lab-wash);
}

/* ---- PCSL target-mark spinner (brand mark, spun by CSS rotation) ---------- */
/* `_macros.html`'s `target_spinner()` macro is the one place this SVG markup is written; every
   size/state rule here is scoped to the `.lab-target-spinner` class it emits. */
.lab-target-spinner {
  display: inline-block;
  flex-shrink: 0;
  vertical-align: middle;
  filter: drop-shadow(var(--lab-target-shadow));
  animation: lab-target-spin 1.1s linear infinite;
}

.lab-target-spinner path {
  stroke-width: 8;
}

.lab-target-outline {
  fill: var(--lab-target-fill);
  stroke: var(--lab-target-stroke);
}

.lab-target-azone,
.lab-target-czone {
  fill: none;
  stroke: var(--lab-target-stroke);
}

.lab-target-sm { width: 16px; height: 16px; }
.lab-target-md { width: 24px; height: 24px; }
.lab-target-lg { width: 48px; height: 48px; }

@keyframes lab-target-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .lab-target-spinner {
    animation: none;
  }
}

/* `base.html` sets `includeIndicatorStyles:false` (htmx's own default indicator CSS is never
   injected), so this is the only place `.htmx-indicator`/`.htmx-request` visibility is wired:
   hidden at rest, shown only while the element it's attached to (via a matching `hx-indicator`)
   is actually in flight. */
.lab-target-spinner.htmx-indicator {
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms ease-in;
}

.lab-target-spinner.htmx-indicator.htmx-request {
  opacity: 1;
  visibility: visible;
}

/* ---- gate trust chip (rail footer) ---------------------------------------- */
.lab-gate-chip {
  padding: var(--lab-space-2) var(--lab-space-3);
  font-size: var(--lab-text-1);
  color: var(--lab-ink-2);
  display: flex;
  flex-direction: column;
  gap: var(--lab-space-1);
  align-items: flex-start;
}

/* ---- legend rows (progressive disclosure) --------------------------------- */
.lab-param-current {
  font-size: var(--lab-text-1);
  color: var(--lab-ink-2);
  white-space: nowrap;
}

.lab-param-details summary {
  cursor: pointer;
  font-size: var(--lab-text-1);
  color: var(--lab-accent-strong);
}

.lab-param-details[open] summary {
  margin-bottom: var(--lab-space-1);
}

/* ---- interactive cards (preset pickers) ----------------------------------- */
.lab-card-interactive {
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.lab-card-interactive:hover {
  background-color: var(--lab-wash);
  border-color: var(--lab-hairline);
}

.lab-card-interactive:active {
  transform: scale(0.98);
}

@media (prefers-reduced-motion: reduce) {
  .lab-card-interactive,
  .lab-card-interactive:active {
    transition: none;
    transform: none;
  }
}

/* ---- wizard (question-first new-experiment path) --------------------------- */
.lab-wizard-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--lab-space-3);
  margin-bottom: var(--lab-space-3);
}

/* The step-1 question cards are `<button>` elements (a safe GET fragment swap, not a link to a
   resource) - this resets the UA's own button chrome down to `.lab-card`'s shared surface. */
.lab-wizard-card {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.lab-wizard-mode-tag {
  margin-top: var(--lab-space-1);
  font-size: var(--lab-text-1);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.lab-wizard-step2 {
  margin-top: var(--lab-space-3);
}

.lab-wizard-step2 label {
  display: block;
  margin-top: var(--lab-space-3);
  font-weight: var(--lab-weight-bold);
}

.lab-wizard-step2 input[type="text"],
.lab-wizard-step2 select {
  margin-top: var(--lab-space-1);
  width: 100%;
  max-width: 20rem;
}

/* Top-3 medal badges (leaderboards). Gold/bronze are the lab's own mode-invariant tokens. */
.lab-badge-gold {
  background: var(--lab-wash);
  color: var(--lab-medal-gold);
}

.lab-badge-bronze {
  background: var(--lab-wash);
  color: var(--lab-medal-bronze);
}
