/* Scholar OS - visual system
   Dark by default, light available. One accent, class colours do the rest. */

:root {
  --bg: #0d1017;
  --bg-2: #12161f;
  --surface: #171c27;
  --surface-2: #1d2331;
  --surface-3: #242b3b;
  --line: #262d3d;
  --line-soft: #1e2431;

  --text: #e8ecf4;
  --text-2: #9aa4b8;
  --text-3: #6b7488;

  --accent: #7c6cf5;
  --accent-2: #a78bfa;
  --accent-soft: rgba(124, 108, 245, 0.14);

  --green: #34d399;
  --amber: #fbbf24;
  /* fixed brand colour - deliberately not themed, so the logo reads the same
     everywhere and matches the icon on the home screen */
  --brand-tile: #0d1017;
  --red: #f87171;
  --blue: #60a5fa;
  --teal: #2dd4bf;
  --pink: #f472b6;
  --violet: #a78bfa;
  --slate: #94a3b8;

  --ring-track: #232a39;
  --shadow: 0 10px 32px rgba(0, 0, 0, 0.45);
  --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.28);
  /* one spacing scale - every page uses these, nothing ad-hoc */
  --sp-1: 6px;
  --sp-2: 10px;
  --sp-3: 14px;
  --sp-4: 18px;
  --sp-5: 24px;
  --sp-6: 34px;

  --radius: 14px;
  --radius-sm: 9px;
  --sidebar-w: 232px;
  --header-h: 60px;
  --tabbar-h: 0px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;
}

html[data-theme='light'] {
  --bg: #f5f6fa;
  --bg-2: #eef0f6;
  --surface: #ffffff;
  --surface-2: #f7f8fc;
  --surface-3: #eef0f7;
  --line: #e2e5ee;
  --line-soft: #eaedf4;
  --text: #161a24;
  --text-2: #5a6379;
  --text-3: #8b93a7;
  --ring-track: #e6e9f2;
  --accent-soft: rgba(124, 108, 245, 0.1);
  --shadow: 0 10px 30px rgba(20, 25, 45, 0.1);
  --shadow-sm: 0 1px 6px rgba(20, 25, 45, 0.07);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  overscroll-behavior-y: none;
  -webkit-tap-highlight-color: transparent;
}

body.modal-open { overflow: hidden; }

h1, h2, h3, h4 { margin: 0; font-weight: 650; letter-spacing: -0.01em; }
h1 { font-size: 22px; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
p { margin: 0; }
a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }

.icon { flex: none; }

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

#app {
  display: flex;
  height: 100vh;
  height: 100dvh;                 /* iOS Safari: survives the collapsing toolbar */
  padding-left: var(--safe-l);
  padding-right: var(--safe-r);
}

.sidebar {
  width: var(--sidebar-w);
  flex: none;
  background: var(--bg-2);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  padding: 16px 12px;
  gap: 4px;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 8px 16px;
}
/* The mark's book pages are white, so it needs a dark tile behind it or the
   interior disappears on the light themes. Same tile as the home-screen icon,
   which also makes the two read as the same app. */
.brand-mark {
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  background: var(--brand-tile) url('/icons/logo-mark.png') center / 74% no-repeat;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
}
.brand-mark.lg { width: 46px; height: 46px; border-radius: 13px; }
.brand-name { font-weight: 700; font-size: 15px; letter-spacing: -0.02em; }
.brand-sub { font-size: 11px; color: var(--text-3); }

.nav { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; }
.nav-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-3); padding: 14px 10px 6px; font-weight: 600;
}
.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--radius-sm);
  color: var(--text-2); cursor: pointer; border: none; background: none;
  font: inherit; text-align: left; width: 100%; position: relative;
}
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item.active { background: var(--accent-soft); color: var(--accent-2); font-weight: 600; }
.nav-item.active::before {
  content: ''; position: absolute; left: -12px; top: 8px; bottom: 8px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--accent);
}
.nav-badge {
  margin-left: auto; font-size: 11px; font-weight: 700; padding: 1px 7px;
  border-radius: 99px; background: var(--surface-3); color: var(--text-2);
}
.nav-badge.hot { background: rgba(248, 113, 113, 0.16); color: var(--red); }
.nav-badge.go { background: rgba(52, 211, 153, 0.16); color: var(--green); }

.sidebar-foot { border-top: 1px solid var(--line-soft); padding-top: 9px; display: flex; flex-direction: column; gap: 6px; }
.sync-line { font-size: 11px; color: var(--text-3); padding: 0 10px; display: flex; align-items: center; gap: 6px; }
.sync-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex: none; }
.sync-dot.off { background: var(--red); }
.sync-dot.busy { background: var(--amber); animation: pulse 1s infinite; }
@keyframes pulse { 50% { opacity: 0.35; } }

/* ------------------------------------------------------------- main ----- */

.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.topbar {
  height: calc(var(--header-h) + var(--safe-t));
  padding-top: var(--safe-t);
  flex: none;
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
  display: flex; align-items: center; gap: 12px;
  padding: 0 20px;
}
.topbar h1 { font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar > div:first-of-type { min-width: 0; }
.topbar > div { min-width: 0; }
.topbar-sub { font-size: 12px; color: var(--text-3); }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.streak-pill {
  display: flex; align-items: center; gap: 6px;
  background: linear-gradient(135deg, rgba(251, 191, 36, 0.16), rgba(248, 113, 113, 0.12));
  border: 1px solid rgba(251, 191, 36, 0.25);
  color: var(--amber); padding: 5px 11px; border-radius: 99px;
  font-size: 12.5px; font-weight: 650;
}
.streak-pill.cold { background: var(--surface-2); border-color: var(--line); color: var(--text-3); }

.content {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 22px 24px calc(60px + var(--tabbar-h) + var(--safe-b));
}
.content.narrow { max-width: 1200px; margin: 0 auto; width: 100%; }

/* ---------------------------------------------------------- primitives -- */

.btn {
  display: inline-flex; align-items: center; gap: 7px; justify-content: center;
  padding: 8px 14px; border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text); font: inherit; font-weight: 600;
  font-size: 13px; cursor: pointer; transition: background 0.14s, border-color 0.14s, transform 0.08s;
  white-space: nowrap;
}
.btn:hover { background: var(--surface-3); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-2); border-color: var(--accent-2); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.btn.danger { background: rgba(248, 113, 113, 0.14); border-color: rgba(248, 113, 113, 0.3); color: var(--red); }
.btn.danger:hover { background: rgba(248, 113, 113, 0.22); }
.btn.sm { padding: 5px 10px; font-size: 12px; }
.btn.lg { padding: 11px 20px; font-size: 14.5px; }
.btn.block { width: 100%; }

.icon-btn {
  display: grid; place-items: center; width: 32px; height: 32px;
  border-radius: var(--radius-sm); border: 1px solid transparent;
  background: transparent; color: var(--text-2); cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn.solid { background: var(--surface-2); border-color: var(--line); }

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--sp-4);
}
.card.pad-lg { padding: var(--sp-5); }
.card.flush { padding: 0; overflow: hidden; }

