/* ice-lab.css — the interactive engineering labs.
   ICE tokens only: no raw hex, no new fonts, no new type scale.

   The band is deliberately dark in BOTH themes, like every other .band--dark
   surface: the 3D content is a lit schematic on a night field, and inverting it
   in light mode would leave the WebGL frame floating on white with nothing to
   read it against. What must work in both themes is the surrounding page and
   the contrast of every label in here — which is why nothing below borrows a
   semantic --ice-color-* token that flips underneath it. */

.lab {
  position: relative;
  background: var(--ice-palette-navy-900);
  color: var(--ice-palette-warm-50);
  padding-block: var(--ice-space-fluid-56-88);
}

/* The header is fixed, and nothing on this site clears it for you — every hero
   adds --nav-h to its own top padding (.hero and .page-hero both do). The lab
   never needed that while it sat mid-page; opening the page, it does, and
   without it the kicker prints straight over the college name. Keyed off
   :first-child rather than a modifier class so any lab that opens any page gets
   this right without being told. */
.lab:first-child {
  padding-top: calc(var(--nav-h) + var(--ice-space-8));
}

/* This band is navy in BOTH themes, but the page-level typography rules are
   written for a light canvas: in light mode `.sec-head .label` resolves to
   --ice-color-text-accent (terracotta-800, a dark brown) and body copy resolves
   to --ice-color-text-muted (slate-600). Both are unreadable here. The design
   system already names the correct pair for a brand-coloured surface, so use
   that rather than a hard-coded hex — and carry enough specificity to beat
   `.page-course main ...` (0,1,2) without reaching for !important. */
/* The lab opens the page, so its title is the page's h1 and carries the display
   size the intro band's headline used to. Slightly tighter than that 5.5rem
   ceiling because this sentence is longer and has to stay on two lines. */
#lab-title {
  margin: 0;
  color: var(--ice-palette-warm-50);
  font-family: var(--ice-font-display);
  font-size: clamp(2.35rem, 4.8vw, 4.1rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
}

.lab .lab-head .course-kicker,
.lab .lab-head .label {
  color: var(--ice-color-text-accent-on-brand);
}

.lab-head {
  max-width: 34ch;
}

.lab .lab-lede {
  color: var(--ice-palette-navy-100);
  max-width: 68ch;
  margin-top: var(--ice-space-4);
}

/* ---- static explanation: no JS / reduced motion / no WebGL2 -------------- */
.lab-static {
  margin-top: var(--ice-space-10);
  display: grid;
  gap: var(--ice-space-6);
  max-width: 78ch;
}

.lab-static__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--ice-space-4);
  counter-reset: labstep;
}

.lab-static__steps li {
  position: relative;
  padding-left: var(--ice-space-10);
  color: var(--ice-palette-navy-100);
  line-height: var(--ice-type-leading-155);
}

.lab-static__steps li b {
  color: var(--ice-palette-warm-50);
}

.lab-static__steps li::before {
  counter-increment: labstep;
  content: counter(labstep, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.1em;
  font-family: var(--ice-font-display);
  color: var(--ice-palette-terracotta-400);
}

.lab-static__note {
  color: var(--ice-palette-navy-100);
  font-style: italic;
  max-width: 62ch;
}

/* The same thirty bays the live lab offers, drawn in plain markup: the
   reduced-motion, no-JS and no-WebGL2 visitor gets the answer the lab teaches,
   not an apology for the thing they cannot load. Each level carries an .sr-only
   sentence and the cells are aria-hidden, so a screen reader reads a sentence
   rather than thirty anonymous boxes. */
.lab-diagram {
  margin: 0;
  display: grid;
  gap: var(--ice-space-3);
  padding: var(--ice-space-5);
  border-radius: var(--ice-radius-surface);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  max-width: 46ch;
}

.lab-diagram__caption {
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-terracotta-400);
  line-height: var(--ice-type-leading-150);
}

