/* ───────────────────────────────────────────────────────────────────
   Review — a reading surface, not a chat app.

   The terminal version put every mechanism on screen: [loading notes],
   [roam] Moving to…, and four lines of citations under every paragraph.
   Here the mechanism is still there, but it sits in the margins: sources
   live under a hairline beneath the sentence they support, topic changes
   are a quiet chip, and note-loading is a shimmer that disappears.
   ─────────────────────────────────────────────────────────────────── */

:root {
  --bg:        #faf9f6;
  --bg-soft:   #f2f0eb;
  --surface:   #ffffff;
  --line:      #e2ded4;
  --line-soft: #ece9e1;
  --ink:       #1d1b16;
  --ink-soft:  #56524a;
  --ink-faint: #8d8878;
  --accent:    #8a6534;
  --strong:    #4f7d63;   /* a claim your notes back            */
  --gray:      #a08d6a;   /* a claim nothing settled            */
  --thin:      #b9714f;   /* a claim with no source at all      */
  --serif: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua',
           Georgia, ui-serif, serif;
  --sans: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI',
          system-ui, sans-serif;
  --measure: 34rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #101113;
    --bg-soft:   #16181b;
    --surface:   #191b1e;
    --line:      #2a2d31;
    --line-soft: #212427;
    --ink:       #e7e4dd;
    --ink-soft:  #a5a196;
    --ink-faint: #6e6a61;
    --accent:    #c8a97e;
    --strong:    #7fae94;
    --gray:      #9a8e75;
    --thin:      #c08a६9;
    --thin:      #c08a69;
  }
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

button { font-family: inherit; cursor: pointer; }
[hidden] { display: none !important; }

/* ══════════════════════════════ setup ══════════════════════════════ */

.setup {
  height: 100%;
  display: grid;
  place-items: center;
  padding: 2rem 1.25rem;
  overflow-y: auto;
}

.setup-inner { width: 100%; max-width: 30rem; }

.setup-head { margin-bottom: 2.5rem; }

.setup-head h1 {
  font-family: var(--serif);
  font-size: 2.1rem;
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0 0 0.3rem;
}

.sub { color: var(--ink-faint); margin: 0; font-size: 0.87rem; }

.field { margin-bottom: 1.75rem; }

.field > label {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.6rem;
}

.modes { display: grid; gap: 0.5rem; }

.mode {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  color: var(--ink);
  transition: border-color .14s, background .14s, transform .14s;
}

.mode:hover { border-color: var(--ink-faint); }
.mode[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

.mode b { font-weight: 550; font-size: 0.92rem; }
.mode span { color: var(--ink-faint); font-size: 0.8rem; }

/* topic picker */
.picker { position: relative; }

#topic-input, textarea {
  width: 100%;
  padding: 0.68rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  outline: none;
  transition: border-color .14s;
}

#topic-input:focus, textarea:focus { border-color: var(--accent); }

.results {
  position: absolute;
  z-index: 30;
  top: calc(100% + 5px);
  left: 0; right: 0;
  max-height: 15rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
  box-shadow: 0 12px 32px -12px rgb(0 0 0 / .3);
  padding: 0.25rem;
}

.result {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  color: var(--ink);
  padding: 0.42rem 0.55rem;
  border-radius: 6px;
  font-size: 0.87rem;
}

.result:hover, .result.on { background: var(--bg-soft); }
.result small { display: block; color: var(--ink-faint); font-size: 0.72rem; }
.results .none { padding: 0.6rem; color: var(--ink-faint); font-size: 0.85rem; }

.hint { color: var(--ink-faint); font-size: 0.78rem; margin: 0.5rem 0 0; }

.begin {
  width: 100%;
  padding: 0.72rem;
  border: 0;
  border-radius: 9px;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.92rem;
  font-weight: 550;
  transition: opacity .14s;
}

.begin:disabled { opacity: 0.35; cursor: default; }
.begin:not(:disabled):hover { opacity: 0.86; }

.err {
  margin: 0.9rem 0 0;
  color: var(--thin);
  font-size: 0.83rem;
  line-height: 1.5;
}

/* ═════════════════════════════ session ═════════════════════════════ */

.session { height: 100%; display: grid; grid-template-rows: auto 1fr auto; }

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.62rem 1.1rem;
  border-bottom: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
}

.bar-left { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }

.dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ink-faint);
  flex: none;
  transition: background .3s;
}

.dot.busy { background: var(--accent); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.28; } }

.where { min-width: 0; line-height: 1.25; }
.chapter {
  display: block;
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.topic {
  display: block;
  font-size: 0.88rem;
  font-weight: 550;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bar-right { display: flex; align-items: center; gap: 0.35rem; flex: none; }
.stat { color: var(--ink-faint); font-size: 0.76rem; margin-right: 0.4rem; }

.ghost {
  border: 1px solid transparent;
  background: none;
  color: var(--ink-faint);
  font-size: 0.78rem;
  padding: 0.28rem 0.55rem;
  border-radius: 6px;
  transition: color .14s, border-color .14s;
}
.ghost:hover { color: var(--ink); border-color: var(--line); }
.ghost.on { color: var(--accent); }

/* thread */
.thread { overflow-y: auto; scroll-behavior: smooth; }
.stream {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2.2rem 1.25rem 3rem;
}

/* a tutor turn */
.turn {
  font-family: var(--serif);
  font-size: 1.06rem;
  line-height: 1.72;
  color: var(--ink);
  margin: 0 0 1.9rem;
  animation: rise .34s ease both;
}

.turn p { margin: 0 0 0.85rem; }
.turn p:last-child { margin-bottom: 0; }

@keyframes rise {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* your answer — indented and quiet, not a bubble */
.mine {
  font-size: 0.92rem;
  color: var(--ink-soft);
  margin: 0 0 1.9rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--line);
  white-space: pre-wrap;
  animation: rise .28s ease both;
}

/* topic change — a chip, not a rule across the page */
.hop {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 1rem;
  padding: 0.3rem 0.6rem 0.3rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-soft);
  font-size: 0.76rem;
  color: var(--ink-soft);
  animation: rise .3s ease both;
}

.hop svg { color: var(--ink-faint); flex: none; }
.hop b { font-weight: 550; color: var(--ink); }
.hop .why { color: var(--ink-faint); }
.hop.jump { border-style: dashed; }

.hop .miss {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--thin);
  flex: none;
}

/* notes loading — a shimmer that removes itself */
.notes {
  font-size: 0.76rem;
  color: var(--ink-faint);
  margin: 0 0 1rem;
  animation: fade 1.6s ease-in-out infinite;
}
@keyframes fade { 0%,100% { opacity: .45; } 50% { opacity: .95; } }

/* thinking */
.thinking {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ink-faint);
  font-size: 0.82rem;
  margin: 0 0 1.9rem;
}