.grid { display: grid; gap: var(--sp-3); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-auto { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.row { display: flex; align-items: center; gap: 10px; }
.row.wrap { flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.col { display: flex; flex-direction: column; gap: 10px; }
.spacer { flex: 1; }
.stack > * + * { margin-top: var(--sp-3); }

.section-head { display: flex; align-items: center; justify-content: space-between; margin: var(--sp-6) 0 var(--sp-3); gap: 12px; }
.section-head:first-child { margin-top: 0; }
.section-head h2 { font-size: 15px; }

/* ---------------------------------------------------------- fold ------- */
.fold { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); margin-top: var(--sp-2); }
.fold + .fold { margin-top: var(--sp-2); }
.fold-head {
  display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4);
  cursor: pointer; list-style: none; user-select: none; border-radius: var(--radius);
}
.fold-head::-webkit-details-marker { display: none; }
.fold-head:hover .fold-title { color: var(--text); }
.fold-title { font-size: 14px; font-weight: 650; color: var(--text); }
.fold-note { flex: none; }
.fold-chev { color: var(--text-3); display: flex; transition: transform 0.16s; }
.fold[open] > .fold-head > .fold-chev { transform: rotate(180deg); }
.fold-body { padding: 0 var(--sp-4) var(--sp-4); }
.fold[open] > .fold-head { border-bottom: 1px solid var(--line-soft); border-radius: var(--radius) var(--radius) 0 0; }
.fold[open] > .fold-body { padding-top: var(--sp-3); }
/* a card inside a fold would be a box in a box */
.fold-body > .card { border: none; background: none; padding: 0; }

/* ------------------------------------------------- formula typesetting - */
/* A real numerator over a real denominator. Inline-flex columns rather than
   a table so a fraction can sit inside a line of other terms, and nest. */
.formula-box { display: flex; flex-direction: column; gap: 5px; }
.formula-expr {
  font-family: var(--mono); font-size: 14px; line-height: 1.25;
  color: var(--text); display: flex; flex-wrap: wrap; align-items: center;
}
.formula-prose { font-size: 12.5px; color: var(--text-2); }
.expr, .seq { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0; }
.expr .op { margin: 0 5px; color: var(--text-2); }
.expr .paren { color: var(--text-3); }
.expr sub, .expr sup { font-size: 0.68em; font-family: var(--mono); }
.expr sub { vertical-align: -0.28em; }
.expr sup { vertical-align: 0.42em; }

.frac {
  display: inline-flex; flex-direction: column; align-items: center;
  vertical-align: middle; margin: 0 4px; text-align: center;
}
.frac-num, .frac-den { padding: 0 5px; white-space: nowrap; }
.frac-num { padding-bottom: 1px; }
.frac-den { padding-top: 1px; }
.frac-bar { width: 100%; height: 1px; background: currentColor; opacity: 0.75; }

/* --- the legend under a formula --- */
.legend { margin-top: 7px; display: flex; flex-direction: column; gap: 3px; }
.legend-row { display: flex; gap: 8px; align-items: baseline; font-size: 11.5px; }
.legend-sym {
  font-family: var(--mono); color: var(--accent-2); font-weight: 600;
  flex: none; min-width: 42px;
}
.legend-mean { color: var(--text-2); }
.legend-note { font-size: 11.5px; color: var(--text-3); margin-top: 3px; }
.legend-missing { font-size: 11px; color: var(--amber); margin-top: 3px; }

@media print {
  .formula-expr { color: #000; }
  .legend-sym { color: #000; }
  .legend-mean, .legend-note { color: #333; }
  .frac-bar { background: #000; }
}

/* ---------------------------------------------------------- formulas --- */
.formula-line {
  font-family: var(--mono); font-size: 12.5px; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: 8px; padding: 7px 9px; margin: 5px 0 4px;
  white-space: pre-wrap; overflow-x: auto;
}
.formula-ink {
  width: 100%; display: block; background: var(--surface-2);
  border: 1px solid var(--line-soft); border-radius: 8px; margin: 5px 0 4px;
}
.formula-row { padding: 11px 2px; border-bottom: 1px solid var(--line-soft); }
.formula-row:last-child { border-bottom: none; }

.muted { color: var(--text-2); }
.dim { color: var(--text-3); }
.tiny { font-size: 11.5px; }
.small { font-size: 12.5px; }
.big { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; }
.mono { font-family: var(--mono); font-size: 12.5px; }
.strong { font-weight: 650; }
.center { text-align: center; }
.nowrap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 99px; font-size: 11px; font-weight: 600;
  background: var(--surface-3); color: var(--text-2); white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.chip.tone { background: color-mix(in srgb, var(--chip) 13%, transparent); color: var(--chip); }
.chip.dot::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--chip); }
.chip.green { background: rgba(52, 211, 153, 0.11); color: var(--green); }
.chip.amber { background: rgba(251, 191, 36, 0.11); color: var(--amber); }
.chip.red { background: rgba(248, 113, 113, 0.11); color: var(--red); }
.chip.blue { background: rgba(96, 165, 250, 0.11); color: var(--blue); }
.chip.violet { background: rgba(167, 139, 250, 0.11); color: var(--violet); }
.chip.teal { background: rgba(45, 212, 191, 0.11); color: var(--teal); }
.chip.pink { background: rgba(244, 114, 182, 0.11); color: var(--pink); }
.chip.slate { background: var(--surface-3); color: var(--text-2); }

.bar { height: 6px; border-radius: 99px; background: var(--ring-track); overflow: hidden; }
.bar.slim { height: 4px; }
.bar-fill { height: 100%; border-radius: 99px; transition: width 0.4s cubic-bezier(0.2, 0.8, 0.2, 1); }

.ring { position: relative; display: grid; place-items: center; }
.ring svg { position: absolute; inset: 0; }
.ring-label { font-weight: 700; letter-spacing: -0.02em; position: relative; }

.spark { width: 100%; }
.spark-empty { font-size: 12px; color: var(--text-3); padding: 10px 0; }

.empty-state { text-align: center; padding: 34px 18px; color: var(--text-2); }
.empty-icon { color: var(--text-3); margin-bottom: 10px; display: grid; place-items: center; }
.empty-state p { margin-bottom: 14px; font-size: 13px; }

.loading { display: flex; align-items: center; gap: 10px; color: var(--text-2); padding: 26px; justify-content: center; }
.spinner {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------- form -- */

.field { display: flex; flex-direction: column; gap: 5px; }
.field-label { font-size: 12px; font-weight: 600; color: var(--text-2); }
.field-hint { font-size: 11.5px; color: var(--text-3); }

.input {
  width: 100%; padding: 9px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text);
  font: inherit; font-size: 13.5px; outline: none; transition: border-color 0.14s, box-shadow 0.14s;
}
.input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.input::placeholder { color: var(--text-3); }
.textarea { resize: vertical; min-height: 62px; line-height: 1.55; }
.select { appearance: none; cursor: pointer; padding-right: 30px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%239aa4b8' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; }

.form-grid { display: grid; gap: 13px; }
.form-grid.two { grid-template-columns: 1fr 1fr; }
.form-grid .full { grid-column: 1 / -1; }

.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 2px; gap: 2px; }
.seg button {
  border: none; background: none; color: var(--text-2); font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 5px 12px; border-radius: 7px; cursor: pointer;
}
.seg button:hover { color: var(--text); }
.seg button.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

.pick-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.pick {
  padding: 6px 11px; border-radius: 99px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text-2); font: inherit; font-size: 12.5px;
  font-weight: 600; cursor: pointer;
}
.pick:hover { color: var(--text); border-color: var(--text-3); }
.pick.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-2); }
.pick.on[data-color] { background: color-mix(in srgb, var(--pc) 18%, transparent); border-color: var(--pc); color: var(--pc); }

.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; }
.switch input { display: none; }
.switch-track { width: 34px; height: 19px; border-radius: 99px; background: var(--surface-3); position: relative; transition: background 0.16s; flex: none; }
.switch-track::after { content: ''; position: absolute; top: 2.5px; left: 2.5px; width: 14px; height: 14px; border-radius: 50%; background: var(--text-3); transition: transform 0.16s, background 0.16s; }
.switch input:checked + .switch-track { background: var(--accent-soft); }
.switch input:checked + .switch-track::after { transform: translateX(15px); background: var(--accent); }

/* -------------------------------------------------------------- modal --- */

.modal-back {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6, 8, 14, 0.62); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 24px;
  opacity: 0; transition: opacity 0.16s;
}
.modal-back.in { opacity: 1; }
.modal {
  width: min(560px, 100%); max-height: 88vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: var(--shadow); transform: translateY(8px) scale(0.99); transition: transform 0.18s;
}
.modal-back.in .modal { transform: none; }
.modal.wide { width: min(900px, 100%); }
.modal.narrow { width: min(420px, 100%); }
.modal-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 18px 12px; }
.modal-title { font-size: 16px; }
.modal-sub { font-size: 12.5px; color: var(--text-3); margin-top: 3px; }
.modal-head .icon-btn { margin-left: auto; }
.modal-body { padding: 4px 18px 18px; overflow-y: auto; }
.modal-foot { padding: 14px 18px; border-top: 1px solid var(--line); display: flex; gap: 8px; justify-content: flex-end; }
.confirm-text { color: var(--text-2); font-size: 13.5px; }

/* -------------------------------------------------------------- toast --- */

.toast-host { position: fixed; bottom: 20px; right: 20px; z-index: 300; display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.toast {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text);
  padding: 10px 14px; border-radius: var(--radius-sm); box-shadow: var(--shadow);
  font-size: 13px; max-width: 420px;
  opacity: 0; transform: translateX(12px); transition: opacity 0.2s, transform 0.2s;
}
.toast.in { opacity: 1; transform: none; }
.toast.success { border-color: rgba(52, 211, 153, 0.4); color: var(--green); }
.toast.error { border-color: rgba(248, 113, 113, 0.4); color: var(--red); }

/* ---------------------------------------------------------- dashboard --- */

.hero { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; }
.hero h1 { font-size: 25px; }
.hero-date { color: var(--text-3); font-size: 13px; margin-top: 3px; }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-2); }
.stat {
  background: var(--surface); border: 1px solid transparent; border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4); display: flex; flex-direction: column; gap: 2px;
}
.stat-label { font-size: 11px; color: var(--text-3); font-weight: 600; letter-spacing: 0.02em; }
.stat-value { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; }
.stat-note { font-size: 12px; color: var(--text-2); }

.class-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0; overflow: hidden; cursor: pointer; transition: border-color 0.14s, transform 0.14s;
  display: flex; flex-direction: column;
}
.class-card:hover { border-color: var(--text-3); transform: translateY(-1px); }
.class-stripe { height: 3px; }
.class-body { padding: 14px 15px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.class-top { display: flex; align-items: flex-start; gap: 12px; }
.class-name { font-weight: 650; font-size: 14.5px; line-height: 1.3; }
.class-code { font-size: 11.5px; color: var(--text-3); font-family: var(--mono); margin-top: 2px; }
.class-meta { display: flex; flex-wrap: wrap; gap: 5px; }
.class-next { font-size: 12.5px; color: var(--text-2); display: flex; align-items: center; gap: 6px; }

/* ------------------------------------------------------ dashboard ------ */
/*
 * The dashboard is a bento layout: Today gets half the width, the two things
 * he actually starts from get their own tiles, and the rest is whichever
 * destinations he has pinned.
 */
.bento {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3); align-items: start;
}
.bento > .tile-stack { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
/* minmax(0, 1fr), never plain 1fr: the rows inside carry nowrap titles, so a
   column sized to min-content blows out to 577px inside a 339px phone. */
@media (max-width: 940px) { .bento { grid-template-columns: minmax(0, 1fr); } }

.tile {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 16px; padding: var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-2);
  min-width: 0;
}
.tile-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.tile-title { font-size: 14px; font-weight: 650; display: flex; align-items: center; gap: 7px; }
.tile-title svg { color: var(--text-3); flex: none; }
.tile-note { font-size: 11.5px; color: var(--text-3); }
.tile-cta { margin-top: auto; }

/* Today can run long; it scrolls inside its own tile rather than stretching
   the page, so the tiles beside it stay where they are. */
.today-scroll { max-height: 340px; overflow-y: auto; overflow-x: hidden; margin: 0 calc(var(--sp-2) * -1); padding: 0 var(--sp-2); }

/* --- the one visual language for "this matters now" --- */
.tile.is-urgent { border-color: color-mix(in srgb, var(--red) 45%, var(--line)); }
.flag {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
  padding: 1px 7px; border-radius: 99px; text-transform: uppercase;
}
.flag.urgent { background: rgba(248, 113, 113, 0.14); color: var(--red); }
.flag.soon { background: rgba(251, 191, 36, 0.14); color: var(--amber); }
.flag.heavy { background: var(--accent-soft); color: var(--accent-2); }
.up-item.urgent .up-bar { background: var(--red) !important; }
.up-item.soon .up-bar { background: var(--amber) !important; }

