/* ==========================================================================
   Candidate Fraud Detection — Dexcom client build
   Palette mapped to Dexcom Brand Central; type per Company Brand > Typography
   Design system reverse-engineered from Stripe Press / Poor Charlie's Almanack
   ========================================================================== */

:root {
  /* ---- DEXCOM CLIENT PALETTE -------------------------------------------------
     Mapped from Dexcom Brand Central, Company Brand > Colors, 2026-08-06.
     Every pairing below was contrast-computed, not eyeballed. See
     Dexcom-Brand-Standards.md section 2 for the full table.
       Bold Gray on Bone .......... 9.39:1  body text OK
       Contrast Green on Bone ..... 4.91:1  body text OK
       Plum on Bone .............. 13.44:1  body text OK
       Plum vs Contrast Green ..... 2.92:1  state pair, separated by luminance
     DO NOT use Dexcom Green (--brand-green) for body text or on Bone:
     #30AB0D on Bone is 2.80:1 and fails even the 3:1 bar. Logo and large
     display only, per Dexcom's own "not for body copy" rule.
  --------------------------------------------------------------------------- */
  --paper: #FFFFFF;        /* White           — page surface, per Dexcom's stated recommendation */
  --surface: #F8F6F2;      /* Bone            — raised cards/artifacts, Dexcom's accent role */
  --ink: #434141;          /* Bold Gray       — all body copy */
  --peach: #137D00;        /* Contrast Green  — accent / hover / active */
  --stone: #D9D8D6;        /* Cool Gray       — rules, dividers */
  --flag-red: #371B2C;     /* Plum            — flagged / suspicious */
  --flag-green: #137D00;   /* Contrast Green  — confirmed / correct */

  --brand-green: #30AB0D;  /* Dexcom Green    — brand marks + large display ONLY */
  --white: #FFFFFF;

  /* Channel copies of the above. The original stylesheet hardcoded the old
     palette's RGB triplets inside 26 rgba() calls, which meant a token swap
     re-skinned 90% of the build and left tinted shadows, rules and washes
     behind. These let rgba() participate in the theme. Keep in sync with the
     hex values above — that is the one duplication the CSS layer still has. */
  --paper-rgb: 255, 255, 255;   /* White */
  --surface-rgb: 248, 246, 242; /* Bone */
  --ink-rgb: 67, 65, 65;        /* Bold Gray */
  --accent-rgb: 19, 125, 0;     /* Contrast Green */
  --shadow-rgb: 26, 22, 20;     /* neutral dark, intentionally not brand-tinted */

  /* THIRD SEMANTIC STATE — needs a Branding decision. The engine has a
     wrong / partial / correct trio; "partial" was a hardcoded amber (#A8763E)
     with no token at all. Dexcom's Company Brand palette contains no amber and
     no red, so there is nothing in-palette that reads as "partially right."
     Mid-Tone Gray is the least-wrong in-palette stand-in: 3.57:1 on Bone, which
     clears the 3:1 UI bar for a border but NOT the 4.5:1 body-text bar — so the
     label text below deliberately stays --ink. This is exactly the
     functional-state-colour question in Dexcom-Brand-Standards.md section 7. */
  --flag-partial: #808285;      /* Mid-Tone Gray — provisional */

  /* Gilroy is Dexcom's primary typeface but is licensed and not supplied to
     outside partners. Arial is Dexcom's own documented web-safe fallback
     (Company Brand > Typography). Listing Gilroy first means anyone inside
     Dexcom with it installed sees the real face; everyone else gets Arial. */
  --font-display: 'Gilroy', Arial, 'Helvetica Neue', Helvetica, sans-serif;
  --font-body: 'Gilroy', Arial, 'Helvetica Neue', Helvetica, sans-serif;
  /* Was a system monospace stack — off-brand for Dexcom, and read as
     "typewriter" in UAT. Retargeted to the brand stack; the letterspaced,
     uppercase treatments that used it keep their look, on-brand. */
  --font-mono: 'Gilroy', Arial, 'Helvetica Neue', Helvetica, sans-serif;

  --col-width: 38rem;
  --wide-width: 76rem;
  --topbar-h: 3.75rem;
}

* {
  box-sizing: border-box;
}

/* Standing accessibility rule: every genuinely interactive element gets a
   visible keyboard-focus indicator by default (WCAG 2.4.7). Individual
   components can override this with their own :focus-visible treatment
   (see .rail-image, .cluster-photo--clickable) as long as they replace it
   with something at least as visible — never just remove it. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Applied while any overlay/modal is open, so scrolling inside it can never
   drag the page behind it along too. */
body.scroll-locked {
  overflow: hidden;
  height: 100vh;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ---- Orphan / widow prevention — standing design rule, not a one-off fix --
   No paragraph, heading, quote, or button label may ever strand a single
   word on its last line. This is applied globally so it never needs manual
   per-element handling again; see HANDOFF's Design Standards section. */

p {
  text-wrap: pretty;
}

h1, h2, h3,
.eyebrow, .cover-title, .cover-subtitle, .cover-audience,
.chapter-title, .pull-quote,
.resume-name, .resume-role, .decision-prompt, .decision-text,
.begin-reading, .cluster-caption {
  text-wrap: balance;
}

/* ---- Top bar (persistent nav, matches source's chrome) -------------------- */

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--topbar-h);
  z-index: 45;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1.5rem;
  background: var(--paper);
  border-bottom: 1px solid var(--ink);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.topbar-left,
.topbar-right {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.topbar-brand {
  padding: 0.35rem 0.5rem;
  transition: background .15s, color .15s;
}

.topbar-brand:hover {
  background: var(--ink);
  color: var(--paper);
}

.topbar-sep {
  opacity: 0.35;
}

.topbar-sub {
  opacity: 0.6;
  display: none;
}

.topbar-progress {
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  min-width: 4.75rem;
  text-align: center;
}

/* Shared "fill pill" mechanic: a black bar grows across the pill (scroll %,
   flags found) and a duplicate white copy of the text is clipped to exactly
   that width, so text sitting inside the fill reads white while the rest
   stays the default ink color — never the black-on-black overlap bug. */
.fill-pill {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.fill-pill-bar {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 0%;
  background: var(--ink);
  z-index: 0;
  transition: width .15s ease;
}

.fill-pill-text {
  position: relative;
  z-index: 1;
}

.fill-pill-text--invert {
  position: absolute;
  inset: 0;
  z-index: 2;
  color: var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path .15s ease;
}

/* The section label ("Front Cover" / "Module One") also opens the TOC now —
   it read as a dead click target when only the hamburger icon worked. */
.topbar-label {
  cursor: pointer;
  padding: 0.35rem 0.5rem;
  transition: background .15s, color .15s;
}

.topbar-label:hover {
  background: var(--ink);
  color: var(--paper);
}

.topbar-toc {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 1rem;
  line-height: 1;
  padding: 0.35rem 0.5rem;
  transition: background .15s, color .15s;
}

.topbar-toc:hover {
  background: var(--ink);
  color: var(--paper);
}

/* ---- Hover-invert highlight --------------------------------------------- */

.hl {
  transition: background .15s, color .15s;
  cursor: pointer;
  border-bottom: 1px solid var(--ink);
}

.hl:hover {
  background: var(--ink);
  color: var(--paper);
  border-bottom-color: transparent;
}

.hl-flag {
  border-bottom: 1px dotted var(--ink);
  transition: background .15s, color .15s, border-radius .15s;
  cursor: pointer;
  padding: 0 .1em;
}

.hl-flag:hover,
.hl-flag.found {
  background: var(--peach);
  color: var(--paper);
  border-radius: 3px;
  border-bottom-color: transparent;
}

/* Decorative hover-emphasis for feedback prose — not tied to the rail system
   or any quiz state, just a scanning aid for long feedback paragraphs. No
   pointer cursor: nothing happens on click, this only responds to hover. */
.feedback-highlight {
  border-bottom: 1px dotted var(--ink);
  transition: background .15s, color .15s, border-radius .15s;
  padding: 0 .1em;
}

.feedback-highlight:hover {
  background: var(--peach);
  color: var(--paper);
  border-radius: 3px;
  border-bottom-color: transparent;
}

/* ---- Hover tooltip (follows cursor, shows fig caption) --------------------- */

.hover-tip {
  position: fixed;
  pointer-events: none;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.45rem 0.7rem;
  z-index: 60;
  opacity: 0;
  transition: opacity .15s ease;
  transform: translate(-50%, -145%);
  white-space: nowrap;
}

.hover-tip.visible {
  opacity: 1;
}

/* ---- TOC overlay --------------------------------------------------------- */

.toc-overlay {
  position: fixed;
  inset: 0;
  background: var(--paper);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease;
}

.toc-overlay.open {
  opacity: 1;
  visibility: visible;
}

.toc-close {
  position: absolute;
  top: 1.75rem;
  right: 1.75rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: none;
  border: none;
  color: var(--ink);
  cursor: pointer;
  padding: 0.4rem 0.6rem;
  transition: background .15s, color .15s;
}

.toc-close:hover {
  background: var(--ink);
  color: var(--paper);
}

.toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
  width: min(90vw, 40rem);
}

/* Testing/QA affordance — clears the self-tests' persisted completion
   state back to genuinely never-opened. Quiet on purpose: not something a
   real learner needs to reach for, just a way out of "it already says
   Reviewed" during repeated review passes in the same browser. */
.toc-reset {
  display: block;
  margin: 1.5rem auto 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: none;
  border: 1px dashed var(--ink);
  color: var(--ink);
  opacity: 0.55;
  cursor: pointer;
  padding: 0.5rem 1rem;
  width: min(90vw, 40rem);
  transition: opacity .15s ease;
}

.toc-reset:hover {
  opacity: 1;
}

.toc-list li {
  border-top: 1px solid var(--ink);
}

.toc-list li:last-child {
  border-bottom: 1px solid var(--ink);
}

.toc-list a,
.toc-list .toc-disabled,
.toc-list .toc-current {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  padding: 1rem 0.5rem;
  transition: background .15s, color .15s;
}

.toc-list a {
  cursor: pointer;
}

.toc-list a:hover {
  background: var(--ink);
  color: var(--paper);
}

.toc-list .toc-disabled {
  opacity: 0.35;
  cursor: default;
}

/* "You are here" — distinct from both the hover-black link state and the
   grayed-out disabled/unbuilt entries. */
.toc-list .toc-current {
  background: rgba(var(--ink-rgb), 0.08);
  cursor: default;
}

.toc-num {
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 400;
  width: 1.5rem;
  flex-shrink: 0;
}

.toc-label {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  width: 8rem;
  flex-shrink: 0;
}

.toc-title {
  font-family: var(--font-display);
  font-size: 1.1rem;
}

/* ---- Page shell ----------------------------------------------------------- */

.page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: calc(var(--topbar-h) + 4rem) 1.5rem 6rem;
}

.column {
  width: 100%;
  max-width: var(--col-width);
}

.column--wide {
  width: 100%;
  max-width: var(--wide-width);
}

.rule {
  border: none;
  border-top: 1px solid var(--ink);
  margin: 3rem 0;
}

/* ---- Cover page ------------------------------------------------------------ */

.cover {
  justify-content: center;
  text-align: center;
  min-height: 100vh;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0 0 1.5rem;
}

.cover-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 340;
  font-size: clamp(2.75rem, 8vw, 5.5rem);
  line-height: 1.02;
  margin: 0 0 1.25rem;
}

.cover-subtitle {
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(1.1rem, 2.2vw, 1.4rem);
  color: var(--ink);
  margin: 0 0 2.5rem;
  max-width: 34rem;
}

.cover-description {
  font-family: var(--font-body);
  font-size: 1.05rem;
  line-height: 1.7;
  max-width: 34rem;
  margin: 0 auto 1rem;
}

.cover-audience {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
  max-width: 30rem;
  margin: 0 auto 3rem;
}

.begin-reading {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid var(--ink);
  padding: 0.9rem 2rem;
  transition: background .15s, color .15s;
}

.begin-reading:hover {
  background: var(--ink);
  color: var(--paper);
}

/* ---- Chapter opener --------------------------------------------------------- */

.chapter-opener {
  text-align: center;
  margin-bottom: 3rem;
}

.chapter-numeral {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(8rem, 35vw, 22rem);
  line-height: 0.85;
  margin: 0.5rem 0;
}

.chapter-numeral--small {
  font-size: clamp(4rem, 16vw, 9rem);
}

.chapter-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  line-height: 1.1;
  margin: 0.5rem 0 0;
}

.chapter-hint {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  opacity: 0.78;
  margin: 0.9rem 0 0;
}

/* ---- Body copy ------------------------------------------------------------ */

.prose {
  font-family: var(--font-body);
  font-size: 1.2rem;
  line-height: 1.7;
}

.prose p {
  margin: 0 0 1.5rem;
}

.prose sup {
  font-family: var(--font-mono);
  font-size: 0.6em;
}

.pull-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-optical-sizing: auto;
  font-weight: 340;
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  line-height: 1.35;
  margin: 3rem 0;
  padding: 0.1em 0;
  /* Tightening the measure (rather than letting it stretch the full
     column) is what actually keeps a short 2-3 line quote from flaring
     wider toward the bottom — text-wrap: balance (below) does the rest. */
  max-width: 32ch;
}

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

.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s ease, transform .6s ease;
}

.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

/* ---- One course, one route (D-102, 16 Sept 2026) ------------------------------
   The track-condensed rules that hid the rail-and-reading split and the chapter
   hints are gone. Module Three shows its split; Module Two shows its three
   figure cards as a row (.fig-row) with no reading beside them, as the SME
   left it. */

.chapter-hint--keep {
  max-width: 64ch;
  margin-left: auto;
  margin-right: auto;
  text-wrap: balance;
}

.fig-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  width: 100%;
  max-width: var(--wide-width);
  margin: 2.5rem auto 3rem;
}

.fig-row .mock-card {
  height: auto;
  min-height: 12rem;
  justify-content: flex-start;
}

.fig-row .rail-explain {
  /* 18 Sept 2026: these three cards are not rail images, so the global
     .rail-explain rule (hidden until a card is .front) left Kristy's
     figure-card text invisible. Always shown here. */
  opacity: 0.85;
  max-height: none;
  overflow: visible;
  margin: 0.75rem 0 0;
}

@media (max-width: 720px) {
  .fig-row { grid-template-columns: 1fr; }
}

/* ---- Split reading layout (sticky companion rail + narrower text column) --- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.35fr);
  gap: 3.5rem;
  width: 100%;
  max-width: var(--wide-width);
  margin: 0 auto;
  align-items: start;
}

.split-rail {
  position: sticky;
  top: calc(var(--topbar-h) + 3rem);
  height: 72vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Extra room below the photo scatter: the .front card un-rotates and
     scales up slightly, which can push its lower edge past where an
     un-scaled card would sit — this gap keeps that growth from ever
     reaching the note text underneath. */
  gap: 2.75rem;
}

.rail-stack {
  position: relative;
  width: 100%;
  max-width: 22rem;
  aspect-ratio: 3 / 4;
  margin: 0 auto;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform .1s ease-out;
}

.rail-ghost-numeral {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(9rem, 16vw, 15rem);
  color: var(--ink);
  opacity: 0.07;
  pointer-events: none;
  line-height: 1;
}

/* Each rail-image sits in its own fixed scatter position (set per-card via
   inline style — left/top/rotate/z-index, same convention as .cluster-photo
   further down) instead of stacking in place and cross-fading like before.
   All of them stay visible at once, like a torn-photo collage. Whichever
   one is currently relevant — scroll position, a hovered highlight in the
   text, or a direct click on the photo itself, all wired in initRails() —
   gets .front: raised above the others, straightened out, and lifted with
   a shadow. Everything else about its scatter position stays put. */
.rail-image {
  position: absolute;
  width: 74%;
  aspect-ratio: 3 / 4;
  cursor: pointer;
  transition: transform .35s ease, box-shadow .3s ease;
}

.rail-image .mock-card {
  height: 100%;
}

.rail-image:hover,
.rail-image:focus-visible {
  box-shadow: 0 14px 26px rgba(var(--ink-rgb), 0.18);
}