.thinking i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  animation: bob 1.15s ease-in-out infinite;
}
.thinking i:nth-child(2) { animation-delay: .16s; }
.thinking i:nth-child(3) { animation-delay: .32s; }
@keyframes bob { 0%,80%,100% { opacity: .25; } 40% { opacity: 1; } }
.thinking .secs { margin-left: 0.2rem; font-variant-numeric: tabular-nums; }

/* the cursor while text streams */
.turn.live > :last-child::after {
  content: '';
  display: inline-block;
  width: 0.44em; height: 1.02em;
  margin-left: 1px;
  vertical-align: -0.16em;
  background: var(--accent);
  opacity: .7;
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

/* ── sources ──────────────────────────────────────────────────────── */
/* A cited sentence keeps a hairline under it. Nothing is printed;
   the source is one hover away.                                       */

.src {
  border-bottom: 1px solid transparent;
  cursor: help;
  transition: border-color .16s, background .16s;
}

body[data-src="subtle"] .src.strong { border-bottom-color: color-mix(in srgb, var(--strong) 55%, transparent); }
body[data-src="subtle"] .src.gray   { border-bottom: 1px dotted color-mix(in srgb, var(--gray) 60%, transparent); }

body[data-src="all"] .src.strong { border-bottom-color: var(--strong); }
body[data-src="all"] .src.gray   { border-bottom: 1px dotted var(--gray); }
body[data-src="all"] .src.unsupported {
  border-bottom: 1px dashed color-mix(in srgb, var(--thin) 70%, transparent);
}

body[data-src="off"] .src { border-bottom-color: transparent !important; cursor: inherit; }

.src:hover { background: color-mix(in srgb, var(--accent) 9%, transparent); }
body[data-src="off"] .src:hover { background: none; }

.cite-pop {
  position: fixed;
  z-index: 60;
  max-width: 25rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0 14px 36px -14px rgb(0 0 0 / .45);
  font-family: var(--sans);
  pointer-events: none;
  animation: rise .12s ease both;
}

.cite-pop-src {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--accent);
  margin-bottom: 0.25rem;
  font-variant-numeric: tabular-nums;
}

.cite-pop-text {
  font-size: 0.83rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

/* an error, inline and undramatic */
.oops {
  margin: 0 0 1.9rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid color-mix(in srgb, var(--thin) 40%, var(--line));
  border-left-width: 2px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--thin) 5%, transparent);
  color: var(--ink-soft);
  font-size: 0.85rem;
  line-height: 1.55;
}

/* ═════════════════════════════ composer ════════════════════════════ */

.composer {
  border-top: 1px solid var(--line-soft);
  padding: 0.7rem 1.25rem 0.55rem;
  background: var(--bg);
}

.composer-inner {
  max-width: var(--measure);
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
}

textarea {
  resize: none;
  max-height: 9rem;
  line-height: 1.5;
  font-size: 0.95rem;
}

#send {
  flex: none;
  width: 2.35rem; height: 2.35rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 8px;
  background: var(--ink);
  color: var(--bg);
  transition: opacity .14s;
}
#send:disabled { opacity: 0.3; cursor: default; }

.composer-hint {
  max-width: var(--measure);
  margin: 0.4rem auto 0;
  color: var(--ink-faint);
  font-size: 0.72rem;
}

/* summary */
.tally { display: grid; gap: 0.5rem; margin-bottom: 1.75rem; }
.tally div {
  display: flex;
  justify-content: space-between;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  font-size: 0.87rem;
}
.tally span { color: var(--ink-faint); }
.tally b { font-weight: 550; }

@media (max-width: 480px) {
  .stream { padding: 1.5rem 1rem 2rem; }
  .turn { font-size: 1.02rem; }
  .bar { padding: 0.55rem 0.85rem; }
}

/* ── clicking a source ────────────────────────────────────────────── */

body:not([data-src="off"]) .src { cursor: pointer; }
.src:active { background: color-mix(in srgb, var(--accent) 18%, transparent); }

.cite-pop-go {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.7rem;
  color: var(--ink-faint);
}

/* a short-lived note about what just happened */
.toast {
  position: fixed;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  z-index: 70;
  max-width: min(30rem, calc(100vw - 2rem));
  padding: 0.5rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 14px 30px -14px rgb(0 0 0 / .45);
  font-size: 0.8rem;
  color: var(--ink-soft);
  animation: rise .18s ease both;
}
.toast.bad { border-color: color-mix(in srgb, var(--thin) 45%, var(--line)); }

/* ── voice ────────────────────────────────────────────────────────── */

#voice-btn { display: inline-flex; align-items: center; gap: 0.3rem; }
#voice-btn.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }

.mic {
  border-top: 1px solid var(--line-soft);
  background: var(--bg);
  padding: 0.85rem 1.25rem;
}

.mic-inner {
  max-width: var(--measure);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.mic-state {
  flex: 1;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.wave { display: inline-flex; align-items: center; gap: 3px; height: 20px; }

.wave i {
  width: 3px;
  height: 5px;
  border-radius: 2px;
  background: var(--ink-faint);
  transition: background .3s;
}

/* idle: flat. listening: a slow breath. speaking: the tutor's turn. */
.wave.live i { background: var(--accent); animation: bars 1s ease-in-out infinite; }
.wave.live i:nth-child(2) { animation-delay: .12s; }
.wave.live i:nth-child(3) { animation-delay: .24s; }
.wave.live i:nth-child(4) { animation-delay: .36s; }
.wave.live i:nth-child(5) { animation-delay: .48s; }
.wave.hot i { background: var(--strong); }

@keyframes bars {
  0%, 100% { height: 5px; }
  50%      { height: 17px; }
}

/* what you said, out loud — same shape as a typed answer, marked as spoken */
.mine.spoken { border-left-style: dotted; }
.mine.spoken::before {
  content: '';
  display: inline-block;
  width: 4px; height: 4px;
  margin: 0 0.45rem 0.15rem 0;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
}

/* ── the score HUD ────────────────────────────────────────────────── */

.hud {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-right: 0.5rem;
  font-variant-numeric: tabular-nums;
}

.combo {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  padding: 0.14rem 0.42rem 0.14rem 0.3rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  font-size: 0.74rem;
  font-weight: 600;
}

.combo .bolt { font-size: 0.68rem; }
.combo.pop { animation: pop .42s cubic-bezier(.2,1.5,.4,1); }

@keyframes pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.32); }
  100% { transform: scale(1); }
}

/* the higher the combo the hotter it reads */
.combo[data-m="3"] { border-color: color-mix(in srgb, var(--accent) 70%, transparent); }
.combo[data-m="4"], .combo[data-m="5"] {
  border-color: var(--thin);
  background: color-mix(in srgb, var(--thin) 15%, transparent);
  color: var(--thin);
}

.lvl { display: flex; align-items: center; gap: 0.35rem; font-size: 0.74rem; color: var(--ink-faint); }

.lvl .bar {
  display: block;
  width: 42px; height: 3px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}

.lvl .bar i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: var(--accent);
  transition: width .5s cubic-bezier(.2,.8,.3,1);
}