/* --- pinned destinations --- */
.pin-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: var(--sp-2); }
.pin {
  display: flex; align-items: center; gap: 9px; text-align: left;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
  padding: 12px 13px; cursor: pointer; color: var(--text);
  transition: border-color 0.14s, transform 0.14s;
}
.pin:hover { border-color: var(--text-3); transform: translateY(-1px); }
.pin svg { color: var(--text-3); flex: none; }
.pin-main { flex: 1; min-width: 0; }
.pin-label { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pin-hint { font-size: 11px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pin-count {
  font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 99px;
  background: var(--surface-3); color: var(--text-2); flex: none;
}
.pin-count.hot { background: rgba(248, 113, 113, 0.14); color: var(--red); }

.mins { display: flex; gap: 6px; flex-wrap: wrap; }
.mins button {
  flex: 1; min-width: 54px; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 10px; padding: 9px 0; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--text); cursor: pointer;
}
.mins button:hover { border-color: var(--accent); color: var(--accent-2); }

.d-status {
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
  font-size: 13px; color: var(--text-2); margin-bottom: var(--sp-4);
}
.d-alert, .d-quiet, .d-more, .d-note {
  background: none; border: none; padding: 0; font: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.d-alert { color: var(--red); font-weight: 650; }
.d-quiet { color: var(--text-3); }
.d-alert:hover, .d-quiet:hover, .d-more:hover { text-decoration: underline; }
.d-label {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 11.5px; font-weight: 600; color: var(--text-3);
  letter-spacing: 0.03em; margin: var(--sp-5) 0 var(--sp-1);
}
.d-more { font-size: 11.5px; font-weight: 600; color: var(--text-3); }
.d-note {
  margin-top: var(--sp-4); font-size: 12.5px; color: var(--text-3); text-align: left;
}
.d-note svg { color: var(--amber); flex: none; }
.d-note:hover { color: var(--text-2); }

.up-list { display: flex; flex-direction: column; }
.up-item {
  display: flex; align-items: center; gap: 12px; padding: 11px 4px;
  border-bottom: 1px solid var(--line-soft); cursor: pointer;
}
.up-item:last-child { border-bottom: none; }
.up-item:hover { background: var(--surface-2); }
.up-bar { width: 3px; align-self: stretch; border-radius: 2px; flex: none; }
.up-main { flex: 1; min-width: 0; }
.up-title { font-weight: 600; font-size: 13.5px; }
.up-sub { font-size: 12px; color: var(--text-3); display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.up-when { text-align: right; font-size: 12.5px; font-weight: 650; flex: none; }
.up-when.soon { color: var(--amber); }
.up-when.now { color: var(--red); }
.up-when.past { color: var(--red); }

.plan-item {
  display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line-soft);
}
/* the class is identified by this bar, so the row does not repeat its name
   in a nowrap chip that stole 40% of the width and wrapped the title over
   five lines */
.plan-bar { width: 3px; align-self: stretch; border-radius: 2px; flex: none; }
.plan-rank { width: 22px; height: 22px; border-radius: 7px; background: var(--accent-soft); color: var(--accent-2);
  display: grid; place-items: center; font-size: 12px; font-weight: 700; flex: none; }
.plan-title { font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-why { font-size: 12px; color: var(--text-3); margin-top: 2px; }

.today-strip { display: flex; gap: 10px; flex-wrap: wrap; }
.today-chip {
  display: flex; align-items: center; gap: 9px; padding: 9px 13px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.today-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.today-time { font-family: var(--mono); font-size: 12px; color: var(--text-3); }

/* ---------------------------------------------------------- calendar ---- */

.cal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.cal-title { font-size: 17px; font-weight: 650; min-width: 190px; }

.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.cal-dow { background: var(--bg-2); padding: 8px 10px; font-size: 11px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; text-align: center; }
.cal-cell { background: var(--surface); min-height: 108px; padding: 7px 8px; display: flex; flex-direction: column; gap: 4px; cursor: pointer; transition: background 0.12s; }
.cal-cell:hover { background: var(--surface-2); }
.cal-cell.dim { background: var(--bg-2); }
.cal-cell.dim .cal-num { color: var(--text-3); opacity: 0.55; }
.cal-cell.today { background: var(--accent-soft); }
.cal-num { font-size: 12px; font-weight: 650; color: var(--text-2); }
.cal-cell.today .cal-num { color: var(--accent-2); }
.cal-num-badge { display: inline-grid; place-items: center; width: 21px; height: 21px; border-radius: 50%; }
.cal-cell.today .cal-num-badge { background: var(--accent); color: #fff; }
/* One pill per thing due. A month cell is only ~75px wide, so every pixel
   spent on decoration is a character of the title lost: the colour signal is a
   3px bar rather than a dot, and the title gets two lines instead of one. */
.cal-ev {
  display: flex;
  align-items: stretch;
  gap: 5px;
  font-size: 11px;
  line-height: 1.3;
  padding: 3px 5px 3px 0;
  border-radius: 4px;
  font-weight: 600;
  min-width: 0;
  cursor: pointer;
  background: color-mix(in srgb, var(--ec) 20%, var(--surface));
  color: var(--text);
  overflow: hidden;
}
.cal-ev:hover { background: color-mix(in srgb, var(--ec) 34%, var(--surface)); }

.cal-ev-dot {
  flex: none;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--ec);
}

.cal-ev-text {
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* An exam is the thing you cannot afford to skim past, so it gets the solid
   fill and everything else stays tinted. */
.cal-ev.exam {
  background: var(--ec);
  color: #fff;
  font-weight: 700;
}
.cal-ev.exam:hover { filter: brightness(1.1); }
.cal-ev.exam .cal-ev-dot { background: rgba(255, 255, 255, 0.85); }

/* Recurring class times are context, not work - they must not compete. */
.cal-ev.meeting {
  background: transparent;
  color: var(--text-3);
  font-weight: 500;
}
.cal-ev.meeting .cal-ev-text { -webkit-line-clamp: 1; line-clamp: 1; }
.cal-ev.meeting .cal-ev-dot { opacity: 0.7; }
.cal-ev.meeting:hover { background: var(--surface-2); }

/* A phone cell is ~48px. Two characters and an ellipsis ("Mo...") tells you
   nothing, so drop the text entirely and let the colour do the work - tapping
   the day opens the full list. This is what iOS and Google Calendar do too. */
@media (max-width: 640px) {
  .cal-ev {
    padding: 0;
    gap: 0;
    height: 7px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--ec) 55%, var(--surface));
  }
  .cal-ev-text { display: none; }
  .cal-ev-dot { display: none; }

  /* an exam still has to shout, so it gets full colour and more height */
  .cal-ev.exam { height: 10px; background: var(--ec); }

  /* class times stay a hairline so they never crowd out real work */
  .cal-ev.meeting {
    height: 3px;
    background: color-mix(in srgb, var(--ec) 40%, transparent);
  }

  .cal-cell { gap: 3px; }
  .cal-more { font-size: 9.5px; }
}
.cal-more { font-size: 10.5px; color: var(--text-3); font-weight: 600; padding-left: 3px; }

.cal-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.cal-week .cal-cell { min-height: 300px; }

.day-panel { display: flex; flex-direction: column; gap: 10px; }
.day-ev { display: flex; gap: 10px; padding: 10px; border-radius: var(--radius-sm); background: var(--surface-2); border-left: 3px solid var(--ec); }

/* ------------------------------------------------------------ classes --- */

.class-hero { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.class-hero-main { flex: 1; min-width: 260px; }
.class-title-row { display: flex; align-items: center; gap: 10px; }
.class-title-row h1 { font-size: 24px; }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin: 20px 0 18px; overflow-x: auto; }
.tab {
  padding: 9px 14px; border: none; background: none; color: var(--text-2);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--accent-2); border-bottom-color: var(--accent); }

.unit-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
}
.unit-num { width: 26px; height: 26px; border-radius: 8px; background: var(--surface-3); color: var(--text-2);
  display: grid; place-items: center; font-size: 12px; font-weight: 700; flex: none; }
.unit-main { flex: 1; min-width: 0; }
.unit-name { font-weight: 600; font-size: 13.5px; }
.unit-topics { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.unit-mastery { width: 116px; flex: none; }

/* ------------------------------------------------------------- tables --- */

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-3); font-weight: 700; padding: 9px 11px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table td { padding: 10px 11px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.table tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--surface-2); }
.table .num { text-align: right; font-family: var(--mono); font-size: 12.5px; }
.table .w-in { width: 74px; padding: 5px 8px; font-size: 12.5px; text-align: right; font-family: var(--mono); }

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }

/* --------------------------------------------------------------- quiz --- */

