:root {
  /* Slate palette and system typography, following the ODSL OCNG 489/689 course
     site: a near-neutral page, high-contrast slate text, one blue accent, and
     flat surfaces with thin borders rather than heavy rounded cards. */
  --ink: #0f172a;
  --muted: #475569;
  --line: #e2e8f0;
  --line-strong: #cbd5e1;
  --paper: #f7fafc;
  --surface: #ffffff;
  --accent: #1d4ed8;
  --accent-soft: #eef2ff;
  --accent-line: #c7d2fe;
  --navy: #1e293b;
  --ocean: #1d4ed8;
  --foam: #f1f5f9;
  --success: #15803d;
  --success-soft: #f0fdf4;
  --warn-ink: #854d0e;
  --warn-soft: #fefce8;
  --warn-line: #fde68a;
  --coral: #b91c1c;
  --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 8px 24px rgba(15, 23, 42, .06);
  --soft-shadow: 0 1px 2px rgba(15, 23, 42, .05);
  --sidebar: 248px;
  --radius: 10px;
  --coach-width: 372px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

html { scroll-behavior: smooth; }
body { margin: 0; color: var(--ink); background: var(--paper); font-family: var(--font); line-height: 1.55; }
/* Palette override only; position and behavior come from the shared base. */
.skip-link { background: var(--navy); }

.app-shell { min-height: 100vh; }
.sidebar { width: var(--sidebar); height: 100vh; position: fixed; inset: 0 auto 0 0; z-index: 40; background: var(--surface); border-right: 1px solid var(--line); padding: 25px 18px 18px; display: flex; flex-direction: column; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; padding: 0 8px 22px; }
/* The Blue Marble is a photograph, so it is masked to the disc rather than set in
   a tile — the original frame is mostly black sky and would read as a dark box. */
.brand-mark { width: 26px; height: 26px; flex: none; display: grid; place-items: center; border-radius: 50%; overflow: hidden; background: var(--navy); }
.brand-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }
.brand strong, .brand small { display: block; }
.brand strong { font: 800 15px/1.1 var(--font); letter-spacing: .07em; }
.brand small { margin-top: 3px; color: var(--muted); font-size: 12px; }
.primary-nav, .secondary-nav { display: grid; gap: 5px; }
.primary-nav a, .secondary-nav a { min-height: 44px; display: flex; align-items: center; gap: 12px; padding: 10px 12px; color: var(--muted); border: 1px solid transparent; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 14px; }
.primary-nav a span, .secondary-nav a span { width: 20px; color: var(--muted); text-align: center; font-size: 19px; }
.primary-nav a:hover, .secondary-nav a:hover { background: var(--foam); color: var(--ink); }
.primary-nav a.active, .secondary-nav a.active { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-line); }
.primary-nav a.active span { color: var(--accent); }
.sidebar-spacer { flex: 1; }
.secondary-nav { padding-top: 14px; border-top: 1px solid var(--line); }
.sidebar-profile { display: grid; grid-template-columns: 36px 1fr auto; align-items: center; gap: 9px; margin-top: 18px; padding: 14px 7px 0; border-top: 1px solid var(--line); }
.sidebar-profile strong, .sidebar-profile small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-profile strong { font-size: 12px; }.sidebar-profile small { color: var(--muted); font-size: 10px; }
.avatar, .mini-avatar { display: grid; place-items: center; color: #f8fafc; background: var(--navy); border-radius: 50%; font-weight: 700; }
.avatar { width: 36px; height: 36px; font-size: 11px; }.mini-avatar { width: 32px; height: 32px; font-size: 10px; }
.icon-button { min-width: 40px; min-height: 40px; border: 0; border-radius: 10px; background: transparent; cursor: pointer; }
.icon-button:hover { background: var(--foam); }

.page-shell { min-height: 100vh; margin-left: var(--sidebar); display: flex; flex-direction: column; }
.topbar { height: 68px; padding: 0 clamp(20px, 4vw, 58px); display: flex; align-items: center; justify-content: space-between; background: rgba(247, 250, 252, .92); border-bottom: 1px solid var(--line); backdrop-filter: blur(14px); position: sticky; top: 0; z-index: 30; }
.crumb { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; }.crumb strong { color: var(--ink); }.crumb span::after { content: "/"; padding-left: 10px; color: var(--line-strong); }
.topbar-actions { display: flex; align-items: center; gap: 10px; }.status-pill { min-height: 38px; padding: 8px 12px; background: white; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); cursor: pointer; font-size: 12px; }.status-pill[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); border-color: var(--accent-line); }.notification-button { position: relative; border: 1px solid var(--line); background: white; }.notification-dot { position: absolute; right: 8px; top: 8px; width: 7px; height: 7px; border-radius: 50%; background: var(--coral); border: 2px solid white; }
.menu-button { display: none; min-width: 42px; min-height: 42px; background: white; border: 1px solid var(--line); border-radius: 10px; }