.elo { font-size: 0.74rem; color: var(--ink-faint); }
.elo.up { color: var(--strong); }
.elo.down { color: var(--thin); }

/* the number that floats off when you score */
.xp-float {
  position: fixed;
  z-index: 65;
  font-size: 0.8rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  pointer-events: none;
  animation: float-up 1.1s ease-out both;
}

@keyframes float-up {
  0%   { opacity: 0; transform: translateY(4px); }
  22%  { opacity: 1; transform: translateY(-2px); }
  100% { opacity: 0; transform: translateY(-26px); }
}

/* a verdict mark in the margin of the turn it belongs to */
.turn { position: relative; }

.verdict {
  position: absolute;
  left: -1.35rem;
  top: 0.42em;
  font-size: 0.78rem;
  line-height: 1;
  opacity: .85;
}
.verdict.right { color: var(--strong); }
.verdict.partial { color: var(--gray); }
.verdict.wrong { color: var(--thin); }

@media (max-width: 700px) {
  .lvl .bar, .elo { display: none; }
  .verdict { position: static; margin-right: 0.35rem; }
}

/* summary extras */
.tally div.hero {
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
}
.movers { margin: 0 0 1.75rem; }
.movers h3 {
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 500;
  margin: 0 0 0.5rem;
}
.mover {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.32rem 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.83rem;
}
.mover:last-child { border-bottom: 0; }
.mover span { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.mover .harder { color: var(--thin); }
.mover .easier { color: var(--strong); }

/* ── sign in, and the board ───────────────────────────────────────── */

.setup-inner.wide { max-width: 40rem; }

.link {
  border: 0;
  background: none;
  padding: 0;
  color: var(--ink-faint);
  font-size: 0.82rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
}
.link:hover { color: var(--accent); text-decoration-color: currentColor; }

.gate-alt {
  display: flex;
  justify-content: space-between;
  margin-top: 1.1rem;
}

.begin.ghosty {
  margin-top: 0.6rem;
  background: none;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-weight: 500;
}
.begin.ghosty:hover { border-color: var(--ink-faint); opacity: 1; }

.whoami {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.4rem;
  font-size: 0.82rem;
  color: var(--ink-faint);
}
.whoami-acts { display: flex; gap: 0.9rem; }
#who-name { font-weight: 550; color: var(--ink); }

.tabs { display: flex; gap: 0.3rem; margin-bottom: 1.1rem; }

.tab {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-faint);
  font-size: 0.8rem;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
}
.tab.on { border-color: var(--accent); color: var(--accent); }

/* the board itself */
.board-row {
  display: grid;
  grid-template-columns: 1.6rem 1fr auto auto auto;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line-soft);
  border-radius: 9px;
  margin-bottom: 0.35rem;
  background: var(--surface);
  font-variant-numeric: tabular-nums;
}

.board-row.you {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}

.board-row .rank { font-size: 0.85rem; color: var(--ink-faint); text-align: right; }
.board-row.top .rank { color: var(--accent); font-weight: 700; }
.board-row .who { min-width: 0; }
.board-row .who b { display: block; font-weight: 550; font-size: 0.92rem; }
.board-row .who small { color: var(--ink-faint); font-size: 0.72rem; }
.board-row .num { text-align: right; font-size: 0.85rem; }
.board-row .num small { display: block; color: var(--ink-faint); font-size: 0.66rem; letter-spacing: .05em; text-transform: uppercase; }
.board-empty { color: var(--ink-faint); font-size: 0.87rem; padding: 1.2rem 0; }

.board-head {
  display: grid;
  grid-template-columns: 1.6rem 1fr auto auto auto;
  gap: 0.7rem;
  padding: 0 0.7rem 0.4rem;
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.board-head span:not(:nth-child(2)) { text-align: right; }

@media (max-width: 520px) {
  .board-row, .board-head { grid-template-columns: 1.4rem 1fr auto auto; }
  .board-row .elo-col, .board-head .elo-col { display: none; }
}

/* ══════════════════════════ rank aesthetics ═══════════════════════
   One fixed layer behind everything, swapped by body[data-tier].
   Everything is CSS — no images — and everything is translucent,
   because it sits under a column of clinical text that has to stay
   the most legible thing on screen.

   The arc is the point: Bronze is deliberately cheap — coarse
   diagonal stripes, muddy fill, visible banding, the look of a
   default. Each tier removes some crudeness and adds some depth,
   and Onyx is the only one that moves of its own accord.
   ────────────────────────────────────────────────────────────── */

#rankbg {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease;
}

#rankbg > i {
  position: absolute;
  inset: -20%;
  display: block;
  opacity: 0;
}

/* the text column gets its own scrim so no tier can hurt legibility */
.thread::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(120% 75% at 50% 45%,
              color-mix(in srgb, var(--bg) 82%, transparent) 0%,
              color-mix(in srgb, var(--bg) 55%, transparent) 55%,
              transparent 100%);
}

/* ── Bronze — cheap on purpose ─────────────────────────────────── */
body[data-tier="bronze"] #rankbg {
  opacity: .38;
  filter: saturate(.62) contrast(1.22);
}
body[data-tier="bronze"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background:
    repeating-linear-gradient(45deg,
      rgba(122, 79, 38, .95) 0 7px,
      rgba(92, 58, 26, .95) 7px 14px),
    linear-gradient(160deg, #7d5527, #3d2914);
}
/* hard banding, the tell of a cheap gradient */
body[data-tier="bronze"] #rankbg > i:nth-child(2) {
  opacity: .5;
  background: repeating-linear-gradient(
    0deg, rgba(0,0,0,.22) 0 3px, rgba(255,255,255,.05) 3px 6px);
}
body[data-tier="bronze"] #rankbg > i:nth-child(3) {
  opacity: .55;
  background: radial-gradient(70% 50% at 78% 88%,
              rgba(180, 118, 54, .5), transparent 70%);
}

/* ── Silver — tidy, brushed, unremarkable ──────────────────────── */
body[data-tier="silver"] #rankbg { opacity: .3; }
body[data-tier="silver"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background: linear-gradient(115deg,
    #79828e 0%, #b9c2cc 26%, #8b949f 42%, #dfe5ea 58%, #949da8 74%, #6f7883 100%);
}
body[data-tier="silver"] #rankbg > i:nth-child(2) {
  opacity: .5;
  background: repeating-linear-gradient(103deg,
    rgba(255,255,255,.10) 0 1px, transparent 1px 4px);
}

/* ── Gold — warm, with a sheen that actually moves ─────────────── */
body[data-tier="gold"] #rankbg { opacity: .3; }
body[data-tier="gold"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background: linear-gradient(118deg,
    #6d4c12 0%, #b8912f 22%, #f0d98d 44%, #cfa63c 60%, #8a6a1c 82%, #5d400f 100%);
}
body[data-tier="gold"] #rankbg > i:nth-child(2) {
  opacity: .8;
  background: radial-gradient(60% 45% at 28% 12%,
              rgba(255, 240, 195, .5), transparent 65%);
}
body[data-tier="gold"] #rankbg > i:nth-child(3) {
  opacity: .45;
  background: linear-gradient(105deg, transparent 38%,
              rgba(255,255,255,.5) 50%, transparent 62%);
  animation: sheen 9s ease-in-out infinite;
}
@keyframes sheen {
  0%, 100% { transform: translateX(-28%); }
  50%      { transform: translateX(28%); }
}

