/* Sinsehkai Student App — shared stylesheet.
   Tokens are master spec §8.1 verbatim. Layout follows §8.3, §25. */

:root {
  --bg: #F4F7F6;
  --surface: #FFFFFF;
  --surface-2: #E8EFEA;
  --primary: #1B4D3E;
  --primary-hover: #246351;
  --accent: #34D399;
  --text: #101D18;
  --text-muted: #5A6B64;
  --border: #D1DDD8;
  --danger: #EF4444;
  --warning: #F59E0B;
  --shadow: 0 4px 24px rgba(27, 77, 62, 0.08);
  --radius: 16px;
  --sunrise: linear-gradient(180deg, #FDE68A 0%, #A7F3D0 40%, #E8EFEA 100%);
}

[data-theme="dark"] {
  --bg: #0B110E;
  --surface: #151F1A;
  --surface-2: #1E2C27;
  --primary: #34D399;
  --primary-hover: #4ADE80;
  --accent: #10B981;
  --text: #E2E8E5;
  --text-muted: #8A9B95;
  --border: #2A3B35;
  --danger: #F87171;
  --warning: #FBBF24;
  --shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
  --sunrise: linear-gradient(180deg, #F59E0B 0%, #065F46 40%, #0B110E 100%);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* an author display rule would otherwise beat the hidden attribute's UA style */
[hidden] { display: none !important; }

html { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  transition: background 0.3s ease, color 0.3s ease;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

button { font: inherit; cursor: pointer; }
input, select { font: inherit; color: inherit; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* ——— buttons ——— */
.btn {
  min-height: 48px;
  padding: 12px 28px;
  border: none;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
}
.btn-primary { background: var(--primary); color: #fff; box-shadow: 0 8px 24px rgba(27, 77, 62, 0.2); }
.btn-primary:hover:not(:disabled) { background: var(--primary-hover); transform: translateY(-2px); }
.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }
[data-theme="dark"] .btn-primary { color: #06120E; }
.btn-ghost { background: transparent; color: var(--text-muted); padding: 12px 20px; }
.btn-ghost:hover { color: var(--text); background: rgba(127, 127, 127, 0.12); }
.btn-outline {
  background: transparent; border: 2px solid var(--border); color: var(--text);
  min-height: 44px; padding: 10px 20px; border-radius: 12px; font-weight: 600; font-size: 14px;
  display: inline-flex; align-items: center; gap: 8px;
}
.btn-outline:hover { border-color: var(--primary); color: var(--primary); }
.btn-block { width: 100%; }

/* ——— forms ——— */
.form-group { margin-bottom: 20px; }
.form-label {
  display: block; font-size: 13px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.5px;
  margin-bottom: 8px;
}
.form-hint { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.form-input, .form-select {
  width: 100%; min-height: 48px;
  padding: 12px 16px;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  font-size: 16px;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.form-input:focus, .form-select:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(52, 211, 153, 0.12);
}
.form-error { color: var(--danger); font-size: 13px; font-weight: 600; margin-top: 8px; min-height: 18px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

/* ——— Ascent (signup / login) ——— */
.environment { position: fixed; inset: 0; z-index: 0; pointer-events: none; transition: background 1s ease; }
body.stage-0 .environment { background: linear-gradient(180deg, var(--surface-2) 0%, var(--bg) 100%); }
body.stage-1 .environment { background: linear-gradient(180deg, #5A7D74 0%, var(--bg) 100%); }
body.stage-2 .environment { background: linear-gradient(180deg, #475569 0%, var(--bg) 100%); }
body.stage-3 .environment { background: linear-gradient(180deg, #64748B 0%, var(--bg) 100%); }
body.stage-4 .environment { background: var(--sunrise); }
[data-theme="dark"] body.stage-1 .environment { background: linear-gradient(180deg, #1B4D3E 0%, var(--bg) 100%); }
[data-theme="dark"] body.stage-2 .environment { background: linear-gradient(180deg, #1E293B 0%, var(--bg) 100%); }
[data-theme="dark"] body.stage-3 .environment { background: linear-gradient(180deg, #334155 0%, var(--bg) 100%); }

.scenery { position: absolute; bottom: 0; left: 0; width: 100%; height: 60%; opacity: 0.15; color: var(--primary); }
[data-theme="dark"] .scenery { opacity: 0.3; }

.ascent-nav {
  position: relative; z-index: 10;
  display: flex; justify-content: space-between; align-items: center;
  max-width: 1200px; margin: 0 auto; padding: 24px;
}
.logo { display: flex; align-items: center; gap: 12px; font-weight: 800; font-size: 20px; letter-spacing: -0.5px; text-decoration: none; color: var(--text); }
.logo-icon {
  width: 40px; height: 40px; background: var(--primary); color: #fff;
  border-radius: 12px; display: grid; place-items: center; font-size: 20px; font-weight: 900;
}
[data-theme="dark"] .logo-icon { color: #06120E; }

.icon-btn {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  display: grid; place-items: center; transition: background 0.2s, border-color 0.2s;
  flex-shrink: 0;
}
.icon-btn:hover { border-color: var(--primary); }
.icon-btn svg { width: 20px; height: 20px; }
/* the language control carries a glyph, not an icon (§3.5) */
.lang-mark { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; }
/* the Chinese overlay is applied once the modules load, so a Chinese console does
   not flash English; the bootstrap's timeout reveals the shell if they never run */
html.i18n-pending .app, html.i18n-pending .bottom-nav { visibility: hidden; }

.progress-path {
  position: fixed; left: 40px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: center; z-index: 20;
}
.path-line { width: 2px; height: 48px; background: var(--border); position: relative; }
.path-line::after { content: ''; position: absolute; inset: 0; background: var(--primary); transform: scaleY(0); transform-origin: top; transition: transform 0.6s ease; }
.path-line.active::after { transform: scaleY(1); }
.path-node { width: 16px; height: 16px; border-radius: 50%; background: var(--surface); border: 2px solid var(--border); transition: all 0.3s; }
.path-node.active { background: var(--primary); border-color: var(--primary); box-shadow: 0 0 0 4px rgba(52, 211, 153, 0.25); transform: scale(1.2); }

.ascent-main { position: relative; z-index: 10; display: flex; align-items: center; justify-content: center; padding: 24px 24px 64px; min-height: calc(100vh - 88px); }
.ascent-card {
  width: 100%; max-width: 560px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(24px);
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: 40px;
  box-shadow: var(--shadow);
}
.step { display: none; }
.step.active { display: block; animation: rise 0.5s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

.step-badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(52, 211, 153, 0.12); color: var(--primary);
  padding: 6px 12px; border-radius: 100px;
  font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  margin-bottom: 20px;
}
.step-title { font-size: 30px; font-weight: 800; line-height: 1.15; letter-spacing: -0.8px; margin-bottom: 14px; }
.step-narrative {
  font-size: 15px; line-height: 1.6; color: var(--text-muted); font-style: italic;
  border-left: 3px solid var(--primary); padding-left: 14px; margin-bottom: 26px;
}

.otp-wrap { display: flex; gap: 10px; justify-content: space-between; margin-bottom: 12px; }
.otp-box {
  width: 52px; height: 64px; text-align: center;
  font-size: 26px; font-weight: 800;
  background: var(--surface); border: 2px solid var(--border); border-radius: 14px;
  transition: border-color 0.2s, transform 0.2s, box-shadow 0.2s;
}
.otp-box:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 4px rgba(52, 211, 153, 0.15); transform: translateY(-3px); }
.otp-helper { display: flex; justify-content: space-between; align-items: center; font-size: 13px; color: var(--text-muted); }
.link-btn { background: none; border: none; color: var(--primary); font-weight: 700; text-decoration: underline; min-height: 44px; }
.link-btn:disabled { color: var(--text-muted); text-decoration: none; cursor: not-allowed; }

.debug-banner {
  background: rgba(245, 158, 11, 0.15); border: 1px solid var(--warning);
  border-radius: 12px; padding: 10px 14px; margin-bottom: 16px;
  font-size: 14px; font-weight: 600;
}

.check-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.check-item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px; background: var(--surface);
  border: 2px solid var(--border); border-radius: 12px; cursor: pointer;
  min-height: 48px; transition: border-color 0.2s, background 0.2s;
}
.check-item:hover { border-color: var(--primary); }
.check-item.selected { border-color: var(--primary); background: rgba(52, 211, 153, 0.06); }
.check-item.locked { border-style: dashed; cursor: not-allowed; }
.check-item.locked:hover { border-color: var(--border); }
.check-item.locked .check-box { border-color: var(--text-muted); }
/* the label keeps the muted text token rather than a reduced opacity so the
   §29 contrast census still sees a solid colour */
.check-item.locked .check-label { color: var(--text-muted); }
.check-item input { position: absolute; opacity: 0; }
.check-box {
  width: 20px; height: 20px; border-radius: 6px; border: 2px solid var(--border);
  display: grid; place-items: center; flex-shrink: 0;
}
.check-item.selected .check-box { background: var(--primary); border-color: var(--primary); }
.check-box svg { width: 12px; height: 12px; color: #fff; opacity: 0; }
.check-item.selected .check-box svg { opacity: 1; }
[data-theme="dark"] .check-item.selected .check-box svg { color: #06120E; }
.check-label { font-size: 14px; font-weight: 600; }

/* The paid lookup options are pills (§13.3, §25.3): one rounded control each, the two length
   options being a radio pair so only one can ever be paid for. */
.pill {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 18px 10px 12px; background: var(--surface);
  border: 2px solid var(--border); border-radius: 999px; cursor: pointer;
  min-height: 44px; transition: border-color 0.2s, background 0.2s;
}
.pill:hover { border-color: var(--primary); }
.pill.selected { border-color: var(--primary); background: rgba(52, 211, 153, 0.06); }
.pill input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.pill-dot {
  width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border);
  background: var(--surface); display: grid; place-items: center; flex-shrink: 0;
}
.pill.selected .pill-dot { background: var(--primary); border-color: var(--primary); }
.pill-dot svg { width: 12px; height: 12px; color: #fff; opacity: 0; }
.pill.selected .pill-dot svg { opacity: 1; }
[data-theme="dark"] .pill.selected .pill-dot svg { color: #06120E; }
.pill input:focus-visible ~ .pill-dot { outline: 3px solid var(--primary); outline-offset: 3px; }
.pill-label { font-size: 14px; font-weight: 600; }

.avatar-upload {
  width: 120px; height: 120px; border-radius: 50%;
  background: var(--surface); border: 3px dashed var(--border);
  margin: 0 auto 20px; display: grid; place-items: center;
  cursor: pointer; position: relative; overflow: hidden; transition: border-color 0.2s, transform 0.2s;
}
.avatar-upload:hover { border-color: var(--primary); transform: scale(1.04); }
.avatar-upload svg { width: 32px; height: 32px; color: var(--text-muted); }
.avatar-upload img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.btn-row { display: flex; gap: 14px; margin-top: 28px; }
.btn-row .btn-primary { flex: 1; }

.outro {
  position: fixed; inset: 0; z-index: 100;
  background: var(--primary); color: #fff;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; transition: opacity 0.7s ease, visibility 0.7s;
  text-align: center; padding: 24px;
}
.outro.show { opacity: 1; visibility: visible; }
.outro h1 { font-size: 44px; letter-spacing: -1px; margin-bottom: 12px; }
.outro p { font-size: 17px; opacity: 0.85; }
[data-theme="dark"] .outro { background: #34D399; color: #06120E; }

/* ——— Study Space shell ——— */
.app { display: flex; min-height: 100vh; }
.sidebar {
  width: 260px; flex-shrink: 0;
  background: var(--surface); border-right: 1px solid var(--border);
  padding: 20px 16px; display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; z-index: 60;
}
.sidebar .logo { padding: 4px 12px 20px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
.nav-menu { list-style: none; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 48px; padding: 10px 16px; margin-bottom: 6px;
  border: none; border-radius: 12px; background: transparent;
  color: var(--text-muted); font-weight: 600; font-size: 15px; text-align: left;
  transition: background 0.2s, color 0.2s;
}
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item.active { background: var(--primary); color: #fff; }
[data-theme="dark"] .nav-item.active { color: #0B110E; }
.nav-item svg { width: 20px; height: 20px; flex-shrink: 0; }

.sidebar-footer { padding: 14px; background: var(--surface-2); border-radius: 16px; text-align: center; }
.credit-badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--primary); color: #fff;
  padding: 8px 16px; border-radius: 100px; font-weight: 700; font-size: 14px; margin-bottom: 6px;
}
[data-theme="dark"] .credit-badge { color: #0B110E; }
.credit-text { font-size: 12px; color: var(--text-muted); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.top-bar {
  min-height: 72px; padding: 12px 28px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px);
  position: sticky; top: 0; z-index: 50;
}
.top-id { display: flex; align-items: center; gap: 12px; min-width: 0; }
.top-title {
  font-size: 18px; font-weight: 800; letter-spacing: -0.3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.top-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.top-credits {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 100px; padding: 8px 14px; font-size: 13px; font-weight: 700;
}
/* The initial letter is white in the light theme, so both ends of its gradient
   have to stay dark (§23 contrast); the dark theme keeps the mint gradient and
   turns the letter to ink instead. */
.avatar-chip {
  width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--surface);
  background: linear-gradient(135deg, var(--primary), var(--primary-hover));
  color: #fff; font-weight: 700; display: grid; place-items: center; overflow: hidden;
  flex-shrink: 0;
}
.avatar-chip img { width: 100%; height: 100%; object-fit: cover; }
[data-theme="dark"] .avatar-chip, [data-theme="dark"] .prof-avatar { color: #06120E; }
.menu-toggle { display: none; }

.view-container { padding: 32px; max-width: 1200px; margin: 0 auto; width: 100%; }
.view { display: none; }
.view.active { display: block; animation: rise 0.35s ease; }
.view-title { font-size: 28px; font-weight: 800; letter-spacing: -0.5px; margin-bottom: 6px; }
.view-sub { color: var(--text-muted); margin-bottom: 28px; }

.panel {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow);
}
.empty-state { text-align: center; padding: 56px 24px; color: var(--text-muted); }
.empty-state svg { width: 56px; height: 56px; margin-bottom: 14px; opacity: 0.35; }
.empty-state p { font-size: 15px; line-height: 1.6; }
.stage-note { margin-top: 18px; font-size: 12px; color: var(--text-muted); font-style: italic; }

/* The Terms of Use document (§11.5, §26.15). One reading column, the app's own
   tokens, and a size on every text rule so §29's floor can see it. */
.terms-main { display: flex; justify-content: center; padding: 40px 24px 72px; position: relative; z-index: 10; min-height: calc(100vh - 88px); }
.terms-card { width: 100%; max-width: 660px; }
.terms-date { font-size: 13px; color: var(--text-muted); margin-bottom: 6px; }
.terms-back { display: inline-block; font-size: 14px; color: var(--primary); margin-bottom: 8px; }
.terms-section { margin-top: 28px; }
.terms-num { display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.6px; color: var(--primary); margin-bottom: 4px; }
.terms-section h2 { font-size: 19px; font-weight: 800; letter-spacing: -0.3px; margin-bottom: 12px; }
.terms-section p { font-size: 15px; line-height: 1.7; margin-bottom: 12px; }
.terms-link { color: var(--primary); }
.terms-foot { margin-top: 34px; font-size: 13px; color: var(--text-muted); }

.prof-head { display: flex; align-items: center; gap: 16px; margin-bottom: 22px; }
.prof-avatar {
  width: 64px; height: 64px; border-radius: 50%; overflow: hidden;
  background: linear-gradient(135deg, var(--primary), var(--primary-hover));
  color: #fff; font-size: 24px; font-weight: 700; display: grid; place-items: center;
}
.prof-avatar img { width: 100%; height: 100%; object-fit: cover; }
.prof-name { font-size: 20px; font-weight: 700; }
.prof-email { font-size: 14px; color: var(--text-muted); }
.stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.stat-box { background: var(--surface-2); border-radius: 12px; padding: 14px; text-align: center; }
.stat-val { font-size: 22px; font-weight: 800; color: var(--primary); }
.stat-lbl { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-top: 4px; }
.prof-fields { margin-top: 22px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px 20px; font-size: 14px; }
.prof-fields dt { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
.prof-fields dd { margin: 2px 0 8px; font-weight: 600; }

/* ——— the profile edit form (§18.1.1, §25.5.1): one column at every width,
   because it also has to work in the half-width .prof-cols column ——— */
.prof-edit { margin-top: 22px; display: grid; gap: 16px; }
.prof-field { min-width: 0; }
.prof-field .form-label { margin-bottom: 6px; }
.prof-field .form-input, .prof-field .form-select { width: 100%; }
.prof-edit .check-grid { grid-template-columns: 1fr; gap: 10px; }
.prof-edit .check-item { padding: 12px; }
.prof-locked { font-size: 15px; font-weight: 600; }
.field-note { font-size: 12px; color: var(--text-muted); margin-top: 6px; line-height: 1.5; }
.prof-avatar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.prof-avatar-row .field-note { margin-top: 0; flex: 1 1 180px; }
.phone-row { display: flex; align-items: center; gap: 10px; }
.phone-cc { font-size: 14px; font-weight: 700; color: var(--text-muted); min-width: 40px; }
.phone-row .form-input { flex: 1; min-width: 0; }
.prof-status { min-height: 20px; margin-top: 14px; font-size: 13px; font-weight: 600; }
.prof-status.bad { color: var(--danger); }
.prof-actions { flex-wrap: wrap; }
.prof-actions .btn-primary { flex: 0 0 auto; }

/* ——— the store (§18.3.1, §25.5.1): three equal cards in a row from 720px ——— */
.store-status { min-height: 20px; margin-bottom: 14px; font-size: 14px; font-weight: 600; }
.store-status.bad { color: var(--danger); }
.pkg-row { display: grid; grid-template-columns: 1fr; gap: 16px; }
.pkg-card { display: flex; flex-direction: column; gap: 10px; }
.pkg-label { font-size: 18px; font-weight: 800; }
.pkg-sub { flex: 1; font-size: 13px; line-height: 1.6; color: var(--text-muted); }
.pkg-buy { align-self: flex-start; }
.store-free { margin-top: 18px; font-size: 14px; font-weight: 600; color: var(--text-muted); }
.store-closed {
  margin-top: 14px; padding: 16px; border-radius: 12px;
  background: var(--surface-2); font-size: 14px; line-height: 1.6; color: var(--text-muted);
}
@media (min-width: 720px) {
  .pkg-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.bottom-nav {
  display: none;
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 70;
  background: var(--surface); border-top: 1px solid var(--border);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
}
.bottom-nav button {
  flex: 1; min-height: 56px; border: none; background: transparent;
  color: var(--text-muted); font-size: 11px; font-weight: 700;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.bottom-nav button.active { color: var(--primary); }
.bottom-nav svg { width: 22px; height: 22px; }

.toast {
  position: fixed; bottom: 28px; left: 50%; transform: translate(-50%, 100px);
  background: var(--text); color: var(--bg);
  padding: 14px 22px; border-radius: 100px; font-size: 14px; font-weight: 600;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25); z-index: 200;
  opacity: 0; pointer-events: none; transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.4s;
}
.toast.show { transform: translate(-50%, 0); opacity: 1; }

/* ——— dictionary console (spec §13, §25.3) ——— */
.lookup-panel { margin-bottom: 24px; }
.lookup-field { min-width: 0; }
.lookup-line { display: flex; gap: 14px; align-items: stretch; }
.lookup-line .form-input { flex: 1; min-width: 0; }
.lookup-btn { flex-shrink: 0; padding: 12px 28px; }
.char-count { font-size: 12px; color: var(--text-muted); text-align: right; margin-top: 6px; font-variant-numeric: tabular-nums; }
.char-count.over { color: var(--danger); font-weight: 700; }

.lookup-options { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }

.lookup-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text-muted); font-weight: 600;
}
.lookup-balance { font-variant-numeric: tabular-nums; color: var(--text); }
.lookup-panel .form-error { margin-top: 12px; }

.dict-state { margin-bottom: 24px; }
.dict-state .empty-state { padding: 44px 24px; }
.dict-retry { justify-content: center; margin-top: 4px; }

.spinner {
  display: inline-block; width: 40px; height: 40px; margin-bottom: 16px;
  border: 3px solid var(--border); border-top-color: var(--primary);
  border-radius: 50%; animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.word-card { padding: 32px 28px; }
.word-query { font-size: 13px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; font-weight: 700; }
.word-hanzi { font-size: 52px; font-weight: 700; line-height: 1.15; letter-spacing: 2px; margin: 8px 0 6px; }
/* §13.5's Mandarin line and §13.8's part-of-speech line: one label-and-value shape, so
   the strings of §26.16 read the same on the dictionary card and on the public share page.
   The label column is 112px because "Part of speech" — the longest label — measures
   98.84px at 11px/800 with 0.5px tracking; the 96px it replaced left that label's value
   touching it, which a share-page screenshot showed as "PART OF SPEECHNoun phrase". */
.word-mandarin, .word-pos-line { font-size: 16px; font-weight: 600; margin: 0 0 12px; }
.word-mandarin-label, .word-pos-line-label {
  display: inline-block; min-width: 112px; font-size: 11px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase; color: var(--primary);
}
.word-english { font-size: 19px; color: var(--text); font-weight: 600; margin-bottom: 26px; }

.dialect-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.dialect-box {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 20px;
}
.dialect-name { font-size: 13px; font-weight: 800; color: var(--primary); letter-spacing: 0.3px; margin-bottom: 12px; }
.dialect-hanzi { font-size: 30px; font-weight: 700; letter-spacing: 1px; margin-bottom: 4px; }
.dialect-rom { font-size: 22px; font-weight: 700; }
.dialect-system { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.dialect-example { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); font-size: 14px; line-height: 1.7; }
.dialect-example p:first-child { font-size: 16px; }
.dialect-example p:last-child { color: var(--text-muted); }

.word-cost { margin-top: 22px; font-size: 12px; color: var(--text-muted); font-weight: 600; }

/* ——— notebook (spec §14, §25.4) ——— */
/* §14.9: the search field above the tabs, and the match line under it */
.nb-search { padding: 14px 16px; margin-bottom: 14px; }
.nb-search-line { display: flex; align-items: center; gap: 10px; }
.nb-search-line .form-input { flex: 1; min-width: 0; }
.nb-search-count { margin-top: 10px; font-size: 13px; line-height: 1.5; color: var(--text-muted); }
.nb-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 16px; margin-bottom: 18px;
}
.nb-tabs { display: flex; gap: 8px; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
.nb-tab {
  display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; min-height: 44px;
  padding: 0 16px; background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  color: var(--text-muted); font-size: 14px; font-weight: 600;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
}
.nb-tab:hover { border-color: var(--primary); color: var(--text); }
.nb-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
[data-theme="dark"] .nb-tab.active { color: #0B110E; }
.nb-tab-count {
  min-width: 24px; padding: 1px 7px; border-radius: 999px; background: var(--surface-2);
  color: var(--text); font-size: 12px; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums;
}
/* 0.2 of white is as far as this chip can lighten and still leave the count
   above 4.5:1 against the white text of the active tab (§23) */
.nb-tab.active .nb-tab-count { background: rgba(255, 255, 255, 0.2); color: inherit; }
[data-theme="dark"] .nb-tab.active .nb-tab-count { background: rgba(11, 17, 14, 0.28); }

.nb-tools { position: relative; display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

.nb-form { margin-bottom: 18px; }
.namer-field { display: block; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
.namer-field .form-input { margin-top: 8px; text-transform: none; letter-spacing: 0; font-size: 15px; font-weight: 400; }
.nb-suggest { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.nb-chip {
  min-height: 40px; padding: 8px 14px; background: transparent;
  border: 1px dashed var(--border); border-radius: 999px;
  color: var(--text-muted); font-size: 13px; font-weight: 600;
}
.nb-chip:hover { border-style: solid; border-color: var(--primary); color: var(--primary); }
.namer-btns { display: flex; gap: 12px; margin-top: 20px; }
.namer-btns .btn { min-width: 140px; }

.nb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.nb-card {
  position: relative; padding: 20px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.nb-word { padding-right: 44px; font-size: 26px; font-weight: 700; line-height: 1.25; letter-spacing: 0.5px; }
.nb-card-hanzi { margin-left: 8px; font-size: 20px; color: var(--text-muted); }
.nb-english { margin: 8px 0 14px; font-size: 15px; line-height: 1.5; }
.nb-read { margin-bottom: 6px; font-size: 15px; font-weight: 600; }
.nb-read-label {
  /* 112px, the same column as the dictionary card's labels above: "Part of speech", the
     longest of the card's four labels (§13.8), measures 98.84px, so every value on the
     card starts at the same place with a visible gap after the longest label */
  display: inline-block; min-width: 112px; font-size: 11px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase; color: var(--primary);
}
.nb-move { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.nb-move label { display: flex; align-items: center; gap: 10px; }
.nb-move-label { flex-shrink: 0; font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted); }
.nb-move .form-select { flex: 1; min-width: 0; padding: 10px 12px; font-size: 14px; }

/* §25.4: the card's Record leaves the view, so it reads as an action and stays
   at least 44px high — the .btn-outline floor — at both widths */
.nb-actions { margin-top: 10px; }
.nb-record { width: 100%; justify-content: center; }

.nb-del {
  position: absolute; top: 10px; right: 10px; width: 44px; height: 44px;
  display: grid; place-items: center; background: transparent;
  border: 1px solid transparent; border-radius: 12px; color: var(--text-muted);
  opacity: 0; transition: opacity 0.2s, color 0.2s, border-color 0.2s;
}
.nb-del svg { width: 20px; height: 20px; }
.nb-card:hover .nb-del, .nb-del:focus-visible { opacity: 1; }
.nb-del:hover { border-color: var(--danger); color: var(--danger); }

.nb-confirm { display: none; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.nb-card.confirming .nb-confirm { display: block; }
.nb-confirm p { margin-bottom: 10px; font-size: 14px; font-weight: 700; }
.nb-confirm-btns { display: flex; gap: 10px; }
.nb-confirm-btns .btn { flex: 1; min-height: 44px; padding: 10px 14px; font-size: 14px; }
.nb-btn-danger { background: var(--danger); color: #fff; }
.nb-btn-danger:hover:not(:disabled) { background: var(--danger); opacity: 0.88; }
.nb-btn-quiet { background: transparent; border: 1px solid var(--border); color: var(--text-muted); }
.nb-btn-quiet:hover:not(:disabled) { border-color: var(--text-muted); color: var(--text); }

/* the word control under the dictionary card: the group select of §14.4 and the
   part-of-speech select of §13.8 side by side, with the kept-word line under them */
.word-actions { position: relative; display: flex; flex-direction: column; margin-top: 22px; }
.word-selects { display: flex; gap: 12px; flex-wrap: wrap; }
.word-group, .word-pos { flex: 1 1 200px; display: flex; align-items: center; gap: 10px; min-width: 0; }
.word-group-label, .word-pos-label {
  flex-shrink: 0; font-size: 11px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted);
}
.word-selects .form-select { flex: 1; min-width: 0; padding: 10px 12px; font-size: 14px; }
.word-kept-note { margin-top: 10px; font-size: 13px; line-height: 1.5; color: var(--text-muted); }

/* ——— menus ——— */
.menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; min-width: 240px;
  padding: 8px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: var(--shadow); text-align: left;
}
.menu-title {
  padding: 8px 10px 6px; font-size: 12px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted);
}
.menu-note { padding: 0 10px 8px; font-size: 13px; line-height: 1.5; color: var(--text-muted); }
.menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%;
  min-height: 44px; padding: 10px 12px; background: transparent; border: none; border-radius: 10px;
  color: var(--text); font-size: 14px; font-weight: 600; text-align: left;
}
.menu-item:hover:not(:disabled) { background: var(--surface-2); }
.menu-danger { color: var(--danger); }

/* ——— responsive (spec §8.3, §25) ——— */
/* ——— Voice booth (§15, §26.11) ——— */
.booth { display: flex; flex-direction: column; gap: 14px; }
.booth-title { font-size: 20px; font-weight: 700; }
.booth-sub { color: var(--text-muted); font-size: 14px; margin-top: 2px; }
.booth-word { font-size: 26px; font-weight: 700; }
.booth-slot { display: flex; flex-direction: column; gap: 8px; }
.booth-slot-label {
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}
.booth-slot-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px dashed var(--border); border-radius: 12px;
  min-height: 60px;
}
.booth-slot-row audio { height: 40px; flex: 1 1 180px; min-width: 140px; }
.booth-meta { font-size: 13px; color: var(--text-muted); }
.booth-empty { font-style: italic; }
.booth-live { color: var(--danger); font-weight: 600; }
.booth-danger { color: var(--danger); }
.booth-msg { font-size: 14px; color: var(--danger); min-height: 20px; }
.booth-actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* the created link stays on screen after the copy, so a refused clipboard is
   still recoverable (§16.4.1) */
.booth-link { display: flex; gap: 10px; align-items: center; }
.booth-link-url { flex: 1; min-width: 0; font-size: 13px; }

/* ——— Grading (§17, §25.5, §26.9.1) ——— */
.panel-title { font-size: 20px; font-weight: 700; }
.panel-sub { color: var(--text-muted); font-size: 14px; margin-top: 2px; }
/* §25.5: the profile card and the queue side by side on a desktop, stacked on a phone */
.prof-cols { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: start; }
@media (min-width: 1024px) {
  .prof-cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.grade-panel { display: flex; flex-direction: column; gap: 12px; }
.grade-list { display: flex; flex-direction: column; gap: 12px; }
.grade-row {
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 12px;
}
.grade-row-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.grade-query { font-size: 18px; font-weight: 700; }
.grade-hanzi { font-size: 18px; font-weight: 700; letter-spacing: 1px; }
.grade-status {
  font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  padding: 4px 10px; border-radius: 999px; background: var(--surface-2); color: var(--text-muted);
}
.grade-status.graded { color: var(--primary); }
.grade-date { font-size: 13px; color: var(--text-muted); }
.grade-row audio { width: 100%; height: 40px; }
.grade-score { font-size: 15px; font-weight: 700; }
.grade-fb-label {
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}
.grade-fb { font-size: 14px; line-height: 1.7; }
.grade-empty { font-size: 14px; color: var(--text-muted); font-style: italic; }

/* the ask, inside the booth (§17.3.1) */
.grade-ask {
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface-2);
}
.grade-ask-title { font-size: 17px; font-weight: 700; }
.grade-ask-takes { display: flex; flex-direction: column; gap: 10px; }
.grade-ask-take { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.grade-ask-take audio { height: 40px; flex: 1 1 180px; min-width: 140px; }
.grade-ask-btns { display: flex; gap: 10px; flex-wrap: wrap; }

/* the teacher's view: one card per row, never wider than 720px (§25.5) */
.grade-cards { display: flex; flex-direction: column; gap: 16px; max-width: 720px; }
.grade-card { display: flex; flex-direction: column; gap: 14px; }
.grade-card-name { font-size: 18px; font-weight: 700; }
.grade-card .word-hanzi { font-size: 34px; }
.grade-card .word-english { margin-bottom: 18px; }
.grade-card audio { width: 100%; height: 40px; }
.grade-no-take { font-size: 14px; color: var(--text-muted); font-style: italic; }
.grade-fields { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 14px; align-items: start; }
.grade-field { display: flex; flex-direction: column; gap: 6px; }
.grade-fb-input { resize: vertical; min-height: 76px; font: inherit; }

@media (max-width: 1024px) {
  .progress-path { display: none; }
}
@media (max-width: 640px) {
  .sidebar {
    position: fixed; left: 0; top: 0; bottom: 0; height: 100vh;
    transform: translateX(-100%); transition: transform 0.3s ease;
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15);
  }
  .sidebar.open { transform: translateX(0); }
  .menu-toggle { display: grid; }
  .bottom-nav { display: flex; }
  .view-container { padding: 20px 16px 96px; }
  .top-bar { padding: 10px 16px; }
  .ascent-card { padding: 28px 20px; border-radius: 20px; }
  .step-title { font-size: 24px; }
  .check-grid { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .otp-box { width: 44px; height: 56px; font-size: 22px; }
  .stats-row { grid-template-columns: 1fr 1fr; }
  .prof-fields { grid-template-columns: 1fr; }
  .btn-block-mobile { width: 100%; }
  /* §25.3: search input and lookup button full width, card and dialect boxes stack */
  .lookup-line { flex-direction: column; }
  .lookup-btn { width: 100%; }
  .dialect-row { grid-template-columns: 1fr; }
  .word-card { padding: 24px 20px; }
  .word-hanzi { font-size: 40px; }
  .lookup-meta { flex-direction: column; align-items: flex-start; gap: 6px; }
  /* §25.4: single column cards, group tabs scroll sideways, delete visible on tap */
  .nb-grid { grid-template-columns: 1fr; }
  .nb-toolbar { flex-direction: column; align-items: stretch; padding: 12px; }
  .nb-tools { justify-content: flex-end; }
  .nb-del { opacity: 1; }
  .nb-card { padding: 18px 16px; }
  .nb-word { font-size: 24px; }
  /* §25.3: the two selects go full width, one under the other */
  .word-selects { flex-direction: column; }
  .word-actions .nb-save { width: 100%; }
  .namer-btns { flex-direction: column; }
  .namer-btns .btn { width: 100%; min-width: 0; }
  /* the booth rows stack: player, then its measure, then its buttons */
  .booth-slot-row { flex-direction: column; align-items: stretch; }
  .booth-slot-row audio { min-width: 0; width: 100%; }
  .booth-slot-row .btn { width: 100%; }
  .booth-link { flex-direction: column; align-items: stretch; }
  .booth-link .btn { width: 100%; }
  /* two buttons now share the action row, so they stack like the save control */
  .booth-actions { flex-direction: column; align-items: stretch; }
  .booth-actions .btn { width: 100%; }
  /* §25.5: the ask stacks, and the teacher's fields go full width */
  .grade-ask-take { flex-direction: column; align-items: stretch; }
  .grade-ask-take audio { min-width: 0; width: 100%; }
  .grade-ask-take .btn { width: 100%; }
  .grade-ask-btns { flex-direction: column; }
  .grade-ask-btns .btn { width: 100%; }
  .grade-fields { grid-template-columns: 1fr; }
  .grade-card { padding: 24px 20px; }
}

/* Narrow phones: the header carries the menu button, the title, the credit chip, the theme
   button and the avatar on one line, so it is the first thing to run out of room (§8.3
   "compact header"). The chip keeps its number and drops the word; tap targets stay 44px. */
@media (max-width: 480px) {
  .top-bar { gap: 8px; padding: 10px 12px; }
  .top-title { font-size: 15px; }
  .top-actions { gap: 8px; }
  .top-credits { padding: 8px 12px; font-size: 12px; }
  .top-credits .chip-word { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