.lab-diagram__levels {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--ice-space-2);
}

.lab-diagram__level {
  display: grid;
  grid-template-columns: 2.4rem auto;
  align-items: center;
  gap: var(--ice-space-3);
  padding-left: 0;
}

.lab-diagram__level b {
  grid-row: 1;
  font-size: var(--ice-type-caption-size);
  font-weight: 700;
  color: var(--ice-palette-slate-300);
  line-height: var(--ice-type-leading-110);
}

.lab-diagram__level em {
  grid-column: 1;
  grid-row: 2;
  font-style: normal;
  font-size: var(--ice-type-caption-size);
  color: var(--ice-palette-terracotta-400);
  line-height: var(--ice-type-leading-110);
}

.lab-diagram__bays {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: inline-flex;
  gap: 3px;
}

.lab-diagram__bays i {
  width: 19px;
  height: 22px;
  border: 1px solid var(--ice-palette-line-700);
  border-radius: 3px;
  background: var(--ice-palette-night-950);
}

.lab-diagram__bays i[data-braced="true"] {
  border-color: var(--ice-palette-terracotta-400);
  background:
    linear-gradient(to top right, transparent calc(50% - 1px),
      var(--ice-palette-terracotta-400) calc(50% - 1px),
      var(--ice-palette-terracotta-400) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--ice-palette-night-950);
}

.lab-diagram__key {
  margin: 0;
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-slate-300);
}

.lab--live .lab-static {
  display: none;
}

/* ---- interactive stage --------------------------------------------------- */
.lab-stage {
  margin-top: var(--ice-space-10);
  display: grid;
  gap: var(--ice-space-8);
  grid-template-columns: minmax(0, 1.6fr) minmax(300px, 0.9fr);
  /* stretch, not start: the control panel is the taller column, and leaving the
     viewport at its own height strands a few hundred pixels of empty band under
     the model. The viewport carries a min-height so the single-column layout
     still gets a usable stage. */
  align-items: stretch;
}

.lab-stage[hidden] {
  display: none;
}

/* One column below 960. Block, not a one-column grid, on purpose: a sticky grid
   ITEM is constrained to its own grid area, so a sticky viewport in a one-column
   grid would occupy a single row and stick to nothing. Block flow makes the
   stage the containing block, which is what lets the model stay on screen while
   the controls scroll under it. */
@media (max-width: 960px) {
  .lab-stage {
    display: block;
  }

  .lab-panel {
    gap: var(--ice-space-4);
  }

  /* Content scrolls BEHIND the pinned model, which is what sticky is for — but
     it also means anything scrolled to lands underneath it. Give every panel
     block a scroll margin the height of the model, so scrollIntoView and any
     anchor stops below the canvas instead of behind it. */
  .lab-panel > * {
    scroll-margin-top: calc(46vh + var(--nav-main-h) + var(--ice-space-4));
  }
}

.lab-viewport {
  position: relative;
  min-height: clamp(420px, 58vh, 620px);
  /* Never taller than the window. `align-items: stretch` sizes this column to
     the control panel, and on a short laptop that made the stage taller than the
     viewport itself — the visitor could not see the whole model at once, and the
     lower half of it was unreachable by the pointer. A little empty band under a
     fully visible model beats a model that runs off the screen. */
  max-height: 74vh;
  border-radius: var(--ice-radius-surface);
  overflow: hidden;
  background:
    radial-gradient(130% 95% at 50% 4%, var(--ice-palette-navy-800) 0%, var(--ice-palette-night-950) 72%);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  cursor: grab;
  touch-action: pan-y; /* vertical page scroll still belongs to the page */
}

.lab-viewport.is-orbiting {
  cursor: grabbing;
}

/* A bay is under the pointer and a click will place or remove a brace there. */
.lab-viewport.is-targeting:not(.is-orbiting) {
  cursor: pointer;
}

