/* =============================================================
   TONE — Hair Colour Education Platform
   Editorial design system
   Typography: Fraunces (display serif) · Inter (sans) · JetBrains Mono (metadata)
   Spacing:    Fibonacci scale (1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144)
   Palette:    Bone ground · Deep ink · Oxblood accent · Champagne tertiary
   ============================================================= */

:root {
  /* ---- Palette ---- */
  --bone:        #F3EEE4;   /* primary ground */
  --paper:       #E8E1D1;   /* secondary surface */
  --cream:       #FAF6EE;   /* elevated surface */
  --ink:         #141110;   /* primary text */
  --ink-2:       #3A332E;   /* secondary text */
  --ink-3:       #776C62;   /* tertiary / caption */
  --line:        #C9BFAD;   /* divider */
  --line-soft:   #DDD4C2;   /* subtle divider */
  --oxblood:     #5A1918;   /* luxe accent */
  --oxblood-2:   #7A2823;   /* hover */
  --champagne:   #B99B6B;   /* tertiary gold */
  --sage:        #7D8A78;   /* success */
  --clay:        #A64B2A;   /* rare accent */
  --alert:       #8B2418;   /* error */

  /* ---- Fibonacci spacing (px) ---- */
  --s-1:   1px;
  --s-2:   2px;
  --s-3:   3px;
  --s-5:   5px;
  --s-8:   8px;
  --s-13:  13px;
  --s-21:  21px;
  --s-34:  34px;
  --s-55:  55px;
  --s-89:  89px;
  --s-144: 144px;
  --s-233: 233px;

  /* ---- Typography ---- */
  --serif:   'Fraunces', 'Didot', 'Times New Roman', serif;
  --sans:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono:    'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace;

  /* ---- Motion ---- */
  --ease:    cubic-bezier(.2, .7, .2, 1);
  --fast:    180ms;
  --med:     320ms;
  --slow:    560ms;
}

/* ===== Reset ===== */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bone);
  font-feature-settings: "ss01", "cv11";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}
img, svg, video { display: block; max-width: 100%; }
button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; }
input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--ink); color: var(--bone); }

/* ===== Typography primitives ===== */
.display {
  font-family: var(--serif);
  font-weight: 300;
  font-style: normal;
  letter-spacing: -0.02em;
  line-height: 0.92;
  font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0;
}
.display-xxl {
  font-family: var(--serif);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 0.88;
  font-size: clamp(64px, 12vw, 180px);
  font-variation-settings: "opsz" 144;
}
.display-xl {
  font-family: var(--serif);
  font-weight: 300;
  letter-spacing: -0.025em;
  line-height: 0.9;
  font-size: clamp(44px, 7.5vw, 104px);
  font-variation-settings: "opsz" 144;
}
.display-l {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 0.98;
  font-size: clamp(32px, 5vw, 56px);
}
.display-m {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.05;
  font-size: clamp(26px, 3.2vw, 38px);
}
.display-italic { font-style: italic; font-weight: 300; }

.eyebrow, .meta, .code {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.meta-ink { color: var(--ink); }
.dot::before { content: "·"; margin: 0 var(--s-8); color: var(--line); }

.body-lg { font-size: 17px; line-height: 1.6; color: var(--ink-2); }
.body    { font-size: 15px; line-height: 1.6; color: var(--ink-2); }
.body-sm { font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.caption { font-size: 12px; color: var(--ink-3); letter-spacing: 0.01em; }

h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 400; }

/* ===== Layout primitives ===== */
.page { min-height: 100vh; display: flex; flex-direction: column; }
.container { width: 100%; max-width: 1440px; margin: 0 auto; padding: 0 var(--s-34); }
.container-lg { max-width: 1600px; margin: 0 auto; padding: 0 var(--s-34); }
.section { padding: var(--s-89) 0; }

.divider { height: 1px; background: var(--line); border: 0; margin: 0; }
.divider-soft { height: 1px; background: var(--line-soft); border: 0; margin: 0; }

/* Fibonacci-guided editorial grid: 5 + 8 + 13 + 21 + 34 = 81 column-units per row */
.grid-fib {
  display: grid;
  grid-template-columns: 5fr 8fr 13fr 21fr 34fr;
  gap: var(--s-34);
}
@media (max-width: 900px) {
  .grid-fib { grid-template-columns: 1fr; gap: var(--s-34); }
}

.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-55); }
.three-col { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-34); }
@media (max-width: 900px) {
  .two-col, .three-col { grid-template-columns: 1fr; gap: var(--s-34); }
}

/* ===== Header / Nav ===== */
.nav {
  position: sticky; top: 0; z-index: 40;
  background: rgba(243, 238, 228, 0.88);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: 72px; padding: 0 var(--s-34);
}
.brand {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 24px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.brand em { font-style: italic; font-weight: 300; }
.nav-links { display: flex; align-items: center; gap: var(--s-34); }
.nav-link {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: color var(--fast);
  padding: var(--s-8) 0;
  border-bottom: 1px solid transparent;
}
.nav-link:hover, .nav-link.active { color: var(--ink); border-bottom-color: var(--ink); }

/* ===== Buttons ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-8);
  padding: 14px 26px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1;
  border: 1px solid var(--ink);
  color: var(--ink);
  background: transparent;
  transition: all var(--med) var(--ease);
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.btn:hover { background: var(--ink); color: var(--bone); }
.btn[disabled] { opacity: 0.4; pointer-events: none; }

.btn-primary {
  background: var(--ink); color: var(--bone);
}
.btn-primary:hover { background: var(--oxblood); border-color: var(--oxblood); }

.btn-oxblood {
  background: var(--oxblood); border-color: var(--oxblood); color: var(--bone);
}
.btn-oxblood:hover { background: var(--oxblood-2); border-color: var(--oxblood-2); }

.btn-ghost {
  border-color: var(--line);
  color: var(--ink-2);
}
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); background: transparent; }

.btn-sm { padding: 10px 18px; font-size: 10px; }
.btn-lg { padding: 18px 34px; font-size: 12px; }
.btn-block { width: 100%; }

/* Underline link */
.u-link {
  position: relative;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  transition: color var(--fast);
}
.u-link:hover { color: var(--oxblood); border-color: var(--oxblood); }

/* ===== Cards / Surfaces ===== */
.card {
  background: var(--cream);
  border: 1px solid var(--line-soft);
  padding: var(--s-34);
  transition: border-color var(--med), transform var(--med);
}
.card:hover { border-color: var(--line); }
.card-ink {
  background: var(--ink); color: var(--bone);
  padding: var(--s-34);
}
.card-oxblood {
  background: var(--oxblood); color: var(--bone);
  padding: var(--s-34);
}
.card-paper {
  background: var(--paper);
  padding: var(--s-34);
}

/* ===== Forms ===== */
.field { display: flex; flex-direction: column; gap: var(--s-8); margin-bottom: var(--s-21); }
.field label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.field input, .field textarea, .field select {
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  padding: 10px 0 12px;
  font-family: var(--sans);
  font-size: 16px;
  color: var(--ink);
  outline: none;
  transition: border-color var(--fast);
  border-radius: 0;
}
.field input:focus, .field textarea:focus, .field select:focus {
  border-bottom-color: var(--ink);
}
.field textarea { min-height: 96px; resize: vertical; }
.field .hint { font-size: 12px; color: var(--ink-3); margin-top: 2px; }
.field .error { font-size: 12px; color: var(--alert); margin-top: 4px; }

.checkbox, .radio {
  display: flex; align-items: center; gap: var(--s-13);
  font-size: 14px; color: var(--ink-2);
  cursor: pointer;
}
.checkbox input, .radio input {
  appearance: none;
  width: 16px; height: 16px;
  border: 1px solid var(--line);
  background: var(--cream);
  position: relative;
  cursor: pointer;
}
.radio input { border-radius: 50%; }
.checkbox input:checked, .radio input:checked { background: var(--ink); border-color: var(--ink); }
.checkbox input:checked::after {
  content: ""; position: absolute; inset: 3px;
  background: var(--bone);
}
.radio input:checked::after {
  content: ""; position: absolute; inset: 4px; border-radius: 50%;
  background: var(--bone);
}

/* Role toggle (segmented) */
.segment {
  display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--ink);
}
.segment button {
  padding: 14px 12px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  transition: all var(--fast);
  border-right: 1px solid var(--ink);
}
.segment button:last-child { border-right: 0; }
.segment button[aria-selected="true"] { background: var(--ink); color: var(--bone); }

/* ===== Pills / Chips / Tags (ID style from the trend report) ===== */
.tag {
  display: inline-flex; align-items: center; gap: var(--s-5);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 4px 10px;
  border: 1px solid var(--line);
  color: var(--ink-2);
  background: transparent;
}
.tag::before {
  content: ""; display: inline-block;
  width: 6px; height: 6px; background: var(--ink);
}
.tag-oxblood::before { background: var(--oxblood); }
.tag-sage::before { background: var(--sage); }
.tag-clay::before { background: var(--clay); }
/* V61: PARTIAL status — warm amber, signals shipped-with-caveats. */
.tag-partial {
  color: var(--warn, #a87a1d);
  border-color: var(--warn, #a87a1d);
}
.tag-partial::before { background: var(--warn, #a87a1d); }
.tag-filled {
  background: var(--ink); color: var(--bone); border-color: var(--ink);
}
.tag-filled::before { background: var(--bone); }

.pill {
  display: inline-flex; align-items: center;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-2);
}

/* ===== Section code (1.1 DIRECT FLASH style) ===== */
.section-code {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: inline-flex; gap: var(--s-13);
  align-items: center;
}
.section-code .num { color: var(--ink); }

/* ===== Table ===== */
.table {
  width: 100%;
  border-collapse: collapse;
}
.table th, .table td {
  padding: var(--s-21) var(--s-13);
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14px;
  vertical-align: middle;
}
.table th {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 400;
}
.table tr:hover td { background: rgba(234, 227, 209, 0.35); }

/* ===== Modal ===== */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(20, 17, 16, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-21);
  animation: fade var(--med) var(--ease);
}
.modal {
  background: var(--bone);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow: auto;
  border: 1px solid var(--line);
  padding: var(--s-55);
  animation: rise var(--med) var(--ease);
}
.modal-wide { max-width: 880px; }
.modal-close {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ===== Animations ===== */
@keyframes fade  { from {opacity: 0;} to {opacity: 1;} }
@keyframes rise  { from {opacity: 0; transform: translateY(12px);} to {opacity: 1; transform: translateY(0);} }
@keyframes slide { from {opacity: 0; transform: translateY(24px);} to {opacity: 1; transform: translateY(0);} }

.fade-in { animation: fade var(--med) var(--ease); }
.slide-in { animation: slide var(--slow) var(--ease); }

/* ===== Dashboard layout ===== */
.app-shell {
  display: grid;
  grid-template-columns: 233px 1fr;
  min-height: 100vh;
}
.sidebar {
  border-right: 1px solid var(--line-soft);
  background: var(--paper);
  padding: var(--s-34) var(--s-21);
  display: flex; flex-direction: column;
  gap: var(--s-34);
  position: sticky; top: 0; height: 100vh;
}
.sidebar-brand {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 400;
  letter-spacing: -0.01em;
}
.side-nav { display: flex; flex-direction: column; gap: var(--s-3); }
.side-link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px var(--s-13);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  border-left: 2px solid transparent;
  transition: all var(--fast);
}
.side-link:hover { background: rgba(20,17,16,0.04); color: var(--ink); }
.side-link.active { border-left-color: var(--ink); color: var(--ink); background: rgba(20,17,16,0.05); }
.side-link .count {
  font-size: 10px; color: var(--ink-3);
  padding: 2px 6px; background: var(--cream);
  border: 1px solid var(--line-soft);
}
.main {
  padding: var(--s-55) var(--s-55) var(--s-144);
  background: var(--bone);
  overflow-x: hidden;
}
@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; }
  .sidebar {
    position: relative; height: auto;
    flex-direction: row; align-items: center;
    gap: var(--s-21); padding: var(--s-21);
    overflow-x: auto;
  }
  .side-nav { flex-direction: row; gap: var(--s-13); }
  .side-link { border-left: 0; border-bottom: 2px solid transparent; padding: 8px 12px; }
  .side-link.active { border-left: 0; border-bottom-color: var(--ink); }
  .main { padding: var(--s-34) var(--s-21) var(--s-89); }
}

/* ===== Hero ===== */
.hero {
  padding: var(--s-89) 0 var(--s-144);
  position: relative;
  overflow: hidden;
}
.hero-word {
  font-family: var(--serif);
  font-size: clamp(80px, 16vw, 260px);
  font-weight: 300;
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: var(--ink);
  display: block;
}
.hero-word em { font-style: italic; font-weight: 300; }

/* ===== Utility ===== */
.muted { color: var(--ink-3); }
.ink { color: var(--ink); }
.oxblood { color: var(--oxblood); }
.champagne { color: var(--champagne); }

.border { border: 1px solid var(--line); }
.border-t { border-top: 1px solid var(--line-soft); }
.border-b { border-bottom: 1px solid var(--line-soft); }
.border-soft { border: 1px solid var(--line-soft); }

.flex { display: flex; }
.ai-c { align-items: center; }
.ai-s { align-items: flex-start; }
.ai-e { align-items: flex-end; }
.jc-sb { justify-content: space-between; }
.jc-c  { justify-content: center; }
.jc-e  { justify-content: flex-end; }
.fd-c  { flex-direction: column; }
.fw-w  { flex-wrap: wrap; }

.gap-3  { gap: 3px; }
.gap-5  { gap: 5px; }
.gap-8  { gap: 8px; }
.gap-13 { gap: 13px; }
.gap-21 { gap: 21px; }
.gap-34 { gap: 34px; }
.gap-55 { gap: 55px; }

.mt-8  { margin-top: 8px; }
.mt-13 { margin-top: 13px; }
.mt-21 { margin-top: 21px; }
.mt-34 { margin-top: 34px; }
.mt-55 { margin-top: 55px; }
.mt-89 { margin-top: 89px; }

.mb-8  { margin-bottom: 8px; }
.mb-13 { margin-bottom: 13px; }
.mb-21 { margin-bottom: 21px; }
.mb-34 { margin-bottom: 34px; }
.mb-55 { margin-bottom: 55px; }

.w-full { width: 100%; }
.ta-c   { text-align: center; }
.ta-r   { text-align: right; }

.hide-sm { }
@media (max-width: 900px) { .hide-sm { display: none !important; } }
.hide-lg { display: none; }
@media (max-width: 900px) { .hide-lg { display: block; } }

/* Loading */
.spinner {
  width: 24px; height: 24px;
  border: 1.5px solid var(--line);
  border-top-color: var(--ink);
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Progress bar */
.progress {
  height: 2px; background: var(--line-soft); width: 100%; position: relative;
}
.progress > span {
  display: block; height: 100%; background: var(--ink);
  transition: width var(--med) var(--ease);
}

/* Avatar (initial) */
.avatar {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 16px; color: var(--ink);
  flex-shrink: 0;
}
.avatar-lg { width: 64px; height: 64px; font-size: 22px; }
.avatar-sm { width: 28px; height: 28px; font-size: 12px; }

/* Toast */
.toast {
  position: fixed; bottom: var(--s-34); right: var(--s-34); z-index: 200;
  background: var(--ink); color: var(--bone);
  padding: var(--s-13) var(--s-21);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  animation: rise var(--med) var(--ease);
}
.toast.err { background: var(--alert); }
.toast.ok  { background: var(--ink); }

/* Resource media tile */
.tile {
  background: var(--cream);
  border: 1px solid var(--line-soft);
  padding: var(--s-21);
  display: flex; flex-direction: column; gap: var(--s-13);
  transition: all var(--med) var(--ease);
  cursor: pointer;
  min-height: 180px;
  position: relative;
}
.tile:hover { border-color: var(--ink); transform: translateY(-2px); }
.tile-type {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.tile-title {
  font-family: var(--serif);
  font-size: 20px;
  line-height: 1.15;
  color: var(--ink);
  margin: var(--s-5) 0 auto;
}
.tile-foot {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12px; color: var(--ink-3);
}

/* Quiz option */
.quiz-opt {
  display: flex; align-items: center; gap: var(--s-13);
  padding: var(--s-21);
  border: 1px solid var(--line);
  background: var(--cream);
  cursor: pointer;
  transition: all var(--fast);
  margin-bottom: var(--s-13);
}
.quiz-opt:hover { border-color: var(--ink-2); }
.quiz-opt.selected { border-color: var(--ink); background: var(--paper); }
.quiz-opt .letter {
  width: 32px; height: 32px;
  border: 1px solid var(--line);
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 11px;
  background: var(--bone);
  flex-shrink: 0;
}
.quiz-opt.selected .letter { background: var(--ink); color: var(--bone); border-color: var(--ink); }

/* Stat block */
.stat {
  padding: var(--s-34);
  background: var(--cream);
  border: 1px solid var(--line-soft);
}
.stat-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-13);
}
.stat-value {
  font-family: var(--serif);
  font-size: clamp(40px, 5vw, 64px);
  font-weight: 300;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -0.02em;
}
.stat-sub { font-size: 12px; color: var(--ink-3); margin-top: var(--s-8); }

/* Code block / credential chip (for educator codes) */
.credential {
  display: inline-flex; align-items: center; gap: var(--s-13);
  padding: var(--s-13) var(--s-21);
  background: var(--ink); color: var(--bone);
  font-family: var(--mono);
  letter-spacing: 0.18em;
  font-size: 14px;
  user-select: all;
}
.credential button {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; color: var(--bone);
  opacity: 0.6; padding: 2px 6px; border: 1px solid rgba(255,255,255,0.25);
}
.credential button:hover { opacity: 1; }

/* Pill — active state for filters */
.pill { cursor: pointer; transition: all var(--fast); }
.pill:hover { border-color: var(--ink); color: var(--ink); }
.pill-active {
  background: var(--ink); color: var(--bone); border-color: var(--ink);
}

/* Compact select (admin register, etc.) */
.select-mini {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 10px;
  border: 1px solid var(--line);
  background: var(--cream);
  color: var(--ink);
  outline: none;
  cursor: pointer;
}
.select-mini:focus { border-color: var(--ink); }

/* Table wrapper for mobile scroll */
.table-wrap { width: 100%; overflow-x: auto; }

/* Tile head (admin library detail) */
.tile-head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.tile-body { margin: 0; }

/* Smaller display — between display-m and body-lg */
.display-s {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.1;
  font-size: clamp(22px, 2.4vw, 28px);
}

/* ================================================================
   Additions for v3 — avatars, profile chip, media viewer,
   student detail, clickable cards, larger avatars.
   ================================================================ */

/* Extra avatar size */
.avatar-xl {
  width: 96px; height: 96px; font-size: 34px;
}

/* Clickable card (roster link) */
.card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: all var(--med) var(--ease);
}
.card-link:hover {
  border-color: var(--ink);
  transform: translateY(-2px);
}
.card-link .chev {
  font-family: var(--serif);
  font-size: 22px;
  color: var(--ink-3);
  transition: transform var(--fast), color var(--fast);
}
.card-link:hover .chev {
  transform: translateX(4px);
  color: var(--ink);
}

/* Profile chip in the sidebar */
.profile-chip {
  display: flex;
  align-items: center;
  gap: var(--s-13);
  padding: var(--s-13);
  border: 1px solid var(--line-soft);
  background: var(--cream);
  text-decoration: none;
  color: inherit;
  transition: all var(--fast);
}
.profile-chip:hover {
  border-color: var(--ink);
  background: var(--paper);
}
.profile-name {
  font-family: var(--serif);
  font-size: 15px;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.profile-role {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 2px;
}

/* Avatar upload (settings page) */
.avatar-upload {
  position: relative;
  width: 160px; height: 160px;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
  border: 1px solid var(--line);
  background: var(--paper);
  flex-shrink: 0;
  transition: all var(--med) var(--ease);
}
.avatar-upload:hover { border-color: var(--ink); }
.avatar-upload img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.avatar-upload-initials {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif);
  font-size: 64px;
  font-weight: 300;
  color: var(--ink);
  letter-spacing: -0.02em;
}
.avatar-upload-overlay {
  position: absolute; inset: 0;
  background: rgba(20,17,16,0.75);
  color: var(--bone);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0;
  transition: opacity var(--fast);
}
.avatar-upload:hover .avatar-upload-overlay { opacity: 1; }

/* View-as banner (admin impersonation) */
.view-as-banner {
  background: var(--oxblood);
  color: var(--bone);
  padding: var(--s-13) var(--s-21);
  margin: calc(var(--s-55) * -1) calc(var(--s-55) * -1) var(--s-34);
  border-bottom: 1px solid rgba(243,238,228,0.2);
}
@media (max-width: 900px) {
  .view-as-banner { margin: calc(var(--s-34) * -1) calc(var(--s-21) * -1) var(--s-21); }
}
.view-as-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-13); flex-wrap: wrap;
}
.view-as-role {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  padding: 4px 10px;
  border: 1px solid rgba(243,238,228,0.3);
  color: var(--bone);
}
.view-as-exit {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  background: var(--bone);
  color: var(--ink);
  border: 1px solid var(--bone);
  padding: 10px 18px;
  cursor: pointer;
  transition: all var(--fast);
}
.view-as-exit:hover { background: transparent; color: var(--bone); }

/* Media viewer frames */
.media-body { display: flex; flex-direction: column; }
.media-frame {
  width: 100%;
  background: var(--ink);
  border: 1px solid var(--line);
  overflow: hidden;
}
.media-frame-video {
  aspect-ratio: 16/9;
}
.media-frame-pdf {
  height: min(72vh, 800px);
  background: var(--bone);
}
.media-frame-image {
  background: var(--bone);
  padding: var(--s-21);
  display: flex; align-items: center; justify-content: center;
}

/* Print suppression */
@media print { .nav, .sidebar, .no-print, .app-shell > aside { display: none !important; } }

/* ============================================================
   MODULES — curriculum card lists
   ============================================================ */
.lesson-list {
  list-style: none;
  margin: 21px 0 0;
  padding: 0;
  border-top: 1px solid var(--line-soft);
}
.lesson-list li {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 15px;
  color: var(--ink-1);
}
.lesson-type {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  min-width: 56px;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 2px;
  text-align: center;
}
.lesson-title { flex: 1; font-family: var(--serif); font-size: 17px; }
.lesson-status { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.link-list {
  border-top: 1px solid var(--line-soft);
}
.link-row {
  display: flex; align-items: center; gap: 13px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
  font-size: 15px;
}
.link-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--ink); }

/* Progress line under modules */
.progress-line {
  width: 100%;
  height: 3px;
  background: var(--line-soft);
  border-radius: 2px;
  overflow: hidden;
}
.progress-line-fill {
  height: 100%;
  background: var(--ink);
  transition: width 360ms ease;
}

/* ============================================================
   COMMENTS — media viewer discussion thread
   ============================================================ */
.media-thread { margin-top: 13px; }
.comment-list { display: flex; flex-direction: column; gap: 21px; margin-bottom: 21px; }
.comment {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}
.comment-body { flex: 1; min-width: 0; }
.comment-head {
  display: flex; gap: 13px; align-items: center;
  margin-bottom: 4px;
  font-size: 13px;
}
.comment-author {
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}
.comment-del {
  background: none; border: none;
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  cursor: pointer;
  padding: 0;
  margin-left: auto;
}
.comment-del:hover { color: var(--oxblood); }
.comment-form {
  display: flex; gap: 13px;
  padding: 21px 0;
  border-top: 1px solid var(--line-soft);
}
.comment-form textarea {
  width: 100%;
  resize: vertical;
}

/* ============================================================
   REPORT CARD + CERTIFICATE
   ============================================================ */
.report-page {
  min-height: 100vh;
  background: var(--paper);
  padding: var(--s-55);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-34);
}
.report-actions {
  width: 100%;
  max-width: 880px;
  display: flex; justify-content: space-between;
}
.report-paper {
  width: 100%;
  max-width: 880px;
  background: var(--bone);
  padding: var(--s-89);
  border: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(0,0,0,0.02);
}
.report-header {
  display: flex; justify-content: space-between; align-items: flex-end;
  margin-bottom: 34px;
  flex-wrap: wrap; gap: 21px;
}
.report-brand {
  font-family: var(--serif);
  font-size: 34px;
  font-style: italic;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.divider {
  border: none;
  border-top: 1px solid var(--ink);
  margin: 34px 0;
  opacity: 0.6;
}
.report-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-21);
}
.report-stat {
  padding: var(--s-21);
  border: 1px solid var(--line-soft);
  background: var(--paper);
}
.report-stat-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 8px;
}
.report-stat-value {
  font-family: var(--serif);
  font-size: 34px;
  letter-spacing: -0.02em;
  color: var(--ink);
  line-height: 1.05;
  margin-bottom: 4px;
}
.report-stat-sub {
  font-size: 12px;
  color: var(--ink-3);
}
.report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}
.report-table th,
.report-table td {
  padding: 13px 8px;
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
}
.report-table th {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.report-modules {
  list-style: none;
  padding: 0;
  margin: 0;
}
.report-modules li {
  display: flex; justify-content: space-between; align-items: center;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}
.report-module-title {
  font-family: var(--serif);
  font-size: 19px;
  color: var(--ink);
}
.report-module-status {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.10em;
  color: var(--ink-3);
}
.report-footer {
  margin-top: 55px;
  padding-top: 21px;
  border-top: 1px solid var(--line-soft);
  text-align: center;
}

/* Certificate */
.certificate {
  width: 100%;
  max-width: 880px;
  aspect-ratio: 11/8.5;
  background: var(--bone);
  padding: var(--s-89) var(--s-55);
  border: 1px solid var(--line);
  text-align: center;
  display: flex; flex-direction: column; justify-content: center;
  gap: var(--s-13);
  position: relative;
}
.cert-hairline {
  position: absolute; left: var(--s-34); right: var(--s-34); top: var(--s-21);
  height: 1px; background: var(--ink); opacity: 0.6;
}
.cert-hairline-bottom { top: auto; bottom: var(--s-21); }
.cert-eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.cert-ornament {
  font-size: 21px;
  color: var(--ink);
  margin: var(--s-13) 0;
}
.cert-title {
  font-family: var(--serif);
  font-style: italic;
  font-size: 55px;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
}
.cert-copy {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink-2);
  margin: 0;
}
.cert-name,
.cert-educator {
  font-family: var(--serif);
  font-size: 44px;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.cert-module {
  font-family: var(--serif);
  font-size: 27px;
  font-style: italic;
  color: var(--oxblood);
}
.cert-signature {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: var(--s-34);
}

/* Report print rules */
@media print {
  body { background: white; }
  .report-page { padding: 0; background: white; }
  .report-paper, .certificate {
    border: none;
    box-shadow: none;
    max-width: 100%;
    margin: 0;
    page-break-after: always;
  }
  .report-actions, .no-print { display: none !important; }
}

/* ============================================================
   Mobile polish — tighten padding, stack sidebar, bigger touch
   ============================================================ */
@media (max-width: 760px) {
  .app-shell {
    grid-template-columns: 1fr !important;
  }
  .app-shell > aside.sidebar {
    position: sticky;
    top: 0;
    z-index: 40;
    width: 100%;
    height: auto;
    padding: var(--s-13) var(--s-21);
    flex-direction: row;
    flex-wrap: wrap;            /* let the nav drop to a second row */
    align-items: center;
    overflow-x: visible;
    gap: var(--s-8);
    border-right: 0;
    border-bottom: 1px solid var(--line);
    background: var(--bone);
  }
  .app-shell > aside .sidebar-brand {
    flex-shrink: 0;
    margin-right: 0;
    font-size: 19px;
  }
  /* Nav takes its own row, full-width, horizontally scrollable */
  .app-shell > aside .side-nav {
    display: flex;
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    flex: 1 0 100%;             /* full row */
    order: 99;                  /* push below brand + profile */
    border: 0;
    padding: 0 0 4px 0;
    margin-top: 4px;
    /* hide ugly scrollbar on iOS */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .app-shell > aside .side-nav::-webkit-scrollbar { display: none; }
  .app-shell > aside .side-link {
    padding: 8px 14px;
    font-size: 13px;
    white-space: nowrap;
    border-radius: 100px;
    border: 1px solid var(--line-soft);
  }
  .app-shell > aside .side-link.active {
    background: var(--ink);
    color: var(--bone);
    border-color: var(--ink);
  }
  /* Profile chip wrapper — pushed to the far right of row 1 */
  .app-shell > aside > div:last-child {
    flex-shrink: 0;
    margin-top: 0 !important;
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--s-8);
  }
  .app-shell > aside > div:last-child > hr { display: none; }
  /* Compact the profile chip on phones — avatar + first name only */
  .app-shell > aside .profile-chip {
    padding: 4px 10px 4px 4px;
    gap: 8px;
    border-radius: 100px;
  }
  .app-shell > aside .profile-chip .profile-name { font-size: 13px; line-height: 1.1; }
  .app-shell > aside .profile-chip .profile-role { display: none; }
  .app-shell > aside > div:last-child .btn { display: none; }

  .main { padding: var(--s-13) !important; }
  .three-col { grid-template-columns: 1fr !important; }
  .two-col { grid-template-columns: 1fr !important; }

  /* v14: kill horizontal overflow everywhere */
  html, body { overflow-x: hidden; max-width: 100vw; }
  .app-shell { max-width: 100vw; overflow-x: hidden; }
  .main { max-width: 100%; overflow-x: hidden; }
  .card, .card-paper, .card-ink, .tile, article { max-width: 100%; overflow-wrap: anywhere; word-break: break-word; }
  table { max-width: 100%; display: block; overflow-x: auto; }
  pre, code { max-width: 100%; overflow-x: auto; white-space: pre-wrap; word-break: break-word; }
  img, canvas, video, iframe { max-width: 100%; height: auto; }

  /* Auth pages: collapse the editorial column, full-width form */
  main[style*="grid-template-columns: 1fr 1fr"],
  main[style*="grid-template-columns:1fr 1fr"] {
    grid-template-columns: 1fr !important;
  }
  main[style*="grid-template-columns: 1fr 1fr"] > section,
  main[style*="grid-template-columns:1fr 1fr"] > section {
    padding: var(--s-34) var(--s-21) !important;
  }

  /* Modal goes nearly full screen and never overflows */
  .modal-backdrop .modal { width: 100% !important; max-width: 100% !important; }

  /* Inputs/textareas/selects don't burst the viewport */
  input, textarea, select { max-width: 100%; }

  /* Header on mobile: stack title and actions */
  .app-shell .main > header { margin-bottom: var(--s-34) !important; }

  /* Quiz options need bigger tap area */
  .quiz-opt { padding: 14px 16px !important; }

  /* Settings + form rows */
  .field { margin-bottom: var(--s-13); }
  .display-xl { font-size: 44px !important; }
  .display-l  { font-size: 34px !important; }
  .display-m  { font-size: 27px !important; }
  .report-paper, .certificate { padding: var(--s-34) var(--s-21); }
  .report-stats { grid-template-columns: repeat(2, 1fr); }
  .cert-title { font-size: 40px; }
  .cert-name, .cert-educator { font-size: 28px; }
  .cert-module { font-size: 21px; }

  /* bigger tap targets */
  .btn { min-height: 44px; }
  .lesson-list li { padding: 13px 0; }

  /* modal full-bleed */
  .modal-backdrop .modal { margin: 0; max-height: 100vh; border-radius: 0; }
}

@media (max-width: 480px) {
  .report-stats { grid-template-columns: 1fr; }
  .display-xl { font-size: 34px !important; }
}

/* ============================================================
   v17 — Drawer nav + universal screen fit
   ============================================================ */

/* v20: Hamburger is a clear pill at the top — never overlaps content,
 * lives outside the main padding, sized for thumbs on phone. */
.nav-toggle {
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 60;
  min-width: 48px;
  height: 48px;
  padding: 0 13px;
  border: 1px solid var(--line);
  background: var(--bone);
  border-radius: 100px;
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  box-shadow: 0 2px 8px rgba(20,17,16,0.06);
}
.nav-toggle::before {
  content: "";
  display: inline-block;
  width: 16px; height: 12px;
  background-image:
    linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink));
  background-position: 0 0, 0 50%, 0 100%;
  background-size: 100% 1.5px;
  background-repeat: no-repeat;
  margin-right: 8px;
}
.nav-toggle span { display: none; }
.nav-toggle::after { content: "Menu"; }
.nav-toggle:hover { background: var(--cream); }
@media (max-width: 760px) {
  .nav-toggle { top: 12px; left: 12px; }
}

/* Scrim — only visible on phones when nav is open */
.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(20, 17, 16, 0.4);
  z-index: 45;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}

/* v19: drawer is ALWAYS fixed-position. The main content never shifts
 * when the drawer opens or closes — that prevents the "page goes weird"
 * jolt. The hamburger button sits permanently top-left; the drawer
 * slides in over the content with a scrim. Same behaviour on every
 * device — only the drawer width changes. */