.rail-image:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

/* !important throughout — each card also carries its own inline z-index,
   width, and transform (its fixed scatter position/rotation/size), and
   inline style always beats an external class selector regardless of
   value unless overridden this way. Without it, whichever card happens to
   have the highest inline z-index (or its original small width) wins
   visually no matter which one is actually .front.

   Growing the box is done via width (not transform:scale) so the quote's
   font-size — set with a viewport-relative clamp(), not a container-
   relative one — doesn't get visually distorted by the zoom; it just gets
   more horizontal room to reflow into, and the newly-revealed .rail-explain
   paragraph below it gets real layout space instead of being squeezed. */
.rail-image.front {
  z-index: 10 !important;
  width: 84% !important;
  transform: rotate(0deg) translateY(-0.35rem) !important;
  box-shadow: 0 22px 40px rgba(var(--ink-rgb), 0.26);
}

.rail-image.front .mock-card {
  height: auto;
  min-height: 100%;
}

/* "Why this matters" explanation — lives directly on each Fig 1/2/3 card,
   hidden until that card is .front, then revealed as the card grows. Two
   earlier approaches (a panel below the photo stack, then a cursor-
   anchored popover over the copy) were both tried and retired: the panel
   read as disconnected from the highlighted text, and the popover — while
   anchored right above the text — still sat over the reading column. This
   keeps it on the left, on the same "picture frame" surface a learner is
   already looking at, and never covers anything on the right. */
.rail-explain {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.55;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  margin: 0;
  transition: opacity .25s ease, max-height .25s ease, margin-top .25s ease;
}

.rail-image.front .rail-explain {
  opacity: 0.85;
  max-height: 12rem;
  margin-top: 0.4rem;
}

.split-copy {
  min-width: 0;
}

.split-copy .prose {
  max-width: 34rem;
}

/* Bridges the reading above to the self-tests below — without it, the
   photo cluster reads as a random exercise rather than a continuation of
   what was just described. */
.cluster-intro {
  font-family: var(--font-body);
  font-size: 1.15rem;
  line-height: 1.65;
  max-width: var(--col-width);
  margin: 0 auto 2rem;
}

.split-copy article {
  margin-bottom: 2.75rem;
}

.split-copy article:last-child {
  margin-bottom: 0;
}

/* ---- Mock artifact cards (CSS-drawn placeholders, no external assets) ------ */

.mock-card {
  width: 100%;
  height: 100%;
  background: var(--stone);
  border: 1px solid var(--ink);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  font-family: var(--font-mono);
  box-shadow: 0 18px 34px rgba(var(--ink-rgb), 0.14);
}

.mock-card-label {
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.78;
  margin-bottom: 0.2rem;
}

/* Quote-style placeholder for the Fig 1/2/3 rail figures — big display-font
   type standing in for a photo, rather than a mock line-chart card. Pure
   CSS/HTML, no image asset: reliable, crisp text with zero risk of an AI
   image generator garbling the actual words. */
.mock-card--quote {
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 1.1rem;
}

.rail-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-optical-sizing: auto;
  font-weight: 340;
  font-size: clamp(1rem, 7vw, 1.35rem);
  line-height: 1.35;
  text-wrap: balance;
  margin: 0;
}

/* Compact email-client header block — Subject/From/Sent on their own tight
   lines instead of section-label + paragraph pairs, so the free-domain
   address and odd send time read as fields in a header, not throwaway body
   text easy to scroll past. Labels are CSS-generated (::before), not part
   of the element's text — keeps them intact when a flag's text swaps to
   its reworded retry variant. */
.email-header {
  margin-bottom: 1.25rem;
}

.email-field {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  margin: 0 0 0.3rem;
  line-height: 1.5;
}

.email-field::before {
  font-weight: 600;
  opacity: 0.78;
  margin-right: 0.4em;
}

.email-field--subject::before { content: "Subject:"; }
.email-field--from::before { content: "From:"; }
.email-field--sent::before { content: "Sent:"; }
.email-field--to::before { content: "To:"; }
.email-field--duration::before { content: "Duration:"; }
.email-field--recruiter::before { content: "Recruiter:"; }

.mock-line {
  height: 0.55rem;
  background: var(--ink);
  opacity: 0.16;
  border-radius: 2px;
}

.mock-line.w-95 { width: 95%; }
.mock-line.w-80 { width: 80%; }
.mock-line.w-60 { width: 60%; }
.mock-line.w-40 { width: 40%; }

.mock-line.flag {
  opacity: 0.4;
  background: var(--peach);
}

.mock-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.mock-avatar {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: var(--ink);
  opacity: 0.18;
  flex-shrink: 0;
}

/* Gives the LinkedIn artifact real profile-card structure — a banner with
   the avatar overlapping its bottom edge, the way an actual LinkedIn header
   is built — without reaching for LinkedIn's brand blue, which would clash
   with the paper/ink/peach palette used everywhere else. Deliberately no
   verified checkmark: that would imply the profile has been confirmed
   legitimate, which undercuts the whole point of the exercise. */
.linkedin-header {
  margin-bottom: 1rem;
}

.linkedin-banner {
  height: 5.5rem;
  background: none;
  border: 1px solid var(--ink);
  border-bottom: none;
}

.linkedin-identity {
  padding: 0 0.15rem;
}

.linkedin-avatar {
  width: 5.5rem;
  height: 5.5rem;
  margin-top: -2.75rem;
  margin-bottom: 0.6rem;
  opacity: 1;
  background: var(--paper);
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 3px var(--paper);
}

.linkedin-identity-text {
  display: block;
}

.linkedin-company-chip {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  opacity: 0.75;
}

.linkedin-company-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.3rem;
  height: 1.3rem;
  border: 1px solid var(--ink);
  font-size: 0.61rem;
  letter-spacing: 0;
  background: var(--stone);
}

.mock-badge {
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  border: 1px solid var(--ink);
  padding: 0.15rem 0.55rem;
  opacity: 0.78;
  border-radius: 999px;
  align-self: flex-start;
}

.mock-video {
  flex: 1;
  background: repeating-linear-gradient(
    135deg,
    var(--paper),
    var(--paper) 8px,
    var(--stone) 8px,
    var(--stone) 16px
  );
  border: 1px solid var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.mock-video-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--peach);
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
}

.mock-spacer {
  flex: 1;
}

/* ---- Full-bleed photo cluster (scattered, tilted, independently parallaxed) - */

.photo-cluster {
  width: 100%;
  margin: 1rem 0 3rem;
}

.cluster-caption {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-style: italic;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
  margin-bottom: 1.5rem;
}

.cluster-stage {
  position: relative;
  width: 100%;
  min-height: 24rem;
}

/* Module-level "what's next" — appears once all four artifacts are done,
   replacing the dead end Cam hit after finishing the last self-test. */
.module-complete-banner {
  max-width: var(--col-width);
  margin: 3rem auto 0;
  padding: 1.5rem 1.75rem;
  border: 2px solid var(--ink);
  text-align: center;
}

.module-complete-msg {
  font-family: var(--font-body);
  font-size: 1rem;
  margin: 0 0 1rem;
}

.module-complete-cta {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--ink);
  color: var(--paper);
  padding: 0.65rem 1.3rem;
  text-decoration: none;
  transition: opacity .15s ease;
}

.module-complete-cta:hover {
  opacity: 0.8;
}

.cluster-photo {
  position: absolute;
  width: 12rem;
  height: 15rem;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform .1s ease-out, box-shadow .2s ease;
}

.cluster-photo .mock-card {
  height: 100%;
}

.cluster-photo:hover {
  z-index: 5;
}

.cluster-photo--clickable {
  cursor: pointer;
}

.cluster-photo--clickable .mock-card {
  outline: none;
}

.cluster-photo--clickable:hover .mock-card,
.cluster-photo--clickable:focus-visible .mock-card {
  box-shadow: 0 22px 36px rgba(var(--ink-rgb), 0.24);
}

.mock-badge--hint {
  border-style: dashed;
  opacity: 0.75;
}

/* Completion state — once the self-test inside is fully done, the card
   itself shows it without needing to reopen the modal. A case-file stamp
   plus a slight desaturation, not just one or the other. */
.cluster-photo--clickable.completed .mock-card {
  filter: grayscale(0.55) contrast(0.92);
}

.cluster-photo--clickable.completed .mock-badge--hint {
  visibility: hidden;
}

.mock-stamp {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.cluster-photo--clickable.completed .mock-stamp {
  display: flex;
}

.mock-stamp-text {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--flag-red);
  border: 3px solid var(--flag-red);
  padding: 0.4rem 0.9rem;
  border-radius: 4px;
  transform: rotate(-11deg);
  opacity: 0.9;
  background: rgba(var(--paper-rgb), 0.55);
}

/* ---- Resume quiz overlay --------------------------------------------------- */

.resume-overlay {
  position: fixed;
  inset: 0;
  background: rgba(var(--ink-rgb), 0.45);
  z-index: 55;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease;
  padding: 2rem 1.5rem;
}

.resume-overlay.open {
  opacity: 1;
  visibility: visible;
}

/*
   The modal is a fixed, non-scrolling header stacked on an independently
   scrolling body — not a single scrolling panel with a sticky bar pinned
   inside it. That approach (sticky + negative margins) still let the
   header drift and cover content. A flex column with the header as a
   fixed-size sibling and the body as the only overflow:auto element can't
   drift, by construction: the header always occupies exactly its own
   height, nothing more, nothing less.
*/
.resume-panel {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--ink);
  width: min(100%, 42rem);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  padding: 0;
  box-shadow: 0 30px 60px rgba(var(--ink-rgb), 0.3);
}

.resume-header {
  flex: 0 0 auto;
  padding: 1.75rem 2.5rem 1.25rem;
  border-bottom: 1px solid var(--ink);
  background: var(--paper);
}

.resume-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1.5rem;
  margin-bottom: 1rem;
}

.resume-close {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--paper);
  border: 1px solid var(--ink);
  color: var(--ink);
  cursor: pointer;
  padding: 0.55rem 0.9rem;
  transition: background .15s, color .15s;
}

.resume-close:hover {
  background: var(--ink);
  color: var(--paper);
}

/* "Redacted document" look for the primary instruction — white text on a
   black bar, echoing the case-file aesthetic of the artifact itself. */
.resume-intro {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  padding: 0.3rem 0.6rem;
  margin: 0;
}

/* Plain text, no background — this is a step-two clarification, not the
   headline instruction, so it shouldn't compete with the redacted bar above. */
.resume-intro-detail {
  font-family: var(--font-mono);
  font-size: 0.79rem;
  letter-spacing: 0.03em;
  text-transform: none;
  opacity: 0.78;
  margin: 0.5rem 0 0;
}

.resume-quiz-counter {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  margin-bottom: 1rem;
  margin-right: 0.6rem;
}

.resume-attempt-counter {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
}

/* Collected-flags tracker — anonymous empty slots that fill in with the
   category once found, so the learner always sees progress and what's
   still outstanding without the slots giving away answers up front. */
.resume-tracker {
  margin-bottom: 0;
}

.resume-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1.75rem 2.5rem 3rem;
}

.resume-tracker-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
  margin: 0 0 0.5rem;
}

.resume-tracker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Sized for the longest possible category label up front (min-width, plus
   centered text) so a slot never visibly grows when it's filled in — it's
   always the size it's going to be, just empty until then. */
.resume-tracker-slot {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: center;
  border: 1px dashed var(--ink);
  opacity: 0.4;
  padding: 0.35rem 0.65rem;
  min-width: 8.5rem;
  transition: background .2s ease, color .2s ease, opacity .2s ease, border-style .2s ease;
}

.resume-tracker-slot.filled {
  opacity: 1;
  border-style: solid;
  background: var(--ink);
  color: var(--paper);
}

.resume-tracker-slot.filled.tracker-correct {
  background: var(--flag-green);
  border-color: var(--flag-green);
}

.resume-tracker-slot.filled.tracker-incorrect {
  background: var(--flag-red);
  border-color: var(--flag-red);
}

.resume-doc {
  font-family: var(--font-body);
}

/* Score/proficiency panel — appears once every flag has been found and
   classified. Pass and fail share the same shape; only the accent color
   and whether a retry button exists differ. */
.resume-results {
  margin: 2rem 0 0.5rem;
  padding: 1.25rem 1.5rem;
  border: 2px solid var(--ink);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .35s ease, transform .35s ease;
}

.resume-results.visible {
  opacity: 1;
  transform: translateY(0);
}

.resume-results.pass {
  border-color: var(--flag-green);
}

.resume-results.fail {
  border-color: var(--flag-red);
}

.resume-results-score {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  margin: 0 0 0.4rem;
}

/* Correct/incorrect keep their own color always — not tied to overall
   pass/fail — same green-right/red-wrong language as the rest of the quiz. */
.resume-results-correct {
  color: var(--flag-green);
}

.resume-results-incorrect {
  color: var(--flag-red);
}

.resume-results-msg {
  font-family: var(--font-body);
  font-size: 0.9rem;
  opacity: 0.8;
  margin: 0 0 1rem;
}

.resume-results-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.resume-results-retry,
.resume-results-continue {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: none;
  padding: 0.6rem 1.1rem;
  cursor: pointer;
  transition: opacity .15s ease, background .15s ease, color .15s ease;
}

.resume-results-continue {
  background: var(--flag-green);
  color: var(--paper);
}

.resume-results-retry {
  background: var(--ink);
  color: var(--paper);
}

/* When retry is the secondary option (shown alongside Continue on a pass),
   it should read as the lower-priority action, not compete with Continue. */
.resume-results-retry--secondary {
  background: none;
  border: 1px solid var(--ink);
  color: var(--ink);
}

.resume-results-retry:hover,
.resume-results-continue:hover {
  opacity: 0.8;
}

/* ==========================================================================
   Video Interview artifact — a branching audio/caption simulation, not a
   flag-and-classify quiz. Reuses .resume-overlay/.resume-panel/.resume-header/
   .resume-close/.resume-body for its outer chrome (see initArtifactOverlay in
   shared.js), then defines its own vi-* components below for everything
   inside, since the interaction shape (play audio, read synced captions,
   branch on a choice) is fundamentally different from the quiz engine.
   Adapted from the reference project's dark/noir theme into this course's
   paper/ink/peach system — see Simulation-Build-Log for the source.
   ========================================================================== */

.vi-panel {
  width: min(100%, 46rem);
}

.vi-chapters {
  display: flex;
  gap: 1.25rem;
  margin-top: 0.75rem;
}

.vi-chapter {
  font-family: var(--font-mono);
  font-size: 0.79rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
  transition: opacity .2s ease;
}

.vi-chapter.active {
  opacity: 1;
  font-weight: 700;
}

.vi-chapter.done {
  opacity: 0.78;
  text-decoration: line-through;
}

.vi-screen {
  display: none;
}

.vi-screen.active {
  display: block;
  animation: vi-fade-in .3s ease;
}

@keyframes vi-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.vi-image-slot {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--stone);
  border: 1px dashed var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-bottom: 1.25rem;
}

.vi-image-placeholder {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  opacity: 0.78;
  text-align: center;
  padding: 0 1rem;
}

.vi-image-slot img,
.vi-image-slot video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Consequence screens (s3a/s3b) reuse the same image-slot component but sit
   inline above the caption box rather than behind an absolutely-positioned
   one, since there's no play button layered over them — the audio for these
   screens lives on the narrator-card above, not on the image itself. */
.vi-consequence .vi-image-slot {
  aspect-ratio: 16 / 9;
  margin-bottom: 1rem;
}

.vi-caption-bar {
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.75rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 0.85rem;
  line-height: 1.5;
  padding: 0.5rem 0.85rem;
  text-align: center;
  min-height: 2.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity .2s ease;
}

.vi-caption-bar.visible {
  opacity: 1;
}

/* Static variant — used on the consequence screens (s3a/s3b/s3c), which have
   no image behind them, so the caption sits in its own bordered box instead
   of overlaying anything. */
