/*
 * Course stylesheet (spec §7.6, §4). The only stylesheet linked from a
 * course page, so it imports the site's tokens and element resets and then
 * adds course-only components. Reads tokens exclusively — no raw colours,
 * sizes or fonts. Visible focus, ≥24px targets, polite status text, and
 * `prefers-reduced-motion` are honoured throughout.
 */

@import url("/css/tokens.css");
@import url("/css/base.css");

/* ---- Utilities -------------------------------------------------------------- */

/* Visually hidden but still available to assistive tech (Finding 4: used
 * where a title would otherwise repeat visibly, e.g. a fieldset legend that
 * duplicates the `h3.ix-title` just above it). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The arrow after a link that opens in a new tab (see src/links.ts). */
.ext-mark {
  margin-inline-start: 0.2em;
  font-size: 0.85em;
  text-decoration: none;
}

/* ---- Page frame ------------------------------------------------------------ */

main,
.course-member,
.breadcrumb,
body > .progress-line {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
}

main {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6) var(--space-section);
}

/* Same grid shrink fix as `.unit-layout` below, one level up: without it, a
 * wide child (a compare table, a sequence notice) can force `main`, and the
 * whole page, wider than the viewport (Finding 2). */
main > * {
  min-width: 0;
}

.breadcrumb a {
  display: inline-flex;
  align-items: center;
  min-height: 1.5rem;
  padding-block: var(--space-1);
}

/* A plain row, not a header: the site header is the page's one header bar. */
.course-member {
  padding-top: var(--space-4);
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
}

.breadcrumb {
  padding-top: var(--space-4);
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

main h1 {
  font-size: var(--text-headline);
  line-height: var(--leading-heading);
}

/* ---- Buttons --------------------------------------------------------------- */

.button,
button {
  font-family: var(--font-ui);
}

button {
  min-height: 3rem;
  min-width: 3rem;
  padding: var(--space-2) var(--space-4);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  transition: background-color var(--duration-hover) ease, border-color var(--duration-hover) ease;
}

button:hover {
  border-color: var(--color-accent);
}

button[data-action="commit"],
button[data-action="check"] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}

button[data-action="commit"]:hover,
button[data-action="check"]:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}

.button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.875rem;
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-md);
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  width: fit-content;
}

.button:hover {
  background: var(--color-accent-hover);
  color: var(--color-on-accent);
}

/* ---- Progress --------------------------------------------------------------- */

progress {
  display: block;
  width: 100%;
  height: 0.5rem;
  border: 0;
  border-radius: var(--radius-pill);
  overflow: hidden;
  appearance: none;
  background: var(--color-tint);
  color: var(--color-accent);
}

progress::-webkit-progress-bar {
  background: var(--color-tint);
  border-radius: var(--radius-pill);
}

progress::-webkit-progress-value {
  background: var(--color-accent);
  border-radius: var(--radius-pill);
  transition: width var(--duration-hover) var(--ease-out);
}

progress::-moz-progress-bar {
  background: var(--color-accent);
  border-radius: var(--radius-pill);
}