.quiz-shell { max-width: 780px; margin: 0 auto; }
.quiz-progress { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.quiz-dots { display: flex; gap: 4px; flex-wrap: wrap; }
.quiz-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--surface-3); }
.quiz-dot.done { background: var(--text-3); }
.quiz-dot.right { background: var(--green); }
.quiz-dot.wrong { background: var(--red); }
.quiz-dot.current { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.q-card { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 24px; }
.q-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.q-text { font-size: 18px; font-weight: 600; line-height: 1.45; letter-spacing: -0.01em; margin-bottom: 20px; }
.q-opts { display: flex; flex-direction: column; gap: 9px; }
.q-opt {
  display: flex; align-items: flex-start; gap: 12px; padding: 13px 15px;
  border: 1.5px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
  cursor: pointer; text-align: left; font: inherit; color: var(--text); width: 100%;
  transition: border-color 0.12s, background 0.12s;
}
.q-opt:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
.q-opt:disabled { cursor: default; }
.q-key {
  width: 24px; height: 24px; border-radius: 7px; background: var(--surface-3);
  display: grid; place-items: center; font-size: 12px; font-weight: 700; flex: none; color: var(--text-2);
}
.q-opt.picked { border-color: var(--accent); background: var(--accent-soft); }
.q-opt.picked .q-key { background: var(--accent); color: #fff; }
.q-opt.right { border-color: var(--green); background: rgba(52, 211, 153, 0.12); }
.q-opt.right .q-key { background: var(--green); color: #06281c; }
.q-opt.wrong { border-color: var(--red); background: rgba(248, 113, 113, 0.1); }
.q-opt.wrong .q-key { background: var(--red); color: #2b0b0b; }
.q-explain {
  margin-top: 16px; padding: 13px 15px; border-radius: var(--radius-sm);
  background: var(--surface-2); border-left: 3px solid var(--accent); font-size: 13px; color: var(--text-2); line-height: 1.6;
}
.q-foot { display: flex; align-items: center; gap: 10px; margin-top: 20px; }

.result-hero { text-align: center; padding: 26px 0 8px; }
.result-score { font-size: 54px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }
.result-sub { color: var(--text-2); margin-top: 8px; font-size: 14px; }
.breakdown-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.breakdown-row:last-child { border-bottom: none; }

/* --------------------------------------------------------------- vault -- */

.vault-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 15px; display: flex; flex-direction: column; gap: 8px; cursor: pointer;
  border-left: 3px solid var(--vc, var(--accent));
}
.vault-card:hover { border-color: var(--text-3); border-left-color: var(--vc, var(--accent)); }
.vault-title { font-weight: 650; font-size: 14px; }
.vault-body { font-size: 12.8px; color: var(--text-2); line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.vault-foot { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

.flash-card {
  min-height: 300px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 34px; text-align: center; background: var(--surface);
  border: 1px solid var(--line); border-radius: 18px; cursor: pointer;
}
.flash-front { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; }
.flash-back { font-size: 15px; color: var(--text-2); line-height: 1.65; max-width: 600px; }
.flash-hint { font-size: 12px; color: var(--text-3); }
.flash-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 16px; }

/* -------------------------------------------------------------- timer --- */

.timer-face { font-family: var(--mono); font-size: 58px; font-weight: 700; letter-spacing: -0.03em; text-align: center; }

/* ------------------------------------------------------------- palette -- */

.palette-back { position: fixed; inset: 0; z-index: 250; background: rgba(6, 8, 14, 0.5); backdrop-filter: blur(2px); display: flex; justify-content: center; padding-top: 12vh; }
.palette { width: min(600px, 92%); background: var(--surface); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); overflow: hidden; height: fit-content; max-height: 68vh; display: flex; flex-direction: column; }
.palette-input { width: 100%; border: none; background: none; padding: 16px 18px; font: inherit; font-size: 15.5px; color: var(--text); outline: none; border-bottom: 1px solid var(--line); }
.palette-list { overflow-y: auto; padding: 6px; }
.palette-item { display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: var(--radius-sm); cursor: pointer; color: var(--text-2); }
.palette-item.on { background: var(--accent-soft); color: var(--accent-2); }
.palette-hint { margin-left: auto; font-size: 11px; color: var(--text-3); font-family: var(--mono); }

/* ------------------------------------------------------------- setup ---- */

.setup { max-width: 560px; margin: 8vh auto; }
.setup ol { padding-left: 18px; color: var(--text-2); font-size: 13.5px; line-height: 1.9; }
.setup code { background: var(--surface-2); padding: 1.5px 6px; border-radius: 5px; font-family: var(--mono); font-size: 12.5px; color: var(--accent-2); }

/* ------------------------------------------------------------ responsive */

/* Anything wide enough for a pointer keeps hover affordances. */
@media (hover: none) {
  .nav-item:hover, .btn:hover, .q-opt:hover:not(:disabled), .pick:hover { background: inherit; }
  .btn:active { transform: scale(0.97); }
  .q-opt:active { border-color: var(--accent); }
}

/* Never let a wide element blow out the page on a phone. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
img, canvas, svg { max-width: 100%; }

@media (max-width: 1100px) {
  .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- tablet and below: drawer nav ---- */
@media (max-width: 900px) {
  .sidebar {
    position: fixed; z-index: 120; height: 100%; width: 280px;
    padding-top: calc(16px + var(--safe-t));
    padding-bottom: calc(16px + var(--safe-b));
    transform: translateX(-100%);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
    box-shadow: var(--shadow);
  }
  .sidebar.open { transform: none; }
  .scrim {
    position: fixed; inset: 0; z-index: 119; background: rgba(0, 0, 0, 0.5);
    opacity: 0; pointer-events: none; transition: opacity 0.22s;
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  }
  .scrim.on { opacity: 1; pointer-events: auto; }
  .menu-btn { display: grid !important; }
  .g2, .form-grid.two { grid-template-columns: minmax(0, 1fr); }
  .nav-item { padding: 12px 12px; font-size: 15px; }
  .content { padding: 18px 16px calc(40px + var(--tabbar-h) + var(--safe-b)); }
}

/* ---- phone ---- */
@media (max-width: 640px) {
  :root { --tabbar-h: 62px; --header-h: 54px; }

  .g3, .g4 { grid-template-columns: minmax(0, 1fr); }
  .grid.g-auto { grid-template-columns: minmax(0, 1fr); }
  .content { padding: 14px 13px calc(28px + var(--tabbar-h) + var(--safe-b)); }

  .topbar { padding: 0 12px; padding-top: var(--safe-t); gap: 8px; }
  .topbar h1 { font-size: 16px; }
  .topbar-right { gap: 6px; }
  .topbar-right .btn span { display: none; }      /* icon-only Quick Add */
  .topbar-right .btn { padding: 9px 11px; }
  .streak-pill { display: none; }
  .topbar .input.select { min-width: 0; max-width: 104px; font-size: 12.5px; padding: 6px 8px; flex: none; }
  .topbar h1 { font-size: 15.5px; }
  .topbar-right { flex: none; }

  h1 { font-size: 19px; }
  .hero { flex-direction: column; align-items: flex-start; gap: 12px; }
  .hero .row { width: 100%; }
  .hero .btn { flex: 1; }

  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-value { font-size: 20px; }
  .card { padding: 14px; }
  .card.pad-lg { padding: 16px; }

  /* iOS zooms the page when a focused input is under 16px */
  .input, input, textarea, select { font-size: 16px; }

  /* comfortable thumb targets */
  .btn { padding: 11px 14px; min-height: 42px; }
  .btn.sm { padding: 8px 11px; min-height: 36px; }
  .icon-btn { width: 40px; height: 40px; }
  .pick { padding: 10px 13px; min-height: 40px; }
  .q-opt { padding: 14px; }
  .switch-track { width: 42px; height: 24px; }
  .switch-track::after { width: 18px; height: 18px; }
  .switch input:checked + .switch-track::after { transform: translateX(18px); }

  .cal-cell { min-height: 58px; }
  .cal-grid { font-size: 11px; }
  .table { font-size: 12.5px; }
  .modal-box { max-height: 88dvh; }
  .sheet-cols { column-count: 1; }
  .result-score { font-size: 44px; }
}

@media (max-width: 400px) {
  .stat-row { grid-template-columns: minmax(0, 1fr); }
  .topbar .input.select { max-width: 88px; }
  .topbar-right .icon-btn.solid:first-of-type { display: none; }   /* search: use the More menu */
}

/* ---- bottom tab bar (phone only) ---- */
.tabbar { display: none; }

@media (max-width: 640px) {
  .tabbar {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 118;
    height: calc(var(--tabbar-h) + var(--safe-b));
    padding-bottom: var(--safe-b);
    background: var(--bg-2);
    border-top: 1px solid var(--line);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
  }
  .tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; border: none; background: none; color: var(--text-3);
    font: inherit; font-size: 10.5px; font-weight: 600; cursor: pointer;
    padding: 0; position: relative; min-width: 0;
  }
  .tab.active { color: var(--accent-2); }
  .tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tab-dot {
    position: absolute; top: 6px; right: calc(50% - 18px);
    min-width: 15px; height: 15px; padding: 0 4px; border-radius: 99px;
    background: var(--red); color: #fff; font-size: 9.5px; font-weight: 700;
    display: grid; place-items: center;
  }
}

/* Landscape phone: the bar eats too much height, so hide it. */
@media (max-height: 460px) and (orientation: landscape) {
  :root { --tabbar-h: 0px; }
  .tabbar { display: none; }
}

.menu-btn { display: none; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 99px; border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--text-3); }

/* ------------------------------------------------------- formula sheet -- */

.sheet {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px 22px; margin-bottom: 20px;
}
.sheet-head { border-bottom: 2px solid var(--line); padding-bottom: 10px; margin-bottom: 14px; }
.sheet-cols { column-count: 2; column-gap: 26px; }
@media (max-width: 780px) { .sheet-cols { column-count: 1; } }
.sheet-block { break-inside: avoid-column; margin-bottom: 14px; }
.sheet-unit {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent-2); border-bottom: 1px solid var(--line-soft); padding-bottom: 3px; margin-bottom: 7px;
}
.sheet-item { break-inside: avoid; margin-bottom: 9px; }
.sheet-name { font-size: 12.5px; font-weight: 650; line-height: 1.3; }
.sheet-formula {
  font-family: var(--mono); font-size: 12px; line-height: 1.5; white-space: pre-wrap;
  color: var(--text); background: var(--surface-2); border-radius: 6px; padding: 5px 8px; margin-top: 3px;
}
.sheet-note { font-size: 11px; color: var(--text-2); line-height: 1.45; margin-top: 3px; }

/* --------------------------------------------------------- theme editor -- */

.swatch-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.swatch-row:last-child { border-bottom: none; }
.swatch {
  width: 34px; height: 26px; border-radius: 7px; border: 1px solid var(--line);
  padding: 0; cursor: pointer; background: none; flex: none; overflow: hidden;
}
.swatch::-webkit-color-swatch-wrapper { padding: 2px; }
.swatch::-webkit-color-swatch { border: none; border-radius: 5px; }
.swatch::-moz-color-swatch { border: none; border-radius: 5px; }
.preset-card {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
  font: inherit; color: var(--text); text-align: left; width: 100%;
}
.preset-card:hover { border-color: var(--accent); }
.preset-card.on { border-color: var(--accent); background: var(--accent-soft); }
.preset-dots { display: flex; gap: 4px; flex: none; }
.preset-dot { width: 14px; height: 14px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.18); }

/* -------------------------------------------------------------- brand --- */

/* Loading: the mark holds still and a ring travels around it. A spinning
   asymmetric logo reads as broken rather than busy. The ring uses --accent so
   it still follows whatever colours are set in Settings. */
.brand-loader {
  position: relative;
  width: 56px;
  height: 56px;
  flex: none;
}
.brand-loader::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-top-color: var(--accent);
  animation: brand-spin 0.9s linear infinite;
}
.brand-loader-mark {
  position: absolute;
  inset: 9px;
  border-radius: 9px;
  background: var(--brand-tile) url('/icons/logo-mark.png') center / 76% no-repeat;
}

@keyframes brand-spin { to { transform: rotate(360deg); } }

/* someone who asked for less motion should get none of it */
@media (prefers-reduced-motion: reduce) {
  .brand-loader::before { animation: none; border-top-color: var(--accent); }
  .brand-loader-mark { animation: none; }
  #boot-splash .brand-loader-mark { animation: none; }
}

/* First paint, before any JavaScript has run. Sits in index.html so there is
   never a blank white flash between opening the app and the shell appearing. */
#boot-splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  gap: 16px;
  align-content: center;
  background: var(--bg);
  transition: opacity 0.28s ease;
}
#boot-splash.gone { opacity: 0; pointer-events: none; }
#boot-splash .boot-name {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* ------------------------------------------------------ lecture notes -- */