.vi-caption-bar--static {
  position: static;
  border: 1px solid var(--ink);
  margin-bottom: 1rem;
  min-height: 3rem;
}

/* Full-slot play/pause control (ported from the reference sim's
   .play-overlay), used on s0 and s2 — the whole image/video area is
   clickable, not just a small corner button, with a centered circle that
   swaps a static triangle for animated "now playing" EQ bars. Auto-hides
   like the reference sim: hidden by default, shown only while
   .vi-image-slot carries .controls-visible (mouseenter/mousemove, or a
   brief nudge on arrival — wired in initVideoInterview), faded back out
   after a few seconds of no movement or on mouseleave — including while
   media is actually playing. The reference sim behaves the same way: the
   .playing class only swaps the icon/ripple, it does NOT pin the overlay
   visible over the subject's face for the whole clip. */
.vi-play-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: rgba(var(--shadow-rgb), 0.15);
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s ease, background .2s ease;
}

.vi-image-slot.controls-visible .vi-play-overlay {
  opacity: 1;
  pointer-events: auto;
}

.vi-play-overlay:hover {
  background: rgba(var(--shadow-rgb), 0.32);
}

/* s0 only — see the HTML comment on this element in module-three.html for
   why the first screen doesn't use the hover-to-reveal pattern. */
.vi-play-overlay--always {
  opacity: 1;
  pointer-events: auto;
}

/* Plain-text fallback under the disabled "Start the Call" button — same
   quiet, step-two-clarification tone as .resume-intro-detail. Hidden once
   shared.js's unlockGate() clears the gate, same moment the button itself
   becomes clickable, so the two states never show stale/contradictory info
   at once. */
.vi-hint {
  font-family: var(--font-mono);
  font-size: 0.79rem;
  letter-spacing: 0.03em;
  opacity: 0.78;
  margin: 0.6rem 0 0;
}

.vi-play-circle {
  width: 3.6rem;
  height: 3.6rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  border: 2px solid rgba(255, 255, 255, 0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  backdrop-filter: blur(6px);
  transition: transform .15s ease, background .15s ease;
}

.vi-play-overlay:hover .vi-play-circle {
  transform: scale(1.08);
  background: rgba(255, 255, 255, 0.22);
}

.vi-play-icon-playing {
  display: none;
  gap: 3px;
  align-items: center;
  height: 1.15rem;
}

.vi-play-icon-playing span {
  display: block;
  width: 3px;
  background: #fff;
  border-radius: 2px;
  animation: vi-eq 0.8s ease-in-out infinite;
}

.vi-play-icon-playing span:nth-child(1) { height: 0.5rem; }
.vi-play-icon-playing span:nth-child(2) { height: 1.05rem; animation-delay: .15s; }
.vi-play-icon-playing span:nth-child(3) { height: 0.5rem; animation-delay: .3s; }

@keyframes vi-eq {
  0%, 100% { transform: scaleY(0.5); }
  50%      { transform: scaleY(1.1); }
}

@keyframes vi-ripple {
  0%   { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.3); }
  100% { box-shadow: 0 0 0 20px rgba(255, 255, 255, 0); }
}

.vi-play-overlay.playing .vi-play-circle {
  animation: vi-ripple 1.3s infinite;
  border-color: #fff;
  background: rgba(255, 255, 255, 0.18);
}

.vi-play-overlay.playing .vi-play-icon-static { display: none; }
.vi-play-overlay.playing .vi-play-icon-playing { display: flex; }

/* Right-edge "continue" affordance (ported from the reference sim's
   .next-edge) — a soft dark gradient plus a chevron, hidden until that
   screen's media finishes, then revealed with a slow pulse so learners
   notice there's a way forward without cluttering the frame during
   playback. Only used on screens with exactly one clear next destination
   (s0 → s2) — s2 itself branches into three choices instead of a single
   next screen, so it doesn't get one, matching the reference sim's own
   scoping. */
.vi-next-edge {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 30%;
  z-index: 4;
  background: linear-gradient(to right, transparent 0%, rgba(var(--shadow-rgb), 0.4) 100%);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 1rem;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s ease;
}

@keyframes vi-next-edge-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

.vi-next-edge.revealed {
  opacity: 1;
  pointer-events: auto;
  animation: vi-next-edge-pulse 3.2s ease-in-out 0.5s infinite;
}

.vi-next-edge:hover {
  background: linear-gradient(to right, transparent 0%, rgba(var(--shadow-rgb), 0.58) 100%);
  animation: none;
  opacity: 1;
}

.vi-caller-name {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  opacity: 0.78;
  margin: 0 0 0.75rem;
}

.vi-question {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 0.75rem;
}

.vi-question-detail {
  font-family: var(--font-body);
  font-size: 0.85rem;
  line-height: 1.5;
  opacity: 0.8;
  margin: -0.4rem 0 0.9rem;
}

.vi-choices {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.vi-choice {
  font-family: var(--font-body);
  font-size: 1.02rem;
  line-height: 1.5;
  text-align: left;
  text-wrap: pretty;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 0.75rem 1rem;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, opacity .15s ease;
}

.vi-choice:hover:not(:disabled) {
  background: var(--ink);
  color: var(--paper);
}

.vi-choice:disabled {
  opacity: 0.35;
  cursor: default;
}

.vi-choice-letter {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  opacity: 0.78;
  margin-bottom: 0.25rem;
}

.vi-narrator-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.75rem;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}

.vi-narrator-card:hover {
  background: var(--ink);
  color: var(--paper);
}

.vi-narrator-card.playing {
  background: var(--flag-green);
  border-color: var(--flag-green);
  color: var(--paper);
}

.vi-consequence {
  border: 2px solid var(--ink);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
}

.vi-consequence--wrong {
  border-color: var(--flag-red);
}

.vi-consequence--partial {
  border-color: var(--flag-partial);
}

.vi-consequence--correct {
  border-color: var(--flag-green);
}

.vi-consequence-label {
  font-family: var(--font-mono);
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 0.85rem;
}

.vi-consequence--wrong .vi-consequence-label { color: var(--flag-red); }
.vi-consequence--partial .vi-consequence-label { color: var(--ink); } /* not --flag-partial: 3.57:1 fails body text */
.vi-consequence--correct .vi-consequence-label { color: var(--flag-green); }

.vi-consequence-note {
  font-family: var(--font-body);
  font-size: 0.85rem;
  opacity: 0.8;
  padding-top: 0.85rem;
  margin-top: 0.85rem;
  border-top: 1px solid var(--ink);
}

.vi-principle {
  border: 1px solid var(--ink);
  padding: 1.1rem 1.25rem;
  text-align: center;
  margin-bottom: 1.25rem;
}

.vi-principle-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.78;
  margin: 0 0 0.5rem;
}

.vi-principle-rule {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  margin: 0 0 0.25rem;
}

.vi-principle-sub {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  opacity: 0.78;
}

.vi-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.resume-name {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.9rem;
  margin: 0 0 0.2rem;
}

.resume-role {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 0.4rem;
}

.resume-contact {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  opacity: 0.78;
  margin: 0 0 1.5rem;
}

.resume-section-label {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.78;
  margin: 1.75rem 0 0.75rem;
}

.resume-role-line {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1rem;
  margin: 1rem 0 0.4rem;
}

.resume-dates {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 0.82rem;
  opacity: 0.78;
  margin-left: 0.5rem;
}

.resume-doc p.quiz-choice {
  font-size: 1.08rem;
  line-height: 1.6;
  margin: 0 0 0.85rem;
  padding: 0.2rem 0;
}

.resume-footer {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  opacity: 0.8;
  margin-top: 1rem;
}

/* Quiz interaction states */

.quiz-choice {
  cursor: pointer;
  border-radius: 2px;
  transition: background .2s ease;
}

.quiz-choice:hover {
  background: rgba(var(--ink-rgb), 0.06);
}

/* Found uses peach, not red — red is reserved for "wrong" in the category
   step that follows, and finding a suspicious line is itself the correct
   move, so it shouldn't look like an error. */
.quiz-choice.found {
  cursor: default;
  background-image: linear-gradient(
    100deg,
    rgba(var(--accent-rgb), 0.05) 0%,
    rgba(var(--accent-rgb), 0.55) 12%,
    rgba(var(--accent-rgb), 0.6) 55%,
    rgba(var(--accent-rgb), 0.5) 88%,
    rgba(var(--accent-rgb), 0.06) 100%
  );
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  transform: rotate(-0.4deg);
  display: inline-block;
}

.quiz-choice.found:hover {
  background-image: linear-gradient(
    100deg,
    rgba(var(--accent-rgb), 0.05) 0%,
    rgba(var(--accent-rgb), 0.55) 12%,
    rgba(var(--accent-rgb), 0.6) 55%,
    rgba(var(--accent-rgb), 0.5) 88%,
    rgba(var(--accent-rgb), 0.06) 100%
  );
}

/* Miss needs to be unmistakable even for a quick click — a shake plus a
   gray wash, still fully reversible (no permanent mark). No red here: a
   decoy line isn't "wrong" the way an incorrect category chip is, so it
   shouldn't borrow that color language. */
.quiz-choice.miss {
  animation: quiz-miss .6s ease;
}

@keyframes quiz-miss {
  0% { background: rgba(var(--ink-rgb), 0.16); transform: translateX(0); }
  15% { transform: translateX(-4px); }
  30% { transform: translateX(4px); }
  45% { transform: translateX(-3px); }
  60% { transform: translateX(3px); }
  75% { transform: translateX(-1px); }
  100% { background: transparent; transform: translateX(0); }
}

/* Explanation copy is neutral ink, not red — this is educational context,
   shown after both correct and incorrect picks, so it shouldn't visually
   imply "wrong" just because it follows a chip choice. */
.quiz-note {
  display: block;
  font-family: var(--font-mono);
  /* UAT 14 Aug: "that's kind of hard to read… is that actually to our standard
     as far as accessibility?" It measured 4.7:1 — passing, but only just, at
     12.8px and on a tilt. This is the teaching text; it earns full strength.
     Ink on Bone is 9.39:1. Tilt kept but halved: character without the cost. */
  font-size: 0.9rem;
  line-height: 1.6;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin: 0.2rem 0 0.9rem 1.25rem;
  transform: rotate(-0.5deg);
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity .35s ease;
}

/* Only the lead word carries color/weight — the reader gets an unambiguous
   Correct/Incorrect signal without the whole explanation reading as an
   alarm (that was the round-2 bug: full-red text on a correct answer). */
.quiz-note-lead {
  font-weight: 700;
  letter-spacing: 0.03em;
}

.quiz-note-lead.correct {
  color: var(--flag-green);
}

.quiz-note-lead.incorrect {
  color: var(--flag-red);
}

.quiz-note.visible {
  opacity: 1;
  max-height: none;
}

.quiz-note::before {
  content: "\2192 ";
}

/* ---- Categorize step (the "step further" layer, reusable across artifacts) - */

.quiz-categorize {
  margin: 0.3rem 0 0.9rem 1.25rem;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity .35s ease;
}

.quiz-categorize.visible {
  opacity: 1;
  max-height: none;
}

.quiz-categorize-prompt {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
  margin: 0 0 0.5rem;
}

.quiz-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.quiz-chip {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--paper);
  border: 1px solid var(--ink);
  color: var(--ink);
  padding: 0.55rem 0.85rem;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.quiz-chip:hover {
  background: var(--ink);
  color: var(--paper);
}

.quiz-chip.correct {
  background: var(--flag-green);
  color: var(--paper);
  border-color: var(--flag-green);
}

.quiz-chip.incorrect {
  background: var(--flag-red);
  color: var(--paper);
  border-color: var(--flag-red);
}

.quiz-chip.locked {
  cursor: default;
  pointer-events: none;
}

/* ---- Artifact / parallax cards (legacy full-width variant, still used for
       standalone single artifacts outside the split rail) ---------------------- */

.artifact {
  background: var(--stone);
  border: 1px solid var(--ink);
  padding: 1.75rem;
  margin: 2rem 0;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform .1s ease-out;
}

.artifact-label {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 1rem;
  opacity: 0.78;
}

.artifact-body {
  font-family: var(--font-body);
  font-size: 1.08rem;
  line-height: 1.6;
}

.artifact-body p {
  margin: 0 0 0.9rem;
}

.artifact-body p:last-child {
  margin-bottom: 0;
}

/* ---- Flags counter ---------------------------------------------------------- */

.flags-counter {
  position: fixed;
  bottom: 1.75rem;
  right: 1.75rem;
  z-index: 40;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  pointer-events: none;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
}

/* ---- Decision point ---------------------------------------------------------- */

.decision-block {
  margin: 3rem 0;
  max-width: var(--col-width);
}

.decision-prompt {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 1.5rem;
}

.decision-option {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
  border: 1px solid var(--ink);
  padding: 1.25rem 1.5rem;
  margin-bottom: -1px;
  cursor: pointer;
  background: var(--paper);
  transition: background .15s, color .15s;
}

.decision-option:hover {
  background: var(--ink);
  color: var(--paper);
}

.decision-option.correct {
  background: var(--flag-green);
  color: var(--paper);
  border-color: var(--flag-green);
}

.decision-option.incorrect {
  background: var(--flag-red);
  color: var(--paper);
  border-color: var(--flag-red);
}

.decision-option[disabled],
.decision-option.locked {
  cursor: default;
  pointer-events: none;
}

/* Never rely on color alone (WCAG 1.4.1) — every locked option also gets an
   explicit text verdict. .correct always marks the actual right answer,
   even when it wasn't the one clicked; .incorrect only ever marks the
   option the learner actually picked (see initDecisionPoint in shared.js),
   so at most one option carries each label. */
.decision-option.correct::after,
.decision-option.incorrect::after {
  margin-left: auto;
  flex-shrink: 0;
  align-self: center;
  padding-left: 1.25rem;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.decision-option.correct::after {
  content: "\2713" " Correct";
}

.decision-option.incorrect::after {
  content: "\2717" " Incorrect";
}

.decision-letter {
  font-family: var(--font-mono);
  font-size: 0.9rem;
  flex-shrink: 0;
  width: 1.2rem;
}

.decision-text {
  font-family: var(--font-body);
  font-size: 1.08rem;
  line-height: 1.5;
}

.feedback {
  margin-top: 2.5rem;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity .5s ease;
}

.feedback.visible {
  max-height: none;
  opacity: 1;
}

.feedback-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 1rem;
}

.feedback-body {
  font-family: var(--font-body);
  font-size: 1.15rem;
  line-height: 1.7;
}

/* ---- Final graded quiz — same visual language as .decision-block/.decision-
   option, its own classes since it's a set of questions, not one prompt --- */

.final-quiz {
  max-width: var(--col-width);
  margin: 3rem auto;
}

.final-quiz-question {
  margin-bottom: 3rem;
}

.final-quiz-question:last-of-type {
  margin-bottom: 2rem;
}

.final-quiz-prompt {
  font-family: var(--font-body);
  font-size: 1.15rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
}

.final-quiz-number {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-70, var(--ink));
  opacity: 0.65;
  margin-bottom: 0.4rem;
}

.final-quiz-option {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
  border: 1px solid var(--ink);
  padding: 1.1rem 1.4rem;
  margin-bottom: -1px;
  cursor: pointer;
  background: var(--paper);
  transition: background .15s, color .15s;
}

.final-quiz-option:hover {
  background: var(--stone);          /* 7.12:1 with ink text */
}

/* Selected is the committed state, so it gets the strongest treatment.
   Hover is a lighter touch. Swapped after UAT — they were the wrong way
   round, and "the one I picked" read weaker than "the one I'm pointing at". */
.final-quiz-option.selected {
  background: var(--ink);            /* 10.14:1 with paper text */
  color: var(--paper);
  border-color: var(--ink);
}

.final-quiz-option.correct {
  background: var(--flag-green);
  color: var(--paper);
  border-color: var(--flag-green);
}

.final-quiz-option.incorrect {
  background: var(--flag-red);
  color: var(--paper);
  border-color: var(--flag-red);
}

.final-quiz-option.locked {
  cursor: default;
  pointer-events: none;
}