.app-shell {
  display: block;
  min-height: 100vh;
}
.app-shell > .sidebar {
  position: fixed;
  top: 0; bottom: 0; left: 0;
  width: min(82vw, 280px);
  z-index: 50;
  background: var(--bone);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  padding: 21px;
  overflow-y: auto;
  transform: translateX(-100%);
  transition: transform 240ms ease;
  box-shadow: 0 0 28px rgba(0,0,0,0.18);
}
html.nav-open .app-shell > .sidebar { transform: translateX(0); }
html.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

/* Sidebar internals */
.sidebar-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 21px; }
.nav-collapse {
  border: 0; background: transparent; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--ink-3);
  width: 32px; height: 32px; border-radius: 6px;
}
.nav-collapse:hover { background: var(--cream); color: var(--ink); }

/* Main content — same padding regardless of drawer state */
.app-shell > .main {
  padding: 55px 55px 55px 70px;
  max-width: 100%;
  overflow-x: hidden;
}
@media (max-width: 1024px) {
  .app-shell > .main { padding: 40px 34px 34px 60px; }
}
@media (max-width: 760px) {
  .app-shell > .main { padding: 60px 16px 21px 16px; }
  .nav-toggle { top: 10px; left: 10px; }
}

/* Universal: kill horizontal overflow, no element can blow past viewport */
html, body { overflow-x: hidden; max-width: 100vw; }
body { padding: 0; margin: 0; }
* { box-sizing: border-box; }
.card, .card-paper, .card-ink, .tile, article, section, header, main {
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-word;
}
img, canvas, video, iframe, svg, picture { max-width: 100%; height: auto; }
table { max-width: 100%; display: block; overflow-x: auto; }
pre, code { max-width: 100%; overflow-x: auto; white-space: pre-wrap; }
input, textarea, select { max-width: 100%; }

/* "Read more" expandable description */
.read-more {
  display: inline;
}
.read-more-btn {
  background: none; border: 0; padding: 0;
  color: var(--oxblood); font-family: var(--mono); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase;
  cursor: pointer; margin-left: 8px;
}
.read-more-btn:hover { text-decoration: underline; }

/* Traffic light tags for targets */
.tag-green { background: #4F6F4A; color: var(--bone); border-color: #4F6F4A; }
.tag-amber { background: #B99B6B; color: var(--ink); border-color: #B99B6B; }
.tag-red   { background: #5A1918; color: var(--bone); border-color: #5A1918; }

/* Register table on mobile */
.register-table {
  width: 100%;
  border-collapse: collapse;
}
.register-table th, .register-table td {
  padding: 10px 13px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
.register-table th { font-family: var(--mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); text-align: left; }
@media (max-width: 760px) {
  .register-table { font-size: 13px; }
  .register-table th, .register-table td { padding: 8px; }
}

/* PWA install prompt */
.pwa-install {
  position: fixed;
  bottom: 21px; right: 21px;
  z-index: 200;
  padding: 13px 21px;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0,0,0,0.15);
}
.pwa-install:hover { background: var(--oxblood); }

/* ============================================================
   v28 — Aesthetic polish & PWA-grade interactions
   ============================================================ */

/* Smoother system-wide */
html { scroll-behavior: smooth; }
* { -webkit-tap-highlight-color: rgba(20,17,16,0.06); }

/* Page-level fade-in is already there; refine timing + add slide */
.fade-in {
  animation: fadeUp 320ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Cards lift gently on hover; feels alive but quiet */
.card, .card-paper, .tile, article.card {
  transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  a.card:hover,
  article.card:not([style*="cursor: pointer"]):hover,
  a.card-link:hover,
  .tile:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(20,17,16,0.06);
    border-color: var(--line);
  }
}

/* Buttons: subtle depress on click, smoother colour change */
.btn {
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease, transform 80ms ease;
}
.btn:active { transform: translateY(1px); }

/* Pills + tags: same treatment */
.pill, .tag {
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}

/* Quiet, accessible focus rings — visible only via keyboard */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 3px;
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 0;
  border-color: var(--ink) !important;
}

/* Form fields: smoother focus border */
input, textarea, select {
  transition: border-color 140ms ease, background 140ms ease;
}

/* Scrollbar — thin, on-brand, only visible on hover (desktop) */
@media (hover: hover) {
  * { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
  *::-webkit-scrollbar { width: 8px; height: 8px; }
  *::-webkit-scrollbar-thumb { background: var(--line-soft); border-radius: 100px; }
  *::-webkit-scrollbar-thumb:hover { background: var(--line); }
  *::-webkit-scrollbar-track { background: transparent; }
}

/* Loading shell: refine the boot animation */
.spinner {
  width: 28px; height: 28px;
  border-radius: 100%;
  border: 1.5px solid var(--line-soft);
  border-top-color: var(--ink);
  animation: spin 720ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Top progress bar shown while a route loads */
#route-progress {
  position: fixed; top: 0; left: 0; right: 0;
  height: 2px; background: var(--ink);
  transform-origin: left; transform: scaleX(0);
  transition: transform 220ms ease, opacity 220ms ease;
  opacity: 0; z-index: 100; pointer-events: none;
}
#route-progress.start { transform: scaleX(0.3); opacity: 1; }
#route-progress.midway { transform: scaleX(0.7); }
#route-progress.done { transform: scaleX(1); opacity: 0; }

/* Empty-state polish */
.card[style*="textAlign: \"center\""],
.card[style*="textAlign: 'center'"] {
  border-style: dashed;
}

/* iOS safe-area awareness */
.app-shell > .main {
  padding-top: max(55px, env(safe-area-inset-top, 0px));
  padding-bottom: max(34px, env(safe-area-inset-bottom, 0px));
}
@media (max-width: 760px) {
  .app-shell > .main {
    padding-top: max(60px, env(safe-area-inset-top, 0px));
    padding-bottom: max(21px, env(safe-area-inset-bottom, 0px));
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
  }
  .nav-toggle { top: max(12px, env(safe-area-inset-top, 0px)); }
}

/* Standalone-mode polish: hide the install button when already installed */
@media all and (display-mode: standalone) {
  .pwa-install { display: none !important; }
  body { background: var(--bone); }
}

/* Reduced-motion respect */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  html { scroll-behavior: auto; }
}

/* =============================================================
   v36.2 — collapsible nav groups
   Renders each group as a <details> element; the summary is a
   small uppercase label with a chevron that rotates on toggle.
   Direct children of .side-nav still flow vertically.
   ========================================================== */
.side-nav-group { display: flex; flex-direction: column; gap: var(--s-3); }
.side-nav-group + .side-nav-group { margin-top: 4px; }

/* Hide the native disclosure marker (Safari + Firefox + Chrome). */
.side-nav-group-head { list-style: none; }
.side-nav-group-head::-webkit-details-marker { display: none; }
.side-nav-group-head::marker { content: ""; }

.side-nav-group-head {
  display: flex; align-items: center; justify-content: space-between;
  cursor: pointer;
  padding: 10px var(--s-13) 6px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
  user-select: none;
  transition: color var(--fast);
}
.side-nav-group-head:hover { color: var(--ink); }
.side-nav-group.has-active > .side-nav-group-head { color: var(--ink); }

.side-nav-group-chev {
  font-size: 11px;
  transition: transform 200ms ease;
  display: inline-block;
}
.side-nav-group:not([open]) > .side-nav-group-head .side-nav-group-chev {
  transform: rotate(-90deg);
}

.side-nav-group-list {
  display: flex; flex-direction: column; gap: var(--s-3);
}

/* v37.5: the legacy "horizontal pill" rail is gone — phone uses a
 * vertical slide-out drawer just like desktop. Group headers must
 * remain visible at every width so apprentices can actually expand
 * the groups they want. */

/* =============================================================
   v37 — Welcome screen (Mendell × Vidakovic × Baldinger)
   Single-page typographic poster. No marketing scroll, no hero
   media. The masthead carries the entire emotional weight; the
   two routes are quiet rules under it.
   ========================================================== */
.welcome {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bone);
  color: var(--ink);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(20px, 4vw, 55px);
  padding-top: max(env(safe-area-inset-top), clamp(20px, 4vw, 55px));
  padding-bottom: max(env(safe-area-inset-bottom), clamp(20px, 4vw, 55px));
  padding-left: max(env(safe-area-inset-left), clamp(20px, 4vw, 55px));
  padding-right: max(env(safe-area-inset-right), clamp(20px, 4vw, 55px));
  overflow: hidden;
}
.welcome-strip {
  display: grid;
  align-items: center;
  gap: clamp(8px, 1.5vw, 21px);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.welcome-strip-top {
  grid-template-columns: auto 1fr auto 1fr auto;
  padding-bottom: clamp(20px, 3vw, 34px);
  border-bottom: 1px solid var(--line-soft);
}
.welcome-strip-bot {
  grid-template-columns: auto 1fr auto;
  padding-top: clamp(20px, 3vw, 34px);
  border-top: 1px solid var(--line-soft);
}
.welcome-rule {
  height: 1px;
  background: var(--line-soft);
  min-width: 8px;
}
.welcome-num {
  font-weight: 600;
  color: var(--ink);
}

.welcome-stage {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  align-items: center;
  gap: clamp(34px, 5vw, 89px);
  padding: clamp(34px, 6vw, 89px) 0;
  min-height: 0;
}

.welcome-mark-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(13px, 2vw, 21px);
  min-width: 0;
}
.welcome-mark {
  font-family: var(--serif);
  font-size: clamp(64px, 14vw, 220px);
  font-weight: 400;
  line-height: 0.84;
  letter-spacing: -0.045em;
  margin: 0;
  word-break: break-word;
}
.welcome-welcome {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 2.6vw, 34px);
  font-weight: 300;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
}
.welcome-em-rule {
  font-style: normal;
  color: var(--ink-3);
  letter-spacing: 0;
}

.welcome-routes {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--ink);
}
.welcome-route {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: clamp(13px, 2vw, 21px);
  padding: clamp(18px, 2.6vw, 28px) clamp(2px, 1.2vw, 14px);
  border-bottom: 1px solid var(--ink);
  text-decoration: none;
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  transition: background 220ms ease, color 220ms ease, padding 220ms ease;
  min-width: 0;
}
.welcome-route:hover,
.welcome-route:focus-visible {
  background: var(--ink);
  color: var(--bone);
  padding-left: clamp(14px, 2.2vw, 26px);
  outline: none;
}
.welcome-route:hover .welcome-route-num,
.welcome-route:focus-visible .welcome-route-num { color: rgba(243, 238, 228, 0.55); }
.welcome-route:hover .welcome-route-arrow,
.welcome-route:focus-visible .welcome-route-arrow { transform: translateX(8px); }
.welcome-route-num {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--ink-3);
  align-self: center;
}
.welcome-route-label {
  font-family: var(--serif);
  font-size: clamp(26px, 4.2vw, 48px);
  font-weight: 400;
  letter-spacing: -0.022em;
  line-height: 1.05;
  word-break: break-word;
}
.welcome-route-arrow {
  font-family: var(--serif);
  font-size: clamp(26px, 4.2vw, 48px);
  align-self: center;
  transition: transform 220ms ease;
}

/* Phone — single column, masthead leans large, routes stay tappable */
@media (max-width: 760px) {
  .welcome-stage {
    grid-template-columns: 1fr;
    gap: clamp(28px, 6vw, 55px);
    padding: clamp(28px, 7vw, 55px) 0;
  }
  .welcome-mark { font-size: clamp(72px, 19vw, 130px); }
  .welcome-welcome { font-size: clamp(18px, 5vw, 24px); }
  .welcome-route-label { font-size: clamp(24px, 7vw, 32px); }
  .welcome-route-arrow { font-size: clamp(24px, 7vw, 32px); }
  /* Drop the privacy line on the top strip on phone — keep eyebrow only. */
  .welcome-strip-top {
    grid-template-columns: auto 1fr auto;
    font-size: 9px;
  }
  .welcome-strip-top > .welcome-rule:nth-of-type(2),
  .welcome-strip-top > .welcome-priv { display: none; }
  .welcome-strip-bot {
    grid-template-columns: 1fr;
    text-align: center;
  }
  .welcome-strip-bot > .welcome-rule,
  .welcome-strip-bot > .welcome-priv { display: none; }
}

/* =============================================================
   v37 — Phone polish.
   Tighter side padding, smaller display sizes at the lowest tier,
   16px form inputs to stop iOS auto-zoom on focus (the single
   biggest cause of "everything goes disproportioned" on phone),
   stackable two-column rows.
   ========================================================== */
@media (max-width: 760px) {
  /* Page chrome — far less side padding than desktop */
  .main { padding: 24px 16px 80px; }
  .container, .container-md, .container-lg { padding-inline: 16px; }

  /* Cards step down */
  .card, .card-paper { padding: 18px 18px; }

  /* Headlines — tighter than the existing 900px tier */
  .display-xl { font-size: 38px !important; line-height: 0.95; }
  .display-l  { font-size: 30px !important; line-height: 1.0; }
  .display-m  { font-size: 24px !important; line-height: 1.1; }
  .display-s  { font-size: 20px !important; line-height: 1.15; }

  /* Two-col rows always stack on phone */
  .two-col { grid-template-columns: 1fr !important; gap: 13px !important; }

  /* iOS Safari zooms when a focused input has font-size below 16px,
     which then breaks every other proportion on the page. Lock to 16px. */
  input, textarea, select { font-size: 16px !important; }

  /* Modals fill the viewport, no awkward gutter */
  .modal { padding: 20px !important; }
  .modal-backdrop .modal { margin: 0; max-height: 100vh; max-height: 100dvh; border-radius: 0; }

  /* Buttons hit a 44px tap target and never overflow on a single line */
  .btn { min-height: 44px; }
  .flex.gap-13 .btn,
  .flex.fw-w .btn { flex: 1 1 auto; min-width: 0; }
}

@media (max-width: 480px) {
  /* Tighter still on small phones */
  .main { padding: 20px 12px 64px; }
  .container, .container-md, .container-lg { padding-inline: 12px; }
  .card, .card-paper { padding: 14px 14px; }
  .display-xl { font-size: 32px !important; }
  .display-l  { font-size: 26px !important; }
  .display-m  { font-size: 21px !important; }
  .display-s  { font-size: 18px !important; }

  /* Section codes shrink so the eyebrow doesn't crowd headlines */
  .section-code, .meta { font-size: 9px; letter-spacing: 0.20em; }

  /* Hamburger sits closer to the corner */
  .nav-toggle { top: 10px; left: 10px; }
}

/* Make sure no fixed-width child can shove the page sideways. */
html, body { max-width: 100%; overflow-x: hidden; }
.main, .card, .card-paper, .container, .container-md, .container-lg { max-width: 100%; }
img, video, canvas { max-width: 100%; height: auto; }

/* =============================================================
   v37.1 — Phone topbar + design language across the app.
   ========================================================== */

/* ---- Phone-only top bar — always visible, replaces the floating
   hamburger pill on small screens. Brand on the left, menu button on
   the right. Stays fixed; main content is padded below. ---- */
.topbar { display: none; }

@media (max-width: 760px) {
  .topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: calc(56px + env(safe-area-inset-top, 0px));
    padding: env(safe-area-inset-top, 0px) 16px 0 16px;
    background: var(--bone);
    border-bottom: 1px solid var(--line);
    z-index: 200;
  }
  .topbar-brand {
    font-family: var(--serif);
    font-size: 22px;
    letter-spacing: -0.02em;
    color: var(--ink);
    text-decoration: none;
  }
  .topbar-menu {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 0 14px;
    background: var(--ink);
    color: var(--bone);
    border: 1px solid var(--ink);
    border-radius: 0;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.20em;
    text-transform: uppercase;
    cursor: pointer;
  }
  .topbar-menu-icon {
    display: inline-flex;
    flex-direction: column;
    justify-content: space-between;
    width: 16px; height: 11px;
  }
  .topbar-menu-icon > span {
    display: block;
    height: 1.5px;
    background: var(--bone);
  }
  .topbar-menu-label { line-height: 1; }

  /* The old floating pill is unnecessary here — hide it. */
  .nav-toggle { display: none !important; }

  /* Push the main content below the bar */
  .app-shell > .main {
    padding-top: calc(72px + env(safe-area-inset-top, 0px));
  }
}

/* ---- Page header (used by every shell page) — hairline strip
   above and below the title, with an inline serif italic subtitle.
   Mendell single-statement, Baldinger architecture. ---- */
.app-shell .main > header {
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: clamp(20px, 3vw, 34px) 0 clamp(24px, 3.5vw, 40px);
  margin-bottom: clamp(28px, 4vw, 55px);
}
.app-shell .main > header .display-xl {
  font-size: clamp(40px, 6vw, 84px) !important;
  letter-spacing: -0.03em;
  line-height: 0.92;
}
@media (max-width: 760px) {
  .app-shell .main > header {
    padding: 16px 0 24px;
    margin-bottom: 24px;
  }
  .app-shell .main > header .display-xl {
    font-size: 34px !important;
  }
}

/* ---- Buttons — sharper, Baldinger-grid feel. Primary inverts on
   hover with a tiny arrow nudge so every CTA carries a hint of the
   welcome-route line treatment. ---- */
.btn { border-radius: 0; transition: background var(--med), color var(--med), border-color var(--med), transform var(--med); }
.btn-primary { border-color: var(--ink); }
.btn-primary:hover { background: var(--ink); color: var(--bone); border-color: var(--ink); }
.btn-oxblood:hover { transform: translateY(-1px); }
.btn-ghost { background: transparent; }
.btn-ghost:hover { background: var(--cream); }

/* ---- Card refinement — keep cream surface but tighten the inside.
   First child eyebrow gets a hairline rule pulled across the card
   for that Baldinger architecture. ---- */
.card .section-code:first-child,
.card-paper .section-code:first-child {
  position: relative;
  padding-bottom: 8px;
}
.card .section-code:first-child::after,
.card-paper .section-code:first-child::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--line-soft);
}

/* ---- Hairline section divider — drop in anywhere as <hr class="rule"> */
hr.rule {
  border: 0;
  border-top: 1px solid var(--ink);
  margin: clamp(34px, 5vw, 55px) 0;
  height: 0;
}
hr.rule-soft {
  border: 0;
  border-top: 1px solid var(--line-soft);
  margin: clamp(21px, 3vw, 34px) 0;
  height: 0;
}

/* ---- Form fields — labels become mono eyebrow caps; inputs
   bottom-bordered only, like an editorial form. ---- */
.field label {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.field input,
.field textarea,
.field select {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  padding: 12px 2px;
  transition: border-color var(--fast);
}
.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-bottom-color: var(--ink);
  border-bottom-width: 2px;
  padding-bottom: 11px;
}

/* On phone: inputs return to a boxed look so they're easier to find. */
@media (max-width: 760px) {
  .field input,
  .field textarea,
  .field select {
    border: 1px solid var(--line);
    padding: 12px 14px;
    background: var(--bone);
  }
  .field input:focus,
  .field textarea:focus,
  .field select:focus {
    border-color: var(--ink);
    border-bottom-width: 1px;
    padding-bottom: 12px;
  }
}

/* ---- Auth (sign-in / sign-up / pending) — match the welcome's
   typographic register. The dark left column gets a hairline strip
   and serif tightening. ---- */
@media (max-width: 760px) {
  /* On phone the dark column hides; restyle the right column to feel
     like a continuation of the welcome screen. */
  body main[style*="grid-template-columns"] {
    grid-template-columns: 1fr !important;
  }
}

/* =============================================================
   v37.2 — Phone drawer fix.
   When the drawer opens on phone it must cover the topbar (which
   sits at z-index 200). Lift drawer above 200; scrim sits between.
   Also widens the drawer to ~88vw with safe-area padding so its
   contents are easy to reach on a phone.
   ========================================================== */
.app-shell > .sidebar { z-index: 220; }
.nav-scrim { z-index: 210; }

@media (max-width: 760px) {
  .app-shell > .sidebar {
    width: min(88vw, 340px);
    padding-top: calc(21px + env(safe-area-inset-top, 0px));
    padding-bottom: calc(21px + env(safe-area-inset-bottom, 0px));
  }
  /* When drawer is open, the topbar sits behind it visually — but on
     iOS the safe-area cutout can still leak through. Push it under. */
  html.nav-open .topbar { z-index: 195; }

  /* Big tap-target for the close-the-drawer chevron */
  .nav-collapse {
    width: 44px;
    height: 44px;
    font-size: 26px;
    border-radius: 0;
  }
  /* Make every nav link comfortably tall on phone */
  .side-link { padding: 14px 16px; font-size: 12px; }
  .side-nav-group-head { padding: 12px 16px 6px; }
}

/* =============================================================
   v37.4 — Phone drawer: legacy CSS reset.
   Older media-query blocks forced the sidebar into a position:sticky
   horizontal strip, which prevented the slide-out drawer from
   actually opening on phone. This block — last in the file —
   restores correct fixed slide-out behaviour and locks body scroll
   while the drawer is open.
   ========================================================== */
@media (max-width: 760px) {
  /* Drawer is a fixed full-height panel sliding in from the left. */
  .app-shell > aside.sidebar,
  .app-shell > .sidebar {
    position: fixed !important;
    top: 0 !important;
    bottom: 0 !important;
    left: 0 !important;
    right: auto !important;
    width: min(88vw, 340px) !important;
    height: auto !important;
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: stretch !important;
    padding: calc(21px + env(safe-area-inset-top, 0px)) 21px calc(21px + env(safe-area-inset-bottom, 0px)) 21px !important;
    background: var(--bone) !important;
    border-right: 1px solid var(--line) !important;
    border-bottom: 0 !important;
    overflow-x: visible !important;
    overflow-y: auto !important;
    box-shadow: 0 0 28px rgba(0,0,0,0.18) !important;
    z-index: 220 !important;
    transform: translateX(-100%);
    transition: transform 240ms ease;
    gap: 0 !important;
  }
  html.nav-open .app-shell > aside.sidebar,
  html.nav-open .app-shell > .sidebar {
    transform: translateX(0) !important;
  }

  /* Sidebar nav is vertical inside the drawer (the legacy block had
     forced it into a horizontal pill rail). */
  .app-shell > aside .side-nav,
  .app-shell > .sidebar .side-nav {
    display: flex !important;
    flex-direction: column !important;
    flex: 1 1 auto !important;
    order: 0 !important;
    gap: 2px !important;
    padding: 0 !important;
    margin: 0 !important;
    overflow: visible !important;
    border: 0 !important;
  }
  .app-shell > aside .side-link,
  .app-shell > .sidebar .side-link {
    border: 0 !important;
    border-left: 2px solid transparent !important;
    border-radius: 0 !important;
    padding: 14px 16px !important;
    font-size: 12px !important;
    white-space: normal !important;
    background: transparent !important;
    color: var(--ink-2) !important;
    width: auto !important;
  }
  .app-shell > aside .side-link.active,
  .app-shell > .sidebar .side-link.active {
    background: rgba(20,17,16,0.05) !important;
    color: var(--ink) !important;
    border-left-color: var(--ink) !important;
  }

  /* Sidebar foot — back to a vertical block */
  .app-shell > aside > div:last-child,
  .app-shell > .sidebar > div:last-child {
    margin-left: 0 !important;
    margin-top: 21px !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 13px !important;
  }
  .app-shell > aside > div:last-child > hr,
  .app-shell > .sidebar > div:last-child > hr { display: block !important; }
  .app-shell > aside .profile-chip,
  .app-shell > .sidebar .profile-chip {
    padding: 12px !important;
    gap: 12px !important;
    border-radius: 0 !important;
  }
  .app-shell > aside .profile-chip .profile-role,
  .app-shell > .sidebar .profile-chip .profile-role { display: block !important; }
  .app-shell > aside > div:last-child .btn,
  .app-shell > .sidebar > div:last-child .btn { display: inline-flex !important; }
  .app-shell > aside .sidebar-brand,
  .app-shell > .sidebar .sidebar-brand { font-size: 22px !important; }

  /* Lock body scroll while the drawer is open (prevents the page
     under the scrim from scrolling when you swipe over it). */
  html.nav-open, html.nav-open body {
    overflow: hidden !important;
    height: 100vh;
  }

  /* Topbar must always be tappable. Make sure no rule pushes it off. */
  .topbar {
    pointer-events: auto !important;
    transform: none !important;
  }
  .topbar-menu {
    /* Slightly larger tap target — 44px guideline */
    height: 44px !important;
    padding: 0 16px !important;
  }
}

/* =============================================================
   v38.2 — Phone modal flow + always-reachable close button.
   Modals previously sat at z-index 100, while the v37 topbar is at
   200; on phone the close button was hidden behind the bar.
   This block lifts modals above every other layer, full-bleeds them
   on phone with smooth iOS-style scrolling, and makes the modal's
   header row sticky so the × is always reachable while scrolling.
   ========================================================== */
.modal-backdrop { z-index: 250 !important; }

@media (max-width: 760px) {
  .modal-backdrop {
    padding: 0 !important;
    align-items: stretch !important;
    justify-content: stretch !important;
  }
  .modal,
  .modal-backdrop .modal {
    width: 100% !important;
    max-width: 100% !important;
    max-height: 100vh !important;
    max-height: 100dvh !important;
    height: 100vh !important;
    height: 100dvh !important;
    margin: 0 !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
    padding-top: max(16px, env(safe-area-inset-top, 0px)) !important;
    padding-bottom: max(20px, env(safe-area-inset-bottom, 0px)) !important;
    border: 0 !important;
    border-radius: 0 !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  /* Pin the modal's first row (typically the meta + Close × header)
     to the top while content scrolls. Buyers always see the Close
     button no matter how long the form. */
  .modal > div:first-child {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bone);
    margin: 0 -16px 13px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--line-soft);
  }
  /* The × button itself becomes a clean tap target */
  .modal-close {
    min-height: 40px;
    padding: 0 12px;
    border: 1px solid var(--line-soft);
    background: var(--cream);
    border-radius: 0;
  }
  /* Remove the soft animations that can feel "sticky" on phone */
  .modal { animation: none !important; }
  .modal-backdrop { animation: none !important; }
}

/* Lock body scroll while a modal is open, but allow the modal itself
   to scroll. We toggle this class from the ui.js helper. */
html.modal-open, html.modal-open body {
  overflow: hidden !important;
  touch-action: none;
}

/* =============================================================
   v40.1 — Phone topbar: hide when a modal is open + trim height.
   The fixed topbar sat above the modal's Close × button on phone.
   When a modal is open the topbar is hidden so the modal can use
   the full viewport, and main padding is reset so the topbar's
   absence isn't noticeable. Topbar is also a touch shorter
   (48px) so it claims less of the screen day-to-day.
   ========================================================== */
@media (max-width: 760px) {
  /* Trim the topbar so it claims less of the page */
  .topbar {
    height: calc(48px + env(safe-area-inset-top, 0px));
  }
  .topbar-brand { font-size: 19px; }
  .topbar-menu  { height: 36px !important; padding: 0 12px !important; font-size: 10px !important; }

  /* Push the main content below the (now slightly shorter) bar */
  .app-shell > .main {
    padding-top: calc(60px + env(safe-area-inset-top, 0px));
  }

  /* When a modal is open, get the topbar fully out of the way so
     the modal's own close button is reachable at the screen's top. */
  html.modal-open .topbar { display: none !important; }
  html.modal-open .app-shell > .main { padding-top: 0 !important; }
}

/* =============================================================
   v41 — Audit-driven fixes
   ========================================================== */

/* (a) Flex-min-width bug.
   On narrow screens any flex row containing a display headline can
   compress its title column down to single-character width. Force
   the title column (first child of every shell page header) to
   take the full row, with action buttons dropping below. */
@media (max-width: 760px) {
  .app-shell .main > header {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 14px !important;
  }
  .app-shell .main > header > * {
    width: 100%;
    min-width: 0;
  }
  .app-shell .main > header > div:first-child > h1,
  .app-shell .main > header > div:first-child > .display-xl,
  .app-shell .main > header > div:first-child > .display-l,
  .app-shell .main > header > div:first-child > .display-m {
    word-break: break-word;
    overflow-wrap: anywhere;
  }
}

/* (b) Tables — guarantee horizontal scroll AND minimum cell widths
   so columns never squash to character-per-line. Applies to both
   the main .table and the register-table on Groups. */
.table-wrap, .register-table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table th, .table td,
.register-table th, .register-table td {
  white-space: nowrap;
  min-width: 90px;
}
.table td:nth-child(1),
.register-table td:nth-child(1) { min-width: 140px; white-space: normal; }
.table td:has(a), .table td:has(button) { white-space: normal; }
@media (max-width: 760px) {
  .table, .register-table { min-width: 560px; }
}

/* (c) Mono small-caps legibility — bump 9.5/10 to 11px and darken
   the label colour for WCAG AA on cream. */
.section-code,
.meta {
  font-size: 11px;
  letter-spacing: 0.20em;
  color: var(--ink-2);
}
.field label,
.side-link,
.welcome-strip,
.welcome-route-num,
.topbar-menu-label {
  /* leave letter-spacing intact, just lift weight/colour where mono
     is used for labelling */
  color: var(--ink-2);
}

/* (d) Focus rings — visible, branded, used everywhere via :focus-visible. */
:focus-visible {
  outline: 2px solid var(--ink) !important;
  outline-offset: 2px !important;
  border-radius: 0 !important;
}

/* (e) Skip-to-content link, visually hidden until focused. */
.skip-link {
  position: absolute;
  top: -100px; left: 8px;
  background: var(--ink); color: var(--bone);
  padding: 10px 16px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  z-index: 9999;
  transition: top 140ms ease;
}
.skip-link:focus, .skip-link:focus-visible {
  top: 8px;
}

/* (f) View-as banner — slim it from a loud full-width strip to a
   tight cream/black line so it doesn't crowd the page. */
.view-as-banner {
  background: var(--ink) !important;
  color: var(--bone) !important;
  padding: 6px 16px !important;
}
.view-as-banner .view-as-inner {
  display: flex !important;
  align-items: center !important;
  justify-content: flex-end !important;
  gap: 12px !important;
  font-size: 11px !important;
  letter-spacing: 0.2em !important;
  text-transform: uppercase;
  font-family: var(--mono);
}
.view-as-banner .view-as-inner > span:nth-child(2) {
  font-family: var(--serif) !important;
  font-style: italic !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  font-size: 13px !important;
}
.view-as-banner .view-as-exit {
  background: var(--bone);
  color: var(--ink);
  border: 1px solid var(--bone);
  padding: 4px 12px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
}

/* (g) Auth pages — anchor form to top instead of vertical centre,
   so on mobile the form is immediately visible rather than buried
   behind half a screen of whitespace. */
@media (max-width: 760px) {
  body main[style*="grid-template-columns"] > section {
    justify-content: flex-start !important;
    padding-top: 32px !important;
  }
}

/* (h) PWA install button — only when JS shows it; hide by default. */
#pwa-install { display: none; }
#pwa-install.visible {
  display: inline-flex;
  position: fixed;
  bottom: 16px; right: 16px;
  z-index: 60;
  background: var(--ink); color: var(--bone);
  border: 1px solid var(--ink);
  padding: 10px 16px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
}

/* (i) Markdown body — module / library / glossary long-form. */
.markdown-body p { margin: 0 0 12px; }
.markdown-body h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(20px, 2.4vw, 24px);
  letter-spacing: -0.012em;
  line-height: 1.2;
  margin: 24px 0 8px;
  color: var(--ink);
}
.markdown-body h4 {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 18px 0 6px;
}
.markdown-body ul, .markdown-body ol { margin: 0 0 12px; padding-left: 1.2em; }
.markdown-body li { margin-bottom: 4px; }
.markdown-body strong { font-weight: 600; color: var(--ink); }
.markdown-body em { font-style: italic; color: var(--ink-2); }
.markdown-body code {
  font-family: var(--mono);
  font-size: 12px;
  background: rgba(20,17,16,0.06);
  padding: 1px 5px;
  border-radius: 2px;
}
.markdown-body a { border-bottom: 1px solid var(--ink); }

/* (j) Public marketing nav — explicit grid so brand + auth cluster
   never overlap. The pages are mostly unreachable today (the welcome
   screen is the front door) but they remain routable, so they need
   to render correctly when visited directly. */
.nav-inner {
  display: grid !important;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 24px;
  padding: 18px 28px;
}
.nav-inner > a.brand { grid-column: 1; }
.nav-inner > nav.nav-links { grid-column: 2; justify-self: end; display: flex; gap: 18px; flex-wrap: wrap; }
.nav-inner > .btn,
.nav-inner > a.nav-link[class*="btn"] { grid-column: 3; }
@media (max-width: 700px) {
  .nav-inner { grid-template-columns: auto 1fr; gap: 12px; padding: 14px 16px; }
  .nav-inner > nav.nav-links { display: none; }
  .nav-inner > .btn { grid-column: 2; justify-self: end; }
}