.lecture-layout {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  margin-top: 16px;
}

.lecture-list { display: flex; flex-direction: column; gap: 2px; max-height: 62dvh; overflow: auto; }
.lecture-month {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-3); padding: 12px 2px 5px;
}

.lecture-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 9px; border: none; border-radius: var(--radius-sm);
  background: none; font: inherit; text-align: left; cursor: pointer;
  border-left: 3px solid var(--ec);
}
.lecture-row:hover { background: var(--surface-2); }
.lecture-row.active { background: color-mix(in srgb, var(--ec) 16%, var(--surface)); }
/* a holiday is on the schedule but is not work - it must not look clickable-important */
.lecture-row.skip { opacity: 0.5; }

.lecture-day {
  flex: none; width: 48px; font-family: var(--mono); font-size: 11px;
  font-weight: 600; color: var(--text-3);
}
.lecture-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.lecture-row-title {
  font-size: 12.5px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lecture-flags { flex: none; display: flex; align-items: center; gap: 5px; }
.lecture-flag { display: grid; place-items: center; color: var(--accent-2); opacity: 0.85; }

.lecture-title { font-size: 18px; letter-spacing: -0.01em; }
.lecture-empty {
  align-items: center; text-align: center; color: var(--text-3);
  min-height: 240px; justify-content: center;
}

/* Notes want to feel like a page, not a form field. */
.notes-area {
  min-height: 300px;
  font-size: 14.5px;
  line-height: 1.7;
  resize: vertical;
  font-family: var(--font);
}

.dropzone.sm { padding: 18px 14px; gap: 4px; }
.dropzone.sm .strong { font-size: 13.5px; }

@media (max-width: 900px) {
  .lecture-layout { grid-template-columns: minmax(0, 1fr); }
  .lecture-list { max-height: 40dvh; }
}
@media (max-width: 640px) {
  .notes-area { min-height: 240px; font-size: 16px; }
  .lecture-day { width: 44px; }
}

/* --------------------------------------------------------- stale banner -- */

/* Deliberately loud. Editing what you believe is live data but is actually a
   stale cache is the one failure here that could cost real work. */
.stale-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 16px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text);
  background: color-mix(in srgb, var(--amber) 22%, var(--surface));
  border-bottom: 1px solid color-mix(in srgb, var(--amber) 50%, transparent);
}
.stale-bar span { flex: 1; min-width: 0; }

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .stale-bar { background: var(--surface-2); border-bottom-color: var(--line); }
}

@media (max-width: 640px) {
  .stale-bar { flex-direction: column; align-items: flex-start; gap: 7px; font-size: 12px; }
}

/* ------------------------------------------------- handwriting & voice -- */

.sketch-canvas {
  display: block;
  width: 100%;
  height: 340px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--line);
  /* the pen must draw rather than pan; a finger is filtered out in JS so the
     page can still be scrolled while a diagram is half finished */
  touch-action: pan-y;
  cursor: crosshair;
  -webkit-user-select: none;
  user-select: none;
}

.sketch-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }

.ink {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  border: 2px solid var(--line);
  background: var(--ink);
  cursor: pointer;
  padding: 0;
}
.ink:hover { border-color: var(--text-3); }

.tx-area {
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.65;
  min-height: 150px;
  resize: vertical;
}

@media (max-width: 640px) {
  .sketch-canvas { height: 260px; }
  .tx-area { font-size: 13px; }
}

/* ------------------------------------------------------------ dropzone -- */

.dropzone {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 30px 18px;
  border: 1.5px dashed var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-2);
  cursor: pointer;
  text-align: center;
}
.dropzone:hover, .dropzone.over { border-color: var(--accent); background: var(--accent-soft); }
.dropzone .strong { color: var(--text); font-size: 15px; }

.preview {
  max-height: 190px;
  overflow: auto;
  margin: 0;
  padding: 11px 13px;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
}

details.paste summary { cursor: pointer; padding: 4px 0; }

@media (max-width: 640px) {
  .dropzone { padding: 26px 14px; }
  .preview { max-height: 150px; font-size: 12.5px; }
}

/* ------------------------------------------------------------- callout -- */

.callout {
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 13.5px;
  line-height: 1.6;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-2);
}
.callout strong { color: var(--text); }
.callout.warn {
  border-color: color-mix(in srgb, var(--amber) 45%, transparent);
  background: color-mix(in srgb, var(--amber) 12%, var(--surface-2));
}
/* older Safari has no color-mix; the plain .callout look is a fine fallback */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .callout.warn { border-color: var(--line); background: var(--surface-2); }
}

/* --------------------------------------------------------- pairing code -- */

.code-input {
  font-family: var(--mono);
  font-size: 26px;
  letter-spacing: 10px;
  text-align: center;
  padding: 14px 12px;
}
/* the letter-spacing pushes the text off-centre, so pull it back */
.code-input { text-indent: 10px; }

/* ------------------------------------------------------- focus arcade -- */

.arcade-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  margin-top: 16px;
}

.arcade-stage {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.arcade-bar { display: flex; align-items: center; gap: 10px; }
.arcade-score { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; font-family: var(--mono); }

.arcade-canvas-wrap { position: relative; }
.arcade-canvas {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  max-height: 62dvh;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  touch-action: none;                 /* the game owns the gestures */
  cursor: crosshair;
  -webkit-user-select: none; user-select: none;
}

.arcade-over {
  position: absolute; inset: 0; display: none;
  place-items: center; text-align: center;
  background: rgba(10, 13, 20, 0.78);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  border-radius: var(--radius-sm);
}
.arcade-over.on { display: grid; }
.arcade-over-inner { display: flex; flex-direction: column; align-items: center; gap: 7px; }

.arcade-player { align-self: start; }
.arcade-text {
  min-height: 92px;
  padding: 13px 15px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--text);
}

/* on-screen controls, only worth showing where there is no keyboard */
.dpad { display: none; }
@media (hover: none) and (pointer: coarse) {
  .dpad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas: '. up .' 'left mid right' '. down .';
    gap: 7px;
    max-width: 232px;
    margin: 2px auto 0;
  }
  .dpad-btn {
    height: 52px; border-radius: 13px;
    border: 1px solid var(--line); background: var(--surface-2);
    color: var(--text-2); font-size: 17px; line-height: 1;
    display: grid; place-items: center;
    -webkit-user-select: none; user-select: none; touch-action: manipulation;
  }
  .dpad-btn.hit { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-2); }
  .dpad-btn.up { grid-area: up; }
  .dpad-btn.left { grid-area: left; }
  .dpad-btn.mid { grid-area: mid; }
  .dpad-btn.right { grid-area: right; }
  .dpad-btn.down { grid-area: down; }
}