.progress-line {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.progress-line progress {
  flex: 1 1 auto;
  max-width: 20rem;
}

/* ---- Course home: week tiles ------------------------------------------------ */

.week-tiles {
  display: grid;
  gap: var(--space-5);
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}

.week-tile {
  position: relative;
  display: grid;
  gap: var(--space-2);
  height: 100%;
  padding: var(--space-5);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  transition: border-color var(--duration-hover) ease;
}

.week-tile:hover,
.week-tile:has(a:focus-visible) {
  border-color: var(--color-accent);
}

.week-tile > a {
  display: grid;
  gap: var(--space-2);
  color: var(--color-ink);
  text-decoration: none;
}

/* Stretched-link: the tile's only `<a>` wraps just the number, theme and
 * title, then covers the whole card via `::after`, so the entire tile is
 * clickable without nesting a second `<a>` inside it (no `[[term]]` link in
 * the plain-text question can ever break the DOM — Finding 1). */
.week-tile > a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.week-number {
  color: var(--color-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.week-theme {
  color: var(--color-accent);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.week-tile h2 {
  font-size: var(--text-lg);
}

.week-question {
  color: var(--color-muted);
}

.week-progress-text,
.week-status {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-muted);
}

/* ---- Week page: modules and units -------------------------------------------- */

.week-outcomes {
  display: grid;
  gap: var(--space-2);
  padding-left: var(--space-5);
}

.week-module {
  display: grid;
  gap: var(--space-3);
  padding-block: var(--space-4);
  border-top: var(--rule-width) solid var(--color-rule);
}

.week-module ol {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  list-style: none;
}

.week-unit {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  font-family: var(--font-ui);
}

.week-unit.complete a {
  color: var(--color-muted);
}

.unit-minutes {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.discuss {
  padding: var(--space-5);
  border-radius: var(--radius-md);
  background: var(--color-tint);
}

/* ---- Unit layout: left rail + article --------------------------------------- */

.unit-layout {
  display: grid;
  gap: var(--space-6);
}

/* Grid items otherwise refuse to shrink below their content's intrinsic
 * (max-content) width — e.g. a wide `.compare` table — which would push
 * `.unit-layout`, and the page, wider than the viewport on mobile even
 * though `.table-scroll` is ready to absorb that overflow internally
 * (Finding 2). */
.unit-layout > * {
  min-width: 0;
}

.week-rail {
  display: none;
}

.week-rail ol,
.week-rail-phone ol {
  display: grid;
  gap: var(--space-1);
  padding: 0;
  list-style: none;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.rail-label {
  margin: var(--space-4) 0 var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-muted);
}

/* The week's units as a contents list; the current one on the teal tint in the brand green. */
.week-rail ol ol,
.week-rail-phone ol ol {
  gap: 0;
}

.week-rail a,
.week-rail-phone a {
  display: block;
  min-height: 2.25rem;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-ink);
  text-decoration: none;
}

.week-rail a:hover,
.week-rail-phone a:hover {
  background: var(--color-tint);
  color: var(--color-ink);
}

.nav-unit.current a {
  background: var(--color-tint);
  color: var(--color-accent);
  font-weight: var(--weight-semibold);
}

.nav-unit.complete a {
  color: var(--color-muted);
}

.week-rail-phone {
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  padding: var(--space-3) var(--space-4);
}

.week-rail-phone summary {
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

/* The unit's title at headline size. */
.unit h1 {
  font-size: var(--text-headline);
  line-height: var(--leading-heading);
  overflow-wrap: break-word;
}

.unit-summary {
  color: var(--color-muted);
  font-size: var(--text-lg);
}

.unit > * + * {
  margin-top: var(--space-6);
}

.unit-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-top: var(--space-5);
  border-top: var(--rule-width) solid var(--color-rule);
}

.unit-nav a:not(.button) {
  font-family: var(--font-ui);
}

@media (min-width: 60rem) {
  .unit-layout {
    grid-template-columns: 16rem minmax(0, 1fr);
    align-items: start;
  }

  .week-rail {
    display: block;
    position: sticky;
    top: 6rem;
    padding: var(--space-5);
    border: var(--rule-width) solid var(--color-rule);
    border-radius: var(--radius-md);
    background: var(--color-surface);
  }

  .week-rail-phone {
    display: none;
  }
}

/* ---- Section panels in a unit (src/course/render/sections.ts) ------------------ */

/* Every kind of section (introduction, exercise, reflection, watch out, regulatory, note) sits in the same panel:
 * the surface, a hairline frame and a small mono label naming the kind. The key idea is the one panel on the band
 * (Direction B), a hierarchy choice, not a colour per kind. */
.unit-part {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-6);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.unit-part > * {
  min-width: 0;
  margin: 0;
}

.unit-part-label {
  justify-self: start;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--color-tint);
  color: var(--color-accent);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  line-height: 1.4;
  text-transform: uppercase;
}

/* The key idea: on the dark band, its label in the highlight. */
.unit-part[data-section="key"] {
  border: 0;
  background: var(--color-band);
  color: var(--color-on-band);
}

.unit-part[data-section="key"] .unit-part-label {
  background: var(--color-band-accent);
  color: var(--color-on-band-accent);
}

.unit-part[data-section="key"] .callout-title {
  color: var(--color-on-band);
}

.unit-part[data-section="key"] a {
  color: var(--color-on-band);
}

.unit-part[data-section="key"] :focus-visible {
  outline-color: var(--color-band-accent);
}

/* The panel is the box: a callout inside it drops its own tint and border. */
.unit-part .callout {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

.unit-part .callout-title {
  color: var(--color-ink);
}

/* An exercise is the panel's content, not a box within it; a document excerpt keeps its frame, on the paper. */
.unit-part .ix {
  padding: 0;
  border: 0;
  background: none;
}

.unit-part .document {
  border-color: var(--color-rule);
  background: var(--color-paper);
}

/* Phones: a slimmer panel, so what is inside keeps its width. */
@media (max-width: 39.99rem) {
  .unit-part {
    padding: var(--space-5) var(--space-4);
  }

  .unit-part .document {
    padding: var(--space-4);
  }
}

/* The introduction is the unit's lede. */
.unit-part .unit-summary {
  color: var(--color-ink);
}

/* Sources: no panel, a rule in ink above; its own heading stands in for the label. */
.unit-part[data-section="sources"] {
  padding: var(--space-4) 0 0;
  border: 0;
  border-top: var(--rule-width) solid var(--color-rule);
  background: none;
}

.unit-part .sources {
  display: grid;
  gap: var(--space-3);
}

/* ---- Sequence notice --------------------------------------------------------- */

.sequence-notice {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-md);
  background: var(--color-tint);
}

.sequence-notice p {
  margin: 0;
}

/* ---- Course updates (spec §9.3) ------------------------------------------------ */

/* The one "Updated" badge on every updated unit (week tiles, week page, rail): the site's unit tag
 * (public/css/site.css, which course pages don't load), with no per-week variants. */
.unit-tag {
  display: inline-block;
  justify-self: start;
  padding: 0.2rem 0.55rem;
  border-radius: var(--radius-sm);
  background: var(--color-tint);
  color: var(--color-accent);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

/* Inside a unit link, spaced by margin rather than a space so the link's underline stops at the title
 * (an inline-block isn't underlined with its parent). */
a .unit-tag {
  margin-inline-start: var(--space-2);
}

/* A rail link turns tint on hover, so the badge gets a frame to stay visible on it. */
.week-rail .unit-tag,
.week-rail-phone .unit-tag {
  box-shadow: inset 0 0 0 var(--rule-width) var(--color-rule);
}

/* The course home banner, in the live teaser's tone: a band-accent rule on the quiet tint. */
.updates-banner {
  display: grid;
  gap: var(--space-3);
  max-width: 44rem;
  margin-bottom: var(--space-6);
  padding: var(--space-5);
  border-left: 4px solid var(--color-band-accent);
  border-radius: var(--radius-sm);
  background: var(--color-tint);
}

.updates-banner p,
.updates-banner ul {
  margin: 0;
}

.updates-banner-title {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-muted);
}

.updates-banner ul {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  list-style: none;
}

.updates-banner-more {
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.updates-banner button {
  justify-self: start;
}

/* The unit header's quiet "Updated <date>", close under the title. */
.unit h1 + .unit-updated {
  margin-top: var(--space-2);
}

.unit-updated {
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

/* A block changed since the member finished the unit: a left rule and a small mono label with the note. */
.unit-change {
  display: grid;
  gap: var(--space-3);
  padding-left: var(--space-4);
  border-left: 3px solid var(--color-band-accent);
}

.unit-change-label {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.unit-change-date {
  margin-inline-end: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink);
}

/* ---- Join panel (visitors) ---------------------------------------------------- */

.join-panel {
  display: grid;
  gap: var(--space-3);
  margin-block: var(--space-6);
  padding: var(--space-5);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-md);
  background: var(--color-tint);
}

.join-panel h2,
.join-panel p {
  margin: 0;
}

.join-panel .button {
  display: inline-block;
  min-height: 44px;
}

.join-panel a:not(.button) {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
}

/* ---- Prose, callouts, documents, compare, flow -------------------------------- */

.prose {
  display: grid;
  gap: var(--space-4);
  max-width: var(--measure);
}

.callout {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-5);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--color-rule-strong);
  background: var(--color-tint);
}

.callout-title {
  font-family: var(--font-ui);
  font-weight: var(--weight-semibold);
}

.callout-trap {
  border-left-color: var(--color-weak);
  background: var(--color-weak-tint);
}

.callout-key {
  border-left-color: var(--color-strong);
  background: var(--color-strong-tint);
}

.callout-regulatory {
  border-left-color: var(--color-signal);
}

.document {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-md);
}