/* =============================================================
   v42 — Redesign tokens + components
   Adds the paper layers used by the mockup (paper-2, paper-3,
   paper-warm) on top of the existing variables, plus the new
   reusable component styles. No new fonts; existing variables
   used wherever names match.
   ========================================================== */
:root {
  --paper-2: #ece5d6;
  --paper-3: #e3dbc9;
  --paper-warm: #efe8d8;
  --line-2: #c2b89d;
  --good: #4a5e3a;
  --warn: #a87a1d;
  --bad:  #7a1b1b;
}

/* ---- Pulse chips ---- */
.pulse-strip {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 0 16px;
}
.pulse-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-2);
}
.pulse-chip.pulse-warm { border-color: var(--good); color: var(--good); }
.pulse-chip.pulse-cool { border-color: var(--warn); color: var(--warn); }
.pulse-chip.pulse-cold { border-color: var(--bad);  color: var(--bad);  background: rgba(122,27,27,0.04); }
.pulse-chip .pulse-num {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: 14px; letter-spacing: 0; text-transform: none;
}

/* ---- Pin strip (Next-step) ---- */
.pin-strip {
  display: flex; align-items: center; gap: 14px;
  background: var(--ink); color: var(--paper);
  border-radius: 6px; padding: 14px 20px;
  margin: 16px 0 8px;
}
.pin-strip .pin-lbl {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(243,238,228,0.65);
  flex-shrink: 0;
}
.pin-strip .pin-body {
  font-family: var(--serif); font-size: 19px; line-height: 1.3;
  flex: 1; min-width: 0;
}
.pin-strip .pin-edit {
  margin-left: auto;
  background: transparent; border: 0; padding: 4px 8px;
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(243,238,228,0.7);
  cursor: pointer;
}
.pin-strip .pin-edit:hover { color: var(--paper); }

/* ---- Mini stats ---- */
.ministats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
.ministat {
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.ministat-v { font-family: var(--serif); font-size: 28px; line-height: 1; }
.ministat-l {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; color: var(--muted);
  margin-top: 6px; text-transform: uppercase;
}

/* ---- Heat map ---- */
.heat-map { display: grid; gap: 6px; margin-top: 8px; }
.heat-row {
  display: grid;
  grid-template-columns: 1fr 80px 60px;
  gap: 10px; align-items: center;
  padding: 8px 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.heat-name { font-size: 14px; }
.heat-bar  { height: 6px; background: var(--paper-3); border-radius: 3px; overflow: hidden; }
.heat-fill { display: block; height: 100%; }
.heat-good  { background: var(--good); }
.heat-warn  { background: var(--warn); }
.heat-bad   { background: var(--bad); }
.heat-empty { background: var(--paper-3); }
.heat-val {
  font-family: var(--mono); font-size: 11px;
  color: var(--ink-2); text-align: right; letter-spacing: 0.05em;
}
.heat-val-muted { color: var(--muted); }

/* ---- R/A/G rows ---- */
.rag-row {
  display: grid;
  grid-template-columns: 1fr 90px;
  gap: 12px; align-items: center;
  padding: 10px 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.rag-row + .rag-row { margin-top: 6px; }
.rag-lbl  { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rag-t    { font-size: 14px; }
.rag-s    {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.12em; color: var(--muted);
  text-transform: uppercase;
}
.rag-pill {
  font-family: var(--mono); font-size: 10px;
  padding: 4px 8px; border-radius: 999px;
  text-transform: uppercase; letter-spacing: 0.14em;
  text-align: center;
}
.rag-pill.rag-green { background: rgba(74,94,58,0.16);   color: var(--good); }
.rag-pill.rag-amber { background: rgba(168,122,29,0.18); color: var(--warn); }
.rag-pill.rag-red   { background: rgba(122,27,27,0.16);  color: var(--bad);  }

/* ---- Avatar serif circle ---- */
.avatar-serif { line-height: 1; }

/* ---- Accordion (drawer) ---- */
.accord-wrap details.accord {
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--paper);
  margin-bottom: 8px;
  overflow: hidden;
}
.accord-summary {
  list-style: none;
  padding: 14px 18px;
  cursor: pointer;
  display: flex; align-items: center; gap: 12px;
  user-select: none;
}
.accord-summary::-webkit-details-marker { display: none; }
.accord-summary::after {
  content: "";
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.5px solid var(--ink-2);
  border-bottom: 1.5px solid var(--ink-2);
  transform: rotate(45deg);
  transition: transform 0.2s;
}
details.accord[open] .accord-summary::after { transform: rotate(-135deg); }
.accord-num {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.12em; color: var(--muted);
  text-transform: uppercase;
  min-width: 36px;
}
.accord-title {
  font-family: var(--serif);
  font-size: 19px; line-height: 1.15;
  flex: 1; min-width: 0;
}
.accord-meta {
  font-family: var(--mono); font-size: 11px;
  color: var(--ink-2); letter-spacing: 0.06em;
}
.accord-body {
  padding: 16px 18px 18px;
  border-top: 1px solid var(--line);
}

/* ---- Frame surfaces ---- */
.frame {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 24px;
}
.frame.warm { background: var(--paper-warm); }
.frame.cool { background: var(--paper-3); }
.frame + .frame { margin-top: 16px; }

/* ---- Notes thread ---- */
.notes-thread { display: grid; gap: 10px; margin-top: 12px; }
.note {
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.note .note-when {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; color: var(--muted);
  text-transform: uppercase;
}
.note .note-body { color: var(--ink-2); margin-top: 4px; white-space: pre-wrap; }
.note.pinned { border-left: 3px solid var(--ink); }
.note.pinned .note-when::before { content: "◆ "; color: var(--ink); }
.note-actions { display: flex; gap: 12px; margin-top: 8px; }
.note-actions button {
  background: transparent; border: 0; padding: 0;
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.note-actions button:hover { color: var(--ink); }

.new-note { display: flex; gap: 8px; margin-top: 4px; }
.new-note input,
.new-note textarea {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--paper);
  font: inherit;
}
.new-note button {
  padding: 10px 16px;
  background: var(--ink);
  color: var(--paper);
  border: 0; border-radius: 4px;
  font-family: var(--mono); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase;
  cursor: pointer;
}

/* ---- Recent work feed ---- */
.feed { display: grid; gap: 10px; }
.feed-item {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 12px; padding: 10px 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  align-items: center;
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
}
.feed-thumb {
  width: 64px; height: 64px;
  border-radius: 4px;
  background: var(--paper-3) center/cover no-repeat;
}
.feed-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.feed-meta .feed-t { font-family: var(--serif); font-size: 16px; line-height: 1.15; }
.feed-meta .feed-s { color: var(--muted); font-size: 12.5px; }
.feed-when {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.12em; color: var(--muted);
  text-align: right; text-transform: uppercase;
}

/* ---- Salon context ---- */
.salon { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 8px; }
.salon dt {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.12em; color: var(--muted);
  text-transform: uppercase;
}
.salon dd { margin: 2px 0 6px; font-size: 14px; }
.salon dd input {
  width: 100%;
  border: 0;
  border-bottom: 1px dashed var(--line);
  background: transparent;
  font: inherit;
  padding: 2px 0;
}
.salon dd input:focus { outline: none; border-bottom-color: var(--ink); border-bottom-style: solid; }

/* ---- Two-column layout for student profile ---- */
.profile-two-col { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 820px) {
  .profile-two-col { grid-template-columns: 1.2fr 1fr; gap: 20px; align-items: start; }
}

/* ---- Bench filter chips (Change 2) ---- */
.bench-filterbar {
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 6px 0 18px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 18px;
  align-items: center;
}
.bench-filterbar .bench-chip {
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
}
.bench-filterbar .bench-chip.active {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}

/* ---- Identity card (educator profile top) ---- */
.id-card {
  display: flex; align-items: center; gap: 16px;
  padding: 18px 0 22px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.id-card .id-name { font-family: var(--serif); font-size: 22px; line-height: 1.15; }
.id-card .id-meta { color: var(--muted); font-size: 13px; margin-top: 2px; }
.id-card .id-meta .dot { margin: 0 6px; }
.id-card .id-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* ---- Check-in notice (apprentice dashboard) ---- */
.checkin-notice {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink);
  border-radius: 4px;
  padding: 14px 18px;
  margin: 12px 0;
}
.checkin-notice .ci-from {
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; color: var(--muted);
  text-transform: uppercase;
}
.checkin-notice .ci-body {
  font-family: var(--serif); font-size: 17px; line-height: 1.3;
  margin-top: 4px;
}

/* =============================================================
   v44 — Model Sheet
   One piece of work, one page. Cover · head sheet · formulary ·
   journal · tags · critique. Editorial layout, generous space.
   ========================================================== */
.model-hero {
  border-bottom: 1px solid var(--line);
  padding-bottom: 21px;
  margin-bottom: 28px;
}
.model-section {
  margin-bottom: 34px;
}
.model-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  margin-bottom: 34px;
}
@media (min-width: 820px) {
  .model-grid { grid-template-columns: 1fr 1.1fr; gap: 24px; }
}

/* ---- Cover photos ---- */
.model-cover {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.model-cover-single { grid-template-columns: minmax(0, 520px); justify-content: start; }
.model-cover-empty {
  background: var(--paper-3);
  border: 1px dashed var(--line);
  padding: 55px;
  text-align: center;
  border-radius: 4px;
  color: var(--muted);
}
.model-cover-fig {
  margin: 0;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.model-cover-fig img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
  background: var(--paper-3);
}
.model-cover-fig figcaption {
  padding: 8px 12px;
  background: var(--paper);
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- Tags ---- */
.model-tags { margin-top: 13px; display: flex; flex-wrap: wrap; gap: 6px; }
.model-tag {
  display: inline-flex;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.10em;
  padding: 3px 8px;
  border-radius: 3px;
  background: var(--paper-3);
  color: var(--ink-2);
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
}
.model-tag:hover { border-color: var(--ink); }

/* ---- Formulary list ---- */
.formula-list { display: grid; gap: 12px; }
.formula-row {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 14px 16px;
}
.formula-row + .formula-row { margin-top: 0; }
.formula-meta { margin-bottom: 8px; }
.formula-title {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.2;
  margin: 4px 0 0;
}
.formula-recipe {
  background: var(--paper-3);
  border-radius: 3px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 12.5px;
  white-space: pre-wrap;
  margin: 0;
}
.formula-notes { margin: 8px 0 0; }
.formula-cost { margin-top: 8px; }

/* ---- Journal block — read-in-bed serif body ---- */
.model-journal.serif p {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.6;
  max-width: 62ch;
  color: var(--ink-2);
}
.model-journal.serif h3,
.model-journal.serif h4 {
  font-family: var(--serif);
  letter-spacing: -0.01em;
}

/* ---- Critique thread ---- */
.critique-compose {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
  align-items: stretch;
}
.critique-input {
  flex: 1;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--paper);
  font: inherit;
  resize: vertical;
}
.critique-thread { display: grid; gap: 10px; }
.critique-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 14px 16px;
}
.critique-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 8px;
}
.critique-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.critique-author { font-family: var(--serif); font-size: 16px; line-height: 1.15; }
.critique-body p:last-child { margin-bottom: 0; }
.critique-delete {
  margin-left: auto;
  background: transparent; border: 0; padding: 0;
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); cursor: pointer;
}
.critique-delete:hover { color: var(--bad); }

/* ---- Danger zone ---- */
.model-danger {
  margin-top: 55px;
  text-align: center;
}
.model-danger .btn {
  border-color: var(--bad);
  color: var(--bad);
}
.model-danger .btn:hover {
  background: var(--bad);
  color: var(--paper);
  border-color: var(--bad);
}

/* ---- Phone tweaks ---- */
@media (max-width: 760px) {
  .model-cover { grid-template-columns: 1fr; }
  .model-cover-fig img { aspect-ratio: 1 / 1; }
}

/* =============================================================
   V45 STABILITY — flex-min-width fix across narrow viewports.
   Three surfaces with the same root cause: a flex row containing
   [eyebrow] + [title] + [meta/chevron] where the title flex item
   has no min-width: 0, so it can't shrink below one character and
   wraps each letter to its own line. One block applied across.
   ========================================================== */

/* Apprentice dashboard accordion summaries */
details.accord > summary,
.accord-summary {
  flex-wrap: wrap !important;
  row-gap: 4px;
}
.accord-summary .accord-title,
details.accord > summary > .accord-title {
  min-width: 0 !important;
  flex: 1 1 auto !important;
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Report Card masthead — wordmark + meta line */
.report-page .report-header,
.report-paper .report-header {
  flex-wrap: wrap;
  row-gap: 12px;
}
.report-page .report-header > div,
.report-paper .report-header > div {
  min-width: 0;
  flex: 1 1 auto;
  overflow-wrap: anywhere;
}
.report-brand {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Public marketing nav (Philosophy / Curriculum / For Educators) */
.nav-inner {
  flex-wrap: wrap;
  row-gap: 12px;
}
.nav-inner > .brand,
.nav-inner > .nav-links,
.nav-inner > .auth-cluster {
  min-width: 0;
  overflow-wrap: anywhere;
}
.nav-link {
  white-space: nowrap;
}

/* Belt-and-braces: any flex row with class .row-clip needs min-width: 0
   on its title child. */
.row-clip { display: flex; flex-wrap: wrap; }
.row-clip > .title { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }

/* =============================================================
   V53 APPLY — auth form polish
   * inputs are now wrapped inside their <label>, which the browser
     auto-associates. `.field-label` styles the visible caption.
   * narrow-viewport overflow killed with overflow-wrap + max-width.
   ========================================================== */
label.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
  margin-bottom: var(--s-21);
  cursor: text;
}
label.field .field-label {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
  cursor: pointer;
}
label.field input,
label.field textarea,
label.field select { cursor: text; }

@media (max-width: 760px) {
  /* Inputs inside <label> need the same boxed treatment we already
     give the .field divs on phone. */
  label.field input,
  label.field textarea,
  label.field select {
    border: 1px solid var(--line);
    padding: 12px 14px;
    background: var(--bone);
    border-radius: 0;
  }
}

/* Auth page section never lets content overflow horizontally. */
body main[style*="grid-template-columns"] > section,
body main[style*="grid-template-columns"] > section * {
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: normal;
}

/* =============================================================
   V61 TRUTHING — Report Card masthead + admin eyebrow nowrap.
   Honest close on what V45 STABILITY only partially shipped.
   ========================================================== */

/* (1) Report Card masthead — never break a wordmark or eyebrow
       character-by-character at narrow viewports. The print-bar
       row stacks below the masthead under 600px so neither one
       gets squeezed into a single-column. */
.report-page .report-actions {
  flex-wrap: wrap;
  row-gap: 12px;
}
.report-paper { padding: var(--s-55) var(--s-34); }
.report-page  { padding: var(--s-34) var(--s-21); }
.report-header,
.report-header > * {
  min-width: 0;
}
.report-header > div {
  flex: 1 1 auto;
  overflow-wrap: anywhere;
}
.report-brand {
  white-space: nowrap;
  overflow-wrap: normal;
}
@media (max-width: 600px) {
  .report-page  { padding: var(--s-21) var(--s-13); }
  .report-paper { padding: var(--s-34) var(--s-21); }
  .report-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .report-header {
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
  }
  .report-header > div { width: 100%; }
}

/* (4) Section-code eyebrow — the dot in 0.01 / 0.02 etc. must
       not be a wrap point. Lock the number span to nowrap and the
       row to non-shrinking so admin overview never reads "0. / 01". */
.section-code {
  flex-wrap: nowrap;
}
.section-code .num {
  white-space: nowrap;
  flex-shrink: 0;
}

/* (2) Access card — Modules / Readings / Examinations merge.
       Chips switch views, rows carry state pills, footnote
       quietly explains the consequence of unticking. */
.access-card .access-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.access-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--cream);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.access-chip:hover { background: var(--paper-2); }
.access-chip.is-active {
  background: var(--ink);
  color: var(--bone);
  border-color: var(--ink);
}
.access-chip .access-chip-count {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  opacity: 0.7;
}
.access-chip.is-active .access-chip-count { opacity: 0.85; }

.access-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.access-row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 12px 16px;
  background: var(--cream);
  border: 1px solid var(--line-soft);
  cursor: pointer;
}
.access-row:hover { background: var(--paper-2); }
.access-row .access-tick {
  width: auto;
  flex-shrink: 0;
  margin: 0;
}
.access-row-body { flex: 1; min-width: 0; }
.access-row-title {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.2;
}
.access-row-sub {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 3px;
}

.access-pill {
  flex-shrink: 0;
  display: inline-block;
  padding: 4px 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border: 1px solid var(--line);
  background: var(--cream);
  color: var(--ink-2);
  white-space: nowrap;
}
.access-pill-locked      { color: var(--muted); border-color: var(--line-soft); }
.access-pill-open        { color: var(--ink-2); border-color: var(--line); }
.access-pill-assigned    { color: var(--bone); background: var(--ink); border-color: var(--ink); }
.access-pill-in-progress { color: var(--warn); border-color: var(--warn); background: transparent; }
.access-pill-cleared     { color: var(--good); border-color: var(--good); background: transparent; }

.access-footnote {
  margin-top: 21px;
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

@media (max-width: 600px) {
  .access-row { flex-wrap: wrap; }
  .access-row .access-pill { margin-left: auto; }
}

/* =============================================================
   V62 AUTHORSHIP — Studio chips, authoring shell, distractor rows.
   ========================================================== */

.studio-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 21px;
}
.studio-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--cream);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.studio-chip:hover { background: var(--paper-2); }
.studio-chip.is-active {
  background: var(--ink);
  color: var(--bone);
  border-color: var(--ink);
}
.studio-chip.is-new {
  background: transparent;
  border-style: dashed;
}
.studio-chip.is-new:hover { background: var(--paper-2); }

/* V69.1 — phone: tighter chip padding + smaller letter-spacing
 * so the fifth chip ("Case studies") doesn't shove + NEW off the
 * row at narrow widths. Wrap is already enabled; this just keeps
 * everything visible without a second row in the common case. */
@media (max-width: 760px) {
  .studio-chip { padding: 9px 12px; letter-spacing: 0.12em; font-size: 10.5px; }
}

/* V69.1 — entry-points strip on the Examinations list, visible
 * for anyone who looks for case studies under examinations. */
.exam-list-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 21px;
  padding-bottom: 21px;
  border-bottom: 1px solid var(--line-soft);
}
.studio-chip-count {
  font-size: 10px;
  opacity: 0.7;
}
.studio-chip.is-active .studio-chip-count { opacity: 0.85; }

.studio-archived-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 21px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.studio-archived-toggle input { width: auto; }

.studio-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.studio-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 21px;
  align-items: center;
  padding: 16px 21px;
  background: var(--cream);
  border: 1px solid var(--line-soft);
}
.studio-row.is-archived { opacity: 0.55; }
.studio-row-handle {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.studio-row-body { min-width: 0; }
.studio-row-title {
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.2;
}
.studio-row-sub {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 3px;
}
.studio-row-meta {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.studio-row-stats {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-align: right;
  color: var(--ink-2);
  white-space: nowrap;
}
.studio-row-stats .muted-stat {
  color: var(--muted);
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.14em;
}
.studio-row-controls {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.icon-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink-2);
  cursor: pointer;
  font-size: 14px;
  font-family: var(--mono);
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
  text-decoration: none;
}
.icon-btn:hover {
  background: var(--paper-2);
  color: var(--ink);
}
.icon-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

@media (max-width: 760px) {
  .studio-row {
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    gap: 13px;
  }
  .studio-row-stats {
    grid-column: 2;
    text-align: left;
  }
  .studio-row-controls {
    grid-column: 1 / -1;
    justify-content: flex-end;
  }
}

/* Authoring shell — three tabs (MODULE / READING / EXAMINATION). */
.authoring-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: 34px;
}
.authoring-tab {
  padding: 13px 21px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.authoring-tab:hover { color: var(--ink-2); }
.authoring-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.authoring-form {
  display: flex;
  flex-direction: column;
  gap: 21px;
  max-width: 720px;
}
.field-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.field-block > label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}
.field-block input[type="text"],
.field-block input[type="url"],
.field-block input[type="file"],
.field-block select,
.field-block textarea {
  width: 100%;
  padding: 10px 13px;
  border: 1px solid var(--line);
  background: var(--paper);
  font: inherit;
  border-radius: 0;
}
.field-block textarea {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}
.md-preview {
  border: 1px solid var(--line-soft);
  background: var(--paper-2);
  padding: 13px 16px;
  font-family: var(--serif);
  font-size: 14px;
  color: var(--ink-2);
  min-height: 60px;
}

.type-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.type-chip {
  padding: 8px 14px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--cream);
  border: 1px solid var(--line);
  cursor: pointer;
}
.type-chip:hover { background: var(--paper-2); }
.type-chip.is-active {
  background: var(--ink);
  color: var(--bone);
  border-color: var(--ink);
}

/* Examination — per-question card with distractor rows. */
.question-list {
  display: flex;
  flex-direction: column;
  gap: 21px;
}
.question-card {
  border: 1px solid var(--line);
  background: var(--cream);
  padding: 21px;
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.question-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.distractor-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.distractor-row input { width: 100%; }

.sequencing-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
}
.sequencing-list li {
  padding: 8px 13px;
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
}

/* =============================================================
   V65 GROUND — mobile root-cause fixes.
   Loaded LATE so it overrides earlier rules without !important
   on most properties. Four areas:
     (1) safe-area on .marketing-header + .marketing-drawer-head
     (2) opaque drawer scrim + body-scroll lock for the app shell
     (3) drop overflow:hidden on .welcome; switch 100vh → 100dvh
     (4) auth shell becomes a normal vertical-scroll page; fields
         clear the keyboard with a bottom buffer.
   ========================================================== */

/* (1) Marketing header — match the auth-app .topbar safe-area
       behaviour so the wordmark + auth cluster + hamburger never
       sit under the Dynamic Island. */
.marketing-header {
  padding-top: max(21px, calc(env(safe-area-inset-top, 0px) + 13px));
  padding-left:  max(34px, env(safe-area-inset-left, 0px));
  padding-right: max(34px, env(safe-area-inset-right, 0px));
  background: var(--bone);
}
@media (max-width: 800px) {
  .marketing-header {
    padding-top:    max(16px, calc(env(safe-area-inset-top, 0px) + 10px));
    padding-left:   max(21px, env(safe-area-inset-left, 0px));
    padding-right:  max(21px, env(safe-area-inset-right, 0px));
  }
}
.marketing-drawer {
  padding-top: max(21px, calc(env(safe-area-inset-top, 0px) + 13px));
  padding-bottom: max(24px, env(safe-area-inset-bottom, 0px));
}
.marketing-drawer-scrim {
  background: var(--ink);
}
.marketing-drawer-scrim.is-open { opacity: 0.92; }

/* (2) App-shell drawer — scrim opacity bumped so the bleed-through
       strip on the right is no longer visible. Sidebar head gets
       safe-area padding so the brand + close arrow are tappable
       under the notch. */
.nav-scrim {
  background: rgba(20, 17, 16, 0.78);
}
.app-shell > .sidebar {
  padding-top: max(21px, calc(env(safe-area-inset-top, 0px) + 13px));
  padding-bottom: max(21px, env(safe-area-inset-bottom, 0px));
}
/* Body-scroll lock applies on every viewport, not just phone, when
   the drawer is open. The previous rule was nested inside the
   max-width: 760px block — desktop tablets could still scroll the
   page under the drawer. */
html.nav-open,
html.nav-open body {
  overflow: hidden;
  height: 100%;
  /* iOS Safari sometimes leaves a 1px gap that lets touches reach
     the underlying scroll container; touch-action: none seals it. */
  touch-action: none;
}

/* (3) Welcome (landing) page — remove the trapped-content
       overflow:hidden. Use dynamic viewport units so the address
       bar collapsing on scroll doesn't crop the bottom strip. */
.welcome {
  overflow: visible;
  min-height: 100dvh;
}
@media (max-width: 760px) {
  .welcome {
    overflow-x: hidden;       /* still prevent horizontal scroll */
    overflow-y: visible;
    /* The grid wraps cleanly on phone via the existing @media at 760px;
       this just removes the scroll trap. */
  }
}

/* (4) Auth shell (sign in / sign up / pending) — replaces the
       inline minHeight:100vh + two-column grid on phone with a
       normal scrolling page. The keyboard now uncovers the
       focused field as the user types, rather than hiding the
       lower fields permanently. */
.auth-shell {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--bone);
}
.auth-shell-form {
  padding: max(34px, env(safe-area-inset-top, 0px)) max(34px, env(safe-area-inset-right, 0px))
           calc(80px + env(safe-area-inset-bottom, 0px)) max(34px, env(safe-area-inset-left, 0px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
}
@media (max-width: 760px) {
  .auth-shell { grid-template-columns: 1fr; }
  .auth-shell-form {
    padding-top: max(72px, calc(env(safe-area-inset-top, 0px) + 56px));
    padding-bottom: calc(160px + env(safe-area-inset-bottom, 0px));
    justify-content: flex-start;
  }
}

.marketing-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 21px;
  padding: 21px 34px;
  border-bottom: 1px solid var(--line);
}
.marketing-brand {
  font-family: var(--serif);
  font-size: 21px;
  text-decoration: none;
  color: var(--ink);
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.marketing-nav-inline {
  display: flex;
  gap: 28px;
  flex: 1;
  justify-content: center;
}
.marketing-nav-inline a {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
}
.marketing-nav-inline a:hover { color: var(--ink); }
.marketing-auth-cluster {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
.marketing-hamburger {
  display: none;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  cursor: pointer;
  flex-shrink: 0;
}
.marketing-hamburger:hover { background: var(--paper-2); }

@media (max-width: 800px) {
  .marketing-header { padding: 16px 21px; }
  .marketing-nav-inline,
  .marketing-auth-cluster { display: none; }
  .marketing-hamburger { display: inline-flex; }
}

/* Drawer + scrim. Mounted to body when open. */
.marketing-drawer-scrim {
  position: fixed;
  inset: 0;
  background: var(--paper, #f3eee4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 240ms ease-out;
  z-index: 2000;
}
.marketing-drawer-scrim.is-open {
  opacity: 0.7;
  pointer-events: auto;
}
.marketing-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(360px, 90vw);
  background: var(--paper);
  border-left: 1px solid var(--ink);
  transform: translateX(100%);
  transition: transform 240ms ease-out;
  z-index: 2001;
  display: flex;
  flex-direction: column;
  padding: 21px 24px 24px;
  gap: 21px;
}
.marketing-drawer.is-open { transform: translateX(0); }
.marketing-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.marketing-drawer-eyebrow {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}
.marketing-drawer-close {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  cursor: pointer;
}
.marketing-drawer-close:hover { background: var(--paper-2); }
.marketing-drawer-nav {
  display: flex;
  flex-direction: column;
  gap: 21px;
  margin-top: 21px;
}
.marketing-drawer-link {
  font-family: var(--serif);
  font-style: italic;
  font-size: 28px;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
.marketing-drawer-link:hover { color: var(--ink-2); }
.marketing-drawer-link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}
.marketing-drawer-divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: auto 0 13px;
}
.marketing-drawer-auth {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.btn-block {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

/* V63 THRESHOLD — slim impersonation banner.
 * Replaces the legacy 80px dark-red .view-as-banner used for the
 * admin "Viewing as" case. The sandbox banner keeps the loud
 * oxblood treatment via its inline override in shell.js. */
.impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  height: 32px;
  padding: 0 24px;
  background: var(--paper);
  border-bottom: 1px solid var(--ink);
  margin: calc(var(--s-55) * -1) calc(var(--s-55) * -1) var(--s-34);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
}
@media (max-width: 900px) {
  .impersonation-banner {
    margin: calc(var(--s-34) * -1) calc(var(--s-21) * -1) var(--s-21);
  }
}
.impersonation-banner .imp-glyph {
  color: var(--ink);
}
.impersonation-banner .imp-label strong {
  font-weight: 500;
  color: var(--ink);
}
.impersonation-banner .imp-return {
  background: transparent;
  border: 0;
  padding: 0 2px;
  font: inherit;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.impersonation-banner .imp-return:hover { color: var(--ink-2); }
.impersonation-banner .imp-return:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* V64 · DISCOVERY — admin access code display. */
.access-code-display {
  font-family: var(--mono);
  font-size: 26px;
  letter-spacing: 0.14em;
  padding: 13px 21px;
  background: var(--cream);
  border: 1px solid var(--line);
  color: var(--ink);
  user-select: all;
}

/* V66 RESOLVED · M-01 — Studio module title becomes a real link.
 * Inherit the existing title style; the underline reveals on hover
 * so the row stops looking like dead text. */
.studio-row-title-link {
  color: var(--ink);
  text-decoration: none;
  display: inline-block;
}
.studio-row-title-link:hover .studio-row-title { text-decoration: underline; text-underline-offset: 4px; }
.studio-row-title-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* V66 RESOLVED · M-06 — profile-photo affordance.
 * Dashed border + "Add photo" overlay always visible (not just on
 * hover) when there's no avatar; ring intensifies on hover to read
 * as an active control. */
.avatar-upload.no-photo {
  border: 1.5px dashed var(--line);
  transition: border-color 160ms ease;
}
.avatar-upload.no-photo:hover,
.avatar-upload.no-photo:focus-visible {
  border-color: var(--ink);
  outline: none;
}
.avatar-upload.no-photo .avatar-upload-overlay {
  opacity: 0.85;
}
.avatar-upload:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

/* V66 RESOLVED · M-14 — devnotes collapse. */
.devnote-card { cursor: default; }
.devnote-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 13px;
  flex-wrap: wrap;
  margin-bottom: 13px;
}
.devnote-summary::-webkit-details-marker { display: none; }
.devnote-summary::before {
  content: "▸";
  margin-right: 6px;
  font-size: 10px;
  color: var(--muted);
  transition: transform 160ms ease;
  display: inline-block;
}
details[open] > .devnote-summary::before { transform: rotate(90deg); }
.devnote-bullets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.devnote-bullets li {
  padding-left: 21px;
  position: relative;
}
.devnote-bullets li::before {
  content: "◇";
  position: absolute;
  left: 0;
  color: var(--ink-3);
  font-size: 10px;
  top: 4px;
}

/* V66 RESOLVED · M-15 — register toolbar.
 * Chips and search input now share one row, left-aligned, with a
 * sensible search width and an inline magnifying-glass glyph. */
.register-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 13px;
}
.register-search {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 13px;
  background: var(--cream);
  border: 1px solid var(--line);
  width: 100%;
  max-width: 320px;
}
.register-search-glyph {
  font-size: 14px;
  color: var(--ink-3);
}
.register-search input {
  flex: 1;
  height: 38px;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  outline: none;
}
.register-search input:focus { outline: none; }
.register-search:focus-within {
  border-color: var(--ink);
}

/* V67.1 BENCH — session badges on the unified list.
 * Each card surfaces which parts of the session were captured —
 * head sheet, formula, journal note, voice note — as small mono
 * pills so the educator can scan the bench at a glance and know
 * what's complete without opening every row. */
.session-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.session-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--cream);
  border: 1px solid var(--line-soft);
}

/* =============================================================
   V68.1 NEUTRALISE — Interactive undercoat wheel.
   Single ring of ten wedges, each clickable. On click, the wedge
   pulses and its fill colour transitions from the undercoat hex
   to the cancel hex; the label swaps from the depth name to the
   cancel code. Editorial cream paper around it.
   ========================================================== */
.neutralise-intro p { line-height: 1.5; }
.neutralise-legend { border-top: 1px solid var(--line-soft); padding-top: 21px; }