/* ── Platinum — cool, engineered, quietly expensive ────────────── */
body[data-tier="platinum"] #rankbg { opacity: .3; }
body[data-tier="platinum"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background:
    radial-gradient(90% 70% at 50% -15%, #e8f1f7, transparent 62%),
    linear-gradient(150deg, #9fb4c4 0%, #d7e3ec 40%, #8ea6ba 72%, #b9cad8 100%);
}
body[data-tier="platinum"] #rankbg > i:nth-child(2) {
  opacity: .35;
  background:
    linear-gradient(0deg, transparent 0 43px, rgba(255,255,255,.30) 43px 44px),
    linear-gradient(90deg, transparent 0 43px, rgba(255,255,255,.30) 43px 44px);
  background-size: 44px 44px, 44px 44px;
}
body[data-tier="platinum"] #rankbg > i:nth-child(3) {
  opacity: .5;
  background: radial-gradient(45% 35% at 74% 78%,
              rgba(190, 225, 255, .55), transparent 70%);
}

/* ── Diamond — refraction: facets that drift through each other ── */
body[data-tier="diamond"] #rankbg { opacity: .32; }
body[data-tier="diamond"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background: conic-gradient(from 200deg at 40% 35%,
    #7fd7ff, #cfe9ff 12%, #a9b8ff 26%, #ffd9f2 42%, #bff5ee 58%,
    #9fc4ff 74%, #e6f4ff 88%, #7fd7ff);
  animation: facet 42s linear infinite;
}
body[data-tier="diamond"] #rankbg > i:nth-child(2) {
  opacity: .55;
  mix-blend-mode: screen;
  background: conic-gradient(from 20deg at 66% 70%,
    transparent, rgba(255,255,255,.65) 18%, transparent 34%,
    rgba(180,240,255,.55) 56%, transparent 74%, rgba(255,220,250,.5) 92%, transparent);
  animation: facet 31s linear infinite reverse;
}
/* the hard edges that make it read as cut stone rather than soup */
body[data-tier="diamond"] #rankbg > i:nth-child(3) {
  opacity: .3;
  background:
    repeating-linear-gradient(62deg, transparent 0 78px, rgba(255,255,255,.5) 78px 79px),
    repeating-linear-gradient(-62deg, transparent 0 96px, rgba(255,255,255,.35) 96px 97px);
}
@keyframes facet { to { transform: rotate(360deg); } }

/* ── Onyx — the only tier that is genuinely alive ──────────────── */
body[data-tier="onyx"] #rankbg { opacity: .78; }
body[data-tier="onyx"] #rankbg > i:nth-child(1) {
  opacity: 1;
  background:
    radial-gradient(120% 90% at 50% 8%, #14161c 0%, #07080b 55%, #030305 100%);
}
/* aurora: two slow blooms that never quite repeat together */
body[data-tier="onyx"] #rankbg > i:nth-child(2) {
  opacity: .85;
  mix-blend-mode: screen;
  background:
    radial-gradient(38% 26% at 26% 30%, rgba(94, 234, 212, .40), transparent 68%),
    radial-gradient(34% 24% at 72% 62%, rgba(167, 139, 250, .42), transparent 70%),
    radial-gradient(30% 22% at 52% 84%, rgba(56, 189, 248, .32), transparent 72%);
  filter: blur(14px);
  animation: aurora 38s ease-in-out infinite alternate;
}
/* a fine, still starfield underneath the movement */
body[data-tier="onyx"] #rankbg > i:nth-child(3) {
  opacity: .5;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 22%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1.1px 1.1px at 78% 14%, rgba(255,255,255,.75), transparent 60%),
    radial-gradient(1.6px 1.6px at 34% 68%, rgba(255,255,255,.85), transparent 60%),
    radial-gradient(1.0px 1.0px at 62% 44%, rgba(255,255,255,.65), transparent 60%),
    radial-gradient(1.3px 1.3px at 88% 76%, rgba(255,255,255,.8), transparent 60%),
    radial-gradient(0.9px 0.9px at 46% 12%, rgba(255,255,255,.6), transparent 60%),
    radial-gradient(1.2px 1.2px at 20% 88%, rgba(255,255,255,.7), transparent 60%);
  background-size: 520px 520px;
  animation: drift 150s linear infinite;
}
@keyframes aurora {
  0%   { transform: translate3d(-3%, -2%, 0) scale(1); }
  50%  { transform: translate3d(4%, 3%, 0) scale(1.12); }
  100% { transform: translate3d(-2%, 4%, 0) scale(1.04); }
}
@keyframes drift { to { background-position: 520px 520px; } }

/* Onyx is dark enough that the page has to come with it. */
body[data-tier="onyx"] { --bg: #08090c; --ink: #eceaf4; }
body[data-tier="onyx"] .thread::before {
  background: radial-gradient(120% 75% at 50% 45%,
              rgba(8, 9, 12, .72) 0%, rgba(8, 9, 12, .42) 58%, transparent 100%);
}

@media (prefers-reduced-motion: reduce) {
  #rankbg > i { animation: none !important; }
}

/* ══════════════════════════════ motion ══════════════════════════════
   The app is paper and should stay paper — but paper that answers when
   you touch it. Every rule below animates transform, opacity or filter
   and nothing else, so all of it runs on the compositor and none of it
   can trigger a layout or a repaint. That is the whole budget: a session
   with this on costs the same frames as a session without it.

   The one thing deliberately left alone is the reading column. Text that
   slides while you are reading it is a toy, so .turn keeps the 5px rise
   it already had and nothing new was added to the stream. */

/* ── arriving at a screen ── */
/* display:none -> displayed restarts a CSS animation, and show() is exactly
   that, so screens announce themselves without a line of JavaScript. */
.setup, .session, .duel, .review, .board { animation: screen-in .42s cubic-bezier(.16,1,.3,1) both; }
@keyframes screen-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.994); }
}
/* The front page brings its own entrance and must not be scaled by this. */
#home { animation: none; }

/* ── things you press ── */
/* One spring, everywhere: a lift toward the pointer, a squash on the click.
   The cubic-bezier overshoots slightly on the way up, which is the part
   that reads as alive rather than as a hover state. */