.final-quiz-option.correct::after,
.final-quiz-option.incorrect::after {
  margin-left: auto;
  flex-shrink: 0;
  align-self: center;
  padding-left: 1.25rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.final-quiz-option.correct::after {
  content: "\2713" " Correct";
}

.final-quiz-option.incorrect::after {
  content: "\2717" " Incorrect";
}

.final-quiz-explain {
  margin-top: 1rem;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  padding: 0 1.4rem;
  border-left: 3px solid var(--ink);
  transition: opacity .4s ease;
}

.final-quiz-explain.visible {
  max-height: none;
  opacity: 1;
  padding: 0.9rem 1.4rem;
}

.final-quiz-controls {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 1px solid var(--ink);
}

.final-quiz-score {
  font-family: var(--font-mono);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
}

.final-quiz-pass,
.final-quiz-fail {
  margin-top: 2rem;
  padding: 1.5rem;
  border: 1px solid var(--ink);
}

.final-quiz-pass {
  border-color: var(--flag-green);
  background: color-mix(in srgb, var(--flag-green) 10%, var(--paper));
}

.final-quiz-fail {
  border-color: var(--flag-red);
  background: color-mix(in srgb, var(--flag-red) 8%, var(--paper));
}

/* ---- Nav footer between pages ---------------------------------------------- */

.page-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: var(--col-width);
  margin-top: 4rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.page-nav a {
  padding: 0.5rem 0.25rem;
  transition: background .15s, color .15s;
}

.page-nav a:hover {
  background: var(--ink);
  color: var(--paper);
}

/* ---- Responsive ------------------------------------------------------------- */

@media (max-width: 900px) {
  .split {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .split-rail {
    position: static;
    height: auto;
    margin-bottom: 1rem;
  }

  .rail-stack {
    max-width: 16rem;
  }
}

@media (max-width: 640px) {
  .page {
    padding: calc(var(--topbar-h) + 2.5rem) 1.25rem 4rem;
  }

  .topbar {
    padding: 0 1rem;
    font-size: 0.72rem;
  }

  .topbar-sub {
    display: none;
  }

  .flags-counter {
    font-size: 0.78rem;
    bottom: 1rem;
    right: 1rem;
  }

  .prose {
    font-size: 1.2rem;
  }

  .cluster-photo {
    width: 9rem;
    height: 11.5rem;
  }

  .resume-header {
    padding: 1.25rem 1.5rem 1rem;
  }

  .resume-body {
    padding: 1.25rem 1.5rem 2.5rem;
  }
}

/* ---- Front cover: two-track selector ---------------------------------------- */

.cover-tracks {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2.5rem;
  margin: 0 auto 3rem;
  max-width: 56rem;
}

.cover-track {
  flex: 1 1 15rem;
  text-align: center;
}

.cover-track-desc {
  font-family: var(--font-body);
  font-size: 0.92rem;
  line-height: 1.6;
  opacity: 0.8;
  margin: 0.9rem 0 0;
}

.begin-reading--secondary {
  border-color: var(--stone);
  opacity: 0.85;
}

.begin-reading--secondary:hover {
  background: var(--stone);
  color: var(--ink);
}

/* ---- Front cover: what-to-expect card ---------------------------------------- */
/* Replaces the old decorative "Case One Preview" mock card. That one looked
   like a document but did nothing when clicked; this one is real content —
   orientation before the learner commits, not a teaser. Real text, not an
   image, so it scales and reads correctly under WCAG AA. */

.expect-card {
  border: 1px solid var(--stone);
  padding: 1.75rem 2rem;
  max-width: 24rem;
  background: var(--paper);
}

.expect-card-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
  margin: 0 0 0.9rem;
}

.expect-card-list {
  font-family: var(--font-body);
  font-size: 0.98rem;
  line-height: 1.6;
  margin: 0;
  padding-left: 1.15rem;
}

.expect-card-list li {
  margin-bottom: 0.6rem;
}

.expect-card-list li:last-child {
  margin-bottom: 0;
}

/* ---- Wrap-up: single completion statement (Cam, 10 Sept 2026) ------------- */

.complete-card {
  border-left: 4px solid var(--peach);
  background: var(--surface);
  border-radius: 0 8px 8px 0;
  padding: 1.75rem 2rem;
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.complete-line {
  font-family: var(--font-body);
  font-size: 1.35rem;
  line-height: 1.45;
  margin: 0;
  text-wrap: balance;
}

.complete-line strong {
  display: block;
  font-size: 1.6rem;
  margin-bottom: 0.4rem;
}

/* ---- Job aid: Vigilance Framework reference card ---------------------------- */

.framework-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin: 2.5rem 0;
}

.framework-card {
  border: 1px solid var(--stone);
  padding: 1.5rem 1.75rem;
}

.framework-card-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
  margin: 0 0 0.6rem;
}

.framework-card-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: 1.3rem;
  margin: 0 0 0.75rem;
}

.framework-card-body {
  font-family: var(--font-body);
  font-size: 0.98rem;
  line-height: 1.6;
  margin: 0;
}

.framework-card-body li {
  margin-bottom: 0.4rem;
}

/* ---- Job aid: process steps -------------------------------------------------- */

.process-steps {
  list-style: none;
  margin: 2rem 0;
  padding: 0;
  counter-reset: process-step;
}

.process-step {
  counter-increment: process-step;
  position: relative;
  padding: 0 0 1.75rem 3rem;
  border-left: 1px solid var(--stone);
  margin-left: 0.9rem;
}

.process-step:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}

.process-step::before {
  content: counter(process-step);
  position: absolute;
  left: -0.9rem;
  top: 0;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.process-step-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: 1.2rem;
  margin: 0 0 0.4rem;
}

.process-step-body {
  font-family: var(--font-body);
  font-size: 0.98rem;
  line-height: 1.65;
  margin: 0;
}

@media (max-width: 720px) {
  .framework-grid {
    grid-template-columns: 1fr;
  }
}


/* ---- WHITE PAGE + BONE CARDS ------------------------------------------------
   Dexcom names White as the recommended background ("allows the primary Greens
   to stand out") and Bone as an accent. This puts each in its stated role rather
   than using the accent as the page.
   The payoff is measurable, not stylistic: Dexcom Green is 3.02:1 on White and
   2.80:1 on Bone, so the brand mark is only usable at all on a White surface.
   Bold Gray on Bone is still 9.39:1, so cards stay fully readable.
--------------------------------------------------------------------------- */
.expect-card,
.mock-card,
.resume-doc {
  background: var(--surface);
}
.topbar-brand { color: var(--brand-green); }
.eyebrow { color: var(--brand-green); }

/* ==========================================================================
   ROLE FORK  (added 2026-08-13 after the Dexcom SME session)
   Two audiences, confirmed by Kristy Ewert: recruiter-facing and
   leader-facing, where "leader" deliberately covers hiring managers AND
   panel members. Role is an axis independent of ?track= length.
   Selection is stored so a learner returning mid-course keeps their path.
   ========================================================================== */

.role-select {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin: 1.75rem 0 0;
  text-align: left;
}

.role-card {
  flex: 1 1 17rem;
  display: flex;
  flex-direction: column;
  gap: .45rem;
  background: var(--surface);
  border: 1px solid var(--stone);
  border-radius: 10px;
  padding: 1.4rem 1.35rem 1.2rem;
  text-decoration: none;
  color: var(--ink);
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

.role-card:hover,
.role-card:focus-visible {
  border-color: var(--peach);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(var(--shadow-rgb), .10);
}

.role-tag {
  font-family: var(--font-mono, var(--font-body));
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--peach);
}

.role-title { font-size: 1.12rem; font-weight: 800; line-height: 1.25; color: var(--flag-red); }
.role-desc  { font-size: .93rem; line-height: 1.5; }
.role-go    { font-size: .88rem; font-weight: 700; color: var(--peach); margin-top: .35rem; }

/* Role-conditional content. The class is set on <html> synchronously by
   initRole() so mismatched blocks never paint, even for one frame. */
html.role-recruiter [data-role="leader"],
html.role-leader    [data-role="recruiter"] { display: none !important; }

/* Small persistent marker so a learner (and a reviewer) can see which path
   they're on without going back to the cover. */
.role-badge {
  display: inline-block;
  font-family: var(--font-mono, var(--font-body));
  font-size: .64rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--paper);
  background: var(--peach);
  border-radius: 3px;
  padding: .18rem .45rem;
  vertical-align: middle;
}

/* Inline teaching callout — used for the "AI use is not fraud" and
   "it might be an accommodation" notes added after the SME session. Both are
   corrective points: they exist to STOP a learner over-flagging, so they read
   as a calm aside rather than another red flag. */
.note-card {
  background: var(--surface);
  border-left: 4px solid var(--peach);
  border-radius: 0 8px 8px 0;
  padding: 1.15rem 1.35rem;
  margin: 2rem 0;
}
.note-card-eyebrow {
  font-family: var(--font-mono, var(--font-body));
  font-size: .66rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--peach);
  margin: 0 0 .5rem;
}
.note-card p { margin: 0; font-size: .98rem; line-height: 1.6; }
.note-card p + p { margin-top: .7rem; }

/* Reveal-on-hover, then stay revealed. Replaces the cursor tooltip (UAT
   2026-08-13). White on Contrast Green measures 5.30:1 — the same pairing
   already used for a found flag, so a revealed line and a caught flag read
   as the same kind of thing, which is the point. */
.hl.revealed,
.hl-flag.revealed,
.feedback-highlight.revealed {
  background: var(--peach);
  color: var(--paper);
  border-radius: 3px;
  border-bottom-color: transparent;
}
.hl:focus-visible,
.hl-flag:focus-visible,
.feedback-highlight:focus-visible {
  outline: 2px solid var(--peach);
  outline-offset: 2px;
}
/* The old floating caption is gone; keep the rule so any stale markup can't
   paint a stray box. */
.hover-tip { display: none !important; }

/* ==========================================================================
   RAIL CARD RESTYLE  (UAT 2026-08-13)
   Cam: "the before you flag anything card… that could be how the figure cards
   look. Maybe that's the way that it goes because that looks really nice."
   So the figure cards adopt the note-card language: Bone ground, Contrast
   Green rule, and the figure label promoted to a headline band instead of a
   cursor tooltip.
   ========================================================================== */

.rail-image .mock-card {
  background: var(--surface);
  border: 1px solid var(--stone);
  border-radius: 8px;
  overflow: hidden;
}

/* Accent only on the card in front. On the rotated back cards the rule read
   as a stray diagonal line floating beside the stack. */
.rail-image.front .mock-card { border-left: 4px solid var(--peach); border-radius: 0 8px 8px 0; }

/* The label the tooltip used to carry, now a headline on the card itself. */
.rail-image .mock-card-label {
  display: block;
  background: var(--ink);
  color: var(--paper);            /* 10.14:1 */
  font-family: var(--font-display, var(--font-body));
  font-size: .6rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 700;
  text-align: left;
  margin: -1px -1px .85rem;
  padding: .45rem .7rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rail-image .rail-quote {
  text-align: left;
  font-size: 1.02rem;
  line-height: 1.4;
}

.rail-image .rail-explain {
  text-align: left;
}

/* A pinned card is one the learner asked for. Say so quietly. */
.rail-image.front .mock-card {
  border-left-color: var(--peach);
  box-shadow: 0 8px 22px rgba(var(--shadow-rgb), .12);
}

/* Affordance: the stack is clickable and nothing currently says so. */
.rail-image.front { cursor: pointer; }
.rail-image.front .mock-card::after {
  content: 'Click for the next figure';
  display: block;
  margin-top: .9rem;
  padding-top: .6rem;
  border-top: 1px solid var(--stone);
  font-size: .66rem;
  letter-spacing: .13em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--peach);
  text-align: left;
}

/* ==========================================================================
   UAT 2026-08-13 — cover and layout pass
   Cam: "I feel like we decided that we wanted the content to all be in the
   centre of the page, but the text should still be left justified."
   Plus: wider column, orphan control, role cards that read as buttons,
   and the mid-grey label that failed contrast.
   ========================================================================== */

/* Wider reading column. 38rem was the Stripe Press inheritance; at 15 minutes
   of runtime the extra width buys back real scroll length and helps line
   balance at the same time. */
:root { --col-width: 44rem; }

/* Content centred, text left-aligned. The block still sits in the middle of
   the page; only the ragging changes. */
.cover { text-align: left; }
.cover .column,
.cover .column--wide { margin-left: auto; margin-right: auto; }
.cover-subtitle,
.cover-description,
.cover-audience { max-width: 42rem; margin-left: 0; margin-right: 0; }

/* "Choose the version…" was Mid-Tone Gray at 0.78 opacity: 3.85:1 before the
   fade, worse after. Body-legible text uses ink. */
.cover-audience { opacity: 1; color: var(--ink); }
.cover-audience--muted { color: var(--mid); }

/* Role cards read as buttons. Start affordance pinned to the bottom so the two
   cards line up regardless of how long the description runs. */
.role-card { min-height: 100%; }
.role-desc { flex: 1 1 auto; }
.role-go {
  align-self: flex-start;
  margin-top: 1rem;
  background: var(--ink);
  color: var(--paper);
  padding: .5rem .9rem;
  border-radius: 5px;
  font-size: .8rem;
  letter-spacing: .06em;
  transition: background .16s ease;
}
.role-card:hover .role-go,
.role-card:focus-visible .role-go { background: var(--peach); }

/* Orphan control. Cam's rule: never a single trailing word, and the last line
   never runs past the line above it. text-wrap:pretty does the heavy lifting
   where supported; the balance is applied to short blocks only. */
.expect-card-list li,
.cover-description,
.chapter-hint,
.module-complete-msg,
.decision-prompt { text-wrap: pretty; }
.chapter-title,
.pull-quote,
.expect-card-eyebrow,
.role-title { text-wrap: balance; }

/* The expect card was 24rem, which is what forced "interview" and "matters."
   onto lines of their own. */
.expect-card { max-width: 30rem; }

/* Nudge the next step. UAT: "my eye sees the bottom and doesn't know what to
   do." Forward link is filled, back link stays quiet. */
.page-nav a:last-child {
  background: var(--ink);
  color: var(--paper);
  padding: .55rem 1rem;
  border-radius: 5px;
  border-bottom: 0;
}
.page-nav a:last-child:hover { background: var(--peach); color: var(--paper); }

/* ==========================================================================
   UAT round 2 — 14 Aug
   ========================================================================== */

/* 1 · The artifact cluster hung off the left edge. The cards are absolutely
   positioned inside .cluster-stage, which was full-width, so "centred" meant
   "wherever the left offsets happen to land." Constrain the stage to the span
   the cards actually occupy and centre that, so the group sits under the
   column instead of drifting away from it. */
.photo-cluster { display: flex; flex-direction: column; align-items: center; }
.photo-cluster > * { width: 100%; max-width: var(--wide-width); }
.cluster-stage {
  max-width: 58rem;
  margin-left: auto;
  margin-right: auto;
  transition: transform .2s ease;
}
.cluster-caption { text-align: left; }

/* 2 · "Attempt 1" was a bare inline span dropped between the counter pill and
   the tracker, so it sat alone on its own line with nothing to belong to.
   Pair it with the found-counter on one row: progress on the left, attempt on
   the right, which is the relationship they actually have. */
.resume-quiz-counter { vertical-align: middle; }
.resume-progress-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.resume-progress-row .resume-quiz-counter { margin-bottom: 0; }
.resume-attempt-counter {
  opacity: 1;
  color: var(--mid);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
}

/* Explicit line breaks on the cover title; balance would fight them. */
.cover-title { text-wrap: normal; }

/* ==========================================================================
   UAT round 3 — 14 Aug
   ========================================================================== */

/* A · Figure cards were clipping their own text. .rail-image carries an
   aspect-ratio, .mock-card carries overflow:hidden (added for the label band),
   and .rail-explain was capped at 12rem. Any explanation longer than the box
   simply vanished mid-sentence. The front card now sizes to its content. */
.rail-image.front { aspect-ratio: auto; height: auto; }
.rail-image.front .mock-card { height: auto; min-height: 0; }
.rail-image.front .rail-explain { max-height: none; transition: opacity .25s ease; }