.document figcaption {
  font-family: var(--font-ui);
  font-weight: var(--weight-semibold);
}

.document pre {
  margin: 0;
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-tint);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  word-break: break-word;
}

/* Quiet utility action, not a primary interaction button (Finding 12). */
.document button[data-action="copy"] {
  justify-self: end;
  min-height: 2rem;
  min-width: auto;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  background: transparent;
  border-color: var(--color-rule-strong);
}

.document button[data-action="copy"]:hover {
  background: var(--color-tint);
}

.table-scroll {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table-scroll:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.compare table {
  width: 100%;
  min-width: 28rem;
  border-collapse: collapse;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.compare th,
.compare td {
  padding: var(--space-3);
  border-bottom: var(--rule-width) solid var(--color-rule);
  text-align: left;
}

.flow ol {
  display: grid;
  gap: var(--space-2);
  padding-left: var(--space-5);
}

.flow-label {
  font-weight: var(--weight-semibold);
}

.flow-detail {
  color: var(--color-muted);
}

/* ---- Figures (src/course/figures/, src/course/render/blocks.ts renderFigure) ------- */

/* Every figure is hand-built inline SVG whose elements carry only classes from this section; the classes read
 * tokens, so a brand redesign changes tokens and no drawing. Lines are 1.5 units, boxes 1, corners 4, and a
 * unit is a CSS pixel at the viewBox's own size (text is 14 units or more, so a drawing that is at most 330
 * wide in its narrow layout stays legible on a 320px phone). The figure is a size container: a drawing with
 * two layouts shows the wide one from 36rem of figure width and the narrow one below it. The hidden layout is
 * `display: none`, not just invisible, so a screen reader meets its title and description once.
 *
 * Shapes:  f-box, f-box-tint, f-box-accent, f-box-strong, f-box-muted, f-box-hue; f-fill-accent, f-fill-muted,
 *          f-fill-tint, f-fill-hue.
 * Lines:   f-line, f-line-ink, f-line-accent, f-line-hue (+ f-dash, f-dot); f-grid (a chart's gridline); arrowheads f-head, f-head-ink,
 *          f-head-accent, f-head-hue.
 * Text:    f-t, f-t-muted, f-t-strong, f-t-head, f-t-lg, f-t-accent, f-t-on-accent, f-t-on-hue, f-t-hue, f-t-num.
 * Hues:    f-hue-<teal|sage|ochre|clay|slate|plum> on a shape, text or group sets the colours that the
 *          *-hue classes inside it read. States are never told by colour alone: use line style, fill versus
 *          outline, or a label as well. Never the verdict colours. */

.fig {
  display: grid;
  gap: var(--space-3);
  margin-inline: 0;
  container-type: inline-size;
}

.fig-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 45rem;
}

.fig-only {
  max-width: 28rem;
}

.fig-narrow {
  display: none;
}

@container (max-width: 35.99rem) {
  .fig-wide {
    display: none;
  }

  .fig-narrow {
    display: block;
  }
}

.fig figcaption {
  max-width: var(--measure);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.fig-long {
  max-width: var(--measure);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.fig-long summary {
  cursor: pointer;
  font-weight: var(--weight-medium);
  color: var(--color-accent);
}

.fig-long p {
  margin-top: var(--space-2);
}

.fig-gallery {
  display: grid;
  gap: var(--space-7);
}

/* Hues: a class sets the three colours, the *-hue classes read them. */
.f-hue-teal {
  --f-hue: var(--color-teal);
  --f-hue-tint: var(--color-teal-tint);
  --f-on-hue: var(--color-on-teal);
}

.f-hue-sage {
  --f-hue: var(--color-sage);
  --f-hue-tint: var(--color-sage-tint);
  --f-on-hue: var(--color-on-sage);
}

.f-hue-ochre {
  --f-hue: var(--color-ochre);
  --f-hue-tint: var(--color-ochre-tint);
  --f-on-hue: var(--color-on-ochre);
}

.f-hue-clay {
  --f-hue: var(--color-clay);
  --f-hue-tint: var(--color-clay-tint);
  --f-on-hue: var(--color-on-clay);
}

.f-hue-slate {
  --f-hue: var(--color-slate);
  --f-hue-tint: var(--color-slate-tint);
  --f-on-hue: var(--color-on-slate);
}

.f-hue-plum {
  --f-hue: var(--color-plum);
  --f-hue-tint: var(--color-plum-tint);
  --f-on-hue: var(--color-on-plum);
}

/* Boxes and fills. */
.f-box,
.f-box-tint,
.f-box-accent,
.f-box-strong,
.f-box-muted,
.f-box-hue {
  stroke-width: 1;
  stroke-linejoin: round;
}

.f-box {
  fill: var(--color-surface);
  stroke: var(--color-rule-strong);
}

.f-box-tint {
  fill: var(--color-tint);
  stroke: var(--color-rule);
}

.f-box-accent {
  fill: var(--color-tint);
  stroke: var(--color-accent);
  stroke-width: 1.5;
}

.f-box-strong {
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 2;
}

.f-box-muted {
  fill: var(--color-paper);
  stroke: var(--color-rule-strong);
  stroke-dasharray: 6 4;
}

.f-box-hue {
  fill: var(--f-hue-tint);
  stroke: var(--f-hue);
  stroke-width: 1.5;
}

.f-fill-accent {
  fill: var(--color-accent);
  stroke: none;
}

.f-fill-muted {
  fill: var(--color-rule-strong);
  stroke: none;
}

/* A quiet area (a zone, a band) behind other shapes: tint, no outline. */
.f-fill-tint {
  fill: var(--color-tint);
  stroke: none;
}

.f-fill-hue {
  fill: var(--f-hue);
  stroke: none;
}

/* Status markers that carry meaning by shape, never by colour: a solid ink fill, and a dashed outline. */
.f-fill-ink {
  fill: var(--color-ink);
  stroke: none;
}

/* A plate in the page colour, to keep a label clear of lines running behind it. */
.f-fill-paper {
  fill: var(--color-paper);
  stroke: none;
}

.f-mark-dash {
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 1.5;
  stroke-dasharray: 3 2;
}

/* Lines and arrowheads. */
.f-line,
.f-line-ink,
.f-line-accent,
.f-line-hue {
  fill: none;
  stroke-width: 1.5;
  stroke-linejoin: round;
}

.f-line {
  stroke: var(--color-rule-strong);
}

.f-line-ink {
  stroke: var(--color-ink);
}

.f-line-accent {
  stroke: var(--color-accent);
  stroke-width: 2;
}

.f-line-hue {
  stroke: var(--f-hue);
}

.f-dash {
  stroke-dasharray: 6 4;
}

.f-grid {
  fill: none;
  stroke: var(--color-rule);
  stroke-width: 1;
}

.f-dot {
  stroke-dasharray: 1.5 3;
  stroke-linecap: round;
}

.f-head,
.f-head-ink,
.f-head-accent,
.f-head-hue {
  stroke: none;
}

.f-head {
  fill: var(--color-rule-strong);
}

.f-head-ink {
  fill: var(--color-ink);
}

.f-head-accent {
  fill: var(--color-accent);
}

.f-head-hue {
  fill: var(--f-hue);
}

/* Text: each class sets the whole face, so a label needs only one of them (plus f-t-num or a hue class).
 * Sizes are viewBox units; the smallest is 14. Order matters: the face, then weight and size, then colour. */
.f-t,
.f-t-muted,
.f-t-strong,
.f-t-head,
.f-t-lg,
.f-t-accent,
.f-t-on-accent,
.f-t-on-hue,
.f-t-hue,
.f-t-num {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: var(--weight-regular);
  fill: var(--color-ink);
  stroke: none;
}

.f-t-strong {
  font-weight: var(--weight-semibold);
}

.f-t-head {
  font-size: 16px;
  font-weight: var(--weight-semibold);
}

.f-t-lg {
  font-size: 20px;
  font-weight: var(--weight-semibold);
}

.f-t-muted {
  fill: var(--color-muted);
}

.f-t-accent {
  fill: var(--color-accent);
}

.f-t-on-accent {
  fill: var(--color-on-accent);
}

.f-t-hue {
  fill: var(--f-hue);
}

.f-t-on-hue {
  fill: var(--f-on-hue);
}

.f-t-num {
  font-variant-numeric: tabular-nums;
}

/* ---- Interactive blocks (shared) ---------------------------------------------- */

.ix {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-5);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-md);
}

/* Same grid-blowout fix as `main` and `.unit-layout` above, one level
 * deeper: an unbreakable rank-list button or wide fieldset could otherwise
 * push an `.ix` section's own content past its border on narrow viewports
 * (Finding 2, Finding 11). */
.ix > * {
  min-width: 0;
}

.ix-title {
  font-size: var(--text-lg);
}

.ix-prompt {
  font-size: var(--text-md);
}

.ix fieldset {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  border: 0;
}

.ix label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 1.5rem;
}