main { width: 100%; max-width: 1520px; margin: 0 auto; padding: 42px clamp(22px, 5vw, 72px) 68px; flex: 1; }
.view { display: none; }.view.active { display: block; animation: appear .28s ease-out; }
@keyframes appear { from { opacity: 0; transform: translateY(5px); } }
.page-intro { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 32px; }
.page-intro h1, .module-header h1 { margin: 2px 0 8px; font: 700 clamp(26px, 2.4vw, 34px)/1.2 var(--font); letter-spacing: -.02em; color: var(--ink); }
.page-intro p, .module-header p { margin: 0; max-width: 680px; color: var(--muted); }
.eyebrow, .overline { margin: 0 0 6px !important; text-transform: uppercase; font-size: 11px !important; line-height: 1.4; font-weight: 700; letter-spacing: .09em; color: var(--muted) !important; }
.overline.ink { color: var(--ink) !important; }
.home-intro { align-items: center; }
.weekly-ring { width: 142px; display: flex; align-items: center; gap: 11px; }
.weekly-ring svg { width: 49px; transform: rotate(-90deg); }.weekly-ring circle { fill: none; stroke: #dce9e8; stroke-width: 5; }.weekly-ring .ring-value { stroke: var(--ocean); stroke-dasharray: 132; stroke-dashoffset: 44; stroke-linecap: round; }.weekly-ring strong, .weekly-ring small { display: block; }.weekly-ring strong { font-size: 15px; }.weekly-ring small { color: var(--muted); font-size: 10px; }

.continue-card { min-height: 220px; display: grid; grid-template-columns: minmax(260px, .8fr) 1.4fr; overflow: hidden; color: #f8fafc; background: var(--navy); border: 1px solid var(--navy); border-radius: var(--radius); box-shadow: var(--soft-shadow); }
.continue-art { min-height: 234px; position: relative; overflow: hidden; background: radial-gradient(circle at 30% 18%, rgba(84, 197, 192, .4), transparent 38%), linear-gradient(170deg, #126477, #0a3c51 72%); }
.continue-art::before { content: ""; position: absolute; inset: 0; opacity: .2; background-image: linear-gradient(rgba(255,255,255,.15) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.15) 1px, transparent 1px); background-size: 30px 30px; transform: perspective(260px) rotateX(54deg) scale(1.4); }
.water-line { position: absolute; left: -5%; width: 110%; height: 70px; border-radius: 50%; border-top: 2px solid rgba(153,235,226,.7); }.line-one { top: 64px; transform: rotate(-3deg); }.line-two { top: 110px; transform: rotate(3deg); }.line-three { top: 155px; transform: rotate(-2deg); }
.parcel { position: absolute; width: 28px; height: 28px; border: 4px solid rgba(255,255,255,.45); border-radius: 9px; transform: rotate(45deg); box-shadow: 0 0 25px rgba(152,234,225,.3); }.parcel-a { top: 48px; left: 28%; background: #6ed4c1; }.parcel-b { top: 107px; left: 58%; background: #f1b95c; }.parcel-c { top: 157px; left: 38%; background: #1d8ba1; }
.continue-copy { padding: 35px clamp(28px, 5vw, 70px) 28px; align-self: center; }.continue-copy .overline { color: #a3d8d5 !important; }.continue-copy h2 { margin: 4px 0 7px; font: 700 clamp(24px, 2.4vw, 34px)/1.15 var(--font); }.continue-copy > p:not(.overline) { color: #cce1e2; margin: 0; }.progress-line { height: 4px; margin: 25px 0 11px; overflow: hidden; background: rgba(255,255,255,.17); border-radius: 99px; }.progress-line span { width: 50%; height: 100%; display: block; background: #67d2be; border-radius: inherit; transition: width .3s ease; }.continue-meta { display: flex; align-items: center; justify-content: space-between; gap: 20px; color: #aac9cd; font-size: 11px; }
.button { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: 1px solid transparent; border-radius: 8px; padding: 10px 16px; text-decoration: none; font-weight: 700; font-size: 12px; cursor: pointer; }.button-light { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }.button-dark { background: var(--ink); color: #f8fafc; }.button-outline { border-color: var(--line-strong); background: var(--surface); color: var(--ink); }.button:hover { border-color: var(--accent); color: var(--accent); }.button-dark:hover { background: var(--navy); color: #f8fafc; border-color: var(--navy); }.full-width { width: 100%; }

.content-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(280px, .72fr); gap: 34px; margin-top: 42px; }.section-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 18px; }.section-heading h2 { margin: 0; padding-bottom: 5px; font: 700 15px/1.3 var(--font); letter-spacing: -.01em; color: var(--ink); border-bottom: 2px solid var(--accent-line); }.section-heading a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; font-size: 12px; font-weight: 600; }.section-heading.compact { align-items: center; }.section-heading.compact h2 { font-size: 17px; }
.module-list { background: white; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }.module-row { display: grid; grid-template-columns: 58px 1fr auto; align-items: center; gap: 17px; min-height: 122px; padding: 20px 22px; }.module-row + .module-row { border-top: 1px solid var(--line); }.module-icon { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 14px; font-size: 29px; font-weight: 500; }.ocean-icon { color: #0d6273; background: #dff2f1; }.density-icon { color: #14736f; background: #def3ed; }.ekman-icon { color: #156f89; background: #e1f0f4; }.wave-icon { color: #81633d; background: #f6eddd; }.module-row h3 { margin: 2px 0 4px; font: 700 15px/1.25 var(--font); }.module-row p { margin: 0; color: var(--muted); font-size: 12px; }.module-row .module-kicker { color: #4f666e; text-transform: uppercase; letter-spacing: .09em; font-size: 9px; font-weight: 700; }.module-action { display: flex; align-items: center; gap: 17px; }.tag { white-space: nowrap; padding: 4px 8px; border-radius: 4px; font-size: 9px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }.in-progress { color: #1e40af; background: var(--accent-soft); }.not-started { color: var(--muted); background: var(--foam); }.upcoming { color: var(--warn-ink); background: var(--warn-soft); }.review-preview { color: var(--warn-ink); background: var(--warn-soft); }.complete { color: #14532d; background: #dcfce7; }.round-button { width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 50%; background: white; cursor: pointer; font-size: 17px; }.round-button:hover { color: white; background: var(--navy); border-color: var(--navy); }.muted-module { border-left: 3px solid #d7bf8b; }.review-module { border-left: 3px solid #e3ad4f; }
.side-column { display: grid; align-content: start; gap: 22px; }.review-card, .mastery-card, .panel, .practice-card, .practice-settings { background: white; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }.review-card { position: relative; overflow: hidden; padding: 24px; }.review-icon { width: 40px; height: 40px; display: grid; place-items: center; margin-bottom: 16px; color: var(--accent); background: var(--accent-soft); border-radius: 50%; font-size: 20px; }.review-card h2 { margin: 3px 0 7px; font: 700 18px/1.2 var(--font); }.review-card > p:not(.overline) { margin: 0; color: var(--muted); font-size: 12px; }.review-meta { display: flex; gap: 23px; margin: 19px 0; color: var(--muted); font-size: 10px; }.review-meta strong { color: var(--ink); font-size: 15px; }.mastery-card { padding: 22px 24px; }.mastery-list { display: grid; gap: 17px; }.mastery-item { display: grid; grid-template-columns: 1fr auto; gap: 6px 12px; }.mastery-item strong { font-size: 12px; }.mastery-item small { color: var(--muted); font-size: 9px; }.mastery-bar { height: 5px; grid-column: 1 / -1; overflow: hidden; background: #e7eeee; border-radius: 99px; }.mastery-bar i { height: 100%; display: block; background: var(--accent); border-radius: inherit; }
.connection-strip { min-height: 110px; display: grid; grid-template-columns: 64px 1fr auto; align-items: center; gap: 22px; margin-top: 34px; padding: 20px 24px; background: var(--foam); border: 1px solid var(--line); border-radius: var(--radius); }.connection-art { width: 52px; height: 52px; display: grid; place-items: center; color: var(--accent); background: var(--surface); border: 1px solid var(--line-strong); border-radius: 50%; font-size: 28px; }.connection-strip h2 { margin: 2px 0; font: 700 16px/1.2 var(--font); }.connection-strip p:not(.overline) { margin: 0; max-width: 740px; color: var(--muted); font-size: 11px; }.text-button { border: 0; background: transparent; color: var(--accent); text-decoration: underline; text-underline-offset: 3px; font-weight: 600; font-size: 12px; cursor: pointer; }

.filter-row { display: flex; gap: 8px; margin-bottom: 22px; overflow-x: auto; }.filter { padding: 7px 14px; color: var(--muted); background: var(--surface); border: 1px solid var(--line); border-radius: 6px; font-size: 12px; cursor: pointer; }.filter.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent-line); font-weight: 600; }.module-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }.module-card { min-height: 390px; display: flex; flex-direction: column; overflow: hidden; background: white; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }.module-card-art { height: 154px; position: relative; display: grid; place-items: center; overflow: hidden; }.module-card-art svg, .module-card-art img { width: 82%; height: 82%; }.module-card-art { background: var(--module-accent, #dceff0); }.module-card-body { flex: 1; padding: 23px; display: flex; flex-direction: column; }.module-card h2 { margin: 5px 0 9px; font: 700 20px/1.2 var(--font); }.module-card p { margin: 0; color: var(--muted); font-size: 12px; }.module-card .review-label { width: fit-content; margin: 0 0 10px; padding: 4px 8px; color: var(--warn-ink); background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: 4px; font-size: 9px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }.module-card .module-card-footer { margin-top: auto; padding-top: 20px; display: flex; align-items: center; justify-content: space-between; }.module-card .module-card-footer span { color: var(--muted); font-size: 10px; }

.module-header { margin-bottom: 24px; }.back-button { margin-bottom: 22px; padding: 0; color: var(--ocean); background: transparent; border: 0; font-weight: 700; font-size: 12px; cursor: pointer; }.module-heading-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }.step-count { color: var(--muted); white-space: nowrap; font-size: 12px; }.stepper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-top: 25px; }.step-marker { height: 5px; border: 0; overflow: hidden; background: #dce7e7; border-radius: 99px; cursor: pointer; }.step-marker.active, .step-marker.done { background: var(--accent); }.lab-shell { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(280px, .65fr); gap: 24px; }.lab-stage, .lab-side { background: white; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }.lab-stage { min-height: 510px; padding: clamp(20px, 3vw, 34px); }.lab-side { padding: 25px; align-self: start; }.lab-side h2, .lab-stage h2 { margin: 0 0 8px; font: 700 19px/1.25 var(--font); }.lab-stage > p, .lab-side > p { margin: 0 0 18px; color: var(--muted); font-size: 12px; }.stage-label { color: var(--ocean); font-size: 10px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }.prediction-box { margin: 20px 0; padding: 20px; background: var(--foam); border: 1px solid var(--line); border-radius: var(--radius); }.prediction-box fieldset { padding: 0; border: 0; }.prediction-box legend { margin-bottom: 12px; font-weight: 700; }.choice-list { display: grid; gap: 8px; }.choice-pill { display: flex; align-items: center; gap: 10px; padding: 11px 13px; background: var(--surface); border: 1px solid var(--line-strong); border-radius: 8px; cursor: pointer; font-size: 12px; }.choice-pill:has(input:checked) { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); background: var(--accent-soft); }.lab-actions { display: flex; gap: 10px; margin-top: 20px; }.lab-actions .button:last-child { margin-left: auto; }.interactive-panel { min-height: 300px; display: grid; grid-template-columns: 1fr 220px; gap: 24px; align-items: center; padding: 20px; background: var(--foam); border: 1px solid var(--line); border-radius: var(--radius); }.control-stack { display: grid; gap: 15px; }.control-stack label { display: grid; grid-template-columns: 1fr auto; gap: 6px; color: var(--muted); font-size: 11px; }.control-stack label span { color: var(--ink); font-weight: 700; }.control-stack input[type="range"] { width: 100%; grid-column: 1 / -1; accent-color: var(--accent); }.control-stack select { grid-column: 1 / -1; min-height: 40px; padding: 7px 10px; background: var(--surface); border: 1px solid var(--line-strong); border-radius: 8px; }.science-summary { margin-top: 16px; padding: 14px 16px; color: var(--ink); background: var(--foam); border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0; font-size: 12px; }.science-summary strong { color: var(--ink); }.text-alternative { margin-top: 15px; }.text-alternative summary { color: var(--accent); cursor: pointer; font-weight: 600; font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }.text-alternative table { margin-top: 12px; }
.tank { height: 270px; position: relative; overflow: hidden; border: 4px solid #28697a; border-top: 0; border-radius: 4px 4px 22px 22px; background: linear-gradient(#d9f6f2, #92cfd1 50%, #397b93); }.tank::after { content: "Depth"; position: absolute; right: 6px; bottom: 10px; color: rgba(255,255,255,.8); font-size: 9px; writing-mode: vertical-rl; }.tank-parcel { position: absolute; left: 50%; width: 62%; transform: translateX(-50%); display: flex; align-items: center; justify-content: space-between; padding: 8px 11px; border-radius: 9px; color: #083849; background: rgba(255,255,255,.72); border: 1px solid rgba(255,255,255,.8); font-size: 10px; transition: top .5s ease; }.tank-parcel::before { content: ""; width: 11px; height: 11px; border-radius: 50%; background: var(--parcel-color); }.density-visual { display: grid; grid-template-columns: 135px 1fr; gap: 18px; align-items: center; }
.coast-scene { height: 300px; position: relative; overflow: hidden; border-radius: 13px; background: linear-gradient(90deg, #e4c98f 0 27%, #8dd6dc 27% 53%, #2d7d96 53%); }.coastline { position: absolute; left: 27%; inset-block: 0; width: 4px; background: #fff4d5; }.arrow { position: absolute; min-width: 76px; padding: 6px 8px; color: white; background: rgba(7,59,76,.85); border-radius: 7px; text-align: center; font-size: 10px; transition: transform .3s ease; }.wind-arrow { left: 35%; top: 40px; }.transport-arrow { left: 46%; top: 130px; background: rgba(218,100,72,.9); }.upwelling-plume { position: absolute; width: 110px; height: 170px; bottom: -50px; left: 29%; opacity: .9; border-radius: 50% 50% 0 0; background: radial-gradient(ellipse at top, #60d5be, #175f7d 70%); transform: translateY(70px); transition: transform .5s ease; }.coast-scene.upwelling .upwelling-plume { transform: translateY(0); }.coast-scene.downwelling .upwelling-plume { left: 48%; transform: translateY(35px) rotate(30deg); }.nutrient-dots { position: absolute; left: 31%; bottom: 25px; color: #fff09c; letter-spacing: 8px; opacity: 0; transition: opacity .3s; }.coast-scene.upwelling.show-nutrients .nutrient-dots { opacity: 1; }
.wave-scene { height: 300px; position: relative; overflow: hidden; border-radius: 13px; background: linear-gradient(165deg, #cceff0, #4897ad 65%, #d9bf82 66%); }.wave-crest { position: absolute; left: 0; width: 80%; height: 25px; border-top: 3px solid white; border-radius: 50%; opacity: .9; transform-origin: right center; }.wave-crest:nth-child(1) { top: 35px; }.wave-crest:nth-child(2) { top: 95px; width: 72%; }.wave-crest:nth-child(3) { top: 150px; width: 60%; }.wave-crest:nth-child(4) { top: 200px; width: 49%; }.wave-ray { position: absolute; height: 2px; width: 73%; left: 7%; top: var(--top); background: rgba(255,235,160,.9); transform: rotate(var(--angle)); transform-origin: right; }.break-line { position: absolute; right: 19%; inset-block: 0; width: 2px; border-left: 2px dashed rgba(255,255,255,.8); }.break-line span { position: absolute; top: 10px; right: 8px; color: white; white-space: nowrap; font-size: 9px; }.wave-metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }.wave-metrics div { padding: 11px; background: white; border: 1px solid var(--line); border-radius: 9px; }.wave-metrics small, .wave-metrics strong { display: block; }.wave-metrics small { color: var(--muted); font-size: 9px; }.wave-metrics strong { margin-top: 2px; color: var(--ink); font-family: var(--mono); font-size: 14px; }
.concept-check { padding: 22px; background: var(--foam); border: 1px solid var(--line); border-radius: var(--radius); }.concept-check h3 { margin: 0 0 14px; font: 700 16px var(--font); }.feedback { display: none; margin-top: 16px; padding: 14px 16px; border-radius: 10px; font-size: 12px; }.feedback.show { display: block; }.feedback.correct { color: #14532d; background: var(--success-soft); border-left: 3px solid var(--success); }.feedback.incorrect { color: #7f1d1d; background: #fef2f2; border-left: 3px solid var(--coral); }.complete-panel { max-width: 670px; margin: 40px auto; text-align: center; }.complete-badge { width: 68px; height: 68px; display: grid; place-items: center; margin: 0 auto 18px; color: #f8fafc; background: var(--success); border-radius: 50%; font-size: 30px; }.complete-panel h2 { font-size: 28px; }.complete-panel .transfer { margin: 23px 0; padding: 18px; text-align: left; background: var(--foam); border-radius: 12px; }

.practice-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) 300px; gap: 24px; }.practice-card { min-height: 460px; padding: clamp(24px, 4vw, 42px); }.practice-settings { padding: 24px; align-self: start; }.practice-settings h2 { margin: 0 0 18px; font: 700 18px var(--font); }.practice-settings fieldset { display: grid; gap: 9px; margin: 0 0 22px; padding: 0; border: 0; }.practice-settings legend { margin-bottom: 8px; font-weight: 700; font-size: 12px; }.practice-settings label { padding: 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 12px; }.question-count { color: var(--accent); font-family: var(--mono); font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }.practice-card h2 { max-width: 680px; margin: 13px 0 22px; font: 700 clamp(20px, 2.5vw, 28px)/1.3 var(--font); }.confidence-row { margin-top: 19px; padding-top: 17px; border-top: 1px solid var(--line); }.confidence-row p { margin: 0 0 8px; color: var(--muted); font-size: 11px; }.confidence-row label { margin-right: 14px; font-size: 11px; }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }.stat-grid article { padding: 18px 20px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }.stat-grid article span, .stat-grid article strong, .stat-grid article small { display: block; }.stat-grid article span { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: .08em; }.stat-grid article strong { margin: 5px 0; color: var(--ink); font: 700 24px/1.2 var(--font); letter-spacing: -.02em; }.stat-grid article small { color: var(--muted); font-size: 10px; }.panel { padding: clamp(20px, 3vw, 30px); margin-bottom: 24px; }.legend { color: var(--muted); font-size: 10px; }.legend i { width: 9px; height: 9px; display: inline-block; margin-right: 5px; background: var(--accent); border-radius: 2px; }.mastery-detail-row { display: grid; grid-template-columns: minmax(150px, 1fr) 2fr 130px; align-items: center; gap: 18px; padding: 13px 0; }.mastery-detail-row + .mastery-detail-row { border-top: 1px solid var(--line); }.mastery-detail-row strong { font-size: 12px; }.mastery-detail-row span { color: var(--muted); font-size: 10px; }.detail-bar { height: 10px; overflow: hidden; background: #e7eeee; border-radius: 99px; }.detail-bar i { height: 100%; display: block; background: var(--accent); border-radius: inherit; }.progress-table-wrap { overflow-x: auto; }table { width: 100%; border-collapse: collapse; font-size: 11px; }th, td { padding: 13px; text-align: left; border-bottom: 1px solid var(--line); }th { color: var(--muted); text-transform: uppercase; letter-spacing: .07em; font-size: 9px; }
.concept-map { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }.concept-card { position: relative; min-height: 180px; padding: 22px; overflow: hidden; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }.concept-card::after { content: attr(data-number); position: absolute; right: 14px; bottom: -24px; color: #edf3f2; font: 800 90px var(--font); }.concept-card h2 { position: relative; z-index: 1; margin: 5px 0 7px; font: 700 19px var(--font); }.concept-card p { position: relative; z-index: 1; max-width: 85%; color: var(--muted); font-size: 12px; }.concept-links { position: relative; z-index: 1; display: flex; gap: 6px; margin-top: 17px; flex-wrap: wrap; }.concept-links span { padding: 4px 8px; color: var(--muted); background: var(--foam); border: 1px solid var(--line); border-radius: 4px; font-size: 10px; }
/* A card with a figure spans the map so labels stay readable. The watermark
   number would sit on the drawing, so it is dropped for those cards. */
.concept-card:has(.concept-figure) { grid-column: 1 / -1; }
.concept-card:has(.concept-figure)::after { content: none; }
.concept-card:has(.concept-figure) p { max-width: 70rem; }
.concept-figure { position: relative; z-index: 1; margin: 14px 0 4px; }
.concept-figure img { display: block; width: 100%; height: auto; background: #fff; border: 1px solid var(--line); border-radius: 10px; }
.concept-figure figcaption { margin: 8px 2px 0; color: var(--muted); font-size: 11px; line-height: 1.45; max-width: 70rem; }
.field { display: grid; gap: 5px; margin-bottom: 16px; }
.field label { font-weight: 700; font-size: 12px; color: var(--ink); }
.field input[type="text"], .field input[type="password"] { min-height: 44px; padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--surface); color: var(--ink); }
.field input:focus-visible { border-color: var(--accent); }
.field small { color: var(--muted); font-size: 11px; line-height: 1.45; }
.field-optional { font-weight: 400; color: var(--muted); }
.sidebar-profile .icon-button { display: grid; place-items: center; text-decoration: none; color: var(--muted); font-size: 18px; }
.badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; margin: 0; padding: 0; list-style: none; }
.badge-card { display: grid; grid-template-columns: 52px 1fr; gap: 13px; padding: 15px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.badge-card.earned { background: var(--success-soft); border-color: #bbf7d0; }
.badge-mark { width: 50px; height: 50px; display: grid; place-items: center; border-radius: 50%; background: var(--foam); color: var(--muted); }
.badge-art { width: 38px; height: 38px; display: block; }
.badge-card.earned .badge-mark { background: var(--success); color: white; }
.badge-card strong { display: block; font-size: 13px; }
.badge-state { display: inline-block; margin-top: 3px; padding: 2px 7px; border-radius: 4px; background: var(--foam); color: var(--muted); font-size: 9px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; }
.badge-card.earned .badge-state { background: #dcfce7; color: #14532d; }
.badge-trophic { display: block; margin-top: 5px; color: var(--muted); font-family: var(--mono); font-size: 10px; }
.badge-card p { margin: 7px 0 0; color: var(--muted); font-size: 11px; line-height: 1.5; }
.instructor-controls { display: flex; align-items: center; gap: 10px; }
.instructor-controls select { min-height: 40px; padding: 6px 10px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--surface); color: var(--ink); font: inherit; font-size: 12px; }
.empty-note { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.5; }
/* `hidden` loses to a display rule, so the empty-state alert stayed on screen
   with no text in it. Stated once, next to the rule that outranks it. */
.instructor-alert[hidden] { display: none; }
.instructor-alert { display: grid; grid-template-columns: 38px 1fr auto; align-items: center; gap: 15px; margin-bottom: 23px; padding: 16px 18px; color: var(--warn-ink); background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: var(--radius); }.instructor-alert > span { width: 32px; height: 32px; display: grid; place-items: center; background: var(--warn-line); border-radius: 50%; font-weight: 700; }.instructor-alert p { margin: 2px 0 0; font-size: 11px; }.analytics-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 24px; }.bar-chart { display: grid; gap: 16px; }.chart-row { display: grid; grid-template-columns: 160px 1fr 40px; align-items: center; gap: 12px; font-size: 11px; }.chart-track { height: 13px; overflow: hidden; background: #edf2f2; border-radius: 99px; }.chart-track i { height: 100%; display: block; background: var(--accent); border-radius: inherit; }.misconception-list { margin: 0; padding: 0; list-style: none; }.misconception-list li { display: flex; gap: 12px; padding: 15px 0; }.misconception-list li + li { border-top: 1px solid var(--line); }.misconception-list li > span { color: var(--muted); font-family: var(--mono); font-weight: 700; }.misconception-list strong, .misconception-list small { display: block; }.misconception-list strong { font-size: 11px; }.misconception-list small { margin-top: 4px; color: var(--muted); font-size: 9px; }.help-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 20px; }
/* Four panels laid out 3 + 1 reads as an afterthought, and the fourth here
   is the disclosure about who can see a student's work. Two by two gives it
   equal weight. :has() so the rule follows the panel count rather than the
   view name. */
.help-grid:has(> .panel:nth-child(4)) { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }.help-grid .panel { min-height: 240px; }.help-grid h2 { font: 700 19px var(--font); }.help-grid p { color: var(--muted); font-size: 12px; }
.review-banner { width: fit-content; margin: 12px 0 0; padding: 8px 11px; color: var(--warn-ink); background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: 6px; font-size: 11px; font-weight: 600; }.evidence-table-wrap { margin: 18px 0; overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; }.evidence-table-wrap table { min-width: 620px; }.evidence-table-wrap caption { padding: 12px; color: var(--ink); background: var(--foam); text-align: left; font-weight: 800; }.evidence-controls { grid-template-columns: minmax(0, 1fr) minmax(220px, .8fr); }.evidence-chain { display: grid; gap: 9px; }.evidence-chain span { padding: 11px 13px; color: var(--ink); background: var(--surface); border: 1px solid var(--line-strong); border-radius: 8px; font-size: 11px; font-weight: 700; }.evidence-chain b { color: var(--accent); text-align: center; }
/* Chapter 1 evidence sort. A responsive grid rather than five fixed columns:
   five side by side is unreadable on a phone, and the activity is a
   classification, not a spatial arrangement, so the cards may wrap. */
.evidence-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin-top: 12px; }
.evidence-column { padding: 12px; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; }
.evidence-unsorted { background: var(--foam); }
.evidence-column h3 { display: flex; justify-content: space-between; gap: 8px; margin: 0 0 9px; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; }
.evidence-column h3 span { color: var(--accent); font-variant-numeric: tabular-nums; }
.evidence-column ul { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.evidence-card, .lab-item { display: grid; gap: 5px; padding: 9px 10px; background: white; border: 1px solid var(--line); border-radius: 8px; }
.evidence-card label, .lab-item label { font-size: 12px; font-weight: 700; }
.evidence-card select, .lab-item select { width: 100%; font-size: 11px; }
.evidence-empty { padding: 9px 10px; color: var(--muted); font-size: 11px; }
#sort-summary ul { margin: 8px 0 0; padding-left: 18px; font-weight: 400; }
#sort-summary li { margin: 0 0 5px; }
/* The human-activity chain reuses the sort's card, in one column: it is an
   order, not a set of bins, so the reading order is the answer. */
.climate-links, .evidence-disciplines, .lab-questions { display: grid; gap: 8px; margin: 12px 0 0; padding: 0; list-style: none; }
.lab-check ul { margin: 8px 0 0; padding-left: 18px; font-weight: 400; }
.lab-check li { margin: 0 0 5px; }
#spread-summary ul { margin: 8px 0 0; padding-left: 18px; font-weight: 400; }
#spread-summary li { margin: 0 0 5px; }
#climate-summary ul { margin: 8px 0 0; padding-left: 18px; font-weight: 400; }
#climate-summary li { margin: 0 0 5px; }
.course-footer { min-height: 70px; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 20px clamp(22px, 5vw, 72px); color: var(--muted); border-top: 1px solid var(--line); font-size: 10px; }.toast { position: fixed; right: 22px; bottom: 22px; z-index: 100; max-width: 340px; padding: 12px 16px; color: #f8fafc; background: var(--ink); border-radius: 8px; box-shadow: var(--shadow); opacity: 0; transform: translateY(12px); pointer-events: none; transition: .2s ease; font-size: 12px; }.toast.show { opacity: 1; transform: translateY(0); }

/* Vibrant right edge on tiles and sections.
   Purely decorative: it repeats the hue already carried by the tile's art or
   icon and never encodes state, so nothing is lost when it is not perceived.
   Module tiles take their own chapter hue via --tile-accent (set inline from
   the module record); everything else cycles the palette below so neighboring
   tiles differ. The bar sits inside existing padding, so no layout shifts. */
:root {
  --tile-bar: 5px;
  --vivid-1: #139ceb; --vivid-2: #0ea97a; --vivid-3: #ee7032;
  --vivid-4: #8f88f5; --vivid-5: #10a3c0; --vivid-6: #c98810;
}
.module-card, .module-row, .stat-grid article, .panel, .concept-card,
.badge-card, .review-card, .mastery-card, .practice-card, .practice-settings {
  position: relative;
}
.module-card::after, .module-row::after, .stat-grid article::after, .panel::after,
.concept-card::before, .badge-card::after, .review-card::after, .mastery-card::after,
.practice-card::after, .practice-settings::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0;
  width: var(--tile-bar); z-index: 2; pointer-events: none;
  border-radius: 0 var(--radius) var(--radius) 0;
  /* Solid at the top, easing off at the foot so the bar reads as a highlight
     rather than a second border. */
  background: linear-gradient(180deg, var(--tile-accent, var(--accent)) 0%,
              var(--tile-accent, var(--accent)) 55%,
              color-mix(in srgb, var(--tile-accent, var(--accent)) 45%, white) 100%);
}
/* .concept-card::after already renders the big chapter number, hence ::before. */
.concept-card::before { z-index: 1; }
.stat-grid article:nth-child(4n+1), .panel:nth-of-type(4n+1) { --tile-accent: var(--vivid-1); }
.stat-grid article:nth-child(4n+2), .panel:nth-of-type(4n+2) { --tile-accent: var(--vivid-2); }
.stat-grid article:nth-child(4n+3), .panel:nth-of-type(4n+3) { --tile-accent: var(--vivid-3); }
.stat-grid article:nth-child(4n+4), .panel:nth-of-type(4n+4) { --tile-accent: var(--vivid-4); }
.concept-card:nth-child(6n+1) { --tile-accent: var(--vivid-1); }
.concept-card:nth-child(6n+2) { --tile-accent: var(--vivid-2); }
.concept-card:nth-child(6n+3) { --tile-accent: var(--vivid-3); }
.concept-card:nth-child(6n+4) { --tile-accent: var(--vivid-4); }
.concept-card:nth-child(6n+5) { --tile-accent: var(--vivid-5); }
.concept-card:nth-child(6n+6) { --tile-accent: var(--vivid-6); }
.badge-card:nth-child(6n+1) { --tile-accent: var(--vivid-2); }
.badge-card:nth-child(6n+2) { --tile-accent: var(--vivid-3); }
.badge-card:nth-child(6n+3) { --tile-accent: var(--vivid-4); }
.badge-card:nth-child(6n+4) { --tile-accent: var(--vivid-5); }
.badge-card:nth-child(6n+5) { --tile-accent: var(--vivid-6); }
.badge-card:nth-child(6n+6) { --tile-accent: var(--vivid-1); }
.review-card { --tile-accent: var(--vivid-3); }
.mastery-card { --tile-accent: var(--vivid-2); }
.practice-card { --tile-accent: var(--vivid-1); }
.practice-settings { --tile-accent: var(--vivid-4); }
/* Rows sit flush inside a card, so only the last one gets the rounded foot. */
.module-row::after { border-radius: 0; }
.module-row:last-child::after { border-radius: 0 0 var(--radius) 0; }
.module-row:first-child::after { border-radius: 0 var(--radius) 0 0; }
/* Fallback for engines without color-mix: a flat bar in the same hue. */
@supports not (background: color-mix(in srgb, red 50%, white)) {
  .module-card::after, .module-row::after, .stat-grid article::after, .panel::after,
  .concept-card::before, .badge-card::after, .review-card::after, .mastery-card::after,
  .practice-card::after, .practice-settings::after {
    background: var(--tile-accent, var(--accent));
  }
}

/* Study coach.
   The disclosure is a permanent part of the view, not a dismissible banner:
   students need to know the replies are generated and stored every time they
   use it, not once. Speaker is carried by the visible "You" / "Study coach"
   text, so the left border and background are redundant decoration rather than
   the only signal. */
/* The nav links set display:flex, which outranks the user-agent [hidden] rule,
   so a hidden link would otherwise still show. */
.primary-nav a[hidden], .secondary-nav a[hidden] { display: none; }
.tutor-disclosure { margin: 0 0 20px; padding: 14px 16px; background: var(--warn-soft); border: 1px solid var(--warn-line); border-left: 4px solid var(--warn-ink); border-radius: var(--radius); color: var(--warn-ink); }
.tutor-disclosure p { margin: 0; font-size: 12px; line-height: 1.55; }
.tutor-disclosure p + p { margin-top: 8px; }
.tutor-shell { padding: clamp(18px, 3vw, 26px); background: white; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--soft-shadow); }
.tutor-log { min-height: 120px; max-height: 52vh; overflow-y: auto; display: grid; gap: 14px; }
.tutor-log:empty::before { content: "Ask a question to begin. The coach answers only from this course's material."; color: var(--muted); font-size: 12px; }
.tutor-turn { padding: 13px 15px; border-radius: 10px; border: 1px solid var(--line); }
.tutor-turn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.tutor-turn-student { background: var(--foam); }
.tutor-turn-coach { background: var(--surface); border-left: 3px solid var(--accent); }
.tutor-turn .turn-speaker { margin: 0 0 6px; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; }
.tutor-turn p { margin: 0; font-size: 13px; line-height: 1.6; }
.tutor-turn p + p { margin-top: 9px; }
.tutor-turn .turn-sources { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--line); color: var(--muted); font-size: 10px; }
.tutor-status { min-height: 18px; margin: 12px 0 0; color: var(--muted); font-size: 12px; }
.tutor-form { display: grid; gap: 14px; margin-top: 6px; }
.tutor-field { display: grid; gap: 6px; }
.tutor-field label { font-size: 12px; font-weight: 700; }
.tutor-field select, .tutor-field textarea { width: 100%; padding: 10px 12px; color: var(--ink); background: white; border: 1px solid var(--line-strong); border-radius: 8px; font: inherit; font-size: 13px; }
.tutor-field textarea { resize: vertical; min-height: 76px; }
.tutor-field :disabled { background: var(--paper); color: var(--muted); cursor: not-allowed; }
.tutor-hint { margin: 0; color: var(--muted); font-size: 10px; }

/* --- Study coach dock -------------------------------------------------------
   Non-modal: no focus trap, no inert, no backdrop, no aria-modal. The student
   can still read and click the question behind it, which is the point -- that
   question is usually what they are asking about. Built as the ARIA disclosure
   pattern (a toggle carrying aria-expanded/aria-controls revealing a named
   region) rather than role="dialog", which in several screen readers confines
   the virtual cursor to the dialog and would take the read-behind away. */
.coach-button { position: relative; border: 1px solid var(--line); background: white; color: var(--coral); }
.coach-button[hidden] { display: none; }
.coach-button:hover { background: #fef2f2; }
/* Open state is carried by aria-expanded and by this filled swatch -- a
   luminance inversion, legible without color vision -- never by hue alone. */
.coach-button[aria-expanded="true"] { color: white; background: var(--coral); border-color: var(--coral); }
.coach-icon { display: block; margin: 0 auto; }
.coach-dock { position: fixed; right: 22px; bottom: 22px; z-index: 60; width: var(--coach-width); max-width: calc(100vw - 32px); max-height: min(72vh, 620px); display: grid; gap: 12px; align-content: start; padding: 16px; overflow: auto; background: var(--surface); border: 1px solid var(--line-strong); border-top: 3px solid var(--coral); border-radius: var(--radius); box-shadow: var(--shadow); }
/* display:grid outranks the user-agent [hidden] rule, exactly as it does for
   .view, so the hidden case has to be restated. */
.coach-dock[hidden] { display: none; }
/* An animation, not a transition: the panel goes display:none -> grid and a
   transition cannot run across that. Both reduced-motion rules already flatten
   animation-duration, so this degrades to instant with no extra rule. */
.coach-dock:not([hidden]) { animation: coach-appear .18s ease-out; }
@keyframes coach-appear { from { opacity: 0; transform: translateY(8px); } }
.coach-dock-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.coach-dock-title { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.coach-context { margin: 3px 0 0; color: var(--muted); font-size: 11px; font-weight: 600; }
.coach-close { flex: none; color: var(--muted); font-size: 20px; line-height: 1; }
.coach-disclosure { margin: 0; padding: 10px 12px; color: var(--warn-ink); background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: 8px; font-size: 10px; line-height: 1.5; }
.coach-log { min-height: 72px; max-height: 34vh; }
.coach-log:empty::before { content: "Ask about what you are looking at. The coach answers from this course's material only."; }
.coach-status { margin: 0; }
.coach-form { display: grid; gap: 10px; }
.coach-form textarea { min-height: 60px; }
.coach-form button { justify-self: stretch; }
/* The toast owns this same corner and carries save failures the student still
   needs, so it steps aside rather than being covered. */
body.coach-open .toast { right: calc(var(--coach-width) + 34px); }
.tutor-form button { justify-self: start; }


@media (max-width: 1100px) {
  /* minmax(0, 1fr) not 1fr: a bare 1fr track has an auto minimum, so the
     620px-min evidence table forces horizontal page overflow on phones. */
  .content-grid, .lab-shell { grid-template-columns: minmax(0, 1fr); }.lab-stage, .lab-side { min-width: 0; }.side-column { grid-template-columns: repeat(2, 1fr); }.module-grid { grid-template-columns: repeat(2, 1fr); }.analytics-grid { grid-template-columns: 1fr; }.stat-grid { grid-template-columns: repeat(2, 1fr); }.help-grid { grid-template-columns: 1fr; }.help-grid .panel { min-height: 0; }
}
@media (max-width: 820px) {
  :root { --sidebar: 272px; }.sidebar { transform: translateX(-102%); transition: transform .2s ease; box-shadow: var(--shadow); }.sidebar.open { transform: translateX(0); }.page-shell { margin-left: 0; }.menu-button { display: inline-grid; place-items: center; }.crumb span { display: none; }.crumb span::after { display: none; }.topbar { padding-inline: 16px; }.status-pill { display: none; }main { padding: 30px 18px 52px; }.continue-card { grid-template-columns: 1fr; }.continue-art { min-height: 170px; }.continue-copy { padding: 27px 24px; }.module-grid { grid-template-columns: 1fr; }.practice-layout { grid-template-columns: 1fr; }.practice-settings { order: -1; }.concept-map { grid-template-columns: 1fr; }.course-footer { padding-inline: 18px; }
}
@media (max-width: 620px) {
  .page-intro, .module-heading-row { align-items: flex-start; flex-direction: column; }.weekly-ring { display: none; }.continue-meta { align-items: stretch; flex-direction: column; }.content-grid { margin-top: 29px; }.side-column { grid-template-columns: 1fr; }.module-row { grid-template-columns: 48px 1fr; gap: 13px; padding: 17px; }.module-icon { width: 45px; height: 45px; }.module-action { grid-column: 2; justify-content: space-between; }.connection-strip { grid-template-columns: 45px 1fr; padding: 20px; }.connection-art { width: 44px; height: 44px; }.connection-strip .text-button { grid-column: 2; justify-self: start; padding: 0; }.interactive-panel { grid-template-columns: 1fr; }.density-visual { grid-template-columns: 1fr; }.tank { height: 230px; }.stat-grid { grid-template-columns: 1fr 1fr; gap: 9px; }.stat-grid article { padding: 16px; }.mastery-detail-row { grid-template-columns: 1fr auto; gap: 7px; }.detail-bar { grid-column: 1 / -1; }.instructor-alert { grid-template-columns: 35px 1fr; }.instructor-alert .text-button { grid-column: 2; justify-self: start; }.chart-row { grid-template-columns: 110px 1fr 35px; }.course-footer { align-items: flex-start; flex-direction: column; }.topbar-actions .mini-avatar { display: none; }/* Capped well under half the viewport: this panel promises the page behind it stays usable, and at 76vh it covered 63% of a 390x844 screen, which made that promise false on a phone. */.coach-dock { right: 8px; left: 8px; bottom: 8px; width: auto; max-width: none; max-height: min(52vh, 400px); }.coach-log { max-height: 20vh; }/* Edge-to-edge here, so sliding the toast sideways is not available; it moves under the topbar instead. */body.coach-open .toast { right: 12px; left: 12px; bottom: auto; top: 78px; max-width: none; }
}
@media print {
  .sidebar, .topbar, .course-footer, .coach-dock, button { display: none !important; }.page-shell { margin: 0; }main { max-width: none; padding: 0; }.view { display: none !important; }.view.active { display: block !important; }.lab-shell { grid-template-columns: 1fr; }.panel, .lab-stage, .lab-side { box-shadow: none; }
  /* Decorative only — not worth a student's toner. */
  .module-card::after, .module-row::after, .stat-grid article::after, .panel::after,
  .concept-card::before, .badge-card::after, .review-card::after, .mastery-card::after,
  .practice-card::after, .practice-settings::after { display: none !important; }
}
/* --- Parameter-lab layout ---------------------------------------------------
   The panel used to be a fixed two-column grid: readouts on the left, controls
   in a 220 px rail on the right. With two dropdowns and three readouts that put
   the things you change into a narrow column beside the things they change, and
   at the mobile breakpoint the whole panel collapsed to one column with the
   readouts above the controls — so a phone user met the answers before the
   question.

   Controls now sit across the top of the panel and the readouts form a card row
   beneath them, which is also their order in the DOM: the reading order a screen
   reader announces and the order the eye follows are the same sequence, not two
   arrangements that happen to agree at one width.

   auto-fit rather than a fixed column count, because the renderer is shared. Two
   controls sit side by side and three readouts sit in a row on a wide screen; a
   lab with three controls and six readouts arranges itself from the same rule,
   and every one of them stacks to a single column when the space is no longer
   there. */
.parameter-lab { grid-template-columns: 1fr; align-items: start; align-content: start; gap: 18px; }
.parameter-lab .control-stack { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px 18px; align-items: end; }
.parameter-lab .control-stack label { align-content: start; }
.parameter-lab .wave-metrics { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* One column below the breakpoint where the side rail stacks: at phone widths
   auto-fit would still fit two 150 px cards and leave a 2 + 1 orphan row. */
@media (max-width: 620px) {
  .parameter-lab .control-stack, .parameter-lab .wave-metrics { grid-template-columns: 1fr; }
}
/* The readouts are the panel's result, so give them a little more presence than
   the surrounding foam once they are a row of their own. */
.parameter-lab .wave-metrics div { padding: 13px 14px; }
/* Readouts are set in mono because they are usually a number and a unit, where
   the fixed advance stops the value jittering as a slider moves. A comparison
   lab reports sentences instead, and bold mono prose is slow to read and runs
   the cards tall. A model declares which kind it produces. */
.wave-metrics[data-readout="prose"] strong { font-family: var(--font); font-size: 12.5px; font-weight: 600; line-height: 1.45; }
/* --- The other module steps, same shape as the lab -------------------------
   Predict, Interact and Explain now read the same way: the things you choose
   run across the top in a row, and the things you read sit below as cards.

   Predict's options are the step's controls, and they are short — a median of
   23 characters across the sixteen modules, longest 39 — so a row of them fits
   and scans in one pass.

   Explain's chain is the step's output. Its links are prose (median 141
   characters), so they are cards in the same auto-fit row as a lab's readouts,
   numbered by the list rather than by a character typed into the text.

   Practice is deliberately NOT converted. Its answer choices are also inputs,
   but they are long — a median of 75 characters and up to 242 — and a
   single-answer question is read top to bottom. Putting four long options
   side by side would apply the pattern and damage the thing it is applied to. */
.choice-row { grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); align-items: stretch; }
.choice-row .choice-pill { align-items: flex-start; }

.chain-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 10px; margin: 0; padding: 0; list-style: none; counter-reset: chain; }
.chain-cards li { counter-increment: chain; display: grid; gap: 6px; align-content: start; padding: 13px 14px; background: white; border: 1px solid var(--line); border-radius: 9px; }
/* The number is generated, so a reordered chain cannot end up mislabeled. */
.chain-cards li::before { content: counter(chain); color: var(--accent); font-family: var(--mono); font-size: 10px; font-weight: 700; }
.chain-cards li span { color: var(--ink); font-size: 12.5px; line-height: 1.45; }

@media (max-width: 620px) {
  .choice-row, .chain-cards { grid-template-columns: 1fr; }
}
/* --- The avatar is the way to the account page ------------------------------
   Both initials circles link to #account: the one in the sidebar footer and the
   one in the top bar. They used to be aria-hidden decoration sitting next to a
   "›" link that did the work, which meant the largest, most obvious target in
   each corner was the one thing that was not clickable.

   The chevron is gone, so the avatars are now the only route to the account
   page from the chrome — they carry a real label rather than the initials,
   which are a decorative restatement of the name printed beside them. */
a.avatar, a.mini-avatar { text-decoration: none; cursor: pointer; }
a.avatar:hover, a.mini-avatar:hover { background: var(--accent); }
a.avatar:focus-visible, a.mini-avatar:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* Two columns now the chevron's `auto` track has nothing in it. */
.sidebar-profile { grid-template-columns: 36px 1fr; }
/* The whole profile row is the link, not the avatar and the name separately —
   one target and one tab stop rather than two that go to the same place. The
   avatar goes back to being decoration inside it; the accessible name comes
   from the row's own text, prefixed so it says where it goes rather than
   reading as "Pilot learner Not signed in". */
a.sidebar-profile { color: inherit; text-decoration: none; border-radius: 9px; }
a.sidebar-profile:hover { background: var(--foam); }
a.sidebar-profile:hover .avatar { background: var(--accent); }
a.sidebar-profile:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* The topbar wordmark goes to the course home, the same destination as the
   brand in the sidebar. A label rather than the visible text, because the
   institution half is display:none below the breakpoint — an accessible name
   built from the text would have changed with the viewport. */
a.crumb { color: var(--muted); text-decoration: none; border-radius: 7px; }
a.crumb:hover strong { color: var(--accent); }
a.crumb:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
/* The sidebar brand has always been a link. It just did not look like one:
   no hover feedback, while the wordmark and profile row beside it now have it.
   Matching them, so the three targets in the chrome behave alike. */
.brand:hover strong { color: var(--accent); }
.brand:hover .brand-mark { box-shadow: 0 0 0 2px var(--accent-line); }
.brand:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 9px; }

.notice-panel {
  position: absolute;
  right: clamp(16px, 4vw, 32px);
  top: 72px;
  z-index: 40;
  width: min(420px, calc(100vw - 32px));
  max-height: min(70vh, 520px);
  overflow: auto;
  padding: 16px 16px 12px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.notice-panel[hidden] { display: none; }
.notice-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.notice-panel-head h2 { margin: 0; font-size: 15px; }
.notice-list, .notice-published { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.notice-list li, .notice-published li { padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--foam); }
.notice-list li.unread { border-color: var(--accent-line); background: var(--accent-soft); }
.notice-list p, .notice-published p { margin: 6px 0 0; color: var(--ink-soft, var(--muted)); font-size: 13px; }
.notice-kicker { margin: 0; color: var(--accent); font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.notice-compose-grid { display: grid; grid-template-columns: 88px 1fr; gap: 12px; }
.notice-compose-grid .field:last-child { min-width: 0; }
.field textarea, .field input[type="number"], .field input[type="date"] {
  min-height: 44px; padding: 10px 12px; border: 1px solid var(--line-strong);
  border-radius: 8px; background: var(--surface); color: var(--ink); font: inherit;
}
.field textarea { min-height: 96px; resize: vertical; }
.notification-dot[hidden] { display: none; }
.page-shell { position: relative; }
@media (max-width: 720px) {
  .notice-compose-grid { grid-template-columns: 1fr; }
}