.neutralise-wheel-stage {
  display: flex;
  justify-content: center;
  padding: 21px 0;
}
.neutralise-wheel {
  width: 100%;
  max-width: 620px;
  height: auto;
  display: block;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* Wedges — the click targets. Hover lifts the wedge a touch so
 * users know it's interactive. The transform is gentle; the
 * shadow filter on the path does the heavy lifting. */
.wheel-wedge {
  transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);
  transform-box: fill-box;
  transform-origin: center;
}
.wheel-wedge:hover path,
.wheel-wedge:focus-visible path {
  filter: brightness(1.06) url(#wheelShadow);
}
.wheel-wedge:focus { outline: none; }
.wheel-wedge:focus-visible path {
  stroke: var(--ink, #141110);
  stroke-width: 2.4;
}

/* Wedge labels — serif italic, just big enough to read on the
 * wedge without crowding the centre plate. */
.wheel-wedge-label {
  font-family: var(--serif, Georgia, serif);
  font-style: italic;
  font-size: 16px;
  letter-spacing: -0.01em;
  pointer-events: none;
}
.wheel-wedge-label-code {
  font-family: var(--mono, ui-monospace, monospace);
  font-style: normal;
  font-size: 22px;
  letter-spacing: 0.05em;
  font-weight: 500;
}
.wheel-wedge-tag {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 9px;
  letter-spacing: 0.22em;
  pointer-events: none;
}

/* Centre plate — Tone wordmark sits on cream paper inside the
 * wheel, matching the OG card type lockup. */
.wheel-centre-eyebrow {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 10px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}
.wheel-centre-mark {
  font-family: var(--serif, Georgia, serif);
  font-style: italic;
  font-size: 26px;
  letter-spacing: -0.01em;
}

/* Phone — wedge labels shrink so two-line undercoat names don't
 * overflow each wedge at narrow widths. */
@media (max-width: 540px) {
  .wheel-wedge-label { font-size: 12px; }
  .wheel-wedge-label-code { font-size: 16px; }
  .wheel-wedge-tag { font-size: 8px; letter-spacing: 0.18em; }
  .wheel-centre-mark { font-size: 20px; }
  .wheel-centre-eyebrow { font-size: 9px; letter-spacing: 0.22em; }
}

/* =============================================================
   V68.2 NEUTRALISE — properly dressed.
   Page-paper backdrop, outer compass ring, centre lockup, code
   legend chips. The swatch hex values are untouched; everything
   below is chrome around them.
   ========================================================== */

/* The wheel sits on its own paper plate, like an editorial chart
 * pasted into the page. Subtle hairline border, generous breath. */
.neutralise-wheel-plate {
  background: var(--paper, #f3eee4);
  border: 1px solid var(--line, rgba(20,17,16,0.12));
  padding: clamp(13px, 3vw, 34px);
  display: flex;
  justify-content: center;
}
.neutralise-wheel { max-width: 720px; }

/* Outer compass — mono caps depth labels around the wheel. */
.nw-compass-label {
  font-family: var(--mono, ui-monospace, Menlo, monospace);
  font-size: 11px;
  letter-spacing: 0.22em;
  font-weight: 500;
  pointer-events: none;
  transition: fill 180ms ease, font-weight 0s;
}

/* Wedge hover lift — minimal, the colour change does the work. */
.wheel-wedge { transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1); }
.wheel-wedge:hover,
.wheel-wedge:focus-visible {
  transform: scale(1.012);
  transform-box: fill-box;
  transform-origin: center;
}
.wheel-wedge:focus { outline: none; }
.wheel-wedge:focus-visible path:first-of-type {
  stroke: var(--ink, #141110);
  stroke-width: 2.4;
}

/* Wedge labels. */
.wheel-wedge-label {
  font-family: var(--serif, "Fraunces", Georgia, serif);
  font-style: italic;
  font-size: 17px;
  letter-spacing: -0.01em;
  pointer-events: none;
}
.wheel-wedge-label-code {
  font-family: var(--mono, ui-monospace, monospace);
  font-style: normal;
  font-size: 26px;
  letter-spacing: 0.04em;
  font-weight: 500;
}
.wheel-wedge-hint {
  font-family: var(--serif, Georgia, serif);
  font-size: 11px;
  pointer-events: none;
  opacity: 0;
  animation: nw-hint-fade-in 1400ms ease 600ms both;
}
@keyframes nw-hint-fade-in { to { opacity: 1; } }

/* Centre plate lockup — ornament, eyebrow, wordmark, caption. */
.nw-centre-orn {
  font-family: var(--serif, Georgia, serif);
  font-size: 14px;
  letter-spacing: 0.04em;
}
.nw-centre-eye {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.36em;
  font-weight: 500;
}
.nw-centre-mark {
  font-family: var(--serif, "Fraunces", Georgia, serif);
  font-style: italic;
  font-size: 34px;
  letter-spacing: -0.015em;
}
.nw-centre-caption {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 9.5px;
  letter-spacing: 0.30em;
  font-weight: 500;
}

/* Phone tightening. */
@media (max-width: 620px) {
  .nw-compass-label { font-size: 9.5px; letter-spacing: 0.18em; }
  .wheel-wedge-label { font-size: 13px; }
  .wheel-wedge-label-code { font-size: 18px; }
  .nw-centre-eye { font-size: 9px; letter-spacing: 0.28em; }
  .nw-centre-mark { font-size: 24px; }
  .nw-centre-caption { font-size: 8.5px; letter-spacing: 0.22em; }
  .nw-centre-orn { font-size: 11px; }
}

/* Code legend — small editorial chips that explain the decimals. */
.code-legend {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 13px;
}
.code-chip {
  display: flex;
  align-items: baseline;
  gap: 13px;
  padding: 13px 16px;
  background: var(--cream, #ECE5D6);
  border: 1px solid var(--line-soft, rgba(20,17,16,0.10));
}
.code-chip-code {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 16px;
  letter-spacing: 0.06em;
  color: var(--ink, #141110);
  min-width: 36px;
}
.code-chip-label {
  font-family: var(--serif, Georgia, serif);
  font-style: italic;
  font-size: 13.5px;
  line-height: 1.35;
  color: var(--ink-2, #2d2725);
}

/* =============================================================
   V69 DERIVATION — case-study attempt + detail surfaces.
   ========================================================== */

/* Authoring form — section dividers between GIVEN / CORRECT / ALIAS. */
.case-study-section {
  padding-top: 21px;
  border-top: 1px solid var(--line-soft);
  margin-top: 13px;
}
.case-study-section:first-child {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

/* V73 — multi-case authoring. Banner above the list of cases, then
   the large dashed-border "+ Add another case" tile at the bottom
   of the host so the educator never has to hunt for it. */
.cs-multi-banner {
  padding: 13px 21px;
  border: 1px solid var(--line);
  background: var(--paper);
  margin-bottom: 21px;
}
.cs-cases-host {
  display: flex;
  flex-direction: column;
  gap: 0; /* cards have their own margin-bottom */
}
.cs-add-case-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 34px 21px;
  width: 100%;
  margin-top: 8px;
  margin-bottom: 21px;
  border: 2px dashed var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  font-family: inherit;
  transition: background 160ms, border-color 160ms;
}
.cs-add-case-btn:hover {
  background: var(--ink);
  color: var(--bone);
}
.cs-add-case-glyph {
  font-family: var(--serif);
  font-size: 36px;
  line-height: 1;
  font-weight: 300;
}
.cs-add-case-label {
  font-family: var(--mono, monospace);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.cs-add-case-hint {
  font-family: var(--serif);
  font-style: italic;
  font-size: 14px;
  opacity: 0.7;
  max-width: 48ch;
  text-align: center;
}
.cs-add-case-btn:hover .cs-add-case-hint { opacity: 0.85; }

/* Alias chip-bar shared between fields. */
.alias-chipbar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  min-height: 44px;
  align-items: center;
}
.alias-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: var(--cream);
  border: 1px solid var(--line-soft);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
}
.alias-chip button {
  border: 0; background: transparent;
  cursor: pointer; padding: 0 0 0 4px;
  color: var(--ink); font-size: 14px; line-height: 1;
}

/* =============================================================
   V69.2 DERIVATION — case-study compact-card format.
   Each line = mono label + colon + value on the same row, stacked.
   Matches the educator's source case-study cards verbatim.
   ========================================================== */
.cs-card {
  background: var(--cream);
  border: 1px solid var(--line);
  padding: 21px 24px;
  max-width: 560px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cs-card-reveal {
  background: var(--paper);
  margin-top: 13px;
}
.cs-card-rule {
  border: 0;
  border-top: 1px solid var(--line-soft);
  margin: 8px 0;
}
.cs-line {
  display: grid;
  grid-template-columns: 76px 1fr;
  align-items: baseline;
  gap: 12px;
  min-height: 32px;
}
.cs-line-label {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-2);
  text-transform: uppercase;
}
.cs-line-value {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--ink);
  white-space: pre-wrap;
}

/* Inputs nest into the same line shape, no extra padding so the
 * baseline stays aligned with the inert lines above. */
.cs-line-input-row { align-items: center; }
.cs-line-input-wrap { display: flex; }
.cs-line-input {
  flex: 1;
  width: 100%;
  padding: 8px 12px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.02em;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 0;
  outline: none;
  transition: border-color 120ms ease;
}
.cs-line-input:focus { border-color: var(--ink); }
.cs-line-input-multi {
  font-size: 13px;
  line-height: 1.4;
  resize: vertical;
  min-height: 56px;
}

/* Review state — correct value on top, apprentice's incorrect
 * answer (if any) underneath in serif italic so the contrast is
 * immediate. */
.cs-line-review .cs-line-value-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.cs-line-stack {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.cs-line-yours {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-transform: uppercase;
}
.cs-line-yours em {
  font-family: var(--serif);
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  color: var(--bad, #7a1b1b);
}
.cs-line.is-wrong .cs-line-value {
  color: var(--ink);
}

.cs-mark {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
}
.cs-mark-ok  { color: var(--good, #4a5e3a); }
.cs-mark-bad { color: var(--bad, #7a1b1b); }
.cs-mark-pending { color: var(--muted); }

.cs-review {
  margin-top: 34px;
  padding-top: 21px;
  border-top: 1px solid var(--line-soft);
}
.cs-rule-note {
  padding: 16px 21px;
  background: var(--paper-2);
  border-left: 2px solid var(--ink);
}

/* Phone — labels shrink the gutter, multiline mix wraps fine. */
@media (max-width: 540px) {
  .cs-card { padding: 16px 18px; }
  .cs-line { grid-template-columns: 60px 1fr; gap: 8px; }
  .cs-line-label { font-size: 11px; }
  .cs-line-value, .cs-line-input { font-size: 13px; }
}

/* Educator detail — time strip + surrender + attempts table. */
.cs-timestrip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 13px;
}
.cs-time-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 13px;
  background: var(--cream);
  border: 1px solid var(--line-soft);
}
.cs-time-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--muted);
}
.cs-time-value {
  font-family: var(--mono);
  font-size: 18px;
  color: var(--ink);
}

.cs-surrender { display: flex; align-items: baseline; gap: 13px; flex-wrap: wrap; }
.cs-surrender-num {
  font-family: var(--serif);
  font-size: 34px;
  color: var(--ink);
}

.cs-attempts .cs-attempt-row td { vertical-align: middle; }
.cs-attempt-expand td { padding: 13px 21px 21px; background: var(--cream); }
.cs-expand-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 13px;
}
.cs-expand-pair {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 13px;
  background: var(--paper);
  border: 1px solid var(--line-soft);
}
.cs-expand-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}
.cs-expand-given {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
}
.cs-expand-correct {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* =============================================================
   V70 ATELIER — Mood boards: file area + editor.
   ========================================================== */

/* File-area shell — left rail of folders + right grid of boards. */
.mb-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 34px;
  align-items: start;
}
@media (max-width: 760px) {
  .mb-shell { grid-template-columns: 1fr; }
}

.mb-rail {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mb-rail-entry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 13px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid transparent;
}
.mb-rail-entry:hover { background: var(--paper-2); }
.mb-rail-entry.is-active { border-color: var(--line); background: var(--cream); color: var(--ink); }
.mb-rail-count { color: var(--muted); font-size: 10px; }
.mb-rail-rule { border: 0; border-top: 1px solid var(--line-soft); margin: 8px 0; }
.mb-rail-add {
  margin-top: 13px;
  padding: 10px 13px;
  background: transparent;
  border: 1px dashed var(--line);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  text-align: left;
}
.mb-rail-add:hover { background: var(--paper-2); }

.mb-folder-header {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 21px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--line-soft);
}

.mb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 21px;
}
.mb-tile { display: flex; flex-direction: column; gap: 8px; }
.mb-tile-link { display: block; text-decoration: none; }
.mb-tile-cover {
  position: relative;
  /* V72.2 — match the editor's 16:10 plate so the live preview
     reads identically (no aspect-ratio distortion). */
  aspect-ratio: 16 / 10;
  border: 1px solid var(--line);
  background-color: var(--paper);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}
/* V72.2 — live preview. The cover is its own container so
   container-query font-size units (cqw) scale text proportionally
   to the tile's width. Every child element positions itself in
   percentages of the 1600×1000 canvas. */
.mb-tile-cover-live {
  container-type: inline-size;
}
.mb-tile-elt {
  position: absolute;
  overflow: hidden;
  pointer-events: none;
}
/* Legacy dot-preview classes kept as a fallback for any tile that
   still uses them (pre-V72.2 covers). */
.mb-tile-preview { position: absolute; inset: 0; }
.mb-tile-dot {
  position: absolute;
  width: 18px; height: 18px;
  border-radius: 0;
  opacity: 0.7;
}
.mb-tile-meta { display: flex; flex-direction: column; gap: 4px; }
.mb-tile-name {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.2;
  color: var(--ink);
  text-decoration: none;
}
.mb-tile-name:hover { text-decoration: underline; }
.mb-tile-sub {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.mb-tile-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  align-items: center;
}
.mb-tile-actions .icon-btn { width: 28px; height: 28px; font-size: 12px; }
.mb-tile-move {
  flex: 1;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 5px 8px;
}

/* Editor — full-width chrome with a top bar, tool rail, stage,
 * properties panel. */
.mb-editor {
  display: flex;
  flex-direction: column;
  min-height: 70vh;
  background: var(--paper-2, #ECE5D6);
  border: 1px solid var(--line);
  margin: 0 calc(-1 * var(--s-21));
}
@media (min-width: 760px) {
  .mb-editor { margin: 0 calc(-1 * var(--s-34)); }
}
.mb-topbar {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 13px 21px;
  border-bottom: 1px solid var(--line);
  background: var(--bone);
}
.mb-name-input {
  flex: 1;
  padding: 8px 13px;
  background: transparent;
  border: 1px solid transparent;
  font-family: var(--serif);
  font-style: italic;
  font-size: 22px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.mb-name-input:focus { border-color: var(--line); background: var(--paper); outline: none; }
.mb-save-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  min-width: 80px;
  text-align: right;
}

.mb-editor-body {
  display: grid;
  grid-template-columns: 200px 1fr 260px;
  flex: 1;
  min-height: 70vh;
}
@media (max-width: 1100px) {
  .mb-editor-body { grid-template-columns: 160px 1fr 220px; }
}
@media (max-width: 760px) {
  .mb-editor-body {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr auto;
  }
}

/* Tool rail. */
.mb-tools {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 21px 13px;
  background: var(--bone);
  border-right: 1px solid var(--line);
}
.mb-tool {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 13px;
  background: transparent;
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  text-align: left;
}
.mb-tool:hover { background: var(--paper-2); }
.mb-tool-swatch {
  display: inline-block;
  width: 18px; height: 18px;
  border: 1px solid var(--line);
}
.mb-tools-rule { border: 0; border-top: 1px solid var(--line-soft); margin: 8px 0; }

/* Stage — the visible workspace that wraps the canvas. */
.mb-stage {
  position: relative;
  background: repeating-linear-gradient(
    45deg, transparent 0 12px, rgba(20,17,16,0.025) 12px 24px
  );
  overflow: auto;
  padding: 21px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
.mb-canvas {
  position: relative;
  flex-shrink: 0;
  transform-origin: top center;
  box-shadow: 0 16px 32px rgba(20,17,16,0.15);
  border: 1px solid var(--line);
}
.mb-canvas.is-droptarget {
  outline: 2px dashed var(--ink);
  outline-offset: -8px;
}

/* Elements on the canvas. */
.mb-elt {
  position: absolute;
  cursor: move;
  user-select: none;
}
.mb-elt.is-selected {
  outline: 1.5px solid var(--ink);
  outline-offset: 2px;
}
.mb-elt-handle {
  position: absolute;
  right: -7px; bottom: -7px;
  width: 14px; height: 14px;
  background: var(--ink);
  border: 1.5px solid var(--bone);
  cursor: nwse-resize;
  z-index: 10;
}
.mb-elt-text {
  width: 100%;
  height: 100%;
  outline: none;
  overflow: hidden;
  word-break: break-word;
}
.mb-elt-fallback {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--muted);
  background: var(--cream);
}

/* Properties panel. */
.mb-props {
  display: flex;
  flex-direction: column;
  gap: 13px;
  padding: 21px 16px;
  background: var(--bone);
  border-left: 1px solid var(--line);
  overflow-y: auto;
}
.mb-prop { display: flex; flex-direction: column; gap: 6px; }
.mb-prop-toggle { flex-direction: row; align-items: center; gap: 8px; }
.mb-prop-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
.mb-prop input[type="number"],
.mb-prop select {
  padding: 8px 10px;
  font: inherit;
  background: var(--paper);
  border: 1px solid var(--line);
}
.mb-prop-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 13px;
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
}

/* Picker overlays — head sheet picker, colour picker. */
.mb-picker-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20,17,16,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 3000;
}
.mb-picker-pane {
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 24px;
  max-width: min(720px, 90vw);
  max-height: 86vh;
  overflow: auto;
}
.mb-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 13px;
}
.mb-picker-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 13px;
  background: var(--cream);
  border: 1px solid var(--line-soft);
  cursor: pointer;
  text-align: center;
}
.mb-picker-card:hover { background: var(--paper-2); }
.mb-picker-name {
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink-2);
}

/* Colour-picker pane. */
.mb-picker-pane-color { width: min(520px, 90vw); }
.mb-picker-row {
  display: flex;
  align-items: center;
  gap: 21px;
  margin-bottom: 13px;
}
.mb-picker-preview {
  width: 90px;
  height: 60px;
  border: 1px solid var(--line);
}
.mb-palette {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 4px;
}
@media (max-width: 540px) {
  .mb-palette { grid-template-columns: repeat(6, 1fr); }
}
.mb-swatch {
  aspect-ratio: 1 / 1;
  border: 1px solid var(--line-soft);
  cursor: pointer;
  padding: 0;
  transition: transform 120ms ease;
}
.mb-swatch:hover { transform: scale(1.06); }

/* V70.1 — refinements over V70 baseline.
   - Shape dropdown
   - Hex input + custom-swatch row in the colour picker
   - Smoother selection (no outline jitter; movement is RAF-batched
     in JS already, this is just visual)
*/

/* Shape dropdown — anchor a popup grid to the Shape tool button. */
.mb-tool-shape-wrap { position: relative; }
.mb-tool-shape-glyph {
  display: inline-block;
  width: 14px; height: 14px;
  background: var(--ink);
  clip-path: polygon(25% 5%, 75% 5%, 100% 50%, 75% 95%, 25% 95%, 0% 50%);
  -webkit-clip-path: polygon(25% 5%, 75% 5%, 100% 50%, 75% 95%, 25% 95%, 0% 50%);
}
.mb-tool-shape-panel {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 6px;
  display: none;
  grid-template-columns: repeat(3, 64px);
  gap: 6px;
  padding: 10px;
  background: var(--paper);
  border: 1px solid var(--ink);
  z-index: 200;
  box-shadow: 0 12px 32px rgba(20,17,16,0.16);
}
.mb-tool-shape-panel.is-open { display: grid; }
.mb-shape-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 64px;
  padding: 6px 4px 8px;
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
}
.mb-shape-card:hover { background: var(--cream); border-color: var(--line-soft); }
.mb-shape-preview {
  width: 40px;
  height: 40px;
}
.mb-shape-name {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  line-height: 1;
  text-align: center;
}

/* Hex input + colour-picker layout — paired controls beside the preview. */
.mb-picker-controls {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.mb-hex-input {
  width: 140px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink);
  outline: none;
}
.mb-hex-input:focus { border-color: var(--ink); }

/* Custom-swatch row. Distinguished from the Pantone row by a
   thin dashed border so the user knows these are theirs. */
.mb-palette-custom .mb-swatch-custom {
  border-style: dashed;
}

/* Selection feedback — outline glides instead of jittering. */
.mb-elt {
  outline: 0 solid transparent;
  transition: outline-color 120ms ease, outline-width 120ms ease;
  will-change: left, top, width, height;
}
.mb-elt.is-selected {
  outline: 1.5px solid var(--ink);
  outline-offset: 2px;
}

/* Make the canvas + workspace feel less old-school: softer
   shadow, no rep-pattern when there's nothing on the plate so
   first-paint reads as clean cream paper. */
.mb-canvas { box-shadow: 0 18px 40px rgba(20,17,16,0.10); }
.mb-stage { background: var(--paper-2, #ECE5D6); }

/* V70.2 — wrapper / inner split. The wrapper holds the click and
   the resize handle; the inner holds the visible content + any
   clip-path. This is the load-bearing fix for "resize doesn't
   show on shapes" — clip-path on the inner can't clip the wrapper's
   own children (the handle). */
.mb-elt-inner {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.mb-elt > .mb-elt-inner img,
.mb-elt > .mb-elt-inner .mb-elt-text,
.mb-elt > .mb-elt-inner > svg {
  pointer-events: auto;
}
.mb-elt-handle {
  /* Keep the handle outside the inner so clip-path never reaches it. */
  z-index: 12;
}

/* Text element — non-editable by default, swap to editable on
   dblclick. Editable state gets a hint outline so the user knows
   they're in edit mode and a drag won't fire. */
.mb-elt-text {
  width: 100%;
  height: 100%;
  outline: none;
  cursor: text;
  caret-color: var(--ink);
  pointer-events: auto;
}
.mb-elt-text[contenteditable="false"] {
  cursor: move;
}
.mb-elt-text.is-editing {
  outline: 1px dashed var(--ink);
  outline-offset: 2px;
}

/* Font select — each option renders in its own family. */
.mb-font-select {
  padding: 8px 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  font-family: inherit;
  font-size: 14px;
}

/* =============================================================
   V70.3 — pages strip, presentation overlay, file-area colour
   pickers. Same hairline / cream / ink discipline as the rest of
   the editor; nothing flashy.
   ============================================================= */
.mb-pages-strip {
  display: flex;
  align-items: stretch;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--line);
  background: var(--paper);
  overflow-x: auto;
  scrollbar-width: thin;
}
.mb-page-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px 6px 6px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono, "JetBrains Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  flex: 0 0 auto;
  transition: border-color 120ms, background 120ms;
}
.mb-page-chip:hover { border-color: var(--ink); }
.mb-page-chip.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bone);
}
.mb-page-chip-add {
  font-family: var(--mono, monospace);
  text-transform: uppercase;
  padding: 6px 12px;
  border-style: dashed;
}
.mb-page-thumb {
  position: relative;
  width: 40px;
  height: 26px;
  border: 1px solid var(--line);
  flex: 0 0 auto;
  overflow: hidden;
}
.mb-page-chip.is-active .mb-page-thumb { border-color: rgba(243,238,228,0.4); }
.mb-page-thumb-dot {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 1px;
}
.mb-page-chip-name {
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mb-page-chip-num {
  opacity: 0.55;
}
.mb-page-chip-action {
  width: 18px; height: 18px;
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0;
  opacity: 0.7;
}
.mb-page-chip-action:hover { opacity: 1; }

/* Presentation overlay — black backdrop, centered slide, light
   chrome that fades after a moment of mouse stillness in a future
   iteration. */
.mb-present-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: #0a0908;
  display: flex;
  align-items: center;
  justify-content: center;
  outline: none;
}
.mb-present-stage {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.mb-present-canvas {
  transform-origin: center center;
  box-shadow: 0 30px 80px rgba(0,0,0,0.5);
}
.mb-present-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1px solid rgba(243,238,228,0.4);
  background: rgba(20,17,16,0.55);
  color: var(--bone);
  font-size: 28px;
  cursor: pointer;
  transition: background 160ms, border-color 160ms;
}
.mb-present-nav:hover:not(:disabled) {
  background: rgba(243,238,228,0.12);
  border-color: var(--bone);
}
.mb-present-nav:disabled { opacity: 0.25; cursor: not-allowed; }
.mb-present-prev { left: 24px; }
.mb-present-next { right: 24px; }
.mb-present-exit {
  position: absolute;
  top: 24px;
  right: 24px;
  padding: 8px 14px;
  border: 1px solid rgba(243,238,228,0.4);
  background: transparent;
  color: var(--bone);
  font-family: var(--mono, monospace);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.mb-present-exit:hover { background: rgba(243,238,228,0.12); }
.mb-present-counter {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(243,238,228,0.7);
  font-family: var(--mono, monospace);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* File-area colour customisation — a small swatch sits next to
   the folder name in the rail and next to the board name on a
   tile. Click opens a native colour picker; the colour is saved
   on the row in the DB. */
.mb-rail-color-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid var(--line);
  margin-right: 8px;
  vertical-align: middle;
  flex: 0 0 auto;
}
.mb-rail-entry {
  display: flex;
  align-items: center;
}
.mb-rail-entry .mb-rail-name {
  display: inline-flex;
  align-items: center;
  flex: 1 1 auto;
}
.mb-tile-colorpicker {
  position: relative;
}
.mb-tile-colorpicker input[type="color"] {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--line);
  background: transparent;
  cursor: pointer;
}
.mb-rail-color-btn {
  appearance: none;
  border: none;
  background: transparent;
  padding: 0 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.mb-rail-color-btn input[type="color"] {
  width: 14px;
  height: 14px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  opacity: 0;
  position: absolute;
}
.mb-rail-color-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.mb-rail-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.mb-rail-row .mb-rail-entry {
  flex: 1 1 auto;
  min-width: 0;
}
.mb-rail-picker {
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid var(--line);
  background: transparent;
  cursor: pointer;
  flex: 0 0 auto;
}

/* =============================================================
   V73.2 — descriptionDetails. Collapsed by default; tapping
   "Read description" opens it. Used on module, reading, quiz,
   case-study cards + intro screens so long bodies don't bury
   the actual content.
   ============================================================= */
.desc-details {
  margin-top: 8px;
}
.desc-details > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono, "JetBrains Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: background 140ms, border-color 140ms, color 140ms;
}
.desc-details > summary::-webkit-details-marker { display: none; }
.desc-details > summary::marker                 { display: none; content: ""; }
.desc-details > summary:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bone);
}
.desc-details[open] > summary {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bone);
}
.desc-details-chev {
  font-size: 10px;
  transition: transform 160ms;
  line-height: 1;
}
.desc-details[open] .desc-details-chev { transform: rotate(180deg); }
.desc-details-content {
  margin-top: 13px;
  max-width: 62ch;
  white-space: pre-wrap;
}

/* =============================================================
   V74 — STILLS 2026 DESIGN TREND LAYER
   -------------------------------------------------------------
   Five trends layered into Tone without breaking the editorial
   foundation underneath:

   1. GRADIENT BLUR  — atmospheric colour wash across heroes,
      hairline melts behind cards, full-bleed section transitions
   2. BLUEPRINT      — corner brackets, dimensional callouts,
      tick-marked rules, schematic dividers
   3. DISTORTED      — chromatic-aberration treatment for portrait
      thumbnails + headshot cells (no portrait imagery yet; class
      reserved for when it lands)
   4. TYPE COLLAGE   — large serif crashed against small mono caps,
      offset / overlapping headlines for chapter intros
   5. SIGNAL         — indicator dots, level scales 1–10, percentage
      meters, ratio bars, broadcast-style status pills

   All token-driven. Existing components are untouched; new utility
   classes opt-in. To pull a page into the new language: wrap its
   shell in `.v74` and use the utilities directly in markup.
   ============================================================= */

:root {
  /* ---- Spectrum: a hair-colour-aware gradient stack ---------- */
  /* Warm side: from copper through gold; Cool: through pearl to ash. */
  --warm-1:  #C77E5E;  /* copper */
  --warm-2:  #E0A580;  /* terracotta */
  --warm-3:  #E8C49C;  /* champagne mid */
  --neutral: #ECE5D6;  /* cream */
  --cool-3:  #B7B4AE;  /* pearl */
  --cool-2:  #8B8F92;  /* slate */
  --cool-1:  #4F575C;  /* graphite */

  /* ---- Signal: the accent palette for level meters, dots,
     broadcast pills. Kept harder + cooler than the editorial
     base — "lab equipment" not "boutique stationery". */
  --signal-ink:    #0E0E10;
  --signal-bone:   #F1ECE0;
  --signal-warm:   #C24A2E;  /* copper alert */
  --signal-cool:   #1F4A6B;  /* deep teal */
  --signal-acid:   #C7C548;  /* lift indicator */
  --signal-mute:   #7A6F65;  /* secondary */

  /* ---- Gradient stops as reusable strings ---- */
  --melt-warm: linear-gradient(135deg,
    rgba(199,126,94,0.32) 0%,
    rgba(232,196,156,0.22) 36%,
    rgba(236,229,214,0.0)  72%);
  --melt-cool: linear-gradient(225deg,
    rgba(31,74,107,0.22)   0%,
    rgba(139,143,146,0.12) 40%,
    rgba(236,229,214,0.0)  78%);
  --melt-spectrum: linear-gradient(135deg,
    rgba(199,126,94,0.28)  0%,
    rgba(232,196,156,0.20) 22%,
    rgba(236,229,214,0.10) 48%,
    rgba(183,180,174,0.18) 74%,
    rgba(79,87,92,0.22)    100%);

  /* ---- Blueprint tokens ---- */
  --bp-rule:        1px solid var(--ink);
  --bp-rule-soft:   1px solid var(--line);
  --bp-bracket:     14px;     /* corner bracket arm length */
  --bp-tick:        4px;      /* tick mark height */
  --bp-offset:      6px;      /* corner inset */
}

/* ===========================================================
   1 · GRADIENT BLUR
   =========================================================== */

/* Body wash — a very faint spectrum melt behind everything so the
   whole app reads as colour-treated rather than flat cream. */
body {
  background:
    radial-gradient(ellipse 1200px 700px at 12% -8%,
      rgba(199,126,94,0.10), transparent 70%),
    radial-gradient(ellipse 1000px 600px at 92% 18%,
      rgba(31,74,107,0.08), transparent 65%),
    radial-gradient(ellipse 1200px 700px at 50% 105%,
      rgba(183,180,174,0.10), transparent 70%),
    var(--bone);
  background-attachment: fixed;
}

/* Reusable melt surfaces — drop behind hero areas / shell headers. */
.melt-warm,
.melt-cool,
.melt-spectrum {
  position: relative;
  isolation: isolate;
}
.melt-warm::before,
.melt-cool::before,
.melt-spectrum::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  filter: blur(28px);
  transform: translateZ(0);
}
.melt-warm::before     { background: var(--melt-warm); }
.melt-cool::before     { background: var(--melt-cool); }
.melt-spectrum::before { background: var(--melt-spectrum); }

/* Full-bleed hero — used by shell header on a per-page basis. */
.hero-melt {
  position: relative;
  padding: var(--s-55) var(--s-34) var(--s-34);
  margin: 0 calc(-1 * var(--s-21)) var(--s-34);
  overflow: hidden;
  isolation: isolate;
}
.hero-melt::before {
  content: "";
  position: absolute;
  inset: -10%;
  z-index: -1;
  background: var(--melt-spectrum);
  filter: blur(48px);
  opacity: 0.85;
  pointer-events: none;
}
.hero-melt::after {
  /* Hairline grain to keep the gradient from feeling AI-glossy. */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(20,17,16,0.025) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg,
      rgba(20,17,16,0.025) 0 1px, transparent 1px 4px);
  pointer-events: none;
  opacity: 0.5;
}

/* ===========================================================
   2 · BLUEPRINT
   =========================================================== */

/* Card with corner brackets — drafting-table feel. Optional
   add-on; original .card stays unchanged. */
.bp-card {
  position: relative;
  background: var(--cream);
  border: var(--bp-rule);
  padding: var(--s-21) var(--s-21);
}
.bp-card::before,
.bp-card::after {
  content: "";
  position: absolute;
  width: var(--bp-bracket);
  height: var(--bp-bracket);
  border: var(--bp-rule);
  pointer-events: none;
}
.bp-card::before {
  top: calc(-1 * var(--bp-offset));
  left: calc(-1 * var(--bp-offset));
  border-right: none;
  border-bottom: none;
  background: var(--bone);
}
.bp-card::after {
  bottom: calc(-1 * var(--bp-offset));
  right: calc(-1 * var(--bp-offset));
  border-left: none;
  border-top: none;
  background: var(--bone);
}

/* Tick-marked rule. Use under section eyebrows for that
   "this is a measurement" feel. */
.bp-rule {
  position: relative;
  height: 1px;
  background: var(--ink);
  margin: var(--s-13) 0 var(--s-21);
}
.bp-rule::before,
.bp-rule::after {
  content: "";
  position: absolute;
  top: -2px;
  width: 1px;
  height: 5px;
  background: var(--ink);
}
.bp-rule::before { left: 0; }
.bp-rule::after  { right: 0; }

/* Dimensional callout — text in mono caps between two tick marks,
   like a drawing's "150mm" annotation. */
.bp-callout {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}
.bp-callout::before,
.bp-callout::after {
  content: "";
  width: 18px;
  height: 1px;
  background: var(--ink);
}
.bp-callout::before { margin-right: 0; }

/* Schematic divider — a thicker rule with notch marks every
   so often, used to separate big page sections. */
.bp-divider {
  height: 16px;
  background-image:
    linear-gradient(to right, var(--ink) 0 100%);
  background-size: 100% 1px;
  background-repeat: no-repeat;
  background-position: 0 50%;
  position: relative;
  margin: var(--s-34) 0;
}
.bp-divider::before,
.bp-divider::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 1px;
  height: 8px;
  background: var(--ink);
  transform: translateY(-50%);
}
.bp-divider::before { left: 0; }
.bp-divider::after  { right: 0; }