.lab-viewport:focus-visible {
  outline: 2px solid var(--ice-palette-terracotta-400);
  outline-offset: 3px;
}

/* The model stays on screen while the controls scroll under it. On a phone the
   panel is far taller than the window, so without this you tap a bay and the
   frame you just changed is a thousand pixels above you. Must come AFTER the
   base rule above: same specificity, so source order decides, and declaring it
   earlier silently left `position: relative` in place. */
@media (max-width: 960px) {
  .lab-viewport {
    position: sticky;
    top: calc(var(--nav-main-h) + var(--ice-space-2));
    z-index: 1;
    margin-bottom: var(--ice-space-6);
    /* Shorter than the desktop stage: it has to leave room for the controls
       scrolling beneath it, and 40vh is plenty to read sway on. */
    min-height: clamp(260px, 40vh, 380px);
    max-height: 46vh;
  }
}


.lab-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.lab-hint {
  position: absolute;
  right: var(--ice-space-4);
  bottom: var(--ice-space-3);
  margin: 0;
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
  pointer-events: none;
}

/* ---- side panel ---------------------------------------------------------- */
.lab-panel {
  display: grid;
  gap: var(--ice-space-6);
  align-content: start;
}

.lab-readouts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ice-space-3);
}

.lab-readout {
  padding: var(--ice-space-3) var(--ice-space-4);
  border-radius: var(--ice-radius-control);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  display: grid;
  gap: var(--ice-space-1);
}

.lab-readout__label {
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-readout__value {
  font-family: var(--ice-font-display);
  font-size: 1.35rem;
  line-height: var(--ice-type-leading-110);
  font-weight: 400;
  color: var(--ice-palette-warm-50);
  font-variant-numeric: tabular-nums;
}

.lab-readout--verdict .lab-readout__value[data-state="pass"] {
  color: var(--ice-palette-terracotta-400);
}

.lab-readout--verdict .lab-readout__value[data-state="fail"] {
  color: var(--ice-palette-crimson-400);
}

.lab-readout--verdict .lab-readout__value[data-state="testing"] {
  color: var(--ice-palette-navy-100);
}

.lab-readout--verdict .lab-readout__value[data-state="idle"] {
  color: var(--ice-palette-slate-300);
}

/* ---- budget -------------------------------------------------------------- */
/* The global constraint, so it sits above the per-level design controls rather
   than inside them. The track is aria-hidden: the figure beside it is the
   accessible reading, and a bar that announced a percentage would say less. */
.lab-budget {
  display: grid;
  gap: var(--ice-space-2);
  padding: var(--ice-space-3) var(--ice-space-4);
  border-radius: var(--ice-radius-control);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
}

.lab-budget__head {
  margin: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ice-space-3);
}

.lab-budget__label {
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-budget__value {
  font-family: var(--ice-font-display);
  font-weight: 400;
  color: var(--ice-palette-warm-50);
  font-variant-numeric: tabular-nums;
}

.lab-budget[data-over="true"] .lab-budget__value {
  color: var(--ice-palette-crimson-400);
}

.lab-budget__track {
  position: relative;
  display: block;
  height: 10px;
  border-radius: 999px;
  background: var(--ice-palette-night-950);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  overflow: hidden;
}

.lab-budget__fill {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--ice-palette-terracotta-400);
}

.lab-budget[data-over="true"] .lab-budget__fill {
  background: var(--ice-palette-crimson-400);
}

/* ---- per-storey drift bars ----------------------------------------------- */
.lab-bars-block {
  display: grid;
  gap: var(--ice-space-3);
}

.lab-bars-title {
  margin: 0;
  display: flex;
  justify-content: space-between;
  gap: var(--ice-space-3);
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-bars-title span {
  color: var(--ice-palette-terracotta-400);
}

.lab-bars {
  display: grid;
  gap: var(--ice-space-2);
}

.lab-bars-hint {
  margin: 0;
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-slate-300);
}