.ix input[type="radio"],
.ix input[type="checkbox"] {
  width: 1.25rem;
  height: 1.25rem;
  accent-color: var(--color-accent);
}

.ix-confidence {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-5);
  padding-top: var(--space-2);
  border-top: var(--rule-width) solid var(--color-rule);
}

.ix-confidence legend {
  width: 100%;
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
}

.ix-status {
  min-height: 1.5em;
  color: var(--color-muted);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.ix-answers summary {
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-accent);
}

.ix-feedback {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-tint);
}

.ix-feedback[data-verdict="strong"] {
  background: var(--color-strong-tint);
  border-left: 3px solid var(--color-strong);
}

.ix-feedback[data-verdict="partial"] {
  border-left: 3px solid var(--color-partial);
}

.ix-feedback[data-verdict="weak"] {
  background: var(--color-weak-tint);
  border-left: 3px solid var(--color-weak);
}

/* Without JS, every `.ix-feedback` in `.ix-answers` is plainly visible, and
 * the `<details>` itself is the disclosure control. With JS, the script
 * reveals only the feedback that matches what the learner did. */
html.js .ix-answers > summary {
  display: none;
}

html.js .ix-feedback {
  display: none;
}

html.js .ix-feedback.is-shown {
  display: block;
}

/* Scenario feedback sits inline in the node, not inside `.ix-answers`, but
 * follows the same reveal rule. */