/* ===========================================================
   3 · DISTORTED PORTRAIT  (treatment for portrait thumbnails)
   =========================================================== */

/* Chromatic-aberration treatment for headshots / portraits.
   Stack two coloured copies offset behind the source so the eye
   reads "colour split". Apply to a wrapping div whose img is the
   first child. */
.dist-chroma {
  position: relative;
  display: inline-block;
  isolation: isolate;
}
.dist-chroma > img,
.dist-chroma > picture {
  display: block;
  position: relative;
  z-index: 2;
  mix-blend-mode: luminosity;
  filter: contrast(1.05);
}
.dist-chroma::before,
.dist-chroma::after {
  content: "";
  position: absolute;
  inset: 0;
  background: inherit;
  background-image: inherit;
  background-size: cover;
  background-position: center;
  z-index: 1;
  pointer-events: none;
  mix-blend-mode: screen;
}
.dist-chroma::before {
  transform: translate(-2px, -2px);
  filter: hue-rotate(-30deg) saturate(1.8);
}
.dist-chroma::after {
  transform: translate(2px, 2px);
  filter: hue-rotate(30deg) saturate(1.8);
}

/* Halftone overlay — drop on any image to ink-screen it. */
.dist-halftone {
  position: relative;
  overflow: hidden;
}
.dist-halftone::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(
    circle at center,
    rgba(20,17,16,0.55) 0.6px,
    transparent 1.2px);
  background-size: 4px 4px;
  mix-blend-mode: multiply;
  opacity: 0.45;
}

/* ===========================================================
   4 · TYPE COLLAGE
   =========================================================== */

/* Headline composition that crashes a huge serif against small
   mono caps offset behind / over it. Use for page heroes. */
.type-collage {
  position: relative;
  display: inline-grid;
  grid-template-columns: auto;
  padding-top: var(--s-13);
  line-height: 0.85;
}
.type-collage > .tc-eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-8);
  position: relative;
  z-index: 2;
}
.type-collage > .tc-head {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  letter-spacing: -0.03em;
  line-height: 0.88;
  font-size: clamp(48px, 8vw, 112px);
  color: var(--ink);
  position: relative;
  z-index: 2;
}
.type-collage > .tc-ghost {
  position: absolute;
  bottom: -8%;
  right: -2%;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(64px, 10vw, 144px);
  line-height: 0.85;
  color: var(--ink);
  opacity: 0.08;
  white-space: nowrap;
  pointer-events: none;
  z-index: 1;
  letter-spacing: -0.04em;
}

/* ===========================================================
   5 · SIGNAL GRAPHICS
   =========================================================== */

/* Indicator dot — used for status: active / locked / warm / cool. */
.sig-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--signal-ink);
  vertical-align: middle;
  margin-right: 8px;
  flex: 0 0 8px;
}
.sig-dot.warm  { background: var(--signal-warm); }
.sig-dot.cool  { background: var(--signal-cool); }
.sig-dot.acid  { background: var(--signal-acid); }
.sig-dot.mute  { background: var(--signal-mute); }
.sig-dot.large { width: 14px; height: 14px; flex-basis: 14px; }

/* Status pill — broadcast-style label. */
.sig-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border: 1px solid var(--ink);
  background: var(--cream);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1;
}
.sig-pill.live   { background: var(--ink); color: var(--bone); }
.sig-pill.live .sig-dot { background: var(--signal-acid); }
.sig-pill.alert  { background: var(--signal-warm); color: var(--signal-bone); border-color: var(--signal-warm); }

/* Level scale — 10 horizontal cells for hair levels 1–10,
   filled to N. Use class .level-N (1..10). */
.sig-level {
  display: inline-grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 2px;
  width: 220px;
  height: 14px;
  align-items: stretch;
  background: var(--paper);
  padding: 2px;
  border: 1px solid var(--line);
}
.sig-level > i {
  display: block;
  background: transparent;
  transition: background var(--fast) var(--ease);
}
.sig-level[data-level="1"]  > i:nth-child(-n+1)  { background: linear-gradient(180deg, #1A1410, #2A2018); }
.sig-level[data-level="2"]  > i:nth-child(-n+2)  { background: linear-gradient(180deg, #281F18, #3A2B20); }
.sig-level[data-level="3"]  > i:nth-child(-n+3)  { background: linear-gradient(180deg, #3B2C20, #50382A); }
.sig-level[data-level="4"]  > i:nth-child(-n+4)  { background: linear-gradient(180deg, #5A3F2A, #714D32); }
.sig-level[data-level="5"]  > i:nth-child(-n+5)  { background: linear-gradient(180deg, #7E5638, #966944); }
.sig-level[data-level="6"]  > i:nth-child(-n+6)  { background: linear-gradient(180deg, #A37852, #BC9166); }
.sig-level[data-level="7"]  > i:nth-child(-n+7)  { background: linear-gradient(180deg, #C29A6E, #D7B286); }
.sig-level[data-level="8"]  > i:nth-child(-n+8)  { background: linear-gradient(180deg, #D9BD92, #E4D0AA); }
.sig-level[data-level="9"]  > i:nth-child(-n+9)  { background: linear-gradient(180deg, #E8DAB8, #F0E5C9); }
.sig-level[data-level="10"] > i:nth-child(-n+10) { background: linear-gradient(180deg, #F2EBD4, #F8F3DE); }

/* Horizontal meter — percentage bar with mono label, replaces
   the older `progress` look on cards. */
.sig-meter {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  gap: var(--s-13);
  align-items: center;
  margin: var(--s-8) 0;
}
.sig-meter-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.sig-meter-bar {
  position: relative;
  height: 6px;
  background: var(--paper);
  border: 1px solid var(--line);
  overflow: hidden;
}
.sig-meter-bar > span {
  display: block;
  height: 100%;
  background: var(--ink);
}
.sig-meter-bar.warm > span { background: var(--signal-warm); }
.sig-meter-bar.cool > span { background: var(--signal-cool); }
.sig-meter-bar.acid > span { background: var(--signal-acid); }
.sig-meter-value {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink);
  min-width: 42px;
  text-align: right;
}

/* Ratio dial — small mono caps display for formula ratios
   (50:50, 1:1.5, 30vol etc.). */
.sig-ratio {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--ink);
  padding: 4px 10px;
  border: 1px solid var(--ink);
  background: var(--bone);
}
.sig-ratio em {
  font-style: normal;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ===========================================================
   6 · APPLIED — pull the existing components forward
   =========================================================== */

/* Sharper hairlines on the existing card so the new language
   reads alongside it without clashing. */
.card,
.card-paper {
  border-radius: 0;
}

/* Buttons get a flatter, more technical face. */
.btn {
  border-radius: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.btn-primary {
  background: var(--ink);
  color: var(--bone);
  border: 1px solid var(--ink);
}
.btn-primary:hover {
  background: var(--signal-cool);
  border-color: var(--signal-cool);
}

/* Section codes (the ◇ + number eyebrows) get tightened. */
.section-code {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.section-code > .num {
  background: var(--ink);
  color: var(--bone);
  padding: 3px 8px;
  letter-spacing: 0.12em;
}

/* Shell header now sits over a faint warm melt so the page
   intro reads colour-aware from the first paint. */
.shell-header {
  position: relative;
  isolation: isolate;
}
.shell-header::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--s-21)) calc(-1 * var(--s-21)) auto;
  height: 220px;
  z-index: -1;
  background: var(--melt-warm);
  filter: blur(36px);
  opacity: 0.85;
  pointer-events: none;
}

/* Tiles + accordions get hairline blueprint corners on hover. */
.tile,
.mb-tile {
  transition: box-shadow var(--fast) var(--ease),
              transform var(--fast) var(--ease);
}
.tile:hover,
.mb-tile:hover {
  box-shadow:
    -4px -4px 0 0 var(--ink),
     4px  4px 0 0 var(--ink);
  transform: translateY(-1px);
}

/* =============================================================
   Reduced motion — every transition we just added respects the
   user's preference.
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  .tile, .mb-tile { transition: none; }
  .sig-meter-bar > span { transition: none; }
  .desc-details-chev { transition: none; }
}

/* =============================================================
   V74.1 — VISIBLE OVERRIDE LAYER
   -------------------------------------------------------------
   Forces the new design language across every existing page
   without touching markup. The utilities above were too quiet;
   this block pulls them onto every card, every section heading,
   every button.
   ============================================================= */

/* ---- Stronger atmospheric body wash. Was ~10% opacity; now
   bold enough to actually read on screen. ---- */
body {
  background:
    radial-gradient(ellipse 1100px 720px at 10% -6%,
      rgba(199,126,94,0.42), transparent 62%),
    radial-gradient(ellipse 900px 620px at 95% 12%,
      rgba(31,74,107,0.32), transparent 60%),
    radial-gradient(ellipse 1100px 700px at 50% 108%,
      rgba(199,126,94,0.22), transparent 65%),
    radial-gradient(ellipse 700px 500px at 78% 84%,
      rgba(183,180,174,0.30), transparent 65%),
    var(--bone) !important;
  background-attachment: fixed;
}

/* ---- Floating spectrum melt over the body so the gradient
   moves a fraction with scroll. Pure CSS, no JS. ---- */
body::before {
  content: "";
  position: fixed;
  inset: -10% -10% -10% -10%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 22% 28%, rgba(199,126,94,0.25), transparent 38%),
    radial-gradient(circle at 78% 18%, rgba(31,74,107,0.20), transparent 42%),
    radial-gradient(circle at 60% 78%, rgba(199,126,94,0.18), transparent 42%);
  filter: blur(80px);
  mix-blend-mode: multiply;
  opacity: 0.55;
}

/* Lift app content above the floating wash. */
#app, .topbar, .modal-root, #modal-root, #toast-root {
  position: relative;
  z-index: 1;
}

/* ---- Every card now reads as a drafting card by default ---- */
.card,
article.card {
  position: relative;
  background: rgba(250, 246, 238, 0.78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--ink);
  border-radius: 0;
}
/* Blueprint corner brackets on every card — top-left + bottom-right. */
.card::before,
.card::after,
article.card::before,
article.card::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border: 1px solid var(--ink);
  pointer-events: none;
  background: var(--bone);
}
.card::before,
article.card::before {
  top: -5px; left: -5px;
  border-right: none; border-bottom: none;
}
.card::after,
article.card::after {
  bottom: -5px; right: -5px;
  border-left: none; border-top: none;
}
.card:hover,
article.card:hover {
  border-color: var(--ink);
  box-shadow: 0 24px 50px -28px rgba(20,17,16,0.35);
}

/* Card-paper variant — slightly lifted from the body but still
   reads as colour-treated. */
.card-paper {
  background: rgba(232, 225, 209, 0.62);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  border-radius: 0;
}

/* Card-ink variant — now reads as a hot copper-to-ink melt
   instead of flat black. */
.card-ink {
  background:
    linear-gradient(135deg,
      rgba(199,126,94,0.18) 0%,
      rgba(20,17,16,1) 55%,
      rgba(31,74,107,0.4) 100%);
  border: 1px solid var(--ink);
}

/* ---- Buttons get a flatter, more confident face. ---- */
.btn {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: 11px !important;
  letter-spacing: 0.16em !important;
  text-transform: uppercase !important;
  padding: 11px 18px !important;
  border-width: 1px !important;
  transition: background var(--fast), border-color var(--fast), color var(--fast);
}
.btn-primary {
  background: var(--ink) !important;
  color: var(--bone) !important;
  border: 1px solid var(--ink) !important;
}
.btn-primary:hover {
  background: var(--signal-cool) !important;
  border-color: var(--signal-cool) !important;
}
.btn-ghost {
  background: transparent !important;
  color: var(--ink) !important;
  border: 1px solid var(--ink) !important;
}
.btn-ghost:hover {
  background: var(--ink) !important;
  color: var(--bone) !important;
}
.btn-oxblood {
  background: var(--signal-warm) !important;
  color: var(--signal-bone) !important;
  border: 1px solid var(--signal-warm) !important;
}
.btn-sm { padding: 7px 13px !important; font-size: 10px !important; }

/* ---- Section codes get the broadcast-pill treatment everywhere. ---- */
.section-code {
  display: inline-flex !important;
  align-items: center;
  gap: 10px;
  font-family: var(--mono) !important;
  font-size: 10px !important;
  letter-spacing: 0.22em !important;
  text-transform: uppercase;
  color: var(--ink-2);
}
.section-code > .num {
  display: inline-block;
  background: var(--ink);
  color: var(--bone);
  padding: 3px 9px;
  letter-spacing: 0.12em;
  font-size: 10px;
  border-radius: 0;
}

/* ---- Display headlines pick up the type-collage feel: tighter
   tracking, more italic confidence on h1/h2 with display class. ---- */
.display-xl, .display-l {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  letter-spacing: -0.025em;
}
.display-m {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.018em;
}

/* ---- Shell header — atmospheric melt behind every page intro. ---- */
.shell-header,
.shell-main > header,
header.shell-header,
.shell > header {
  position: relative;
  isolation: isolate;
  padding-top: var(--s-34);
  padding-bottom: var(--s-21);
}
.shell-header::before {
  content: "";
  position: absolute;
  inset: -34px -55px -10px -55px;
  z-index: -1;
  background:
    radial-gradient(ellipse 600px 320px at 20% 50%,
      rgba(199,126,94,0.55), transparent 65%),
    radial-gradient(ellipse 500px 280px at 85% 35%,
      rgba(31,74,107,0.32), transparent 65%);
  filter: blur(48px);
  opacity: 1;
  pointer-events: none;
}
.shell-header::after {
  /* Bottom hairline with corner ticks acts as the blueprint
     boundary between the page intro and the body content. */
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--ink);
  z-index: -1;
}

/* ---- Topbar / drawer — sharper, lab-equipment feel. ---- */
.topbar {
  background: rgba(243, 238, 228, 0.72) !important;
  backdrop-filter: blur(20px) !important;
  -webkit-backdrop-filter: blur(20px) !important;
  border-bottom: 1px solid var(--ink) !important;
}
.topbar-brand {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  letter-spacing: -0.02em;
}
.side {
  background: rgba(20, 17, 16, 0.96) !important;
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-right: 1px solid var(--ink);
}
.side-link {
  border-radius: 0 !important;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 11px !important;
}
.side-link.active {
  background: var(--signal-warm) !important;
  color: var(--signal-bone) !important;
}

/* ---- Pills + tags get the same broadcast treatment. ---- */
.tag, .pill {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: 10px !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase;
  padding: 4px 10px !important;
  border: 1px solid var(--ink) !important;
  background: var(--cream) !important;
}
.tag-sage  { background: var(--signal-cool) !important; color: var(--signal-bone) !important; border-color: var(--signal-cool) !important; }
.tag-partial { background: var(--signal-acid) !important; color: var(--signal-ink) !important; border-color: var(--signal-ink) !important; }

/* ---- Inputs + textareas tighten to drafting style. ---- */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="url"], input[type="search"],
textarea, select {
  border-radius: 0 !important;
  border: 1px solid var(--ink) !important;
  background: rgba(243, 238, 228, 0.65) !important;
  padding: 10px 12px !important;
  font-family: var(--sans) !important;
}
input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus,
input[type="number"]:focus, input[type="url"]:focus, input[type="search"]:focus,
textarea:focus, select:focus {
  outline: 1px solid var(--signal-warm);
  outline-offset: 2px;
}

/* ---- The credential card (educator code) — signal-style. ---- */
.credential {
  background: var(--ink);
  color: var(--signal-acid);
  font-family: var(--mono);
  letter-spacing: 0.18em;
  border: 1px solid var(--signal-warm);
}

/* ---- HRs become hairlines with ticks. ---- */
hr {
  border: none;
  height: 1px;
  background: var(--ink);
  margin: var(--s-21) 0;
  position: relative;
}

/* ---- Modal frames get the blueprint treatment. ---- */
.modal {
  border-radius: 0 !important;
  border: 1px solid var(--ink) !important;
  background: rgba(250, 246, 238, 0.96) !important;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

/* ---- Tile previews on the file area get sharper edges. ---- */
.tile, .mb-tile {
  border-radius: 0 !important;
}

/* ---- Mood-board tile cover gets a faint colour wash so the
   editorial atmosphere extends into the file area. ---- */
.mb-tile-cover {
  position: relative;
}
.mb-tile-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 30% 30%,
    rgba(199,126,94,0.10), transparent 60%);
  z-index: 1;
}
.mb-tile-cover-live::after {
  background: radial-gradient(ellipse at 30% 30%,
    rgba(199,126,94,0.06), transparent 60%);
}

/* ---- High-contrast mode: respect ---- */
@media (prefers-contrast: more) {
  body::before { display: none; }
  .card { background: var(--cream); backdrop-filter: none; }
}

/* ---- Mobile: tone down the gradient so legibility wins ---- */
@media (max-width: 760px) {
  body::before { opacity: 0.35; filter: blur(60px); }
  .card::before, .card::after,
  article.card::before, article.card::after {
    width: 10px; height: 10px;
  }
}

/* =============================================================
   V75 — HAIR ATLAS PALETTE + DM SERIF DISPLAY TYPOGRAPHY
   -------------------------------------------------------------
   The level system IS the brand palette. L1 (true black) through
   L10 (lightest blonde / platinum) maps directly to the
   foreground / background scale. Undertones (.1 ash · .3 gold
   · .4 copper · .2 iris · .7 matte) sit alongside as accents.
   ACID lime is the single signal colour — used sparingly for
   action, focus, and "you are here".

   Typography goes editorial: DM Serif Display for headlines
   (high-contrast, GT-Sectra-adjacent slab), DM Serif Text for
   medium serif body, Inter for UI sans, JetBrains Mono for
   labels.

   This block overrides V74.1 so it wins the cascade.
   ============================================================= */

:root {
  /* ---- Hair Atlas: L1 → L10 depth scale ---- */
  --L1:  #0A0705;   /* true black */
  --L2:  #19120D;   /* deep brown black */
  --L3:  #29201A;   /* very dark brown */
  --L4:  #44342A;   /* dark brown */
  --L5:  #604838;   /* light brown */
  --L6:  #7E6147;   /* dark blonde */
  --L7:  #9F8362;   /* medium blonde */
  --L8:  #C0A584;   /* light blonde */
  --L9:  #DBC4A4;   /* very light blonde */
  --L10: #F0E4CC;   /* lightest platinum */

  /* ---- Undertone pigments ---- */
  --pig-ash:      #A29E92;   /* .1 cool / neutralise yellow */
  --pig-iris:     #6B5B7D;   /* .2 violet / neutralise yellow */
  --pig-gold:     #C99654;   /* .3 warm */
  --pig-copper:   #B8593A;   /* .4 warm / saturate */
  --pig-mahogany: #7B3A3A;   /* .5 deep red */
  --pig-matte:    #5A6B52;   /* .7 cool / neutralise red */

  /* ---- ACID — the signal colour ---- */
  --acid:       #C7C548;
  --acid-2:     #D6D460;   /* hover */
  --acid-deep:  #8B8A28;   /* pressed / shadow */

  /* ---- Remap legacy tokens onto the atlas so every existing
     selector picks up the new palette without further edits. */
  --bone:        var(--L10);        /* primary ground */
  --paper:       var(--L9);         /* secondary surface */
  --cream:       #F7ECD4;           /* elevated tier */
  --ink:         var(--L1);         /* primary text */
  --ink-2:       var(--L3);         /* secondary text */
  --ink-3:       var(--L6);         /* tertiary / caption */
  --line:        var(--L7);         /* divider */
  --line-soft:   var(--L8);         /* subtle divider */
  --oxblood:     var(--pig-copper); /* legacy accent → copper */
  --oxblood-2:   #D26B4C;
  --champagne:   var(--pig-gold);
  --sage:        var(--pig-matte);
  --clay:        var(--pig-copper);
  --alert:       var(--pig-mahogany);

  /* Signal tokens used by sig-* widgets get pulled into the
     new palette so meters, pills, level cells stay coherent. */
  --signal-ink:    var(--L1);
  --signal-bone:   var(--L10);
  --signal-warm:   var(--pig-copper);
  --signal-cool:   var(--pig-iris);
  --signal-acid:   var(--acid);
  --signal-mute:   var(--pig-ash);

  /* ---- Typography: editorial ---- */
  --display: 'DM Serif Display', 'Fraunces', 'GT Sectra Display',
             'Didot', 'Times New Roman', serif;
  --serif:   'DM Serif Text', 'DM Serif Display', 'Fraunces',
             'Source Serif Pro', serif;
  --sans:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
             system-ui, sans-serif;
  --mono:    'JetBrains Mono', 'IBM Plex Mono', 'GT America Mono',
             ui-monospace, monospace;
}

/* ===== Re-issue the atmospheric body wash with the new palette.
   Warm L9 + L8 with a single acid breath through the upper-right
   so the level system + signal accent both read at first glance. */
body {
  background:
    radial-gradient(ellipse 1100px 720px at 10% -6%,
      rgba(184, 89, 58, 0.32), transparent 62%),
    radial-gradient(ellipse 900px 620px at 96% 14%,
      rgba(199, 197, 72, 0.18), transparent 55%),
    radial-gradient(ellipse 1100px 700px at 50% 108%,
      rgba(107, 91, 125, 0.20), transparent 65%),
    radial-gradient(ellipse 700px 500px at 78% 84%,
      rgba(162, 158, 146, 0.26), transparent 65%),
    var(--L10) !important;
  background-attachment: fixed;
  color: var(--L2);
}
body::before {
  background:
    radial-gradient(circle at 22% 28%, rgba(184, 89, 58, 0.24), transparent 38%),
    radial-gradient(circle at 78% 18%, rgba(107, 91, 125, 0.22), transparent 42%),
    radial-gradient(circle at 60% 78%, rgba(184, 89, 58, 0.16), transparent 42%);
}

/* ===== Re-issue typography on every display class. ===== */
.display,
.display-xxl,
.display-xl,
.display-l,
.display-m,
h1, h2, h3,
.tc-head {
  font-family: var(--display) !important;
  font-weight: 400 !important;
  font-style: normal;
  font-feature-settings: "kern", "liga", "ss01";
}
/* Italics on DM Serif Display are dramatic — use sparingly on
   subtitle accents, not on every display headline (which now
   sit upright). */
.display-italic,
.tc-head[data-italic],
em.display,
.display.italic {
  font-style: italic !important;
  font-family: var(--display) !important;
}

/* Headline scale (DM Serif Display reads heavier than Fraunces
   so the sizes drop a touch). */
.display-xxl { font-size: clamp(56px, 11vw, 156px); line-height: 0.88; letter-spacing: -0.025em; }
.display-xl  { font-size: clamp(40px, 7vw, 92px);   line-height: 0.92; letter-spacing: -0.02em; }
.display-l   { font-size: clamp(30px, 4.6vw, 52px); line-height: 1.0;  letter-spacing: -0.015em; }
.display-m   { font-size: clamp(24px, 3vw, 34px);   line-height: 1.08; letter-spacing: -0.01em; }

/* Body text — Inter, slightly tighter than the default for that
   modern editorial feel. */
body {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: -0.005em;
}
p, li, dd, dt {
  font-family: var(--sans);
}
/* Body serif — when you want long-form reading text in the
   editorial register, swap to DM Serif Text. */
.body-serif {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.55;
  letter-spacing: 0;
}

/* Mono labels everywhere — tighter cap-height for the editorial
   feel. JetBrains Mono is good but the letter-spacing in v74 was
   slightly loose; tighten it here. */
.meta, .eyebrow, .code, .caption,
.section-code, .section-code > .num,
.btn, .sig-pill, .pill, .tag {
  font-family: var(--mono) !important;
  letter-spacing: 0.12em !important;
}

/* Buttons get the ACID accent on hover so the action colour
   shows up the moment the user reaches for anything. */
.btn-primary {
  background: var(--L1) !important;
  color: var(--L10) !important;
  border: 1px solid var(--L1) !important;
}
.btn-primary:hover {
  background: var(--acid) !important;
  color: var(--L1) !important;
  border-color: var(--acid-deep) !important;
}
.btn-ghost:hover {
  background: var(--L1) !important;
  color: var(--acid) !important;
}

/* The new signal-acid colour: used for the "live" indicator dot,
   level meter fills, focus rings, and the active drawer link. */
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--acid) !important;
  outline-offset: 2px;
}
.sig-pill.live .sig-dot,
.sig-dot.acid       { background: var(--acid); }
.sig-meter-bar.acid > span { background: var(--acid); }
.credential {
  background: var(--L1);
  color: var(--acid);
  border: 1px solid var(--acid-deep);
}

/* Active drawer link — copper background was nice but acid is
   the brand. Swap. */
.side-link.active {
  background: var(--acid) !important;
  color: var(--L1) !important;
}

/* The section-code num pill becomes acid so each page's
   "0.3 STUDIO" marker reads as the brand's signature. */
.section-code > .num {
  background: var(--L1) !important;
  color: var(--acid) !important;
}

/* ===== Shell header — atlas-tinted melt ===== */
.shell-header::before {
  background:
    radial-gradient(ellipse 600px 320px at 20% 50%,
      rgba(184, 89, 58, 0.45), transparent 65%),
    radial-gradient(ellipse 500px 280px at 85% 35%,
      rgba(199, 197, 72, 0.22), transparent 65%) !important;
}

/* ===== Cards — frosted L9 paper over the atlas wash ===== */
.card,
article.card {
  background: rgba(247, 236, 212, 0.78) !important;
  border-color: var(--L1) !important;
}
.card-paper {
  background: rgba(219, 196, 164, 0.55) !important;
  border-color: var(--L7) !important;
}
.card-ink {
  background:
    linear-gradient(135deg,
      rgba(184, 89, 58, 0.22) 0%,
      var(--L1) 55%,
      rgba(107, 91, 125, 0.45) 100%) !important;
  color: var(--L10) !important;
  border-color: var(--L1) !important;
}

/* Mood-board tile cover gets the acid breath. */
.mb-tile-cover::after {
  background: radial-gradient(ellipse at 30% 30%,
    rgba(184, 89, 58, 0.10), transparent 60%) !important;
}

/* Hero / shell sub-text — pull subtitle into the serif italic
   for that magazine-cover feel. Used by the shell's `sub` field
   automatically since the shell.js renders it as a serif em. */
.shell-header .shell-sub,
.shell-sub,
.shell-header em {
  font-family: var(--display) !important;
  font-style: italic !important;
  font-weight: 400;
  color: var(--ink-2);
}

/* Selection highlight in acid. */
::selection { background: var(--acid); color: var(--L1); }

/* =============================================================
   V75.1 — COOL PANTONE WASH + INSTRUMENT SERIF
   -------------------------------------------------------------
   The V75 warm L10 cream felt too "boutique stationery". This
   block cools the whole site into Pantone gallery-wall territory
   (think Lichen Blue 14-4505 meets Silver Lining 14-4504), and
   swaps the display face from DM Serif Display (too decorative)
   to Instrument Serif (the restrained editorial serif used by
   the cool studios right now). Inter + JetBrains Mono stay.

   Acid lime stays as the single signal colour — it reads cleaner
   over a cool ground than over the warm cream it sat on before.
   ============================================================= */

:root {
  /* ---- Pantone-anchored cool studio palette ---- */
  /* Body ground sits between Pantone 12-4304 Lichen Blue and
     11-4302 Bay — a near-white with a cool blue-grey breath. */
  --paper-cool-1: #ECEEEA;   /* lightest — body */
  --paper-cool-2: #E2E5E1;   /* paper layer */
  --paper-cool-3: #D2D7D3;   /* divider tier */
  --paper-cool-4: #B7C0BD;   /* deep divider */
  --paper-cool-5: #8A9590;   /* secondary text */

  /* Pantone accents in the wash ---------------------------- */
  --pt-lichen:    #B7C5CC;   /* 14-4505 Lichen Blue */
  --pt-bay:       #C7D2D2;   /* 12-4304 Bay */
  --pt-silver:    #C8C7BD;   /* 14-4504 Silver Lining */
  --pt-pewter:    #A5A39A;
  --pt-mocha:     #A47864;   /* 17-1230 Mocha Mousse — used very sparingly */
  --pt-cinder:    #4A4D4F;

  /* Remap the legacy tokens onto the cool palette. Hair-system
     undertones (copper / iris / acid) are kept for accents
     because they're the brand — only the SURFACE goes cool. */
  --bone:      var(--paper-cool-1) !important;
  --paper:     var(--paper-cool-2) !important;
  --cream:     #F4F5F2 !important;     /* elevated tier */
  --L10:       var(--paper-cool-1) !important;
  --L9:        var(--paper-cool-2) !important;
  --L8:        var(--paper-cool-3) !important;
  --L7:        var(--paper-cool-4) !important;
  --line:      var(--paper-cool-4) !important;
  --line-soft: var(--paper-cool-3) !important;
  --ink-3:     var(--paper-cool-5) !important;

  /* ---- Typography swap: Instrument Serif as the new display. ---- */
  --display: 'Instrument Serif', 'GT Sectra Display', 'Fraunces',
             'Source Serif Pro', 'Times New Roman', serif;
  --serif:   'Instrument Serif', 'Fraunces', 'Source Serif Pro', serif;
}

/* ===== Body wash — cool studio gradient ===== */
body {
  background:
    radial-gradient(ellipse 1100px 720px at 10% -6%,
      rgba(183, 197, 204, 0.55), transparent 62%),
    radial-gradient(ellipse 900px 620px at 95% 14%,
      rgba(199, 197, 72, 0.10), transparent 55%),
    radial-gradient(ellipse 1100px 700px at 50% 108%,
      rgba(165, 163, 154, 0.34), transparent 65%),
    radial-gradient(ellipse 700px 500px at 78% 84%,
      rgba(184, 89, 58, 0.12), transparent 65%),
    var(--paper-cool-1) !important;
  background-attachment: fixed;
  color: var(--L2);
}
body::before {
  background:
    radial-gradient(circle at 22% 28%, rgba(183, 197, 204, 0.30), transparent 38%),
    radial-gradient(circle at 78% 18%, rgba(74, 77, 79, 0.12), transparent 42%),
    radial-gradient(circle at 60% 78%, rgba(184, 89, 58, 0.08), transparent 42%);
  filter: blur(80px);
}

/* ===== Re-issue typography on every display class with
   Instrument Serif. Restrained, narrow, italic-leaning. ===== */
.display,
.display-xxl,
.display-xl,
.display-l,
.display-m,
h1, h2, h3,
.tc-head {
  font-family: 'Instrument Serif', 'Fraunces', serif !important;
  font-weight: 400 !important;
  font-style: normal;
  letter-spacing: -0.012em !important;
  font-feature-settings: "kern", "liga";
}
/* Instrument Serif's italic is its signature — use it on the
   biggest headline tier so the editorial cadence reads
   immediately. */
.display-xxl,
.display-xl {
  font-style: italic !important;
}
/* Instrument Serif reads tighter than DM Serif Display so the
   sizes need to climb a notch. */
.display-xxl { font-size: clamp(64px, 13vw, 196px); line-height: 0.88; letter-spacing: -0.03em; }
.display-xl  { font-size: clamp(44px, 8vw, 116px);  line-height: 0.92; letter-spacing: -0.025em; }
.display-l   { font-size: clamp(32px, 5vw, 64px);   line-height: 0.98; letter-spacing: -0.018em; }
.display-m   { font-size: clamp(26px, 3.4vw, 42px); line-height: 1.08; letter-spacing: -0.012em; }

/* Shell header — cool melt instead of the warm copper one. */
.shell-header::before {
  background:
    radial-gradient(ellipse 600px 320px at 20% 50%,
      rgba(183, 197, 204, 0.55), transparent 65%),
    radial-gradient(ellipse 500px 280px at 85% 35%,
      rgba(199, 197, 72, 0.16), transparent 65%),
    radial-gradient(ellipse 400px 240px at 50% 70%,
      rgba(184, 89, 58, 0.10), transparent 65%) !important;
}

/* Cards — frosted cool-paper plates over the wash. */
.card,
article.card {
  background: rgba(244, 245, 242, 0.78) !important;
  border-color: var(--L1) !important;
}
.card-paper {
  background: rgba(226, 229, 225, 0.62) !important;
  border-color: var(--paper-cool-4) !important;
}
.card-ink {
  background:
    linear-gradient(135deg,
      rgba(183, 197, 204, 0.18) 0%,
      var(--L1) 55%,
      rgba(184, 89, 58, 0.30) 100%) !important;
}

/* Topbar / drawer in cool tones. */
.topbar {
  background: rgba(236, 238, 234, 0.78) !important;
}
.side {
  background: rgba(10, 7, 5, 0.97) !important;
}

/* Mood-board tile cover keeps a very faint copper breath so the
   creative surface still feels colour-aware. */
.mb-tile-cover::after {
  background: radial-gradient(ellipse at 30% 30%,
    rgba(184, 89, 58, 0.08), transparent 60%) !important;
}

/* Inputs sit on cool paper instead of warm. */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="url"], input[type="search"],
textarea, select {
  background: rgba(236, 238, 234, 0.72) !important;
}

/* Theme-color meta in the manifest can't be live-updated from CSS
   so this is the cool-equivalent for any other places that read
   the legacy oxblood var. */
:root { --oxblood-2: var(--pt-mocha); }

/* =============================================================
   V75.2 — JETBRAINS MONO EVERYWHERE
   -------------------------------------------------------------
   Every text element on the site uses JetBrains Mono. Whole app
   reads as a single typographic register: technical, lab-grade,
   intentional. Display tiers stay big and weighty; body stays
   readable by tightening the letter-spacing (mono fonts ship
   wide by default which kills long-form legibility).

   The display vs body distinction is now WEIGHT + SIZE only,
   not face. Italics stay italic for accents (subtitle, ghost
   layers, "Welcome, Finlee" register). Acid lime accent + cool
   Pantone wash from V75.1 are preserved underneath.
   ============================================================= */

:root {
  /* Promote JetBrains Mono to the primary face across the system. */
  --display: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
  --serif:   'JetBrains Mono', ui-monospace, monospace !important;
  --sans:    'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
  --mono:    'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
}

/* ---- Body + every prose element ---- */
html, body,
p, li, dd, dt, blockquote, figcaption,
input, textarea, select, button, a,
.body, .body-sm, .body-lg, .body-serif,
.caption, .meta, .eyebrow, .code,
.desc-details-content, .desc-details-summary,
.field-block, .field label,
.shell-sub, .shell-title,
.tile, .tile-title, .tile-foot, .tile-type,
.lesson-list, .lesson-title, .lesson-status, .lesson-type {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
}

/* Body register: tighten the tracking so paragraphs are
   actually readable. JetBrains Mono is a programming font —
   wide by default — so we pull -0.02em out of the spacing for
   body copy. Slightly smaller too. */
body {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
  font-size: 14px;
  line-height: 1.55;
  letter-spacing: -0.015em;
  font-weight: 400;
}
p {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
  letter-spacing: -0.012em;
  line-height: 1.6;
}
.body, .body-sm, .body-serif {
  letter-spacing: -0.012em;
  line-height: 1.6;
}
.body-lg {
  font-size: 17px;
  letter-spacing: -0.018em;
  line-height: 1.55;
}

/* ---- Display tier: SAME face, just weight + size to feel like
   headlines instead of paragraphs. Italics on top-tier headlines
   so the editorial cadence still reads. ---- */
.display,
.display-xxl, .display-xl, .display-l, .display-m,
h1, h2, h3, h4, h5, h6,
.tc-head,
.display-italic {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace !important;
  font-weight: 500 !important;
  font-style: normal !important;
  letter-spacing: -0.04em !important;
  font-feature-settings: "kern", "liga", "ss01", "ss02";
}
.display-xxl {
  font-size: clamp(48px, 9.5vw, 144px);
  line-height: 0.92;
  letter-spacing: -0.055em !important;
  font-weight: 600 !important;
}
.display-xl {
  font-size: clamp(36px, 6.5vw, 96px);
  line-height: 0.94;
  letter-spacing: -0.05em !important;
  font-weight: 600 !important;
}
.display-l {
  font-size: clamp(28px, 4.2vw, 56px);
  line-height: 1.0;
  letter-spacing: -0.04em !important;
  font-weight: 500 !important;
}
.display-m {
  font-size: clamp(22px, 2.8vw, 34px);
  line-height: 1.1;
  letter-spacing: -0.035em !important;
  font-weight: 500 !important;
}

/* Italic accent — only on the shell-sub ("Welcome, Finlee."
   register) and on intentional .italic / em.display markers. */
.shell-sub,
.shell-header em,
.display-xl em,
.display-l em,
em.display,
.display.italic {
  font-style: italic !important;
  font-weight: 400 !important;
  color: var(--ink-2);
}

/* ---- Labels (mono caps): keep the wide tracking only here. ---- */
.meta, .eyebrow, .code, .caption,
.section-code, .section-code > .num,
.btn, .sig-pill, .pill, .tag,
.lesson-type, .tile-type,
.cs-line-label,
.desc-details > summary {
  letter-spacing: 0.12em !important;
  text-transform: uppercase !important;
}

/* Section-code num pill — acid letters keep wide tracking. */
.section-code > .num {
  letter-spacing: 0.06em !important;
}

/* Inputs in mono — the form FEELS like a console now. */
input, textarea, select {
  font-family: 'JetBrains Mono', ui-monospace, monospace !important;
  letter-spacing: -0.01em !important;
  font-size: 14px !important;
}

/* The topbar wordmark — keep mono too. */
.topbar-brand {
  font-family: 'JetBrains Mono', ui-monospace, monospace !important;
  font-style: normal !important;
  font-weight: 600 !important;
  letter-spacing: -0.02em !important;
}

/* Smooth out font rendering for the heavier mono weights. */
body, button, input, textarea, select {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* =============================================================
   V75.3 — MOBILE LAYOUT + ASSIGNED-PILL CONTRAST FIX
   -------------------------------------------------------------
   Two real bugs:

   1. Case-study + quiz cards squash their title block to zero
      width on phones because the action buttons (Analytics /
      Edit / Delete + Average stat) eat the entire row, and
      JetBrains Mono falls back to character-by-character wrap
      ("E / s / s / e / n / t / i / a / l / s"). Forcing the
      title row + actions row to stack vertically below 760px
      gives the eyebrow its full width back.

   2. Assigned-student pills disappeared because V75 added
      `background: var(--cream) !important` on .pill, which beat
      the inline `style="background: var(--ink)"` that
      educator.js sets for the active state. Drop the !important
      so the inline style wins; the active pill goes ink-dark
      with bone-light text again.
   ============================================================= */

/* ---- 1 · Mobile layout for cards ---- */
@media (max-width: 760px) {
  /* Any flex row inside a card that says "space-between, wrap"
     stacks vertically on phones so the title gets full width. */
  .card > .flex.jc-sb,
  .card > .flex.ai-e.jc-sb,
  .card > .flex.ai-c.jc-sb,
  article.card > .flex.jc-sb,
  article.card > .flex.ai-e.jc-sb,
  article.card > .flex.ai-c.jc-sb {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 13px !important;
  }
  /* Stat values + analytics column on the right used to be 160px
     min-width; release that on mobile. */
  article.card [style*="min-width: 160px"],
  article.card [style*="minWidth"] {
    min-width: 0 !important;
    text-align: left !important;
  }
  /* Action button row inside the card now stretches full-width
     and wraps freely. */
  .card .flex.gap-13.fw-w,
  article.card .flex.gap-13.fw-w {
    width: 100%;
    flex-wrap: wrap;
  }
  .card .flex.gap-13.fw-w > .btn,
  article.card .flex.gap-13.fw-w > .btn {
    flex: 1 1 auto;
    min-width: 90px;
  }
  /* Section-code eyebrow must NEVER wrap character-by-character.
     Force normal word-break + allow inline-flex contents to wrap
     at natural word boundaries. */
  .section-code,
  .section-code * {
    word-break: keep-all !important;
    overflow-wrap: normal !important;
  }
  .section-code {
    flex-wrap: wrap !important;
    min-width: 0;
    row-gap: 6px;
  }
  /* Card titles use a serif-like display anyway; ensure they too
     never break inside a word on phone widths. */
  .card .display-m,
  .card .display-l,
  article.card .display-m,
  article.card .display-l {
    word-break: keep-all !important;
    overflow-wrap: break-word !important;
    hyphens: none !important;
  }
  /* Tighten the display font sizes on mobile so headlines fit. */
  .card .display-m,
  article.card .display-m {
    font-size: 22px !important;
    letter-spacing: -0.025em !important;
  }
}

/* ---- 2 · Pill contrast for assigned state ----
   educator.js sets the active state via inline style:
   style="background: var(--ink); color: var(--bone); border-color: var(--ink)"
   The V75 !important rule was beating that. Re-issue the .pill
   base with NO !important on background/color so the inline
   style wins for active pills, then add a high-contrast
   "is-active" rule for any new code that uses the class instead. */
.tag, .pill {
  border-radius: 0 !important;
  font-family: 'JetBrains Mono', monospace !important;
  font-size: 10px !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase;
  padding: 5px 11px !important;
  border: 1px solid var(--L1) !important;
  background: var(--cream);   /* no !important — inline style wins */
  color: var(--L1);           /* no !important — inline style wins */
  cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.tag:hover, .pill:hover {
  background: var(--L1);
  color: var(--acid);
}
.pill.is-active,
.pill[aria-pressed="true"] {
  background: var(--L1) !important;
  color: var(--acid) !important;
  border-color: var(--L1) !important;
}

/* The legacy active inline style sets color to var(--bone), which
   under V75 is the new cool-grey #ECEEEA — nearly invisible on
   the dark ink background. Force any pill that has background:
   var(--ink) inline to ALSO read in the brighter bone tone. */
.pill[style*="--ink"],
.pill[style*="var(--ink)"] {
  color: var(--paper-cool-1) !important;
}

/* =============================================================
   V76 — ASSIGNMENT CONTROL
   -------------------------------------------------------------
   Two-button row with a dropdown panel (pick who has access) and
   a side panel (see who already has access). Both panels open
   inside the .assign-control wrapper.
   ============================================================= */
.assign-control {
  /* V76.2 — no longer position: relative because the dropdown is
     now inline. Keeps cards from creating an unnecessary stacking
     context. */
  margin-top: 8px;
}
.assign-triggers {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.assign-trigger-main,
.assign-trigger-side {
  font-family: 'JetBrains Mono', monospace !important;
  font-size: 11px !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase;
  padding: 9px 14px !important;
}

/* ---- Dropdown panel (full apprentice list with toggle).
   V76.2 — rendered INLINE inside the card so the card just grows
   in height when opened. The original absolutely-positioned
   version sat on top of (or under) the next card and clipped the
   list. Inline keeps everything in document flow and never
   collides with anything. ---- */
.assign-dropdown {
  display: none;
  margin-top: 10px;
  max-height: 360px;
  overflow-y: auto;
  background: rgba(247, 245, 240, 0.96);
  border: 1px solid var(--L1);
  padding: 13px;
}
.assign-control.dropdown-open .assign-dropdown {
  display: block;
}
.assign-dropdown-header {
  padding-bottom: 10px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--paper-cool-3);
}
.assign-dropdown-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.assign-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 1px solid transparent;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--L1);
  cursor: pointer;
  text-align: left;
  transition: background var(--fast), border-color var(--fast);
}
.assign-row:hover {
  background: var(--paper-cool-2);
  border-color: var(--paper-cool-4);
}
.assign-row.is-on {
  background: var(--L1);
  color: var(--acid);
  border-color: var(--L1);
}
.assign-row-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 1px solid currentColor;
  font-size: 12px;
  line-height: 1;
  flex: 0 0 18px;
}
.assign-row.is-on .assign-row-check {
  background: var(--acid);
  color: var(--L1);
  border-color: var(--acid);
}
.assign-row-name {
  flex: 1;
}

/* ---- Side panel (who already has access). ---- */
.assign-side {
  display: none;
  margin-top: 13px;
  padding: 16px;
  border: 1px solid var(--paper-cool-4);
  background: rgba(236, 238, 234, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.assign-control.side-open .assign-side {
  display: block;
}
.assign-side-header {
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--paper-cool-3);
}
.assign-side-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.assign-side-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 13px;
  padding: 8px 0;
  border-bottom: 1px dashed var(--paper-cool-3);
}
.assign-side-row:last-child {
  border-bottom: none;
}
.assign-side-name {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  letter-spacing: -0.005em;
  color: var(--L1);
}
.assign-side-revoke {
  border: 1px solid var(--L1);
  background: transparent;
  color: var(--L1);
  width: 26px;
  height: 26px;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.assign-side-revoke:hover {
  background: var(--pig-copper);
  color: var(--L10);
  border-color: var(--pig-copper);
}

/* Mobile — tighten padding so the dropdown reads cleanly on phones. */
@media (max-width: 760px) {
  .assign-dropdown { padding: 10px; max-height: 320px; }
}

/* V76.1 — orphan-row indicator. Used when an apprentice was once
   assigned but is no longer in the educator's roster. */
.assign-row.is-orphan {
  opacity: 0.78;
}
.assign-row-tag {
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px;
  letter-spacing: 0.18em;
  padding: 2px 6px;
  border: 1px solid currentColor;
  margin-left: auto;
  flex: 0 0 auto;
  text-transform: uppercase;
}
.assign-empty {
  padding: 13px 16px;
  border: 1px dashed var(--paper-cool-4);
  background: rgba(236, 238, 234, 0.5);
}

/* =============================================================
   V77 STUDIO — unified workshop surface.
   ============================================================= */
.studio-shell {
  display: flex;
  flex-direction: column;
  gap: 34px;
}

.studio-actionbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.5);
}
.studio-actionbar .studio-action-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.6;
  padding-right: 8px;
  flex: 0 0 auto;
}

/* Folder grid — every module + every custom folder + Unfiled. */
.studio-folder-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 13px;
}
.studio-folder-tile {
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--L1, var(--line));
  background: var(--folder-tint, var(--cream));
  padding: 16px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
  text-align: left;
  font-family: var(--mono);
  color: var(--ink);
}
.studio-folder-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 28px -18px rgba(20, 17, 16, 0.45);
  border-color: var(--ink);
}
.studio-folder-tile.is-active {
  outline: 2px solid var(--ink);
  outline-offset: -1px;
}
.studio-folder-tile .ft-kind {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.6;
}
.studio-folder-tile .ft-name {
  font-family: var(--mono);
  font-size: 18px;
  line-height: 1.2;
  font-weight: 500;
  word-break: break-word;
  margin-top: 8px;
}
.studio-folder-tile .ft-counts {
  margin-top: auto;
  font-size: 11px;
  letter-spacing: 0.05em;
  opacity: 0.7;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.studio-folder-tile .ft-counts span { white-space: nowrap; }
.studio-folder-tile .ft-tools {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.14s ease;
}
.studio-folder-tile:hover .ft-tools { opacity: 1; }
.studio-folder-tile .ft-tool {
  width: 24px;
  height: 24px;
  border: 1px solid var(--ink);
  background: rgba(247, 245, 240, 0.92);
  font-family: var(--mono);
  font-size: 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.studio-folder-tile.is-add {
  background: transparent;
  border: 1px dashed var(--ink);
  align-items: center;
  justify-content: center;
  color: var(--ink);
  opacity: 0.8;
}
.studio-folder-tile.is-add:hover { opacity: 1; }
.studio-folder-tile.is-add .ft-plus {
  font-family: var(--mono);
  font-size: 32px;
  font-weight: 300;
}

/* Folder detail header. */
.studio-folder-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 13px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--L1, var(--line));
}
.studio-folder-head .head-title {
  font-family: var(--mono);
  font-size: 24px;
  line-height: 1.1;
}
.studio-folder-head .head-eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.6;
}
.studio-folder-head .head-back {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 6px 10px;
  background: transparent;
  cursor: pointer;
}

/* Item-type section heading inside a folder view. */
.studio-section-head {
  display: flex;
  align-items: baseline;
  gap: 13px;
  margin: 21px 0 10px;
  font-family: var(--mono);
}
.studio-section-head .num {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.55;
}
.studio-section-head .title {
  font-size: 16px;
  font-weight: 500;
}
.studio-empty-row {
  padding: 16px;
  border: 1px dashed var(--L1, var(--line));
  font-family: var(--mono);
  font-size: 12px;
  opacity: 0.6;
  text-align: center;
}

/* Item rows — a compact unified card for any item type. */
.studio-item-row {
  display: grid;
  grid-template-columns: 70px 1fr auto;
  gap: 13px;
  align-items: center;
  padding: 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.4);
  margin-bottom: 8px;
}
.studio-item-row .kind-chip {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 6px;
  border: 1px solid var(--ink);
  text-align: center;
  align-self: start;
}
.studio-item-row .meta-line {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0.65;
  margin-bottom: 4px;
}
.studio-item-row .title-line {
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.25;
}
.studio-item-row .ctrls {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}
.studio-item-row .ctrls .btn { padding: 6px 10px; font-size: 11px; }
@media (max-width: 720px) {
  .studio-item-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .studio-item-row .ctrls { justify-content: flex-start; }
}

/* Folder picker on the create-item modals. */
.studio-folder-picker {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.studio-folder-picker label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--L1, var(--line));
  font-family: var(--mono);
  font-size: 12px;
  cursor: pointer;
}
.studio-folder-picker label.is-on {
  background: var(--ink);
  color: var(--paper);
}