@media (max-width: 900px) {
  .arcade-grid { grid-template-columns: minmax(0, 1fr); }
  .arcade-canvas { aspect-ratio: 1 / 1; max-height: 46dvh; }
}
@media (max-width: 640px) {
  .arcade-canvas { max-height: 42dvh; }
  .arcade-text { font-size: 16.5px; min-height: 76px; }
  .arcade-player .form-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* landscape on a phone: put the game beside the notes and shrink the chrome */
@media (max-height: 460px) and (orientation: landscape) {
  .arcade-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .arcade-canvas { aspect-ratio: auto; height: 60dvh; max-height: none; }
  .arcade-text { min-height: 0; }
  .dpad { max-width: 168px; }
  .dpad-btn { height: 40px; }
}

@media print {
  .sidebar, .topbar, .btn, .seg, .no-print, .nav, .toast-host { display: none !important; }
  body, .content { overflow: visible; height: auto; background: #fff; color: #000; }
  .content, .view { padding: 0 !important; margin: 0 !important; }
  .hero { margin-bottom: 10px !important; }

  .sheet { border: none; padding: 0; background: #fff; color: #000; }
  .sheet-unit { color: #000; border-bottom: 1px solid #999; }
  .sheet-formula { background: #f2f2f2; color: #000; }
  .sheet-note { color: #333; }
  .sheet-cols { column-count: 2; }
  .card { border-color: #ccc !important; background: #fff !important; box-shadow: none !important; }
  @page { margin: 12mm; }
}

/* ---- syllabus prep on a lecture ---- */
.prep-box {
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  padding: 10px 12px;
  background: var(--surface-2, rgba(127, 127, 127, .05));
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.prep-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.prep-head svg { flex: none; }
.prep-line {
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* ---- slide reader ---- */
.deck-shell {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.deck-controls {
  align-items: center;
  gap: 8px;
}
.slide-jump {
  width: 64px;
  text-align: center;
  padding: 4px 6px;
}
.deck-stage {
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2, rgba(127, 127, 127, .05));
  /* Tall enough that a slide is legible without scrolling the page, capped so
     the note box stays on screen next to it on a laptop. */
  min-height: 420px;
}
.deck-frame {
  display: block;
  width: 100%;
  height: 62vh;
  min-height: 420px;
  border: 0;
}
.deck-card {
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.deck-card-text > div {
  font-size: 14px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
.deck-card-text > div:first-child {
  font-weight: 600;
  font-size: 15px;
}
.deck-images {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.deck-img {
  max-width: 240px;
  max-height: 180px;
  border-radius: 8px;
  border: 1px solid var(--line-soft);
  object-fit: contain;
  background: var(--surface, #fff);
}
.deck-noteblock {
  border-top: 1px solid var(--line-soft);
  padding-top: 12px;
}
.deck-note {
  width: 100%;
  font: inherit;
}
.deck-marks {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
}
.slide-chip {
  border: 1px solid var(--line);
  background: var(--surface, #fff);
  color: var(--text);
  border-radius: 999px;
  min-width: 24px;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}
.slide-chip:hover { border-color: var(--accent); }
.slide-chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* On a phone the iframe cannot be both tall and leave room for the note, so
   the slide gets the screen and the note sits under it. */
@media (max-width: 720px) {
  .deck-frame { height: 52vh; min-height: 300px; }
  .deck-stage { min-height: 300px; }
  .deck-img { max-width: 45vw; }
}

/* ---- My Notes ---- */
.notes-search {
  width: 100%;
  font-size: 15px;
  padding: 10px 12px;
}
.notes-kinds {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.notes-class {
  border-left: 3px solid var(--ec, var(--line));
}
.notes-unit {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--line-soft);
}
.notes-unit-name {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--muted);
  flex: 1;
}
.note-row {
  display: block;
  width: 100%;
  text-align: left;
  border: 1px solid var(--line-soft);
  border-radius: 9px;
  background: var(--surface, #fff);
  color: var(--text);
  padding: 9px 11px;
  margin-top: 6px;
  cursor: pointer;
  font: inherit;
}
.note-row:hover { border-color: var(--accent); }
.note-kind {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--accent);
}
.note-title {
  font-weight: 600;
  font-size: 13px;
  margin-top: 2px;
}
.note-body {
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  margin-top: 3px;
  overflow-wrap: anywhere;
}
.note-body.dim { font-style: italic; }

/* ------------------------------------------------------------ the tutor -- */
/*
 * One rule runs through this: an answer must read as prose, and its sources
 * must read as furniture. So passages get comfortable line-height and real
 * paragraph width, and citations get 11px and the dim colour. The moment the
 * citations compete with the answer, the page stops being a tutor and starts
 * being a search results list.
 */

.ask-row { gap: var(--sp-2); align-items: stretch; }
/* minmax(0) so a long placeholder cannot set the row's minimum width and
   push the Ask button off a phone screen. */
.ask-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
.ask-input { font-size: 15px; }
.ask-filters { gap: var(--sp-1); margin-top: var(--sp-1); }
.ask-starters { margin-top: var(--sp-2); }

.chip.tap {
  border: 1px solid var(--line); background: var(--surface-2); cursor: pointer;
  padding: 4px 10px; color: var(--text-2);
}
.chip.tap:hover { border-color: var(--accent); color: var(--text); }
.chip.tap.on { background: var(--accent-soft); border-color: var(--accent); color: var(--text); }

.ask-topic {
  padding: var(--sp-3) var(--sp-4); border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line-soft); gap: var(--sp-3);
}

.ask-section .ask-passage + .ask-passage {
  margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line-soft);
}
.ask-passage p { margin: 0 0 var(--sp-2); line-height: 1.65; max-width: 72ch; white-space: pre-wrap; }
.ask-cite { gap: var(--sp-2); align-items: center; }

.ask-formula + .ask-formula { margin-top: var(--sp-3); }
.ask-formula { display: flex; flex-direction: column; gap: 4px; }

.linklike {
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--accent-2);
  display: inline-flex; align-items: center; gap: 3px; font-weight: 600;
}
.linklike:hover { text-decoration: underline; }

.ask-moves { gap: var(--sp-2); }
.ask-panel { border-left: 3px solid var(--accent); }

.ask-question + .ask-question {
  margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line-soft);
}
.ask-options { gap: var(--sp-1); margin: var(--sp-2) 0; }
.ask-option {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text);
  font-size: 13px; line-height: 1.5;
}
.ask-option:hover { border-color: var(--accent); }
.ask-option.right { border-color: var(--green); background: rgba(52, 211, 153, 0.1); }
.ask-option.wrong { border-color: var(--red); background: rgba(248, 113, 113, 0.1); }

.ask-hints { gap: var(--sp-2); margin: var(--sp-2) 0; }
.ask-hint {
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  background: var(--surface-2); border-left: 3px solid var(--amber);
}
.ask-answer {
  margin-top: var(--sp-2); padding: var(--sp-3);
  border-radius: var(--radius-sm); background: var(--surface-2);
  border-left: 3px solid var(--green);
}
.ask-answer p { margin: var(--sp-1) 0 0; line-height: 1.6; }

.ask-sources { gap: var(--sp-2); }
.ask-source {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  border: 1px solid var(--line-soft); background: var(--surface-2);
}
.ask-source:hover { border-color: var(--accent); }
.ask-source p { margin: 4px 0 0; }

.ask-gap-unit { gap: var(--sp-3); padding: var(--sp-2) 0; }
.ask-gap-unit + .ask-gap-unit { border-top: 1px solid var(--line-soft); }

@media (max-width: 640px) {
  .ask-row { grid-template-columns: minmax(0, 1fr); }
  .ask-topic { flex-direction: column; align-items: flex-start; }
}

/* ------------------------------------------------------ what if? labs -- */
/*
 * The chart is the loudest thing on the page and everything else gets out of
 * its way. Readouts are monospaced and tabular so a number does not jitter
 * sideways while a slider is being dragged - that jitter is what makes a
 * simulation feel cheap.
 */

.lab-grid {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
}

.lab-card {
  display: flex; flex-direction: column; gap: var(--sp-2);
  text-align: left; cursor: pointer; min-width: 0;
  padding: var(--sp-4); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--text); transition: border-color 0.15s, transform 0.15s;
}
.lab-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.lab-card p { margin: 0; }
.lab-card-title { font-size: 16px; font-weight: 700; line-height: 1.3; }
.lab-card-foot { justify-content: space-between; align-items: center; gap: var(--sp-2); margin-top: auto; }
.lab-go { display: inline-flex; align-items: center; gap: 4px; color: var(--accent-2); font-size: 12px; font-weight: 600; }

.lab-calibration {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-3); align-items: center;
}
.lab-cal-num {
  font-size: 30px; font-weight: 800; color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}

.lab-view { max-width: 1000px; }
.lab-head { gap: var(--sp-3); align-items: flex-start; }
.lab-title { font-size: 22px; margin: 0 0 2px; line-height: 1.2; }

.lab-steps { gap: var(--sp-4); margin: calc(var(--sp-2) * -1) 0 0; }
.lab-step { display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); }
.lab-step-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--surface-3); border: 1px solid var(--line);
}
.lab-step.on { color: var(--text); }
.lab-step.on .lab-step-dot { background: var(--accent); border-color: var(--accent); }
.lab-step.done { color: var(--text-2); }
.lab-step.done .lab-step-dot { background: var(--green); border-color: var(--green); }

.lab-prompt {
  border-left: 3px solid var(--accent); padding: var(--sp-2) 0 var(--sp-2) var(--sp-3);
}
.lab-prompt-text { margin: 4px 0 0; font-size: 16px; line-height: 1.55; max-width: 62ch; }

.lab-now {
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.lab-now-val { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }

.lab-dirs { gap: var(--sp-2); }
.lab-dir {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: var(--sp-2) var(--sp-4); border-radius: 99px;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-2); font-size: 13px; font-weight: 600;
}
.lab-dir:hover { border-color: var(--accent); color: var(--text); }
.lab-dir.on { background: var(--accent-soft); border-color: var(--accent); color: var(--text); }
/* The arrows carry the meaning; the icon set has one trend glyph, so rotate it. */
.lab-dir.down svg { transform: scaleY(-1); }
.lab-dir.same svg { opacity: 0.6; }

.lab-guess { gap: var(--sp-1); }
.lab-guess-val {
  font-size: 18px; font-weight: 700; color: var(--amber);
  font-variant-numeric: tabular-nums;
}

.lab-slider {
  -webkit-appearance: none; appearance: none; width: 100%; height: 22px;
  background: transparent; cursor: pointer;
}
.lab-slider::-webkit-slider-runnable-track {
  height: 5px; border-radius: 99px; background: var(--surface-3);
}
.lab-slider::-moz-range-track { height: 5px; border-radius: 99px; background: var(--surface-3); }
.lab-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: -7px;
  width: 19px; height: 19px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--surface);
  box-shadow: var(--shadow-sm);
}
.lab-slider::-moz-range-thumb {
  width: 19px; height: 19px; border-radius: 50%; border: 2px solid var(--surface);
  background: var(--accent); box-shadow: var(--shadow-sm);
}
.lab-slider:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--accent-2); outline-offset: 2px; }

.lab-chart-hidden {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2); padding: var(--sp-6) var(--sp-4); text-align: center;
  border: 1px dashed var(--line); border-radius: var(--radius);
  color: var(--text-3); background: var(--surface-2);
}
.lab-chart-hidden p { margin: 0; }

.lab-chart { margin: var(--sp-2) 0; }
.plot { width: 100%; height: auto; display: block; overflow: visible; }
.plot-grid { stroke: var(--line-soft); stroke-width: 1; }
.plot-axis { stroke: var(--line); stroke-width: 1.5; }
.plot-zero { stroke: var(--text-3); stroke-width: 1.5; stroke-dasharray: 4 4; }
.plot-tick { fill: var(--text-3); font-size: 11px; font-family: 'JetBrains Mono', ui-monospace, monospace; }
.plot-axis-label { fill: var(--text-2); font-size: 12px; font-weight: 600; }
.plot-marker-label { font-size: 11px; font-weight: 700; }
.plot-band-label { fill: var(--text-2); font-size: 11px; font-weight: 600; }

.plot-legend { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-1); }
.plot-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); }
.plot-swatch { width: 14px; height: 3px; border-radius: 99px; display: inline-block; }
.plot-swatch.dashed { background-image: linear-gradient(90deg, currentColor 50%, transparent 50%); background-size: 5px 3px; }

.lab-verdict {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--radius);
  background: var(--surface-2); border-left: 3px solid var(--line);
}
.lab-verdict.right { border-left-color: var(--green); }
.lab-verdict.wrong { border-left-color: var(--amber); }
.lab-verdict.right svg { color: var(--green); }
.lab-verdict.wrong svg { color: var(--amber); }