html.js .ix-node .ix-feedback {
  display: none;
}

html.js .ix-node .ix-feedback.is-shown {
  display: inline-block;
}

.ix-debrief {
  color: var(--color-muted);
  font-style: italic;
}

/* ---- sort, rank -------------------------------------------------------------- */

/* Segmented control per item: each item's buckets sit in one horizontal row
 * instead of stacking vertically (Finding 9). */
.ix-sort fieldset {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-sm);
}

.ix-sort fieldset legend {
  width: 100%;
  margin-bottom: var(--space-1);
  font-family: var(--font-ui);
  font-weight: var(--weight-medium);
}

.ix-sort label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 1.5rem;
  margin-right: 0;
  padding: var(--space-1) var(--space-3);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-sm);
}

.ix-sort label:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--color-tint);
  font-weight: var(--weight-semibold);
}

.ix-rank-list {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  list-style: none;
}

.ix-rank-list > li {
  min-width: 0;
}

.ix-rank-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-sm);
}

.ix-rank-label {
  flex: 1 1 12rem;
  min-width: 0;
  font-family: var(--font-ui);
}

.ix-rank-actions {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-2);
}

/* Compact reorder buttons, grouped so they wrap as a pair below a long
 * label instead of squeezing it into a narrow column (Finding 11). */