/* =============================================================
   V78 — folder photo customisation.
   ============================================================= */
.studio-folder-tile.has-image {
  background:
    linear-gradient(180deg, rgba(20, 17, 16, 0) 0%, rgba(20, 17, 16, 0) 40%, rgba(20, 17, 16, 0.78) 100%),
    var(--folder-image) center/cover no-repeat;
  color: #fff;
}
.studio-folder-tile.has-image .ft-kind,
.studio-folder-tile.has-image .ft-counts {
  color: #f4f1ec;
  opacity: 0.95;
}
.studio-folder-tile.has-image .ft-name { color: #fff; }
.studio-folder-tile.has-image .ft-tool {
  background: rgba(20, 17, 16, 0.5);
  color: #fff;
  border-color: rgba(255,255,255,0.85);
}
.studio-folder-tile.has-image .ft-body {
  text-shadow: 0 1px 6px rgba(20, 17, 16, 0.65);
}

/* Folder modal preview box. */
.studio-folder-preview {
  height: 140px;
  border: 1px solid var(--L1, var(--line));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  position: relative;
}
.studio-folder-preview .meta {
  background: rgba(247, 245, 240, 0.85);
  padding: 4px 8px;
  border: 1px solid rgba(20, 17, 16, 0.3);
}

/* =============================================================
   V78 — THE LOUNGE (educator feed).
   ============================================================= */
.lounge-feed {
  display: flex;
  flex-direction: column;
  gap: 21px;
  max-width: 640px;
  margin: 0 auto;
}
.lounge-post {
  background: rgba(247, 245, 240, 0.6);
  border: 1px solid var(--L1, var(--line));
  padding: 21px;
  font-family: var(--mono);
}
.lounge-post-head {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-bottom: 13px;
}
.lounge-post-author { flex: 1; min-width: 0; }
.lounge-post-name {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.lounge-post-date {
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0.6;
}
.lounge-post-body {
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-wrap;
  margin: 0 0 13px;
}
.lounge-post-image {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  border: 1px solid var(--L1, var(--line));
  cursor: pointer;
  padding: 0;
  margin-bottom: 13px;
}
.lounge-anon-av {
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono);
  font-size: 20px;
  flex-shrink: 0;
}
.lounge-anon-av.sm {
  width: 32px; height: 32px; font-size: 14px;
}

/* Replies */
.lounge-replies {
  margin-top: 13px;
  padding-top: 13px;
  border-top: 1px solid var(--L1, var(--line));
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.lounge-reply {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.lounge-reply-body { flex: 1; min-width: 0; }
.lounge-reply-name { font-family: var(--mono); font-size: 12px; font-weight: 500; }
.lounge-reply-date { font-family: var(--mono); font-size: 11px; opacity: 0.55; }
.lounge-reply-text {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  margin: 0 0 6px;
}
.lounge-reply-image {
  display: block;
  width: 50%;
  max-width: 240px;
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  border: 1px solid var(--L1, var(--line));
  cursor: pointer;
  padding: 0;
}
.lounge-reply-del {
  font-family: var(--mono);
  font-size: 14px;
  background: transparent;
  border: none;
  cursor: pointer;
  opacity: 0.5;
  padding: 0 4px;
}
.lounge-reply-del:hover { opacity: 1; color: var(--oxblood, #6b1d1d); }

/* Reply composer */
.lounge-reply-form {
  margin-top: 4px;
  padding: 10px 13px;
  background: rgba(247, 245, 240, 0.5);
  border: 1px solid var(--L1, var(--line));
}
.lounge-reply-input {
  width: 100%;
  border: none;
  background: transparent;
  font-family: var(--mono);
  font-size: 13px;
  resize: vertical;
  padding: 4px 0;
  outline: none;
  min-height: 32px;
}
.lounge-pill {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border: 1px solid var(--ink);
  background: transparent;
  cursor: pointer;
}
.lounge-pill.toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.lounge-pill.toggle input { margin: 0; }

/* Composer modal */
.lounge-composer-preview {
  margin-top: 13px;
  height: 200px;
  background-size: cover;
  background-position: center;
  border: 1px solid var(--L1, var(--line));
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
}
.lounge-composer-preview.small { height: 120px; }
.lounge-anon-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  padding: 4px 10px;
  border: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}
.lounge-anon-toggle input { margin: 0; }

/* V79 — Edit pill on the folder detail header. */
.studio-folder-head .head-title-row {
  display: flex;
  align-items: center;
  gap: 13px;
  flex-wrap: wrap;
}
.studio-folder-head .head-edit {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 6px 12px;
  border: 1px solid var(--ink);
  background: transparent;
  cursor: pointer;
  color: var(--ink);
}
.studio-folder-head .head-edit:hover {
  background: var(--ink);
  color: var(--paper);
}

/* =============================================================
   V79 — FILL-IN-THE-BLANK editor + attempt.
   ============================================================= */
.fb-form .fb-body {
  width: 100%;
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.55;
  padding: 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.55);
}
.fb-blanks-list {
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.fb-blank-row {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 13px;
  align-items: start;
  padding: 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.4);
}
.fb-blank-num {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 6px 8px;
  background: var(--ink);
  color: var(--paper);
  text-align: center;
}
.fb-blank-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 13px;
}
@media (max-width: 720px) {
  .fb-blank-row { grid-template-columns: 1fr; }
  .fb-blank-cols { grid-template-columns: 1fr; }
}
.fb-alias-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 10px;
  background: var(--paper-cool-0, rgba(247, 245, 240, 0.4));
  border: 1px solid var(--L1, var(--line));
  min-height: 36px;
  align-items: center;
}
.fb-alias-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  background: var(--cream, #eee);
  border: 1px solid var(--L1, var(--line));
}
.fb-alias-x {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
}

/* Apprentice attempt */
.fb-attempt-card {
  padding: 34px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.45);
}
.fb-attempt-body {
  font-family: var(--mono);
  font-size: 18px;
  line-height: 2;
  margin: 0;
}
.fb-answer {
  display: inline-block;
  font-family: var(--mono);
  font-size: 16px;
  line-height: 1.4;
  padding: 4px 10px;
  margin: 0 4px;
  border: none;
  border-bottom: 2px solid var(--ink);
  background: transparent;
  min-width: 100px;
  width: auto;
  outline: none;
}
.fb-answer.ok    { border-color: #2a7a3a; background: rgba(60, 140, 80, 0.12); }
.fb-answer.wrong { border-color: #8c2a2a; background: rgba(140, 60, 60, 0.12); }
.fb-score-box {
  margin-top: 21px;
  padding: 21px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
}
.fb-score-num {
  font-family: var(--mono);
  font-size: 48px;
  line-height: 1;
  margin-bottom: 8px;
}
.fb-score-sub {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.8;
}

/* =============================================================
   V79 — DRAG-AND-DROP MATCH editor + attempt.
   ============================================================= */
.match-pairs-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.match-row {
  display: grid;
  grid-template-columns: 40px 1fr 22px 1fr 30px;
  gap: 10px;
  align-items: center;
  padding: 8px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.4);
}
.match-num {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-align: center;
  opacity: 0.6;
}
.match-arrow {
  font-family: var(--mono);
  font-size: 14px;
  text-align: center;
  opacity: 0.55;
}
.match-row-x {
  font-family: var(--mono);
  font-size: 16px;
  background: transparent;
  border: none;
  cursor: pointer;
  opacity: 0.5;
}
.match-row-x:hover { opacity: 1; color: var(--oxblood, #6b1d1d); }

/* Apprentice match attempt */
.match-attempt {
  padding: 21px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.4);
}
.match-board {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 21px;
}
@media (max-width: 720px) {
  .match-board { grid-template-columns: 1fr; }
}
.match-col-head {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.6;
  margin-bottom: 13px;
}
.match-col-left {}
.match-col-right .match-pool {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 80px;
  padding: 13px;
  border: 1px dashed var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.5);
}
.match-row-attempt {
  display: grid;
  grid-template-columns: 1fr 22px 1fr;
  gap: 8px;
  align-items: center;
  padding: 6px 8px;
  margin-bottom: 8px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.6);
  font-family: var(--mono);
  font-size: 13px;
}
.match-row-left { padding: 6px 4px; }
.match-row-arrow {
  font-family: var(--mono);
  font-size: 14px;
  text-align: center;
  opacity: 0.55;
}
.match-row-slot {
  min-height: 36px;
  padding: 4px;
  border: 1px dashed var(--ink);
  background: rgba(247, 245, 240, 0.5);
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 12px;
}
.match-row-slot.over { background: rgba(199, 197, 72, 0.25); }
.match-row-slot.filled { border-style: solid; }
.match-row-slot.correct {
  border-color: #2a7a3a;
  background: rgba(60, 140, 80, 0.18);
}
.match-row-slot.wrong {
  border-color: #8c2a2a;
  background: rgba(140, 60, 60, 0.18);
}
.match-slot-empty { opacity: 0.4; letter-spacing: 0.08em; }
.match-chip {
  padding: 6px 12px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 12px;
  cursor: grab;
  user-select: none;
}
.match-chip.in-slot {
  cursor: grab;
  background: var(--cream, #f5f0e3);
  color: var(--ink);
  border: 1px solid var(--ink);
}
.match-chip:active { cursor: grabbing; }
.match-score-box {
  margin-top: 21px;
  padding: 21px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
}
.match-score-num {
  font-family: var(--mono);
  font-size: 48px;
  line-height: 1;
  margin-bottom: 8px;
}
.match-score-sub {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.8;
}

/* =============================================================
   V79.1 — Bench session-type toggle (Colour / Cut).
   ============================================================= */
.bench-type-toggle {
  display: inline-flex;
  border: 1px solid var(--ink);
  overflow: hidden;
}
.bench-type-pill {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 8px 16px;
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--ink);
}
.bench-type-pill + .bench-type-pill { border-left: 1px solid var(--ink); }
.bench-type-pill.is-on {
  background: var(--ink);
  color: var(--paper);
}

/* =============================================================
   V82 — Bench cut-technique checklist.
   ============================================================= */
.bench-tech-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 8px;
  margin-top: 8px;
}
.bench-tech-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.5);
  font-family: var(--mono);
  font-size: 12px;
  cursor: pointer;
  user-select: none;
}
.bench-tech-row:hover { border-color: var(--ink); }
.bench-tech-row input {
  margin: 0;
  width: 14px;
  height: 14px;
}
.bench-tech-row.is-on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

/* =============================================================
   V83 — THE DICTIONARY.
   ============================================================= */
.dictionary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 21px;
}
.dictionary-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.55);
  overflow: hidden;
}
.dictionary-card-image {
  width: 100%;
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  background-color: rgba(20, 17, 16, 0.04);
  border: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
}
.dictionary-card-image.placeholder {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.5;
}
.dictionary-card-body {
  padding: 16px 18px 8px;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dictionary-card-title {
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.02em;
  margin: 0;
}
.dictionary-card-desc {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  margin: 0;
  white-space: pre-wrap;
  /* Clamp to 4 lines on the card; full text shows in the viewer. */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dictionary-card-footer {
  display: flex;
  gap: 6px;
  padding: 8px 18px 16px;
  flex-wrap: wrap;
}
.dictionary-card-footer .btn { padding: 6px 10px; font-size: 11px; }

.dictionary-editor-preview {
  height: 200px;
  border: 1px solid var(--L1, var(--line));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
  background-color: rgba(20, 17, 16, 0.04);
}

/* =============================================================
   V84 — HEAD EDUCATOR.
   ============================================================= */
.head-team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 21px;
}
.head-team-card {
  display: block;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.55);
  padding: 21px;
  text-decoration: none;
  color: inherit;
  transition: transform 0.14s ease, border-color 0.14s ease;
}
.head-team-card:hover {
  transform: translateY(-2px);
  border-color: var(--ink);
}
.head-team-card-head {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-bottom: 13px;
}
.head-team-name {
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 500;
}
.head-team-status .pill {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 3px 8px;
  display: inline-block;
  margin-top: 4px;
}
.head-team-status .pill-on {
  background: rgba(60, 140, 80, 0.18);
  color: #2a7a3a;
}
.head-team-status .pill-off {
  background: rgba(140, 60, 60, 0.18);
  color: #8c2a2a;
}
.head-team-counts {
  font-family: var(--mono);
  font-size: 12px;
  opacity: 0.7;
  display: flex;
  gap: 13px;
  flex-wrap: wrap;
}

/* Educator detail */
.head-section {
  margin-bottom: 34px;
}
.head-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.head-list li {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 10px 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.45);
  font-family: var(--mono);
  font-size: 13px;
}
.head-list-name { font-weight: 500; }
.head-list-sub  { opacity: 0.6; font-size: 12px; margin-left: 8px; }
.head-studio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 13px;
}
.head-stat {
  padding: 16px;
  border: 1px solid var(--L1, var(--line));
  text-align: center;
  font-family: var(--mono);
}
.head-stat-num {
  font-size: 28px;
  line-height: 1;
  margin-bottom: 6px;
}
.head-stat-lab {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.6;
}

/* Deactivate dialog */
.deact-group {
  margin-bottom: 21px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--L1, var(--line));
}
.deact-group-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  flex-wrap: wrap;
  gap: 8px;
}
.deact-group-title {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  margin: 0;
}
.deact-bulk {
  display: flex;
  align-items: center;
  gap: 6px;
}
.deact-bulk select {
  font-family: var(--mono);
  font-size: 11px;
  padding: 4px 6px;
}
.deact-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.deact-row {
  display: grid;
  grid-template-columns: 1fr 220px;
  gap: 10px;
  align-items: center;
  padding: 6px 10px;
  background: rgba(247, 245, 240, 0.4);
  border: 1px solid var(--L1, var(--line));
  font-family: var(--mono);
  font-size: 12px;
}
.deact-row select {
  font-family: var(--mono);
  font-size: 11px;
  padding: 4px 6px;
  width: 100%;
}
@media (max-width: 600px) {
  .deact-row { grid-template-columns: 1fr; gap: 4px; }
}

/* V84 — admin team-membership modal row */
.team-row {
  display: grid;
  grid-template-columns: 24px auto 1fr;
  gap: 13px;
  align-items: center;
  padding: 8px 13px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.45);
  cursor: pointer;
}
.team-row:hover { border-color: var(--ink); }
.team-row input { margin: 0; width: 16px; height: 16px; }
.team-row.is-on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

/* =============================================================
   V85 — POLISHED MEDIA TILES + VIEWER.
   ============================================================= */

/* ---- TILES (photo-led card for the Studio Readings grid) ---- */
.media-tile {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0;
  border: 1px solid var(--L1, var(--line));
  background: var(--paper-cool-0, rgba(247, 245, 240, 0.55));
  cursor: pointer;
  overflow: hidden;
  font: inherit;
  color: inherit;
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
.media-tile:hover {
  transform: translateY(-2px);
  border-color: var(--ink);
  box-shadow: 0 14px 28px -18px rgba(20, 17, 16, 0.45);
}
.media-tile-preview {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: rgba(20, 17, 16, 0.04);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.media-tile-image {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
}
.media-tile-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 36px;
  color: rgba(255, 255, 255, 0.95);
  text-shadow: 0 4px 16px rgba(20, 17, 16, 0.7);
  pointer-events: none;
}
.media-tile-placeholder {
  background: linear-gradient(135deg,
    rgba(20, 17, 16, 0.04) 0%,
    rgba(20, 17, 16, 0.10) 100%);
  flex-direction: column;
  gap: 12px;
}
.media-tile-placeholder-pdf    { background: linear-gradient(135deg, rgba(140, 60, 60, 0.10), rgba(140, 60, 60, 0.20)); }
.media-tile-placeholder-doc    { background: linear-gradient(135deg, rgba(60, 90, 140, 0.10), rgba(60, 90, 140, 0.20)); }
.media-tile-placeholder-slides { background: linear-gradient(135deg, rgba(140, 100, 60, 0.10), rgba(140, 100, 60, 0.20)); }
.media-tile-placeholder-audio  { background: linear-gradient(135deg, rgba(90, 80, 140, 0.10), rgba(90, 80, 140, 0.20)); }
.media-tile-glyph {
  font-family: var(--mono);
  font-size: 38px;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--ink);
  opacity: 0.55;
}
.media-tile-pkind {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--ink);
  opacity: 0.5;
}
.media-tile-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.media-tile-chip {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  padding: 3px 8px;
  background: var(--ink);
  color: var(--paper);
  align-self: flex-start;
}
.media-tile-title {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
}
.media-tile-desc {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  opacity: 0.75;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- VIEWER (the polished modal) ---- */
.mv-shell {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.mv-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--L1, var(--line));
  margin-bottom: 13px;
}
.mv-head-meta {
  display: flex;
  align-items: center;
  gap: 13px;
}
.mv-chip {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  padding: 4px 10px;
  background: var(--ink);
  color: var(--paper);
}
.mv-eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.55;
}
.mv-close {
  font-family: var(--mono);
  font-size: 26px;
  line-height: 1;
  background: transparent;
  border: 1px solid var(--ink);
  width: 36px;
  height: 36px;
  cursor: pointer;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
}
.mv-close:hover { background: var(--ink); color: var(--paper); }