.lab-outputs {
  display: grid; gap: var(--sp-2);
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
}
.lab-output {
  min-width: 0; padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm); background: var(--surface-2);
  border: 1px solid var(--line-soft);
}
.lab-output.lead { border-color: var(--accent); background: var(--accent-soft); }
.lab-output-val {
  font-size: 18px; font-weight: 700; margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.lab-output-val.neg { color: var(--red); }
.lab-hint { margin-top: 3px; line-height: 1.4; }

.lab-dials {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.lab-dial { min-width: 0; }
.lab-dial-val { font-weight: 700; font-variant-numeric: tabular-nums; }

.lab-short { font-size: 15px; font-weight: 600; margin: 0; line-height: 1.5; max-width: 66ch; }
.lab-view p.small { max-width: 72ch; line-height: 1.65; }
.lab-formula {
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  font-size: 13px; overflow-x: auto;
}
.lab-course + .lab-course { margin-top: var(--sp-3); }

@media (max-width: 640px) {
  .lab-calibration { grid-template-columns: minmax(0, 1fr); }
  .lab-head { flex-direction: column; align-items: flex-start; }
  .lab-steps { gap: var(--sp-3); }
  .lab-dirs .lab-dir { flex: 1 1 auto; justify-content: center; }
  /* The chart stops being readable much below this, so let it scroll rather
     than shrink the axis labels into illegibility. */
  .lab-chart { overflow-x: auto; }
  .lab-chart .plot { min-width: 460px; }
}

.lab-chip { gap: 4px; padding: 2px 8px; }
.lab-chip svg { opacity: 0.85; }

/* Your own notes inside a study session. Set apart from the teaching content
   with a warm accent, because the one thing that must be obvious at a glance
   is which words are yours and which are the unit's. */
.study-yours {
  border-left: 3px solid var(--amber);
  padding-left: var(--sp-3);
}
.study-yours-note + .study-yours-note {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line-soft);
}
.study-yours-note p { margin: 0 0 4px; line-height: 1.6; white-space: pre-wrap; max-width: 72ch; }

.quiz-behind { gap: var(--sp-3); padding: var(--sp-2) 0; }
.quiz-behind + .quiz-behind { border-top: 1px solid var(--line-soft); }

/* The unit picker on a lecture. Toggles rather than a dropdown, because one
   class can teach four chapters and a <select> would force three away. */
.unit-picker .callout { margin: var(--sp-1) 0; }
.unit-choices {
  display: grid; gap: var(--sp-1); margin: var(--sp-2) 0;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
}
.unit-choice {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  text-align: left; cursor: pointer; min-width: 0;
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-2); font-size: 13px;
}
.unit-choice:hover { border-color: var(--accent); color: var(--text); }
.unit-choice.on {
  background: var(--accent-soft); border-color: var(--accent); color: var(--text); font-weight: 600;
}
.unit-choice.guess { border-style: dashed; }
.unit-choice-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------- look-up on highlight - */
/* Select any text in the reading area and a small button offers a lookup.
   Fixed-position because it is anchored to the selection rectangle, which is
   in viewport coordinates. */
.lookup-pill {
  position: fixed; z-index: 70;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border-radius: 999px;
  background: var(--accent); color: #fff; border: none;
  font-size: 12px; font-weight: 600; cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}
.lookup-pill:hover { filter: brightness(1.08); }

.lookup-panel {
  position: fixed; inset: 0; z-index: 71;
  background: rgba(0, 0, 0, 0.45);
  display: flex; justify-content: flex-end;
}
.lookup-panel-inner {
  width: min(460px, 100%);
  height: 100%; overflow: auto;
  padding: 18px;
  background: var(--bg-1);
  border-left: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 12px;
}
@media (max-width: 720px) {
  .lookup-panel { align-items: flex-end; }
  .lookup-panel-inner {
    width: 100%; height: 82dvh;
    border-left: none; border-top: 1px solid var(--line);
    border-radius: 14px 14px 0 0;
  }
}

.lookup-def { border-left: 3px solid var(--accent); }

.lookup-hit {
  display: block; width: 100%; text-align: left;
  padding: 10px 12px; border-radius: 10px;
  background: var(--bg-2); border: 1px solid var(--line-soft);
  cursor: pointer; color: inherit;
}
.lookup-hit:hover { border-color: var(--accent); }
.lookup-hit p { margin: 4px 0 2px; }

/* ---------------------------------------------------- streaks and celebration - */
/* The confetti layer. Fixed, on top of everything, and NEVER clickable - the
   next answer button sits underneath it. */
.celebrate-canvas {
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
}

/* The streak badge. Each tier is louder than the last: that escalation is the
   whole mechanism, so the steps have to be obvious side by side. */
.streak-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: 999px;
  font-weight: 800; letter-spacing: 0.04em;
  border: 1.5px solid transparent;
  white-space: nowrap;
}
.streak-badge .streak-n { font-size: 16px; line-height: 1; }
.streak-badge .streak-label { font-size: 9.5px; text-transform: uppercase; opacity: 0.92; }