.ix-rank-list li button {
  flex-shrink: 0;
  min-height: 2.25rem;
  min-width: 2.25rem;
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-xs);
}

/* ---- scenario ------------------------------------------------------------------ */

.ix-choices {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  list-style: none;
}

.ix-choice {
  display: inline-block;
  min-height: 1.5rem;
  font-family: var(--font-ui);
}

.ix-choice[aria-disabled="true"] {
  pointer-events: none;
  color: var(--color-muted);
  text-decoration: none;
}

.ix-continue,
.ix-start-again {
  justify-self: start;
}

/* ---- reveal -------------------------------------------------------------------- */

.reveal {
  display: grid;
  gap: var(--space-3);
}

/* Reveal cards read as ruled lines: the claim in the italic serif, a plus that opens it. */
.reveal {
  gap: 0;
}

.ix-card {
  border-top: var(--rule-width) solid var(--color-rule);
}

.ix-card:last-child {
  border-bottom: var(--rule-width) solid var(--color-rule);
}

.ix-card summary {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-style: italic;
  list-style: none;
}

.ix-card summary::-webkit-details-marker {
  display: none;
}

.ix-card summary::after {
  content: "+";
  content: "+" / "";
  color: var(--color-accent);
  font-style: normal;
}

.ix-card[open] summary::after {
  content: "−";
  content: "−" / "";
}