.begin, .ghost, .mode, .tab, .opt, .grade, .landcard, .deckgroup summary,
#send, .notes-hits .hit, .gradebar button {
  transition: transform .18s cubic-bezier(.2,.9,.3,1.3),
              border-color .16s, background .16s, color .16s, opacity .16s;
}
.begin:not(:disabled):hover, .mode:hover, .opt:not(:disabled):hover,
.grade:hover, .landcard:hover { transform: translateY(-2px); }
.begin:not(:disabled):active, .mode:active, .opt:not(:disabled):active,
.grade:active, .landcard:active, .tab:active, .ghost:active {
  transform: translateY(0) scale(.975);
}
#send:not(:disabled):hover { transform: scale(1.08); }
#send:not(:disabled):active { transform: scale(.92); }
.ghost:hover { transform: translateY(-1px); }
.notes-hits .hit:hover { transform: translateX(2px); }

/* A pressed answer in a duel should feel chosen before the server agrees. */
.opt:not(:disabled):active { transform: translateX(3px) scale(.99); }

/* ── the notes panel ── */
/* It is toggled with [hidden], so this replays on every open, and the
   panel arrives from its own edge instead of blinking into place. */
#notes { animation: panel-in .34s cubic-bezier(.16,1,.3,1); }
@keyframes panel-in {
  from { opacity: 0; transform: translate3d(3%, 0, 0); }
}
/* Full screen is a different gesture — it grows, it does not slide. */
body.notes-full #notes { animation: panel-grow .34s cubic-bezier(.16,1,.3,1); }
@keyframes panel-grow {
  from { opacity: .4; transform: scale(.985); }
}
/* Swapping between the reading and the topic browser inside the panel. */
.notes-body, .notes-find { animation: fade-in .26s ease both; }
@keyframes fade-in { from { opacity: 0; } }

/* The edge tab nudges out when you go for it. */
#notes-tab { transition: transform .2s cubic-bezier(.2,.9,.3,1.3), color .16s, border-color .16s; }
/* Scoped: on a phone the tab has no translateY to preserve, and a touch
   :hover sticks after the tap. */
@media (hover: hover) and (min-width: 601px) {
  #notes-tab:hover { transform: translateY(-50%) translateX(-3px); }
}

/* ── keyboard ── */
/* Everything focusable gets the same ring, and only when the keyboard is
   doing the focusing — a mouse user never sees it. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ── scrolling ── */
.thread, .notes-body, .notes-hits, .setup { scroll-behavior: smooth; }
.thread, .notes-body, .notes-hits { overscroll-behavior: contain; }
/* A hairline scrollbar rather than the platform's, which is 15px of grey
   down the side of a reading column. */
.notes-body::-webkit-scrollbar, .notes-hits::-webkit-scrollbar,
.thread::-webkit-scrollbar { width: 9px; }
.notes-body::-webkit-scrollbar-thumb, .notes-hits::-webkit-scrollbar-thumb,
.thread::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 999px;
  border: 3px solid transparent; background-clip: content-box;
}
.notes-body::-webkit-scrollbar-thumb:hover, .notes-hits::-webkit-scrollbar-thumb:hover,
.thread::-webkit-scrollbar-thumb:hover { background-color: var(--ink-faint); background-clip: content-box; }
.notes-body::-webkit-scrollbar-track, .notes-hits::-webkit-scrollbar-track,
.thread::-webkit-scrollbar-track { background: transparent; }

/* ── the cited line ── */
/* It was already lit; now it lands, because you were sent here from a
   sentence and the eye needs telling where "here" is. */
.notes-body .cited { animation: citedin .5s ease-out, cited-land .45s cubic-bezier(.16,1,.3,1); }
@keyframes cited-land { from { transform: translateX(-6px); } }

/* Nobody has to have any of this. */
@media (prefers-reduced-motion: reduce) {
  .setup, .session, .duel, .review, .board, #notes,
  .notes-body, .notes-find, .notes-body .cited { animation: none !important; }
  .begin, .ghost, .mode, .tab, .opt, .grade, .landcard, #send,
  .notes-hits .hit, #notes-tab, .gradebar button { transition: none !important; }
  .begin:hover, .mode:hover, .opt:hover, .grade:hover, .landcard:hover,
  #send:hover, .notes-hits .hit:hover { transform: none !important; }
  .thread, .notes-body, .notes-hits, .setup { scroll-behavior: auto; }
}

/* ── the crest in the bar ──────────────────────────────────────── */
.rank {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: .02em;
}
.rank .crest { fill: currentColor; opacity: .9; }