.streak-badge.tier-nod {
  background: color-mix(in srgb, var(--green) 16%, transparent);
  color: var(--green); border-color: color-mix(in srgb, var(--green) 40%, transparent);
}
.streak-badge.tier-building {
  background: color-mix(in srgb, var(--green) 26%, transparent);
  color: var(--green); border-color: var(--green);
}
.streak-badge.tier-fire {
  background: linear-gradient(135deg, #ff8a3d, #ffd166);
  color: #23160a; border-color: #ff8a3d;
  box-shadow: 0 0 18px rgba(255, 138, 61, 0.45);
}
.streak-badge.tier-unreal {
  background: linear-gradient(135deg, #ffb300, #ffd700, #fff3b0);
  color: #2a1e00; border-color: #ffd700;
  box-shadow: 0 0 26px rgba(255, 215, 0, 0.6);
}
.streak-badge.tier-jackpot {
  background: linear-gradient(120deg, #ffd700, #ff6b6b, #c084fc, #60a5fa, #4ade80, #ffd700);
  background-size: 300% 300%;
  color: #17110a; border-color: #fff3b0;
  box-shadow: 0 0 34px rgba(255, 215, 0, 0.75), 0 0 60px rgba(192, 132, 252, 0.4);
}

/* Motion only when the device has not asked us to stop. The badge itself still
   appears either way - the number is the information, the movement is decoration. */
.streak-badge.animate { animation: streak-pop 420ms cubic-bezier(.2,1.6,.4,1); }
.streak-badge.tier-unreal.animate,
.streak-badge.tier-jackpot.animate { animation: streak-pop 420ms cubic-bezier(.2,1.6,.4,1), streak-shimmer 2.4s linear infinite; }

@keyframes streak-pop {
  0%   { transform: scale(0.6); opacity: 0; }
  60%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes streak-shimmer {
  0%   { background-position: 0% 50%; }
  100% { background-position: 300% 50%; }
}

/* The question card flashes in the tier's colour, so the reward lands where his
   eyes already are rather than only in the corner. */
.celebrate-flash {
  animation: card-flash 650ms ease-out;
}
@keyframes card-flash {
  0%   { box-shadow: 0 0 0 0 var(--flash-color); }
  35%  { box-shadow: 0 0 34px 6px var(--flash-color); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* A correct answer should feel like one, not merely be recorded as one. */
.q-opt.right {
  animation: opt-right 420ms cubic-bezier(.2,1.6,.4,1);
}
@keyframes opt-right {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.025); }
  100% { transform: scale(1); }
}

.result-streak {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 10px; padding: 8px 16px; border-radius: 999px;
  font-weight: 800;
  background: linear-gradient(135deg, #ffb300, #ffd700);
  color: #2a1e00;
}

@media (prefers-reduced-motion: reduce) {
  .streak-badge.animate,
  .streak-badge.tier-unreal.animate,
  .streak-badge.tier-jackpot.animate,
  .celebrate-flash,
  .q-opt.right { animation: none; }
}

/* ---- a phrase carried here from a highlight lookup ------------------------
   Marked and scrolled to by findmark.js. It has to read as "this is the thing
   you clicked" without looking like the app's own emphasis, so it borrows the
   accent rather than the usual browser yellow, which is unreadable on dark. */
mark.find-hit {
  background: var(--accent-soft);
  color: inherit;
  border-bottom: 2px solid var(--accent-2);
  border-radius: 3px;
  padding: 0 2px;
  animation: find-hit-pulse 1.6s ease-out 1;
}

@keyframes find-hit-pulse {
  0%   { background: var(--accent-2); color: #fff; }
  60%  { background: var(--accent-soft); color: inherit; }
  100% { background: var(--accent-soft); color: inherit; }
}

@media (prefers-reduced-motion: reduce) {
  mark.find-hit { animation: none; }
}

/* ---- slide text, drawn as a slide ----------------------------------------
   The deck already knows its own hierarchy; this is what showing it looks
   like. Sizes step down with depth so four levels stay legible without
   indenting off the right edge of a phone. */
.slide-card {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--surface-2, var(--surface));
  padding: 16px 18px;
  margin-bottom: 12px;
}
.slide-card.dense { border: 0; padding: 0; background: none; margin-bottom: 0; }

.slide-card-head {
  display: flex; flex-direction: column; gap: 4px;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.slide-card.dense .slide-card-head { padding-bottom: 6px; margin-bottom: 8px; }
.slide-card-no {
  font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3); font-weight: 600;
}
.slide-card-title {
  font-size: 17px; font-weight: 650; line-height: 1.25; color: var(--text-1);
}
.slide-card.dense .slide-card-title { font-size: 15px; }

.slide-card-body { display: flex; flex-direction: column; gap: 7px; }
.slide-card-point { display: flex; gap: 9px; align-items: baseline; }
.slide-card-glyph { color: var(--accent-2); flex: 0 0 auto; font-size: 9px; line-height: 1.7; }
.slide-card-text { flex: 1 1 auto; line-height: 1.5; }

.slide-card-point[data-level="0"] { margin-left: 0;    font-size: 14px; }
.slide-card-point[data-level="1"] { margin-left: 18px; font-size: 13.5px; }
.slide-card-point[data-level="2"] { margin-left: 36px; font-size: 13px; color: var(--text-2); }
.slide-card-point[data-level="3"] { margin-left: 52px; font-size: 12.5px; color: var(--text-2); }
.slide-card-point[data-level="4"] { margin-left: 66px; font-size: 12.5px; color: var(--text-3); }
.slide-card-point[data-level="1"] .slide-card-glyph { font-size: 8px; }
.slide-card-point[data-level="2"] .slide-card-glyph,
.slide-card-point[data-level="3"] .slide-card-glyph,
.slide-card-point[data-level="4"] .slide-card-glyph { color: var(--text-3); }

.slide-card-prose { margin: 2px 0; line-height: 1.55; font-size: 13.5px; }

.slide-card-notes {
  margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--line-soft);
  font-size: 12.5px; color: var(--text-2); line-height: 1.5;
}
.slide-card-notes-label {
  display: block; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3); font-weight: 600; margin-bottom: 3px;
}
.slide-card-hint { margin-top: 10px; }

@media (max-width: 560px) {
  .slide-card { padding: 13px 14px; }
  .slide-card-point[data-level="2"] { margin-left: 26px; }
  .slide-card-point[data-level="3"] { margin-left: 36px; }
  .slide-card-point[data-level="4"] { margin-left: 44px; }
}

/* ---- highlighting -------------------------------------------------------
   Four colours that have to stay legible on a dark surface AND on the light
   theme, so each is a translucent wash over the text rather than a solid fill
   with its own foreground colour to fight. */
mark.hl {
  color: inherit;
  border-radius: 3px;
  padding: 0 2px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
mark.hl-yellow { background: rgba(250, 204, 21, 0.30); box-shadow: inset 0 -2px 0 rgba(250, 204, 21, 0.75); }
mark.hl-green  { background: rgba( 52, 211, 153, 0.28); box-shadow: inset 0 -2px 0 rgba( 52, 211, 153, 0.75); }
mark.hl-blue   { background: rgba( 96, 165, 250, 0.28); box-shadow: inset 0 -2px 0 rgba( 96, 165, 250, 0.75); }
mark.hl-pink   { background: rgba(244, 114, 182, 0.28); box-shadow: inset 0 -2px 0 rgba(244, 114, 182, 0.75); }

.hl-bar {
  position: fixed; z-index: 9000;
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
}
.hl-swatch {
  width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .25); cursor: pointer; padding: 0;
}
.hl-swatch:hover { transform: scale(1.12); }
.hl-swatch.hl-yellow { background: #facc15; }
.hl-swatch.hl-green  { background: #34d399; }
.hl-swatch.hl-blue   { background: #60a5fa; }
.hl-swatch.hl-pink   { background: #f472b6; }
.hl-ask {
  border: 0; background: none; cursor: pointer;
  color: var(--text-2); font-size: 12px; padding: 2px 6px 2px 8px;
  border-left: 1px solid var(--line-soft);
}
.hl-ask:hover { color: var(--text-1); }

/* a highlight shown in the review list, with its colour as the spine */
.hl-row { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.hl-row:last-child { border-bottom: 0; }
.hl-spine { width: 4px; align-self: stretch; border-radius: 2px; flex: 0 0 auto; }
.hl-spine.hl-yellow { background: #facc15; }
.hl-spine.hl-green  { background: #34d399; }
.hl-spine.hl-blue   { background: #60a5fa; }
.hl-spine.hl-pink   { background: #f472b6; }

@media (prefers-reduced-motion: reduce) { .hl-swatch:hover { transform: none; } }

/* a colour dot on the highlight filter chips, and the spine on a result row */
.hl-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.hl-dot.hl-yellow { background: #facc15; }
.hl-dot.hl-green  { background: #34d399; }
.hl-dot.hl-blue   { background: #60a5fa; }
.hl-dot.hl-pink   { background: #f472b6; }
.note-row-hl { position: relative; padding-left: 14px; }
.note-row-hl > .hl-spine { position: absolute; left: 4px; top: 10px; bottom: 10px; }

/* ------------------------------------------- one concept at a time ------ */
/*
 * The study guide used to render a whole unit at once - mechanism, terms, the
 * lecture text, every question, pitfalls - on one page. Complete, and nobody
 * read it. These rules dress the stepper: a progress strip, one card, Back and
 * Next. See stepper.js and concepts.js.
 */
.stepper { max-width: 760px; margin: 0 auto; }

.stepper-head { margin-bottom: 12px; }
.stepper-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent-2);
}
.stepper-track {
  display: flex; gap: 3px; margin-top: 9px;
}
.stepper-seg {
  flex: 1 1 0; height: 4px; min-width: 4px; padding: 0; border: 0;
  border-radius: 2px; background: var(--ring-track); cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}
.stepper-seg:hover { transform: scaleY(2); }
.stepper-seg.done { background: var(--green); }
.stepper-seg.now { background: var(--accent); }

.concept-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 22px 24px;
}
.concept-title {
  font-size: 19px; line-height: 1.35; margin: 0 0 14px;
}
.concept-terms { display: flex; flex-direction: column; gap: 14px; }
.concept-term {
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line-soft);
}
.concept-term-eg {
  margin-top: 7px; font-size: 12.5px; color: var(--text-2);
  white-space: pre-wrap; border-left: 2px solid var(--line);
  padding-left: 10px;
}
.concept-formula {
  padding: 14px; border-radius: var(--radius-sm); background: var(--surface-2);
  border-left: 3px solid var(--violet); font-size: 14px;
  white-space: pre-wrap; overflow-x: auto;
}
.concept-miss {
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--surface-2); border-left: 3px solid var(--amber);
  margin-bottom: 10px;
}

.concept-q { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
.concept-q-offer { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.concept-q-stem { margin-bottom: 11px; line-height: 1.5; }
.concept-q-live .q-opts { margin-top: 0; }
.concept-q-live .q-explain { margin-top: 12px; }

.stepper-foot { display: flex; align-items: center; gap: 10px; margin-top: 18px; }
.runner-nav {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft);
}

.contents-row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 14px; background: none; border: 0;
  border-bottom: 1px solid var(--line-soft); cursor: pointer; color: inherit;
}
.contents-row:last-child { border-bottom: none; }
.contents-row:hover { background: var(--surface-2); }
.contents-row.now { background: var(--accent-soft); }
.contents-no {
  width: 24px; height: 24px; flex: none; border-radius: 50%;
  background: var(--surface-3); color: var(--text-2);
  font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* ------------------------------------------- teaching text, parsed ----- */
/*
 * These fields are hard-wrapped at ~76 columns to fit a monday.com long_text
 * box. Rendering them with `pre-wrap` kept every one of those wraps, so on a
 * phone every second line was three words long. prose.js undoes the wraps and
 * recovers the structure; this draws it.
 */
.prose { display: flex; flex-direction: column; gap: 12px; }
.prose-sec { display: flex; flex-direction: column; gap: 9px; }
.prose-head {
  font-size: 12px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-2);
}
.prose-p { margin: 0; line-height: 1.68; color: var(--text-2); font-size: 14px; }
.prose-p.inset {
  padding-left: 12px; border-left: 2px solid var(--line);
  font-size: 13.5px;
}
.prose-list, .prose-num { margin: 0; padding: 0 0 0 2px; list-style: none; }
.prose-num { padding-left: 0; }
.prose-item {
  display: flex; gap: 9px; align-items: baseline;
  line-height: 1.6; font-size: 14px; color: var(--text-2);
  padding: 3px 0;
}
.prose-n {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-2);
  font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  align-self: flex-start; margin-top: 1px;
}
.prose-lead {
  font-weight: 700; color: var(--text); margin-right: 6px;
  letter-spacing: 0.02em;
}
.prose-lead::after { content: ':'; }
.prose-glyph { color: var(--accent-2); flex: none; font-size: 8px; line-height: 2; }
.prose-item[data-level="1"] { margin-left: 18px; font-size: 13.5px; }
.prose-item[data-level="2"] { margin-left: 34px; font-size: 13px; color: var(--text-3); }
.prose-item[data-level="3"] { margin-left: 48px; font-size: 13px; color: var(--text-3); }
.prose-item[data-level="2"] .prose-glyph,
.prose-item[data-level="3"] .prose-glyph { color: var(--text-3); }

.prose-ladder {
  display: flex; flex-direction: column;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  overflow: hidden;
}
.prose-ladder-row {
  display: flex; gap: 12px; padding: 8px 12px; font-size: 13.5px;
  border-bottom: 1px solid var(--line-soft);
}
.prose-ladder-row:last-child { border-bottom: none; }
.prose-ladder-row:nth-child(odd) { background: var(--surface-2); }
.prose-ladder-label {
  flex: 0 0 118px; font-weight: 600; color: var(--text);
}
.prose-ladder-val { flex: 1 1 auto; color: var(--text-2); line-height: 1.5; }

@media (max-width: 620px) {
  .concept-card { padding: 16px 15px; }
  .concept-title { font-size: 17px; }
  .prose-ladder-row { flex-direction: column; gap: 2px; }
  .prose-ladder-label { flex: none; }
  .stepper-foot .btn.lg { flex: 1 1 auto; justify-content: center; }
}

@media print {
  .fold { display: block !important; }
  .fold > .fold-body { display: block !important; }
  .stepper-track, .stepper-foot, .runner-nav { display: none !important; }
}

.concept-clip {
  margin-top: 18px; padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--surface-2); border-left: 3px solid var(--amber);
}
.concept-clip .strong { color: var(--amber); }
.concept-clip p { margin: 4px 0 0; color: var(--text-2); line-height: 1.6; }

/* ---- pictures on a slide card ---------------------------------------- */
/*
 * The extraction worked for months but only the lecture viewer ever called
 * it, so every slide in the study guide showed the words and dropped the
 * diagram. On a lot of these slides the diagram IS the content.
 */
.slide-card-figs {
  display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px;
}
.slide-card-fig {
  max-width: 100%; max-height: 340px; width: auto; height: auto;
  border-radius: var(--radius-sm); border: 1px solid var(--line-soft);
  background: #fff;            /* most deck art is drawn for a white slide */
  object-fit: contain;
}
.slide-card.dense .slide-card-fig { max-height: 260px; }
@media (max-width: 620px) {
  .slide-card-fig { max-height: 220px; }
}

/* ---- the deck moves ---------------------------------------------------- */
/*
 * Next and Back have to feel like different actions. The card arrives from
 * the side he is travelling towards; without this both were the same silent
 * swap and the deck felt like a slideshow of static pages.
 */
@keyframes card-in-fwd {
  from { opacity: 0; transform: translate3d(26px, 0, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes card-in-back {
  from { opacity: 0; transform: translate3d(-26px, 0, 0); }
  to   { opacity: 1; transform: none; }
}
.concept-card.card-in-fwd  { animation: card-in-fwd 0.22s cubic-bezier(0.22, 0.9, 0.3, 1) both; }
.concept-card.card-in-back { animation: card-in-back 0.22s cubic-bezier(0.22, 0.9, 0.3, 1) both; }

.stepper-seg { transition: background 0.2s ease, transform 0.15s ease; }

/* The streak badge sits in the header, beside where he already looks for
   "4 of 17", so the reward is not somewhere he has to go and find. */
.stepper-streak { display: inline-flex; align-items: center; margin-left: 4px; }
.stepper-streak:empty { display: none; }
.stepper-streak .streak-badge { transform: scale(0.82); transform-origin: left center; }

/* Answering should register physically even without haptics. */
.concept-q-live .q-opt { transition: transform 0.12s ease, border-color 0.15s ease; }
.concept-q-live .q-opt:active:not([disabled]) { transform: scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  .concept-card.card-in-fwd,
  .concept-card.card-in-back { animation: none; }
  .stepper-seg { transition: none; }
  .concept-q-live .q-opt { transition: none; }
  .concept-q-live .q-opt:active:not([disabled]) { transform: none; }
}