/* B · Cover: standalone display items centre, running text stays left.
   Cam's rule: "when we have a paragraph, left justified. When we have bullet
   points, left justified. But the standalone items, layout centred." */
.cover .eyebrow,
.cover .cover-title,
.cover .cover-subtitle { text-align: center; }
.cover .cover-subtitle { margin-left: auto; margin-right: auto; }
.cover-audience { text-align: center; margin-left: auto; margin-right: auto; }
.cover-description { text-align: left; }
.role-card, .role-card * { text-align: left; }

/* C · "What to Expect" adopts the note-card language — Bone ground, Contrast
   Green rule, green eyebrow — so it reads as deliberate rather than as a
   floating box. */
.expect-card {
  background: var(--surface);
  border: 1px solid var(--stone);
  border-left: 4px solid var(--peach);
  border-radius: 0 8px 8px 0;
  text-align: left;
  margin-left: auto;
  margin-right: auto;
}
.expect-card-eyebrow { color: var(--peach); opacity: 1; font-weight: 700; letter-spacing: .15em; }

/* D · "5 Connections" sat under the REVIEWED stamp once the card completed.
   Move it clear of the stamp's centre band. */
.mock-badge { position: relative; z-index: 2; }
.cluster-photo--clickable .mock-card > .mock-badge:not(.mock-badge--hint) {
  position: absolute;
  left: 0.75rem;
  bottom: 2.6rem;
}

/* E · Pull quotes: accent rule and an indent instead of a filled panel.
   "just a little accent line without the bone color and just slightly
   indented… changes the cognitive approach to it." */
.pull-quote {
  background: none;
  border: 0;
  border-left: 3px solid var(--peach);
  padding: .35rem 0 .35rem 1.5rem;
  margin-left: 1.25rem;
  border-radius: 0;
}

/* F · Locked forward navigation reads as broken because it looks identical to
   an active link. Show the lock. */
.page-nav a.nav-locked {
  background: var(--stone);
  color: var(--ink);          /* 7.12:1 — the lock is still readable */
  cursor: not-allowed;
}
/* The reason, not just the state. A lock without a reason is a wall. */
.page-nav a.nav-locked::after {
  content: ' · ' attr(data-lock-reason);
  font-size: .82em;
  letter-spacing: .08em;
  opacity: .85;
}

/* Chapter pips double as backwards navigation once passed (UAT 14 Aug). */
.vi-chapter--available {
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--peach);
}
.vi-chapter--available:hover { color: var(--peach); }
.vi-chapter--available:focus-visible { outline: 2px solid var(--peach); outline-offset: 2px; }

/* ==========================================================================
   UAT 2026-08-14 (pm) — Cam's read of the rebuilt Module One
   ==========================================================================
   Four things, all from the recording:

   1. "They ARE paper shaped, but then when we click on them they become
      square shaped. Well, let's just leave them paper shaped."
      My own 13 Aug clipping fix set aspect-ratio:auto on the front card, so
      once the copy got shorter the box collapsed to content height. Ratio
      comes back as a FLOOR (min-height), not a cap — paper proportions when
      the text is short, room to grow when it isn't. No clipping either way.

   2. "That text could probably be bigger." It should be, and not as a taste
      call: Dexcom's published type scale sets body copy at 11pt/15pt minimum,
      which maps to ~15-16px on screen. .rail-explain was 0.82rem = 13.1px,
      under their own floor. Now 1rem.

   3. Opacity 0.85 on Bold Gray renders #5E5C5C, a colour that is not in the
      palette. Their rule is Bold Gray or White for body fill. Full opacity
      is both on-brand and better contrast (6.16:1 -> 9.40:1 on Bone).

   4. "The paragraph itself is left justified, but that whole block should be
      centred." Applies to every module bridge, not just Module One.
   ========================================================================== */

/* 1 — paper shape as a floor, in every state */
.rail-image.front {
  aspect-ratio: auto;
  height: auto;
}
.rail-image.front .mock-card {
  height: auto;
  min-height: 0;
  aspect-ratio: 3 / 4;          /* floor: the card is at least paper-shaped */
  display: flex;
  flex-direction: column;
  overflow: visible;            /* grow past the ratio rather than clip */
}

/* 2 + 3 — legible, on-brand figure text */
.rail-image .rail-explain {
  font-size: 1rem;              /* was 0.82rem / 13.1px — under Dexcom's 11pt floor */
  line-height: 1.6;
  opacity: 1;                   /* was .85, which rendered an off-palette grey */
  color: var(--ink);
}
.rail-image.front .rail-explain { opacity: 1; }

.rail-image .rail-explain strong {
  font-weight: 700;
  color: var(--ink);
}

/* The label band was 0.6rem / 9.6px — footnote size for a headline element. */
.rail-image .mock-card-label {
  font-size: .75rem;
  letter-spacing: .09em;
  padding: .55rem .8rem;
}

.rail-image.front .mock-card::after {
  font-size: .72rem;
  margin-top: auto;             /* pin the affordance to the bottom of the card */
  padding-top: .9rem;
}

.rail-image .mock-card { padding: 1.15rem 1.25rem 1.25rem; }

/* 4 — bridge block centred, copy still left-justified */
.column--wide > p.reveal[data-page-read-marker] {
  max-width: var(--col-width);
  margin-left: auto;
  margin-right: auto;
  text-align: left;
}

/* ==========================================================================
   UAT 2026-08-14 (late) — rail figure cards, label band and back cards
   ==========================================================================
   Cam: "The black highlight runs off the card… the cards behind are also
   getting strange when they are behind and not up front."

   One root cause for both. The label band is a headline that bleeds to the
   card edges with negative margins, and it carried white-space:nowrap. A long
   title ("Fig 1 — The Pause That Never Varies") is wider than the card, so:

     · on the FRONT card it escaped, because my 14 Aug aspect-ratio fix had
       set overflow:visible on the card to stop the text clipping;
     · on the BACK cards it was clipped mid-word by overflow:hidden, which is
       the floating "STION" and "G 1 — THE PA" debris in the stack.

   Fix the label instead of the overflow: let it wrap to two lines. Nothing
   then exceeds the card horizontally, so the card can go back to clipping at
   its rounded corners, and the paper proportion moves to the CONTAINER as a
   floor — which is where it belonged all along.
   ========================================================================== */

/* The container holds the paper shape as a minimum. */
.rail-image.front {
  aspect-ratio: 3 / 4;
  height: auto;
}

/* The card fills it, and is free to grow taller than it if the copy is long. */
.rail-image.front .mock-card,
.rail-image .mock-card {
  aspect-ratio: auto;
  height: auto;
  min-height: 100%;
  overflow: hidden;          /* band now stays inside the rounded corners */
}

/* Two lines is fine. Chopped words are not. */
.rail-image .mock-card-label {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.25;
  hyphens: none;
  text-wrap: balance;        /* split "Fig 1 — The Pause / That Never Varies" evenly */
}

/* Back cards: the band is decoration at this size, so keep it calm rather
   than letting a half-read headline compete with the card in front. */
.rail-image:not(.front) .mock-card-label {
  opacity: .75;
}

/* The band is meant to bleed edge to edge. Its negative margin was -1px,
   which only ever cancelled the border — with nowrap the text overflowed and
   made it *look* full width. Now that it wraps, pull it back by the card's
   actual padding so the band spans the card properly. */
.rail-image .mock-card { padding: 0 0 1.25rem; }
.rail-image .mock-card-label { margin: 0 0 .9rem; padding: .55rem 1.15rem; }
.rail-image .rail-explain,
.rail-image .mock-card--quote > :not(.mock-card-label) { padding-left: 1.15rem; padding-right: 1.15rem; }
.rail-image.front .mock-card::after { margin-left: 1.15rem; margin-right: 1.15rem; }

/* Back cards read as blank sheets in a stack. Showing a sliver of a dark
   headline behind the front card looks like a rendering fault, not a photo
   pile — and half a title is worse than no title. The band keeps its height
   so the cards still look like cards. */
.rail-image:not(.front) .mock-card-label {
  background: var(--stone);
  color: transparent;
  opacity: .45;
}

/* ==========================================================================
   Rail figure cards — the label band comes off, 28 Aug 2026
   ==========================================================================
   Cam, on seeing the Matt build: the dark band was decided against. It sits
   at the top running off the card, and on the back cards its grey stand-in
   reads as a rendering fault rather than a blank sheet.

   The label returns to plain uppercase type over a hairline, which is the
   treatment the base .mock-card-label rule had before 14 Aug. Back cards
   carry no label mark at all, but keep its height so the stack still reads
   as three sheets of paper.

   Revert: delete this block. A copy of the file as it stood before this
   change is in _ARCHIVE as styles-BEFORE-label-band-removal-2026-08-28.css.
   ========================================================================== */

.rail-image .mock-card-label {
  background: none;
  color: var(--ink);
  opacity: .72;
  font-weight: 700;
  text-align: left;
  margin: 0 1.15rem .9rem;
  padding: 1.35rem 0 .6rem;
  border-bottom: 1px solid var(--stone);
}

.rail-image:not(.front) .mock-card-label {
  background: none;
  color: transparent;
  border-bottom-color: transparent;
  opacity: 0;
}

/* ==========================================================================
   Carry-forward quotes — module two, LinkedIn overlay, 28 Aug 2026
   ==========================================================================
   These lines are what the resume said, carried into the LinkedIn panel so
   the learner can hold the two versions of the career side by side.

   They were originally built from .resume-tracker's own classes, which was
   the error: a dashed pill is this course's "not earned yet" affordance, so
   pre-filled pills read either as flags handed over free or as fields still
   waiting to be completed. A quote now differs from a flag on shape, case
   and alignment at once — no box, sentence case, left aligned, italic, in
   quotation marks.

   The dashed pill belongs to flags and to nothing else.

   Contrast on white: quote text is ink at .8 = 5.63:1, the label is ink at
   .78 = 5.32:1 (the same value .resume-tracker-label uses). Both clear AA.
   ========================================================================== */

.carry-quote {
  margin-top: 1.25rem;
  border-left: 2px solid var(--stone);
  padding-left: .95rem;
}

.carry-quote-label {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  opacity: .78;
  margin: 0 0 .45rem;
}

.carry-quote-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.carry-quote-list li {
  font-style: italic;
  font-size: .9rem;
  line-height: 1.55;
  opacity: .8;
  margin-bottom: .25rem;
}

.carry-quote-list li:last-child { margin-bottom: 0; }

/* ---- 18 Sept 2026: shared mid width, boxed guidance section, numbered list --
   Cam's pass on the live pages: the Module Three checklist read as a second
   card next to "Five things to listen for on camera". It is now a page
   section boxed in Dexcom green, on a width shared with that card (64rem,
   an inch inside the 76rem wide container). Kristy's wording is untouched.
   Text colour uses Contrast Green (--flag-green, 4.8:1 on white); the bright
   Dexcom Green stays on borders and rules, where 3:1 is the bar.
   -------------------------------------------------------------------------- */
.column--mid { width: 100%; max-width: 64rem; margin-left: auto; margin-right: auto; }