.mv-stage {
  width: 100%;
  background: var(--ink);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.mv-stage-image,
.mv-stage-video {
  min-height: 50vh;
  max-height: 72vh;
}
.mv-image,
.mv-video {
  display: block;
  max-width: 100%;
  max-height: 72vh;
  width: auto;
  height: auto;
  margin: 0 auto;
}
.mv-stage-video { background: #000; }
.mv-video { width: 100%; height: 100%; }

.mv-stage-frame {
  height: 75vh;
  background: rgba(247, 245, 240, 0.95);
  padding: 13px;
  border: 1px solid var(--L1, var(--line));
}
.mv-iframe {
  width: 100%;
  height: 100%;
  border: none;
  background: #fff;
}

.mv-stage-audio {
  flex-direction: column;
  gap: 21px;
  background: linear-gradient(135deg,
    rgba(20, 17, 16, 0.92) 0%,
    rgba(20, 17, 16, 0.78) 100%);
  color: var(--paper);
  padding: 55px 34px;
}
.mv-audio-glyph {
  font-family: var(--mono);
  font-size: 76px;
  color: rgba(247, 245, 240, 0.7);
}
.mv-audio {
  width: 100%;
  max-width: 480px;
}

.mv-stage-empty {
  flex-direction: column;
  gap: 13px;
  padding: 76px 34px;
  background: rgba(247, 245, 240, 0.55);
  border: 1px dashed var(--L1, var(--line));
  color: var(--ink);
}
.mv-empty-glyph {
  font-family: var(--mono);
  font-size: 48px;
  opacity: 0.4;
}
.mv-empty-line {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.55;
  margin: 0;
}

.mv-title-block {
  padding: 21px 0 13px;
}
.mv-title {
  font-family: var(--mono);
  font-size: 22px;
  line-height: 1.2;
  letter-spacing: -0.005em;
  margin: 0 0 8px;
}
.mv-desc {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.55;
  opacity: 0.78;
  margin: 0;
  white-space: pre-wrap;
  max-width: 64ch;
}
.mv-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding-bottom: 8px;
}
.mv-thread {
  margin-top: 8px;
}

/* Studio Readings now use the tile grid instead of stacked rows. */
.studio-readings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}
.studio-readings-grid + .studio-empty-row { margin-top: 8px; }

/* Educator/admin read-row controls under a tile. */
.media-tile-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 0 18px 16px;
}
.media-tile-actions .btn { padding: 5px 10px; font-size: 11px; }

/* Wrap around a media tile so we can stack action buttons under it
   without breaking the grid layout. */
.media-tile-wrap {
  display: flex;
  flex-direction: column;
}
.media-tile-wrap .media-tile {
  flex: 1;
}
.media-tile-wrap .media-tile-actions {
  background: rgba(247, 245, 240, 0.55);
  border: 1px solid var(--L1, var(--line));
  border-top: 0;
  padding: 10px 18px;
}

/* =============================================================
   V86.1 — assignment row busy / disabled hint.
   ============================================================= */
.assign-row.is-busy {
  opacity: 0.55;
  cursor: progress;
}
.assign-row.is-busy .assign-row-check {
  animation: assign-pulse 0.8s ease-in-out infinite alternate;
}
@keyframes assign-pulse {
  from { opacity: 0.4; }
  to   { opacity: 1; }
}

/* =============================================================
   V87 — TRACKING (heatmap).
   ============================================================= */
.tracking-summary {
  display: flex;
  gap: 13px;
  flex-wrap: wrap;
  margin-bottom: 34px;
}
.tm-stat {
  flex: 1;
  min-width: 120px;
  padding: 16px;
  border: 1px solid var(--L1, var(--line));
  background: rgba(247, 245, 240, 0.55);
  text-align: center;
  font-family: var(--mono);
}
.tm-stat-n {
  font-size: 28px;
  line-height: 1;
  margin-bottom: 6px;
}
.tm-stat-l {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.55;
}

.tm-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 8px;
}
.tm-grid {
  display: grid;
  gap: 4px;
  min-width: 0;
  font-family: var(--mono);
}
.tm-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 8px;
  background: rgba(247, 245, 240, 0.5);
  border: 1px solid var(--L1, var(--line));
  font-size: 12px;
  letter-spacing: 0.02em;
  min-height: 48px;
  box-sizing: border-box;
  text-align: center;
}
.tm-cell.tm-h {
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.tm-h-kind {
  display: inline-block;
  width: 18px;
  height: 18px;
  line-height: 18px;
  margin-right: 6px;
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  font-weight: 600;
}
.tm-hcorner, .tm-foot-name, .tm-row-name {
  position: sticky;
  left: 0;
  z-index: 1;
  justify-content: flex-start;
  gap: 8px;
  padding-left: 13px;
}
.tm-hitem {
  flex-direction: column;
  gap: 4px;
  padding: 8px 6px;
}
.tm-h-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 10px;
  line-height: 1.2;
  text-transform: none;
  letter-spacing: 0.02em;
  text-align: center;
}
.tm-row-name {
  background: rgba(247, 245, 240, 0.85);
  font-size: 13px;
  letter-spacing: 0.01em;
  text-transform: none;
  font-weight: 500;
}
.tm-score {
  background: transparent;
  cursor: pointer;
  font-weight: 600;
  font-size: 12px;
  transition: transform 0.1s ease;
}
.tm-score:hover { transform: scale(1.05); }
.tm-score:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.tm-avg {
  font-weight: 600;
  background: rgba(20, 17, 16, 0.04);
}
.tm-foot {
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.04em;
}

/* Heat tiers — score → colour. Same scale as Swatch Lab undercoats:
   red = below pass mark, green = mastery, none = no attempt. */
.tm-tier-none   { background: rgba(20, 17, 16, 0.04); color: rgba(20, 17, 16, 0.3); }
.tm-tier-red    { background: rgba(140, 60, 60, 0.22);  color: #6b1d1d; border-color: rgba(140, 60, 60, 0.35); }
.tm-tier-amber  { background: rgba(200, 140, 60, 0.24); color: #6b3d10; border-color: rgba(200, 140, 60, 0.40); }
.tm-tier-lime   { background: rgba(140, 170, 70, 0.30); color: #3e5510; border-color: rgba(140, 170, 70, 0.45); }
.tm-tier-green  { background: rgba(60, 140, 80, 0.32);  color: #1f4628; border-color: rgba(60, 140, 80, 0.50); }
.tm-foot.tm-tier-red,   .tm-avg.tm-tier-red    { color: var(--paper); background: rgba(140, 60, 60, 0.85); }
.tm-foot.tm-tier-amber, .tm-avg.tm-tier-amber  { color: var(--paper); background: rgba(200, 140, 60, 0.85); }
.tm-foot.tm-tier-lime,  .tm-avg.tm-tier-lime   { color: var(--paper); background: rgba(140, 170, 70, 0.85); }
.tm-foot.tm-tier-green, .tm-avg.tm-tier-green  { color: var(--paper); background: rgba(60, 140, 80, 0.85); }

/* Legend */
.tm-legend {
  display: flex;
  gap: 13px;
  flex-wrap: wrap;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0.75;
}
.tm-legend-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tm-legend-swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 1px solid var(--L1, var(--line));
}

/* Big score readout inside the cell-detail modal. */
.tm-score-big {
  font-family: var(--mono);
  font-size: 64px;
  line-height: 1;
  text-align: center;
  padding: 21px;
  border: 1px solid var(--L1, var(--line));
}

/* V87 — Settings tier-perks list */
.tier-perks {
  list-style: none;
  margin: 13px 0 0;
  padding: 0;
  font-family: var(--mono);
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.tier-perks li {
  padding: 6px 10px;
  background: rgba(247, 245, 240, 0.4);
  border-left: 2px solid var(--ink);
}

/* =============================================================
   V87.3 — PWA orchestration: push prompt modal + banners.
   ============================================================= */

/* The "enable notifications" / "ios install" / "denied" modal body.
   Inherits the modal-content shell from ui.css; this just paints the
   inside. */
.push-modal {
  font-family: var(--sans);
  color: var(--ink);
  max-width: 460px;
}
.push-modal-mark {
  width: 55px;
  height: 55px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 28px;
  font-family: var(--serif);
  margin-bottom: 13px;
}
.push-modal-rows {
  display: flex;
  flex-direction: column;
  gap: 13px;
  padding: 13px 0 0;
  border-top: 1px solid rgba(20, 17, 16, 0.13);
}
.push-modal-row {
  display: flex;
  gap: 13px;
  align-items: flex-start;
}
.push-modal-glyph {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(20, 17, 16, 0.25);
  border-radius: 50%;
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink);
  flex-shrink: 0;
}
.push-modal-row-title {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 2px;
}
.push-modal-row-body {
  font-family: var(--sans);
  font-size: 13px;
  color: rgba(20, 17, 16, 0.65);
  line-height: 1.5;
}
.push-modal-steps {
  font-family: var(--sans);
  padding-left: 21px;
  color: rgba(20, 17, 16, 0.78);
  line-height: 1.6;
}
.push-modal-steps li {
  padding: 4px 0;
}

/* Top-of-page banners — update available, offline. Pinned to the top
   so they never block the main content; fade-up on appear. */
.pwa-banner {
  position: fixed;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--ink);
  color: var(--paper);
  padding: 10px 16px;
  border-radius: 100px;
  display: flex;
  align-items: center;
  gap: 13px;
  z-index: 1000;
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.02em;
  box-shadow: 0 8px 24px rgba(20, 17, 16, 0.18);
  animation: pwa-banner-in 240ms ease-out;
  max-width: calc(100vw - 16px);
}
.pwa-banner .btn {
  padding: 6px 12px !important;
  font-size: 12px !important;
}
.pwa-banner-x {
  background: none;
  border: none;
  color: rgba(247, 245, 240, 0.55);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
}
.pwa-banner-x:hover { color: var(--paper); }
.pwa-banner-update { background: var(--ink); }
.pwa-banner-offline { background: #6b3a26; }
.pwa-banner-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #f0c87a;
  display: inline-block;
  animation: pwa-banner-pulse 1.4s ease-in-out infinite;
}
@keyframes pwa-banner-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
@keyframes pwa-banner-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}
@media (max-width: 480px) {
  .pwa-banner { font-size: 12px; padding: 8px 12px; }
}

/* V87.3 — push diagnostic card on dev notes */
.diag-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  margin-top: 13px;
}
.diag-row {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 13px;
  padding: 8px 10px;
  border-bottom: 1px dashed rgba(20, 17, 16, 0.1);
}
.diag-row-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.6);
}
.diag-row-value {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink);
  word-break: break-all;
}
.diag-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.diag-list li {
  padding: 8px 12px;
  background: rgba(247, 245, 240, 0.4);
  border-left: 2px solid var(--ink);
}
.diag-list-name {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
}
.diag-list-meta {
  font-family: var(--mono);
  font-size: 11px;
  color: rgba(20, 17, 16, 0.55);
  margin-top: 2px;
  word-break: break-all;
}
@media (max-width: 720px) {
  .diag-row { grid-template-columns: 1fr; gap: 2px; padding: 6px 0; }
}

/* V87.3 — side nav divider between role sections */
.side-nav-divider {
  margin: 21px 0 8px;
  padding: 8px 16px 4px;
  border-top: 1px dashed rgba(20, 17, 16, 0.18);
}
.side-nav-divider-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.42);
}

/* V87.5 — preview banner above match attempt page when an educator
   is viewing through the apprentice's lens. */
.preview-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: rgba(247, 245, 240, 0.55);
  border: 1px dashed rgba(20, 17, 16, 0.32);
  border-radius: 100px;
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: rgba(20, 17, 16, 0.7);
  margin: 0 0 21px;
  max-width: max-content;
}
.preview-banner-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #c89a4e;
  display: inline-block;
  animation: pwa-banner-pulse 1.6s ease-in-out infinite;
}

/* =============================================================
   V87.6 — MATCH ATTEMPT page polish.
   Smaller, more editorial. Constrains the working surface to a
   reading-friendly column on wide screens. Refined typography on
   the rows, soft serif italic on the prompts, monospace tags for
   the draggable chips. The whole article sits inside a paper card
   with a hairline border so it reads as one composed object.
   ============================================================= */

/* The article wrapper around the board + blurb + buttons. */
.match-attempt {
  max-width: 920px;
  margin: 0 auto;
  padding: 34px;
  border: 1px solid rgba(20, 17, 16, 0.13);
  background: #fbf8f1;
  border-radius: 2px;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 24px 60px -32px rgba(20, 17, 16, 0.18);
}
@media (max-width: 720px) {
  .match-attempt { padding: 21px; }
}

/* Short body paragraph above the board, replacing the giant headline
   the description used to render as. Limit to 60ch for reading. */
.match-attempt-blurb {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.55;
  color: rgba(20, 17, 16, 0.78);
  max-width: 60ch;
  margin: 0 0 34px;
  font-style: italic;
  letter-spacing: 0.005em;
}

/* Tighter board grid and gap. The two columns sit closer together
   so the eye reads "left arrow right" naturally. */
.match-board {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px;
  align-items: start;
}
@media (max-width: 720px) {
  .match-board { gap: 21px; }
}

/* Hairline column eyebrow — tighter type, more spacing. */
.match-col-head {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-bottom: 21px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(20, 17, 16, 0.13);
}

/* Each left row — labelled prompt + arrow + drop target. Serif on
   the prompt for editorial weight. */
.match-row-attempt {
  display: grid;
  grid-template-columns: 1fr 22px 1fr;
  gap: 13px;
  align-items: center;
  padding: 0;
  margin-bottom: 13px;
  border: none;
  background: transparent;
  font-family: var(--serif);
  font-size: 16px;
}
.match-row-left {
  padding: 10px 0;
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.match-row-arrow {
  font-family: var(--mono);
  font-size: 11px;
  text-align: center;
  opacity: 0.35;
  letter-spacing: 0;
}
.match-row-slot {
  min-height: 44px;
  padding: 10px 13px;
  border: 1px dashed rgba(20, 17, 16, 0.32);
  background: rgba(247, 245, 240, 0.45);
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 12px;
  border-radius: 2px;
  transition: border-color 140ms ease, background 140ms ease;
}
.match-row-slot.over {
  background: rgba(200, 154, 78, 0.18);
  border-color: rgba(20, 17, 16, 0.5);
  border-style: solid;
}
.match-row-slot.filled {
  border-style: solid;
  border-color: rgba(20, 17, 16, 0.28);
  background: rgba(247, 245, 240, 0.7);
}
.match-row-slot.correct {
  border-color: rgba(60, 120, 70, 0.55);
  background: rgba(60, 140, 80, 0.10);
}
.match-row-slot.wrong {
  border-color: rgba(140, 60, 60, 0.55);
  background: rgba(140, 60, 60, 0.10);
}
.match-slot-empty {
  opacity: 0.32;
  letter-spacing: 0.16em;
  font-size: 10px;
  text-transform: uppercase;
}

/* The right pool — sits inside a soft paper card, fixed minimum
   height so the empty state doesn't collapse the layout. */
.match-col-right .match-pool {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  min-height: 120px;
  padding: 21px;
  border: 1px dashed rgba(20, 17, 16, 0.18);
  background: rgba(247, 245, 240, 0.6);
  border-radius: 2px;
}

/* Draggable chip — quieter than before. Serif on the label so it
   pairs with the left-row text on contact. */
.match-chip {
  padding: 10px 16px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--serif);
  font-size: 15px;
  letter-spacing: -0.005em;
  cursor: grab;
  user-select: none;
  border-radius: 2px;
  transition: transform 100ms ease, box-shadow 100ms ease;
  box-shadow: 0 1px 0 rgba(20, 17, 16, 0.18);
}
.match-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px -4px rgba(20, 17, 16, 0.32);
}
.match-chip:active { cursor: grabbing; transform: none; }
.match-chip.in-slot {
  background: var(--paper, #fbf8f1);
  color: var(--ink);
  border: 1px solid rgba(20, 17, 16, 0.5);
  padding: 8px 14px;
  font-size: 14px;
}

/* Score readout — quieter ink card with mono numerals. */
.match-score-box {
  margin-top: 34px;
  padding: 34px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
  border-radius: 2px;
}
.match-score-num {
  font-family: var(--mono);
  font-size: 55px;
  font-weight: 300;
  line-height: 1;
  margin-bottom: 13px;
  letter-spacing: -0.02em;
}
.match-score-sub {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.65;
}

/* =============================================================
   V87.7 — MATCH ATTEMPT: pointer-events drag + tap-to-place.
   Adds visible affordances for the new interactions.
   ============================================================= */

/* Tiny "drag or tap" instruction line above the board. */
.match-attempt-hint {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  color: rgba(20, 17, 16, 0.5);
  margin: 0 0 21px;
  text-transform: uppercase;
}

/* The currently-tapped (selected) chip — outlined and lifted to make
   the next-tap-places-it pattern obvious without a tutorial. */
.match-chip.selected {
  outline: 2px solid #c89a4e;
  outline-offset: 3px;
  transform: translateY(-2px);
  box-shadow: 0 6px 16px -6px rgba(20, 17, 16, 0.32);
}

/* The original chip while it's being dragged — fade to a hint of
   itself so the apprentice knows the ghost is the real interaction. */
.match-chip.dragging { opacity: 0.25; }

/* The floating clone that tracks the pointer / finger during a drag. */
.match-chip-ghost {
  pointer-events: none;
  transform: scale(1.04);
  box-shadow: 0 16px 32px -12px rgba(20, 17, 16, 0.45);
  opacity: 0.95;
}

/* The pool gets a slightly clearer "over" state during a drag so
   apprentices know they're dropping into the return area. */
.match-pool.over {
  background: rgba(200, 154, 78, 0.15);
  border-color: rgba(20, 17, 16, 0.45);
  border-style: solid;
}

/* Disable native browser drag/scroll inside the board — pointer
   events handle everything. Without this, an in-progress drag on
   iOS Safari can be hijacked by pinch-zoom or page-scroll. */
.match-board, .match-chip, .match-row-slot, .match-pool {
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

/* Keyboard focus ring on chips. */
.match-chip:focus-visible {
  outline: 2px solid #c89a4e;
  outline-offset: 3px;
}

/* =============================================================
   V87.9 — MATCH ATTEMPT mobile rebuild.
   Below 720px the two-column board re-stacks so the pool is at
   the top (compact, scrollable) and the left rows fill the width
   underneath. Tap targets get a phone-appropriate 44px height
   floor and the prompt text scales down so long answers (e.g.
   undercoat names) don't wrap to four lines.
   ============================================================= */
@media (max-width: 720px) {
  .match-attempt {
    padding: 16px;
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: none;
    margin: 0 -16px;
  }

  /* Pool at the top, full-bleed inside the card. Soft cream
     background so it reads as a "pick from here" tray. */
  .match-board {
    display: flex;
    flex-direction: column-reverse;
    gap: 21px;
  }
  .match-col-head {
    margin-bottom: 13px;
    padding-bottom: 6px;
  }
  .match-col-right .match-pool {
    padding: 13px;
    min-height: 96px;
    gap: 8px;
    border: 1px solid rgba(20, 17, 16, 0.13);
    background: rgba(247, 240, 225, 0.6);
    border-radius: 4px;
  }
  /* Chips a little smaller, but tap-area still ≥ 44px because of padding. */
  .match-chip {
    font-size: 14px;
    padding: 12px 16px;
    border-radius: 4px;
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .match-chip.in-slot {
    font-size: 13px;
    padding: 10px 14px;
  }

  /* Left rows — prompt left, drop slot right, arrow gone (the
     equals-sign treatment carries the connection). Each row is a
     full-width band with a hairline rule between them. */
  .match-row-attempt {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 0;
    padding: 13px 0;
    border-bottom: 1px solid rgba(20, 17, 16, 0.08);
    align-items: center;
  }
  .match-row-attempt:last-child { border-bottom: none; }
  .match-row-arrow { display: none; }
  .match-row-left {
    padding: 0;
    font-size: 16px;
    line-height: 1.3;
    overflow-wrap: anywhere;
  }
  .match-row-slot {
    min-height: 48px;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 13px;
  }
  .match-slot-empty {
    font-size: 9px;
    opacity: 0.36;
    letter-spacing: 0.12em;
  }

  /* Blurb + hint scale with the smaller paper. */
  .match-attempt-blurb {
    font-size: 15px;
    margin-bottom: 21px;
  }
  .match-attempt-hint {
    font-size: 10px;
    margin-bottom: 13px;
    letter-spacing: 0.04em;
  }

  /* Score card slimmer on phone. */
  .match-score-box { padding: 21px; margin-top: 21px; }
  .match-score-num { font-size: 42px; }
}

/* Below 380px (small phones) shrink further. */
@media (max-width: 380px) {
  .match-chip { font-size: 13px; padding: 11px 13px; }
  .match-row-left { font-size: 15px; }
  .match-attempt-blurb { font-size: 14px; }
}

/* =============================================================
   V87.10 — TRACKING redesign.
   List of assessment cards, detail view with per-apprentice
   attempt strips.
   ============================================================= */

/* Card grid — one assessment per card on the list view. */
.tracking-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 21px;
  margin-top: 21px;
}
.tracking-card {
  display: block;
  padding: 21px;
  border: 1px solid rgba(20, 17, 16, 0.13);
  background: #fbf8f1;
  text-decoration: none;
  color: inherit;
  border-radius: 2px;
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.tracking-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px -16px rgba(20, 17, 16, 0.25);
}
.tracking-card-row1 {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 13px;
}
.tracking-card-kind {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
}
.tracking-card-kind[data-kind="case"]       { background: #6b3a26; }
.tracking-card-kind[data-kind="fill_blank"] { background: #3a4a44; }
.tracking-card-kind[data-kind="match"]      { background: #4a3a6b; }
.tracking-card-attempts {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}
.tracking-card-title {
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.25;
  margin: 0 0 21px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.tracking-card-row3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding-top: 13px;
  border-top: 1px dashed rgba(20, 17, 16, 0.13);
}
.tracking-card-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tracking-card-stat-num {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 500;
  color: var(--ink);
}
.tracking-card-stat-lbl {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}

/* Detail view — vertical list of apprentice rows. */
.tracking-list {
  display: flex;
  flex-direction: column;
  gap: 13px;
  margin-top: 21px;
}
.tracking-row {
  display: grid;
  grid-template-columns: 220px 1fr 220px;
  gap: 21px;
  align-items: center;
  padding: 16px;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 2px;
}
.tracking-row-who {
  display: flex;
  gap: 13px;
  align-items: center;
  min-width: 0;
}
.tracking-row-name {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.tracking-row-meta {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
  margin-top: 2px;
}
.tracking-tiles { min-width: 0; }
.tracking-tile-strip {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.tracking-empty {
  font-family: var(--mono);
  font-size: 11px;
  opacity: 0.45;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.tracking-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 58px;
  padding: 8px 10px;
  border: 1px solid rgba(20, 17, 16, 0.15);
  border-radius: 4px;
  background: rgba(247, 245, 240, 0.5);
  cursor: pointer;
  transition: transform 100ms ease, box-shadow 100ms ease;
  font-family: var(--mono);
}
.tracking-tile:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px rgba(20, 17, 16, 0.22);
}
.tracking-tile-n {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}
.tracking-tile-d {
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.55;
  margin-top: 2px;
}

/* Right rail with Latest / Best / Avg. */
.tracking-summary-rail {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  padding: 8px;
  border-left: 1px dashed rgba(20, 17, 16, 0.13);
}
.tracking-rail-stat {
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-align: center;
}
.tracking-rail-lbl {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.5);
}
.tracking-rail-val {
  font-family: var(--mono);
  font-size: 15px;
  color: var(--ink);
}

/* Heat tiers — already defined elsewhere, reasserted here so the new
   classes pick up the colour scale. */
.tracking-tile.tm-tier-red   { background: rgba(168, 60, 60, 0.18);  border-color: rgba(168, 60, 60, 0.45); }
.tracking-tile.tm-tier-amber { background: rgba(200, 154, 78, 0.22); border-color: rgba(200, 154, 78, 0.5); }
.tracking-tile.tm-tier-lime  { background: rgba(165, 178, 90, 0.25); border-color: rgba(118, 138, 60, 0.5); }
.tracking-tile.tm-tier-green { background: rgba(72, 134, 84, 0.30);  border-color: rgba(60, 120, 70, 0.55); }
.tracking-tile.tm-tier-none  { background: rgba(247, 245, 240, 0.5); border-color: rgba(20, 17, 16, 0.13); }

/* Phone collapse — stack the row into name / tiles / rail vertically. */
@media (max-width: 720px) {
  .tracking-row {
    grid-template-columns: 1fr;
    gap: 13px;
  }
  .tracking-summary-rail {
    border-left: none;
    border-top: 1px dashed rgba(20, 17, 16, 0.13);
    padding: 13px 0 0;
  }
  .tracking-card-title { font-size: 18px; }
}

/* =============================================================
   V87.11 — FILL-IN-THE-BLANK
   New: multi-question authoring + paged attempt with editorial
   inline inputs.
   ============================================================= */

/* ---- Editor: per-question card ---- */
.fb-q-list {
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.fb-q-card {
  border: 1px solid rgba(20, 17, 16, 0.13);
  background: #fbf8f1;
  border-radius: 2px;
}
.fb-q-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 13px;
  border-bottom: 1px dashed rgba(20, 17, 16, 0.13);
  background: rgba(247, 245, 240, 0.6);
}
.fb-q-card-num {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.65);
}
.fb-q-card-actions { display: flex; gap: 6px; }
.fb-q-iconbtn {
  width: 26px; height: 26px;
  background: transparent;
  border: 1px solid rgba(20, 17, 16, 0.18);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
  cursor: pointer;
  border-radius: 2px;
  display: grid;
  place-items: center;
  transition: background 100ms ease;
}
.fb-q-iconbtn:hover { background: rgba(20, 17, 16, 0.05); }
.fb-q-iconbtn-x:hover { background: rgba(168, 60, 60, 0.12); border-color: rgba(168, 60, 60, 0.5); color: #8c2a2a; }
.fb-q-card-body { padding: 16px; }

/* ---- Attempt: paged carousel ---- */

.fb-attempt-card { padding: 34px; max-width: 760px; }

.fb-attempt-eyebrow {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-bottom: 13px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}
.fb-attempt-eyebrow-num {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* Progress dots across the top, one per question. Current dot fills
   solid; previously-seen dots get a muted fill; unseen are outlined. */
.fb-progress {
  display: flex;
  gap: 8px;
  margin-bottom: 34px;
}
.fb-progress-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(20, 17, 16, 0.32);
  display: inline-block;
}
.fb-progress-dot.done {
  background: rgba(20, 17, 16, 0.45);
  border-color: rgba(20, 17, 16, 0.45);
}
.fb-progress-dot.current {
  background: var(--ink);
  border-color: var(--ink);
  transform: scale(1.5);
  transition: transform 150ms ease;
}

/* The body text — editorial serif, generous line-height so inline
   inputs sit comfortably. */
.fb-attempt-body {
  font-family: var(--serif);
  font-size: 26px;
  line-height: 1.55;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0 0 34px;
  word-break: break-word;
}
.fb-attempt-body-sm {
  font-size: 18px;
  line-height: 1.55;
  margin: 0 0 13px;
}
.fb-text { white-space: pre-wrap; }

/* The inline input fields that replace the {{N}} tokens. Underlined
   serif text inputs that visually live inside the sentence. */
.fb-inline-input {
  font-family: var(--serif);
  font-size: inherit;
  line-height: inherit;
  font-style: italic;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 2px solid rgba(20, 17, 16, 0.32);
  padding: 0 4px 3px;
  margin: 0 2px;
  min-width: 5ch;
  text-align: center;
  outline: none;
  transition: border-color 140ms ease, background 140ms ease;
}
.fb-inline-input:focus {
  border-bottom-color: var(--ink);
  background: rgba(200, 154, 78, 0.10);
}
.fb-inline-input::placeholder {
  font-style: italic;
  color: rgba(20, 17, 16, 0.25);
}

/* Footer nav row — back / next / submit. */
.fb-attempt-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 21px;
  padding-top: 21px;
  border-top: 1px dashed rgba(20, 17, 16, 0.13);
}

/* ---- Review screen ---- */
.fb-review-list {
  display: flex;
  flex-direction: column;
  gap: 21px;
}
.fb-review-q {
  padding: 21px;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 2px;
  background: rgba(247, 245, 240, 0.5);
}
.fb-review-q-eyebrow {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
  margin-bottom: 10px;
}
.fb-review-pill {
  font-family: var(--serif);
  font-style: italic;
  padding: 2px 8px;
  margin: 0 2px;
  border-bottom: 2px solid currentColor;
}
.fb-review-pill.ok {
  color: rgba(60, 120, 70, 0.95);
  background: rgba(60, 140, 80, 0.10);
}
.fb-review-pill.wrong {
  color: rgba(140, 60, 60, 0.95);
  background: rgba(140, 60, 60, 0.10);
  text-decoration: line-through;
}
.fb-review-corrects {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding-top: 13px;
  margin-top: 13px;
  border-top: 1px dashed rgba(20, 17, 16, 0.13);
}
.fb-review-corrects-lbl {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}
.fb-review-correct-pill {
  font-family: var(--mono);
  font-size: 12px;
  padding: 4px 10px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 100px;
}
.fb-review-correct-pill strong {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  margin-left: 2px;
}

/* ---- Phone ---- */
@media (max-width: 720px) {
  .fb-attempt-card {
    padding: 21px;
    margin: 0 -16px;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
  .fb-attempt-body { font-size: 20px; line-height: 1.5; margin-bottom: 21px; }
  .fb-attempt-body-sm { font-size: 16px; }
  .fb-inline-input { font-size: inherit; }
  .fb-progress { margin-bottom: 21px; }
}

/* =============================================================
   V87.13 — NOTIFICATIONS dashboard + nav badge.
   ============================================================= */

/* Side-nav red unread badge. Renders next to "Notifications" label.
   Counts > 99 collapse to "99+". */
.notif-badge {
  margin-left: auto;
  display: inline-grid;
  place-items: center;
  min-width: 21px;
  height: 21px;
  padding: 0 7px;
  border-radius: 100px;
  background: #6b1d1d;
  color: #fbf8f1;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  font-weight: 500;
}

/* ---- Page ---- */
.notif-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 21px;
  padding-bottom: 21px;
  border-bottom: 1px dashed rgba(20, 17, 16, 0.13);
}
.notif-counts { display: flex; flex-direction: column; gap: 4px; }
.notif-count-big {
  font-family: var(--mono);
  font-size: 42px;
  line-height: 1;
  color: var(--ink);
}
.notif-count-lbl {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}

.notif-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 21px;
}
.notif-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: stretch;
  border: 1px solid rgba(20, 17, 16, 0.10);
  background: rgba(247, 245, 240, 0.45);
  border-radius: 2px;
  overflow: hidden;
}
.notif-row.unread {
  background: #fbf8f1;
  border-color: rgba(20, 17, 16, 0.22);
  box-shadow: 0 6px 16px -10px rgba(20, 17, 16, 0.15);
}

.notif-main {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 16px 18px;
  background: transparent;
  border: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font-family: var(--sans);
}
.notif-main:hover { background: rgba(20, 17, 16, 0.03); }

.notif-kind {
  display: inline-grid;
  place-items: center;
  padding: 5px 10px;
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--paper);
  height: max-content;
  min-width: 100px;
  text-align: center;
}
.notif-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.notif-title {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
  letter-spacing: -0.003em;
  overflow-wrap: anywhere;
}
.notif-blurb {
  font-family: var(--sans);
  font-size: 13px;
  color: rgba(20, 17, 16, 0.66);
  line-height: 1.5;
}
.notif-time {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.5);
  margin-top: 2px;
}
.notif-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #c89a4e;
  flex-shrink: 0;
}
.notif-x {
  background: transparent;
  border: none;
  border-left: 1px solid rgba(20, 17, 16, 0.08);
  padding: 0 18px;
  font-size: 20px;
  cursor: pointer;
  color: rgba(20, 17, 16, 0.4);
  font-family: var(--mono);
  transition: background 100ms ease, color 100ms ease;
}
.notif-x:hover {
  background: rgba(168, 60, 60, 0.10);
  color: #8c2a2a;
}