.ix-card p {
  padding: 0 0 var(--space-4);
  color: var(--color-muted);
}

/* ---- spot ---------------------------------------------------------------------- */

.ix-segments {
  display: grid;
  gap: var(--space-2);
}

.ix-segment {
  min-height: auto;
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: var(--rule-width) solid var(--color-rule);
  background: var(--color-surface);
  color: var(--color-ink);
  text-align: left;
  font-family: var(--font-text);
  font-weight: var(--weight-regular);
}

.ix-segment[aria-pressed="true"] {
  border-color: var(--color-accent);
  background: var(--color-tint);
}

/* ---- estimate (device-only) ----------------------------------------------------- */

.ix-inputs {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.ix-input {
  display: grid;
  gap: var(--space-1);
}

.ix-input label {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.ix-input input[type="number"] {
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-3);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-ink);
  font-family: var(--font-ui);
}

.ix-note {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.ix-outputs {
  display: grid;
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: var(--rule-width) solid var(--color-rule);
}

.ix-output {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--space-3);
  font-family: var(--font-ui);
}

.ix-output output {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  text-align: right;
}

/* ---- questions ------------------------------------------------------------------ */

.ix-question {
  display: grid;
  gap: var(--space-1);
  padding-block: var(--space-2);
}

.ix-why {
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* ---- workbook (unit page + workbook page) --------------------------------------- */

.wb-device-note {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.ix-workbook textarea,
textarea[name] {
  width: 100%;
  min-height: 6rem;
  padding: var(--space-3);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-ink);
  font-family: var(--font-text);
  font-size: var(--text-md);
  resize: vertical;
}

.wb-field {
  display: grid;
  gap: var(--space-2);
  padding-block: var(--space-3);
  border-top: var(--rule-width) solid var(--color-rule);
}

.wb-field-label {
  font-family: var(--font-ui);
  font-weight: var(--weight-medium);
}

.wb-text {
  white-space: pre-wrap;
}

.wb-empty {
  color: var(--color-muted);
  font-style: italic;
}

.workbook-page-group {
  display: grid;
  gap: var(--space-5);
  padding-block: var(--space-5);
  border-top: var(--rule-width) solid var(--color-rule-strong);
}

.wb-page {
  display: grid;
  gap: var(--space-3);
}

.workbook-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ---- rate ------------------------------------------------------------------------ */

/* Segmented control: each rating statement's 1–5 options sit in a single
 * horizontal row (Finding 5). `fieldset.ix-statement` outweighs the generic
 * `.ix fieldset` grid rule above on specificity. */
fieldset.ix-statement {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4);
  /* A shadow, not border-top: a border is cut open where the legend sits on it. */
  border: 0;
  box-shadow: 0 calc(-1 * var(--rule-width)) 0 var(--color-rule);
}