/* Numbered steps, Dexcom green discs */
.numbered-list { list-style: none; margin: 1.5rem 0 1.25rem; padding: 0; counter-reset: nstep; }
.numbered-list li {
  counter-increment: nstep; position: relative; padding-left: 3rem;
  margin: 0 0 1.35rem; line-height: 1.55;
}
.numbered-list li::before {
  content: counter(nstep);
  position: absolute; left: 0; top: -0.1em;
  width: 1.9rem; height: 1.9rem; border-radius: 50%;
  background: var(--flag-green); color: var(--white);
  font-family: var(--font-mono); font-size: .85rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* Guidance section, boxed in Dexcom green */
.guidance { margin: 2.5rem auto 1rem; text-align: left; }
.guidance-box {
  border: 1px solid var(--brand-green);
  border-left: 5px solid var(--brand-green);
  border-radius: 0 10px 10px 0;
  background: rgba(48, 171, 13, 0.04);
  padding: 2rem 2.25rem 2.25rem;
}
.guidance-title {
  font-family: var(--font-display); font-weight: 400; font-size: clamp(1.6rem, 3.2vw, 2.3rem);
  line-height: 1.15; margin: 0 0 1rem; color: var(--ink);
}
.guidance-intro { font-size: 1.05rem; line-height: 1.6; margin: 0 0 1.75rem; max-width: 46rem; }
.guidance-block { border-top: 1px solid var(--brand-green); padding: 1.5rem 0 1.3rem; }
.guidance-lead {
  font-family: var(--font-display); font-size: 1.15rem; letter-spacing: .01em;
  font-weight: 700; margin: 0 0 1.1rem; color: var(--flag-green); line-height: 1.3;
}
.guidance-list { display: grid; grid-template-columns: 17rem minmax(0, 1fr); column-gap: 2.5rem; row-gap: 1rem; margin: 0; }
.guidance-list dt { font-weight: 700; margin: 0; }
.guidance-list dd { margin: 0; line-height: 1.55; }
.guidance-flags { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem 2.5rem; margin: 0; padding-left: 1.2rem; }
.guidance-flags li::marker { color: var(--brand-green); }
.guidance-report {
  border-top: 1px solid var(--brand-green); margin: 1.5rem 0 0; padding: 1.4rem 0 0;
  font-size: 1.05rem; line-height: 1.6;
}
@media (max-width: 900px) {
  .guidance-box { padding: 1.5rem 1.25rem; }
  .guidance-list { grid-template-columns: 1fr; row-gap: .35rem; }
  .guidance-list dd { margin-bottom: .9rem; }
  .guidance-flags { grid-template-columns: 1fr; }
}

.numbered-list li:last-child { margin-bottom: 0; }

/* Video card: a still from the interview itself, in place of the hatched placeholder. */
.mock-video-still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.mock-video-dot { z-index: 2; box-shadow: 0 0 0 2px rgba(255,255,255,.85); }


/* ===== MOCKUP D, 20 Sept ===================================================
   The wrap layout is opt-in (.split--wrap), so Module Four keeps the layout it
   has always had. Modules One and Three carry the class.
   ------------------------------------------------------------------------ */
.split--wrap {
  display: grid;
  grid-template-columns: 21rem minmax(0, 1fr);
  column-gap: 3.25rem;
  width: 100%;
  max-width: 64rem;
  margin: 0 auto;
  align-items: stretch;
}
.split--wrap .split-rail {
  position: static; height: auto; top: auto;
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 2.75rem; padding-block: 0;
}
.split--wrap .rail-stack { max-width: 19.5rem; margin: 0; }
.split--wrap .split-copy { grid-column: 2; grid-row: 1; min-width: 0; }
.split--wrap .split-copy .prose { max-width: none; }
.split--wrap .prose-below { grid-column: 1 / -1; grid-row: 2; margin-top: 0.25rem; max-width: none; }

/* Air under the chapter opener, and a hint line that can actually be read. */
.chapter-opener { margin-bottom: 2.25rem; }
.chapter-hint { font-size: 0.95rem; letter-spacing: 0.02em; opacity: 0.82; margin-top: 1rem; }

/* Room under the lead note card before the reading starts. */
.card-lead .note-card { margin-top: 0.75rem; margin-bottom: 2.5rem; }

/* --- The video block -------------------------------------------------------
   Centred container, text left-aligned inside it, measure set so the three
   lines balance rather than running two long and one short. The card itself is
   now video-shaped: 16:9 rather than the portrait document proportion the
   résumé and LinkedIn cards use. */
.video-lede { width: 100%; max-width: 64rem; margin: 0 auto; }
.video-lede .cluster-intro {
  max-width: 54rem;
  margin: 0 auto 2.5rem;
  text-align: left;
  text-wrap: balance;
}
.video-lede .photo-cluster { margin: 0; }
.video-lede .cluster-caption {
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  opacity: 0.85;
  text-align: left;
  max-width: 54rem;
  margin: 0 auto 1.25rem;
}
.video-lede .cluster-stage { min-height: 21.5rem; }
.video-lede .cluster-photo { width: 24rem; height: auto; }
.video-lede .mock-video { flex: none; aspect-ratio: 16 / 9; width: 100%; }
.video-lede .mock-card { height: auto; justify-content: flex-start; gap: 0.9rem; padding: 1.5rem; }

@media (max-width: 860px) {
  .split--wrap { grid-template-columns: 1fr; }
  .split--wrap .split-rail { grid-column: 1; grid-row: 1; max-width: 22rem; margin: 0 auto 2rem; }
  .split--wrap .split-copy { grid-column: 1; grid-row: 2; }
  .split--wrap .prose-below { grid-column: 1; grid-row: 3; margin-top: 1.75rem; }
  .video-lede .cluster-photo { width: 18rem; height: 13rem; }
}


/* ===== MOCKUP G, 20 Sept: the same width system across the other pages ===== */

/* Module One / Three: pull the wide paragraphs up a quarter inch. */
.split--wrap .prose-below { margin-top: -1.5rem; }

/* --- Cover: the two opening paragraphs get the wider measure; everything
   else on the page keeps the width it has. --------------------------------- */
.cover .column { max-width: 64rem; }
.cover-description { max-width: 54rem; }
.cover .role-select,
.cover .expect-card,
.cover .cover-audience { max-width: 44rem; margin-left: auto; margin-right: auto; }

/* --- Module Two ----------------------------------------------------------- */
/* The opening paragraph is a lede, not a hint line: body face, readable size,
   left-aligned in a centred container. */
.chapter-hint--keep {
  font-family: var(--font-body);
  font-size: 1.15rem;
  line-height: 1.65;
  letter-spacing: 0;
  opacity: 1;
  text-transform: none;
  max-width: 64rem;
  margin: 1.5rem auto 0;
  padding-right: 10rem;
  text-align: left;
  text-wrap: pretty;
}
/* Figure row on the shared width, text left-aligned like every other note. */
.fig-row { max-width: 64rem; margin-left: auto; margin-right: auto; }
.fig-row .mock-card--quote { align-items: flex-start; text-align: left; }
.fig-row .mock-card-label { align-self: flex-start; }

/* The instruction above the documents, and the figure caption, share the
   text block's width and left edge. */
.cluster-intro { max-width: 64rem; margin-left: auto; margin-right: auto; padding-right: 10rem; text-align: left; text-wrap: pretty; }
.photo-cluster .cluster-caption { max-width: 64rem; margin-left: auto; margin-right: auto; text-align: left; }
.cluster-stage { max-width: 64rem; }

/* --- The completion box, in the same language as the Dexcom checklist ------ */
.module-complete-banner,
.complete-card {
  max-width: 64rem;
  margin-left: auto; margin-right: auto;
  border: 1px solid var(--brand-green);
  border-left: 5px solid var(--brand-green);
  border-radius: 0 10px 10px 0;
  background: rgba(48, 171, 13, 0.04);
  text-align: left;
  padding: 1.75rem 2rem;
}
.module-complete-msg { line-height: 1.6; max-width: 54rem; text-wrap: pretty; }
.complete-line { text-align: left; max-width: 54rem; text-wrap: pretty; }

/* --- Wrap-up: the same widths as everywhere else --------------------------- */
.page.cover .note-card { max-width: 64rem; margin-left: auto; margin-right: auto; }
.cover-subtitle { max-width: 54rem; margin-left: auto; margin-right: auto; }
.page.cover .cover-description { max-width: 64rem; padding-right: 10rem; }

@media (max-width: 900px) {
  .chapter-hint--keep, .cluster-intro, .page.cover .cover-description { padding-right: 0; }
}


/* --- 21 Sept ------------------------------------------------------------- */
/* Module Two: drop the three documents clear of the Fig 4 caption and sit them
   evenly between it and the completion box. */
.photo-cluster .cluster-stage { margin-top: 6.5rem; margin-bottom: 1rem; min-height: 20rem; }

/* Wrap-up: the completion line is centred in its box. */
.complete-card { text-align: center; }
.complete-card .complete-line { text-align: center; max-width: 44rem; margin-left: auto; margin-right: auto; }

/* --- 21 Sept, contrast fixes -----------------------------------------------
   The eyebrow used bright Dexcom Green at 13.6px, which measures 3.0:1 on
   white and fails AA for text that size. Contrast Green is 4.8:1 and is what
   the rest of the small green text already uses. The dimmed figure labels on
   the back cards sat at 4.33:1; nudged to clear 4.5:1. */
.eyebrow { color: var(--flag-green); }
.rail-image .mock-card-label { opacity: 0.86; }
.cluster-photo .mock-card-label { opacity: 0.86; }


/* --- 21 Sept: cover and wrap-up, symmetry -----------------------------------
   The paragraphs on these two pages were capped at 54rem inside a 64rem box
   with the spare 10rem left on the right, so their left edge lined up with the
   cards. On a page whose title is centred that reads as a lopsided margin, and
   it is what made the cover look like an inch on the left and over two on the
   right. Here the block is centred instead: equal space both sides. */
.page.cover .cover-description { max-width: 54rem; margin-left: auto; margin-right: auto; padding-right: 0; }

/* Wrap-up: the lede keeps its centred box but reads left, and a green rule
   separates it from "Escalate." above. */
.page.cover .wrap-lede {
  max-width: 54rem;
  margin: 0 auto;
  text-align: left;
  border-top: 1px solid var(--flag-green);
  padding-top: 2rem;
  margin-top: 2.5rem;
  margin-bottom: 2.25rem;
}

/* ===== 21 Sept: Dexcom type floor + Dexcom's 48px target bar ===============
   Dexcom Brand Standards (Brand Central, captured 6 Aug) sets body copy at
   11pt/15pt minimum, which the same document translates as 15–16px on screen,
   and sets its own click-target bar at 48px, stricter than WCAG's 24px.
   Floor applied here: course text 16px, labels and captions 14px. The chrome
   inside the simulated documents (stamps, badges, card labels) is exempt: it
   is a depiction of a résumé, a LinkedIn profile and an email, not course
   text, and sizing it up stops it reading as what it imitates.
   ------------------------------------------------------------------------ */

/* Course text to 16px */
.rail-explain { font-size: 1rem; line-height: 1.6; }
.role-desc { font-size: 1rem; }
.decision-prompt { font-size: 1rem; }
.cover-audience { font-size: 1rem; }
.cluster-caption { font-size: 0.95rem; }

/* Labels and captions to 14px */
.eyebrow { font-size: 0.875rem; }
.expect-card-eyebrow { font-size: 0.875rem; }
.role-tag { font-size: 0.875rem; }
.role-go { font-size: 0.875rem; }
.module-complete-cta { font-size: 0.875rem; }
.feedback-eyebrow { font-size: 0.875rem; }
.mock-card-label { font-size: 0.875rem; }

/* Dexcom's 48px targets. Inline highlights inside a sentence are a WCAG
   exception and stay as they are. */
.page-nav a,
.module-complete-cta,
.role-go,
.topbar-toc {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.topbar-toc { min-width: 48px; }
.page-nav a { padding-inline: 0.75rem; }

/* Cover: the role choice reads as its own step, not the next line of the
   paragraph above it. */
.cover .cover-audience { margin-top: 3.5rem; }
.cover .role-select { margin-top: 1.25rem; }

/* Wrap-up: the completion box sits to its content rather than running the
   full width. */
.complete-card {
  width: fit-content;
  max-width: 44rem;
  margin-left: auto; margin-right: auto;
  padding: 2rem 3rem;
}
.cover-audience.cover-audience--muted { font-size: 1rem; }
.page-nav a { font-size: 0.875rem; }

.cover .cover-audience--muted { font-size: 1rem; }


/* ===== 21 Sept, second pass ============================================== */

/* Completion boxes: one outline all the way round, rounded, no accent bar,
   sized to their contents rather than spanning the column. */
.module-complete-banner,
.complete-card {
  border: 1px solid var(--brand-green);
  border-radius: 10px;
  width: fit-content;
  max-width: 44rem;
  margin-left: auto; margin-right: auto;
  padding: 2rem 2.5rem;
  background: rgba(48, 171, 13, 0.04);
}
.module-complete-banner { text-align: left; }

/* Module Three: the video card sits closer to its caption and clear of the
   box below it. */
.video-lede .cluster-stage { margin-top: 2rem; margin-bottom: 2.5rem; }

/* Wrap-up: equal air above and below the green rule, and the card drops away
   from the paragraph above it. */
.page.cover .wrap-lede { margin-top: 2.5rem; padding-top: 2.5rem; }

/* Cover: two green rules break the page into its three steps — read this,
   choose your role, here is what to expect. */
.cover .cover-audience {
  border-top: 1px solid var(--flag-green);
  padding-top: 2rem;
  margin-top: 3rem;
  max-width: 54rem;
  margin-left: auto; margin-right: auto;
}
.cover .cover-audience--muted {
  border-top: 0;
  border-bottom: 1px solid var(--flag-green);
  margin-top: 2.25rem;
  padding-top: 0;
  padding-bottom: 2rem;
  display: flex; align-items: center; justify-content: center; gap: .55rem;
}
.cover .cover-audience--muted::before {
  content: "";
  width: 1.05rem; height: 1.05rem; flex: none;
  background: no-repeat center/contain url('data:image/svg+xml;utf8,\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23137D00" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>');
}


/* ===== 21 Sept, third pass =============================================== */

/* Bullets in the note cards get the same air as the numbered list in
   Module Three, and a narrower measure so the lines stop orphaning. */
.note-card ul li,
.note-card ol li { margin-bottom: 1rem; line-height: 1.6; text-wrap: pretty; }
.note-card ul li:last-child,
.note-card ol li:last-child { margin-bottom: 0; }
.page.cover .note-card { max-width: 54rem; }

/* Where a page ends in a completion box, that box carries the real call to
   action. The forward link underneath is a way back to the route, not a
   second button, so it reads as text like the one beside it. */
main:has(.module-complete-banner) .page-nav a:last-child {
  background: none;
  color: var(--ink);
  padding: 0.5rem 0.25rem;
  border-radius: 0;
}
main:has(.module-complete-banner) .page-nav a:last-child:hover {
  background: none;
  color: var(--peach);
}


/* ===== 21 Sept, fourth pass ============================================= */

/* Cover: the banded middle — choose your role, the two cards, the running
   time — sits with the same air above the top rule as below the bottom one.
   The top figure is 6px short of the bottom one because the paragraph above
   carries half a line of leading under its last line and the card below
   starts at a hard border. */
.cover .cover-audience { margin-top: 4.5rem; }
.cover .expect-card { margin-top: 2.64rem !important; }

/* ===== 21 Sept, fifth pass — one line colour ============================= */

/* Every horizontal divider in the course now reads in Contrast Green, the
   same rule the cover and the wrap-up use. Dividers inside the mock
   documents stay neutral: those lines belong to Alex's resume, LinkedIn
   page and email, not to Dexcom's course. */
.rule { border-top-color: var(--flag-green); }
.mock-card .rule,
.resume-doc .rule,
.linkedin-doc .rule,
.email-doc .rule { border-top-color: var(--ink); }

/* The green boxes and their rules move off bright Dexcom Green, which is a
   brand-marks-only colour at 3.02:1, and onto Contrast Green with the rest. */
.guidance-box { border-color: var(--flag-green); }
.guidance-block,
.guidance-report { border-top-color: var(--flag-green); }
.guidance-flags li::marker { color: var(--flag-green); }
.module-complete-banner,
.complete-card { border-color: var(--flag-green); }

/* The one piece of course instruction sitting inside the mock artwork —
   the hint on the front card — comes up to the label floor. */
.rail-image.front .mock-card::after { font-size: 0.875rem; }

/* ===== 21 Sept, sixth pass — Module Four joins the wrap layout ========== */

/* Module Four now uses the same three-part shape as One and Three: the lead
   card and the closing question sit on the shared 64rem width, the first
   stretch of reading runs beside the figure cards, and the rest wraps
   underneath at full width. */
.decision-block--mid { max-width: none; margin-inline: auto; }
.decision-block--mid .decision-prompt { text-wrap: balance; }
.decision-block--mid .feedback-body { max-width: none; }

/* ===== 21 Sept, seventh pass — the open document ======================== */

/* The document sheet had no padding of its own, so Alex's name and every
   line under it sat hard against the edge of the Bone panel. The sheet now
   carries its own margin and the panel around it gives a little back, so
   the reading measure stays where it was. */
.resume-doc { padding: 2rem 2.25rem; border-radius: 4px; }
.resume-body { padding: 1.5rem 1.75rem 2.5rem; }

/* The found-flag highlight was dark enough that the sentence under it sat
   at 3.57:1 — under the 4.5:1 bar. Same green, less of it: the mark still
   reads as a highlighter stroke and the text under it clears the bar. */
.quiz-choice.found,
.quiz-choice.found:hover {
  background-image: linear-gradient(
    100deg,
    rgba(var(--accent-rgb), 0.04) 0%,
    rgba(var(--accent-rgb), 0.32) 12%,
    rgba(var(--accent-rgb), 0.35) 55%,
    rgba(var(--accent-rgb), 0.29) 88%,
    rgba(var(--accent-rgb), 0.05) 100%
  );
}

/* The video debrief box comes to the same 1px outline every other
   completion box in the course uses. */
.vi-consequence { border-width: 1px; }

/* ===== MOCKUP ONLY — Module Two's figure row ============================ */
/* These three cards have never carried an accent. A green cap on top ties
   them to the note card above without giving them the left bar the info
   boxes use. Nothing else changes. */
.fig-row .mock-card {
  border-top: 4px solid var(--peach);
  border-radius: 6px;
}

/* ===== 21 Sept, Astra's narrow-width findings =========================== */

/* Astra, 18 Sept: the figure cards landed on top of the reading on a phone.
   Cause: .split-rail centres its children, and every card inside .rail-stack
   is absolutely positioned, so the stack collapsed to zero width and the
   cards rendered out of a box with no size. Give the stack its own width in
   the collapsed layout and the cards sit in their own space again. */
@media (max-width: 860px) {
  .split--wrap .split-rail { align-items: stretch; }
  .split--wrap .rail-stack {
    width: 100%;
    max-width: 20rem;
    margin-left: auto;
    margin-right: auto;
  }
}

/* A long attachment filename in Alex's email ran off the edge at phone
   width. Let it break rather than push the sheet wider. */
.resume-doc .email-field,
.resume-doc .email-attachment,
.resume-overlay .email-field {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* The rail was still collapsing: `margin: 0 auto` on a grid item overrides
   the default stretch and sizes it to its content, and its content is all
   absolutely positioned — so it measured zero. Give it a real width. */
@media (max-width: 860px) {
  .split--wrap .split-rail {
    width: min(20rem, 100%);
    max-width: none;
    height: auto;
    justify-self: center;
  }
  .split--wrap .rail-stack { width: 100%; max-width: none; }
}

/* Below 360px the document scatter and the figure stack both need to come
   down a size: the cards were wider than the screen, and the stack's box
   ended above the cards inside it, so the lowest one met the first
   paragraph. */
@media (max-width: 380px) {
  .split--wrap .split-rail { margin-bottom: 3.5rem; }
  .photo-cluster .cluster-photo { width: 9.5rem; height: 12.5rem; }
  .video-lede .cluster-photo { width: 13rem; height: 9.4rem; }
  .cluster-stage { max-width: 100%; }
}

@media (max-width: 340px) {
  .photo-cluster .cluster-photo { width: 8.5rem; height: 11rem; }
}

/* ===== 22 Sept — click targets inside the overlays ======================= */
/* Dexcom's own bar is 48px on every control (SOURCE — Dexcom Brand
   Standards). The page controls already meet it; these are the ones inside
   the document, video and contents overlays that did not: Close buttons
   (35px), the flag chips (34px), the video chapter tabs (14px), "Start the
   call" and the score-panel buttons (34px), the contents Close (28px) and
   the course title in the top bar (26px). Same look, taller hit area. */
.resume-close,
.toc-close,
.quiz-chip,
.resume-results-continue,
.resume-results-retry,
.vi-chapter,
.topbar-brand {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
}
.vi-chapter { padding: 0.9rem 0.2rem; margin: 0; cursor: default; }
.vi-chapters { margin-top: 0.25rem; }
.vi-chapter.vi-chapter--available, .vi-chapter[role="button"] { cursor: pointer; }
.topbar-brand { min-height: 48px; }

/* ===== 22 Sept — Astra's second technical pass ========================== */

/* Astra 4: the email's attachment line is `.resume-footer.quiz-choice`, not
   the classes the earlier rule named. Let every line inside a document sheet
   break rather than push the sheet wider. */
.resume-doc,
.resume-doc * { overflow-wrap: anywhere; }

/* Astra 3: the top bar's right-hand group overflowed the viewport below
   about 380px, taking the contents button with it. Let the bar shrink its
   gaps and hide the decorative separators first; the button stays. */
@media (max-width: 480px) {
  .topbar { padding: 0 0.75rem; }
  .topbar-left, .topbar-right { gap: 0.5rem; min-width: 0; }
  .topbar-sep { display: none; }
  .topbar-brand { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  .topbar-toc { flex: none; }
}
@media (max-width: 380px) {
  .topbar-label { display: none; }
  .topbar-brand { font-size: 0.72rem; letter-spacing: 0.06em; }
}
/* The open contents menu: long titles wrap rather than clip. */
.toc-list a, .toc-list .toc-disabled, .toc-list .toc-current { flex-wrap: wrap; }
.toc-title { min-width: 0; overflow-wrap: anywhere; }

/* Astra 5: the video chapter row wraps when it does not fit. */
.vi-chapters { flex-wrap: wrap; row-gap: 0.25rem; }

/* Astra 8: a little more room under the figure stack once it sits above the
   reading, so the lowest card and the first paragraph never touch. */
@media (max-width: 860px) {
  .split--wrap .split-rail { margin-bottom: 2.75rem; }
}
@media (max-width: 380px) {
  .split--wrap .split-rail { margin-bottom: 4rem; }
}

/* Astra 9: the figure-card headings are course text, not document artwork,
   so they come up to the 14px label floor like every other label. */
.rail-image .mock-card-label { font-size: 0.875rem; }
.fig-row .mock-card-label { font-size: 0.875rem; }

/* Astra 1: the newly focusable lines and options show a visible focus ring. */
.quiz-choice:focus-visible,
.decision-option:focus-visible {
  outline: 2px solid var(--flag-green);
  outline-offset: 2px;
}

/* The left group must be the one that gives way: the brand shrinks and
   truncates, the right group keeps its natural width, the button stays on. */
@media (max-width: 480px) {
  .topbar-left { flex: 1 1 auto; min-width: 0; overflow: hidden; }
  .topbar-right { flex: 0 0 auto; }
  .topbar-brand { display: block; max-width: 100%; }
}

/* The flaggable document lines are the course's main activity, so they get
   the 48px hit height too: a little more air between lines, nothing else. */
.resume-doc .quiz-choice { min-height: 48px; box-sizing: border-box; padding-top: 0.45rem; padding-bottom: 0.45rem; }


/* ===== 22 Sept — Astra's third technical pass ============================ */

/* Astra 2: the chapter tabs had negative vertical margins so their 48px hit
   areas did not add height; once the row wrapped, the rows sat on top of
   each other. No negative margins now; the row is as tall as its tabs. */

/* Astra 4: item 14 says every label, heading and button is at least 14px.
   Make it true. The top bar, the chapter tabs, Close, and the narrator card
   were 12.6–13.6px. */
.topbar { font-size: 0.875rem; }
.vi-chapter { font-size: 0.875rem; }
.resume-close, .toc-close { font-size: 0.875rem; }
.vi-narrator-card { font-size: 0.875rem; }
@media (max-width: 380px) {
  .topbar-brand { font-size: 0.875rem; letter-spacing: 0.04em; }
}

/* Astra 4, the rest of it: every remaining piece of course instruction text
   under 14px comes up to the floor — the contents menu labels, the
   instruction lines and counters inside the documents and the video, the
   debrief heading and hint, and the secondary retry button. Kristy's four
   debrief paragraphs were 13.6px, under Dexcom's body floor; they are 16px. */
.toc-label,
.resume-intro, .resume-intro-detail,
.fill-pill-text, .fill-pill-text--invert,
.resume-attempt-counter, .resume-tracker-label,
.quiz-categorize-prompt,
.vi-consequence-label, .vi-hint,
.resume-results-retry--secondary, .resume-results-retry { font-size: 0.875rem; }
.vi-consequence-note { font-size: 1rem; line-height: 1.6; }

/* ===== 22 Sept — Astra's fourth technical pass =========================== */

/* Astra 1: with the reading stacked under the figure cards, the card that is
   brought forward grows to 84% and un-rotates, and at 320px that pushed it
   past the right edge and down into the first paragraph. In the collapsed
   layout the front card keeps the stack's width and the stack leaves room
   for the lowest card at its front size. */
@media (max-width: 860px) {
  .split--wrap .rail-image.front { width: 74% !important; transform: rotate(0deg) !important; }
  .split--wrap .rail-stack { aspect-ratio: 3 / 4.6; overflow: visible; }
  .split--wrap .split-rail { margin-bottom: 3.5rem; }
}
@media (max-width: 380px) {
  .split--wrap .rail-stack { aspect-ratio: 3 / 5.6; }
  .split--wrap .split-rail { margin-bottom: 5rem; }
}

/* Astra 4: the document toolbar's Close ran past the edge at 320px. */
@media (max-width: 400px) {
  .resume-toolbar { gap: 0.75rem; flex-wrap: wrap; }
  .resume-toolbar > * { min-width: 0; max-width: 100%; }
  .resume-close { padding-left: 0.6rem; padding-right: 0.6rem; }
  .resume-overlay .resume-body, .resume-overlay .resume-header { box-sizing: border-box; max-width: 100vw; }
}

/* Astra 3: the remaining interface text under 14px — the filled flag
   tracker, the "check the profile against the résumé" note, the score line,
   the Continue buttons, and "Click to Inspect" on the document cards. */
.resume-tracker-slot, .carry-quote-label, .resume-results-score,
.resume-results-continue, .mock-badge, .mock-badge--hint { font-size: 0.875rem; }

/* ===== 22 Sept — Astra's fifth technical pass ============================ */

/* The play/pause control stays visible while it has keyboard focus. */
.vi-image-slot:has([data-vi-play]:focus-visible) .vi-play-overlay,
.vi-play-overlay:focus-visible { opacity: 1 !important; }

/* The last interface text under 14px, generated text included: captions,
   the caller's name, the call question, the A/B/C letters, the principle
   label and its line, the numbered-list discs, the Correct/Incorrect
   decision labels, and the locked-navigation reasons. */
.vi-caption-bar, .vi-caller-name, .vi-question, .vi-question-detail,
.vi-choice-letter, .vi-principle-label, .vi-principle-sub,
.numbered-list li::before,
.decision-option.correct::after, .decision-option.incorrect::after,
.page-nav a.nav-locked::after, .page-nav a[aria-disabled="true"]::after { font-size: 0.875rem; }
.vi-caption-bar { font-size: 1rem; }

/* =====================================================================
   Round 4 split pop-ups (25 Sept 2026). Cam chose option 2 of three after
   Jenna Haney's (23 Sept) and Eitienne Hitchcock's (24-25 Sept) feedback on
   the pop-ups: on screens at least 960px wide and 500px tall, the documents
   and the video fill most of the screen and split in two, so the line, the
   choice and the feedback, or the video and its question, are on screen
   together. Kept in step with SPLIT_QUERY in shared.js.
   ===================================================================== */

/* All widths. In a document, the side panel holds what the Round 3 header
   held below the instructions (the counter and Flags Collected). On narrow
   screens it is that same band, under the header; the feedback for each
   flag stays under its line and does not repeat the line. */
.resume-panel--split > .resume-header { order: 0; border-bottom: 0; padding-bottom: 0.25rem; }
.resume-panel--split > .resume-side {
  order: 1;
  flex: 0 0 auto;
  padding: 0.75rem 2.5rem 1rem;
  border-bottom: 1px solid var(--ink);
  background: var(--paper);
}
.resume-panel--split > .resume-body { order: 2; }
.resume-body .quiz-entry-quote { display: none; }
.quiz-entries:empty { display: none; }
/* The four category buttons were 12.5px in Round 3, inside the document, where
   the size check exempts the mock-document artwork; they are buttons, so they
   take the 14px label floor like every other control (found 25 Sept). */
.quiz-chip { font-size: 0.875rem; }
@media (max-width: 640px) {
  .resume-panel--split > .resume-side { padding: 0.75rem 1.5rem 1rem; }
}

@media (min-width: 960px) and (min-height: 500px) {
  .resume-overlay { padding: 1rem 1.25rem; }
  .resume-panel--split, .vi-panel {
    width: min(96vw, 84rem);
    height: min(92vh, 62rem);
    max-height: none;
  }

  /* Documents: header across the top; document left; side panel right. */
  .resume-panel--split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(19rem, 24rem);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "head head" "body side";
  }
  .resume-panel--split > .resume-header {
    grid-area: head;
    padding: 1.1rem 2.5rem 1rem;
    border-bottom: 1px solid var(--ink);
  }
  .resume-panel--split > .resume-body { grid-area: body; min-height: 0; overflow-y: auto; }
  .resume-panel--split > .resume-side {
    grid-area: side;
    min-height: 0;
    overflow-y: auto;
    border-bottom: 0;
    border-left: 1px solid var(--ink);
    padding: 1.25rem 1.5rem 2rem;
  }
  /* One slot per row: the two-word labels are joined against orphans, so
     "Identity Inconsistency" cannot wrap and needs the full width. */
  .resume-side .resume-tracker-list { display: grid; grid-template-columns: 1fr; gap: 0.35rem; }
  .resume-side .resume-tracker-slot {
    min-width: 0;
    white-space: normal;
    line-height: 1.25;
    letter-spacing: 0.02em;
    padding: 0.4rem 0.4rem;
  }
  .quiz-entries { margin-top: 1.25rem; }
  .quiz-entry {
    border-top: 1px solid rgba(var(--ink-rgb), 0.2);
    margin-top: 1.25rem;
    padding-top: 1.25rem;
  }
  .quiz-entry:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
  .quiz-entry-quote { font-size: 1rem; font-style: italic; line-height: 1.45; margin: 0 0 0.75rem; }
  .resume-side .quiz-categorize { margin: 0; }
  .resume-side .quiz-chips { display: grid; grid-template-columns: 1fr 1fr; }
  .resume-side .quiz-chip { width: 100%; min-height: 48px; padding: 0.5rem; line-height: 1.2; }
  .resume-side .quiz-note { margin: 0.9rem 0 0; }
  .resume-side .resume-results { margin: 1.25rem 0 0; }

  /* The video: title, chapters and Close on one row; on the introduction and
     the call, the picture on the left and everything else on the right; on
     the three outcomes, the picture on the left of the outcome box. */
  .vi-panel { display: flex; flex-direction: column; }
  .vi-panel > .resume-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem 2rem;
    padding: 1rem 2.5rem 0.9rem;
  }
  .vi-panel > .resume-header > .resume-toolbar { display: contents; }
  .vi-panel > .resume-header > .resume-toolbar > div { order: 1; flex: 0 1 auto; }
  .vi-panel > .resume-header > .vi-chapters { order: 2; margin: 0; }
  .vi-panel > .resume-header > .resume-toolbar > .resume-close { order: 3; margin-left: auto; }
  .vi-panel > .resume-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
  .vi-screen.active[data-vi-screen="s0"],
  .vi-screen.active[data-vi-screen="s2"] {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(17rem, 1fr);
    column-gap: 2rem;
    align-items: start;
  }
  .vi-screen[data-vi-screen="s0"] > .vi-image-slot,
  .vi-screen[data-vi-screen="s2"] > .vi-image-slot { grid-column: 1; grid-row: 1 / span 8; margin-bottom: 0; }
  .vi-screen[data-vi-screen="s0"] > :not(.vi-image-slot),
  .vi-screen[data-vi-screen="s2"] > :not(.vi-image-slot) { grid-column: 2; }
  .vi-screen[data-vi-screen="s2"] .vi-question { margin-top: 0; }
  .vi-screen[data-vi-screen="s3a"] .vi-consequence,
  .vi-screen[data-vi-screen="s3b"] .vi-consequence,
  .vi-screen[data-vi-screen="s3c"] .vi-consequence {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(17rem, 1fr);
    column-gap: 2rem;
    align-items: start;
  }
  .vi-consequence > .vi-consequence-label { grid-column: 1 / -1; }
  .vi-consequence > .vi-image-slot { grid-column: 1; grid-row: 2 / span 6; margin-bottom: 0; }
  .vi-consequence > :not(.vi-image-slot):not(.vi-consequence-label) { grid-column: 2; }
}
/* On the narrower split screens (a landscape iPad, a small laptop window) the
   picture gives more room to the choices so all three stay on screen. */
@media (min-width: 960px) and (max-width: 1199px) and (min-height: 500px) {
  .vi-screen.active[data-vi-screen="s0"],
  .vi-screen.active[data-vi-screen="s2"],
  .vi-screen[data-vi-screen="s3a"] .vi-consequence,
  .vi-screen[data-vi-screen="s3b"] .vi-consequence,
  .vi-screen[data-vi-screen="s3c"] .vi-consequence { grid-template-columns: minmax(0, 1.1fr) minmax(17rem, 1fr); column-gap: 1.5rem; }
  .vi-panel > .resume-header, .resume-panel--split > .resume-header { padding-left: 2rem; padding-right: 2rem; }
  .vi-screen[data-vi-screen="s2"] .vi-choice { line-height: 1.4; padding: 0.6rem 0.9rem; }
  .vi-screen[data-vi-screen="s2"] .vi-caller-name { margin-bottom: 0.5rem; }
}

/* Round 4, step 3: fit a laptop. The newest entry does not repeat its line (it
   is highlighted beside it); earlier entries keep the quote so they say which
   line they belong to. The tracker slots are tighter. */
@media (min-width: 960px) and (min-height: 500px) {
  .quiz-entries > .quiz-entry:first-child .quiz-entry-quote { display: none; }
  .resume-side .resume-tracker { margin-bottom: 0; }
  .resume-side .resume-tracker-label { margin-bottom: 0.4rem; }
  .resume-side .resume-tracker-slot { padding-top: 0.3rem; padding-bottom: 0.3rem; }
  .resume-side .resume-progress-row { margin-bottom: 0.75rem; }
  .vi-consequence > .vi-principle { margin: 1rem 0; }
  .vi-consequence > .vi-actions { margin-top: 0.5rem; }
}

/* Round 4, step 5: the Found counter stays pinned at the top of the side panel
   when the panel scrolls, so progress is always in view. */
@media (min-width: 960px) and (min-height: 500px) {
  .resume-side .resume-progress-row {
    position: sticky;
    top: -1.25rem;
    z-index: 1;
    background: var(--paper);
    margin: -1.25rem -1.5rem 0.75rem;
    padding: 1.25rem 1.5rem 0.6rem;
  }
}

/* =====================================================================
   Round 4 build 20260926a (26 Sept 2026). Items 1-5 of the order of work
   in Cam's 25 Sept email, judged at Jenna Haney's screen: a 1920x1080
   Windows laptop at 150%, browser maximised, a 1280 x 599 window.
   ===================================================================== */

/* Wrong answers are red (Jenna and Eitienne). Plum stays for role titles,
   which used the same variable but are not a wrong answer.
   #A61B1B: white on it 7.52:1; as text on white 7.52:1. */
:root { --flag-red: #A61B1B; --role-title: #371B2C; }
.role-title { color: var(--role-title); }

/* Check and X, as Module Four already shows them (Eitienne). Generated text,
   hidden from screen readers where supported: the words already say it. */
.quiz-chip.correct::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; font-weight: 700; }
.quiz-chip.incorrect::before { content: "\2717\00a0"; content: "\2717\00a0" / ""; font-weight: 700; }
.resume-tracker-slot.filled.tracker-correct::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; }
.resume-tracker-slot.filled.tracker-incorrect::before { content: "\2717\00a0"; content: "\2717\00a0" / ""; }
.quiz-note-lead.correct::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; }
.quiz-note-lead.incorrect::before { content: "\2717\00a0"; content: "\2717\00a0" / ""; }
.quiz-note:has(> .quiz-note-lead)::before { content: none; }