/* "Tab to the grid, then use the arrow keys" is instructions for a device this
   visitor does not have. Keyed on the absence of ANY fine pointer rather than on
   `pointer: coarse`, so a touchscreen laptop — which has both — still gets it. */
@media not all and (any-pointer: fine) {
  .lab-hint--keyboard {
    display: none;
  }
}

.lab-bar {
  display: grid;
  grid-template-columns: 2.4rem auto minmax(0, 1fr);
  align-items: center;
  gap: var(--ice-space-3);
}

/* ---- the bay grid --------------------------------------------------------- */
/* Six cells per storey, addressing exactly what a click on the 3D model
   addresses. One tab stop for the whole grid (roving tabindex in the
   controller) and the arrow keys move inside it, so a keyboard visitor reaches
   any of the thirty bays without thirty tab stops. */
.lab-bays {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.lab-bay {
  width: 19px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--ice-palette-line-700);
  border-radius: 3px;
  background: var(--ice-palette-navy-800);
  cursor: pointer;
}

.lab-bay:hover {
  border-color: var(--ice-palette-terracotta-400);
}

/* A braced bay carries a diagonal, the same thing the model draws in the bay. */
.lab-bay[data-braced="true"] {
  border-color: var(--ice-palette-terracotta-400);
  background:
    linear-gradient(to top right, transparent calc(50% - 1px),
      var(--ice-palette-terracotta-400) calc(50% - 1px),
      var(--ice-palette-terracotta-400) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--ice-palette-navy-800);
}

.lab-bay:focus-visible {
  outline: 2px solid var(--ice-palette-terracotta-400);
  outline-offset: 2px;
}

/* A 19x22 cell is a fine mouse target and a bad thumb one. Where the pointer is
   coarse the cells grow to the 44px minimum and share the row's full width
   instead of taking a fixed size — six 44px cells plus a label column overflow a
   360px phone, and flexing them means the grid fits whatever width it is given
   rather than fitting one particular handset. The drift bar moves to its own
   line to make the room. */
@media (pointer: coarse), (max-width: 720px) {
  .lab-bar {
    grid-template-columns: 2.4rem minmax(0, 1fr);
    row-gap: var(--ice-space-2);
  }

  .lab-bays {
    display: flex;
    width: 100%;
  }

  .lab-bay {
    flex: 1;
    min-width: 0;
    height: 44px;
  }

  .lab-bar__track {
    grid-column: 1 / -1;
  }
}

/* Level name over the price of one brace at that level. Stacked rather than
   given its own column: a fourth column would come out of the drift track, which
   is already the narrowest thing in a 300px panel. */
.lab-bar b {
  display: grid;
  font-size: var(--ice-type-caption-size);
  font-weight: 700;
  line-height: var(--ice-type-leading-110);
  color: var(--ice-palette-slate-300);
  font-variant-numeric: tabular-nums;
}

.lab-bar__price {
  font-style: normal;
  font-weight: 400;
  color: var(--ice-palette-terracotta-400);
}

.lab-bar__track {
  position: relative;
  display: block;
  height: 8px;
  border-radius: 999px;
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  overflow: hidden;
}

/* The limit marker sits where drift == 100% of the code limit. The track runs
   to 135% of the limit, so a failing storey visibly overshoots the line rather
   than just pinning full. */
.lab-bar__track::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 74.07%;
  width: 1px;
  background: var(--ice-palette-terracotta-400);
  opacity: 0.75;
}

.lab-bar__fill {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--ice-palette-terracotta-400);
}

.lab-bar__fill.is-over {
  background: var(--ice-palette-crimson-400);
}

/* ---- controls ------------------------------------------------------------ */
.lab-controls {
  display: grid;
  gap: var(--ice-space-4);
}

.lab-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ice-space-3);
}