.ix-statement legend {
  width: 100%;
  margin-bottom: var(--space-1);
  font-family: var(--font-ui);
  font-weight: var(--weight-medium);
}

.ix-statement > label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 1.5rem;
  margin-right: 0;
  padding: var(--space-1) var(--space-3);
  border: var(--rule-width) solid var(--color-rule);
  border-radius: var(--radius-sm);
}

.ix-statement > label:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--color-tint);
  font-weight: var(--weight-semibold);
}

/* ---- Glossary and term popovers --------------------------------------------------- */

.glossary-entry {
  padding-block: var(--space-4);
  border-top: var(--rule-width) solid var(--color-rule);
}

/* Glossary terms are stored in natural case (Ruling 19: "token", not
 * "Token"), so prose reads correctly mid-sentence; the glossary heading
 * capitalises its own first letter for display. */
.glossary-entry h2::first-letter {
  text-transform: uppercase;
}

a.term {
  text-decoration-style: dotted;
}

/* Whatever block contains a term link and its popover (a `<p>`, `<li>`,
 * `<dd>`, a callout, …) becomes the popover's positioning context, so the
 * popover never affects that block's own line layout (Finding 7). */
:has(> .term-popover) {
  position: relative;
}

.term-popover {
  display: block;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 10;
  max-width: min(22rem, 90vw);
  margin-top: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border: var(--rule-width) solid var(--color-rule-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}

/* Toggled by `course.js` (never an inline style) when the default
 * left-aligned popover would overflow the viewport's right edge. */
.term-popover--align-end {
  left: auto;
  right: 0;
}

/* ---- Sources ---------------------------------------------------------------------- */

.sources ul {
  display: grid;
  gap: 0;
  padding-left: 0;
  list-style: none;
}

.sources li {
  padding-block: var(--space-3);
  border-bottom: var(--rule-width) solid var(--color-rule);
  font-size: var(--text-sm);
}

/* ---- Print (workbook page) --------------------------------------------------------- */

@media print {
  .course-member,
  .breadcrumb,
  .workbook-actions,
  .week-rail,
  .week-rail-phone,
  .unit-nav,
  .join-panel,
  .sequence-notice {
    display: none;
  }

  .workbook-page-group {
    break-inside: avoid;
  }

  main {
    padding: 0;
    max-width: none;
  }

  /* The workbook page's real printed content is `.wb-text` (filled from
   * the browser's own saved answers by `course.js`); it has no height or
   * overflow constraint, so it already prints in full. Any `<textarea>` —
   * only present in a unit page's in-context workbook block — is an input
   * control, not output, and an empty one prints as a large grey box, so
   * hide it outright rather than just restyling it (Finding 15; Finding 2
   * of the round-2 review). */
  .ix-workbook textarea,
  textarea[name] {
    display: none;
  }

  .wb-text {
    overflow: visible;
  }
}

/* Reduced motion: `base.css` already disables all transitions and
 * animations under `prefers-reduced-motion: reduce`; this stylesheet adds
 * none of its own. */