/* The pop-up's border shows the latest answer (Eitienne). Drawn outside the
   panel's own edge, so it never crowds the text inside. */
.resume-panel.answer-correct { outline: 5px solid var(--flag-green); outline-offset: 0; }
.resume-panel.answer-incorrect { outline: 5px solid var(--flag-red); outline-offset: 0; }

/* The explanation after a flag was 14.4px, under Dexcom's 11pt body minimum
   (about 14.7px). */
.quiz-note { font-size: 0.9375rem; }

/* Space between an outlined line and its text (Cam, 25 Sept). */
.quiz-choice:focus, .quiz-choice:focus-visible { outline-offset: 5px; }

/* Short laptop screens (Jenna's is 599 tall). */
@media (min-width: 960px) and (min-height: 500px) and (max-height: 700px) {
  .resume-side .resume-tracker-list { grid-template-columns: 1fr 1fr; }
  .resume-side .resume-tracker-slot { white-space: normal; }
  .vi-screen.active[data-vi-screen="s2"],
  .vi-screen[data-vi-screen="s3a"] .vi-consequence,
  .vi-screen[data-vi-screen="s3b"] .vi-consequence,
  .vi-screen[data-vi-screen="s3c"] .vi-consequence { grid-template-columns: minmax(0, 1.05fr) minmax(17rem, 1fr); column-gap: 1.5rem; }
  .vi-screen[data-vi-screen="s2"] .vi-choice { line-height: 1.4; padding: 0.55rem 0.9rem; }
  .vi-screen[data-vi-screen="s2"] .vi-caller-name { margin-bottom: 0.4rem; }
  /* the debrief's caption box holds its space before the narration starts */
  .vi-caption-bar--static:empty { min-height: 0; border-width: 0; padding: 0; margin-bottom: 0.5rem; }
  /* the debrief's four paragraphs sit a little closer together */
  .vi-screen[data-vi-screen="s4"] .vi-consequence-note { margin-top: 0.5rem; margin-bottom: 0.5rem; padding-top: 0.5rem; }
}