/* ---- ground motion record picker ----------------------------------------- */
/* Native radios in a fieldset, visually a stacked list. Radios rather than
   buttons because "exactly one of these" is what a radio group means, and the
   arrow-key navigation and grouped announcement come with it correctly. The
   input itself stays in the layout — hiding it and faking the control is how
   keyboard focus ends up invisible. */
.lab-records {
  margin: 0;
  padding: 0;
  border: 0;
  display: grid;
  gap: var(--ice-space-2);
}

.lab-records__legend {
  padding: 0;
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-records__list {
  display: grid;
  gap: var(--ice-space-2);
}

.lab-record {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--ice-space-1) var(--ice-space-3);
  padding: var(--ice-space-2) var(--ice-space-3);
  border-radius: var(--ice-radius-control);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  cursor: pointer;
}

.lab-record:hover {
  box-shadow: inset 0 0 0 1px var(--ice-palette-terracotta-400);
}

.lab-record input[type="radio"] {
  grid-row: span 2;
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--ice-palette-terracotta-400);
  cursor: pointer;
}

.lab-record input:focus-visible {
  outline: 2px solid var(--ice-palette-terracotta-400);
  outline-offset: 3px;
}

.lab-record__name {
  color: var(--ice-palette-warm-50);
  font-weight: 600;
  font-size: var(--ice-type-caption-size);
}

.lab-record__meta {
  color: var(--ice-palette-slate-300);
  font-size: var(--ice-type-caption-size);
  font-variant-numeric: tabular-nums;
}

.lab-record:has(input:checked) {
  box-shadow: inset 0 0 0 1px var(--ice-palette-terracotta-400);
}

.lab-record:has(input:checked) .lab-record__meta {
  color: var(--ice-palette-terracotta-400);
}

.lab-records__note {
  margin: 0;
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-slate-300);
}

/* Name and figures share a line on a phone: three stacked two-line cards is
   170px of a 670px screen spent on a control you touch once per run. The label
   is the tap target and it stays well over 44px tall either way. */
@media (pointer: coarse), (max-width: 720px) {
  .lab-record {
    grid-template-columns: auto auto minmax(0, 1fr);
    align-items: center;
    column-gap: var(--ice-space-2);
    padding: var(--ice-space-2) var(--ice-space-3);
    min-height: 44px;
  }

  .lab-record input[type="radio"] {
    grid-row: auto;
    width: 20px;
    height: 20px;
  }

  .lab-record__meta {
    text-align: right;
  }
}

.lab-shake {
  justify-self: start;
}

.lab-field {
  display: grid;
  gap: var(--ice-space-2);
  color: var(--ice-palette-navy-100);
  font-size: var(--ice-type-caption-size);
}

.lab-field__label {
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-field--switch {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--ice-space-3);
  cursor: pointer;
}

.lab-field input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--ice-palette-terracotta-400);
  cursor: pointer;
}

.lab-field input[type="range"] {
  width: 100%;
  accent-color: var(--ice-palette-terracotta-400);
  cursor: pointer;
}

.lab-field input:focus-visible {
  outline: 2px solid var(--ice-palette-terracotta-400);
  outline-offset: 3px;
}

/* ghost button on a dark band needs its own outline and a light label */
.lab .btn-ghost {
  justify-self: start;
  color: var(--ice-palette-warm-50);
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--ice-palette-slate-300) 55%, transparent);
}

.lab .btn-ghost:hover {
  border-color: var(--ice-palette-warm-50);
  background: color-mix(in srgb, var(--ice-palette-warm-50) 8%, transparent);
}

/* ---- result card --------------------------------------------------------- */
/* Drift and money in one block, because "it stands" is not a result on its own.
   The state colour lives on a left edge rather than in the body text, so the
   sentences keep full-contrast body colour in every state. */
.lab-card {
  display: grid;
  gap: var(--ice-space-2);
  padding: var(--ice-space-4);
  border-radius: var(--ice-radius-control);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  border-left: 3px solid var(--ice-palette-slate-300);
}