@media (max-width: 720px) {
  .notif-main {
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    padding: 13px 13px;
  }
  .notif-kind { min-width: 64px; font-size: 9px; padding: 4px 6px; letter-spacing: 0.12em; }
  .notif-title { font-size: 15px; }
  .notif-blurb { font-size: 12px; }
  .notif-x { padding: 0 13px; }
  .notif-count-big { font-size: 34px; }
}

/* =============================================================
   V87.14 — WORKBOOKS
   ============================================================= */

/* Studio root: workbook section under the folder grid. */
.studio-workbooks {
  margin-top: 55px;
  padding-top: 34px;
  border-top: 1px dashed rgba(20, 17, 16, 0.13);
}
.studio-workbooks-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 21px;
}
.studio-workbook-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 21px;
}
.studio-workbook-tile {
  display: block;
  padding: 21px;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.13);
  text-decoration: none;
  color: inherit;
  border-radius: 2px;
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.studio-workbook-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px -16px rgba(20, 17, 16, 0.22);
}
.studio-workbook-eyebrow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 13px;
}
.studio-workbook-kind {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 4px 8px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 2px;
}
.studio-workbook-title {
  font-family: var(--serif);
  font-size: 21px;
  margin: 0 0 8px;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.studio-workbook-blurb {
  font-family: var(--sans);
  font-size: 13px;
  color: rgba(20, 17, 16, 0.65);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Workbook viewer + editor — stacked editorial pages. */
.wb-pages {
  display: flex;
  flex-direction: column;
  gap: 55px;
  align-items: center;
  margin: 0 auto;
  max-width: 100%;
}
.wb-page {
  display: flex;
  flex-direction: column;
  gap: 13px;
  width: 100%;
  max-width: 720px;
}
.wb-page-eyebrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 13px;
  padding: 0 4px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}
.wb-page-num {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* Stage — the canvas + overlay layer. Editorial look: ivory tone,
   hairline border, soft drop shadow. */
.wb-page-stage {
  position: relative;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 4px;
  overflow: hidden;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 24px 60px -32px rgba(20, 17, 16, 0.22);
}
.wb-page-stage canvas { display: block; }

/* Overlay layer that holds the field nodes. Sits at the same size
   as the canvas via absolute positioning inside the stage. */
.wb-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.wb-overlay > * { pointer-events: auto; }

/* A placed field. */
.wb-field {
  position: absolute;
  box-sizing: border-box;
}
.wb-field-edit {
  border: 1.5px dashed rgba(200, 154, 78, 0.85);
  background: rgba(200, 154, 78, 0.08);
  cursor: move;
  touch-action: none;
  user-select: none;
}
.wb-field-edit.selected {
  border-style: solid;
  border-color: rgba(20, 17, 16, 0.8);
  background: rgba(200, 154, 78, 0.18);
  box-shadow: 0 4px 14px -6px rgba(20, 17, 16, 0.3);
}
.wb-field-edit .wb-field-inner {
  width: 100%; height: 100%;
  display: flex;
  align-items: center;
  padding: 2px 8px;
  pointer-events: none;
}
.wb-field-edit .wb-field-inner input {
  flex: 1; min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  font-family: var(--serif);
  font-size: 14px;
  color: rgba(20, 17, 16, 0.7);
  pointer-events: none;
}
.wb-field-handle {
  position: absolute;
  right: -7px; bottom: -7px;
  width: 14px; height: 14px;
  background: var(--ink);
  border: 2px solid var(--paper);
  border-radius: 50%;
  cursor: nwse-resize;
  touch-action: none;
}

/* =============================================================
   V87.17 — Workbook fields: real handwriting on real paper.
   No box, no border, no card. Just clean writing-on-paper.
   Bigger handwritten type. Proper navy-black pen ink with a
   trace of bleed shadow. Indigo ruled lines like a notebook.
   Subtle paper-grain wash on the writing area only, so the eye
   reads "the apprentice is writing here" without an explicit
   container.

   Tokens, all in one place at the top so the look is tweakable:
     --wb-rule-color   indigo rule, opaque enough to guide but not shout
     --wb-rule-step    pixels between rules (= font line-height)
     --wb-ink          pen colour, deep navy-black
     --wb-ink-soft     dimmer pen for ::placeholder
   ============================================================= */
:root {
  --wb-rule-color: rgba(72, 90, 140, 0.32);
  --wb-rule-step: 36px;
  --wb-ink: #14213d;
  --wb-ink-soft: rgba(20, 33, 61, 0.30);
}

/* Outer wrapper — no chrome. Just an anchor for the writing
   surface and the label. Tiny breathing-room padding above the
   input so the ink isn't crammed against the page text above. */
.wb-field-view {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  backdrop-filter: none;
  box-shadow: none;
}
.wb-field-view:focus-within {
  background: transparent;
  border: none;
  box-shadow: none;
}

/* The hint label sits as small italic serif marginalia above the
   field — never as a UI form-label. If the educator left the label
   blank, the span isn't rendered (workbookView.js skips it). */
.wb-field-label {
  display: block;
  font-family: var(--serif), "Instrument Serif", serif;
  font-style: italic;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: rgba(20, 17, 16, 0.42);
  margin: 0 0 4px 2px;
  pointer-events: none;
  user-select: none;
}

/* V87.18 — Fully transparent.
   No background, no rules, no cream wash, no noise grain. Just
   ink directly on the PDF page where the educator placed the field.
   The handwriting reads as though the apprentice wrote on the page
   itself, with nothing layered between the pen and the paper.
   ============================================================= */
.wb-field-input {
  width: 100%;
  min-height: var(--wb-rule-step);
  box-sizing: border-box;
  background: transparent;
  background-color: transparent;
  background-image: none;
  border: none;
  outline: none;
  resize: none;

  font-family: "Caveat", "Kalam", "Architects Daughter", "Segoe Script", "Bradley Hand", cursive;
  font-style: normal;
  font-weight: 500;
  font-size: 24px;
  line-height: var(--wb-rule-step);
  letter-spacing: 0.01em;
  color: var(--wb-ink);
  caret-color: var(--wb-ink);
  padding: 0;
  margin: 0;

  /* Tiny ink-bleed shadow so the writing looks like pen ink, not
     a screen render. Keeps the only "extra" treatment that
     doesn't break the no-background promise. */
  text-shadow: 0 0.5px 0 rgba(20, 33, 61, 0.10);

  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* Placeholder: lighter, italic Caveat — reads as a soft pencil
   prompt that disappears the moment she starts writing. */
.wb-field-input::placeholder {
  font-family: "Caveat", "Kalam", "Architects Daughter", cursive;
  font-style: italic;
  font-weight: 400;
  color: var(--wb-ink-soft);
  text-shadow: none;
}
.wb-field-input::-webkit-input-placeholder { font-family: "Caveat", cursive; }

/* V87.18 — focus state is completely silent. The transparent field
   has nothing to "wake up" — the writing just appears. */
.wb-field-view:focus-within .wb-field-input {
  background: transparent;
  background-image: none;
}

/* Selection looks like a soft highlighter, not a blue OS select. */
.wb-field-input::selection {
  background: rgba(200, 154, 78, 0.45);
  color: var(--wb-ink);
}

/* Phone tightens up — same look, scale-down. */
@media (max-width: 720px) {
  :root { --wb-rule-step: 32px; }
  .wb-field-input { font-size: 21px; padding: 0 5px; }
  .wb-field-label { font-size: 10px; }
}

/* Selection toolbar at the bottom of the editor — sticky so it
   always follows the user as they scroll through pages. */
.wb-sel-toolbar {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 13px;
  flex-wrap: wrap;
  padding: 13px 16px;
  margin-top: 21px;
  background: rgba(247, 245, 240, 0.96);
  border: 1px solid rgba(20, 17, 16, 0.13);
  backdrop-filter: blur(8px);
  border-radius: 100px;
  z-index: 30;
}
.wb-toolbar-label {
  flex: 1;
  min-width: 220px;
  background: transparent;
  border: none;
  border-bottom: 1px dashed rgba(20, 17, 16, 0.32);
  padding: 6px 0;
  font-family: var(--serif);
  font-size: 15px;
  outline: none;
}
.wb-toolbar-label:focus { border-bottom-color: var(--ink); }

.wb-add-field {
  margin-left: auto;
}

@media (max-width: 720px) {
  .wb-page { max-width: 100%; padding: 0; }
  .wb-pages { gap: 34px; }
  .wb-field-input { font-size: 14px; }
  .wb-sel-toolbar {
    border-radius: 0;
    margin: 21px -16px 0;
  }
}

/* =============================================================
   V87.19 — Reading + video viewer reframed to match the workbook.
   The PDF iframe (with browser PDF chrome) is replaced by stacked
   editorial page cards, each rendered through PDF.js to a canvas.
   Videos sit inside the same paper card so the whole modal reads
   as one composed object instead of a gray-bordered viewer.
   ============================================================= */

/* PDF stack — vertically scrollable column of editorial page cards. */
.mv-stage-pdf-editorial {
  background: rgba(247, 245, 240, 0.92);
  padding: 34px 21px;
  max-height: 80vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 34px;
  align-items: center;
}
.mv-pdf-loading {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.5);
  padding: 55px 0;
}

/* One PDF page card. */
.mv-pdf-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 820px;
}
.mv-pdf-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
  padding: 0 4px;
}
.mv-pdf-num {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 10px;
  letter-spacing: 0.06em;
}
.mv-pdf-stage {
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 4px;
  overflow: hidden;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 24px 60px -32px rgba(20, 17, 16, 0.22);
}
.mv-pdf-stage canvas { display: block; }

/* Editorial video frame — same paper card vocabulary. */
.mv-stage-video-editorial {
  background: rgba(247, 245, 240, 0.92);
  padding: 34px 21px;
  display: flex;
  justify-content: center;
}
.mv-stage-video-editorial .mv-page-stage {
  background: #0a0907;
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 4px;
  overflow: hidden;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 24px 60px -32px rgba(20, 17, 16, 0.32);
  width: 100%;
  max-width: 820px;
}
.mv-stage-video-editorial .mv-video {
  width: 100%;
  height: auto;
  max-height: 72vh;
  display: block;
}

@media (max-width: 720px) {
  .mv-stage-pdf-editorial,
  .mv-stage-video-editorial { padding: 21px 13px; }
  .mv-pdf-card { gap: 8px; }
  .mv-pdf-eyebrow { font-size: 10px; }
}

/* =============================================================
   V87.20 — READING — cover + presentation full-page surface.
   ============================================================= */

/* COVER */
.reading-cover {
  max-width: 720px;
  margin: 34px auto 0;
  padding: 55px 34px;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 4px;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 32px 80px -48px rgba(20, 17, 16, 0.22);
  text-align: center;
}
.reading-cover-eyebrow {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 13px;
  margin-bottom: 34px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}
.reading-cover-kind {
  background: var(--ink);
  color: var(--paper);
  padding: 5px 12px;
  border-radius: 2px;
}
.reading-cover-module {
  color: rgba(20, 17, 16, 0.55);
}
.reading-cover-title {
  font-family: var(--serif);
  font-size: 55px;
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 0 0 21px;
  color: var(--ink);
}
.reading-cover-blurb {
  font-family: var(--serif);
  font-style: italic;
  font-size: 19px;
  line-height: 1.55;
  color: rgba(20, 17, 16, 0.78);
  max-width: 58ch;
  margin: 0 auto 34px;
}
.reading-cover-blurb.muted {
  font-style: normal;
  color: rgba(20, 17, 16, 0.5);
}
.reading-cover-divider {
  width: 55px;
  height: 1px;
  background: rgba(20, 17, 16, 0.22);
  margin: 0 auto 34px;
}
.reading-cover-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 13px;
}
.reading-cover-cta {
  padding: 18px 34px !important;
  font-size: 15px !important;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-family: var(--mono);
  border-radius: 100px;
}

/* PRESENTATION — V87.21 widened.
   Now uses the full main column, not a max-820px reading column.
   The canvas keeps its native pixel size (set by PDF.js), so the
   page renders at whatever cssWidth the JS computed — usually the
   full width of the page card. */
.reading-presentation {
  display: flex;
  flex-direction: column;
  gap: 34px;
  align-items: center;
  margin: 21px auto 55px;
  padding: 0;
  width: 100%;
}
.reading-page {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 1100px;
}
.reading-page-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
  padding: 0 4px;
}
.reading-page-num {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 10px;
  letter-spacing: 0.06em;
}
.reading-page-stage {
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.10);
  border-radius: 4px;
  overflow: hidden;
  box-shadow:
    0 1px 0 rgba(20, 17, 16, 0.04),
    0 24px 60px -32px rgba(20, 17, 16, 0.22);
}
/* V87.21 — DON'T override the canvas width. PDF.js sets it in CSS
   pixels for the cssWidth we asked for; forcing width: 100% with
   height: auto can distort high-DPR rendering on iOS Safari. */
.reading-page-stage canvas { display: block; max-width: 100%; }

@media (max-width: 720px) {
  .reading-cover {
    padding: 34px 21px;
    margin: 16px -16px 0;
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: none;
  }
  .reading-cover-title { font-size: 38px; }
  .reading-cover-blurb { font-size: 17px; }
  .reading-cover-cta { padding: 16px 28px !important; font-size: 13px !important; }
  .reading-presentation { padding: 0 13px; gap: 21px; }
}

/* =============================================================
   V87.23 — Workbook cover tile + editor settings panel.
   ============================================================= */

/* When the workbook has a cover image, fill the tile and overlay
   the text in a paper card at the bottom — like a magazine cover. */
.studio-workbook-tile.has-cover {
  position: relative;
  padding: 0;
  background-size: cover;
  background-position: top center;
  background-color: #efe9d8;
  aspect-ratio: 3 / 4;
  min-height: 340px;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.studio-workbook-tile.has-cover::before {
  /* Soft gradient at the bottom so the overlay text is readable. */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(20, 17, 16, 0) 50%,
    rgba(20, 17, 16, 0.10) 70%,
    rgba(20, 17, 16, 0.55) 100%
  );
  pointer-events: none;
}
.studio-workbook-tile-overlay {
  position: relative;
  width: 100%;
  padding: 21px;
  background: rgba(251, 248, 241, 0.96);
  backdrop-filter: blur(6px);
  border-top: 1px solid rgba(20, 17, 16, 0.13);
}
/* No cover: keep the original card look. */
.studio-workbook-tile:not(.has-cover) .studio-workbook-tile-overlay {
  background: transparent;
  backdrop-filter: none;
  border-top: none;
  padding: 0;
}

/* Workbook editor: settings + assignment panel above the pages. */
.wb-meta-panel {
  margin: 0 auto 34px;
  padding: 21px;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
  max-width: 920px;
}
.wb-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px;
}
@media (max-width: 720px) {
  .wb-meta-grid { grid-template-columns: 1fr; gap: 21px; }
}
.wb-meta-block { min-width: 0; }
.wb-meta-select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid rgba(20, 17, 16, 0.22);
  background: var(--paper, #fcfaf3);
  font-family: var(--sans);
  font-size: 14px;
  border-radius: 2px;
}

/* =============================================================
   V87.25 — colorField: native swatch + hex text input pair.
   Used in the studio folder editor, the module editor, and any
   other surface where a colour can be set.
   ============================================================= */
.color-field {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  border: 1px solid rgba(20, 17, 16, 0.32);
  border-radius: 2px;
  overflow: hidden;
  background: var(--paper, #fbf8f1);
  max-width: 220px;
}
.color-field-swatch {
  -webkit-appearance: none;
  appearance: none;
  width: 44px;
  height: 38px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
  border-right: 1px solid rgba(20, 17, 16, 0.18);
}
.color-field-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.color-field-swatch::-webkit-color-swatch { border: none; border-radius: 0; }
.color-field-swatch::-moz-color-swatch { border: none; border-radius: 0; }
.color-field-hex {
  flex: 1;
  min-width: 110px;
  border: none;
  background: transparent;
  padding: 0 12px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  outline: none;
}
.color-field-hex:focus { background: rgba(20, 17, 16, 0.04); }
.color-field-hex.invalid {
  color: #8c2a2a;
  background: rgba(168, 60, 60, 0.06);
}

/* =============================================================
   V87.26/27 — RELEASE FORMS surface.
   ============================================================= */

/* Template list grid (looks like workbook tile but the pill says
   RELEASE FORM and the kind colour is oxblood). */
.rf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 21px;
  margin-top: 21px;
}
.rf-tile {
  display: block;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.rf-tile:hover { transform: translateY(-2px); box-shadow: 0 14px 32px -16px rgba(20, 17, 16, 0.22); }
.rf-tile.has-cover {
  background-size: cover;
  background-position: top center;
  aspect-ratio: 3 / 4;
  min-height: 340px;
  display: flex;
  align-items: flex-end;
  position: relative;
}
.rf-tile.has-cover::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(20,17,16,0) 50%, rgba(20,17,16,0.55) 100%);
  pointer-events: none;
}
.rf-tile-overlay {
  position: relative;
  padding: 21px;
  background: rgba(251, 248, 241, 0.96);
  backdrop-filter: blur(6px);
  width: 100%;
}
.rf-tile-eyebrow {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 10px;
}
.rf-tile-kind {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 4px 8px;
  background: #6b1d1d;
  color: var(--paper);
  border-radius: 2px;
}
.rf-tile-title {
  font-family: var(--serif);
  font-size: 21px;
  margin: 0 0 6px;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.rf-tile-blurb {
  font-family: var(--sans);
  font-size: 13px;
  color: rgba(20, 17, 16, 0.6);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Editor field overlay — small kind glyph + label. */
.rf-field-edit-text      { border-color: rgba(60, 100, 170, 0.65); background: rgba(60, 100, 170, 0.08); }
.rf-field-edit-checkbox  { border-color: rgba(120, 60, 170, 0.65); background: rgba(120, 60, 170, 0.10); }
.rf-field-edit-signature { border-color: rgba(170, 60, 60, 0.7);   background: rgba(170, 60, 60, 0.10); }
.rf-field-glyph {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  padding: 0 6px 0 4px;
  color: rgba(20, 17, 16, 0.55);
}
.rf-field-text {
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  color: rgba(20, 17, 16, 0.7);
}

/* Fill flow — wrapping card around the document + model-name field. */
.rf-fill-card {
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
  padding: 34px 21px;
  max-width: 920px;
  margin: 0 auto;
}
.rf-fill-modelname {
  background: rgba(247, 245, 240, 0.6);
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
  padding: 13px 16px;
  margin-bottom: 34px;
  display: flex;
  align-items: center;
  gap: 13px;
  flex-wrap: wrap;
}
.rf-fill-modelname label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.65);
}
.rf-fill-modelname input {
  flex: 1;
  background: transparent;
  border: none;
  border-bottom: 1px dashed rgba(20, 17, 16, 0.32);
  outline: none;
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  padding: 4px 0;
  min-width: 220px;
  color: var(--ink);
}
.rf-fill-modelname input:focus { border-bottom-color: var(--ink); }

/* Fill-mode overlay nodes (apprentice / model interacting). */
.rf-fill-checkbox {
  /* V87.29 — position absolute so the inline left/top/width/height
     placed by the JS actually anchor the checkbox to where the
     educator dropped it on the PDF page. Without this it fell
     into the document flow and the tap never registered on the
     visible box because the visible box was somewhere else. */
  position: absolute;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.55);
  border: 1.5px solid rgba(20, 17, 16, 0.42);
  border-radius: 2px;
  cursor: pointer;
  padding: 0;
  font-family: var(--serif);
  color: transparent;
  /* iOS Safari sometimes blocks button activation on rapid taps
     unless we explicitly enable touch-manipulation. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.rf-fill-checkbox.checked {
  background: rgba(72, 134, 84, 0.85);
  border-color: rgba(72, 134, 84, 0.95);
}
.rf-fill-checkbox-tick {
  font-size: clamp(14px, 4vw, 28px);
  color: transparent;
  line-height: 1;
}
.rf-fill-checkbox.checked .rf-fill-checkbox-tick {
  color: var(--paper);
}

.rf-fill-textwrap { padding: 0; background: transparent; border: none; }

/* Signature pad — sketch area + tiny "Clear" button bottom-right. */
.rf-fill-sig {
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, 0.75);
  border: 1.5px dashed rgba(20, 17, 16, 0.42);
  border-radius: 2px;
  overflow: hidden;
  position: absolute;
}
.rf-fill-sig-canvas {
  flex: 1;
  width: 100%;
  height: 100%;
  cursor: crosshair;
  touch-action: none;
  background: transparent;
}
.rf-fill-sig-actions {
  position: absolute;
  bottom: 4px;
  right: 6px;
}
.rf-fill-sig-clear {
  background: transparent;
  border: none;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
  cursor: pointer;
  padding: 4px 6px;
}
.rf-fill-sig-clear:hover { color: var(--ink); }

/* Model Sheet — completed releases section. */
.mss-releases {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mss-release-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 13px 16px;
  background: rgba(247, 245, 240, 0.6);
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
}
.mss-release-name {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
}
.mss-release-meta {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.55);
}

/* =============================================================
   V87.31 — Model Sheet · Release forms strip.
   ============================================================= */
.model-releases { margin-top: 34px; }
.model-rf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 13px;
}
.model-rf-tile {
  display: block;
  background: #fbf8f1;
  border: 1px solid rgba(20, 17, 16, 0.13);
  border-radius: 2px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  position: relative;
  aspect-ratio: 3 / 4;
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.model-rf-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px -16px rgba(20, 17, 16, 0.22);
}
.model-rf-tile.has-cover {
  background-size: cover;
  background-position: top center;
}
.model-rf-tile.has-cover::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom,
    rgba(20, 17, 16, 0) 50%, rgba(20, 17, 16, 0.55) 100%);
}
.model-rf-tile-overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 13px;
  background: rgba(251, 248, 241, 0.96);
  backdrop-filter: blur(6px);
}
.model-rf-tile-title {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
  margin-top: 4px;
  line-height: 1.2;
  letter-spacing: -0.005em;
}

/* V87.38 — bench photo fields show existing photo as a thumbnail
   so editing a session pre-populates visually. */
.bench-photo-field { display: flex; flex-direction: column; }
.bench-photo-thumb {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: #f1ede4;
  border: 1px dashed rgba(20, 17, 16, 0.18);
  border-radius: 2px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bench-photo-thumb.is-empty::before {
  content: "No photo";
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(20, 17, 16, 0.4);
}
.bench-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.bench-photo-hint {
  margin-top: 6px;
  font-size: 12px;
}

/* V87.36 — release tiles inside the Log a session modal.
   Slightly smaller minmax so they sit nicely next to the journal
   note, and a disabled state for unsaved sessions. */
.bench-rf-grid {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.model-rf-tile {
  /* button-tile resets — when the tile is a <button> instead of
     an <a> the browser defaults look wrong, so neutralise them. */
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  appearance: none;
}
.model-rf-tile.is-disabled {
  opacity: 0.55;
  cursor: not-allowed;
  filter: grayscale(0.4);
}
.model-rf-tile.is-disabled:hover {
  transform: none;
  box-shadow: none;
}

/* =============================================================
   V88.0 — POLISH PASS
   Robustness + mobile feel. Everything below is additive; no
   earlier rule is removed, in keeping with the file's
   append-by-version convention.
   ============================================================= */

/* ---- Workbook autosave status -------------------------------- */
/* A quiet mono pill that tells the apprentice her writing is safe.
   Sticky just under the top bar so it's visible mid-page. */
.wb-save-status-row {
  position: sticky;
  top: max(8px, env(safe-area-inset-top));
  z-index: 30;
  display: flex;
  justify-content: flex-end;
  pointer-events: none;
  min-height: 0;
}
.wb-save-status {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0;
  border-radius: 999px;
  transition: opacity var(--med) var(--ease);
  opacity: 0;
}
.wb-save-status.is-busy,
.wb-save-status.is-ok,
.wb-save-status.is-warn,
.wb-save-status.is-err {
  opacity: 1;
  padding: 6px 14px;
  background: var(--cream, #FAF6EE);
  border: 1px solid var(--line-soft, #DDD4C2);
  box-shadow: 0 8px 24px -16px rgba(20, 17, 16, 0.35);
}
.wb-save-status.is-busy { color: var(--ink-3, #776C62); }
.wb-save-status.is-ok   { color: var(--sage, #7D8A78); border-color: var(--sage, #7D8A78); }
.wb-save-status.is-warn { color: #a87a1d; border-color: #a87a1d; }
.wb-save-status.is-err  { color: var(--alert, #8B2418); border-color: var(--alert, #8B2418); }

/* ---- Route error card ---------------------------------------- */
.route-error-card {
  max-width: 480px;
  margin: 13vh auto 0;
  padding: 55px 34px;
  text-align: center;
  background: var(--cream, #FAF6EE);
  border: 1px solid var(--line, #C9BFAD);
}
.route-error-card .display-m { margin: 13px 0; }
.route-error-card .u-link { display: inline-block; margin-top: 21px; }
.route-error-card .jc-c { justify-content: center; }

/* ---- Touch targets (phones, salon floor, gloves) -------------- */
@media (pointer: coarse) {
  .btn-sm { min-height: 44px; }
  .btn    { min-height: 44px; }
  /* The tiny text-link actions (Delete / Remove / Edit rows) get a
     taller invisible hit area without changing their look. */
  button.caption.u-link,
  .caption.u-link {
    position: relative;
    padding-top: 10px;
    padding-bottom: 10px;
    margin-top: -6px;
    margin-bottom: -6px;
  }
  /* Checkboxes were 16px — hard to hit with a gloved thumb. */
  input[type="checkbox"] {
    width: 22px;
    height: 22px;
    min-width: 22px;
    accent-color: var(--ink, #141110);
  }
}

/* ---- Focus visibility (one consistent ring) ------------------- */
:focus-visible {
  outline: 2px solid var(--ink, #141110);
  outline-offset: 2px;
}
.btn:focus-visible,
.tile:focus-visible,
.model-rf-tile:focus-visible {
  outline: 2px solid var(--oxblood, #5A1918);
  outline-offset: 2px;
}
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: none; /* fields keep their existing border treatment */
}

/* ---- Skeleton shimmer for anything loading -------------------- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--paper, #E8E1D1);
  color: transparent !important;
  border-color: transparent !important;
  pointer-events: none;
  min-height: 1em;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(250, 246, 238, 0)   0%,
    rgba(250, 246, 238, 0.7) 50%,
    rgba(250, 246, 238, 0)   100%);
  transform: translateX(-100%);
  animation: tone-shimmer 1.4s var(--ease) infinite;
}
@keyframes tone-shimmer {
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

/* ---- iOS scroll feel ------------------------------------------ */
.mv-stage-pdf-editorial,
.wb-pages,
.modal {
  -webkit-overflow-scrolling: touch;
}
/* Stop modal scroll chaining to the page beneath on phones. */
.modal { overscroll-behavior: contain; }

/* ---- Safer destructive buttons -------------------------------- */
/* Slightly larger gap so Delete is never a thumb-slip away from
   the primary action on the session composer. */
@media (pointer: coarse) {
  form .btn-ghost.btn-sm:last-child { margin-left: 8px; }
}

/* =============================================================
   V89.0 — MEMBERSHIP + INSTALL
   ============================================================= */

/* Tier cards on the Membership page. */
.membership-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 21px;
  align-items: stretch;
}
.membership-card {
  display: flex;
  flex-direction: column;
  padding: 34px 26px;
  border: 1px solid var(--line, #C9BFAD);
  background: var(--cream, #FAF6EE);
}
.membership-card.is-current {
  border-color: var(--ink, #141110);
  box-shadow: 0 24px 60px -40px rgba(20, 17, 16, 0.45);
}
.membership-points {
  list-style: none;
  margin: 0 0 21px;
  padding: 0;
  flex: 1;
}
.membership-points li {
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft, #DDD4C2);
  font-size: 14px;
}
.membership-points li:last-child { border-bottom: none; }

/* Install steps inside the Download-the-app modal. */
.install-steps {
  margin: 0;
  padding-left: 21px;
}
.install-steps li {
  margin-bottom: 13px;
  line-height: 1.6;
}
.install-glyph {
  font-size: 17px;
  vertical-align: -1px;
}

/* =============================================================
   V90.0 — SELF-SERVE SIGNUP (tier picker cards)
   ============================================================= */
.signup-tiers {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 8px;
}
.signup-tier {
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  padding: 13px;
  background: var(--cream, #FAF6EE);
  border: 1px solid var(--line, #C9BFAD);
  cursor: pointer;
  font-family: inherit;
  transition: border-color var(--fast, 140ms) var(--ease, ease),
              box-shadow var(--fast, 140ms) var(--ease, ease);
}
.signup-tier:hover { border-color: var(--ink-3, #776C62); }
.signup-tier.selected {
  border-color: var(--ink, #141110);
  box-shadow: 0 8px 24px -16px rgba(20, 17, 16, 0.45);
}
.signup-tier-name {
  font-family: var(--serif);
  font-size: 17px;
}
.signup-tier-price {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--oxblood, #5A1918);
}
.signup-tier-blurb {
  font-size: 11px;
  line-height: 1.45;
  color: var(--ink-3, #776C62);
}

/* =============================================================
   V91.0 — THE VAULT + PRESENTER
   ============================================================= */

/* ---- Vault grid ---- */
.vault-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 21px;
}
.vault-card {
  background: var(--cream, #FAF6EE);
  border: 1px solid var(--line, #C9BFAD);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.vault-thumb-btn {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  border-bottom: 1px solid var(--line-soft, #DDD4C2);
  background: var(--paper, #E8E1D1);
  cursor: pointer;
  aspect-ratio: 16 / 10;
  overflow: hidden;
}
.vault-thumb { width: 100%; height: 100%; display: flex; align-items: flex-start; justify-content: center; overflow: hidden; }
.vault-thumb canvas { width: 100% !important; height: auto !important; }
.vault-thumb-loading {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--ink-3, #776C62);
  align-self: center;
}
.vault-present-hint {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.2em;
  color: var(--bone, #F3EEE4);
  background: rgba(20, 17, 16, 0.55);
  opacity: 0;
  transition: opacity var(--fast, 140ms) var(--ease, ease);
}
.vault-thumb-btn:hover .vault-present-hint,
.vault-thumb-btn:focus-visible .vault-present-hint { opacity: 1; }
.vault-card-body { padding: 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.vault-card-title {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 400;
  line-height: 1.25;
  margin: 0;
}
.vault-mod-chip { color: var(--oxblood, #5A1918); }
.vault-card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding-top: 8px;
}

/* ---- Presenter ---- */
html.presenting { overflow: hidden; }
.presenter-root {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: #0E0C0B;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.presenter-stage { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.presenter-slide canvas {
  box-shadow: 0 30px 90px -30px rgba(0, 0, 0, 0.9);
}
.presenter-loading, .presenter-error {
  color: rgba(243, 238, 228, 0.7);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0 34px;
  text-align: center;
}
.presenter-chrome {
  position: absolute;
  top: 0; left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: max(13px, env(safe-area-inset-top)) 21px 13px;
  background: linear-gradient(rgba(14, 12, 11, 0.85), transparent);
  transition: opacity 400ms var(--ease, ease);
}
.presenter-title {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(243, 238, 228, 0.6);
}
.presenter-close {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bone, #F3EEE4);
  background: transparent;
  border: 1px solid rgba(243, 238, 228, 0.35);
  padding: 8px 16px;
  cursor: pointer;
  min-height: 44px;
}
.presenter-close:hover { border-color: var(--bone, #F3EEE4); }
.presenter-footer {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 21px;
  padding: 13px 21px max(13px, env(safe-area-inset-bottom));
  background: linear-gradient(transparent, rgba(14, 12, 11, 0.85));
  transition: opacity 400ms var(--ease, ease);
}
.presenter-counter {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.2em;
  color: rgba(243, 238, 228, 0.75);
  min-width: 80px;
  text-align: center;
}
.presenter-nav {
  font-size: 17px;
  color: var(--bone, #F3EEE4);
  background: transparent;
  border: 1px solid rgba(243, 238, 228, 0.35);
  width: 44px;
  height: 44px;
  cursor: pointer;
}
.presenter-nav:disabled { opacity: 0.25; cursor: default; }
.presenter-nav:hover:not(:disabled) { border-color: var(--bone, #F3EEE4); }
.presenter-root.chrome-hidden .presenter-chrome,
.presenter-root.chrome-hidden .presenter-footer { opacity: 0; pointer-events: none; }

/* V91.1 — embed presenter (Office viewer / video / image) + thumbs */
.presenter-root-embed .presenter-stage { padding: 0; }
.presenter-embed {
  width: 100vw;
  height: 100vh;
  border: none;
  background: #0E0C0B;
}
.presenter-video, .presenter-image {
  width: auto;
  height: auto;
  max-width: 100vw;
  max-height: 100vh;
  object-fit: contain;
  margin: auto;
}
.vault-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