/* =====================================================================
   Round 4 build 20260927a (27 Sept 2026). Cam, on the document pop-ups at
   Jenna's screen: no Found pill, "Attempt 1" on the Flags Collected line,
   and a cue when the right side has scrolled.
   ===================================================================== */
.side-more { display: none; }
@media (min-width: 960px) and (min-height: 500px) {
  .resume-panel--split > .resume-side { position: relative; }
  /* The Found pill goes; its words stay for screen readers. */
  .resume-side .resume-quiz-counter {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  /* "Attempt 1" sits at the right end of the Flags Collected line. */
  .resume-side .resume-progress-row {
    position: absolute; top: 1.25rem; right: 1.5rem;
    margin: 0; padding: 0; background: none; z-index: 1;
  }
  .resume-side .resume-tracker-label { padding-right: 7.5rem; }
  /* Scrolled cue: a fade and a round Contrast Green arrow button. Takes no
     room: its height is given back by the negative margin below it. */
  .side-more {
    display: flex; justify-content: center; align-items: flex-start;
    position: sticky; top: -1.25rem; z-index: 3;
    height: 3.4rem; margin: -1.25rem -1.5rem -2.15rem;
    background: linear-gradient(to bottom, var(--paper) 45%, rgba(255, 255, 255, 0));
    pointer-events: none; visibility: hidden; opacity: 0;
    transition: opacity 0.2s, visibility 0s linear 0.2s;
  }
  .resume-side.is-scrolled .side-more { visibility: visible; opacity: 1; transition: opacity 0.2s; }
  .side-up {
    pointer-events: auto; width: 48px; height: 48px; margin-top: 2px;
    padding: 0; border: 0; background: transparent; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
  }
  .side-up-circle {
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 50%;
    background: var(--flag-green); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  }
  .side-up:focus-visible { outline: 3px solid var(--ink); outline-offset: 0; border-radius: 50%; }
}

/* =====================================================================
   Round 4 build 20260929a (29 Sept 2026): the side panel shows only the
   flag just done; a click on a flagged line brings its explanation back.
   ===================================================================== */
.resume-side .quiz-entry--past { display: none; }
.quiz-choice.found { cursor: pointer; }

/* =====================================================================
   Round 4 build 20260929b (29 Sept 2026): results-only side panel, and the
   AI use disclaimer on the cover.
   ===================================================================== */
.resume-side.has-results .carry-quote { display: none; }
.resume-side.has-results .quiz-entries:not(:has(.quiz-entry:not(.quiz-entry--past))) { margin-top: 0; }
.resume-results-hint { display: none; }
.resume-side .resume-results-hint {
  display: block;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0.9rem 0 0;
}
.cover-ai-note {
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--mid);
  max-width: 44rem;
  margin: 1rem auto 0;
  text-align: center;
}
/* Short screens (Jenna's 1280 x 599): tighten the results box so the
   results and the review line fit without scrolling the side panel. */
@media (min-width: 960px) and (min-height: 500px) and (max-height: 700px) {
  .resume-side.has-results { padding-bottom: 0.75rem; }
  .resume-side .resume-results { padding: 0.85rem 1.1rem; margin-top: 1rem; }
  .resume-side .resume-results-msg { margin-bottom: 0.7rem; }
  .resume-side .resume-results-actions { gap: 0.5rem; }
  .resume-side .resume-results-hint { margin-top: 0.6rem; line-height: 1.35; }
}

/* =====================================================================
   Round 4 build 20260929c (29 Sept 2026): the AI use disclaimer sits at the
   very bottom of the cover, under What to Expect, with a small eye icon.
   ===================================================================== */
.cover > .cover-ai-note {
  flex-basis: 100%;
  grid-column: 1 / -1;
  width: 100%;
  max-width: 44rem;
  margin: 3rem auto 0;
  padding: 0 1rem;
  text-align: center;
}
.cover-ai-icon {
  display: inline-block;
  vertical-align: -4px;
  margin-right: 0.4rem;
  color: var(--flag-green);
}

/* =====================================================================
   Round 4 build 20261006a (6 Oct 2026): Mockup G and cover Mockup I5,
   built in as Cam approved them on screen (Decision Log D-168 to D-173).
   ===================================================================== */

/* ---- Document pop-ups: no black bar ---------------------------------- */
/* The instruction is plain bold text on one line; the four Flags Collected
   slots sit as bars under it (the words "Flags Collected" stay for screen
   readers); "Attempt 1" sits at the top of the side panel. */
.pop-hdr .resume-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 1rem; row-gap: 0.5rem; align-items: center; margin-bottom: 0; }
.pop-hdr .resume-toolbar > div:first-child { grid-column: 1; grid-row: 1; min-width: 0; }
.pop-hdr .resume-toolbar .resume-close { grid-column: 2; grid-row: 1; align-self: center; padding-top: 0.4rem; padding-bottom: 0.4rem; }
.pop-hdr .resume-intro { white-space: nowrap; background: none !important; color: var(--ink) !important; font-family: var(--font-body) !important; text-transform: none !important; letter-spacing: 0 !important; font-size: 1.08rem !important; font-weight: 600 !important; padding: 0 !important; line-height: 1.35 !important; }
@media (max-width: 900px) { .pop-hdr .resume-intro { white-space: normal; } }
.pop-hdr .hdr-flags { grid-column: 1 / -1; grid-row: 2; min-width: 0; }
.pop-hdr .hdr-flags .resume-tracker-label { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }
.pop-hdr .hdr-flags .resume-tracker-list { display: grid !important; grid-template-columns: repeat(4, minmax(0, 1fr)) !important; gap: 0.4rem !important; margin: 0 !important; padding: 0 !important; list-style: none; }
.pop-hdr .hdr-flags .resume-tracker-slot { min-width: 0 !important; white-space: nowrap !important; letter-spacing: 0 !important; padding: 0.3rem 0.3rem !important; margin: 0 !important; }
.pop-hdr .resume-header { padding-top: 0.8rem; padding-bottom: 0.7rem; }
.pop-hdr .resume-side > .resume-progress-row { position: static !important; display: flex !important; justify-content: flex-end; margin: -0.35rem 0 0.35rem; height: auto !important; }
.pop-hdr .resume-side .quiz-entries { margin-top: 0 !important; }
.pop-hdr .resume-side .carry-quote + .quiz-entries { margin-top: 1rem !important; }
.pop-hdr .resume-side .resume-results { margin-top: 0 !important; }

/* ---- Modules One, Three, Four: each figure and its text as a section --- */
.sec-chunks { max-width: 64rem; margin: 0 auto; }
.sec-chunk { display: flow-root; max-width: none !important; margin: 0 !important; }
.sec-chunk ul, .sec-chunk ol { display: flow-root; }
.sec-chunk > p:last-child, .sec-chunk > ul:last-child { margin-bottom: 0; }
.sec-divider { border: 0; border-top: 1px solid rgba(0,0,0,.18); margin: 2.5rem 0; height: 0; }
.sec-fig { width: 18.5rem; margin: 0.35rem 0 1.25rem; }
.sec-fig.left { float: left; clear: left; margin-right: 2.25rem; }
.sec-fig.right { float: right; clear: right; margin-left: 2.25rem; }
.sec-fig .rail-image { position: relative !important; left: auto !important; top: auto !important; width: auto !important; transform: none !important; opacity: 1 !important; visibility: visible !important; z-index: auto !important; cursor: default !important; }
.sec-fig .rail-image .mock-card { height: auto !important; min-height: 0 !important; }
.sec-fig .rail-image { background: none !important; box-shadow: none !important; height: auto !important; min-height: 0 !important; aspect-ratio: auto !important; padding: 0 !important; border: 0 !important; }
.sec-fig .rail-image .mock-card::after { content: none !important; display: none !important; }
@media (max-width: 720px) {
  .sec-fig, .sec-fig.left, .sec-fig.right { float: none; width: auto; margin: 0 0 1.25rem; }
}

/* ---- Module Two: Fig 1 to 3 as flip cards ------------------------------ */
.fig-row--flip { align-items: stretch; }
.flip { display: block; width: 100%; min-width: 0; padding: 0; border: 0; background: none; cursor: pointer; perspective: 1400px; text-align: left; font: inherit; color: inherit; transition: transform .3s ease; position: relative; z-index: 1; }
.flip[aria-pressed="true"] { z-index: 2; }
.flip:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }
.flip-inner { display: grid; grid-template-columns: minmax(0, 1fr); height: 100%; transition: transform .5s ease; transform-style: preserve-3d; }
.flip-face { grid-area: 1 / 1; min-width: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; margin: 0 !important; height: 100%; }
.flip-face.flip-back { transform: rotateY(180deg); }
.flip[aria-pressed="true"] .flip-back { box-shadow: 0 14px 34px rgba(0,0,0,.18); }
.flip-front { display: flex; flex-direction: column; }
.flip-front .flip-photo { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 4px; margin-bottom: 0.9rem; }
.flip-hint { font-family: var(--font-mono); font-size: 0.875rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--flag-green); margin-top: auto; padding-top: 0.8rem; }
/* once a card has finished turning, the 3D turn is dropped so its text is sharp */
.flip.settled .flip-inner { transform: none !important; transition: none !important; }
.flip.settled .flip-back { transform: none !important; }
.flip.settled .flip-front { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .flip, .flip-inner { transition: none; } }

/* ---- Cover: photo in the top-right corner, title on the left ------------ */
.cover { overflow-x: clip; }
.cover-hero { position: relative; width: 100vw; margin-left: calc(50% - 50vw); margin-top: -4rem; min-height: 27rem; padding-top: 6.5rem; margin-bottom: 2.25rem; }
.cover-hero-photo { position: absolute; right: 0; top: 0; width: 78vw; height: 33rem; pointer-events: none; user-select: none;
  -webkit-mask-image: linear-gradient(225deg, #000 0%, #000 22%, rgba(0,0,0,.55) 38%, rgba(0,0,0,.18) 52%, transparent 64%), linear-gradient(to bottom, #000 62%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(225deg, #000 0%, #000 22%, rgba(0,0,0,.55) 38%, rgba(0,0,0,.18) 52%, transparent 64%), linear-gradient(to bottom, #000 62%, transparent 100%);
  mask-composite: intersect; }
.cover-hero-photo img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 30% 30%; transform: scaleX(-1); }
.cover-hero-text { position: relative; z-index: 1; width: 100%; max-width: 54rem; margin: 0 auto; }
.cover-hero-text > * { max-width: 26rem; }
.cover-hero .eyebrow, .cover-hero .cover-title, .cover-hero .cover-subtitle { text-align: left !important; margin-left: 0 !important; margin-right: 0 !important; }
.cover-hero .cover-title { font-size: clamp(2.75rem, 6vw, 4.6rem); }
.cover-hero .cover-subtitle { margin-bottom: 0 !important; }
@media (max-width: 860px) {
  .cover-hero-text > * { max-width: none; }
  .cover-hero-photo { opacity: .25; width: 100%; }
}

/* ---- Cover: role cards (icon, role name as the title) ------------------- */
.cover .role-select { max-width: 54rem; }
.role-head { display: flex; align-items: center; gap: .8rem; }
.role-icon { flex: none; color: var(--flag-green, #137D00); }
.role-card .role-tag { font-size: 1.3rem; letter-spacing: .05em; line-height: 1.2; }
.role-card .role-title { font-size: 1.02rem; font-weight: 700; line-height: 1.35; }

/* ===== 20261007a (Astra R4-T2, R4-T5; Cam's pass, D-179) ===== */
/* R4-T5: the document instruction wraps whenever it cannot sit beside Close (it ran under Close and off the panel
   between about 900 and 1000px wide). Balanced over two lines. At 1280 x 599 it still fits on one line. */
.pop-hdr .resume-intro { white-space: normal !important; text-wrap: balance; }
/* R4-T2: the Flags Collected names were clipped and covered at 320 and 390px (four fixed columns, no wrapping).
   Below 960px (where the clipping happened; the two-column layout above it fits the names) names may wrap inside
   their slot, and below 600px the four slots sit two by two. At 1280 x 599 nothing changes. */
@media (max-width: 959px) { .pop-hdr .hdr-flags .resume-tracker-slot { white-space: normal !important; overflow-wrap: anywhere; text-align: center; line-height: 1.25; } }
@media (max-width: 600px) { .pop-hdr .hdr-flags .resume-tracker-list { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }

/* ===== 20261007b (Cam's pass, D-184) ===== */
/* Text marked .reveal is hidden only once the script has started (html.reveal-on), so a slow script download never
   leaves the page blank. Anything on screen at that moment is already marked visible; text below still fades in on scroll. */
html:not(.reveal-on) .reveal { opacity: 1; transform: none; transition: none; }

/* ===== 20261009a (Cam's pass, 8 Oct 2026) ===== */
/* Under an explanation in the side panel: how many highlighted lines are still waiting for their flag type. */
.quiz-waiting { display: none; }
.resume-side .quiz-waiting:not([hidden]) {
  display: block;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0.9rem 0 0;
}

/* ===== 20261009b (Cam's pass, 9 Oct 2026) ===== */
/* In the side panel, a line still waiting for its flag type is quoted above its buttons, and outlined in the document,
   so it is always clear which line is being named. A named line goes back to the 29 Sept look (no quote, no outline). */
@media (min-width: 960px) and (min-height: 500px) {
  .quiz-entries > .quiz-entry.is-waiting:first-child .quiz-entry-quote { display: block; }
  .quiz-choice.quiz-choice--current { outline: 3px solid var(--ink); outline-offset: 3px; border-radius: 2px; }
  .resume-side .quiz-entries > .quiz-entry.is-waiting:first-child .quiz-entry-quote { margin: 0 0 0.5rem; }
}