.lab-card[data-state="pass"] {
  border-left-color: var(--ice-palette-terracotta-400);
}

.lab-card[data-state="fail"] {
  border-left-color: var(--ice-palette-crimson-400);
}

.lab-card[data-state="testing"],
.lab-card[data-state="partial"] {
  border-left-color: var(--ice-palette-navy-100);
}

.lab-card__head {
  margin: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ice-space-3);
  flex-wrap: wrap;
}

.lab-card__label {
  font-size: var(--ice-type-caption-size);
  letter-spacing: var(--ice-type-track-wide-5);
  text-transform: uppercase;
  color: var(--ice-palette-slate-300);
}

.lab-card__verdict {
  font-family: var(--ice-font-display);
  font-size: 1.15rem;
  font-weight: 400;
  line-height: var(--ice-type-leading-110);
  color: var(--ice-palette-warm-50);
  font-variant-numeric: tabular-nums;
}

.lab-card[data-state="pass"] .lab-card__verdict {
  color: var(--ice-palette-terracotta-400);
}

.lab-card[data-state="fail"] .lab-card__verdict {
  color: var(--ice-palette-crimson-400);
}

/* One chip per record: how THIS design did against each. The set is the point —
   a single verdict cannot say "safe against one earthquake and not another". */
.lab-chips {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ice-space-2);
}

.lab-chip {
  display: grid;
  gap: 2px;
  padding: var(--ice-space-2);
  border-radius: var(--ice-radius-control);
  background: var(--ice-palette-night-950);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-110);
}

.lab-chip b {
  font-weight: 600;
  color: var(--ice-palette-slate-300);
}

.lab-chip i {
  font-style: normal;
  font-variant-numeric: tabular-nums;
  color: var(--ice-palette-slate-300);
}

.lab-chip[data-state="pass"] {
  box-shadow: inset 0 0 0 1px var(--ice-palette-terracotta-400);
}

.lab-chip[data-state="pass"] i {
  color: var(--ice-palette-terracotta-400);
}

.lab-chip[data-state="fail"] {
  box-shadow: inset 0 0 0 1px var(--ice-palette-crimson-400);
}

.lab-chip[data-state="fail"] i {
  color: var(--ice-palette-crimson-400);
}

.lab-chip[data-state="testing"] i {
  color: var(--ice-palette-warm-50);
}

.lab-card__line {
  margin: 0;
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-navy-100);
}

.lab-card__best {
  margin: 0;
  padding-top: var(--ice-space-2);
  border-top: 1px solid var(--ice-palette-line-700);
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-slate-300);
}

.lab-note {
  margin: 0;
  font-size: var(--ice-type-caption-size);
  line-height: var(--ice-type-leading-150);
  color: var(--ice-palette-slate-300);
}

.lab-course-link {
  display: inline-flex;
  align-items: center;
  gap: var(--ice-space-3);
  justify-self: start;
  padding: var(--ice-space-3) var(--ice-space-4);
  border-radius: var(--ice-radius-control);
  text-decoration: none;
  color: var(--ice-palette-warm-50);
  background: var(--ice-palette-navy-800);
  box-shadow: inset 0 0 0 1px var(--ice-palette-line-700);
  font-weight: 600;
}

.lab-course-link i {
  color: var(--ice-palette-terracotta-400);
  font-style: normal;
  transition: transform 0.2s ease;
}

.lab-course-link:hover {
  box-shadow: inset 0 0 0 1px var(--ice-palette-terracotta-400);
}

.lab-course-link:hover i {
  transform: translateX(3px);
}

/* The live-region announcement is the screen-reader path through the lab: it
   carries the verdict as a sentence. Visually hidden, never display:none —
   display:none removes it from the accessibility tree and it would announce
   nothing at all. */
.lab-status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .lab-course-link i {
    transition: none;
  }
}