body[data-tier="bronze"]   .rank { color: #a97142; }
body[data-tier="silver"]   .rank { color: #9aa4b0; }
body[data-tier="gold"]     .rank { color: #d0a63c; }
body[data-tier="platinum"] .rank { color: #7fa8c4; }
body[data-tier="diamond"]  .rank { color: #6fd3ef; }
body[data-tier="onyx"]     .rank { color: #b9a7f5; }
body[data-tier="onyx"]     .rank .crest {
  filter: drop-shadow(0 0 5px rgba(167,139,250,.85));
}

/* promotion */
.promo {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  pointer-events: none;
  background: radial-gradient(60% 45% at 50% 50%, rgba(0,0,0,.55), transparent 75%);
  animation: promo-in .35s ease both, promo-out .6s ease 2.6s both;
}
.promo b {
  font-family: var(--serif);
  font-size: clamp(2rem, 8vw, 3.6rem);
  font-weight: 400;
  letter-spacing: .04em;
  color: #fff;
  text-shadow: 0 2px 40px currentColor;
}
.promo small {
  display: block;
  text-align: center;
  margin-top: .3rem;
  font-family: var(--sans);
  font-size: .78rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: .75;
  color: #fff;
}
@keyframes promo-in  { from { opacity: 0; transform: scale(.94); } }
@keyframes promo-out { to   { opacity: 0; } }

.tier-chip {
  display: inline-block;
  margin-left: .4rem;
  padding: .05rem .38rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  font-size: .6rem;
  font-style: normal;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  vertical-align: 1px;
}
.t-bronze   { color: #a97142; }
.t-silver   { color: #9aa4b0; }
.t-gold     { color: #d0a63c; }
.t-platinum { color: #7fa8c4; }
.t-diamond  { color: #6fd3ef; }
.t-onyx     { color: #b9a7f5; }

/* ══════════════════════════════ arena ════════════════════════════ */

.searching {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  margin-bottom: 1.1rem;
}
.searching b { display: block; font-weight: 550; font-size: 0.95rem; }
.searching small { color: var(--ink-faint); font-size: 0.8rem; }

.pulse {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent);
  animation: ping 1.5s ease-out infinite;
}
@keyframes ping {
  70%  { box-shadow: 0 0 0 14px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* the duel */
.duel { height: 100%; display: grid; grid-template-rows: auto auto 1fr auto; }

.duel-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.8rem;
  padding: 0.7rem 1.1rem 0.6rem;
}

.fighter { display: flex; align-items: center; gap: 0.55rem; min-width: 0; }
.fighter.them { flex-direction: row-reverse; text-align: right; }

.fighter .pts {
  font-size: 1.35rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  transition: color .3s;
}
.fighter .pts.gain { color: var(--strong); }
.fighter .nm { min-width: 0; }
.fighter .nm b {
  display: block;
  font-size: 0.86rem;
  font-weight: 550;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fighter .nm small { color: var(--ink-faint); font-size: 0.68rem; }
.fighter .locked { color: var(--strong); }

.versus {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.timer { height: 2px; background: var(--line-soft); }
.timer i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--accent);
  transform-origin: left;
  transition: transform .12s linear, background .3s;
}
.timer i.hot { background: var(--thin); }

.duel-body { overflow-y: auto; display: grid; align-items: center; }
.duel-inner {
  width: 100%;
  max-width: 38rem;
  margin: 0 auto;
  padding: 1.6rem 1.25rem 2rem;
}

.d-topic {
  margin: 0 0 0.5rem;
  font-size: 0.66rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.d-stem {
  margin: 0 0 1.4rem;
  font-family: var(--serif);
  font-size: 1.14rem;
  line-height: 1.6;
}

.opts { display: grid; gap: 0.5rem; }

.opt {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font-size: 0.94rem;
  transition: border-color .12s, background .12s, transform .12s;
}
.opt:not(:disabled):hover { border-color: var(--ink-faint); }
.opt:not(:disabled):active { transform: scale(.995); }
.opt kbd {
  flex: none;
  font: inherit;
  font-size: 0.7rem;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0 0.28rem;
}
.opt.picked { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.opt.right {
  border-color: var(--strong);
  background: color-mix(in srgb, var(--strong) 14%, var(--surface));
}
.opt.wrong {
  border-color: var(--thin);
  background: color-mix(in srgb, var(--thin) 12%, var(--surface));
}
.opt .tag { margin-left: auto; font-size: 0.68rem; color: var(--ink-faint); }

.d-why {
  margin-top: 1rem;
  padding: 0.75rem 0.9rem;
  border-left: 2px solid var(--line);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-soft);
  animation: rise .25s ease both;
}
.d-why a {
  display: inline-block;
  margin-top: 0.35rem;
  font-size: 0.75rem;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.d-wait { margin: 0.9rem 0 0; font-size: 0.8rem; color: var(--ink-faint); }

.duel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 1.1rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.74rem;
  color: var(--ink-faint);
}

.countdown {
  text-align: center;
  font-family: var(--serif);
  font-size: clamp(3rem, 14vw, 6rem);
  line-height: 1;
  color: var(--accent);
  animation: pop .45s cubic-bezier(.2,1.4,.4,1);
}

@media (max-width: 520px) {
  .fighter .nm small { display: none; }
  .d-stem { font-size: 1.05rem; }
}

.d-why a.flagq { color: var(--ink-faint); }
.d-why a.flagq:hover { color: var(--thin); }

.roster { margin: 0 0 1.1rem; }
.roster h3 {
  font-size: .66rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 500; margin: 0 0 .45rem;
}
.bot-row {
  display: flex; align-items: center; justify-content: space-between; gap: .7rem;
  padding: .45rem .7rem; border: 1px solid var(--line-soft);
  border-radius: 8px; margin-bottom: .3rem; background: var(--surface);
  font-variant-numeric: tabular-nums;
  width: 100%; text-align: left; font: inherit; color: inherit;
  cursor: pointer; transition: border-color .12s, background .12s;
}
.bot-row:hover { border-color: var(--line); }
.bot-row.picked { border-color: var(--accent); background: var(--bg-soft); }
.bot-row.picked .who b::after { content: " \2713"; opacity: .7; }
.bot-row .who b { display: block; font-size: .87rem; font-weight: 550; }
.bot-row .who small { color: var(--ink-faint); font-size: .72rem; }
.bot-row .num { text-align: right; font-size: .85rem; }
.bot-row .num small { display: block; color: var(--ink-faint); font-size: .64rem; }

/* ── notes panel ────────────────────────────────────────────────────
   Fixed to the right rather than a column in the duel's flow: the duel
   layout is centred on a reading measure and stays exactly as it is with
   the panel shut. */
#notes {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(460px, 44vw); z-index: 40;
  display: flex; flex-direction: column;
  background: var(--bg-soft); border-left: 1px solid var(--line);
}
/* Every screen makes room for it, not just the duel. */
body.notes-open #gate,
body.notes-open #board,
body.notes-open #setup,
body.notes-open #session,
body.notes-open #arena,
body.notes-open #duel,
body.notes-open #verdict { padding-right: min(460px, 44vw); }

/* The way back in once it is shut: a tab on the edge, on every screen. */
#notes-tab {
  position: fixed; right: 0; top: 50%; transform: translateY(-50%);
  z-index: 39; padding: .9rem .35rem; border: 1px solid var(--line);
  border-right: 0; border-radius: 7px 0 0 7px;
  background: var(--bg-soft); color: var(--ink-faint);
  font-size: .6rem; letter-spacing: .12em;
}
#notes-tab span { writing-mode: vertical-rl; }
#notes-tab:hover { color: var(--ink); border-color: var(--accent); }

.notes-where { min-width: 0; flex: 1; }
.notes-head .ghost { flex: none; padding: .2rem .4rem; }

.notes-find { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.notes-find input {
  margin: .7rem .9rem; padding: .45rem .6rem; font: inherit; font-size: .82rem;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: 7px;
}
.notes-find input:focus { outline: none; border-color: var(--accent); }
.notes-hits { flex: 1; overflow-y: auto; padding: 0 .6rem 1rem; }
.notes-hits .hit {
  display: block; width: 100%; text-align: left; font: inherit;
  padding: .35rem .55rem; border: 0; border-radius: 6px;
  background: none; color: inherit;
}
.notes-hits .hit:hover { background: var(--surface); }
.notes-hits .hit b { display: block; font-size: .8rem; font-weight: 550; }
.notes-hits .hit small { color: var(--ink-faint); font-size: .68rem; }
.notes-hits .hit.chap {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .6rem; padding: .45rem .55rem;
}
.notes-hits .hit.chap b { font-size: .84rem; }
.notes-hits .hit.chap small { flex: none; }
.notes-hits .hit.up b { color: var(--ink-faint); font-weight: 400; font-size: .74rem; }
.notes-hits .hit.up:hover b { color: var(--ink); }
.notes-hits .grouphead {
  margin: .5rem .55rem .2rem; font-size: .66rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-faint);
}
.notes-hits .none { color: var(--ink-faint); font-size: .78rem; padding: .4rem .55rem; }
.notes-hits .none.searching { opacity: .65; }

/* A text hit reads as the line does in the note, with the match lit and the
   topic named quietly above it — the topic is context for the line, not the
   other way round, because the line is what you were looking for. */
.notes-hits .tgroup { margin: .1rem 0 .5rem; }
.notes-hits .hit.topichead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .6rem; padding: .3rem .55rem;
}
.notes-hits .hit.topichead b { font-size: .78rem; color: var(--ink-soft); }
.notes-hits .hit.topichead small { flex: none; }
.notes-hits .hit.line {
  display: flex; align-items: baseline; gap: .5rem;
  margin-left: .55rem; padding: .3rem .55rem .3rem .75rem;
  border-left: 1px solid var(--line-soft); border-radius: 0 6px 6px 0;
}
.notes-hits .hit.line:hover { border-left-color: var(--accent); }
.notes-hits .hit.line .snip {
  flex: 1; min-width: 0; font-size: .76rem; line-height: 1.45;
  color: var(--ink-soft); overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
}
.notes-hits .hit.line small {
  flex: none; font-size: .62rem; font-variant-numeric: tabular-nums;
}
.notes-hits mark {
  background: color-mix(in srgb, var(--accent) 26%, transparent);
  color: var(--ink); border-radius: 2px; padding: 0 .08em;
}

.notes-head {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .7rem .9rem; border-bottom: 1px solid var(--line-soft);
}
.notes-head b { display: block; font-size: .9rem; }
.notes-head small { color: var(--ink-faint); font-size: .68rem;
  font-variant-numeric: tabular-nums; }
/* Coverage and visit count sit under the path, quiet enough to ignore while
   reading and legible when you go looking for them. */
.read-line { display: block; margin-top: .12rem; }
.read-line b { color: var(--accent); font-weight: 600; }
.notes-hits .hit .reads { float: right; color: var(--ink-faint);
  font-size: .64rem; font-variant-numeric: tabular-nums; }

.notes-body {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: .9rem 1rem 4rem; font-size: .82rem; line-height: 1.5;
}
.notes-body h2 { font-size: .95rem; margin: 1.1rem 0 .4rem; }
.notes-body h3 { font-size: .86rem; margin: .9rem 0 .3rem; color: var(--ink-soft); }
.notes-body h4, .notes-body h5, .notes-body h6 {
  font-size: .8rem; margin: .7rem 0 .25rem; color: var(--ink-soft); }
.notes-body p { margin: .35rem 0; }
.notes-body hr { border: 0; border-top: 1px solid var(--line-soft); margin: .9rem 0; }
.notes-body blockquote {
  margin: .4rem 0; padding-left: .6rem; border-left: 2px solid var(--line);
  color: var(--ink-soft); }
.notes-body .row { font-variant-numeric: tabular-nums; white-space: pre-wrap; }
.notes-body .li {
  display: flex; gap: .4rem; margin: .18rem 0;
  padding-left: calc(var(--d, 0) * .85rem);
}
.notes-body .li .bullet { color: var(--ink-faint); flex: none; }
.notes-body code {
  font-size: .92em; padding: 0 .2em; border-radius: 3px; background: var(--surface); }
.notes-body figure { margin: .6rem 0; }
.notes-body img {
  max-width: 100%; border-radius: 6px; border: 1px solid var(--line-soft); }

/* the cited line, lit and left lit — you are usually reading around it */
.notes-body .cited {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-radius: 4px;
  box-shadow: -.35rem 0 0 0 var(--accent);
  animation: citedin .5s ease-out;
}
@keyframes citedin {
  from { background: color-mix(in srgb, var(--accent) 45%, transparent); }
}

.notes-foot {
  display: flex; gap: .9rem; padding: .55rem .9rem;
  border-top: 1px solid var(--line-soft); background: var(--bg-soft);
}

/* ── the panel, full screen ─────────────────────────────────────────
   Sometimes the vault is the thing you are doing, not a reference beside
   the thing you are doing. Full screen takes the panel to the whole window
   and sets the text on a reading measure rather than a sidebar's. Nothing
   else changes — same topic browser, same lit citation, same ✕ — so it is
   one key back either way. */
body.notes-full #notes { width: 100%; border-left: 0; }
body.notes-full.notes-open #gate,
body.notes-full.notes-open #board,
body.notes-full.notes-open #setup,
body.notes-full.notes-open #session,
body.notes-full.notes-open #arena,
body.notes-full.notes-open #duel,
body.notes-full.notes-open #verdict { padding-right: 0; }

/* Centred by padding rather than a max-width box, so the head's and foot's
   rules still run edge to edge across the window. */
body.notes-full .notes-head,
body.notes-full .notes-body,
body.notes-full .notes-hits,
body.notes-full .notes-foot {
  padding-inline: max(1.1rem, calc((100% - 74ch) / 2));
}
body.notes-full .notes-find input { width: min(100%, 74ch); margin-inline: auto; }
body.notes-full .notes-head b { font-size: 1rem; }
body.notes-full .notes-body {
  font-size: .92rem; line-height: 1.62; padding-top: 1.4rem;
}
body.notes-full .notes-body h2 { font-size: 1.1rem; margin: 1.4rem 0 .5rem; }
body.notes-full .notes-body h3 { font-size: .98rem; margin: 1.1rem 0 .35rem; }
body.notes-full .notes-body img { max-width: min(100%, 46rem); }

/* ══════════════════════════════ phone ══════════════════════════════
   Not a shrunken desktop. Three things actually change: the notes panel
   stops being a column beside the reading and becomes a sheet over it,
   every target grows to a thumb, and anything that names a key you do not
   have on a phone goes away. */

@media (max-width: 820px) {
  /* No room for a column — the panel covers, so nothing shifts for it. */
  body.notes-open #gate,
  body.notes-open #board,
  body.notes-open #setup,
  body.notes-open #session,
  body.notes-open #arena,
  body.notes-open #duel,
  body.notes-open #verdict { padding-right: 0; }

  #notes { width: 100%; border-left: 0; }
}

@media (max-width: 600px) {
  /* The address bar changes the viewport height as it hides; dvh follows
     it, so the composer is not pushed under the fold mid-sentence. */
  html, body { height: 100dvh; }
  .setup, .session, .duel, .board { height: 100dvh; }

  /* ── reading ── */
  .stream { padding: 1.15rem .95rem 1.5rem; }
  .turn { font-size: 1rem; line-height: 1.55; }
  .setup { padding: 1.5rem 1rem; }
  .setup-inner { width: 100%; }

  /* ── the bar ── */
  .bar {
    gap: .5rem;
    padding-top: max(.62rem, env(safe-area-inset-top));
    padding-left: max(.85rem, env(safe-area-inset-left));
    padding-right: max(.85rem, env(safe-area-inset-right));
  }
  .bar-right { gap: .5rem; }
  .where { min-width: 0; }
  .where .topic {
    display: block; max-width: 42vw;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Voice runs on the Mac's own microphone, so from a phone the button is
     an offer the app cannot keep. */
  #voice-btn { display: none; }
  .rank .crest { display: none; }

  /* ── the composer ── */
  .composer {
    padding: .55rem .8rem;
    padding-bottom: max(.55rem, env(safe-area-inset-bottom));
  }
  /* 16px exactly: anything smaller and iOS zooms the page on focus and
     never zooms back. */
  textarea { font-size: 16px; }
  #send { width: 2.75rem; height: 2.75rem; }
  .composer-hint { display: none; }

  /* ── the duel ── */
  .duel-bar { padding-top: max(.5rem, env(safe-area-inset-top)); }
  .opt { padding: .85rem .8rem; min-height: 2.9rem; align-items: center; }
  .opt kbd { display: none; }          /* no number row to press */
  #d-hint { display: none; }
  .duel-foot { padding-bottom: max(.5rem, env(safe-area-inset-bottom)); }
  .fighter .nm b { font-size: .85rem; }

  /* ── the notes panel, as a sheet ── */
  #notes {
    top: auto; height: 88dvh; border-top: 1px solid var(--line);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -12px 34px rgb(0 0 0 / .28);
    animation: sheetup .22s ease-out;
  }
  @keyframes sheetup { from { transform: translateY(14%); opacity: .6; } }
  /* Full screen takes the sheet up to the top of the window. */
  body.notes-full #notes {
    top: 0; height: 100dvh; border-radius: 0; box-shadow: none; animation: none;
  }
  .notes-head {
    position: sticky; top: 0; z-index: 1; background: var(--bg-soft);
    padding: .8rem .9rem;
  }
  .notes-head .ghost { padding: .45rem .6rem; font-size: 1rem; }
  .notes-body { font-size: .9rem; padding-bottom: max(3rem, env(safe-area-inset-bottom)); }
  .notes-foot { padding-bottom: max(.55rem, env(safe-area-inset-bottom)); }
  .notes-hits .hit { padding: .6rem .55rem; }
  .notes-find input { font-size: 16px; }

  /* Reachable with a thumb, not stranded at the middle of the screen. */
  #notes-tab {
    top: auto; bottom: max(1rem, env(safe-area-inset-bottom));
    right: .8rem; transform: none;
    border-radius: 999px; border-right: 1px solid var(--line);
    padding: .6rem .85rem; font-size: .62rem;
    background: var(--surface);
    box-shadow: 0 4px 14px rgb(0 0 0 / .22);
  }
  #notes-tab span { writing-mode: horizontal-tb; }

  /* ── arena ── */
  .bot-row { padding: .6rem .7rem; }
  .tally div { padding: .55rem .7rem; }
}

/* ══════════════════════════════ cards ══════════════════════════════
   A card is one question in the middle of an empty screen, because the
   only decision being made is whether you knew it. Everything else —
   counts, deck, intervals — sits at the edges. */

.deckgroup { border-bottom: 1px solid var(--line-soft); }
.deckgroup summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: .7rem; padding: .6rem .2rem; cursor: pointer; list-style: none;
}
.deckgroup summary::-webkit-details-marker { display: none; }
.deckgroup summary::before {
  content: "›"; color: var(--ink-faint); transition: transform .15s;
  display: inline-block; width: .7rem;
}
.deckgroup[open] summary::before { transform: rotate(90deg); }
.deckgroup summary b { flex: 1; font-size: .88rem; font-weight: 550; }
.pill { display: flex; align-items: center; gap: .35rem;
  font-variant-numeric: tabular-nums; }
.pill small { color: var(--ink-faint); font-size: .68rem; min-width: 2.2rem;
  text-align: right; }
.pill i {
  font-style: normal; font-size: .66rem; padding: .05rem .38rem;
  border-radius: 999px; font-weight: 600;
}
.pill i.due { background: color-mix(in srgb, var(--thin) 22%, transparent);
  color: var(--thin); }
.pill i.new { background: color-mix(in srgb, var(--strong) 20%, transparent);
  color: var(--strong); }

.deckrow {
  display: flex; align-items: center; justify-content: space-between;
  gap: .7rem; width: 100%; text-align: left; font: inherit; color: inherit;
  background: none; border: 0; border-radius: 7px;
  padding: .4rem .55rem .4rem 1.1rem;
}
.deckrow:hover { background: var(--surface); }
.deckrow b { font-weight: 400; font-size: .82rem; }

/* ── reviewing ── */
.review { height: 100%; display: grid; grid-template-rows: auto 1fr auto; }
.review-bar .rv-counts { font-size: .72rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; }
.review-bar .rv-counts b { color: var(--ink-soft); font-weight: 600; }

.review-body { overflow-y: auto; display: grid; align-items: center;
  padding: 1.5rem 1.25rem; }
.card-inner { width: 100%; max-width: var(--measure); margin: 0 auto; }

.card-front {
  font-family: var(--serif); font-size: 1.32rem; line-height: 1.4;
  margin: 0 0 1.2rem; text-wrap: balance;
}
.card-back { border-top: 1px solid var(--line); padding-top: 1rem; }
.card-answer { font-size: .96rem; line-height: 1.55; }
.card-answer p { margin: 0 0 .6rem; }
.card-shots { display: grid; gap: .6rem; margin: .9rem 0 .4rem;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.card-shots img { width: 100%; border-radius: 8px;
  border: 1px solid var(--line-soft); }
.card-done { color: var(--ink-faint); font-size: .95rem; text-align: center; }

.review-foot {
  border-top: 1px solid var(--line-soft); padding: .7rem 1.25rem;
  padding-bottom: max(.7rem, env(safe-area-inset-bottom));
}
.review-foot .begin { max-width: var(--measure); margin: 0 auto; display: block; }
.grades { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem;
  max-width: var(--measure); margin: 0 auto; }
.grade {
  font: inherit; font-size: .82rem; padding: .6rem .3rem; min-height: 3rem;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface); color: var(--ink);
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
}
.grade small { font-size: .62rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; }
.grade:hover { border-color: var(--ink-faint); }
.grade.again:hover { border-color: var(--thin); color: var(--thin); }
.grade.easy:hover  { border-color: var(--strong); color: var(--strong); }

@media (max-width: 600px) {
  .review { height: 100dvh; }
  .card-front { font-size: 1.15rem; }
  .card-shots { grid-template-columns: 1fr; }
  .grades { gap: .35rem; }
  .grade { font-size: .74rem; padding: .55rem .15rem; min-height: 3.2rem; }
  .grade kbd { display: none; }
}

/* ── landing ────────────────────────────────────────────────────────
   Two or three doors, not a menu. Big enough to hit with a thumb and
   quiet enough that it is not a decision you dread making twice a day. */
.lands { display: grid; gap: .6rem; margin: .4rem 0 1rem; }
.landcard {
  display: block; width: 100%; text-align: left; font: inherit; color: inherit;
  padding: .9rem 1rem; border: 1px solid var(--line); border-radius: 11px;
  background: var(--surface); transition: border-color .14s, transform .14s;
}
.landcard:hover { border-color: var(--accent); transform: translateY(-1px); }
.landcard b { display: block; font-size: .95rem; font-weight: 550; }
.landcard small {
  display: block; margin: .2rem 0 .5rem; color: var(--ink-soft);
  font-size: .78rem; line-height: 1.4;
}
.landcard .n {
  font-size: .68rem; color: var(--ink-faint); letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 600px) {
  .landcard { padding: .8rem .85rem; }
  .landcard small { font-size: .75rem; }
}
