:root {
  /* Leitner logo palette - bulb gradient + ink from Linearity exports */
  --brand: #365fcf;
  --brand-hover: #2a4eb5;
  --brand-bright: #5b9aff;
  --brand-deep: #2849a8;
  --brand-soft: rgba(54, 95, 207, 0.1);
  --brand-ring: rgba(54, 95, 207, 0.22);
  --brand-glow: rgba(91, 154, 255, 0.28);
  --brand-gradient: linear-gradient(165deg, var(--brand-bright) 0%, var(--brand) 48%, var(--brand-deep) 100%);
  --growth: #3a9e62;
  --growth-soft: rgba(58, 158, 98, 0.12);
  --ink: #231f20;
  --bg: #f2f4fa;
  --surface: #ffffff;
  --surface-2: #f8f9fd;
  --surface-glass: rgba(255, 255, 255, 0.74);
  --surface-glass-strong: rgba(255, 255, 255, 0.9);
  --text: var(--ink);
  --text-secondary: #5c5c62;
  --text-tertiary: #7a7a82;
  --success: #248a3d;
  --success-soft: rgba(36, 138, 61, 0.1);
  --error: #d70015;
  --error-soft: rgba(215, 0, 21, 0.08);
  --border: rgba(54, 95, 207, 0.08);
  --border-strong: rgba(54, 95, 207, 0.16);
  --shadow-sm: 0 2px 10px rgba(54, 95, 207, 0.06);
  --shadow-md: 0 10px 32px rgba(54, 95, 207, 0.09);
  --shadow-lg: 0 22px 56px rgba(54, 95, 207, 0.12);
  --shadow-brand: 0 8px 28px rgba(54, 95, 207, 0.18);
  --radius: 24px;
  --radius-sm: 16px;
  --radius-xs: 12px;
  --font: "Inter", -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
  --ease: cubic-bezier(0.25, 0.1, 0.25, 1);

  /*
   * Match ↔ Study flag hop (locked 2026-07-28 · founder):
   * One top-pad + flag-row seat so the language mark does not jump.
   * Overridden at narrow / wide / coarse — both surfaces must use these vars.
   */
  --study-mid-shell-pad-top: 0.78rem;
  --study-mid-flag-row: 2.15rem;
  --study-mid-flag-seat: 2.15rem;
  --study-mid-flag-band-mb: 0.48rem;

  /* Type scale - keep secondary UI on the same steps */
  --text-lg: 1.05rem;
  --text-md: 0.95rem;
  --text-sm: 0.88rem;
  --text-xs: 0.78rem;
  --text-2xs: 0.68rem;
  --lh-tight: 1.3;
  --lh-body: 1.45;

  /* Chips / pills (filters, meta, related pairs) */
  --chip-font: 0.84rem;
  --chip-pad-y: 0.4rem;
  --chip-pad-x: 0.85rem;
  --chip-radius: 999px;
  --chip-min-h: 2.05rem;

  /* Status pills that show a short result (gloss, review match) */
  --status-font: 0.95rem;
  --status-pad-y: 0.4rem;
  --status-pad-x: 0.85rem;
  --status-min-h: 2.15rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  color-scheme: light;
  width: 100%;
  max-width: 100%;
  /* Kill grey WebKit tap flash (double-flash with :active / selected paint) */
  -webkit-tap-highlight-color: transparent;
  /*
   * Single scrollport model (critical for Mac trackpad on Safari):
   * html is a fixed viewport shell; body is THE scroller.
   * Keyboard often scrolls the document even when trackpad wheel fails if
   * overflow lives only on html — two-finger scroll targets body instead.
   */
  height: 100%;
  height: 100dvh;
  overflow: hidden;
}

body {
  margin: 0;
  /* Fill the html shell; content taller than this scrolls *inside* body */
  height: 100%;
  height: 100dvh;
  width: 100%;
  max-width: 100%;
  font-family: var(--font);
  background:
    radial-gradient(ellipse 85% 50% at 50% -10%, var(--brand-glow), transparent 70%),
    radial-gradient(ellipse 55% 42% at 100% 18%, rgba(54, 95, 207, 0.07), transparent 68%),
    radial-gradient(ellipse 45% 35% at 0% 62%, rgba(91, 154, 255, 0.05), transparent 72%),
    var(--bg);
  color: var(--text);
  line-height: 1.47059;
  letter-spacing: -0.022em;
  position: relative;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Body is THE page scrollport — kill edge rubber-band (Cards / Path / Study). */
  overscroll-behavior: none;
}

/* Ambient brand - soft glow */
.ambient-brand {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}

.ambient-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(72px);
}

.ambient-glow--primary {
  width: min(78vw, 720px);
  height: min(78vw, 720px);
  right: -18%;
  top: 6%;
  background: radial-gradient(circle, var(--brand-glow) 0%, transparent 68%);
}

.ambient-glow--secondary {
  width: min(52vw, 480px);
  height: min(52vw, 480px);
  left: -14%;
  bottom: 8%;
  background: radial-gradient(circle, rgba(54, 95, 207, 0.11) 0%, transparent 70%);
}

@media (max-width: 720px) {
  .ambient-glow--primary {
    width: 95vw;
    height: 95vw;
    right: -35%;
    top: 2%;
  }
}

.app {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: min(780px, 100%);
  margin: 0 auto;
  padding: 2.5rem 1.5rem 3rem;
  /* Fill the window when short; grow with long tabs (Cards / Path) */
  min-height: 100dvh;
  min-height: 100svh;
  height: auto;
  display: flex;
  flex-direction: column;
  overflow: visible;
  box-sizing: border-box;
}

main,
.panel {
  max-width: 100%;
  min-width: 0;
}

main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  /*
   * min-height: auto (not 0): document scroll for Cards/Path on Safari.
   * Nested scroll modes (e.g. mobile Read) set min-height: 0 explicitly.
   */
  min-height: auto;
  height: auto;
  overflow: visible;
}

/* Header */
.header {
  margin-bottom: 2.5rem;
  text-align: center;
}






.brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1.35rem;
}

.brand-logo {
  display: block;
  width: min(300px, 78vw);
  height: auto;
  margin: 0 auto 0.5rem;
  object-fit: contain;
  /* Header master = logo-primary-dense.png (hires lockup from founding master). No soft blur on the mark. */
  /* No width transition: layout animation jerked on mobile GPUs. */
  filter: none;
}

.category-picker {
  position: relative;
  margin: 0 0 0.35rem;
}

/*
 * Path prefs — one visual system (grid, not free wrap).
 * Order (B): [ 🇳🇴 ] [ Basics … ] [ About ] ··· [ Female|Male ]
 * Shared: pill height, border, surface, type scale, hover/focus.
 */
.progress-prefs {
  --prefs-h: 2.35rem;
  --prefs-pad-x: 0.72rem;
  --prefs-font: 0.76rem;
  --prefs-gap: 0.45rem;
  display: grid;
  /* lang · Basics · About | spacer | voice */
  grid-template-columns: auto minmax(0, max-content) auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--prefs-gap);
  row-gap: 0.45rem;
  width: 100%;
  /* Quiet handoff into volume glance */
  margin: 0 0 0.62rem;
  min-height: var(--prefs-h);
  box-sizing: border-box;
  overscroll-behavior: none;
  touch-action: manipulation;
}

.progress-prefs > .category-picker--progress {
  grid-column: 1;
  grid-row: 1;
}

.progress-prefs > .progress-basics-btn {
  grid-column: 2;
  grid-row: 1;
  justify-self: start;
  min-width: 0;
}

.progress-prefs > .progress-about-btn {
  grid-column: 3;
  grid-row: 1;
  justify-self: start;
}

.progress-prefs > .progress-voice {
  grid-column: 5;
  grid-row: 1;
  justify-self: end;
  margin-left: 0;
}

.category-picker--progress {
  position: relative;
  flex: 0 0 auto;
  margin: 0;
  /* Menu is wider than the closed chip - never clip the open list */
  overflow: visible;
}

.category-picker--progress:has(.category-picker-btn[aria-expanded="true"]),
.category-picker--progress:has(.category-picker-menu:not(.hidden)) {
  z-index: 55;
}


.category-picker--progress .category-picker-menu {
  left: 0;
  right: auto;
  transform: none;
  /*
   * Open list: same size on mobile + desktop (flag + full names).
   * Fixed width - never inherit the closed chip (flag-only on phone).
   * Longest labels: Portuguese, Norwegian, Italian…
   * max-height is a fallback only — openCategoryMenu fits remaining viewport
   * (and uses position:fixed so the list is never clipped by the page).
   */
  width: 14rem;
  min-width: 14rem;
  max-width: min(14rem, calc(100vw - 1.25rem));
  /* Elegant fold — same bar as Cards/Stories (JS fits remaining viewport) */
  max-height: min(22rem, 50dvh);
  z-index: 40;
  box-sizing: border-box;
  overflow-x: hidden;
  overflow-y: hidden;
}

.category-picker--progress .category-picker-menu.is-open-up {
  top: auto;
  bottom: calc(100% + 0.45rem);
}

/*
 * Language - same neutral pill as Basics / About in this row.
 * Must beat the later .category-picker-btn blue chip (same specificity, later in file).
 */
.category-picker-btn.category-picker-btn--progress {
  min-width: 0;
  min-height: var(--prefs-h);
  height: var(--prefs-h);
  /* Room for longest language names on desktop (menu is separate on mobile) */
  max-width: min(13.5rem, 52vw);
  padding: 0 0.55rem 0 0.5rem;
  gap: 0.35rem;
  justify-content: flex-start;
  align-items: center;
  text-transform: none;
  letter-spacing: -0.01em;
  font-size: var(--prefs-font);
  font-weight: 600;
  /* >1 so descenders in “Norwegian” (g) / other names aren’t clipped */
  line-height: 1.25;
  color: var(--text-secondary);
  background: var(--surface-glass-strong);
  border: 1px solid var(--border-strong);
  box-shadow: none;
  overflow: visible;
  transition:
    color 0.15s var(--ease, ease),
    background 0.15s var(--ease, ease),
    border-color 0.15s var(--ease, ease),
    box-shadow 0.15s var(--ease, ease);
}

/* Open menu = intentional selected look; focus fill only with fine pointer */
.category-picker-btn.category-picker-btn--progress[aria-expanded="true"] {
  color: var(--brand-deep);
  background: var(--brand-soft);
  border-color: transparent;
  outline: none;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) {
  .category-picker-btn.category-picker-btn--progress:hover {
    color: var(--brand-deep);
    background: var(--brand-soft);
    border-color: transparent;
    outline: none;
    box-shadow: none;
  }

  .category-picker-btn.category-picker-btn--progress:focus-visible {
    color: var(--brand-deep);
    background: var(--brand-soft);
    border-color: transparent;
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
  }
}

/* Brief attention after a language switch - not a permanent selected look */
.category-picker-btn.category-picker-btn--progress.is-flashing {
  color: var(--brand-deep);
  background: var(--brand-soft);
  border-color: transparent;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

.category-picker-btn.category-picker-btn--progress .category-flag {
  font-size: 1.12rem;
}

.category-picker-lang {
  min-width: 0;
  flex: 1 1 auto;
  white-space: nowrap;
  /* Horizontal ellipsis only - line-height gives vertical room for g/y/p */
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
  line-height: 1.3;
  /* Prevent the flex line box from shaving font descenders */
  padding-block: 0.08em 0.12em;
  box-sizing: content-box;
}

.category-picker-btn.category-picker-btn--progress .category-picker-chevron {
  flex-shrink: 0;
  opacity: 0.55;
}

.category-flag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  line-height: 1;
}

.category-option-flag {
  flex-shrink: 0;
  font-size: 1.2rem;
  line-height: 1;
  /* Don’t force a tight box that crops flag emoji */
  width: auto;
  min-width: 1.5rem;
  text-align: center;
  overflow: visible;
}

/* Higher specificity so later .category-option { column } cannot stack flag over name */
.category-option.category-option--compact {
  flex-direction: row;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.75rem;
  width: 100%;
  box-sizing: border-box;
  /* Allow the row to define menu content width; don’t collapse labels */
  min-width: min-content;
  overflow: visible;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Basics (learning) + About (meta) — About quieter (Pa4) */
.progress-basics-btn,
.progress-about-btn {
  appearance: none;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.38rem;
  min-height: var(--prefs-h);
  height: var(--prefs-h);
  padding: 0 var(--prefs-pad-x);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--prefs-font);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  text-decoration: none;
  line-height: 1.25;
  white-space: nowrap;
  cursor: pointer;
  touch-action: manipulation;
  box-shadow: none;
  overflow: visible;
  transition:
    color 0.15s var(--ease),
    background 0.15s var(--ease),
    border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease),
    transform 0.12s ease;
}

/* Pa1: Basics is a learning control — solid hit target */
.progress-basics-btn {
  padding: 0 0.72rem 0 0.78rem;
  max-width: min(12.5rem, 52vw);
  font-weight: 650;
}

/* Pa4: About is tertiary meta in the prefs row */
.progress-about-btn {
  font-weight: 550;
  font-size: calc(var(--prefs-font) * 0.96);
  color: var(--text-tertiary);
  border-color: color-mix(in srgb, var(--border-strong) 75%, transparent);
  background: transparent;
}

.progress-basics-kicker {
  flex-shrink: 0;
  font-size: inherit;
  font-weight: 600;
  letter-spacing: inherit;
  color: inherit;
}

.progress-basics-glyphs {
  flex-shrink: 1;
  min-width: 0;
  /* Slightly smaller than before so æøå fit the pill height cleanly */
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  /* Room for descenders (æ, g, y, å) - line-height:1 + overflow was clipping bottoms */
  line-height: 1.35;
  color: var(--brand-deep);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-feature-settings: "kern" 1;
  /* Tiny vertical slack so glyphs aren’t hard-clipped by the flex line box */
  padding-block: 0.06em;
  box-sizing: content-box;
}

.progress-basics-btn:focus-visible .progress-basics-glyphs {
  color: var(--brand);
}
@media (hover: hover) and (pointer: fine) {
  .progress-basics-btn:hover .progress-basics-glyphs {
    color: var(--brand);
  }
}

/* Soft fill only with cursor / keyboard on fine pointer — not after a finger tap */
@media (hover: hover) and (pointer: fine) {
  .progress-basics-btn:hover,
  .progress-about-btn:hover,
  .progress-basics-btn:focus-visible,
  .progress-about-btn:focus-visible {
    color: var(--brand-deep);
    background: var(--brand-soft);
    border-color: transparent;
    outline: none;
  }

  .progress-basics-btn:focus-visible,
  .progress-about-btn:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
  }
}

/* Press: quiet opacity only — scale read as rubber-band on Path */
.progress-basics-btn:active,
.progress-about-btn:active {
  transform: none;
  opacity: 0.88;
}

/* Voice - same height as chips; grid places it in the settings cluster */

@media (min-width: 721px) and (max-width: 900px) {
  .progress-prefs {
    --prefs-gap: 0.35rem;
    --prefs-font: 0.72rem;
  }

  .category-picker-btn.category-picker-btn--progress {
    max-width: min(9.5rem, 36vw);
  }
}

.category-picker--welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 1rem;
}

.category-picker--welcome .category-picker-menu {
  z-index: 210;
}

/* Full-screen ceremony when switching language / learning track */
.track-switch-overlay {
  position: fixed;
  inset: 0;
  z-index: 10040;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s var(--ease, ease);
}

.track-switch-overlay.is-visible {
  opacity: 1;
  pointer-events: none;
}

.track-switch-overlay.hidden {
  display: none;
}

.track-switch-veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      120% 80% at 50% 42%,
      color-mix(in srgb, var(--brand, #365fcf) 34%, transparent) 0%,
      rgba(18, 24, 38, 0.42) 42%,
      rgba(12, 16, 28, 0.72) 100%
    );
  backdrop-filter: blur(14px) saturate(1.15);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
}

/*
 * Portal ceremony: opaque cover + instant appear (never semi-transparent fade-in —
 * Review must not flash under the music). Colors stay fully opaque; weight is
 * dialed via depth of navy + brand glow, not alpha.
 * First entry (is-welcome-enter) keeps a slightly richer veil; mid-session is cooler.
 */
.track-switch-overlay.is-welcome-portal {
  transition: none;
  background:
    radial-gradient(
      130% 90% at 50% 38%,
      #141c2e 0%,
      #0e1422 52%,
      #0a0e18 100%
    );
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter {
  background:
    radial-gradient(
      130% 90% at 50% 38%,
      color-mix(in srgb, var(--brand, #365fcf) 14%, #161e32) 0%,
      #101624 50%,
      #0a0e18 100%
    );
}

.track-switch-overlay.is-welcome-portal.is-visible {
  opacity: 1;
}

/* Soft fade-out only when the ceremony ends */
.track-switch-overlay.is-welcome-portal.is-leaving {
  transition: opacity 0.4s var(--ease, ease);
  opacity: 0;
}

.track-switch-overlay.is-welcome-portal .track-switch-veil {
  background:
    radial-gradient(
      120% 80% at 50% 42%,
      color-mix(in srgb, var(--brand, #365fcf) 22%, #141c2e) 0%,
      #121a2a 50%,
      transparent 100%
    );
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-veil {
  background:
    radial-gradient(
      120% 80% at 50% 42%,
      color-mix(in srgb, var(--brand, #365fcf) 32%, #161e32) 0%,
      color-mix(in srgb, var(--brand, #365fcf) 8%, #121a2a) 48%,
      transparent 100%
    );
}

.track-switch-overlay-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  width: min(100%, 20.5rem);
  padding: 1.85rem 1.6rem 1.7rem;
  border-radius: 1.35rem;
  border: 1px solid color-mix(in srgb, var(--brand, #365fcf) 28%, white);
  background:
    linear-gradient(
      160deg,
      color-mix(in srgb, white 94%, var(--brand, #365fcf)) 0%,
      color-mix(in srgb, var(--surface-glass-strong, #fff) 88%, var(--brand, #365fcf) 12%) 100%
    );
  box-shadow:
    0 0 0 1px color-mix(in srgb, white 55%, transparent) inset,
    0 18px 50px rgba(18, 24, 38, 0.28),
    0 0 60px color-mix(in srgb, var(--brand, #365fcf) 28%, transparent);
  text-align: center;
  transform: translateY(0.55rem) scale(0.94);
  opacity: 0.88;
  transition:
    transform 0.42s cubic-bezier(0.2, 0.85, 0.25, 1),
    opacity 0.32s ease;
}

.track-switch-overlay.is-visible .track-switch-overlay-inner {
  transform: translateY(0) scale(1);
  opacity: 1;
}

.track-switch-logo-wrap {
  position: relative;
  width: 5.5rem;
  height: 5.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.track-switch-logo-bloom {
  position: absolute;
  inset: -18%;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--brand, #365fcf) 45%, transparent) 0%,
    color-mix(in srgb, var(--brand, #365fcf) 12%, transparent) 48%,
    transparent 72%
  );
  opacity: 0.35;
  transform: scale(0.7);
}

.track-switch-logo-ring {
  position: absolute;
  inset: 0.15rem;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--brand, #365fcf) 35%, transparent);
  opacity: 0;
  transform: scale(0.75);
}

.track-switch-logo {
  position: relative;
  z-index: 1;
  width: 3.35rem;
  height: auto;
  display: block;
  transform: scale(0.72) translateY(0.2rem);
  opacity: 0.55;
  filter: drop-shadow(0 8px 16px color-mix(in srgb, var(--brand, #365fcf) 28%, transparent));
}

.track-switch-overlay.is-visible .track-switch-logo {
  animation: track-switch-logo-in 0.95s cubic-bezier(0.2, 0.9, 0.25, 1) forwards;
}

.track-switch-overlay.is-visible .track-switch-logo-bloom {
  animation: track-switch-bloom 1.05s cubic-bezier(0.2, 0.85, 0.25, 1) forwards;
}

.track-switch-overlay.is-visible .track-switch-logo-ring {
  animation: track-switch-ring 1.05s cubic-bezier(0.15, 0.85, 0.25, 1) forwards;
}

.track-switch-overlay-flag {
  margin: 0.15rem 0 0;
  font-size: clamp(2.35rem, 8vw, 3rem);
  line-height: 1;
  filter: drop-shadow(0 6px 14px rgba(18, 24, 38, 0.18));
  opacity: 0;
  transform: scale(0.72) translateY(0.35rem);
}

.track-switch-overlay.is-visible .track-switch-overlay-flag:not([hidden]) {
  animation: track-switch-flag-in 0.75s cubic-bezier(0.2, 0.9, 0.25, 1) 0.12s forwards;
}

.track-switch-overlay-name {
  margin: 0;
  max-width: 100%;
  font-size: clamp(1.45rem, 5.2vw, 1.9rem);
  font-weight: 750;
  letter-spacing: -0.035em;
  color: var(--ink, #121826);
  line-height: 1.15;
  opacity: 0;
  transform: translateY(0.45rem);
}

.track-switch-overlay.is-visible .track-switch-overlay-name {
  animation: track-switch-name-in 0.7s cubic-bezier(0.2, 0.85, 0.25, 1) 0.22s forwards;
}

/* First-run: a touch more presence (still calm) */
.track-switch-overlay.is-welcome-enter .track-switch-overlay-inner {
  width: min(100%, 21.5rem);
  padding: 2rem 1.75rem 1.85rem;
  gap: 1.05rem;
  box-shadow:
    0 0 0 1px color-mix(in srgb, white 55%, transparent) inset,
    0 22px 60px rgba(18, 24, 38, 0.32),
    0 0 80px color-mix(in srgb, var(--brand, #365fcf) 34%, transparent);
}

.track-switch-overlay.is-welcome-enter .track-switch-logo-wrap {
  width: 6rem;
  height: 6rem;
  transition: opacity 0.45s var(--ease, ease), transform 0.45s var(--ease, ease);
}

.track-switch-overlay.is-welcome-enter .track-switch-logo {
  width: 3.6rem;
}

.track-switch-overlay.is-welcome-enter .track-switch-overlay-name {
  font-size: clamp(1.55rem, 5.6vw, 2.05rem);
}

/*
 * Portal music ceremony - calm & accessible.
 * No screen flashes, ripples, or large luminance strobes (photosensitive-seizure safe).
 * Soft scale on the beat only; logo hands off gently to the language flag.
 *
 * Craft package 1 (2026-07-26): full-bleed navy stage — mark + flag + name on the
 * field. No light floating card (that read as a second modal on the ceremony room).
 */
.track-switch-overlay.is-welcome-portal .track-switch-overlay-inner,
.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-overlay-inner {
  position: relative;
  /* Fixed stage height so logo→flag phase does not re-center the ceremony */
  min-height: min(22rem, 58dvh);
  justify-content: center;
  gap: 1.05rem;
  width: min(100%, 22rem);
  padding: 1.25rem 1rem 1.5rem;
  border: none;
  background: transparent;
  box-shadow: none;
  /* Instant presence on opaque cover — no card scale-in */
  transform: none;
  opacity: 1;
  box-sizing: border-box;
}

.track-switch-overlay.is-welcome-portal.is-visible .track-switch-overlay-inner {
  transform: none;
  opacity: 1;
}

.track-switch-stage {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
}

/* Portal stage scale + P4 (~+10%): fuller decals on full-bleed navy */
.track-switch-overlay.is-welcome-portal .track-switch-stage {
  height: 9.6rem;
  flex-direction: row;
  gap: 0;
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-stage {
  height: 10.45rem;
}

.track-switch-overlay-kicker {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink, #121826) 55%, var(--brand, #365fcf));
  opacity: 0;
  transform: translateY(0.2rem);
}

/* Portal: hide normal flag entrance; logo owns phase 1 */
.track-switch-overlay.is-welcome-portal.is-visible .track-switch-overlay-flag:not([hidden]) {
  animation: none;
}

.track-switch-overlay.is-welcome-portal .track-switch-logo-wrap {
  position: relative;
  z-index: 2;
  width: 8.5rem;
  height: 8.5rem;
  transition:
    opacity 0.55s cubic-bezier(0.25, 0.8, 0.25, 1),
    transform 0.55s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-logo-wrap {
  width: 9.35rem;
  height: 9.35rem;
}

.track-switch-overlay.is-welcome-portal .track-switch-logo {
  width: 5.65rem;
  /* White mark on navy — soft brand bloom, no card-era blue plate shadow */
  filter: drop-shadow(0 12px 32px rgba(54, 95, 207, 0.38));
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-logo {
  width: 6.2rem;
}

.track-switch-overlay.is-welcome-portal .track-switch-logo-bloom {
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--brand, #365fcf) 55%, transparent) 0%,
    color-mix(in srgb, var(--brand, #365fcf) 14%, transparent) 48%,
    transparent 72%
  );
  opacity: 0.45;
}

.track-switch-overlay.is-welcome-portal .track-switch-logo-ring {
  border-color: color-mix(in srgb, white 22%, transparent);
}

.track-switch-overlay.is-welcome-portal .track-switch-overlay-flag {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  transform: translate(-50%, -50%) scale(0.72);
  margin: 0;
  font-size: clamp(3.7rem, 14vw, 5.05rem);
  opacity: 0;
  pointer-events: none;
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.28));
  transition:
    opacity 0.55s cubic-bezier(0.25, 0.8, 0.25, 1),
    transform 0.55s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter .track-switch-overlay-flag {
  font-size: clamp(4.15rem, 15vw, 5.65rem);
  filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.32));
}

.track-switch-overlay.is-welcome-portal .track-switch-overlay-kicker {
  display: block;
}

/* Optional: hide "Now learning" while keeping flag + language name */
.track-switch-overlay.is-welcome-portal.is-hide-kicker .track-switch-overlay-kicker {
  display: none !important;
}

.track-switch-overlay.is-welcome-portal .track-switch-overlay-name {
  color: #fff;
  letter-spacing: -0.03em;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.28);
  transition:
    opacity 0.45s ease,
    transform 0.45s ease,
    font-size 0.45s ease;
}

/*
 * P3 · Name timing: phase 1 mark owns the stage (name fully quiet).
 * Phase 2: name firms with the flag. Same type size reserved so layout does not jump.
 */
.track-switch-overlay.is-welcome-portal:not(.is-phase-language) .track-switch-overlay-name {
  opacity: 0;
  visibility: hidden;
  font-size: clamp(2.1rem, 7vw, 2.65rem);
  min-height: 1.15em;
  color: #fff;
}

.track-switch-overlay.is-welcome-portal.is-welcome-enter:not(.is-phase-language) .track-switch-overlay-name {
  opacity: 0;
  visibility: hidden;
  font-size: clamp(2.1rem, 7vw, 2.65rem);
  min-height: 1.15em;
}

.track-switch-overlay.is-welcome-portal:not(.is-phase-language) .track-switch-overlay-kicker {
  opacity: 0;
}

/* Phase 2 - gentle handoff (no flash / blur / spin) */
.track-switch-overlay.is-welcome-portal.is-phase-language .track-switch-logo-wrap {
  opacity: 0;
  transform: scale(0.88);
  pointer-events: none;
}

.track-switch-overlay.is-welcome-portal.is-phase-language .track-switch-overlay-flag:not([hidden]) {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.track-switch-overlay.is-welcome-portal.is-phase-language .track-switch-overlay-kicker {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 0.5s ease 0.08s,
    transform 0.5s ease 0.08s;
}

.track-switch-overlay.is-welcome-portal.is-phase-language .track-switch-overlay-name {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  color: #fff;
  font-size: clamp(2.1rem, 7vw, 2.65rem);
  min-height: 1.15em;
}

.track-switch-overlay.is-welcome-portal.is-phase-language .track-switch-logo-bloom {
  opacity: 0.2;
}

/*
 * Soft beat pulse only - small scale, no brightness strobe, no screen flash.
 * Keep contrast changes gentle for photosensitive safety (WCAG 2.3).
 */
.track-switch-logo.is-beat-flash {
  animation: welcome-beat-logo 0.42s cubic-bezier(0.25, 0.85, 0.3, 1) forwards;
}

.track-switch-logo-wrap.is-beat-flash .track-switch-logo-bloom {
  animation: welcome-beat-bloom 0.5s cubic-bezier(0.25, 0.85, 0.3, 1) forwards;
}

.track-switch-overlay-flag.is-beat-flash {
  animation: welcome-beat-flag 0.4s cubic-bezier(0.25, 0.85, 0.3, 1) forwards;
}

.track-switch-overlay-name.is-beat-flash {
  animation: welcome-beat-name 0.4s cubic-bezier(0.25, 0.85, 0.3, 1) forwards;
}

/* Beat pulses: small scale only — calmer mid-session, still readable on the hit */
@keyframes welcome-beat-logo {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.04);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes welcome-beat-bloom {
  0% {
    opacity: 0.35;
    transform: scale(1);
  }
  40% {
    opacity: 0.55;
    transform: scale(1.06);
  }
  100% {
    opacity: 0.4;
    transform: scale(1);
  }
}

@keyframes welcome-beat-flag {
  0% {
    transform: translate(-50%, -50%) scale(1);
  }
  40% {
    transform: translate(-50%, -50%) scale(1.045);
  }
  100% {
    transform: translate(-50%, -50%) scale(1);
  }
}

@keyframes welcome-beat-name {
  0% {
    transform: translateY(0) scale(1);
  }
  40% {
    transform: translateY(0) scale(1.015);
  }
  100% {
    transform: translateY(0) scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .track-switch-logo.is-beat-flash,
  .track-switch-overlay-flag.is-beat-flash,
  .track-switch-overlay-name.is-beat-flash,
  .track-switch-logo-wrap.is-beat-flash .track-switch-logo-bloom {
    animation: none !important;
  }
}

@keyframes track-switch-logo-in {
  0% {
    opacity: 0.4;
    transform: scale(0.62) translateY(0.35rem);
  }
  55% {
    opacity: 1;
    transform: scale(1.08) translateY(0);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes track-switch-bloom {
  0% {
    opacity: 0.15;
    transform: scale(0.55);
  }
  45% {
    opacity: 0.85;
    transform: scale(1.15);
  }
  100% {
    opacity: 0.55;
    transform: scale(1);
  }
}

@keyframes track-switch-ring {
  0% {
    opacity: 0;
    transform: scale(0.7);
  }
  40% {
    opacity: 0.9;
    transform: scale(1.05);
  }
  100% {
    opacity: 0.45;
    transform: scale(1.18);
  }
}

@keyframes track-switch-name-in {
  0% {
    opacity: 0;
    transform: translateY(0.55rem);
    letter-spacing: -0.01em;
  }
  100% {
    opacity: 1;
    transform: translateY(0);
    letter-spacing: -0.035em;
  }
}

@keyframes track-switch-flag-in {
  0% {
    opacity: 0;
    transform: scale(0.65) translateY(0.4rem);
  }
  55% {
    opacity: 1;
    transform: scale(1.08) translateY(0);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .track-switch-overlay,
  .track-switch-overlay-inner,
  .track-switch-overlay.is-visible .track-switch-logo,
  .track-switch-overlay.is-visible .track-switch-logo-bloom,
  .track-switch-overlay.is-visible .track-switch-logo-ring,
  .track-switch-overlay.is-visible .track-switch-overlay-name,
  .track-switch-overlay.is-visible .track-switch-overlay-flag {
    animation: none !important;
    transition: opacity 0.15s ease !important;
    opacity: 1 !important;
    transform: none !important;
  }
}





.category-picker-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.16), rgba(54, 95, 207, 0.1));
  border: 1px solid var(--brand-ring);
  color: var(--brand-deep);
  cursor: pointer;
  transition: all 0.2s var(--ease);
}

.category-picker-btn[aria-expanded="true"] {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.22), rgba(54, 95, 207, 0.14));
  border-color: rgba(54, 95, 207, 0.28);
  box-shadow: var(--shadow-sm);
}
@media (hover: hover) and (pointer: fine) {
  .category-picker-btn:hover {
    background: linear-gradient(135deg, rgba(91, 154, 255, 0.22), rgba(54, 95, 207, 0.14));
    border-color: rgba(54, 95, 207, 0.28);
    box-shadow: var(--shadow-sm);
  }
}

.category-picker-chevron {
  width: 0.45rem;
  height: 0.45rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-1px);
  transition: transform 0.2s var(--ease);
}

.category-picker-btn[aria-expanded="true"] .category-picker-chevron {
  transform: rotate(225deg) translateY(1px);
}

.category-picker-menu {
  position: absolute;
  top: calc(100% + 0.45rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  min-width: min(18rem, 88vw);
  /* Product lists fold at ~22rem; Welcome may override taller */
  max-height: min(22rem, 50dvh);
  overflow: hidden;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  z-index: 20;
}

/* Scrollable options only - cue stays pinned under the list */
.category-picker-menu-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  /* Neutral scrollbar - not brand blue (must not look like a selected language) */
  scrollbar-width: thin;
  scrollbar-color: rgba(18, 24, 38, 0.22) transparent;
}

.category-picker-menu-scroll::-webkit-scrollbar {
  width: 5px;
}

.category-picker-menu-scroll::-webkit-scrollbar-track {
  background: transparent;
  margin: 0.2rem 0;
}

.category-picker-menu-scroll::-webkit-scrollbar-thumb {
  background: rgba(18, 24, 38, 0.18);
  border-radius: 999px;
  border: 1px solid transparent;
  background-clip: padding-box;
}

.category-picker-menu-scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(18, 24, 38, 0.3);
  border: 1px solid transparent;
  background-clip: padding-box;
}

/*
 * More languages below: clip mid-row so the next flag peeks through a fade.
 * That peek is the real cue; the chevron pill only confirms “scroll here.”
 */
.category-picker-menu.has-more-below .category-picker-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow: inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

.category-picker-menu.has-more-above .category-picker-menu-scroll {
  mask-image: linear-gradient(to bottom, transparent 0%, #000 1.35rem, #000 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 1.35rem, #000 100%);
  box-shadow: inset 0 1.1rem 0.9rem -0.75rem color-mix(in srgb, var(--brand-deep) 12%, transparent);
}

.category-picker-menu.has-more-above.has-more-below .category-picker-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 1.2rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 1.2rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow:
    inset 0 1.1rem 0.9rem -0.75rem color-mix(in srgb, var(--brand-deep) 12%, transparent),
    inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

/*
 * Scroll-only cues: overlays (no layout height), never clickable.
 * Opacity only - so the language list never jumps when cues appear.
 */
.category-picker-scroll-cue {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 2;
  display: none;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0.3rem 0.35rem;
  border: none;
  border-radius: 0;
  color: color-mix(in srgb, var(--brand-deep) 78%, var(--muted));
  background: transparent;
  box-shadow: none;
  pointer-events: none;
  user-select: none;
  opacity: 0;
  transition: opacity 0.18s var(--ease, ease);
}

.category-picker-scroll-cue--down {
  bottom: 0.15rem;
  padding-bottom: 0.25rem;
}

.category-picker-scroll-cue--up {
  top: 0.1rem;
  padding-top: 0.25rem;
}

/* Show when the list can scroll; fade in only when more content that way */
.category-picker-menu.is-scrollable .category-picker-scroll-cue {
  display: flex;
}

.category-picker-menu.has-more-below .category-picker-scroll-cue--down {
  opacity: 1;
}

.category-picker-menu.has-more-above .category-picker-scroll-cue--up {
  opacity: 1;
}

.category-picker-scroll-cue-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.08rem;
  line-height: 0;
  animation: category-scroll-cue-bounce-down 1.3s var(--ease, ease) infinite;
}

.category-picker-scroll-cue--up .category-picker-scroll-cue-icon {
  animation-name: category-scroll-cue-bounce-up;
  /* Stack chevrons so they point up: rotate whole stack */
  transform: rotate(180deg);
}

.category-picker-scroll-cue-chevron {
  display: block;
  width: 0.55rem;
  height: 0.55rem;
  margin-top: -0.24rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  opacity: 0.9;
}

.category-picker-scroll-cue-chevron:first-child {
  margin-top: 0;
  opacity: 0.45;
}

@keyframes category-scroll-cue-bounce-down {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.8;
  }
  50% {
    transform: translateY(2px);
    opacity: 1;
  }
}

@keyframes category-scroll-cue-bounce-up {
  0%,
  100% {
    transform: rotate(180deg) translateY(0);
    opacity: 0.8;
  }
  50% {
    transform: rotate(180deg) translateY(2px);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .category-picker-scroll-cue {
    transition: none;
  }

  .category-picker-scroll-cue-icon {
    animation: none;
  }

  .category-picker-scroll-cue--up .category-picker-scroll-cue-icon {
    transform: rotate(180deg);
  }
}

.category-option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: none;
  border-radius: var(--radius-xs);
  background: transparent;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

/* Hover = quiet gray (not the same as “current language”) */
@media (hover: hover) and (pointer: fine) {
  .category-option:hover:not(:disabled):not(.active) {
    background: rgba(18, 24, 38, 0.05);
  }
}

/* Current language: full wrap (all sides), not a left-only accent bar */
.category-option.active {
  background: color-mix(in srgb, var(--brand-soft) 75%, white);
  box-shadow: none;
  border: 1.5px solid color-mix(in srgb, var(--brand, #365fcf) 48%, transparent);
  border-radius: 0.75rem;
}

@media (hover: hover) and (pointer: fine) {
  .category-option.active:hover:not(:disabled) {
    background: color-mix(in srgb, var(--brand-soft) 88%, white);
    border-color: color-mix(in srgb, var(--brand, #365fcf) 58%, transparent);
  }
}

.category-option.active .category-option-label {
  color: var(--brand-deep, #1e3a8a);
}

.category-option.unavailable {
  opacity: 0.55;
  cursor: not-allowed;
}

.category-option--soon {
  padding: 0.5rem 0.85rem;
}

.category-option-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
  text-transform: none;
  white-space: nowrap;
  overflow: visible;
  text-overflow: clip;
  flex: 0 0 auto;
}





.category-picker-group-label {
  margin: 0.45rem 0.85rem 0.25rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}



@media (max-width: 720px) {
  .app {
    padding:
      calc(1rem + env(safe-area-inset-top, 0px))
      calc(1rem + env(safe-area-inset-right, 0px))
      calc(1rem + env(safe-area-inset-bottom, 0px))
      calc(1rem + env(safe-area-inset-left, 0px));
  }

  .header {
    margin-bottom: 1rem;
  }



  .progress-prefs {
    --prefs-h: 2.5rem;
    --prefs-pad-x: 0.6rem;
    --prefs-font: 0.72rem;
    --prefs-gap: 0.3rem;
    margin-bottom: 0.9rem;
  }

  /*
   * Mobile closed chip: flag-only to save prefs-row space.
   * Open list uses the same 14rem menu as desktop (flag + full name) - 
   * see base .category-picker--progress .category-picker-menu and the
   * override after the general mobile .category-picker-menu rule.
   */
  .category-picker-btn.category-picker-btn--progress {
    flex: 0 0 auto;
    width: var(--prefs-h);
    min-width: var(--prefs-h);
    max-width: var(--prefs-h);
    min-height: var(--prefs-h);
    height: var(--prefs-h);
    padding: 0;
    gap: 0.12rem;
    justify-content: center;
    overflow: visible;
  }

  .category-picker-btn.category-picker-btn--progress .category-picker-lang {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .category-picker-btn.category-picker-btn--progress .category-flag {
    font-size: 1.2rem;
  }

  .category-picker-btn.category-picker-btn--progress .category-picker-chevron {
    width: 0.36rem;
    height: 0.36rem;
  }

  .progress-basics-btn {
    max-width: none;
    gap: 0.28rem;
    padding: 0 0.55rem;
  }

  .progress-basics-glyphs {
    font-size: 0.82rem;
    letter-spacing: 0.04em;
    line-height: 1.35;
  }
  .brand {
    margin-bottom: 0.85rem;
    gap: 0.3rem;
  }

  .brand-logo {
    width: min(200px, 58vw);
    margin-bottom: 0.15rem;
  }

  /* - Mobile Study: tabs only (brand hidden via .practice-focus); hero card - */
  .app.practice-focus .header {
    margin-bottom: 0.5rem;
  }

  .app.practice-focus .prompt,
  .app.practice-focus .prompt.norwegian {
    font-size: clamp(1.72rem, 8vw, 2.25rem);
    /* Fixed 2-line seat + optical center; denser to field (holistic B) */
    margin-bottom: 0.42rem;
  }

  .feedback-slot {
    min-height: 1.85rem;
    height: 1.85rem;
    margin-bottom: 0.16rem;
  }

  .feedback-slot:has(.feedback.is-empty),
  .feedback-slot:has(.feedback:empty) {
    min-height: 0;
    height: 0;
    margin: 0;
  }

  /* Mid-session: empty pill seat collapses; live pill keeps seat (phones) */
  #practice-active .feedback-slot:has(.feedback.is-empty),
  #practice-active .feedback-slot:has(.feedback:empty) {
    height: 0;
    min-height: 0;
    margin: 0;
  }

  #practice-active .feedback-slot:has(.feedback:not(.is-empty)) {
    height: 1.85rem;
    min-height: 1.85rem;
    margin: 0 0 0.16rem;
  }

  .feedback {
    max-height: 1.85rem;
    padding: 0.22rem 0.6rem;
    font-size: clamp(0.84rem, 3vw, 0.98rem);
  }

  .practice-goal-strip,
  .practice-meta {
    max-width: 14rem;
    gap: 0.38rem;
    margin-bottom: 0.75rem;
  }

  .app.practice-focus .practice-goal-strip,
  .app.practice-focus .practice-meta {
    margin-bottom: 0.65rem;
  }

  .daily-goal-chip {
    min-height: 2.35rem;
    min-width: 3.5rem;
    padding: 0.35rem 0.9rem;
    font-size: 0.9rem;
  }

  .daily-progress {
    max-width: 10.5rem;
    height: 0.34rem;
  }

  /*
   * P4 density only (padding). Shell weight lives on base .practice-card so
   * 720↔721 does not flip light glass ↔ heavy slab (resize multipass / law of one layout).
   */
  .app.practice-focus .practice-card,
  .practice-card {
    --study-mid-shell-pad-top: 0.72rem;
    --study-mid-flag-band-mb: 0.42rem;
    padding: var(--study-mid-shell-pad-top) 0.72rem 0.68rem;
    min-height: min(13.25rem, 40dvh);
  }

  .match-room {
    --study-mid-shell-pad-top: 0.72rem;
    --study-mid-flag-band-mb: 0.42rem;
    padding-top: var(--study-mid-shell-pad-top);
  }

  .practice-card-top,
  .match-room__top {
    margin-bottom: var(--study-mid-flag-band-mb);
  }

  #practice-active.practice-card .answer-field-shell:not(.received):not(.incorrect):not(.near-miss) {
    background: rgba(255, 255, 255, 0.88);
    border-color: rgba(54, 95, 207, 0.12);
  }

  .practice-card-top {
    display: flex;
    justify-content: center;
    margin-bottom: 0.42rem;
    min-height: 2.15rem;
  }

  .practice-card-top .direction-label {
    font-size: 0.72rem;
  }

  .prompt {
    font-size: clamp(1.75rem, 8.2vw, 2.35rem);
    margin-bottom: 0.42rem;
  }

  .prompt.norwegian {
    /* Keep 2-line seat (stable shell) — do not collapse short L2 */
    height: calc(2 * var(--prompt-lh, 1.32) * 1em);
    min-height: calc(2 * var(--prompt-lh, 1.32) * 1em);
    max-height: calc(2 * var(--prompt-lh, 1.32) * 1em);
  }

  .answer-form {
    max-width: none;
    width: 100%;
  }

  .answer-form input[type="text"] {
    font-size: max(16px, 1.12rem); /* prevent iOS focus zoom (incl. coarse pointer) */
    font-weight: 500;
    padding: 0.55rem 0.95rem;
  }

  .answer-field-shell {
    margin-bottom: 0.12rem;
    --field-note-seat: 1rem;
    --field-form-min: 2.4rem;
    --field-shell-h: calc(var(--field-form-min) + var(--field-note-seat));
    --field-border-y: 2px;
    --field-inner-h: calc(var(--field-shell-h) - var(--field-border-y));
    height: var(--field-shell-h);
    min-height: var(--field-shell-h);
    max-height: var(--field-shell-h);
  }

  .answer-field-shell.has-teaching-note.received,
  .answer-field-shell.has-teaching-note.incorrect {
    height: var(--field-shell-h);
    min-height: var(--field-shell-h);
    max-height: var(--field-shell-h);
  }

  /* Phone: same mid-capsule caret system as desktop */
  .answer-field-shell:not(.has-teaching-note) > input[type="text"] {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    height: 1.4em;
    min-height: 1.4em;
    max-height: 1.4em;
    padding: 0 0.95rem;
    line-height: 1.4;
  }

  .answer-field-shell.has-teaching-note > input[type="text"] {
    position: static;
    transform: none;
    padding: 0.4rem 0.95rem 0.08rem;
    line-height: 1.25;
    height: auto;
    min-height: var(--field-form-min);
    max-height: none;
  }

  .app.practice-focus .prompt,
  .app.practice-focus .prompt.norwegian {
    margin-bottom: 0.42rem;
  }

  .answer-actions {
    display: flex;
    justify-content: center;
    width: 100%;
    max-width: none;
  }

  .answer-actions-core {
    column-gap: 0.45rem;
    align-items: center;
  }

  .answer-actions .btn,
  .answer-action {
    touch-action: manipulation;
  }

  /* Keep Hear clearly larger than SPEAK on narrow layouts */
  .answer-actions .btn.answer-action--hear {
    min-height: 50px;
    min-width: 7rem;
    padding: 0.65rem 1.35rem;
    font-size: 1.05rem;
    font-weight: 650;
  }

  .answer-actions .btn.answer-action--speak {
    min-height: 44px;
    height: 44px;
    min-width: 4.2rem;
    max-width: 5.2rem;
    padding: 0.3rem 0.55rem;
    font-size: 0.72rem;
    font-weight: 550;
  }

  .answer-actions .btn.answer-action--match {
    min-height: 44px;
    height: 44px;
    min-width: 2.75rem;
  }

  /* Empty Study home: same fluid cap as base (no 720↔721 width snap). */
  #practice-panel.active #practice-empty:not(.hidden) {
    width: min(100%, 20rem);
    margin-inline: auto;
    box-sizing: border-box;
  }

  .empty-state {
    padding: 1.75rem 1.1rem 1.5rem;
  }

  .empty-state--actions {
    padding: 1.35rem 1rem 1.25rem;
  }

  .empty-actions {
    width: 100%;
    max-width: none;
  }

  .empty-actions .btn {
    width: 100%;
    max-width: none;
    box-sizing: border-box;
  }

  .page-float-top {
    right: max(0.85rem, env(safe-area-inset-right, 0px));
    bottom: max(0.95rem, env(safe-area-inset-bottom, 0px));
  }



  .header {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
  }

  main,
  .panel.active {
    width: 100%;
    min-width: 0;
  }

  .empty-state {
    padding: 2rem 1rem 1.65rem;
    box-sizing: border-box;
  }

  .empty-state--actions {
    padding: 1.5rem 1rem 1.35rem;
  }

  .empty-actions {
    max-width: 100%;
    width: 100%;
  }

  .welcome-modal,
  .confirm-modal,
  .about-modal {
    padding:
      max(1rem, env(safe-area-inset-top, 0px))
      max(1rem, env(safe-area-inset-right, 0px))
      max(1rem, env(safe-area-inset-bottom, 0px))
      max(1rem, env(safe-area-inset-left, 0px));
  }

  .about-card {
    width: min(100%, 24rem);
    max-height: calc(100dvh - 1.5rem);
  }

  .welcome-card {
    width: min(100%, 20rem);
    padding: 1.5rem 1.15rem 1.25rem;
  }

  .category-picker--welcome {
    width: 100%;
    max-width: 16rem;
  }

  /* Welcome (and any full-width picker): stretch to trigger width */
  .category-picker-menu {
    left: 0;
    right: 0;
    transform: none;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }

  /*
   * Path language list must NOT inherit chip width (flag-only closed).
   * Same open size as desktop: full flag + full language name.
   * Placed after the general rule so it always wins on mobile.
   */
  .category-picker--progress .category-picker-menu {
    left: 0;
    right: auto;
    transform: none;
    width: 14rem;
    min-width: 14rem;
    max-width: min(14rem, calc(100vw - 1rem));
  }
}

/* Tabs - pill segment, brand-active.
 * One fluid layout at every width (Study-card pattern): equal segments,
 * calm max width — no 720↔721 full-bleed ↔ inline-flex snap. */
.tabs {
  display: flex;
  align-self: center;
  /* Five tabs: Study · Speak · Stories · Cards · Path (2026-08-09) */
  width: min(100%, 32rem);
  max-width: 100%;
  box-sizing: border-box;
  gap: clamp(0.08rem, 0.35vw, 0.18rem);
  background: var(--surface-glass);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--border-strong);
  padding: clamp(0.22rem, 0.6vw, 0.3rem);
  border-radius: 999px;
  margin: 0 auto;
  box-shadow: var(--shadow-sm);
}

.tab {
  flex: 1 1 0;
  min-width: 0;
  min-height: 2.4rem;
  padding: 0.55rem clamp(0.08rem, 0.9vw, 0.7rem);
  border: none;
  border-radius: var(--chip-radius);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: clamp(0.62rem, 0.36rem + 1vw, 0.84rem);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: var(--lh-tight);
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  touch-action: manipulation;
  /* No transition: all — avoids animating sticky hover/focus paint on touch */
  transition:
    color 0.2s var(--ease),
    background 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .tab:hover:not(.active) {
    color: var(--brand-deep);
    background: var(--brand-soft);
  }
}

.tab.active {
  background: var(--brand-gradient);
  color: #fff;
  box-shadow: var(--shadow-brand);
}

@media (max-width: 720px) {
  .tab {
    min-height: 44px;
  }
}

.panel {
  display: none;
  animation: fadeIn 0.35s var(--ease);
}

.panel.active {
  display: block;
  flex: 1 1 auto;
  /* auto: long panels grow the page (Safari document scroll). Nested modes override. */
  min-height: auto;
  height: auto;
  overflow: visible;
}

/*
 * Cards + Progress: keep the body scrollport (trackpad + keyboard).
 * Flatten flex so long content grows the body scroll height; never reassign
 * overflow-y to html (Safari two-finger scroll targets body).
 * overscroll none: long library/Path must not rubber-band the window edge.
 */
body:has(#cards-panel.active) .app,
body:has(#stats-panel.active) .app {
  display: block;
  height: auto;
  min-height: 100%;
  overflow: visible;
  overscroll-behavior: none;
}

body:has(#cards-panel.active) .app main,
body:has(#stats-panel.active) .app main,
body:has(#cards-panel.active) #cards-panel.active,
body:has(#stats-panel.active) #stats-panel.active {
  display: block;
  flex: none;
  height: auto;
  min-height: auto;
  overflow: visible;
  overscroll-behavior: none;
}

/* Beat any panel-specific display rules when the tab is not active */
.panel[hidden],
.panel:not(.active) {
  display: none !important;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.panel h2 {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 0.5rem;
}

.panel h3 {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 0 0 0.35rem;
}



/* Theme set strip only (chip + bar) — not a daily goal picker. */
.practice-goal-strip,
.practice-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  max-width: 16rem;
  margin: 0 auto 1.15rem;
  box-sizing: border-box;
}

.practice-goal-strip.hidden,
.practice-meta.hidden {
  display: none;
}

/* Pack focus: strip ends the set and returns to core Study home */
.practice-meta.is-theme {
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.practice-meta.is-theme:focus-visible {
  outline: none;
  border-radius: 0.75rem;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}

/* Theme Study set progress label (parent strip is the hit target). */
.daily-goal-chip {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.15rem;
  min-width: 3.5rem;
  padding: 0.32rem 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: none;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1;
  cursor: inherit;
  user-select: none;
  pointer-events: none;
}

.practice-meta.is-theme .daily-goal-chip {
  cursor: pointer;
}

.practice-meta.is-theme .daily-progress,
.daily-progress.is-theme-bar {
  background: rgba(54, 95, 207, 0.1);
}

.practice-meta.is-theme .daily-progress-fill {
  background: linear-gradient(90deg, #6b8fd4, #8eb0f0);
}

.daily-goal-chip__count {
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: inherit;
  text-align: center;
}

/*
 * In-progress (1/20…): keep rest look. The number + bar already show progress;
 * a permanent brand fill read as “stuck depressed.”
 */
.daily-goal-chip.is-live {
  color: var(--text-secondary);
  background: var(--surface-glass-strong);
  border-color: var(--border-strong);
}

/* Theme chip complete state (class name is legacy; not a daily-goal chrome) */
.daily-goal-chip.goal-met {
  color: #1f6b45;
  background: color-mix(in srgb, rgba(72, 187, 120, 0.1) 80%, var(--surface-glass-strong));
  border-color: rgba(56, 161, 105, 0.28);
}

.daily-progress {
  width: 100%;
  max-width: 11rem;
  height: 0.32rem;
  margin: 0;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  border-radius: 999px;
  overflow: hidden;
}

.daily-progress.hidden {
  display: none;
}

.daily-progress-fill {
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--brand), #5b9aff);
  transition: width 0.35s var(--ease);
}

.daily-progress.is-complete,
.practice-goal-strip.is-complete .daily-progress {
  background: rgba(56, 161, 105, 0.16);
}

.daily-progress.is-complete .daily-progress-fill,
.practice-goal-strip.is-complete .daily-progress-fill {
  background: linear-gradient(90deg, #3a9e62, #48bb78);
}

/*
 * Practice card — one fluid shell at every width (P4 lightness + desktop calm).
 * No breakpoint-only second layout for fill/shadow/radius (720↔721 snap class).
 * Holistic density B (2026-07-28): denser session placard; seats still fixed
 * (stable shell). Home power island is separate — not this min-height.
 */
.practice-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: rgba(255, 255, 255, 0.76);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(54, 95, 207, 0.07);
  border-radius: 18px;
  padding: var(--study-mid-shell-pad-top) 0.9rem 0.72rem;
  box-shadow: 0 6px 24px rgba(54, 95, 207, 0.075);
  text-align: center;
  /* Session denser; internal seats (prompt · field · sample · tools) stay fixed */
  min-height: min(13.6rem, 40dvh);
  box-sizing: border-box;
}

/* Theme strip: hold a slim slot when present so it does not thrash card position */
.practice-goal-strip:not(.hidden),
.practice-meta:not(.hidden) {
  min-height: 2.75rem;
}

/* Su1: home → first card settles in (opacity only — no layout thrash) */
#practice-active.practice-card:not(.hidden) {
  animation: study-card-land 0.32s var(--ease, ease) both;
}

@keyframes study-card-land {
  from {
    opacity: 0.55;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  #practice-active.practice-card:not(.hidden) {
    animation: none;
  }
}

.practice-card .answer-form {
  width: 100%;
}

.app.practice-focus .practice-goal-strip,
.app.practice-focus .practice-meta {
  margin-bottom: 0.85rem;
  max-width: 14rem;
}

/*
 * P1: Top band = one quiet caption line (flag + direction), not a toolbar.
 * Flag is identity + hop; direction is orientation. No glass chip chrome.
 * Flag always sits next to the L2 name:
 *   type (L2 → EN):  🇳🇴 Norwegian → English
 *   SPEAK (EN → L2): English → Norwegian 🇳🇴
 */
.practice-card-top {
  position: relative;
  z-index: 12;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  flex-wrap: nowrap;
  /* Shared with Match top band — flag hop Y law */
  margin-bottom: var(--study-mid-flag-band-mb);
  min-height: var(--study-mid-flag-row);
}

/* SPEAK: reverse so flag lands on the L2 side (right of “English → Norwegian”) */
body.speak-mode-active #practice-active .practice-card-top {
  flex-direction: row-reverse;
}

.practice-card-top.is-quiet {
  /* Keep margin + min-height — only the label text goes quiet */
}

/* Mid-session only (lives inside #practice-active — never on power home) */
.study-lang-picker {
  position: relative;
  flex: 0 0 auto;
  z-index: 13;
  display: flex;
  align-items: center;
}

/* Study language list must paint above card chrome (feedback, tools) */
#practice-active.practice-card:has(.study-lang-cue[aria-expanded="true"]),
#practice-active.practice-card:has(#study-lang-menu:not(.hidden)) {
  z-index: 40;
}

/*
 * Study flag = Match glyph size (2026-07-28 · founder + holistic B):
 * Same ~1.55rem glyph so Match ↔ Study does not resize the mark.
 * Hit seat denser with the session placard; coarse still ≥44px (below).
 */
.study-lang-cue {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--study-mid-flag-seat);
  min-width: var(--study-mid-flag-seat);
  min-height: var(--study-mid-flag-seat);
  padding: 0;
  border: none;
  border-radius: 0.45rem;
  background: transparent;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    background 0.15s var(--ease),
    box-shadow 0.15s var(--ease);
  font-family: inherit;
  font-size: 1.55rem;
}

@media (hover: hover) and (pointer: fine) {
  .study-lang-cue:hover,
  .study-lang-cue:focus-visible {
    background: var(--brand-soft);
  }

  .study-lang-cue:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 20%, transparent);
    outline: none;
  }
}

.study-lang-cue[aria-expanded="true"] {
  background: color-mix(in srgb, var(--brand-soft) 85%, transparent);
}

.study-lang-cue-flag {
  font-size: 1.55rem;
  line-height: 1;
  /* Soft presence — not a sticker on chrome */
  filter: drop-shadow(0 0.5px 0.5px rgba(15, 23, 42, 0.08));
}

/* Reuse Cards list chrome; Study list is centered under the flag (JS fit). */
.study-lang-menu.library-lang-menu {
  /* default library-lang-menu rules apply; open position set in fitCategoryMenuToViewport */
}

.study-lang-menu.is-scrollable .category-picker-scroll-cue {
  display: flex;
}

.study-lang-menu.has-more-below .category-picker-scroll-cue--down {
  opacity: 1;
}

.study-lang-menu.has-more-above .category-picker-scroll-cue--up {
  opacity: 1;
}

/*
 * Scroll cues: centered on the panel (founder craft).
 * Panel itself is centered under the Study flag so mid-panel = under flag on phone.
 */

@media (pointer: coarse) {
  /*
   * Shared flag hop seat (Study + Match): ≥44px so phone flag Y matches.
   * Glyph stays 1.55rem; only the hit box grows.
   */
  :root {
    --study-mid-flag-row: 44px;
    --study-mid-flag-seat: 44px;
  }

  .study-lang-cue,
  .match-lang-cue {
    min-height: var(--study-mid-flag-seat);
    min-width: var(--study-mid-flag-seat);
    width: var(--study-mid-flag-seat);
  }

  .practice-card-top,
  .match-room__top {
    min-height: var(--study-mid-flag-row);
    gap: 0.4rem;
  }

  #match-room .match-home-btn.power-on-btn {
    width: var(--study-mid-flag-seat) !important;
    height: var(--study-mid-flag-seat) !important;
    min-width: var(--study-mid-flag-seat) !important;
    min-height: var(--study-mid-flag-seat) !important;
    max-width: var(--study-mid-flag-seat) !important;
    max-height: var(--study-mid-flag-seat) !important;
  }

  #match-room .match-room__spacer,
  .match-room__spacer {
    width: var(--study-mid-flag-seat);
    min-width: var(--study-mid-flag-seat);
    max-width: var(--study-mid-flag-seat);
  }
}

.direction-label {
  display: block;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  box-shadow: none;
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 550;
  letter-spacing: -0.012em;
  text-transform: none;
  color: var(--text-tertiary);
  line-height: 1.25;
  min-height: 1.25em;
  text-align: left;
  cursor: default;
  user-select: none;
  pointer-events: none;
}

/* Invisible but still occupies the reserved band (display:none would collapse). */
.direction-label.hidden {
  visibility: hidden;
  color: transparent;
}







/*
 * Prompt stage (stable shell · Kai B optical · 2026-07-28):
 * Fixed 2-line seat so SPEAK/type never resize the card.
 * Short lemmas (og) sit vertically centered — not floating above a void.
 * Tighter margin to the field; height stays fixed.
 */
.prompt {
  --prompt-lh: 1.32;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 100%;
  font-size: clamp(2.05rem, 5.6vw, 2.95rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: var(--prompt-lh);
  margin-top: 0.05rem;
  margin-bottom: 0.42rem;
  word-break: break-word;
  color: var(--ink);
  overflow: hidden;
  height: calc(2 * var(--prompt-lh) * 1em);
  min-height: calc(2 * var(--prompt-lh) * 1em);
  max-height: calc(2 * var(--prompt-lh) * 1em);
  box-sizing: content-box;
  text-align: center;
}

.prompt.norwegian {
  display: flex;
  font-size: clamp(2.5rem, 7vw, 3.5rem);
  letter-spacing: -0.03em;
  line-height: var(--prompt-lh);
  height: calc(2 * var(--prompt-lh) * 1em);
  min-height: calc(2 * var(--prompt-lh) * 1em);
  max-height: calc(2 * var(--prompt-lh) * 1em);
  padding: 0 0.04em;
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

body.speak-mode-active #practice-active .prompt,
body.speak-mode-active #practice-active .prompt.norwegian,
body.speak-mode-active #practice-active .prompt.prompt--speak-en {
  height: calc(2 * var(--prompt-lh) * 1em);
  min-height: calc(2 * var(--prompt-lh) * 1em);
  max-height: calc(2 * var(--prompt-lh) * 1em);
  font-size: clamp(2.35rem, 6.5vw, 3.35rem);
  line-height: var(--prompt-lh);
}

.answer-form {
  max-width: 420px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}

/*
 * Answer field shell (stable card · form center · 2026-07-28):
 * Fixed capsule height always (form + room for note). Typed/graded text sits
 * optically centered when no note; note paints in the lower band without growing.
 */
.answer-field-shell {
  /* Holistic B: denser capsule; still room for form + teaching note */
  --field-note-seat: 1rem;
  --field-form-min: 2.45rem;
  --field-shell-h: calc(var(--field-form-min) + var(--field-note-seat));
  /* Content box inside 1px top+bottom border — used so empty caret can mid-align */
  --field-border-y: 2px;
  --field-inner-h: calc(var(--field-shell-h) - var(--field-border-y));
  position: relative;
  width: 100%;
  margin-top: 0.1rem;
  margin-bottom: 0.12rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-glass);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-sizing: border-box;
  transition:
    border-color 0.2s,
    box-shadow 0.2s,
    background 0.2s;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  height: var(--field-shell-h);
  min-height: var(--field-shell-h);
  max-height: var(--field-shell-h);
}

.answer-form input[type="text"] {
  width: 100%;
  /* Equal vertical padding — form line centered in its flex area */
  padding: 0.58rem 1.1rem;
  /* ≥16px always — iPad “desktop” width still zooms below 16px on focus */
  /* Holistic B: slightly denser type in a shorter field seat */
  font-size: max(1.15rem, 16px);
  font-weight: 500;
  letter-spacing: -0.02em;
  font-family: inherit;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  margin: 0;
  outline: none;
  box-shadow: none;
  text-align: center;
  /* Stop iOS from auto-zooming / auto-sizing the field independently */
  -webkit-text-size-adjust: 100%;
  flex: 1 1 auto;
  min-height: 0;
  box-sizing: border-box;
}

/*
 * No note: true mid-capsule caret (empty + typing + near-miss).
 *
 * WebKit will not honor empty-caret vertical position inside a native <input>
 * (top when empty, mid/low once text exists). Do not fight the UA caret when empty:
 * hide it and paint a centered brand caret on the shell instead.
 *
 * Typed text: one-line input absolutely centered in the capsule (transform),
 * native caret on that line only.
 */
.answer-field-shell:not(.has-teaching-note) > input[type="text"] {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  flex: none;
  width: 100%;
  height: 1.4em;
  min-height: 1.4em;
  max-height: 1.4em;
  padding: 0 1.1rem;
  line-height: 1.4;
  margin: 0;
  border: none;
  border-radius: var(--radius-sm);
  box-sizing: border-box;
  background: transparent;
}

/* Empty + focused: hide native caret, show mid-capsule brand caret */
.answer-field-shell:not(.has-teaching-note).is-empty:focus-within:not(.received):not(.incorrect)
  > input[type="text"] {
  caret-color: transparent;
}

.answer-field-shell:not(.has-teaching-note).is-empty:focus-within:not(.received):not(.incorrect)::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  height: 1.2em;
  transform: translate(-50%, -50%);
  background: var(--brand, #365fcf);
  border-radius: 1px;
  pointer-events: none;
  z-index: 3;
  animation: answer-caret-blink 1.05s step-end infinite;
}

@keyframes answer-caret-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .answer-field-shell:not(.has-teaching-note).is-empty:focus-within:not(.received):not(.incorrect)::after {
    animation: none;
    opacity: 1;
  }
}

/* Note visible: form band + fixed note; shell height unchanged */
.answer-field-shell.has-teaching-note > input[type="text"] {
  position: static;
  transform: none;
  flex: 1 1 auto;
  height: auto;
  min-height: var(--field-form-min);
  max-height: none;
  padding: 0.45rem 1.1rem 0.1rem;
  line-height: 1.25;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* Teaching note: no custom empty caret */
.answer-field-shell.has-teaching-note.is-empty:focus-within::after {
  content: none;
  display: none;
}

.answer-field-shell.has-teaching-note.received,
.answer-field-shell.has-teaching-note.incorrect {
  height: var(--field-shell-h);
  min-height: var(--field-shell-h);
  max-height: var(--field-shell-h);
}

/*
 * Graded correct / miss: hide caret so it does not distract from the form.
 * Near (amber) keeps the caret — learner still needs to retype.
 */
.answer-field-shell.received input[type="text"],
.answer-field-shell.incorrect input[type="text"] {
  caret-color: transparent;
}

.answer-field-shell:focus-within:not(.received):not(.incorrect):not(.near-miss) {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft), var(--shadow-sm);
  background: var(--surface);
}

/*
 * Card tools layout:
 *   [ SPEAK | Hear | Match ]  — one centered row under the field.
 * Equal side columns so Hear stays true-center even when SPEAK is wider than Match.
 * Give up = empty Enter (no Show).
 */
.answer-actions {
  display: flex;
  justify-content: center;
  width: 100%;
  max-width: 26rem;
  margin: 0.06rem auto 0;
  align-items: center;
  /* Always reserve Hear-row height so settle hide/show never resizes the card */
  min-height: 2.7rem;
  box-sizing: border-box;
}

.answer-actions-core {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0.55rem;
  width: 100%;
  min-width: 0;
}

/*
 * Size hierarchy (do not flatten):
 * Hear is the primary helper under the field — clearly larger type + pad + height.
 * SPEAK is a compact wing. Match is a separate icon door.
 * Selectors must beat `.btn` and any later `.btn` min-height floors.
 */
.answer-actions .btn.answer-action {
  min-width: 0;
  flex: 0 0 auto;
  letter-spacing: -0.01em;
}

/* Hear: clearly larger — primary helper, locked to center column */
.answer-actions .btn.answer-action--hear {
  grid-column: 2;
  justify-self: center;
  min-width: 6.8rem;
  min-height: 2.7rem;
  height: auto;
  padding: 0.55rem 1.35rem;
  font-weight: 650;
  font-size: 1rem;
  letter-spacing: -0.015em;
  color: var(--text-secondary);
}

/*
 * SPEAK / Match: equal side columns (1 / 3). Same height.
 * SPEAK readable (not ghost). Match brand icon door.
 */
.answer-actions .btn.answer-action--speak {
  grid-column: 1;
  justify-self: end;
  /* Fixed seat — never grow for Listening… text */
  min-width: 4.4rem;
  width: 4.4rem;
  max-width: 4.4rem;
  min-height: 2.2rem;
  height: 2.2rem;
  padding: 0.28rem 0.4rem;
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: var(--text-secondary);
  background: var(--surface-glass, rgba(255, 255, 255, 0.72));
  border-color: var(--border-strong, rgba(54, 95, 207, 0.16));
  opacity: 1;
  box-sizing: border-box;
}

.answer-actions .btn.answer-action--match {
  grid-column: 3;
  justify-self: start;
  min-height: 2.2rem;
  height: 2.2rem;
}

/* Finger-first: Hear ≥50px; SPEAK/Match matched wings ≥44px */
@media (pointer: coarse) {
  .answer-actions {
    min-height: 50px;
  }

  .answer-actions .btn.answer-action--hear {
    min-height: 50px;
    touch-action: manipulation;
  }

  .answer-actions .btn.answer-action--speak,
  .answer-actions .btn.answer-action--match {
    min-height: 44px;
    height: 44px;
    touch-action: manipulation;
  }

  .tab {
    min-height: 44px;
    touch-action: manipulation;
  }
}

/*
 * Cursor-only over paint (Kai · 2026-07-28): one family for SPEAK · Hear · Match.
 * Soft brand lift so none look dead next to Match. No sticky hover on touch.
 */
@media (hover: hover) and (pointer: fine) {
  .answer-actions .btn.answer-action--hear:hover {
    color: var(--brand-deep, #2849a8);
    border-color: color-mix(in srgb, var(--brand, #365fcf) 32%, transparent);
    background: var(--brand-soft, rgba(54, 95, 207, 0.1));
  }

  .answer-actions .btn.answer-action--speak:hover {
    color: var(--brand-deep, #2849a8);
    border-color: color-mix(in srgb, var(--brand, #365fcf) 32%, transparent);
    background: var(--brand-soft, rgba(54, 95, 207, 0.1));
    opacity: 1;
  }

  /* Match: same family, hair more brand as the icon door */
  .answer-actions .btn.answer-action--match:hover {
    color: var(--brand-deep, #2849a8);
    border-color: color-mix(in srgb, var(--brand, #365fcf) 42%, transparent);
    background: color-mix(in srgb, var(--brand-soft, rgba(54, 95, 207, 0.1)) 88%, white);
    opacity: 1;
  }
}

#speak-btn.is-active,
#speak-btn[aria-pressed="true"]:not(.listening) {
  color: var(--brand-deep);
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 12%, transparent);
  font-weight: 650;
}

/* Buttons */
.btn {
  padding: 0.7rem 1.4rem;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  /* No transition: all — paint transitions only feel right with a cursor */
  transition:
    color 0.2s var(--ease),
    background 0.2s var(--ease),
    border-color 0.2s var(--ease),
    box-shadow 0.2s var(--ease),
    transform 0.15s var(--ease);
}

.btn:active {
  transform: scale(0.97);
}

.btn.primary {
  background: var(--brand-gradient);
  color: #fff;
  box-shadow: var(--shadow-brand);
}

@media (hover: hover) and (pointer: fine) {
  .btn.primary:hover {
    background: linear-gradient(165deg, #6cabff 0%, var(--brand-hover) 48%, var(--brand-deep) 100%);
    box-shadow: 0 10px 28px rgba(54, 95, 207, 0.32);
  }
}

.btn.secondary {
  background: var(--surface-glass-strong);
  color: var(--brand-deep);
  border: 1px solid var(--brand-ring);
  box-shadow: var(--shadow-sm);
}

@media (hover: hover) and (pointer: fine) {
  .btn.secondary:hover {
    background: var(--surface);
    box-shadow: var(--shadow-md);
  }
}

.btn.ghost {
  background: var(--surface-glass);
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
}

@media (hover: hover) and (pointer: fine) {
  .btn.ghost:hover {
    color: var(--brand-deep);
    border-color: var(--brand-ring);
    background: var(--brand-soft);
  }
}

.btn.small {
  min-height: var(--chip-min-h);
  padding: var(--chip-pad-y) var(--chip-pad-x);
  font-size: var(--chip-font);
  line-height: var(--lh-tight);
}

.btn.danger {
  color: var(--error);
}

/* SPEAK production mode: English prompt, say L2 (exit via SPEAK toggle) */
body.speak-mode-active #practice-active .prompt {
  color: var(--brand-deep);
  background: none;
  -webkit-text-fill-color: var(--brand-deep);
}

body.speak-mode-active #practice-active .direction-label {
  color: var(--brand-deep);
  font-weight: 600;
  /* Label reads left→right; flag is the trailing L2 cue (row-reverse on top). */
  text-align: right;
}

#speak-btn.listening {
  color: #fff;
  border-color: transparent;
  background: var(--brand-gradient);
  box-shadow: var(--shadow-brand);
  animation: speakPulse 1.6s ease-in-out infinite;
}

@keyframes speakPulse {
  0%,
  100% {
    box-shadow: var(--shadow-brand);
  }
  50% {
    box-shadow: 0 10px 28px rgba(54, 95, 207, 0.38);
  }
}

/* Seat 10: no infinite SPEAK pulse when the system asks for less motion */
@media (prefers-reduced-motion: reduce) {
  #speak-btn.listening {
    animation: none;
  }
}

/*
 * Feedback pill slot — reserved height (stable card · Kai B slim · 2026-07-28).
 * Slimmer seat cuts idle air; still fixed so grade never resizes the card.
 */
.feedback-slot {
  width: 100%;
  height: 2.4rem;
  min-height: 2.4rem;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 0 0.28rem;
  pointer-events: none;
  box-sizing: border-box;
  overflow: hidden;
}

/* Empty pill seat collapses (idle · miss with form in field · no twin pill). */
.feedback-slot:has(.feedback.is-empty),
.feedback-slot:has(.feedback:empty) {
  height: 0;
  min-height: 0;
  margin: 0;
  overflow: hidden;
}

/*
 * Mid-session Study (B · 2026-07-28): empty pill seat no longer forces a ~1.85rem
 * gap under the field (that pushed miss samples too low). Soft-status / SPEAK
 * form pills still get a seat when feedback is not empty.
 */
#practice-active .feedback-slot:has(.feedback.is-empty),
#practice-active .feedback-slot:has(.feedback:empty) {
  height: 0;
  min-height: 0;
  margin: 0;
  overflow: hidden;
}

#practice-active .feedback-slot:has(.feedback:not(.is-empty)) {
  height: 1.85rem;
  min-height: 1.85rem;
  margin: 0 0 0.16rem;
  overflow: hidden;
}

.feedback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  max-width: 100%;
  margin: 0;
  padding: 0.22rem 0.65rem;
  border-radius: 999px;
  font-size: clamp(0.88rem, 3vw, 1.02rem);
  line-height: 1.2;
  letter-spacing: -0.03em;
  font-weight: 600;
  border: 1px solid transparent;
  text-align: center;
  word-break: break-word;
  max-height: 1.85rem;
  overflow: hidden;
  box-sizing: border-box;
  transition: opacity 0.18s var(--ease), background 0.18s var(--ease), border-color 0.18s var(--ease);
}

.feedback.is-empty {
  opacity: 0;
  visibility: hidden;
  border-color: transparent;
  background: transparent;
  padding-inline: 0.85rem;
  min-width: 0;
  min-height: 0;
}

.feedback.correct {
  background: var(--success-soft);
  color: var(--success);
  border-color: rgba(36, 138, 61, 0.28);
  box-shadow: 0 0 0 1px rgba(36, 138, 61, 0.06);
}

.feedback.incorrect {
  background: var(--error-soft);
  color: var(--error);
  border-color: rgba(215, 0, 21, 0.24);
  box-shadow: 0 0 0 1px rgba(215, 0, 21, 0.05);
}

/*
 * SPEAK room (2026-07-28): SPEAK is primary; Hear + Match soft secondary.
 * Still clickable — leave SPEAK / open Match / Hear model without thrash.
 */
body.speak-mode-active #practice-active:not(.tools-settle-hide) .answer-actions .answer-action--hear,
body.speak-mode-active #practice-active:not(.tools-settle-hide) .answer-actions .answer-action--match {
  opacity: 0.4;
}

/*
 * Study focus law (B · 2026-07-28):
 * Near: equal soft dim, still clickable (retries left).
 * Wrong / correct settle: tools invisible but seat kept — card height must not jump.
 */
#practice-active.tools-near .answer-actions .answer-action--speak,
#practice-active.tools-near .answer-actions .answer-action--hear,
#practice-active.tools-near .answer-actions .answer-action--match {
  opacity: 0.42;
}

/* Near + SPEAK: keep equal near dim (don't double-darken Hear/Match unevenly) */
body.speak-mode-active #practice-active.tools-near .answer-actions .answer-action--hear,
body.speak-mode-active #practice-active.tools-near .answer-actions .answer-action--match {
  opacity: 0.42;
}

#practice-active.tools-settle-hide .answer-actions,
#practice-active.miss-settle--example .answer-actions,
#practice-active.miss-settle .answer-actions {
  visibility: hidden;
  pointer-events: none;
  /* do not use display:none — that collapses the card */
}

@media (prefers-reduced-motion: reduce) {
  #practice-active.tools-near .answer-actions .answer-action--speak,
  #practice-active.tools-near .answer-actions .answer-action--hear,
  #practice-active.tools-near .answer-actions .answer-action--match {
    transition: none;
  }
}

/*
 * Soft status (mic, speech unavailable): one calm pill line — not a lecture.
 * Smaller type than grade pills so help never floods the field stack.
 */
.feedback.revealed {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.1), rgba(54, 95, 207, 0.06));
  color: var(--brand-deep);
  border-color: color-mix(in srgb, var(--brand-ring, rgba(54, 95, 207, 0.22)) 85%, transparent);
  font-size: clamp(0.82rem, 2.8vw, 0.98rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  padding: 0.28rem 0.8rem;
  max-height: 2.4rem;
  white-space: nowrap;
}

@media (max-width: 420px) {
  .feedback.revealed {
    white-space: normal;
    max-width: min(100%, 18rem);
  }
}

.feedback.near {
  background: linear-gradient(135deg, rgba(255, 193, 70, 0.18), rgba(255, 149, 0, 0.1));
  color: #9a5b00;
  border-color: rgba(255, 149, 0, 0.28);
}

/*
 * Miss example / near line band (stable stack · craft B air+hierarchy · 2026-07-28):
 * Fixed two-line seat — never grow the card when long story lines show.
 * Breath under the field; L2 softer than settle form; EN quieter gloss.
 */
.feedback-example {
  --sample-lh: 1.22;
  --sample-fs: clamp(0.98rem, 2.8vw, 1.05rem);
  width: 100%;
  /* Breath under field once empty pill seat collapses (B · spacing) */
  margin: 0.28rem 0 0.08rem;
  padding: 0.02rem 0.35rem;
  text-align: center;
  font-size: var(--sample-fs);
  line-height: var(--sample-lh);
  letter-spacing: -0.01em;
  color: var(--text-secondary);
  border-radius: 0;
  background: transparent;
  border: none;
  box-sizing: border-box;
  /* Fixed seat — type readable; no jump */
  height: calc(2 * var(--sample-lh) * 1.05rem + 0.1rem);
  min-height: calc(2 * var(--sample-lh) * 1.05rem + 0.1rem);
  max-height: calc(2 * var(--sample-lh) * 1.05rem + 0.1rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
  transition: opacity 0.18s var(--ease, ease);
}

@media (prefers-reduced-motion: reduce) {
  .feedback-example {
    transition: none;
  }
}

/*
 * Override global `.hidden { display: none !important }` — that was collapsing
 * the reserved sample band so tools sat flush under the field (founder live 2026-07-28).
 */
.feedback-example.hidden {
  display: flex !important;
  visibility: hidden;
  color: transparent;
  pointer-events: none;
  /* fixed height stays from base .feedback-example */
}

/*
 * Near retry (B · 2026-07-28): quiet line in the sample-band seat.
 * Same reserved height as miss example — no amber pill chrome.
 */
.feedback-example.is-near-status {
  display: flex !important;
  visibility: visible;
  color: #9a5b00;
  pointer-events: none;
}

.feedback-near-line {
  display: block;
  max-width: 100%;
  font-size: clamp(0.82rem, 2.5vw, 0.92rem);
  font-weight: 550;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: #9a5b00;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* L2 line is display-only (auto-played once); Hear is for the prompt */
.feedback-example-l2 {
  display: block;
  width: 100%;
  max-width: 100%;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  font-size: 1em;
  /* Context under form — secondary gray, not near-black twin of the answer */
  color: var(--text-secondary, #5c5c62);
  font-weight: 500;
  opacity: 0.9;
  letter-spacing: -0.02em;
  cursor: default;
  pointer-events: none;
  border-radius: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.feedback-example-en {
  display: block;
  width: 100%;
  max-width: 100%;
  margin-top: 0.1rem;
  /* Quieter gloss under L2 */
  font-size: 0.78em;
  opacity: 0.95;
  font-weight: 450;
  color: var(--text-tertiary);
  pointer-events: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
 * Grade field (B residual · 2026-07-28 · seam fix):
 * Chrome on the shell only — form + note share one continuous surface.
 * Correct = soft green wash + grounded green form (no pill twin).
 * Miss = soft red wash + border; form is dark (truth), not pure error red.
 */
.answer-field-shell.received {
  background: rgba(36, 138, 61, 0.09);
  border-color: rgba(36, 138, 61, 0.38);
  box-shadow: none;
}

/* Kai B: settle forms a step stronger than typing (same family, not thin draft) */
.answer-field-shell.received input[type="text"] {
  color: color-mix(in srgb, var(--success) 78%, var(--text, #231f20));
  font-size: max(1.22rem, 16px);
  font-weight: 650;
  letter-spacing: -0.025em;
}

.answer-field-shell.received:focus-within {
  border-color: rgba(36, 138, 61, 0.48);
  box-shadow: 0 0 0 3px rgba(36, 138, 61, 0.11);
  background: color-mix(in srgb, var(--success) 12%, white);
}

/* Near: same type as typing — amber shell already means almost */
.answer-field-shell.near-miss {
  border-color: rgba(255, 149, 0, 0.55);
  box-shadow: 0 0 0 4px rgba(255, 193, 70, 0.22);
  background: rgba(255, 248, 235, 0.95);
}

.answer-field-shell.near-miss input[type="text"] {
  font-size: max(1.2rem, 16px);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink, #231f20);
}

/* Miss chrome = soft red; form ink = truth (readable dark), weight matches correct */
.answer-field-shell.incorrect {
  border-color: rgba(215, 0, 21, 0.28);
  box-shadow: none;
  background: rgba(215, 0, 21, 0.07);
}

.answer-field-shell.incorrect input[type="text"] {
  color: var(--text, #231f20);
  font-size: max(1.22rem, 16px);
  font-weight: 650;
  letter-spacing: -0.025em;
}

.answer-field-shell.incorrect:focus-within {
  border-color: rgba(215, 0, 21, 0.36);
  box-shadow: 0 0 0 3px rgba(215, 0, 21, 0.08);
  background: color-mix(in srgb, var(--error, #d70015) 6%, white);
}

/*
 * Teaching note: shell height always includes room for it (stable).
 * Empty: out of flow so form text can center mid-capsule.
 * Full: fixed lower band under the form (no shell grow).
 */
.answer-teaching-note {
  display: block;
  width: 100%;
  box-sizing: border-box;
  text-align: center;
  /* Quieter under settle form (Kai B · 2026-07-28) */
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--text-tertiary, #7a7a82);
  padding: 0 1.2rem 0.35rem;
  margin: 0;
  border: none;
  background: transparent;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Empty note: no layout (form fills capsule; height already fixed on shell) */
.answer-teaching-note.hidden,
.answer-field-shell:not(.has-teaching-note) .answer-teaching-note {
  display: block !important;
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  visibility: hidden;
  pointer-events: none;
  flex: none;
  min-height: 0;
  max-height: 0;
}

.answer-field-shell.has-teaching-note .answer-teaching-note:not(.hidden) {
  position: static;
  display: block;
  visibility: visible;
  clip: auto;
  width: 100%;
  height: var(--field-note-seat, 1.2rem);
  min-height: var(--field-note-seat, 1.2rem);
  max-height: var(--field-note-seat, 1.2rem);
  margin: 0;
  padding: 0 1.2rem 0.35rem;
  white-space: nowrap;
}

.answer-field-shell.has-teaching-note.received .answer-teaching-note:not(.hidden) {
  color: color-mix(in srgb, var(--text-tertiary, #7a7a82) 70%, var(--success, #248a3d));
}

.answer-field-shell.has-teaching-note.incorrect .answer-teaching-note:not(.hidden) {
  color: var(--text-tertiary, #7a7a82);
}


/* Empty state — calm hero card under Study */
.empty-state {
  text-align: center;
  padding: 2.75rem 1.85rem 2.35rem;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
}

/*
 * Review home card: one stable width at every browser size.
 * H2 light shell; cap hugs the ritual (~power disc) so the island is not a wide empty slab.
 */
#practice-panel.active #practice-empty:not(.hidden) {
  width: min(100%, 20rem);
  margin-inline: auto;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.62);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(54, 95, 207, 0.05);
  border-radius: 18px;
  box-shadow: var(--shadow-sm);
}

/*
 * Study home ritual seat (locked · platform parity):
 * One place under the tabs — Safari tab, Home Screen Web App, desktop.
 * Optical high-of-center (not dead middle): flex center + extra bottom padding
 * lifts the island into the active band on tall phones without crowding tabs.
 * Does NOT lock body overflow (trackpad). Standalone height-lock stays separate.
 * Short / landscape viewports still top-dock (see max-height overrides).
 */
.app.practice-focus:has(#practice-empty:not(.hidden)) main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.app.practice-focus #practice-panel.active:has(#practice-empty:not(.hidden)) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  justify-content: safe center;
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  box-sizing: border-box;
  /* Asymmetric: more bottom free space → island sits ~high of center */
  padding-top: 0.45rem;
  padding-bottom: clamp(2.25rem, 11dvh, 5.5rem);
}

/* Active review card: same idea — fluid but capped, not breakpoint-jumpy */
#practice-panel.active:has(#practice-active:not(.hidden)) .practice-card {
  width: min(100%, 34rem);
  margin-inline: auto;
  box-sizing: border-box;
}

/*
 * B stable stack (2026-07-28): mid-session island sits top-stable, not re-centered
 * when the sample/note bands fill in. Home (empty) keeps high-of-center seat.
 */
.app.practice-focus #practice-panel.active:has(#practice-active:not(.hidden)) {
  justify-content: flex-start;
  padding-top: 0.65rem;
  padding-bottom: clamp(1.5rem, 8dvh, 4rem);
}

/*
 * Page overscroll seals (Study / Cards / Path).
 * Body is the scrollport — rubber-band at top/bottom is body bounce, not nested.
 * Do NOT lock height/overflow:hidden here (Safari trackpad needs body scroll).
 * Installed / Home Screen: extra shell below for Study; Cards/Path stay body-scroll.
 */
html:has(.app.practice-focus),
body:has(.app.practice-focus),
html:has(#cards-panel.active),
body:has(#cards-panel.active),
html:has(#stats-panel.active),
body:has(#stats-panel.active) {
  overscroll-behavior: none;
}

.app.practice-focus,
body:has(#cards-panel.active) .app,
body:has(#stats-panel.active) .app,
body:has(#cards-panel.active) #cards-panel.active,
body:has(#stats-panel.active) #stats-panel.active {
  overscroll-behavior: none;
}

/*
 * ─────────────────────────────────────────────────────────────
 * Installed app shell (PWA / Home Screen Web App)
 * display-mode: standalone | fullscreen | minimal-ui
 * + html.standalone-app (iOS navigator.standalone; set in app.js)
 *
 * Bounce is more visible without browser chrome. Browser-tab Study keeps
 * body scroll; installed Study on phone/tablet uses an app-like shell so
 * short surfaces (power mark home) do not rubber-band the whole window.
 * Desktop installed PWA keeps body scroll + overscroll none only.
 * ─────────────────────────────────────────────────────────────
 */
@media (display-mode: standalone),
  (display-mode: fullscreen),
  (display-mode: minimal-ui) {
  html,
  body {
    overscroll-behavior: none;
  }
}

html.standalone-app,
html.standalone-app body {
  overscroll-behavior: none;
}

/* Touch / narrow installed shell: Study as filled viewport (no body bounce) */
@media (display-mode: standalone) and (max-width: 1024px),
  (display-mode: fullscreen) and (max-width: 1024px),
  (display-mode: minimal-ui) and (max-width: 1024px),
  (display-mode: standalone) and (pointer: coarse),
  (display-mode: fullscreen) and (pointer: coarse),
  (display-mode: minimal-ui) and (pointer: coarse) {
  html:has(.app.practice-focus),
  body:has(.app.practice-focus) {
    height: 100%;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
  }

  body:has(.app.practice-focus) {
    max-height: 100svh;
    max-height: 100dvh;
  }

  .app.practice-focus {
    height: 100%;
    height: 100dvh;
    max-height: 100svh;
    max-height: 100dvh;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    overscroll-behavior: none;
    /* Notch / home indicator: all four insets (homescreen has no browser chrome) */
    padding:
      max(0.65rem, env(safe-area-inset-top, 0px))
      max(0.9rem, env(safe-area-inset-right, 0px))
      max(0.55rem, env(safe-area-inset-bottom, 0px))
      max(0.9rem, env(safe-area-inset-left, 0px));
  }

  .app.practice-focus .header {
    flex-shrink: 0;
  }

  .app.practice-focus main {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .app.practice-focus #practice-panel.active {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
  }

  /* Home power mark: same high-of-center seat as browser tab (base padding) */
  .app.practice-focus #practice-panel.active:has(#practice-empty:not(.hidden)) {
    justify-content: center;
    justify-content: safe center;
  }
}

/* Same Study shell when JS set html.standalone-app (iOS Home Screen) */
@media (max-width: 1024px), (pointer: coarse) {
  html.standalone-app:has(.app.practice-focus),
  html.standalone-app:has(.app.practice-focus) body {
    height: 100%;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
  }

  html.standalone-app:has(.app.practice-focus) body {
    max-height: 100svh;
    max-height: 100dvh;
  }

  html.standalone-app .app.practice-focus {
    height: 100%;
    height: 100dvh;
    max-height: 100svh;
    max-height: 100dvh;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    overscroll-behavior: none;
    padding:
      max(0.65rem, env(safe-area-inset-top, 0px))
      max(0.9rem, env(safe-area-inset-right, 0px))
      max(0.55rem, env(safe-area-inset-bottom, 0px))
      max(0.9rem, env(safe-area-inset-left, 0px));
  }

  html.standalone-app .app.practice-focus .header {
    flex-shrink: 0;
  }

  html.standalone-app .app.practice-focus main {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  html.standalone-app .app.practice-focus #practice-panel.active {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
  }

  html.standalone-app
    .app.practice-focus
    #practice-panel.active:has(#practice-empty:not(.hidden)) {
    justify-content: center;
    justify-content: safe center;
  }
}

/*
 * Desktop Study: calm shell fill — still no nested overflow:hidden on body.
 * Nested 100dvh + overflow:hidden diverges Safari vs Chrome; document scroll stays.
 */
@media (min-width: 721px) {
  .app.practice-focus {
    min-height: 100dvh;
    min-height: 100svh;
    padding:
      max(1.25rem, env(safe-area-inset-top, 0px))
      1.5rem
      max(1.1rem, env(safe-area-inset-bottom, 0px));
  }

  .app.practice-focus .header {
    flex-shrink: 0;
  }

  .app.practice-focus #practice-panel.active {
    flex: 1 1 auto;
    min-height: 0;
  }
}

/*
 * Stories overscroll parity (desktop): mobile already locks nested chain + overscroll.
 * At wider widths, body can still bounce; quiet that without breaking trackpad scroll.
 */
html:has(.app.read-focus),
body:has(.app.read-focus) {
  overscroll-behavior-y: none;
}

.app.read-focus {
  overscroll-behavior-y: none;
}

/* Wide screens: fit Review/Read in one stable viewport when content is modest */
@media (min-width: 721px) {
  .app {
    /* Tighter chrome so logo + tabs + card fit without dead page scroll */
    padding: 1.65rem 1.5rem 1.75rem;
    min-height: 100dvh;
  }

  .header {
    margin-bottom: 1.35rem;
  }

  .brand {
    margin-bottom: 0.7rem;
    gap: 0.35rem;
  }

  /* Compact logo by default on desktop (was ~300px and forced scroll) */
  .brand-logo {
    width: min(200px, 28vw);
    margin-bottom: 0.25rem;
  }

  /* Home seat is base (safe center). Desktop only softens empty padding. */
  #practice-panel.active:has(#practice-empty:not(.hidden)) .practice-goal-strip,
  #practice-panel.active:has(#practice-empty:not(.hidden)) .practice-meta {
    width: min(100%, 16rem);
  }

  #practice-panel.active #practice-empty:not(.hidden) {
    /* width from base rule — only padding softens on wide screens */
    padding: 2.5rem 2.1rem 2.15rem;
  }

  /* Same high-of-center bias as base; desktop can breathe a little more bottom */
  .app.practice-focus #practice-panel.active:has(#practice-empty:not(.hidden)) {
    padding-top: 0.55rem;
    padding-bottom: clamp(2.5rem, 12dvh, 6rem);
  }

  #practice-panel.active:has(#practice-active:not(.hidden)) .practice-card {
    /* Holistic density B: denser session placard — seats stay fixed */
    --study-mid-shell-pad-top: 0.9rem;
    padding: var(--study-mid-shell-pad-top) 1.2rem 0.82rem;
    min-height: min(13.6rem, 40dvh);
  }

  .match-room {
    --study-mid-shell-pad-top: 0.9rem;
    padding-top: var(--study-mid-shell-pad-top);
  }

  /* - Desktop Study: tabs only; home hero can breathe without lockup - */
  .app.practice-focus .header {
    margin-bottom: 0.65rem; /* chrome handoff rhythm */
  }

  /* Home disc size is fluid (clamp) — only padding density steps here */
  #practice-panel.active:has(#practice-empty:not(.hidden)) .empty-state--power-complete {
    padding: 1.85rem 1.35rem 1.55rem;
  }

  .practice-goal-strip,
  .practice-meta {
    max-width: 15rem;
    gap: 0.5rem;
    margin-bottom: 1.2rem;
  }

  .daily-goal-chip {
    min-height: 2.25rem;
    min-width: 3.65rem;
    padding: 0.36rem 0.95rem;
    font-size: 0.92rem;
  }

  .daily-progress {
    max-width: 11.5rem;
    height: 0.36rem;
  }

  .app.practice-focus .practice-goal-strip,
  .app.practice-focus .practice-meta {
    margin-bottom: 0.9rem;
  }

  .practice-card-top {
    margin-bottom: 0.55rem;
    min-height: 2.15rem;
  }

  .practice-card-top .direction-label {
    font-size: 0.72rem;
  }

  /* Holistic B: less empty air under the prompt on wide layouts */
  .prompt {
    margin-bottom: 0.55rem;
  }

  .prompt.norwegian {
    font-size: clamp(2.35rem, 3.8vw, 2.95rem);
    margin-bottom: 0.55rem;
  }

  .answer-form {
    max-width: 26rem;
  }

  .answer-form input[type="text"] {
    padding: 0.62rem 1.15rem;
    font-size: max(1.15rem, 16px);
    font-weight: 500;
  }

  .answer-field-shell {
    margin-bottom: 0.12rem;
    --field-note-seat: 1rem;
    --field-form-min: 2.5rem;
    --field-shell-h: calc(var(--field-form-min) + var(--field-note-seat));
    height: var(--field-shell-h);
    min-height: var(--field-shell-h);
    max-height: var(--field-shell-h);
  }

  .answer-field-shell.has-teaching-note.received,
  .answer-field-shell.has-teaching-note.incorrect {
    height: var(--field-shell-h);
    min-height: var(--field-shell-h);
    max-height: var(--field-shell-h);
  }

  .prompt {
    margin-bottom: 0.55rem;
  }

  .prompt.norwegian {
    margin-bottom: 0.55rem;
  }

  .feedback-slot {
    min-height: 1.95rem;
    margin-bottom: 0.2rem;
  }

  #practice-active .feedback-slot:has(.feedback.is-empty),
  #practice-active .feedback-slot:has(.feedback:empty) {
    height: 0;
    min-height: 0;
    margin: 0;
  }

  #practice-active .feedback-slot:has(.feedback:not(.is-empty)) {
    height: 1.95rem;
    min-height: 1.95rem;
    margin: 0 0 0.16rem;
  }

  .answer-actions {
    max-width: 26rem;
    margin-top: 0.1rem;
    min-height: 2.75rem;
  }

  .answer-actions-core {
    column-gap: 0.5rem;
  }

  .answer-actions .btn.answer-action--hear {
    min-height: 2.75rem;
    min-width: 7.25rem;
    padding: 0.58rem 1.45rem;
    font-size: 1.02rem;
  }

  .answer-actions .btn.answer-action--speak,
  .answer-actions .btn.answer-action--match {
    min-height: 2.2rem;
    height: 2.2rem;
  }

  .answer-actions .btn.answer-action--speak {
    min-width: 4.25rem;
    max-width: 5.1rem;
    font-size: 0.72rem;
  }
}

.empty-state .btn {
  min-height: 44px;
  touch-action: manipulation;
}

.empty-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  max-width: 16rem;
  margin: 0 auto;
}

.empty-actions .btn {
  width: 100%;
}

.empty-state--actions {
  padding: 2rem 1.35rem 1.75rem;
}

.empty-state--actions .empty-actions {
  margin-top: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}

/* P2: Home ritual — resolved composition, less void under the mark */
.empty-state--power-complete {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2.15rem 1.5rem 1.65rem;
}

.empty-state--power-complete .empty-actions {
  order: 1;
}

.empty-state--power-complete .empty-home-status {
  order: 2;
  /* Close under the disc — streak is caption, not a second block of void */
  margin-top: 0.4rem;
}

.empty-power {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  /* Button → optional teaser; shell tracks disc, not a tall empty stack */
  gap: 0.22rem;
  min-height: clamp(7.15rem, 18vw, 8rem);
  box-sizing: border-box;
}

/*
 * Power mark base = State 1 (not flossed).
 * Quiet chrome, but enough edge to read as a pressable coin on the light home island
 * (C1) — not the old heavy device-button metal. State 2/3 stay intentional.
 */
.power-on-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 6.25rem;
  height: 6.25rem;
  padding: 0;
  border: 1px solid rgba(54, 95, 207, 0.14);
  border-radius: 50%;
  background: linear-gradient(165deg, #ffffff 0%, #f3f6fd 100%);
  box-shadow:
    0 8px 22px rgba(54, 95, 207, 0.11),
    0 0 0 1px rgba(255, 255, 255, 0.65) inset,
    inset 0 1px 0 rgba(255, 255, 255, 0.95);
  cursor: pointer;
  touch-action: manipulation;
  /* T4: ease size between Study home hero and default mark */
  transition:
    width 0.28s var(--ease, ease),
    height 0.28s var(--ease, ease),
    transform 0.18s var(--ease),
    border-color 0.18s var(--ease),
    box-shadow 0.18s var(--ease),
    background 0.18s var(--ease);
}

.power-on-btn__glow {
  position: absolute;
  inset: -0.35rem;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(91, 154, 255, 0.28) 0%, rgba(91, 154, 255, 0) 72%);
  opacity: 0;
  transition: opacity 0.18s var(--ease);
  pointer-events: none;
}

.power-on-btn__icon {
  position: absolute;
  width: 2.35rem;
  height: auto;
  pointer-events: none;
  transition:
    width 0.28s var(--ease, ease),
    opacity 0.16s var(--ease),
    transform 0.18s var(--ease);
}

.power-on-btn__icon--on {
  opacity: 0;
  transform: scale(0.96);
}

@media (hover: hover) and (pointer: fine) {
  .power-on-btn:hover {
    border-color: rgba(54, 95, 207, 0.2);
    box-shadow:
      0 10px 26px rgba(54, 95, 207, 0.14),
      0 0 0 1px rgba(255, 255, 255, 0.7) inset,
      inset 0 1px 0 rgba(255, 255, 255, 0.95);
  }
}

@media (hover: hover) and (pointer: fine) {
  .power-on-btn:hover .power-on-btn__glow {
    opacity: 0.55;
  }
}

/* Press paint: finger = brief opacity only (see touch seal). Cursor/keyboard get full press. */
.power-on-btn:active {
  transform: scale(0.94);
  border-color: rgba(54, 95, 207, 0.32);
  background: linear-gradient(165deg, #f7faff 0%, #e8f0ff 100%);
  box-shadow:
    0 6px 18px rgba(54, 95, 207, 0.24),
    inset 0 2px 8px rgba(54, 95, 207, 0.08);
}

.power-on-btn:active .power-on-btn__glow {
  opacity: 1;
}

.power-on-btn:active .power-on-btn__icon--off {
  opacity: 0;
  transform: scale(0.92);
}

.power-on-btn:active .power-on-btn__icon--on {
  opacity: 1;
  transform: scale(1);
}

@media (hover: hover) and (pointer: fine) {
  .power-on-btn:focus-visible {
    transform: scale(0.94);
    border-color: rgba(54, 95, 207, 0.32);
    background: linear-gradient(165deg, #f7faff 0%, #e8f0ff 100%);
    box-shadow:
      0 6px 18px rgba(54, 95, 207, 0.24),
      inset 0 2px 8px rgba(54, 95, 207, 0.08);
  }

  .power-on-btn:focus-visible .power-on-btn__glow {
    opacity: 1;
  }

  .power-on-btn:focus-visible .power-on-btn__icon--off {
    opacity: 0;
    transform: scale(0.92);
  }

  .power-on-btn:focus-visible .power-on-btn__icon--on {
    opacity: 1;
    transform: scale(1);
  }
}

/*
 * Trio law (2026-07-27): same coin frame for all three states.
 * State 1 black · State 2 blue continue · State 3 reward rest.
 * Only fill / icon / pressability change — not disc size, mark %, or edge grammar family.
 */
.power-on-btn__icon--complete {
  opacity: 0;
  transform: scale(0.88);
}

.power-on-btn__icon--reward {
  opacity: 0;
  transform: scale(0.92);
  /* Same optical weight as flat icons; glossy asset still denser */
  width: 2.35rem;
  height: auto;
  object-fit: contain;
}

/* State 2: flossed + still due — brand fill CTA, same coin edge language as State 1 */
.power-on-btn--complete:not(:disabled) {
  cursor: pointer;
  border-color: rgba(54, 95, 207, 0.32);
  background: linear-gradient(165deg, #5b9aff 0%, #365fcf 52%, #2d4fb8 100%);
  box-shadow:
    0 8px 22px rgba(54, 95, 207, 0.22),
    0 0 0 1px rgba(255, 255, 255, 0.22) inset,
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

@media (hover: hover) and (pointer: fine) {
  .power-on-btn--complete:not(:disabled):hover {
    border-color: rgba(54, 95, 207, 0.38);
    box-shadow:
      0 10px 26px rgba(54, 95, 207, 0.26),
      0 0 0 1px rgba(255, 255, 255, 0.26) inset,
      inset 0 1px 0 rgba(255, 255, 255, 0.34);
  }
}

.power-on-btn--complete:not(:disabled) .power-on-btn__glow {
  /* Quieter than legacy 0.75 — still alive, not a second blue thrash next to live streak */
  opacity: 0.38;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.28) 0%, rgba(91, 154, 255, 0) 72%);
}

.power-on-btn--complete .power-on-btn__icon--off,
.power-on-btn--complete .power-on-btn__icon--on,
.power-on-btn--complete .power-on-btn__icon--reward {
  opacity: 0;
}

.power-on-btn--complete .power-on-btn__icon--complete {
  opacity: 1;
  transform: scale(1);
}

/* Cursor press only — finger uses global touch opacity seal */
@media (hover: hover) and (pointer: fine) {
  .power-on-btn--complete:not(:disabled):active,
  .power-on-btn--complete:not(:disabled):focus-visible {
    transform: scale(0.94);
  }
}

/* State 3: flossed + nothing due — soft rest coin, same edge family as State 1, not a CTA */
.power-on-btn--reward {
  cursor: default;
  border-color: rgba(54, 95, 207, 0.12);
  background: linear-gradient(165deg, #ffffff 0%, #f5f8fd 100%);
  box-shadow:
    0 6px 18px rgba(54, 95, 207, 0.08),
    0 0 0 1px rgba(255, 255, 255, 0.7) inset,
    inset 0 1px 0 rgba(255, 255, 255, 0.95);
  opacity: 1;
}

.power-on-btn--reward:disabled,
.power-on-btn--reward:disabled:active,
.power-on-btn--reward:disabled:focus-visible {
  transform: none;
  cursor: default;
  border-color: rgba(54, 95, 207, 0.12);
  background: linear-gradient(165deg, #ffffff 0%, #f5f8fd 100%);
  box-shadow:
    0 6px 18px rgba(54, 95, 207, 0.08),
    0 0 0 1px rgba(255, 255, 255, 0.7) inset,
    inset 0 1px 0 rgba(255, 255, 255, 0.95);
  opacity: 1;
}

@media (hover: hover) and (pointer: fine) {
  .power-on-btn--reward:disabled:hover {
    transform: none;
    border-color: rgba(54, 95, 207, 0.12);
    background: linear-gradient(165deg, #ffffff 0%, #f5f8fd 100%);
    box-shadow:
      0 6px 18px rgba(54, 95, 207, 0.08),
      0 0 0 1px rgba(255, 255, 255, 0.7) inset,
      inset 0 1px 0 rgba(255, 255, 255, 0.95);
  }
}

.power-on-btn--reward .power-on-btn__glow {
  /* Soft life only — not a halo that competes with State 2 */
  opacity: 0.28;
  background: radial-gradient(circle, rgba(91, 154, 255, 0.22) 0%, rgba(91, 154, 255, 0) 72%);
}

.power-on-btn--reward .power-on-btn__icon--off,
.power-on-btn--reward .power-on-btn__icon--on,
.power-on-btn--reward .power-on-btn__icon--complete {
  opacity: 0;
}

.power-on-btn--reward .power-on-btn__icon--reward {
  opacity: 1;
  transform: scale(1);
}

/* Hide reward art outside reward mode (default opacity 0 is not enough if cascade flips). */
.power-on-btn:not(.power-on-btn--reward) .power-on-btn__icon--reward {
  opacity: 0;
  pointer-events: none;
}

/*
 * Chrome handoff law (four tabs)
 * ─────────────────────────────
 * Study + Stories: no header lockup (power mark / in-shell flag+title carry brand).
 * Cards + Path: one shared quiet lockup size + one header margin so switching
 * between them does not resize the mark (second-look 2026-07-26).
 *
 * Instant show/hide (display:none). Soft max-height/opacity transitions forced
 * layout every frame and jerked on mobile / Home Screen Web App — worse than a pop.
 */
/*
 * Chrome handoff: hide lockup from first paint.
 * Prefer panel :has() so brand does not flash Cards/Path size before JS adds
 * .practice-focus / .read-focus. Class rules remain for the same seats.
 */
body:has(#practice-panel.active) .brand,
body:has(#read-panel.active) .brand,
.app.practice-focus .brand,
.app.read-focus .brand {
  display: none;
}

body:has(#practice-panel.active) .header,
body:has(#read-panel.active) .header,
.app.practice-focus .header,
.app.read-focus .header {
  margin-bottom: 0.5rem;
}

/* Shared brand band for library + orientation tabs */
body:has(#cards-panel.active) .header,
body:has(#stats-panel.active) .header {
  margin-bottom: 0.5rem;
}

body:has(#cards-panel.active) .brand,
body:has(#stats-panel.active) .brand {
  margin-bottom: 0.3rem;
  gap: 0.22rem;
}

/* C1: Cards + Path shared lockup step (~+12%) — keep both tabs in one family */
body:has(#cards-panel.active) .brand-logo,
body:has(#stats-panel.active) .brand-logo {
  width: min(157px, 42vw);
  margin-bottom: 0.12rem;
}

@media (min-width: 721px) {
  body:has(#practice-panel.active) .header,
  body:has(#read-panel.active) .header,
  .app.practice-focus .header,
  .app.read-focus .header,
  body:has(#cards-panel.active) .header,
  body:has(#stats-panel.active) .header {
    margin-bottom: 0.65rem;
  }

  body:has(#cards-panel.active) .brand-logo,
  body:has(#stats-panel.active) .brand-logo {
    width: min(184px, 24vw);
  }
}

@media (min-width: 1100px) {
  body:has(#cards-panel.active) .brand-logo,
  body:has(#stats-panel.active) .brand-logo {
    width: min(198px, 19vw);
  }
}

/*
 * H1 + C2: Study home — mark leads (~50% of disc). Fluid size.
 * Hit target stays well above 44px at every width.
 */
#practice-panel.active:has(#practice-empty:not(.hidden)) .power-on-btn {
  width: clamp(7.15rem, 18vw, 8rem);
  height: clamp(7.15rem, 18vw, 8rem);
}

/* Card shell stays size-stable card-to-card (no soft width/padding bounce) */
@media (prefers-reduced-motion: reduce) {
  .power-on-btn,
  .power-on-btn__icon {
    transition:
      transform 0.18s var(--ease),
      border-color 0.18s var(--ease),
      box-shadow 0.18s var(--ease),
      background 0.18s var(--ease),
      opacity 0.16s var(--ease);
  }
  .power-on-btn {
    transition:
      transform 0.18s var(--ease),
      border-color 0.18s var(--ease),
      box-shadow 0.18s var(--ease),
      background 0.18s var(--ease);
  }
}

/* Same mark % for black / white / glossy on home (trio frame) */
#practice-panel.active:has(#practice-empty:not(.hidden))
  .power-on-btn__icon:not(.power-on-btn__icon--reward),
#practice-panel.active:has(#practice-empty:not(.hidden)) .power-on-btn__icon--reward {
  width: clamp(3.55rem, 9vw, 4rem);
}

#practice-panel.active:has(#practice-empty:not(.hidden)) .empty-home-status {
  margin-top: 0.45rem;
}

#practice-panel.active:has(#practice-empty:not(.hidden)) .empty-state--power-complete {
  /* Vertical balance: similar air above mark and below streak */
  padding: 1.7rem 1.25rem 1.45rem;
}

.empty-power.power-on--celebrate .power-on-btn {
  animation: power-complete-rise 0.85s var(--ease) both;
}

.empty-power.power-on--celebrate .power-on-btn__glow {
  animation: power-complete-glow 1.5s ease-in-out 0.15s infinite alternate;
}

/* Seat 10: celebrate is soft/instant under reduced motion (no infinite glow) */
@media (prefers-reduced-motion: reduce) {
  .empty-power.power-on--celebrate .power-on-btn,
  .empty-power.power-on--celebrate .power-on-btn__glow {
    animation: none;
  }
}

/* Seat 4 / 6: finger hit floor even if a future size clamp shrinks the disc */
@media (pointer: coarse) {
  .power-on-btn {
    min-width: 44px;
    min-height: 44px;
  }
}

@keyframes power-complete-rise {
  0% {
    opacity: 0;
    transform: scale(0.82) translateY(14px);
  }
  55% {
    transform: scale(1.06) translateY(-5px);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes power-complete-glow {
  from {
    opacity: 0.55;
    transform: scale(1);
  }
  to {
    opacity: 1;
    transform: scale(1.1);
  }
}

.empty-home-status {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  width: min(100%, 12rem);
  margin: 0.35rem auto 0;
  /* Status type shell — enough for streak; no tall empty reserve */
  min-height: 2.45rem;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
}

.empty-home-status:empty {
  /* Keep the slot; hide only paint (display:none would thrash on first fill) */
  visibility: hidden;
}

/*
 * Caption under the power mark — status only, never a control.
 * Number = streak count. Label = READY (state 1) · STREAK (state 2) · dynamic (state 3).
 * Same seat for all three; no extra band for “tomorrow / soon”.
 */
.study-streak {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.12rem;
  min-width: 0;
  padding: 0.12rem 0.25rem 0;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  text-align: center;
  pointer-events: none;
  user-select: none;
  cursor: default;
}

.study-streak--live .study-streak__count {
  color: var(--brand);
}

/* State 1: ready cue; number may be 0 (never labeled STREAK) */
.study-streak--ready .study-streak__label {
  color: var(--brand);
  letter-spacing: 0.08em;
}

/* State 3: REST — same quiet meter seat as READY / STREAK */
.study-streak--reward .study-streak__label {
  letter-spacing: 0.08em;
}

/* At-risk: type only — no ring/border that looks like a button state */
.study-streak--risk .study-streak__count {
  color: var(--brand-deep);
}

.study-streak--risk .study-streak__label {
  color: var(--brand);
}

.study-streak__count {
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.study-streak__label {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  line-height: 1.2;
}

/* Optional quiet cue under the power mark (usually empty; tab says Study). */
.power-on-hint {
  margin: 0;
  max-width: 14rem;
  min-height: 1.25em;
  padding: 0 0.35rem;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-secondary);
  line-height: 1.25;
  text-align: center;
  text-transform: none;
}

.power-on-hint--action {
  color: var(--brand-deep);
  font-weight: 650;
}

.power-on-hint--idle {
  color: var(--text-tertiary);
  font-weight: 550;
  font-size: 0.86rem;
}

.power-on-teaser {
  margin: 0;
  min-height: 1.4em;
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--text-tertiary);
  line-height: 1.4;
  max-width: 16rem;
}

.empty-state .btn + .btn {
  margin-top: 0;
}

.hidden {
  display: none !important;
}

.boot-error {
  text-align: center;
  padding: 2rem 1.25rem;
  background: var(--surface-glass-strong);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

.boot-error-detail {
  font-size: 0.88rem;
  color: var(--text-tertiary);
  margin-bottom: 1.25rem;
}

body.modal-open {
  /* Lock the real scrollport (body) while a modal is open */
  overflow: hidden !important;
  overscroll-behavior: none;
  /* position:fixed + top pin applied in lockPageScroll() — kills iOS rubber-band */
  touch-action: none;
}

html:has(body.modal-open) {
  overflow: hidden !important;
  overscroll-behavior: none;
}

body.welcome-open .app {
  pointer-events: none;
  user-select: none;
}

/*
 * First-visit boot: hide the Review/app shell until the language gate is ready.
 * Applied in <head> via html.needs-welcome so the first paint never shows Review.
 * (practice-focus / header lockup live under .app — they cannot flash while hidden.)
 */
html.needs-welcome .app {
  visibility: hidden !important;
  pointer-events: none !important;
}

/*
 * First-visit door from first CSS paint — do not wait for the post-modal script
 * or app.js. While needs-welcome and the portal is not covering, force the gate
 * open even though the markup starts with .hidden (display:none !important).
 * When the portal is .is-visible (after language pick), keep the gate closed so
 * the ceremony covers the swap; needs-welcome still hides .app underneath.
 */
html.needs-welcome:not(:has(#track-switch-overlay.is-visible)) #welcome-modal.hidden {
  display: flex !important;
}

/* Product blue ambient glows stay off in the welcome room (Study ambient only). */
html.needs-welcome .ambient-brand,
body.welcome-open .ambient-brand {
  opacity: 0;
  visibility: hidden;
}

/*
 * Welcome craft (shipped): one continuous soft room from first paint through the door.
 * Body bed matches the modal field — no blue flash under the white room.
 */
/*
 * T3: first-paint + post-portal bed handoff.
 * needs-welcome / welcome-open share one soft white room (no blue flash under door).
 * Portal covers the swap to product ambient; Study is revealed under the cover.
 * Soften product ambient slightly so the first Study frame after leave is calm.
 */
html.needs-welcome body,
body.welcome-open {
  background:
    radial-gradient(
      90% 70% at 50% 42%,
      #ffffff 0%,
      #f7f9fd 42%,
      #eef2fa 72%,
      #e4eaf6 100%
    );
}

/* Product shell only when not in the welcome room (never override needs-welcome bed) */
html:not(.needs-welcome) body:not(.welcome-open) {
  background:
    radial-gradient(ellipse 90% 48% at 50% -8%, rgba(91, 154, 255, 0.14), transparent 68%),
    radial-gradient(ellipse 55% 42% at 100% 18%, rgba(54, 95, 207, 0.06), transparent 68%),
    radial-gradient(ellipse 45% 35% at 0% 62%, rgba(91, 154, 255, 0.045), transparent 72%),
    var(--bg);
}

.welcome-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  /* Pin from top — vertical centering re-jumps when door yields + list opens */
  align-items: flex-start;
  justify-content: center;
  padding:
    clamp(2.25rem, 11vh, 5rem)
    1.25rem
    max(1.25rem, env(safe-area-inset-bottom, 0px));
  /* Transparent so body.welcome-open / needs-welcome is the single room */
  background: transparent;
  pointer-events: auto;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.welcome-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: min(100%, 18rem);
  overflow: visible;
  padding: 1.25rem 1rem 1.75rem;
  /* Card dissolves into the white room — mark is the only door */
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  margin-block: 0;
  position: relative;
  /* Room for closed door or open list without re-centering the composition */
  min-height: min(70dvh, 34rem);
  justify-content: flex-start;
}

/*
 * Quiet rest under the base only — not a full white disk behind the bulb.
 * The old circular halo read as an awkward shadow puddle around the mark.
 */
.welcome-card::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(9.5rem, 46vw);
  height: min(3.4rem, 16vw);
  /* Sit under the two bands (foot of the mark), not centered on the glass */
  transform: translate(-50%, 58%);
  border-radius: 50%;
  background: radial-gradient(
    ellipse at 50% 40%,
    rgba(54, 95, 207, 0.1) 0%,
    rgba(54, 95, 207, 0.035) 48%,
    transparent 74%
  );
  pointer-events: none;
  z-index: 0;
}

.welcome-door {
  position: relative;
  z-index: 1;
  width: auto;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.welcome-logo {
  display: block;
  /* W1: fuller closed door hero. Open list: yields via :has rule below. */
  width: min(200px, 48vw);
  max-width: 12.75rem;
  height: auto;
  margin: 0;
  padding: 0;
  object-fit: contain;
  object-position: center bottom;
  image-rendering: auto;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
  /* Yield duration must match trackWelcomeMenuDock (~280ms incl. slack) */
  transition:
    width 0.22s var(--ease, ease),
    max-width 0.22s var(--ease, ease),
    transform 0.2s var(--ease, ease);
}

/* Ground under the door tracks the same beat so list dock has one motion, not two */
.welcome-card::before {
  transition:
    width 0.22s var(--ease, ease),
    height 0.22s var(--ease, ease),
    transform 0.22s var(--ease, ease),
    opacity 0.22s var(--ease, ease);
}

@media (min-width: 721px) {
  .welcome-logo {
    width: min(212px, 24vw);
    max-width: 13.25rem;
  }
}

@media (min-width: 1100px) {
  .welcome-logo {
    width: min(224px, 18vw);
    max-width: 14rem;
  }
}

/* When languages are open, door yields — list owns the stage (still smaller than closed) */
.category-picker--welcome:has(.category-picker-btn[aria-expanded="true"]) .welcome-logo {
  width: min(150px, 40vw);
  max-width: 9.5rem;
}

.welcome-card:has(.category-picker-btn[aria-expanded="true"])::before {
  width: min(7.25rem, 36vw);
  height: min(2.6rem, 12vw);
  transform: translate(-50%, 42%);
  opacity: 0.72;
}

.category-picker--welcome {
  position: relative;
  width: auto;
}

.category-picker--welcome .category-picker-menu {
  z-index: 10050;
  /* Width/position set fixed by fitCategoryMenuToViewport; W1 slightly wider dock */
  width: min(17.5rem, 88vw);
  min-width: min(17.5rem, 88vw);
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  max-height: min(28rem, 50dvh);
  /* Docked list under the door — one composition with the mark */
  background: rgba(255, 255, 255, 0.96);
  border: 1px solid color-mix(in srgb, var(--brand) 14%, transparent);
  border-radius: 1.15rem;
  box-shadow:
    0 14px 36px rgba(54, 95, 207, 0.12),
    0 0 0 1px rgba(255, 255, 255, 0.9) inset;
  padding: 0.45rem;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

/* Soft dock handle: list feels attached to the bulb, not a free popup */
.category-picker--welcome .category-picker-menu::before {
  content: "";
  position: absolute;
  top: -0.48rem;
  left: 50%;
  transform: translateX(-50%);
  width: 2.25rem;
  height: 0.34rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 16%, #e8eef8);
  pointer-events: none;
}

.category-picker--welcome .category-picker-menu.is-open-up {
  top: auto;
  bottom: calc(100% + 0.55rem);
}

/*
 * Prefer showing the full list. Only scroll when the viewport-fit max-height
 * is smaller than the 10-language list (JS sets the real max-height).
 */
.category-picker--welcome .category-picker-menu.is-scrollable {
  max-height: min(28rem, 50dvh);
}

/* Welcome language rows: calm pills (not dense utility list) */
.category-picker--welcome .category-option.category-option--compact {
  border-radius: 999px;
  min-height: 2.55rem;
  padding: 0.5rem 0.85rem;
  gap: 0.65rem;
  color: var(--text-secondary);
  border: 1px solid transparent;
  box-shadow: none;
}

.category-picker--welcome .category-option-label {
  color: inherit;
  font-weight: 600;
}

.category-picker--welcome .category-option-flag {
  font-size: 1.12rem;
}

@media (hover: hover) and (pointer: fine) {
  .category-picker--welcome .category-option:hover:not(:disabled):not(.active) {
    background: var(--brand-soft);
    color: var(--brand-deep);
  }
}

.category-picker--welcome .category-option.active {
  background: var(--brand-soft);
  color: var(--brand-deep);
  border: 1px solid transparent;
  border-radius: 999px;
  box-shadow: none;
}

.category-picker--welcome .category-option.active .category-option-label {
  color: var(--brand-deep);
}

.category-picker--progress .category-picker-menu.is-scrollable {
  /* Fallback; JS max-height from remaining viewport wins via inline style */
  max-height: min(28rem, 50dvh);
}

.category-picker-menu.is-scrollable {
  max-height: min(28rem, 50dvh);
}

/* The bulb is the only door — generous hit area; no chrome ring */
.category-picker-btn--welcome.welcome-door-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 44px;
  min-height: 44px;
  gap: 0;
  /* Soft pad so the mark is easy to hit without looking like a button chrome */
  padding: 0.65rem 0.85rem;
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: none;
  color: inherit;
  background: transparent;
  border: none;
  box-shadow: none;
  border-radius: 1.25rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/*
 * No rectangular focus/open ring — the mark is the door.
 * Keyboard focus: same quiet logo lift as hover. Open menu signals expanded.
 */
.category-picker-btn--welcome.welcome-door-btn:focus-visible {
  outline: none;
  background: transparent;
  border: none;
  box-shadow: none;
}

.category-picker-btn--welcome.welcome-door-btn:focus-visible .welcome-logo {
  transform: translateY(-2px) scale(1.02);
}

.category-picker-btn--welcome.welcome-door-btn[aria-expanded="true"] {
  background: transparent;
  border: none;
  box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
  .category-picker-btn--welcome.welcome-door-btn:hover {
    background: transparent;
    border: none;
    box-shadow: none;
  }

  .category-picker-btn--welcome.welcome-door-btn:hover .welcome-logo {
    transform: translateY(-2px) scale(1.02);
  }
}

.category-picker-btn--welcome.welcome-door-btn:active .welcome-logo {
  transform: translateY(0) scale(0.98);
}

.category-picker-btn--welcome.welcome-door-btn .welcome-logo {
  /* Keep width/max-width so open-list yield animates; transform for hover lift */
  transition:
    width 0.22s var(--ease, ease),
    max-width 0.22s var(--ease, ease),
    transform 0.2s var(--ease, ease);
}

@media (prefers-reduced-motion: reduce) {
  .category-picker-btn--welcome.welcome-door-btn .welcome-logo,
  .welcome-logo {
    transition: none;
  }
  .category-picker-btn--welcome.welcome-door-btn:hover .welcome-logo,
  .category-picker-btn--welcome.welcome-door-btn:focus-visible .welcome-logo,
  .category-picker-btn--welcome.welcome-door-btn:active .welcome-logo {
    transform: none;
  }
  .category-picker--welcome:has(.category-picker-btn[aria-expanded="true"]) .welcome-logo {
    /* Instant size change when motion is reduced */
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .category-picker-btn--welcome.welcome-door-btn .welcome-logo {
    transition: none;
  }

  .category-picker-btn--welcome.welcome-door-btn:hover .welcome-logo,
  .category-picker-btn--welcome.welcome-door-btn:focus-visible .welcome-logo,
  .category-picker-btn--welcome.welcome-door-btn:active .welcome-logo {
    transform: none;
  }
}

.confirm-modal {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
  padding:
    max(1.25rem, env(safe-area-inset-top, 0px))
    1.25rem
    max(1.25rem, env(safe-area-inset-bottom, 0px));
  background: rgba(18, 24, 38, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  overscroll-behavior: contain;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.confirm-card {
  width: min(100%, 22rem);
  min-height: 8.5rem;
  padding: 1.25rem 1.2rem 1.1rem;
  background: linear-gradient(145deg, var(--surface-glass-strong) 0%, rgba(248, 249, 253, 0.98) 100%);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  box-sizing: border-box;
}

.confirm-card--compact {
  width: fit-content;
  min-width: 10.5rem;
  max-width: min(100%, 15rem);
  min-height: 5.5rem;
  padding: 0.8rem 0.85rem 0.7rem;
  box-sizing: border-box;
}

.confirm-card--compact .confirm-message {
  margin-bottom: 0.65rem;
  font-size: 0.9rem;
  line-height: 1.4;
}

.confirm-card--compact .confirm-actions {
  gap: 0.4rem;
}

.confirm-card--compact .confirm-actions .btn {
  min-height: 2.15rem;
  padding: 0.38rem 0.7rem;
  font-size: 0.86rem;
}

.confirm-message {
  margin: 0 0 1rem;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink);
  text-align: center;
  white-space: pre-line;
}

.confirm-story-title {
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--brand);
}

.confirm-message-note {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

/* About - compact, one calm card (public scrapes + human readers) */
.about-modal {
  position: fixed;
  inset: 0;
  z-index: 220;
  display: flex;
  /* Top-pin on short viewports so tall Basics does not re-center as content paints */
  align-items: flex-start;
  justify-content: center;
  padding:
    max(1rem, env(safe-area-inset-top, 0px), min(8vh, 2.5rem))
    1rem
    max(1rem, env(safe-area-inset-bottom, 0px));
  background: rgba(18, 24, 38, 0.42);
  backdrop-filter: blur(8px) saturate(1.05);
  -webkit-backdrop-filter: blur(8px) saturate(1.05);
  overscroll-behavior: contain;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Roomier windows: center About (short card). Basics stays top-pin via min-height. */
@media (min-height: 720px) {
  .about-modal:not(.basics-modal) {
    align-items: center;
    padding: 1rem;
  }
}

.about-modal.hidden {
  display: none;
}

.about-card {
  display: flex;
  flex-direction: column;
  width: min(100%, 22.5rem);
  min-height: min(16rem, 42dvh);
  max-height: calc(100dvh - 2rem);
  overflow: hidden;
  background:
    linear-gradient(
      165deg,
      color-mix(in srgb, white 96%, var(--brand)) 0%,
      var(--surface-glass-strong) 100%
    );
  border: 1px solid var(--border-strong);
  border-radius: calc(var(--radius-sm) + 2px);
  box-shadow: var(--shadow-lg);
  box-sizing: border-box;
}

.about-card-head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  padding: 0.5rem 0.7rem 0;
  flex-shrink: 0;
}

.about-logo {
  display: block;
  height: 3.5rem;
  width: auto;
  margin: 0.1rem auto 1rem;
  object-fit: contain;
  /* Brand law: no blur/drop-shadow on the mark (softens edges) */
  filter: none;
}

.about-body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 1.15rem 1.1rem;
  min-height: 6rem;
}

/* about-lead removed - language lives in the global header */

.about-section {
  margin-bottom: 0.85rem;
}

.about-section:last-of-type {
  margin-bottom: 0.7rem;
}

.about-section-title {
  margin: 0 0 0.28rem;
  font-size: var(--text-2xs);
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  line-height: var(--lh-tight);
}

.about-section p {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--text-secondary);
  letter-spacing: -0.01em;
}

.about-section strong {
  color: var(--ink);
  font-weight: 600;
}

.about-inline-link {
  color: var(--brand-deep);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--brand) 35%, transparent);
  text-underline-offset: 0.15em;
}

.about-inline-link:focus-visible {
  color: var(--brand);
  text-decoration-color: var(--brand);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .about-inline-link:hover {
    color: var(--brand);
    text-decoration-color: var(--brand);
    outline: none;
  }
}

/* License unlock (About) — calm, no theater */
.about-license-actions {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  margin-top: 0.55rem;
}

.about-license-buy {
  display: inline-flex;
  align-self: flex-start;
  text-decoration: none;
  min-height: 44px;
  align-items: center;
}

.about-license-form {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0;
}

.about-license-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 500;
}

.about-license-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: stretch;
}

.about-license-input {
  flex: 1 1 10rem;
  min-width: 0;
  min-height: 44px;
  font-size: max(16px, 1rem);
  font-family: inherit;
  letter-spacing: 0.04em;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  box-sizing: border-box;
}

.about-license-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.about-license-redeem {
  min-height: 44px;
  flex: 0 0 auto;
}

.about-license-status-line {
  margin-top: 0.15rem;
}

/* Legal one-pagers (privacy / support) */
.legal-page {
  max-width: 36rem;
  margin: 0 auto;
  padding: 1.5rem 1.15rem 3rem;
  font-family: inherit;
  color: var(--text);
  line-height: 1.5;
}

.legal-page h1 {
  font-size: 1.35rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
  color: var(--brand-deep);
}

.legal-page h2 {
  font-size: 1rem;
  font-weight: 600;
  margin: 1.35rem 0 0.4rem;
}

.legal-page p,
.legal-page li {
  font-size: 0.95rem;
  color: var(--text-secondary);
  margin: 0 0 0.65rem;
}

.legal-page a {
  color: var(--brand);
}

.legal-page .legal-back {
  display: inline-block;
  margin-bottom: 1.25rem;
  font-size: 0.9rem;
}







.about-note {
  margin: 0;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-xs);
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: var(--text-sm) !important;
  line-height: var(--lh-body) !important;
  color: var(--text-secondary) !important;
}

/* Standalone notes between sections */
.about-body > .about-note {
  margin: 0 0 0.85rem;
}

/*
 * Continuity panel (Your path) — quiet account + backup in About.
 * Free multi-device · magic link · export always (Eli 2026-08-11).
 */
.continuity-panel {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.continuity-signin {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: stretch;
}

.continuity-email-label {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.continuity-email-input {
  box-sizing: border-box;
  width: 100%;
  min-height: 2.75rem;
  padding: 0.55rem 0.75rem;
  border-radius: 0.65rem;
  border: 1px solid var(--border-strong, var(--border));
  background: var(--surface, #fff);
  font: inherit;
  font-size: 1rem;
  color: var(--ink, var(--text));
}

.continuity-email-input:focus-visible {
  outline: 2px solid var(--brand-ring, var(--brand));
  outline-offset: 2px;
}

.continuity-signed {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.continuity-email-out {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--brand-deep, var(--brand));
  word-break: break-word;
}

.continuity-signed-actions,
.continuity-files {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}

.continuity-import-label {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.continuity-import-input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

.continuity-signin[hidden],
.continuity-signed[hidden],
.continuity-cloud-note[hidden] {
  display: none !important;
}











/* House credit: Rún mark (Primary) + public line. */
.about-house-line {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.65rem;
  margin: 0.85rem 0 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
}

.about-house-mark {
  display: block;
  width: 2.25rem;
  height: 2.25rem;
  flex-shrink: 0;
  border-radius: 50%;
  object-fit: cover;
}

.about-house-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.08rem;
  min-width: 0;
}

.about-house-name {
  font-size: var(--text-sm);
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--ink);
  line-height: var(--lh-tight);
}

.about-house-slogan {
  font-size: var(--text-sm);
  font-weight: 450;
  color: var(--text-tertiary);
  letter-spacing: -0.01em;
  line-height: 1.35;
}

.about-contact-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.55rem;
  margin: 0;
  padding-top: 0.55rem;
  font-size: var(--text-sm);
  line-height: var(--lh-tight);
}

.about-contact-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.about-contact-line a {
  color: var(--brand-deep);
  font-weight: 600;
  text-decoration: none;
  word-break: break-all;
}

.about-contact-line a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 0.15em;
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .about-contact-line a:hover {
    text-decoration: underline;
    text-underline-offset: 0.15em;
    outline: none;
  }
}

/* ── Basics modal - learning guide, not a plain About clone ── */
.basics-modal .basics-card {
  width: min(100%, 28.5rem);
  min-height: min(20rem, 55dvh);
  box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--brand) 18%, var(--border-strong));
  box-shadow:
    var(--shadow-lg),
    0 0 0 1px color-mix(in srgb, white 40%, transparent) inset,
    0 18px 48px color-mix(in srgb, var(--brand) 12%, transparent);
  background:
    linear-gradient(
      165deg,
      color-mix(in srgb, white 96%, var(--brand)) 0%,
      var(--surface-glass-strong) 42%,
      var(--surface-glass-strong) 100%
    );
}

.basics-body {
  min-height: 8rem;
  overscroll-behavior: contain;
}

.basics-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.65rem;
  flex-shrink: 0;
  padding: 0.95rem 0.85rem 0.85rem 1rem;
  border-bottom: 1px solid color-mix(in srgb, var(--brand) 10%, var(--border));
  background:
    radial-gradient(
      120% 90% at 12% 0%,
      color-mix(in srgb, var(--brand) 16%, transparent) 0%,
      transparent 58%
    );
}

.basics-hero {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  flex: 1;
}

/* Flag is decorative next to the title - not a control (no pill/bubble) */
.basics-hero-flag {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  font-size: 2rem;
  line-height: 1;
  background: none;
  box-shadow: none;
  pointer-events: none;
  user-select: none;
}

.basics-hero-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
}

.basics-modal-title {
  margin: 0;
  min-width: 0;
  font-size: clamp(1.45rem, 4.8vw, 1.85rem);
  font-weight: 780;
  letter-spacing: -0.035em;
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--brand-gradient, linear-gradient(135deg, #5b9aff 0%, #365fcf 100%));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.basics-close-btn {
  flex-shrink: 0;
  margin-top: 0.15rem;
}

.basics-body {
  padding: 0.85rem 0.9rem 1.05rem !important;
}

.basics-section {
  margin-bottom: 1.05rem;
}

.basics-section:last-of-type {
  margin-bottom: 0.15rem;
}

.basics-section-title {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  line-height: 1.25;
}

.basics-sound-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.basics-sound-list--compact {
  gap: 0.4rem;
}

.basics-sound-row {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.65rem 0.7rem;
  border-radius: 0.85rem;
  background:
    linear-gradient(
      145deg,
      color-mix(in srgb, white 92%, var(--brand)) 0%,
      var(--surface-2, #f4f6fb) 100%
    );
  border: 1px solid color-mix(in srgb, var(--brand) 8%, var(--border));
  box-shadow: 0 1px 0 color-mix(in srgb, white 70%, transparent) inset;
}

/* Visual mark only — not a control. Hearing lives on example words. */
.basics-glyph {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.85rem;
  min-height: 2.85rem;
  padding: 0.28rem 0.5rem;
  border: 1px solid color-mix(in srgb, var(--brand) 22%, transparent);
  border-radius: 0.8rem;
  background:
    linear-gradient(
      160deg,
      color-mix(in srgb, white 78%, var(--brand)) 0%,
      color-mix(in srgb, var(--brand-soft) 88%, white) 100%
    );
  color: var(--brand-deep);
  font-size: 1.5rem;
  font-weight: 750;
  line-height: 1;
  letter-spacing: -0.02em;
  cursor: default;
  user-select: none;
  pointer-events: none;
  box-shadow:
    0 2px 8px color-mix(in srgb, var(--brand) 8%, transparent),
    0 0 0 1px color-mix(in srgb, white 55%, transparent) inset;
}

.basics-glyph--sm {
  min-width: 2.75rem;
  min-height: 2.75rem;
  font-size: 1.28rem;
}

.basics-glyph--pair {
  min-width: 3.15rem;
  min-height: 2.75rem;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  padding-inline: 0.4rem;
}

.basics-sound-copy {
  min-width: 0;
  flex: 1;
  padding-top: 0.12rem;
}

.basics-sound-approx {
  margin: 0 0 0.4rem !important;
  font-size: 0.9rem !important;
  line-height: 1.4 !important;
  color: var(--ink) !important;
  font-weight: 500;
}

.basics-sound-approx strong {
  color: var(--brand-deep);
  font-weight: 700;
}

.basics-sound-approx em {
  font-style: normal;
  color: var(--text-secondary);
  font-weight: 600;
}


/* Two chips by content law — prefer one row; wrap only if words are very long */
.basics-sound-examples {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.45rem;
  margin: 0;
}

.basics-example {
  display: inline-flex;
  align-items: baseline;
  gap: 0.28rem;
  max-width: 100%;
  min-height: 2rem;
  padding: 0.28rem 0.5rem 0.28rem 0.4rem;
  border-radius: 999px;
  background: color-mix(in srgb, white 72%, var(--surface-2, #f4f6fb));
  border: 1px solid color-mix(in srgb, var(--brand) 10%, var(--border));
  line-height: 1.2;
}

.basics-example-gloss {
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 7.5rem;
}

.basics-word {
  appearance: none;
  display: inline;
  margin: 0;
  padding: 0.15rem 0.22rem;
  border: 0;
  border-radius: 0.3rem;
  background: none;
  color: var(--brand-deep);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--brand) 28%, transparent);
  text-underline-offset: 0.14em;
  cursor: pointer;
  touch-action: manipulation;
}

.basics-word:focus-visible {
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  text-decoration-color: var(--brand);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .basics-word:hover {
    color: var(--brand);
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    text-decoration-color: var(--brand);
    outline: none;
  }
}

.basics-word:active {
  transform: scale(0.98);
}

.basics-empty {
  margin: 0.5rem 0 0;
  text-align: center;
  color: var(--text-secondary);
  font-size: 0.92rem;
  line-height: 1.45;
}

@media (max-width: 720px) {
  .basics-card-head {
    padding: 0.85rem 0.7rem 0.75rem 0.8rem;
  }

  .basics-hero-flag {
    font-size: 1.75rem;
  }

  .basics-modal-title {
    font-size: 1.4rem;
  }

  .basics-body {
    padding: 0.75rem 0.75rem 0.95rem !important;
  }

  .basics-sound-row {
    padding: 0.55rem 0.6rem;
    gap: 0.55rem;
  }
}

.read-story-source {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}


























.add-card-form {
  position: relative;
  z-index: 30;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.8rem 0.9rem 0.75rem;
  margin-bottom: 0.65rem;
  box-shadow: var(--shadow-sm);
  /* Pair with Check review so list below does not leap when review opens */
  min-height: 9.5rem;
  box-sizing: border-box;
}

.add-card-form.is-suggesting {
  z-index: 40;
}

.add-card-form-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.65rem;
}

/* No empty header bar when not editing */
.add-card-form-head:not(:has(:not(.hidden))) {
  display: none;
  margin: 0;
}

.add-card-mode-label {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--brand-deep);
}

.add-card-field {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
  min-width: 0;
}

.add-card-field:focus-within {
  z-index: 2;
}

.add-card-field-nb .add-card-label {
  color: var(--brand-deep);
}

.add-card-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.add-card-field-join {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 0.55rem;
  color: var(--text-tertiary);
  user-select: none;
}

.add-card-field-join-mark {
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  opacity: 0.55;
}

.library-suggest {
  position: absolute;
  top: calc(100% + 0.25rem);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 12.5rem;
  overflow-y: auto;
  /* No -webkit-overflow-scrolling: momentum has been the default since iOS 13,
     and the legacy value is one of the things known to interact badly with a
     backdrop-filter on the same scrolling box. Not a verified fix for the
     scroll snap-back seen on device — just one less obsolete variable in it. */
  overscroll-behavior: contain;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  box-sizing: border-box;
}

/*
 * Last resort when the keyboard leaves almost nothing under the field: open
 * upward over the other field. JS sets max-height from visualViewport in both
 * directions — the 12.5rem above is only a ceiling, never the actual height.
 */
.library-suggest.is-above {
  top: auto;
  bottom: calc(100% + 0.25rem);
}

/* Same pulse language as Check card while typeahead / MT is working */
.library-suggest .library-suggest-loading,
.library-suggest .review-context-loading {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.2rem 0.35rem;
  padding: 0.35rem 0.15rem;
  min-height: 2.1rem;
  font-size: 0.84rem;
  font-weight: 550;
  color: var(--text-secondary);
}

.library-suggest-option {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.45rem;
  width: 100%;
  /* Roomy chip - full pill (999px) clipped multi-line text awkwardly */
  padding: 0.62rem 0.85rem;
  min-height: 2.55rem;
  border: none;
  border-radius: 0.85rem;
  background: transparent;
  font-family: inherit;
  text-align: left;
  line-height: 1.35;
  transition: background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.library-suggest-option.is-selectable {
  cursor: pointer;
  touch-action: manipulation;
}

.library-suggest-option.is-selectable:focus-visible {
  background: color-mix(in srgb, var(--brand-soft) 88%, white);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 16%, transparent);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .library-suggest-option.is-selectable:hover {
    background: color-mix(in srgb, var(--brand-soft) 88%, white);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 16%, transparent);
    outline: none;
  }
}

.library-suggest-option.is-info {
  cursor: default;
  opacity: 0.82;
}

/* English first, then Norwegian - same order as the form */
.library-suggest-option-native {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text-secondary);
  line-height: 1.35;
}

.library-suggest-option-foreign {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--brand-deep);
  line-height: 1.35;
}

.library-suggest-option-sep {
  font-size: 0.8rem;
  color: var(--text-tertiary);
  opacity: 0.7;
  line-height: 1.35;
}

.library-suggest-option-meta {
  flex-basis: 100%;
  margin-bottom: 0.1rem;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.3;
}

.add-card-review {
  background:
    linear-gradient(
      165deg,
      color-mix(in srgb, white 92%, var(--brand)) 0%,
      color-mix(in srgb, var(--surface-glass-strong) 92%, var(--brand)) 100%
    );
  border: 1px solid color-mix(in srgb, var(--brand) 22%, var(--border-strong));
  border-radius: var(--radius-sm);
  padding: 0.95rem 1rem 0.9rem;
  margin-bottom: 0.85rem;
  box-shadow:
    var(--shadow-sm),
    0 0 0 1px color-mix(in srgb, white 45%, transparent) inset;
  min-height: 9.5rem;
  box-sizing: border-box;
}

.add-card-review.hidden {
  display: none;
}

.add-card-review-head {
  margin: 0 0 0.7rem;
}

.add-card-review-heading {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--brand-deep);
  line-height: 1.2;
}

.add-card-review-pair {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.45rem 0.55rem;
  margin-bottom: 0.7rem;
}

.add-card-review-side {
  display: flex;
  flex-direction: column;
  gap: 0.22rem;
  flex: 1 1 8rem;
  min-width: 0;
}

.add-card-review-join {
  display: flex;
  align-items: center;
  align-self: center;
  padding-top: 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-tertiary);
  opacity: 0.55;
  user-select: none;
  flex: 0 0 auto;
}

.add-card-review-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.add-card-review-side.is-nb .add-card-review-label {
  color: var(--brand-deep);
}

.add-card-review-value {
  margin: 0;
  padding: 0.55rem 0.8rem;
  font-size: 0.95rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.35;
  color: var(--ink);
  border: 1px solid var(--border-strong);
  border-radius: 0.85rem;
  background: rgba(255, 255, 255, 0.78);
  word-break: break-word;
}

.add-card-review-side.is-nb .add-card-review-value {
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
  color: var(--brand-deep);
  background: color-mix(in srgb, var(--brand-soft) 55%, white);
}

.add-card-review-context {
  display: flex;
  /* Verdict and caution are both fit-content, so they sit side by side when
     the phone has room and stack when it does not. `Related in deck` is
     width:100% and always takes its own line. */
  flex-flow: row wrap;
  align-items: flex-start;
  gap: 0.5rem;
  /* Loading → LOOKS GOOD / Save Anyway: keep Check panel from jumping */
  min-height: 2.5rem;
  box-sizing: border-box;
}

.review-context-loading {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.84rem;
  font-weight: 550;
  color: var(--text-secondary);
}

.review-context-loading-dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
  animation: review-loading-pulse 1.1s ease-in-out infinite;
}

@keyframes review-loading-pulse {
  0%,
  100% {
    opacity: 0.45;
    transform: scale(0.9);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .review-context-loading-dot {
    animation: none;
  }
}

/* Chip hugs content, with air so long pairs don’t feel clipped */
.review-context-block {
  box-sizing: border-box;
  width: fit-content;
  max-width: 100%;
  padding: 0.7rem 1rem;
  border-radius: 0.95rem;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--border);
  line-height: 1.4;
}

.review-context-block.is-warning {
  border-color: rgba(154, 52, 18, 0.28);
  background: rgba(254, 242, 242, 0.75);
}

.review-context-block.is-match {
  border-color: rgba(47, 179, 82, 0.28);
  background: rgba(240, 253, 244, 0.8);
}

/*
 * A disabled Add looked exactly like a live one. On an exact duplicate the
 * button has always been disabled, so the learner met a full-strength blue
 * Add that swallowed every tap — the wall was real and invisible. If the
 * red block says stop, the button has to look stopped.
 */
#add-card-confirm:disabled {
  opacity: 0.45;
  filter: saturate(0.35);
  cursor: not-allowed;
  box-shadow: none;
}

/* Soft duplicate: a caution you can walk past. Red is reserved for Add being
   disabled — if the button still works, the block must not read as a stop. */
.review-context-block.is-caution {
  border-color: rgba(180, 83, 9, 0.3);
  background: rgba(255, 251, 235, 0.85);
}

.review-context-block.is-caution .review-context-title {
  color: #92400e;
}

.review-context-block.is-caution .review-context-hint {
  color: #b45309;
}

/* The caution states one fact and offers one route. Only the fact is amber —
   the route is guidance, and three warning-coloured lines read as alarm. */
.review-context-block .review-context-hint.is-quiet {
  color: var(--text-secondary);
  font-weight: 550;
  letter-spacing: 0;
}

/* Title-only green/red status - true pill like practice feedback */
.review-context-block.is-match:not(:has(.review-context-copy)):not(:has(.review-context-hint)),
.review-context-block.is-differs:not(:has(.review-context-copy)):not(:has(.review-context-hint)),
.review-context-block.is-warning:not(:has(.review-context-copy)):not(:has(.review-context-hint)) {
  display: inline-flex;
  align-items: center;
  min-height: var(--status-min-h);
  padding: var(--status-pad-y) var(--status-pad-x);
  border-radius: var(--chip-radius);
}

.review-context-block.is-match:not(:has(.review-context-copy)):not(:has(.review-context-hint)) .review-context-title,
.review-context-block.is-differs:not(:has(.review-context-copy)):not(:has(.review-context-hint)) .review-context-title,
.review-context-block.is-warning:not(:has(.review-context-copy)):not(:has(.review-context-hint)) .review-context-title {
  margin: 0;
}

.review-context-block.is-differs {
  border-color: rgba(185, 28, 28, 0.32);
  background: rgba(254, 226, 226, 0.82);
}

.review-context-block.is-differs .review-context-title {
  color: #991b1b;
}

.review-context-block.is-actionable {
  cursor: pointer;
  padding: 0.78rem 1.1rem;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.review-context-block.is-actionable:focus-visible {
  border-color: rgba(185, 28, 28, 0.5);
  background: rgba(254, 226, 226, 0.95);
  box-shadow: var(--shadow-sm);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .review-context-block.is-actionable:hover {
    border-color: rgba(185, 28, 28, 0.5);
    background: rgba(254, 226, 226, 0.95);
    box-shadow: var(--shadow-sm);
    outline: none;
  }
}

.review-context-hint {
  margin: 0.45rem 0 0;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #991b1b;
}

.review-context-block.is-clear {
  background: rgba(255, 255, 255, 0.42);
}

.review-context-block.is-info {
  width: 100%;
  border-color: rgba(37, 99, 235, 0.18);
  background: rgba(239, 246, 255, 0.65);
  border-radius: 1rem;
  padding: 0.65rem 0.8rem;
}

.review-context-block.is-info .review-context-title {
  color: #1e40af;
}

.review-context-block.is-info .review-context-list {
  margin-top: 0.4rem;
}

.review-context-title {
  margin: 0 0 0.28rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--text-secondary);
}

.review-context-copy {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.4;
  color: var(--ink);
}

.review-context-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.4rem;
}

.review-context-item {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  min-height: var(--chip-min-h);
  padding: var(--chip-pad-y) var(--chip-pad-x);
  border-radius: var(--chip-radius);
  border: 1px solid rgba(37, 99, 235, 0.16);
  background: rgba(255, 255, 255, 0.72);
  box-sizing: border-box;
}

.review-context-item-pair {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem;
  font-size: var(--chip-font);
  line-height: var(--lh-tight);
  color: var(--ink);
}

.review-context-item-pair .review-context-en {
  font-weight: 500;
  color: var(--text-secondary);
}

.review-context-item-pair .review-context-nb {
  font-weight: 600;
  color: var(--brand-deep);
}

.add-card-review-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  margin-top: 0.85rem;
  padding-top: 0.15rem;
}

/* Hug the label - not a full-width bar */
.add-card-review-actions .btn,
.add-card-form-actions .btn {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  min-height: 2.35rem;
  padding: 0.4rem 0.95rem;
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  border-radius: 999px;
}

.add-card-review-actions .btn.primary,
.add-card-form-actions .btn.primary {
  flex: 0 0 auto;
  min-width: 5.5rem;
  font-weight: 650;
}

/* Ca2: primary confirm is the clear next step after Check */
.add-card-review-actions .btn.primary {
  min-width: 6.5rem;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--brand) 18%, transparent);
}

.add-card-secondary-btn {
  color: var(--text-tertiary);
  background: transparent;
  border-color: color-mix(in srgb, var(--border-strong) 70%, transparent);
  font-weight: 550;
  font-size: 0.82rem;
}

.add-card-secondary-btn:focus-visible {
  color: var(--text-secondary);
  background: var(--surface-glass);
  border-color: var(--border-strong);
}
@media (hover: hover) and (pointer: fine) {
  .add-card-secondary-btn:hover {
    color: var(--text-secondary);
    background: var(--surface-glass);
    border-color: var(--border-strong);
  }
}

.card-item.is-editing {
  border-color: var(--brand);
  box-shadow: 0 0 0 1px var(--brand-ring);
}

/* Soft land after Add — confirmation, not a flash (photosensitive-safe). */
.card-item.is-just-added {
  border-color: color-mix(in srgb, var(--brand) 55%, var(--border-strong));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-ring) 70%, transparent);
  background: color-mix(in srgb, var(--brand) 6%, var(--surface-glass, #fff));
  transition:
    border-color 0.45s var(--ease, ease),
    box-shadow 0.45s var(--ease, ease),
    background 0.45s var(--ease, ease);
}

@media (prefers-reduced-motion: reduce) {
  .card-item.is-just-added {
    transition: none;
  }
}

@media (max-width: 560px) {
  .add-card-review-join {
    display: none;
  }

  .add-card-field-join {
    display: none;
  }
}

.add-card-form-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  margin-top: 0.55rem;
}

.add-card-form-actions .btn {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  min-height: var(--chip-min-h);
  padding: var(--chip-pad-y) var(--chip-pad-x);
  font-size: var(--chip-font);
  line-height: var(--lh-tight);
}

.add-card-form-actions .btn.ghost {
  min-width: 0;
}

.add-card-form-actions .btn.primary {
  margin-top: 0;
}

.add-card-form input {
  width: 100%;
  padding: 0.55rem 0.8rem;
  font-family: inherit;
  /* 16px minimum: iOS/iPadOS zooms the page on focus below this (including iPad “desktop” width) */
  font-size: 16px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass);
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
}

.add-card-form input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.add-card-field-nb input:focus {
  box-shadow: 0 0 0 3px rgba(54, 95, 207, 0.14);
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.form-row.add-card-fields {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0.45rem 0.55rem;
  margin-bottom: 0;
  align-items: end;
}

@media (max-width: 560px) {
  .form-row {
    grid-template-columns: 1fr;
  }

  .form-row.add-card-fields {
    grid-template-columns: 1fr;
  }
}

.add-card-form label {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-secondary);
}

.add-card-form input {
  padding: 0.55rem 0.8rem;
  font-family: inherit;
  font-size: 16px; /* iOS/iPadOS focus zoom */
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass);
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}

.add-card-form input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}







/* Library → Packs filter only: compact optional grid (not a second product) */
.library-themes {
  /* Ca3: calm gap when Packs mode is on */
  margin: 0 0 0.85rem;
  padding: 0.15rem 0 0;
  border: none;
  background: transparent;
}

.library-themes.hidden {
  display: none;
}

/* Soft separation so All → Packs does not feel like a hard second product */
#cards-panel.active:has(#library-themes:not(.hidden)) .library-controls {
  margin-bottom: 0.35rem;
}

#cards-panel.active:has(#library-themes:not(.hidden)) .library-themes {
  padding-top: 0.25rem;
  border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}

/* Clustered tiles - alphabetical order, denser than a full-width stack */
.library-themes-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.3rem;
  /* Don’t stretch short tiles to match an open preview in the same row
     (was turning Airport into a tall empty blue slab next to Bank). */
  align-items: start;
}

.library-theme-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0.36rem 0.42rem 0.32rem;
  border: 1px solid var(--border-strong, rgba(54, 95, 207, 0.14));
  border-radius: 10px;
  background: var(--surface-glass-strong, rgba(255, 255, 255, 0.9));
  box-shadow: none;
  min-width: 0;
  height: auto;
  align-self: start;
  transition:
    background 0.15s var(--ease, ease),
    border-color 0.15s var(--ease, ease);
}

/*
 * Added packs (Dining / Health in your shot): soft brand field so “in deck”
 * reads at a glance - a step clearer than a whisper tint, still not a press state.
 */
.library-theme-card.is-enabled {
  border-color: color-mix(in srgb, var(--brand, #365fcf) 48%, transparent);
  background: linear-gradient(
    145deg,
    color-mix(in srgb, var(--brand-bright, #5b9aff) 14%, #fff) 0%,
    color-mix(in srgb, var(--brand, #365fcf) 9%, #fff) 100%
  );
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand, #365fcf) 12%, transparent);
}

/*
 * Tile header only (not the word list):
 *   Name                 [Study / Add]
 *   status (fixed slot)  [Remove / spacer]
 * Fixed height — not min-height — so added vs not-added tiles match.
 */
.library-theme-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 3.55rem;
  grid-template-rows: 1.95rem 1.95rem;
  column-gap: 0.28rem;
  row-gap: 0.12rem;
  align-items: stretch;
  min-width: 0;
  height: 4.02rem;
  min-height: 4.02rem;
  max-height: 4.02rem;
  box-sizing: border-box;
}

/* Category title is the hero of the tile */
.library-theme-name {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  margin: 0;
  align-self: center;
  font-size: 0.95rem;
  font-weight: 780;
  letter-spacing: -0.035em;
  color: var(--ink, #231f20);
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* In-deck: name takes brand ink so it sits in the tinted field */
.library-theme-card.is-enabled .library-theme-name {
  color: var(--brand-deep, #1e3a8a);
}

.library-theme-status {
  grid-column: 1;
  grid-row: 2;
  margin: 0;
  align-self: center;
  min-height: 0;
  font-size: 0.68rem;
  line-height: 1.15;
  color: var(--muted, #5c6570);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.library-theme-status:empty {
  visibility: hidden;
}

.library-theme-card.is-enabled .library-theme-status {
  color: color-mix(in srgb, var(--brand-deep, #2849a8) 62%, var(--muted, #5c6570));
  font-weight: 550;
}

/*
 * Action column: always two equal slots (Study/Add + Remove/spacer).
 * DOM always has both children so height never depends on enabled state.
 */
.library-theme-actions {
  grid-column: 2;
  grid-row: 1 / -1;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  align-items: stretch;
  justify-content: space-between;
  align-self: stretch;
  gap: 0.12rem;
  width: 3.55rem;
  min-width: 3.55rem;
  height: 100%;
  box-sizing: border-box;
}

/* Invisible second slot on Add-only tiles — same footprint as Remove */
.library-theme-action-spacer {
  display: block;
  width: 100%;
  height: 1.85rem;
  min-height: 1.85rem;
  max-height: 1.85rem;
  flex-shrink: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Word list under the header — full card width; closed = no extra height */
.library-theme-preview {
  display: block;
  margin: 0.15rem 0 0;
  border: none;
  background: transparent;
  width: 100%;
  max-width: 100%;
  text-align: left;
  min-width: 0;
  min-height: 0;
}

.library-theme-preview:not([open]) {
  /* Keep only the summary line when closed (belt-and-braces vs grid stretch) */
  height: auto;
}

.library-theme-preview-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.18rem;
  padding: 0;
  margin: 0;
  font-size: 0.68rem;
  font-weight: 500;
  line-height: 1.1;
  color: var(--muted, #5c6570);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.library-theme-preview-summary::-webkit-details-marker {
  display: none;
}

.library-theme-preview-summary::before {
  content: "";
  width: 0.35rem;
  height: 0.35rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  opacity: 0.7;
  transition: transform 0.15s ease;
}

.library-theme-preview[open] > .library-theme-preview-summary::before {
  transform: rotate(45deg);
}

.library-theme-preview-summary:focus-visible {
  color: var(--brand-deep, #2a4a9b);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .library-theme-preview-summary:hover {
    color: var(--brand-deep, #2a4a9b);
    outline: none;
  }
}

.library-theme-word-list {
  list-style: none;
  width: 100%;
  max-width: 100%;
  margin: 0.2rem 0 0;
  /* Extra top inset so the first EN·L2 row never clips under the radius / fade */
  padding: 0.42rem 0.4rem 0.28rem;
  border-radius: 8px;
  background: color-mix(in srgb, var(--brand, #365fcf) 4%, var(--surface, #fff));
  border: 1px solid rgba(54, 95, 207, 0.08);
  /* Short peek - scroll inside for the rest; one open pack at a time */
  max-height: 8.5rem;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  text-align: left;
  box-sizing: border-box;
  scroll-padding-top: 0.35rem;
  /* Quiet scrollbar - cue is the edge fade, not a brand bar */
  scrollbar-width: thin;
  scrollbar-color: rgba(18, 24, 38, 0.2) transparent;
}

/*
 * More pack words below/above - same lesson as the language menu.
 * Fade mid-row so the next line peeks; no extra chevron chrome.
 */
.library-theme-word-list.has-more-below {
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 1.85rem),
    rgba(0, 0, 0, 0.5) calc(100% - 0.85rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 1.85rem),
    rgba(0, 0, 0, 0.5) calc(100% - 0.85rem),
    transparent 100%
  );
  box-shadow: inset 0 -1rem 0.85rem -0.65rem color-mix(in srgb, var(--brand-deep, #2849a8) 12%, transparent);
}

/* Top fade only after scroll - keep first row fully solid when just opened */
.library-theme-word-list.has-more-above {
  mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  box-shadow: inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep, #2849a8) 10%, transparent);
}

.library-theme-word-list.has-more-above.has-more-below {
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 1.85rem),
    rgba(0, 0, 0, 0.5) calc(100% - 0.85rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 1.85rem),
    rgba(0, 0, 0, 0.5) calc(100% - 0.85rem),
    transparent 100%
  );
  box-shadow:
    inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep, #2849a8) 10%, transparent),
    inset 0 -1rem 0.85rem -0.65rem color-mix(in srgb, var(--brand-deep, #2849a8) 12%, transparent);
}

.library-theme-word {
  /* Two flexible columns inside the tile - long words wrap, never clip mid-glyph */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  column-gap: 0.45rem;
  align-items: baseline;
  padding: 0.16rem 0;
  border-bottom: 1px solid rgba(26, 31, 38, 0.05);
  font-size: 0.8rem;
  line-height: 1.25;
  min-width: 0;
}

.library-theme-word:last-child {
  border-bottom: none;
  padding-bottom: 0.04rem;
}

.library-theme-word:first-child {
  padding-top: 0.1rem;
}

/* English - quieter anchor */
.library-theme-word-en {
  min-width: 0;
  font-weight: 450;
  font-size: 0.76rem;
  color: var(--muted, #5c6570);
  text-align: left;
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Target language - slightly stronger; wraps instead of cutting off */
.library-theme-word-l2 {
  min-width: 0;
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: -0.01em;
  color: var(--ink, #1a1f26);
  text-align: left;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.library-theme-btn {
  flex-shrink: 0;
  min-height: 1.5rem;
  padding-inline: 0.48rem;
  font-size: 0.7rem;
}

/*
 * Study + Add: same horizontal pill on every form factor.
 * Fixed height so platform coarse 44px rule cannot stretch them.
 */
.btn.primary.library-theme-btn.library-theme-btn--study,
.library-theme-btn--study,
.btn.secondary.library-theme-btn.library-theme-btn--add,
.library-theme-btn--add {
  display: inline-flex;
  width: 100%;
  min-width: 0;
  flex: 0 0 1.9rem;
  min-height: 1.9rem !important;
  max-height: 1.9rem;
  height: 1.9rem;
  padding: 0 0.45rem;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
  box-shadow: none;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
}

@media (hover: hover) and (pointer: fine) {
  .btn.primary.library-theme-btn.library-theme-btn--study:hover, .library-theme-btn--study:hover {
    box-shadow: 0 4px 12px rgba(54, 95, 207, 0.22);
  }
}

/* Remove: same footprint as the Add-only spacer */
.btn.ghost.library-theme-btn.library-theme-btn--remove,
.library-theme-btn--remove {
  display: inline-flex;
  width: 100%;
  min-width: 0;
  flex: 0 0 1.85rem;
  min-height: 1.85rem !important;
  max-height: 1.85rem;
  height: 1.85rem;
  padding: 0 0.2rem;
  margin-top: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: var(--text-tertiary);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
  text-align: center;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
}

.btn.ghost.library-theme-btn.library-theme-btn--remove:focus-visible, .library-theme-btn--remove:focus-visible {
  color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink));
  background: var(--error-soft, rgba(215, 0, 21, 0.08));
  border-color: color-mix(in srgb, var(--error, #d70015) 18%, transparent);
  box-shadow: none;
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn.ghost.library-theme-btn.library-theme-btn--remove:hover, .library-theme-btn--remove:hover {
    color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink));
    background: var(--error-soft, rgba(215, 0, 21, 0.08));
    border-color: color-mix(in srgb, var(--error, #d70015) 18%, transparent);
    box-shadow: none;
    outline: none;
  }
}

.library-theme-btn:disabled {
  opacity: 0.72;
  cursor: default;
}

.library-themes-body:empty {
  display: none;
}

@media (max-width: 520px) {
  .library-themes-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.28rem;
  }

  .library-theme-card {
    padding: 0.32rem 0.38rem 0.28rem;
  }

  .library-theme-name {
    font-size: 0.9rem;
  }

  /* Keep Study/Add/Remove on the shared pill metrics — no circle override */

  .library-theme-word {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    column-gap: 0.4rem;
  }
}

/*
 * Keep 2 columns at every width while we have 10 packs.
 * 3-col left Work alone on the last row - don’t invent packs just to “fill.”
 * When pack count is a multiple of 3, we can revisit a wider grid.
 */
@media (min-width: 640px) {
  .library-themes-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem;
  }
}

.library-header {
  position: relative;
  /* Rest below add form (z=30); open list must win — see :has expanded */
  z-index: 25;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  /* Tight into the add form — count is a short meter */
  margin-bottom: 0.5rem;
}

/*
 * Language list is a fixed child of this header. Stacking is trapped by the
 * header’s z-index — so when open, raise above .add-card-form (30) and
 * .add-card-form.is-suggesting (40).
 */
.library-header:has(.library-lang-cue[aria-expanded="true"]),
.library-header:has(#library-lang-menu:not(.hidden)) {
  z-index: 55;
}

/*
 * Flag + count: one quiet meter cluster.
 * Flag = soft identity (Study mid-session grammar), not a second glass chip
 * fighting the number. Count remains the sole Cards meter (tab already says Cards).
 */
.library-header-lead {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}

/* Anchor: menu docks under the flag only (not under the whole header row) */
.library-lang-picker {
  position: relative;
  flex: 0 0 auto;
  z-index: 26;
  display: flex;
  align-items: center;
}

.library-lang-cue {
  appearance: none;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  min-width: 1.75rem;
  min-height: 1.75rem;
  padding: 0;
  border: none;
  border-radius: 0.4rem;
  background: transparent;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    background 0.15s var(--ease),
    box-shadow 0.15s var(--ease);
  font-family: inherit;
}

@media (hover: hover) and (pointer: fine) {
  .library-lang-cue:hover,
  .library-lang-cue:focus-visible {
    background: var(--brand-soft);
  }

  .library-lang-cue:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 20%, transparent);
    outline: none;
  }
}

.library-lang-cue[aria-expanded="true"] {
  background: color-mix(in srgb, var(--brand-soft) 85%, transparent);
}

.library-lang-cue-flag {
  font-size: 1.2rem;
  line-height: 1;
  filter: drop-shadow(0 0.5px 0.5px rgba(15, 23, 42, 0.06));
}

/*
 * Sole Cards number meter (tab already says Cards).
 * Calm type next to the flag — not a heavy title competing with the control.
 */
.library-deck-meta {
  margin: 0;
  min-width: 0;
  font-size: 1.2rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--ink);
}

/*
 * Cards language list — Path/Stories parity:
 * dock under flag, capped height, scroll + edge fades + chevron cues.
 */
.library-lang-menu {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  width: 14rem;
  min-width: 14rem;
  max-width: min(14rem, calc(100vw - 1.25rem));
  /* Hard cap so overflow is real before JS fits remaining viewport */
  max-height: min(22rem, 50dvh);
  height: auto;
  overflow: hidden;
  background: color-mix(in srgb, white 97%, var(--surface-2, #f8f9fd));
  backdrop-filter: blur(18px) saturate(1.05);
  -webkit-backdrop-filter: blur(18px) saturate(1.05);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.35rem;
  z-index: 50;
  box-sizing: border-box;
}

.library-lang-menu.hidden {
  display: none !important;
}

.library-lang-menu.is-open-up {
  top: auto;
  bottom: calc(100% + 0.35rem);
}

.library-lang-menu-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: thin;
  scrollbar-color: rgba(18, 24, 38, 0.22) transparent;
}

/* Edge fades — same language as Stories / Path */
.library-lang-menu.has-more-below .library-lang-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow: inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

.library-lang-menu.has-more-above .library-lang-menu-scroll {
  mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  box-shadow: inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep) 10%, transparent);
}

.library-lang-menu.has-more-above.has-more-below .library-lang-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow:
    inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep) 10%, transparent),
    inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

/* Reuse Path scroll-cue chrome on Cards list */
.library-lang-menu.is-scrollable .category-picker-scroll-cue {
  display: flex;
}

.library-lang-menu.has-more-below .category-picker-scroll-cue--down {
  opacity: 1;
}

.library-lang-menu.has-more-above .category-picker-scroll-cue--up {
  opacity: 1;
}

@media (pointer: coarse) {
  /* Hit target ≥44px; paint stays quiet (no chip border) — same as Study flag */
  .library-lang-cue {
    min-height: 44px;
    min-width: 44px;
    width: 44px;
  }

  .library-header-lead {
    gap: 0.35rem;
    min-height: 44px;
  }
}

/*
 * Rare / caution action — quiet at rest (tertiary).
 * Soft red only with a real cursor (hover) or on press (:active).
 * Never always-on red for touch (cursor-only hover paint law · 2026-07-26).
 */
.library-reset-btn {
  flex-shrink: 0;
  /* Baseline with the count; no tall hit-box stretching the row */
  min-height: 0;
  padding: 0.1rem 0.35rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--text-tertiary);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.15;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    color 0.15s var(--ease),
    background 0.15s var(--ease),
    border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease);
}

/* Touch: larger target only — stay quiet grey at rest (no permanent caution red) */
@media (pointer: coarse) {
  .library-reset-btn {
    padding: 0.35rem 0.55rem;
    min-height: 2.5rem;
    color: var(--text-tertiary);
    border-color: transparent;
    background: transparent;
  }

  /* Focus after tap must not stick as red “hover” */
  .library-reset-btn:focus,
  .library-reset-btn:focus-visible {
    color: var(--text-tertiary);
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    outline: none;
  }
}

/* Keyboard / fine pointer: red only when intentional */
@media (hover: hover) and (pointer: fine) {
  .library-reset-btn:hover {
    color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink));
    background: var(--error-soft, rgba(215, 0, 21, 0.08));
    border-color: color-mix(in srgb, var(--error, #d70015) 22%, transparent);
    outline: none;
  }

  .library-reset-btn:focus-visible {
    color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink));
    background: var(--error-soft, rgba(215, 0, 21, 0.08));
    border-color: color-mix(in srgb, var(--error, #d70015) 22%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--error, #d70015) 16%, transparent);
    outline: none;
  }
}

.library-reset-btn:active {
  color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink));
  background: color-mix(in srgb, var(--error, #d70015) 12%, transparent);
  border-color: color-mix(in srgb, var(--error, #d70015) 18%, transparent);
}

.library-controls {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-bottom: 0.75rem;
}

.library-search {
  width: 100%;
  min-height: 2.55rem;
  padding: 0.7rem 1rem;
  font-family: inherit;
  /* 16px minimum: iOS/iPadOS focus zoom (iPad often uses desktop CSS width) */
  font-size: 16px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--ink);
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.library-search:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

.library-search.library-search--ready {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

.library-search::placeholder {
  color: var(--text-tertiary);
}

/* All · Phrases · Yours · Themes - one row, equal segments */
.filter-chips {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.35rem;
  width: 100%;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 2.15rem;
  min-width: 0;
  padding: 0.35rem 0.35rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition:
    color 0.15s var(--ease),
    background 0.15s var(--ease),
    border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .filter-chip:hover {
    color: var(--brand-deep);
    border-color: transparent;
    background: var(--brand-soft);
  }
}

.filter-chip.active {
  background: var(--brand-gradient);
  border-color: transparent;
  color: #fff;
  box-shadow: none;
}

/* Packs last: optional filter - white chip body, stronger brand type + outline.
   Avoid filled wash (reads as “always pressed”); type must still read clearly. */
.filter-chip--themes:not(.active) {
  color: var(--brand-deep, #1e3a8a);
  font-weight: 750;
  letter-spacing: -0.015em;
  border-color: color-mix(in srgb, var(--brand, #365fcf) 58%, transparent);
  background: var(--surface-glass-strong);
  box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
  .filter-chip--themes:not(.active):hover {
    color: var(--brand-deep, #1e3a8a);
    border-color: var(--brand, #365fcf);
    background: color-mix(in srgb, var(--brand-soft, #e8efff) 55%, var(--surface-glass-strong));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand, #365fcf) 14%, transparent);
  }
}



/* Library section jump (All only) — sticky index for long decks.
   One fluid layout at every width (same idea as Study home card):
   equal columns keep subcategory spacing even while resizing;
   no 720↔721 flip (scroll strip vs space-between) and no shape jump.
   Sticky is relative to body (page scrollport) — trackpad + keyboard. */
/* Ca4: jump bar quieter — index aid, not a second primary nav */
.library-jump {
  position: sticky;
  top: 0.45rem;
  z-index: 20;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0 0 0.85rem;
  /* Fluid inset — blue active pill stays inside the rounded shell */
  padding: clamp(0.18rem, 0.55vw, 0.3rem) clamp(0.22rem, 0.85vw, 0.42rem);
  /*
   * Opaque shell — frosted glass was letting card action labels (Edit/Hear/Delete)
   * ghost through the sticky index on mobile browsers (Android Chrome especially).
   */
  background: var(--surface);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid color-mix(in srgb, var(--border-strong) 85%, transparent);
  border-radius: 999px;
  box-shadow: 0 4px 16px rgba(54, 95, 207, 0.07);
  overflow: hidden;
  isolation: isolate;
}

.library-jump.hidden {
  display: none;
}

.library-jump-track {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: stretch;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  gap: clamp(0.04rem, 0.35vw, 0.15rem);
  min-width: 0;
  overflow: hidden;
}

.library-jump-track::after {
  display: none;
  content: none;
}

.library-jump-chip {
  /* Equal columns → even gaps between Essentials…Wider at every width */
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 1.85rem;
  padding: 0.22rem clamp(0.08rem, 0.45vw, 0.38rem);
  border: 1px solid transparent;
  border-radius: var(--chip-radius);
  background: transparent;
  color: var(--text-tertiary);
  font-family: inherit;
  font-size: clamp(0.56rem, 0.3rem + 1vw, 0.7rem);
  font-weight: 550;
  letter-spacing: -0.02em;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    color 0.2s var(--ease),
    background 0.2s var(--ease),
    border-color 0.2s var(--ease);
}

.library-jump-chip:focus-visible {
  color: var(--brand-deep);
  background: var(--brand-soft);
  border-color: var(--brand-ring);
  outline: none;
}

@media (hover: hover) and (pointer: fine) {
  .library-jump-chip:hover {
    color: var(--brand-deep);
    background: var(--brand-soft);
    border-color: var(--brand-ring);
    outline: none;
  }
}

.library-jump-chip.is-active {
  color: #fff;
  background: var(--brand-gradient);
  border-color: transparent;
  box-shadow: none;
  font-weight: 650;
}

/* Ca5: row actions ≥44px whenever fingers are primary (incl. wide iPad) */
@media (pointer: coarse) {
  .card-item-actions .btn {
    min-height: 48px;
    min-width: 2.75rem;
    touch-action: manipulation;
    padding: 0.4rem 0.65rem;
    font-weight: 600;
  }

  .filter-chip {
    min-height: 44px;
    touch-action: manipulation;
  }

  .page-float-top-btn {
    min-height: 48px;
    min-width: 48px;
  }
}

/*
 * Cards panel: one calm max width at every browser size (Study-card pattern).
 * Avoids 720↔721 full-bleed ↔ capped jumps that reflow the jump bar.
 */
#cards-panel.active {
  width: min(100%, 40rem);
  margin-inline: auto;
  box-sizing: border-box;
  min-width: 0;
}

/*
 * Cards content (library-forward): stack under shared chrome handoff brand.
 * Brand size/margin: see “Chrome handoff law” above.
 */
/* - Desktop Library: calm stack, clear filters vs jump, readable list - */
@media (min-width: 721px) {
  /* width owned by base #cards-panel.active (fluid at every size) */

  .library-header {
    margin-bottom: 0.55rem;
    align-items: center;
  }

  .library-deck-meta {
    font-size: 1.25rem;
  }

  .library-reset-btn {
    font-size: 0.82rem;
  }

  .add-card-form {
    padding: 0.85rem 1rem 0.8rem;
    margin-bottom: 0.65rem;
  }

  .form-row.add-card-fields {
    gap: 0.5rem 0.7rem;
  }

  .add-card-form input {
    padding: 0.6rem 0.9rem;
    font-size: 16px; /* iOS/iPadOS focus zoom (desktop-width iPad too) */
  }

  .add-card-form-actions {
    margin-top: 0.55rem;
    gap: 0.45rem;
  }

  .add-card-form-actions .btn {
    min-height: 2.2rem;
    padding: 0.38rem 0.9rem;
  }

  .library-controls {
    gap: 0.5rem;
    margin-bottom: 0.65rem;
  }

  .library-search {
    padding: 0.75rem 1.05rem;
    font-size: 16px;
  }

  /* All / Phrases / Yours / Packs - one equal row */
  .filter-chips {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.35rem;
    width: 100%;
  }

  .filter-chip {
    width: 100%;
    min-height: 2.2rem;
    padding: 0.35rem 0.3rem;
    font-size: 0.8rem;
  }

  /* Jump bar: base fluid rules only — no layout flip at 721px */

  .card-list {
    gap: 1.5rem;
  }

  .card-group-title {
    margin-bottom: 0.65rem;
    font-size: 0.74rem;
    letter-spacing: 0.07em;
  }

  .card-group-list {
    gap: 0.55rem;
  }

  .card-item {
    padding: 1rem 1.2rem;
    gap: 1.15rem;
    transition:
      border-color 0.2s var(--ease),
      box-shadow 0.2s var(--ease);
  }

  @media (hover: hover) and (pointer: fine) {
    .card-item:hover {
      box-shadow: var(--shadow-md);
    }
  }

  .card-item-foreign {
    font-size: 1.15rem;
  }

  .card-item-native {
    font-size: 0.94rem;
  }

  .card-item-actions {
    gap: 0.4rem;
  }

  .card-item-actions .btn {
    min-height: 2.15rem;
    padding: 0.35rem 0.75rem;
  }

  .library-empty {
    padding: 2.75rem 2rem;
  }
}

/* - Mobile Library: must follow base library + card-item so overrides win - */
@media (max-width: 720px) {
  /* #cards-panel width: fluid base rule (min 100%, 40rem) — no full-bleed flip */

  /* Ca1: list-first — tighten top stack so cards arrive sooner */
  .library-header {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    text-align: left;
    gap: 0.55rem;
    margin-bottom: 0.4rem;
  }

  .library-deck-meta {
    font-size: 1.15rem;
  }

  .library-reset-btn {
    /* Keep a usable tap target without stretching the meter row */
    min-height: 2.5rem;
    padding: 0.45rem 0.5rem;
    display: inline-flex;
    align-items: center;
  }

  /* Add form: stacked fields — more compact corridor to the list */
  .add-card-form {
    padding: 0.6rem 0.7rem 0.55rem;
    margin-bottom: 0.4rem;
  }

  .form-row.add-card-fields {
    grid-template-columns: 1fr;
    gap: 0.4rem;
  }

  .add-card-field-join {
    display: none;
  }

  .add-card-form label,
  .add-card-label {
    font-size: 0.68rem;
    margin-bottom: 0.2rem;
  }

  .add-card-form input {
    font-size: 16px; /* prevent iOS focus zoom */
    min-height: 44px;
    padding: 0.55rem 0.85rem;
  }

  .add-card-form-actions {
    margin-top: 0.4rem;
    gap: 0.35rem;
  }

  .add-card-form-actions .btn {
    min-height: 44px;
    padding-inline: 1rem;
    font-size: 0.88rem;
    font-weight: 600;
  }

  .add-card-form-actions .btn.primary {
    flex: 1 1 auto;
    font-weight: 650;
  }

  .library-suggest-option {
    min-height: 44px;
    padding: 0.6rem 0.85rem;
    align-items: center;
  }

  /* Confirm pair: full-width action row */
  .add-card-review {
    padding: 0.75rem 0.75rem;
    margin-bottom: 0.55rem;
  }

  .add-card-review-join {
    display: none;
  }

  .add-card-review-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.7rem;
    justify-content: stretch;
  }

  .add-card-review-actions .btn {
    flex: 1 1 calc(50% - 0.2rem);
    min-width: calc(50% - 0.2rem);
    width: auto;
    min-height: 48px;
    justify-content: center;
    font-weight: 600;
  }

  .add-card-review-actions .btn.primary {
    flex: 1 1 100%;
  }

  .add-card-review-actions .btn.hidden {
    display: none;
  }

  /* Search + filters — denser corridor to the first card (Ca1) */
  .library-controls {
    gap: 0.32rem;
    margin-bottom: 0.4rem;
  }

  .library-search {
    font-size: 16px; /* prevent iOS focus zoom */
    min-height: 44px;
    padding: 0.55rem 0.85rem;
  }

  .filter-chips {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.24rem;
    max-width: 100%;
    margin: 0;
    overflow: visible;
  }

  .filter-chip {
    width: 100%;
    min-height: 44px;
    padding-inline: 0.2rem;
    font-size: 0.74rem;
    font-weight: 600;
    touch-action: manipulation;
  }

  /* Jump bar stays equal-column fluid (base). Only sticky top tightens on phone. */
  .library-jump {
    top: 0.2rem;
    margin-bottom: 0.5rem;
    padding: 0.16rem 0.22rem;
  }

  .card-group {
    scroll-margin-top: 3.25rem;
  }

  .card-list {
    gap: 1.1rem;
  }

  .card-group-title {
    margin-bottom: 0.4rem;
    font-size: 0.68rem;
  }

  .card-group-list {
    gap: 0.4rem;
  }

  /*
   * Card rows: stretch text (no zigzag). Actions = equal 3-up like Review.
   * align-items: stretch must beat base align-items: center.
   */
  .card-item {
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
    padding: 0.95rem 0.9rem 0.85rem;
  }

  .card-item-text {
    width: 100%;
    flex: none;
  }

  .card-item-foreign {
    font-size: 1.08rem;
  }

  .card-item-native {
    font-size: 0.9rem;
    margin-top: 0.15rem;
  }

  /*
   * Phone residual B + soft Hear (2026-07-28): Edit · Hear · Delete hierarchy.
   * DOM stays Hear · Edit · Delete (desktop side-row). Visual order puts
   * Hear in the thumb-rest center. Center column slightly wider.
   * Edit + Delete share quiet shells; Hear soft primary (not solid — calm long list).
   */
  .card-item-actions {
    display: grid;
    grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.22fr) minmax(0, 0.92fr);
    gap: 0.35rem;
    width: 100%;
  }

  .card-item-actions .edit-card-btn {
    order: 1;
  }
  .card-item-actions .card-action--hear {
    order: 2;
  }
  .card-item-actions .card-action--delete {
    order: 3;
  }

  .card-item-actions .btn {
    min-height: 48px;
    width: 100%;
    touch-action: manipulation;
    padding-inline: 0.25rem;
    font-size: 0.78rem;
    font-weight: 550;
  }

  /* Matched secondary shells (Edit + Delete) — same chrome language */
  .card-item-actions .edit-card-btn,
  .card-item-actions .btn.danger.card-action--delete {
    color: var(--text-secondary);
    border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
    background: #fff;
  }

  .card-item-actions .btn.danger.card-action--delete {
    color: var(--text-tertiary);
  }

  /* Soft Hear primary — desktop language; after shared .btn so paint wins cascade */
  .card-item-actions .card-action--hear {
    color: var(--brand-deep);
    border-color: color-mix(in srgb, var(--brand) 35%, transparent);
    background: color-mix(in srgb, var(--brand) 8%, #fff);
    font-size: 0.88rem;
    font-weight: 700;
    box-shadow: none;
  }

  /* Danger still announces on engage (not at rest) */
  .card-item-actions .btn.danger.card-action--delete:focus-visible,
  .card-item-actions .btn.danger.card-action--delete:active {
    color: var(--error, #c43c3c);
    border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
    background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
  }

  .add-card-review-actions .btn.primary {
    min-height: 50px;
    font-weight: 650;
  }

  .library-empty {
    padding: 2rem 1.15rem;
  }

  .page-float-top-btn {
    min-height: 48px;
    min-width: 48px;
    padding: 0.6rem 1.05rem;
  }
}

/* Shared Top control for long Library / Path pages */
.page-float-top {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right, 0px));
  bottom: max(1.15rem, env(safe-area-inset-bottom, 0px));
  z-index: 30;
  display: flex;
  align-items: center;
}

/* Cards TOP matches Path: bottom-right (safe-area aware). */

.page-float-top.hidden {
  display: none;
}

.page-float-top-btn {
  min-height: 44px;
  min-width: 44px;
  padding: 0.55rem 0.95rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  color: var(--brand-deep);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  box-shadow: var(--shadow-md);
  cursor: pointer;
  touch-action: manipulation;
  transition:
    opacity 0.2s var(--ease),
    transform 0.2s var(--ease),
    background 0.2s var(--ease),
    border-color 0.2s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .page-float-top-btn:hover,
  .page-float-top-btn:focus-visible {
    background: var(--brand-soft);
    border-color: var(--brand-ring);
    outline: none;
  }
}

.page-float-top-btn:active {
  transform: scale(0.97);
}

.card-list {
  display: flex;
  flex-direction: column;
  gap: 1.35rem;
  /* End-of-page room for fixed TOP - not between packs and the first card group */
  padding-bottom: 5rem;
}

.card-group {
  scroll-margin-top: 4.25rem;
}

.card-group-title {
  margin: 0 0 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.card-group-range {
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  opacity: 0.75;
}

.card-group-range::before {
  content: "·";
  margin: 0 0.35em;
  opacity: 0.7;
}

.card-group-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.library-empty {
  text-align: center;
  /* Tighter when filters (Yours / Packs) have no jump bar above */
  padding: 1.65rem 1.35rem 1.5rem;
  color: var(--text-secondary);
  background:
    linear-gradient(
      165deg,
      color-mix(in srgb, white 94%, var(--brand)) 0%,
      var(--surface-glass-strong) 100%
    );
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}

.library-empty-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--text-secondary);
}



.card-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0.8rem 0.95rem;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .card-item:hover {
    border-color: var(--brand-ring);
    box-shadow: var(--shadow-sm), 0 0 0 1px color-mix(in srgb, var(--brand) 8%, transparent);
  }
}

.card-item-text {
  min-width: 0;
  flex: 1 1 auto;
  text-align: left;
}

.card-item-actions {
  display: flex;
  gap: 0.25rem;
  flex-shrink: 0;
  align-items: center;
}

.card-action {
  min-height: 2.05rem;
  padding: 0.28rem 0.58rem;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  border-radius: 999px;
}

.card-action--hear {
  color: var(--text-secondary);
}

/* Specificity must beat .btn.danger so Delete is not always-on red (base rest) */
.card-item-actions .btn.danger.card-action--delete {
  color: var(--text-tertiary);
  border-color: transparent;
  background: transparent;
}

.card-item-actions .btn.danger.card-action--delete:focus-visible,
.card-item-actions .btn.danger.card-action--delete:active {
  color: var(--error, #c43c3c);
  border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
  background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  .card-item-actions .btn.danger.card-action--delete:hover {
    color: var(--error, #c43c3c);
    border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
    background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
  }
}

/*
 * Desktop residual B (2026-07-28 · after base Delete so shells win cascade):
 * side-row · Hear soft primary · Edit + Delete matched quiet shells · danger
 * only on hover / focus / press.
 */
@media (min-width: 721px) {
  .card-item-actions .card-action--hear {
    color: var(--brand-deep);
    border-color: color-mix(in srgb, var(--brand) 32%, transparent);
    background: color-mix(in srgb, var(--brand) 6%, #fff);
    font-weight: 700;
  }

  .card-item-actions .edit-card-btn {
    color: var(--text-secondary);
    border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
    background: #fff;
    font-weight: 550;
  }

  .card-item-actions .btn.danger.card-action--delete {
    color: var(--text-tertiary);
    border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
    background: #fff;
    font-weight: 550;
  }

  .card-item-actions .btn.danger.card-action--delete:focus-visible,
  .card-item-actions .btn.danger.card-action--delete:active {
    color: var(--error, #c43c3c);
    border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
    background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
  }

  @media (hover: hover) and (pointer: fine) {
    .card-item-actions .btn.danger.card-action--delete:hover {
      color: var(--error, #c43c3c);
      border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
      background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
    }
  }
}

/*
 * Mobile seal (after base Delete rules). Soft Hear + Edit/Delete quiet shells.
 * Soft Hear (not solid) keeps the thumb seat without a blue band down long lists.
 */
@media (max-width: 720px) {
  .card-item-actions .edit-card-btn {
    color: var(--text-secondary);
    border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
    background: #fff;
  }

  .card-item-actions .btn.danger.card-action--delete {
    color: var(--text-tertiary);
    border-color: color-mix(in srgb, var(--border-strong) 90%, transparent);
    background: #fff;
  }

  .card-item-actions .btn.ghost.card-action--hear,
  .card-item-actions .btn.ghost.card-action--hear:hover,
  .card-item-actions .btn.ghost.card-action--hear:focus,
  .card-item-actions .btn.ghost.card-action--hear:focus-visible {
    color: var(--brand-deep);
    border-color: color-mix(in srgb, var(--brand) 35%, transparent);
    background: color-mix(in srgb, var(--brand) 8%, #fff);
    font-size: 0.88rem;
    font-weight: 700;
    box-shadow: none;
  }

  .card-item-actions .btn.danger.card-action--delete:focus-visible,
  .card-item-actions .btn.danger.card-action--delete:active {
    color: var(--error, #c43c3c);
    border-color: color-mix(in srgb, var(--error, #c43c3c) 35%, transparent);
    background: color-mix(in srgb, var(--error, #c43c3c) 8%, transparent);
  }
}

.card-item-foreign {
  font-weight: 750;
  font-size: 1.08rem;
  letter-spacing: -0.025em;
  color: var(--brand-deep);
  word-break: break-word;
  line-height: 1.25;
  text-align: left;
}

.card-item-native {
  font-size: 0.92rem;
  color: var(--text-secondary);
  margin-top: 0.2rem;
  line-height: 1.35;
  text-align: left;
}

/* Soft section cards - desktop + mobile share the same language */
.progress-section {
  margin-bottom: 0.75rem;
  padding: 1.05rem 1.05rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--surface-glass-strong);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-sm), 0 0 0 1px rgba(255, 255, 255, 0.45) inset;
  box-sizing: border-box;
}

/*
 * Foundation gauge (2026-07-30 · founder go):
 * Orientation headline above the volume+levels cluster, which stays contiguous.
 * A fuel gauge, not a scoreboard: one bar, one percentage, one quiet line.
 * The dose line holds a reserved seat, so the Path shell never resizes when the
 * line has nothing honest to say (stable shell law).
 */
.progress-section--foundation {
  margin-bottom: 0.48rem;
  padding: 0.9rem 0.95rem 0.86rem;
}

.progress-section--foundation .progress-section-head {
  margin-bottom: 0.5rem;
}

/* Foundation head: % only (Talk chip retired 2026-08-09 → Speak tab). */
.progress-section-head--foundation {
  gap: 0.55rem;
}

/*
 * Speak tab home — behind the conversation room when Leave returns here.
 * One line + one door. No Path dual entry.
 */
.speak-home {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  min-height: min(52vh, 22rem);
  padding: 2rem 1.25rem;
  text-align: center;
  box-sizing: border-box;
}

.speak-home__line {
  margin: 0;
  max-width: 18rem;
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text-secondary);
  letter-spacing: -0.01em;
}

.speak-home__open {
  min-width: 8.5rem;
  min-height: 2.75rem;
  padding: 0.7rem 1.4rem;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Speak language hop (2026-08-09 · founder) — same flag menu as Stories. */
.speak-lang-picker {
  position: relative;
  display: flex;
  justify-content: center;
  flex: 0 0 auto;
}

.speak-lang-picker--home {
  margin-bottom: 0.35rem;
}

.speak-lang-picker--room {
  justify-content: flex-start;
  /* Menu above stage; do not paint the flag ON TOP of Speak|Type (876). */
  z-index: 5;
  flex: 0 0 auto;
  flex-shrink: 0;
}

.speak-lang-cue {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0.35rem 0.55rem;
  border: 1px solid color-mix(in srgb, var(--brand) 18%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, #fff 88%, var(--brand-soft));
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: inherit;
}

.speak-lang-cue-flag {
  font-size: 1.35rem;
  line-height: 1;
}

@media (hover: hover) and (pointer: fine) {
  .speak-lang-cue:hover {
    border-color: color-mix(in srgb, var(--brand) 32%, transparent);
    background: color-mix(in srgb, #fff 70%, var(--brand-soft));
  }
}

.speak-lang-cue:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

.speak-lang-menu {
  z-index: 40;
  text-align: left;
}

.spar-room__top-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  /*
   * Take remaining row after the flag — never grow under it.
   * margin-left:auto + content-sized width let the group overflow LEFT when
   * the row is tight: Speak sat under the flag (Varde audit 875 · 320/360px).
   */
  flex: 1 1 0;
  min-width: 0;
  margin-left: 0;
}

.foundation-head-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  min-width: 0;
}

.foundation-pct {
  flex-shrink: 0;
  font-size: 1.04rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--brand-deep);
  font-variant-numeric: tabular-nums;
}

.foundation-gauge {
  position: relative;
  height: 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 9%, transparent);
  overflow: hidden;
}

/* Waypoint ticks (400 · 600). Drawn over the fill so they read on both sides. */
.foundation-gauge-mark {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: color-mix(in srgb, var(--brand-deep) 32%, transparent);
}

.foundation-gauge-fill {
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand) 88%, var(--brand-bright)) 0%,
    var(--brand-bright) 100%
  );
  transition: width 0.4s var(--ease);
}

/*
 * Reserved seat: a silent line must not collapse the section, and a long line
 * must not grow it. Stable shell law is explicit that long copy ellipses inside
 * the seat rather than reflowing, so the seat is hard-capped at one line. This
 * is the belt to the copy's braces: on a narrow device, large Dynamic Type, or
 * a wider system font, the line clips instead of pushing the card taller.
 */
.foundation-dose {
  margin: 0.55rem 0 0;
  min-height: 1.08rem;
  color: var(--text-secondary);
  font-size: 0.78rem;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (prefers-reduced-motion: reduce) {
  .foundation-gauge-fill {
    transition: none;
  }
}

/*
 * Path stack craft (pass 2 · 2026-07-27):
 * Prefs → Volume (glance, brand numbers) → Levels (spine) → Stories (quiet).
 * Volume+Levels = one cluster; Stories steps back. Best·Day keeps brand blue.
 */
.progress-section--volume {
  margin-bottom: 0.48rem;
  padding: 0.82rem 0.9rem 0.78rem;
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, #fff 92%, var(--brand-soft)) 0%,
      color-mix(in srgb, var(--surface-glass-strong) 88%, var(--bg)) 100%
    );
  border-color: color-mix(in srgb, var(--border-strong) 68%, transparent);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.65) inset,
    0 2px 10px rgba(54, 95, 207, 0.045);
}

.path-volume-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.32fr);
  align-items: stretch;
  text-align: center;
  min-height: 3.45rem;
}

/*
 * Path volume B (2026-07-28):
 * Run = Cards · Day = Cards + Match · Best = Cards + Streak
 * Equal columns · shared number/caption row heights so duals align
 * (CARDS text vs Match icon sit on one baseline — not by accident higher/lower).
 */
.path-volume-bar--dual,
.path-volume-bar--day-match {
  grid-template-columns: 1fr 1fr 1fr;
  min-height: 3.85rem;
}

.path-volume-dual,
.path-volume-single,
.path-volume-best-pair {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 0.55rem;
  width: 100%;
}

/* kai: more air between Day Cards and Match (go ship both 2026-07-28) */
.path-volume-dual {
  gap: 0.85rem;
}

.path-volume-best-pair {
  gap: 0.65rem;
}

/*
 * Day Match number: full brand blue — same family as Day Cards.
 * Do not mute Path volume numbers with tertiary mix (reads faded / broken).
 * Secondary story is the Match mark caption, not a washed-out digit.
 */
.path-volume-v[data-path-volume="day-match"] {
  /* inherit size/weight/color from .path-volume-v + day-match bar rules */
  color: var(--brand, #365fcf);
  font-weight: 700;
  height: 1.65rem;
}

.path-volume-pair {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 0.15rem;
  min-width: 0;
  flex: 0 1 auto;
}

.path-volume-best-pair .path-volume-pair,
.path-volume-single .path-volume-pair,
.path-volume-dual .path-volume-pair {
  min-width: 2.15rem;
}

/* Legacy triple (unused) — keep rule soft in case of old HTML */
.path-volume-best-triple {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 0.42rem;
  width: 100%;
}

.path-volume-best-triple .path-volume-pair {
  flex: 0 1 auto;
  min-width: 2.15rem;
}

/*
 * Shared rows: numbers one band, captions one band.
 * Match icon is centered in the same caption band as CARDS / STREAK text.
 */
.path-volume-sk--match {
  /* height from .path-volume-sk */
}

/*
 * G · Board mark — square; optical size for caption row.
 * Same brand blue as Study Match door (identity · full opacity on Path caption).
 */
/* Same 2×2 G-board as Study Match door; caption scale only */
.path-volume-match-ico {
  width: 0.92rem;
  height: 0.92rem;
  display: block;
  color: var(--brand, #365fcf);
  opacity: 1;
}

.path-volume-bar--dual .path-volume-v,
.path-volume-bar--day-match .path-volume-v {
  font-size: clamp(1.2rem, 4.2vw, 1.42rem);
}

.path-volume-bar--dual .path-volume-v--best,
.path-volume-bar--day-match .path-volume-v--best {
  font-size: clamp(1.2rem, 4.2vw, 1.42rem);
}

.path-volume-cell {
  position: relative;
  padding: 0.2rem 0.28rem 0.16rem;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.28rem;
}

.path-volume-cell + .path-volume-cell::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 58%;
  max-height: 2.35rem;
  background: linear-gradient(
    180deg,
    transparent 0%,
    color-mix(in srgb, var(--border-strong) 88%, transparent) 22%,
    color-mix(in srgb, var(--border-strong) 88%, transparent) 78%,
    transparent 100%
  );
}

.path-volume-k {
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  line-height: 1.15;
  /* Shared header band — no lift (lift desynced Best vs Run/Day) */
  min-height: 1.15em;
  display: flex;
  align-items: center;
  justify-content: center;
}

.path-volume-cell--best .path-volume-k {
  color: var(--text-tertiary);
  font-weight: 700;
  letter-spacing: 0.1em;
  transform: none;
}

.path-volume-v {
  margin: 0;
  /* Fixed band so dual metrics share one number baseline */
  height: 1.65rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(1.42rem, 4.9vw, 1.65rem);
  font-weight: 700;
  letter-spacing: -0.048em;
  font-variant-numeric: tabular-nums;
  color: var(--brand);
  line-height: 1;
}

.path-volume-cell--best {
  gap: 0.28rem;
  justify-content: center;
  padding-inline: 0.15rem;
}

/*
 * B′: one number blue everywhere (no brand / brand-deep split).
 * Captions (CARDS / STREAK): tertiary under Run · Day · Best.
 * Match mark: brand blue (Study Match door twin) — not caption gray.
 * Best numbers share the same row height as Run/Day (no smaller dual type).
 */
.path-volume-v--best {
  height: 1.65rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(1.42rem, 4.9vw, 1.65rem);
  font-weight: 700;
  letter-spacing: -0.048em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--brand);
}

.path-volume-sk {
  font-size: 0.54rem;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  line-height: 1;
  /* Shared caption band — CARDS text and Match icon center on one line */
  height: 0.9rem;
  min-height: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.path-volume-pair--streak .path-volume-v--best,
.path-volume-pair--day .path-volume-v--best {
  color: var(--brand);
}

.path-volume-cell--best .path-volume-sk {
  color: var(--text-tertiary);
  font-weight: 650;
  letter-spacing: 0.07em;
}

.path-volume-cell--best .path-volume-match-ico {
  color: var(--brand, #365fcf);
  opacity: 1;
}

/* Levels = Path spine; sits tight under volume as one cluster */
#stats-panel .progress-section--levels {
  min-height: 0;
  margin-bottom: 0.85rem;
  padding: 0.95rem 1rem 0.92rem;
  box-shadow:
    var(--shadow-sm),
    0 0 0 1px rgba(255, 255, 255, 0.5) inset;
}

#stats-panel .progress-section--levels .progress-section-head {
  margin-bottom: 0.5rem;
}

#stats-panel .progress-section--levels .progress-section-title {
  margin-bottom: 0;
  letter-spacing: 0.075em;
  color: color-mix(in srgb, var(--text-secondary) 92%, var(--brand));
}

#stats-panel .progress-section--levels .box-stats {
  gap: 0.28rem;
}

.progress-section:last-of-type {
  margin-bottom: 0.55rem;
}

/* Pa2: section titles — orientation, not scoreboard */
.progress-section-title {
  margin: 0 0 0.75rem;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.065em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--text-secondary);
}

/* Pa3: Stories steps back after the volume+levels cluster */
#progress-read-section.progress-section {
  margin-top: 0.05rem;
  margin-bottom: 0.55rem;
  padding: 0.9rem 0.95rem 0.88rem;
  background: color-mix(in srgb, var(--surface-glass-strong) 96%, var(--bg));
  border-color: color-mix(in srgb, var(--border-strong) 72%, transparent);
  box-shadow: 0 1px 5px rgba(54, 95, 207, 0.03);
  min-height: 0;
  box-sizing: border-box;
}

#progress-read-section .progress-section-title {
  color: var(--text-tertiary);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  font-weight: 650;
}

/* Reset All — touch size only; quiet at rest (same law as Cards Reset) */
@media (pointer: coarse) {
  .progress-read-reset-all:not(.hidden) {
    min-height: 2.5rem;
    color: var(--text-tertiary);
    border-color: var(--border-strong);
    background: transparent;
  }

  .progress-read-reset-all:focus,
  .progress-read-reset-all:focus-visible {
    color: var(--text-tertiary);
    background: transparent;
    border-color: var(--border-strong);
    box-shadow: none;
    outline: none;
  }
}

.progress-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.65rem;
}

.progress-section-head .progress-section-title {
  margin-bottom: 0;
}

.progress-read-reset-all {
  flex-shrink: 0;
  min-height: 2rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--text-tertiary);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    border-color 0.15s var(--ease),
    background 0.15s var(--ease),
    color 0.15s var(--ease);
}

/* Press only on touch — no permanent caution fill */
.progress-read-reset-all:active {
  color: color-mix(in srgb, var(--error, #d70015) 80%, var(--ink));
  background: color-mix(in srgb, var(--error, #d70015) 10%, transparent);
  border-color: color-mix(in srgb, var(--error, #d70015) 16%, transparent);
}

@media (hover: hover) and (pointer: fine) {
  .progress-read-reset-all:hover {
    border-color: transparent;
    background: var(--brand-soft);
    color: var(--brand-deep);
  }
}

/*
 * Path panel: one calm max width at every browser size (Study-card pattern).
 * Avoids 720↔721 full-bleed ↔ capped jumps.
 */
#stats-panel.active {
  width: min(100%, 38.5rem);
  margin-inline: auto;
  box-sizing: border-box;
  min-width: 0;
  /* Soft floor so last section doesn’t kiss the tab bar */
  padding-bottom: 0.35rem;
}

/*
 * Path content (orientation-forward): prefs + levels under shared chrome brand.
 * Brand size/margin: see “Chrome handoff law” above (same as Cards).
 */
/* - Desktop Path: calm levels · reading - */
@media (min-width: 721px) {
  /* width owned by base #stats-panel.active */

  .progress-prefs {
    --prefs-h: 2.45rem;
    --prefs-font: 0.78rem;
    --prefs-pad-x: 0.8rem;
    --prefs-gap: 0.5rem;
    margin-bottom: 0.75rem;
    row-gap: 0.5rem;
  }

  .progress-basics-btn {
    max-width: min(13.5rem, 44vw);
  }

  .progress-basics-glyphs {
    font-size: 0.9rem;
    line-height: 1.35;
  }
  .progress-section {
    margin-bottom: 0.8rem;
    padding: 1.05rem 1.1rem 1rem;
  }

  .progress-section--volume {
    margin-bottom: 0.52rem;
    padding: 0.92rem 1.1rem 0.88rem;
  }

  .path-volume-bar {
    min-height: 3.6rem;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.28fr);
  }

  .path-volume-v {
    font-size: 1.68rem;
  }

  .path-volume-v--best {
    font-size: 1.32rem;
  }

  .path-volume-best-pair {
    gap: 0.95rem;
  }

  .path-volume-k {
    font-size: 0.6rem;
    letter-spacing: 0.11em;
  }

  .path-volume-sk {
    font-size: 0.56rem;
  }

  .progress-section:last-of-type {
    margin-bottom: 0.6rem;
  }

  .progress-section-title {
    font-size: 0.75rem;
  }

  .progress-section-head {
    margin-bottom: 0.65rem;
  }

  #stats-panel .progress-section--levels {
    margin-bottom: 0.95rem;
    padding: 1.05rem 1.1rem 1rem;
  }

  #stats-panel .progress-section--levels .progress-section-head {
    margin-bottom: 0.58rem;
  }

  #stats-panel .progress-section--levels .box-stats {
    gap: 0.32rem;
  }

  #progress-read-section.progress-section {
    padding: 0.95rem 1.05rem 0.92rem;
  }

  .box-stats,
  .read-progress-stats {
    gap: 0.32rem;
  }

  .box-stat-row {
    min-height: 2.42rem;
    grid-template-columns: minmax(0, 8.25rem) 1fr 2.2rem;
    padding: 0.1rem 0;
  }

  .box-stat-bar-wrap {
    height: 6px;
  }

  @media (hover: hover) and (pointer: fine) {
    .read-stat-row--link:hover {
      background: var(--brand-soft);
    }
  }

  .read-stat-group {
    column-gap: 0.85rem;
    row-gap: 0.4rem;
  }

  .read-stat-group + .read-stat-group {
    margin-top: 1.15rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--border);
  }

  .read-stat-group-title {
    margin-bottom: 0.45rem;
    font-size: 0.74rem;
  }

  .read-stat-title {
    font-size: 0.92rem;
  }

  .read-stat-count {
    font-size: 0.88rem;
  }
}

/*
 * Tablet soft band (iPad portrait / small landscape).
 * Same desktop structure; only fix real mid-width pain: touch targets,
 * Path 4-up density, Read options wrap, Library jump label density.
 */
@media (min-width: 721px) and (max-width: 1024px) {
  .app {
    padding:
      calc(1.5rem + env(safe-area-inset-top, 0px))
      calc(1.25rem + env(safe-area-inset-right, 0px))
      calc(1.5rem + env(safe-area-inset-bottom, 0px))
      calc(1.25rem + env(safe-area-inset-left, 0px));
  }

  /* Tabs: comfortable touch without looking like phone */
  .tab {
    min-height: 2.55rem;
    padding: 0.5rem 1rem;
  }

  /* Review: direction is caption text, not a control */
  .practice-card-top .direction-label {
    font-size: 0.7rem;
  }

  /* Do not flatten Hear/SPEAK — hierarchy lives on base .answer-action--* rules */
  .answer-actions .btn.answer-action--hear {
    min-height: 3.15rem;
  }

  .answer-actions .btn.answer-action--speak,
  .answer-actions .btn.answer-action--match {
    min-height: 2.35rem;
    height: 2.35rem;
  }

  /* Read: footer can wrap on mid widths without crowding */
  .read-footer {
    flex-wrap: wrap;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.65rem 0.85rem;
  }

  .read-options {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: 0.4rem;
    max-width: none;
    width: auto;
    margin-inline: 0;
  }

  .read-action {
    min-height: 2.55rem;
    min-width: 5.5rem;
    width: auto;
  }

  .read-nav-btn {
    min-height: 2.55rem;
  }

  .read-title-row {
    min-height: 2.75rem;
  }

  /* Library: equal filters already; jump chips keep fluid type from base */
  .filter-chip {
    min-height: 2.65rem;
  }

  .library-jump-chip {
    min-height: 2.55rem;
  }

  .card-item-actions .btn {
    min-height: 2.55rem;
  }
}

@media (max-width: 720px) {
  /* - Mobile Path: section cards, touch rows - */
  /* #stats-panel width: fluid base rule — no full-bleed flip */

  /*
   * Pa1 B: one row — language · Basics · About · voice
   * (About after Basics; voice stays trailing. No second-row orphan.)
   */
  .progress-prefs {
    --prefs-h: 2.55rem;
    --prefs-gap: 0.35rem;
    --prefs-font: 0.74rem;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    margin-bottom: 0.6rem;
  }

  .progress-prefs > .category-picker--progress {
    grid-column: 1;
    grid-row: 1;
  }

  .progress-prefs > .progress-basics-btn {
    grid-column: 2;
    grid-row: 1;
    justify-self: stretch;
    max-width: none;
    min-height: 2.55rem;
    padding-inline: 0.55rem;
  }

  .progress-prefs > .progress-about-btn {
    grid-column: 3;
    grid-row: 1;
    justify-self: start;
    min-height: 2.55rem;
    font-size: 0.72rem;
  }

  .progress-prefs > .progress-voice {
    grid-column: 4;
    grid-row: 1;
    justify-self: end;
  }

  .progress-section {
    margin-bottom: 0.65rem;
    padding: 0.88rem 0.82rem 0.82rem;
  }

  .progress-section--volume {
    margin-bottom: 0.42rem;
    padding: 0.74rem 0.72rem 0.7rem;
  }

  .path-volume-bar {
    min-height: 3.3rem;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.36fr);
  }

  .path-volume-cell {
    padding: 0.14rem 0.12rem 0.1rem;
    gap: 0.24rem;
  }

  .path-volume-best-pair {
    gap: 0.55rem;
  }

  .path-volume-sk {
    font-size: 0.52rem;
    letter-spacing: 0.065em;
  }

  .path-volume-k {
    font-size: 0.56rem;
    letter-spacing: 0.09em;
  }

  .progress-section:last-of-type {
    margin-bottom: 0.5rem;
  }

  .progress-section-title {
    font-size: 0.7rem;
  }

  .progress-section-head {
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
  }

  #stats-panel .progress-section--levels {
    margin-bottom: 0.75rem;
    padding: 0.88rem 0.82rem 0.84rem;
  }

  #stats-panel .progress-section--levels .progress-section-head {
    margin-bottom: 0.42rem;
  }

  #stats-panel .progress-section--levels .box-stats {
    gap: 0.22rem;
  }

  #progress-read-section.progress-section {
    padding: 0.82rem 0.8rem 0.78rem;
  }

  .progress-read-reset-all {
    min-height: 2.5rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.72rem;
  }

  .box-stats {
    gap: 0.28rem;
    margin-bottom: 0;
  }

  /* Level rows: label | bar | count - stay one line on phones */
  .box-stat-row {
    grid-template-columns: minmax(0, 5.6rem) 1fr 1.9rem;
    gap: 0.45rem;
    min-height: 2.42rem;
    align-items: center;
    padding: 0.08rem 0;
  }

  .box-stat-name {
    font-size: 0.86rem;
    font-weight: 650;
  }

  .box-stat-interval {
    font-size: 0.66rem;
  }

  .box-stat-bar-wrap {
    height: 6px;
  }

  .box-stat-count {
    text-align: right;
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
  }

  .read-progress-stats {
    gap: 0.75rem;
    margin-bottom: 0;
  }

  .read-stat-group {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.45rem;
    row-gap: 0.4rem;
  }

  .read-stat-group + .read-stat-group {
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border);
  }

  .read-stat-group-title {
    margin-bottom: 0.4rem;
    font-size: 0.72rem;
  }

  /* Story row: title above bar; count + reset beside */
  .read-stat-row {
    grid-template-columns: 1fr;
    gap: 0.35rem;
    padding: 0.4rem 0.2rem;
  }

  .read-stat-row--link {
    min-height: 48px;
    touch-action: manipulation;
  }

  .read-stat-actions {
    grid-template-columns: auto 2.5rem;
    gap: 0.35rem;
    align-self: center;
  }

  .read-stat-count {
    text-align: right;
    font-size: 0.82rem;
  }

  .read-stat-reset-btn {
    width: 2.5rem;
    height: 2.5rem;
    min-height: 44px;
    min-width: 44px;
    font-size: 1.05rem;
  }

  .read-stat-reset-spacer {
    width: 2.5rem;
    height: 2.5rem;
  }

  .empty-home-status {
    width: 100%;
    max-width: 100%;
    gap: 0.5rem;
  }

  .library-deck-meta {
    font-size: 1.05rem;
  }
}

ul.box-stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
}

.box-stat-row {
  display: grid;
  grid-template-columns: minmax(0, 7.5rem) 1fr 2rem;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.32rem;
  padding: 0.1rem 0;
  font-size: 0.9rem;
}

.box-stat-row--empty {
  opacity: 0.48;
}

.box-stat-row--empty .box-stat-bar {
  opacity: 0;
}

.box-stat-count {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  letter-spacing: -0.025em;
}

.box-stat-bar-wrap {
  height: 0.36rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  overflow: hidden;
}

.box-stat-bar {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand) 88%, #5b9aff) 0%,
    #5b9aff 100%
  );
  transition: width 0.35s var(--ease);
}

/* Hairline when share is real but sub-pixel (e.g. 1 of 1000) - not a fake % floor */
.box-stat-bar--has {
  min-width: 3px;
}

.read-stat-label {
  display: flex;
  flex-direction: column;
  gap: 0.12rem;
  min-width: 0;
}

.read-context-gap {
  display: inline;
}

/* Category on first line, interval under it (Learning → Next day) — not side by side */
.box-stat-label {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  min-width: 0;
}

.box-stat-name,
.read-stat-title {
  color: var(--ink);
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.015em;
}

.box-stat-interval,
.read-stat-trail {
  display: block;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--text-tertiary);
  line-height: 1.3;
}

.read-stat-group {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7rem;
  column-gap: 0.65rem;
  row-gap: 0.35rem;
  align-items: center;
}

.read-stat-row-wrap {
  display: contents;
}

.read-stat-row-wrap .read-stat-row {
  grid-column: 1;
  min-width: 0;
}

.read-stat-actions {
  grid-column: 2;
  display: grid;
  grid-template-columns: 4.35rem 1.65rem;
  gap: 0.45rem;
  align-items: center;
}

.read-stat-reset-spacer {
  width: 1.65rem;
  height: 1.65rem;
}

.read-stat-row-wrap--completed .read-stat-title,
.read-stat-row-wrap--completed .read-stat-count {
  color: #2f855a;
}

.read-stat-reset-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.65rem;
  height: 1.65rem;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  background: var(--surface-glass-strong);
  color: var(--text-tertiary);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    border-color 0.15s var(--ease),
    background 0.15s var(--ease),
    color 0.15s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .read-stat-reset-btn:hover {
    border-color: var(--brand-ring);
    background: var(--brand-soft);
    color: var(--brand);
  }
}

.read-stat-row {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) 1fr;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.9rem;
}

.read-stat-row--link {
  width: 100%;
  border: none;
  border-radius: var(--radius-xs);
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .read-stat-row--link:hover {
    background: var(--brand-soft);
  }
}

.read-stat-group + .read-stat-group {
  margin-top: 1rem;
}

.read-stat-group-title {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  grid-column: 1 / -1;
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.read-stat-group-symbol {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.35rem;
}

.read-stat-count {
  text-align: right;
  font-weight: 600;
  color: var(--text-secondary);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}









/* Read tab - parallel text (brand lockup hidden via .read-focus rule above). */
.app.read-focus .header {
  margin-bottom: 0.5rem; /* chrome handoff rhythm */
}

/*
 * Stories shell: one calm max width at every size (Study-card pattern).
 * Mobile read-focus still owns the nested sentence scrollport; this only
 * stops full-bleed ↔ 40rem snaps when the window crosses 721.
 */
.read-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(100%, 40rem);
  margin-inline: auto;
  box-sizing: border-box;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.05rem 1.1rem 0.95rem;
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(255, 255, 255, 0.55) inset;
}

/* Calm empty when this language has no reading pack yet */
.read-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: min(52vh, 22rem);
  padding: 1.25rem 0.75rem 1.5rem;
  box-sizing: border-box;
}

.read-empty.hidden {
  display: none;
}

.read-empty-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: min(100%, 22rem);
  padding: 1.75rem 1.35rem 1.5rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background:
    linear-gradient(
      165deg,
      color-mix(in srgb, white 94%, var(--brand)) 0%,
      var(--surface-glass-strong) 100%
    );
  box-shadow: var(--shadow-md);
}

.read-empty-flag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  margin-bottom: 0.85rem;
  border-radius: 0.9rem;
  font-size: 1.55rem;
  line-height: 1;
  background: color-mix(in srgb, var(--brand-soft) 65%, white);
  border: 1px solid color-mix(in srgb, var(--brand) 16%, transparent);
}

.read-empty-title {
  margin: 0 0 0.4rem;
  font-size: 1.2rem;
  font-weight: 750;
  letter-spacing: -0.03em;
  color: var(--ink);
  line-height: 1.2;
}

.read-empty-copy {
  margin: 0;
  max-width: 18rem;
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
}

.read-empty-browse {
  margin-top: 1.1rem;
  min-height: 2.5rem;
  min-width: 9rem;
}

.read-empty-browse.hidden {
  display: none;
}

.read-header {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 0.7rem;
}

.read-shell--menu-open .read-header {
  z-index: 30;
}

/*
 * Read title bar:
 *   [ flag → language list ] | [ trail + title + ▾ → story list ]
 * Reading-focused language hop without leaving Stories.
 */
.read-title-row {
  display: flex;
  align-items: stretch;
  gap: 0;
  min-width: 0;
  min-height: 2.55rem;
  border: 1px solid var(--border-strong);
  border-radius: 0.75rem;
  background: var(--surface-glass-strong);
  overflow: hidden;
  box-shadow: 0 1px 0 color-mix(in srgb, white 55%, transparent) inset;
}

.read-lang-cue {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.55rem;
  min-height: 100%;
  padding: 0 0.55rem;
  border: 0;
  border-right: 1px solid var(--border-strong);
  border-radius: 0;
  background: color-mix(in srgb, var(--surface-2, #f4f6fb) 55%, transparent);
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  transition: background 0.15s var(--ease);
  font-family: inherit;
}

@media (hover: hover) and (pointer: fine) {
  .read-lang-cue:hover,
  .read-lang-cue:focus-visible {
    background: var(--brand-soft);
    outline: none;
  }

  .read-lang-cue:focus-visible {
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--brand) 50%, transparent);
  }
}

.read-lang-cue[aria-expanded="true"] {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.14), rgba(54, 95, 207, 0.08));
}

.read-lang-cue-flag {
  font-size: 1.12rem;
  line-height: 1;
  filter: drop-shadow(0 0.5px 0.5px rgba(15, 23, 42, 0.08));
}

/*
 * Stories language list — docked under the flag (JS: fixed + containing-block fix).
 * Elegant fold like Path/Cards: capped height, edge fades, scroll chevrons.
 */
.read-lang-menu {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  width: 14rem;
  min-width: 14rem;
  max-width: min(14rem, calc(100vw - 1.25rem));
  max-height: min(22rem, 50dvh);
  overflow: hidden;
  /* Near-opaque: glass 0.9 let “God morgen” show through the open list */
  background: color-mix(in srgb, white 96%, var(--surface-2, #f8f9fd));
  backdrop-filter: blur(18px) saturate(1.05);
  -webkit-backdrop-filter: blur(18px) saturate(1.05);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.35rem;
  z-index: 41;
  box-sizing: border-box;
}

/* Path-parity scroll chevrons on Stories language list */
.read-lang-menu.is-scrollable .category-picker-scroll-cue {
  display: flex;
}

.read-lang-menu.has-more-below .category-picker-scroll-cue--down {
  opacity: 1;
}

.read-lang-menu.has-more-above .category-picker-scroll-cue--up {
  opacity: 1;
}

/* Raise Stories chrome while the language list is open (above sentence stage) */
.read-header:has(#read-lang-btn[aria-expanded="true"]),
.read-header:has(#read-lang-menu:not(.hidden)) {
  z-index: 40;
}

/* Raise chrome while the language list is open (stack above the sentence stage) */
.read-shell--lang-menu-open .read-header {
  z-index: 40;
}

.read-lang-menu-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: thin;
  scrollbar-color: rgba(18, 24, 38, 0.22) transparent;
}

.read-lang-menu.has-more-below .read-lang-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow: inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

.read-lang-menu.has-more-above .read-lang-menu-scroll {
  mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 0.75rem, #000 100%);
  box-shadow: inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep) 10%, transparent);
}

.read-lang-menu.has-more-above.has-more-below .read-lang-menu-scroll {
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.75rem,
    #000 calc(100% - 2.6rem),
    rgba(0, 0, 0, 0.55) calc(100% - 1.35rem),
    transparent 100%
  );
  box-shadow:
    inset 0 0.7rem 0.55rem -0.45rem color-mix(in srgb, var(--brand-deep) 10%, transparent),
    inset 0 -1.4rem 1.1rem -0.85rem color-mix(in srgb, var(--brand-deep) 14%, transparent);
}

.read-lang-option {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  min-height: 2.4rem;
  padding: 0.4rem 0.65rem;
  border: none;
  border-radius: var(--radius-xs);
  background: transparent;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  transition: background 0.15s var(--ease);
}

.read-lang-option:focus-visible {
  background: var(--brand-soft);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .read-lang-option:hover {
    background: var(--brand-soft);
    outline: none;
  }
}

.read-lang-option.active {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.14), rgba(54, 95, 207, 0.08));
  color: var(--brand-deep);
}

.read-lang-option-flag {
  flex-shrink: 0;
  font-size: 1.15rem;
  line-height: 1;
}

.read-lang-option-label {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.read-story-select {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-width: 0;
  min-height: 100%;
  padding: 0.38rem 0.7rem 0.38rem 0.65rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s var(--ease);
  touch-action: manipulation;
}

.read-story-select-trail {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
}

.read-story-select-trail .read-trail-symbol--green-circle,
.read-story-select-trail .read-trail-symbol--blue-square {
  width: 0.88rem;
  height: 0.88rem;
}

.read-story-select-trail .read-trail-symbol--black-diamond {
  width: 0.7rem;
  height: 0.7rem;
}

.read-story-select-trail .read-trail-symbol--double-black-diamond .read-trail-diamond {
  width: 0.52rem;
  height: 0.52rem;
}

.read-story-select:focus-visible {
  background: var(--brand-soft);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .read-story-select:hover {
    background: var(--brand-soft);
    outline: none;
  }
}

.read-story-select:focus-visible {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--brand) 50%, transparent);
}

.read-story-select[aria-expanded="true"] {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.12), rgba(54, 95, 207, 0.06));
}

.read-story-select-copy {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.06rem;
  min-width: 0;
}

/* Story title - primary chrome text */
.read-story-select-title {
  max-width: 100%;
  font-size: 0.98rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.read-story-select-meta {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: auto;
  padding-left: 0.15rem;
}



.read-story-select-chevron {
  width: 0.42rem;
  height: 0.42rem;
  border-right: 2px solid var(--text-tertiary);
  border-bottom: 2px solid var(--text-tertiary);
  transform: rotate(45deg) translateY(-1px);
  opacity: 0.55;
}

/* Progress under the title bar - quiet, always the same footprint */
.read-progress-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1.7rem;
  align-items: center;
  gap: 0.35rem;
  min-height: 1.5rem;
  padding-inline: 0.1rem;
}

.read-progress-bar {
  height: 3.5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  overflow: hidden;
  min-width: 0;
}

.read-progress-fill {
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: var(--brand-gradient);
  transition: width 0.35s var(--ease), background 0.35s var(--ease);
}

.read-progress-bar.is-complete .read-progress-fill {
  background: linear-gradient(90deg, #3db87a, #2f855a);
}

.read-progress-row .read-reset-btn {
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid transparent;
  border-radius: 50%;
  color: var(--text-tertiary);
  opacity: 1;
  transition:
    opacity 0.2s var(--ease),
    color 0.15s var(--ease),
    background 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.read-progress-row .read-reset-btn.is-idle {
  opacity: 0;
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .read-progress-row .read-reset-btn:not(.is-idle):hover {
    border-color: var(--brand-ring);
    background: var(--brand-soft);
    color: var(--brand);
  }
}

.read-progress-bar.is-complete ~ .read-reset-btn:not(.is-idle) {
  color: #2f855a;
}

.read-menu {
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  right: 0;
  max-height: min(22rem, 62vh);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.35rem;
  z-index: 40;
  box-sizing: border-box;
}

/* Soft edge fades when more stories sit off-screen (scroll the list) */
.read-menu.has-more-below {
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 1.75rem),
    rgba(0, 0, 0, 0.45) calc(100% - 0.75rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    #000 calc(100% - 1.75rem),
    rgba(0, 0, 0, 0.45) calc(100% - 0.75rem),
    transparent 100%
  );
}

.read-menu.has-more-above {
  mask-image: linear-gradient(to bottom, transparent 0%, #000 0.7rem, #000 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 0.7rem, #000 100%);
}

.read-menu.has-more-above.has-more-below {
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.7rem,
    #000 calc(100% - 1.75rem),
    rgba(0, 0, 0, 0.45) calc(100% - 0.75rem),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 0.7rem,
    #000 calc(100% - 1.75rem),
    rgba(0, 0, 0, 0.45) calc(100% - 0.75rem),
    transparent 100%
  );
}

.read-menu-empty {
  margin: 0;
  padding: 0.85rem 0.7rem 0.95rem;
  font-size: 0.84rem;
  color: var(--text-tertiary);
  text-align: center;
}

.read-menu-section {
  padding-bottom: 0.25rem;
}

.read-menu-section + .read-menu-section {
  margin-top: 0.2rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--border);
}



.read-menu-option {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.65rem 0.7rem;
  border: none;
  border-radius: var(--radius-xs);
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s var(--ease);
  touch-action: manipulation;
}

@media (hover: hover) and (pointer: fine) {
  .read-menu-option:hover {
    background: var(--brand-soft);
  }
}

.read-menu-option.active {
  background: linear-gradient(135deg, rgba(91, 154, 255, 0.14), rgba(54, 95, 207, 0.08));
}

.read-menu-option-symbol {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
}

.read-menu-option-text {
  display: flex;
  flex-direction: column;
  gap: 0.08rem;
  min-width: 0;
  flex: 1;
}

.read-menu-option-title {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.read-menu-option-meta {
  font-size: 0.74rem;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.read-menu-option-pct {
  flex-shrink: 0;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.read-trail-symbol {
  display: block;
  flex-shrink: 0;
}

.read-trail-symbol--green-circle {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: #2fb352;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

.read-trail-symbol--blue-square {
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 0.12rem;
  background: #2f7fd4;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

.read-trail-symbol--black-diamond {
  width: 0.9rem;
  height: 0.9rem;
  background: #1c1c1e;
  transform: rotate(45deg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.22);
}

.read-trail-symbol--double-black-diamond {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}

.read-trail-symbol--double-black-diamond .read-trail-diamond {
  width: 0.72rem;
  height: 0.72rem;
  background: #1c1c1e;
  transform: rotate(45deg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.22);
}

/*
 * Prior-context band: always the same height (St3 + stability pass).
 * Empty on sentence 1 = quiet strip, not height 0 — collapsing shoved the Read box.
 * kai (2026-07-28): softer prior so L2 stage stays the hero when EN+gloss open.
 */
.read-context--before {
  margin-bottom: 0.35rem;
  height: 1.75rem;
  max-height: 1.75rem;
  overflow: hidden;
  border-radius: var(--radius-xs);
  background: rgba(54, 95, 207, 0.03);
  padding: 0 0.5rem;
  box-sizing: border-box;
}

/* Empty (first sentence): keep slot, no fill — no layout jump when prior lines appear */
.read-context--before:not(:has(.read-context-track)) {
  background: transparent;
  opacity: 0.28;
}

.read-context-anchor {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.read-context-anchor::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1.75rem;
  background: linear-gradient(to right, rgba(54, 95, 207, 0.04), transparent);
  pointer-events: none;
  z-index: 1;
}

.read-context-track {
  position: absolute;
  top: 50%;
  left: 0;
  display: inline-block;
  min-width: min-content;
  max-width: none;
  font-size: 0.82rem;
  line-height: 1.35;
  color: var(--text-tertiary);
  white-space: nowrap;
  will-change: transform;
}

.read-context-sentence {
  display: inline;
}

.read-focus {
  flex-shrink: 0;
  text-align: center;
  /* kai: slightly tighter stage when help layers stack (EN + gloss) */
  padding: 1.05rem 0.9rem 0.95rem;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--border);
  box-shadow: none;
  /* Desktop: keep stage shell from shrinking across English / gloss / line wrap */
  min-height: min(14.5rem, 40dvh);
  box-sizing: border-box;
}

/* When full English is on, trim stage a hair more so the stack stays calm */
.read-focus.has-english {
  padding: 0.95rem 0.85rem 0.85rem;
  min-height: min(13.5rem, 38dvh);
}

.read-focus-nb {
  /*
   * Reserve two lines (em × line-height + padding, border-box).
   * Undersized clamps let 1↔2 line wraps grow/shrink the shell and
   * shove the ← → nav under the cursor on desktop.
   * R1: slightly stronger L2 presence.
   */
  padding: 0.28rem 0.15rem;
  font-size: clamp(1.55rem, 5.5vw, 2.15rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.48;
  min-height: calc((2 * 1.48em) + 0.56rem);
  color: var(--ink);
  overflow-wrap: break-word;
}

.read-unit {
  display: inline;
}

.read-unit--glued {
  white-space: nowrap;
}

/*
 * Gloss slot: fixed reserve (open or closed, English on or off).
 * Changing min-height with has-english / open gloss was shifting the Read box.
 */
.read-gloss-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.45rem;
  margin-top: 0.35rem;
  flex-shrink: 0;
}

/* When full-sentence English is on, soft frame stays — type one step quieter, not faint */
.read-focus.has-english .read-gloss {
  background: color-mix(in srgb, var(--brand) 7%, white);
  border-color: color-mix(in srgb, var(--brand) 22%, transparent);
}

.read-focus.has-english .read-gloss-en {
  font-size: 0.94em;
  font-weight: 600;
  color: color-mix(in srgb, var(--brand-deep) 70%, var(--text-tertiary));
}

.read-focus.has-english .read-gloss-lemma {
  opacity: 0.8;
}

/*
 * Word gloss (B weight · 2026-07-28): soft rectangle, clearer than first pass.
 * Stronger brand border + type; still not a round pill. Slot height reserved.
 */
.read-gloss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  max-width: min(100%, 22rem);
  min-height: 2.05rem;
  max-height: 2.45rem;
  padding: 0.3rem 0.75rem;
  border-radius: 0.55rem;
  background: color-mix(in srgb, var(--brand) 9%, white);
  border: 1.5px solid color-mix(in srgb, var(--brand) 28%, transparent);
  text-align: center;
  box-sizing: border-box;
  overflow: hidden;
  transition:
    border-color 0.15s var(--ease),
    background 0.15s var(--ease),
    opacity 0.15s var(--ease);
}

.read-gloss.is-deck {
  border-color: color-mix(in srgb, var(--brand) 32%, transparent);
  background: color-mix(in srgb, var(--brand) 10%, white);
}

.read-gloss.is-extra {
  border-color: color-mix(in srgb, var(--brand) 22%, transparent);
  background: color-mix(in srgb, var(--brand) 7%, white);
}

.read-gloss.is-collapsed {
  /* Slot min-height holds space; content invisible when closed */
  visibility: hidden;
  opacity: 0;
  border-color: transparent;
  background: transparent;
}

.read-gloss-meaning {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.08rem;
  font-size: clamp(0.98rem, 2.9vw, 1.06rem);
  line-height: var(--lh-tight);
  letter-spacing: -0.02em;
  word-break: break-word;
}

.read-gloss-en {
  color: var(--brand-deep);
  font-weight: 650;
  letter-spacing: -0.02em;
}

.read-gloss-lemma {
  font-size: 0.78em;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: -0.01em;
}

.read-gloss-lemma::before {
  content: "from ";
  font-weight: 450;
  opacity: 0.85;
}

/*
 * St1: English band always reserves 2-line height so open/close does not shove footer.
 * Collapsed = content invisible; shell height stays (calmer than reclaim-and-jump).
 * kai: open EN is quieter support under L2 — not a second equal paragraph.
 */
.read-focus-en-slot {
  min-height: calc(2 * 1.4em + 0.75rem);
  margin: 0.35rem 0 0;
  padding-top: 0.35rem;
  border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
  box-sizing: border-box;
  transition: border-color 0.2s var(--ease, ease), opacity 0.2s var(--ease, ease);
}

.read-focus-en-slot.is-collapsed {
  border-top-color: transparent;
  opacity: 0.3;
}

.read-focus-en {
  margin: 0;
  font-size: clamp(0.88rem, 2.6vw, 1rem);
  line-height: 1.4;
  color: var(--text-tertiary);
  font-weight: 450;
  /* Keep English stage calm when open (1↔2 line translations) */
  min-height: calc(2 * 1.4em);
}

.read-focus.has-english .read-focus-en {
  color: var(--text-tertiary);
}

.read-focus-en-slot.is-collapsed .read-focus-en {
  visibility: hidden;
}

.read-word {
  display: inline;
  border: none;
  background: none;
  padding: 0.08em 0.04em;
  margin: 0;
  font: inherit;
  color: inherit;
  border-radius: 0.35rem;
  cursor: default;
  vertical-align: baseline;
  transition: background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.read-word--tappable {
  cursor: pointer;
  text-underline-offset: 0.18em;
}

/*
 * Deck words in Stories: clearly in your Cards (not a whisper).
 * Solid brand underline + visible wash so lay users notice the link.
 */
.read-word--deck {
  text-decoration: underline;
  text-decoration-thickness: 2.25px;
  text-decoration-color: color-mix(in srgb, var(--brand) 72%, transparent);
  background: color-mix(in srgb, var(--brand) 16%, transparent);
  border-radius: 0.32rem;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 28%, transparent);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.read-word--deck:focus-visible {
  background: color-mix(in srgb, var(--brand) 22%, transparent);
  text-decoration-color: var(--brand);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 40%, transparent);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .read-word--deck:hover {
    background: color-mix(in srgb, var(--brand) 22%, transparent);
    text-decoration-color: var(--brand);
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--brand) 38%, transparent);
    outline: none;
  }
}

/* Story-only words: still tappable; quieter than deck so deck stands out */
.read-word--extra {
  text-decoration: underline dotted;
  text-decoration-thickness: 1.35px;
  text-decoration-color: color-mix(in srgb, var(--text-secondary) 55%, transparent);
}

.read-word--extra:focus-visible {
  background: color-mix(in srgb, var(--text-secondary) 7%, transparent);
  text-decoration-color: var(--text-secondary);
  outline: none;
}
@media (hover: hover) and (pointer: fine) {
  .read-word--extra:hover {
    background: color-mix(in srgb, var(--text-secondary) 7%, transparent);
    text-decoration-color: var(--text-secondary);
    outline: none;
  }
}

.read-word--active {
  text-decoration-thickness: 2px;
  text-decoration-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 14%, transparent);
}

.read-word--deck.read-word--active {
  background: color-mix(in srgb, var(--brand) 26%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 42%, transparent);
  text-decoration-thickness: 2.5px;
}

.read-word--extra.read-word--active {
  background: color-mix(in srgb, var(--text-secondary) 12%, transparent);
  text-decoration-style: solid;
}

/*
 * Read footer:
 *  Nav (prev · count · next)  +  tools (Hear primary · English toggle quieter)
 * Matches Review action hierarchy: short labels, clear primary tool.
 */
.read-footer {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
  margin-top: 0.85rem;
  padding-top: 0.35rem;
  border-top: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
}

.read-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
}

.read-nav-btn {
  min-width: 2.9rem;
  min-height: 2.55rem;
  padding-inline: 0.8rem;
  font-size: 1.05rem;
  font-weight: 650;
  touch-action: manipulation;
  border-radius: 999px;
}

.read-nav-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

/* St4: bar above is primary progress; 1/N is a quiet secondary cue */
.read-progress {
  min-width: 4rem;
  text-align: center;
  font-size: 0.78rem;
  font-weight: 550;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text-secondary);
}

.read-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.45rem;
  width: 100%;
  max-width: 20rem;
  margin-inline: auto;
  align-items: stretch;
  min-height: 0;
}

.read-action {
  min-height: 2.55rem;
  width: 100%;
  padding: 0.5rem 0.75rem;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  border-radius: 999px;
  touch-action: manipulation;
}

/*
 * kai (2026-07-28): Hear primary · English quieter mode
 * Aligns with Study tools hierarchy without flattening the pair.
 */
.read-action--hear {
  color: var(--text-secondary);
  font-size: 0.98rem;
  font-weight: 650;
  min-height: 2.7rem;
  background: var(--surface, #fff);
  box-shadow: 0 2px 10px rgba(54, 95, 207, 0.06);
  border-color: var(--border-strong);
}

.read-action--hear:focus-visible {
  color: var(--brand-deep);
}
@media (hover: hover) and (pointer: fine) {
  .read-action--hear:hover {
    color: var(--brand-deep);
  }
}

/* English = quieter toggle; on state uses brand soft */
.read-action--english {
  font-weight: 500;
  font-size: 0.82rem;
  color: var(--text-tertiary);
  background: transparent;
  border-color: color-mix(in srgb, var(--border-strong) 65%, transparent);
  opacity: 0.92;
  min-height: 2.55rem;
}

.read-action--english:focus-visible {
  color: var(--text-secondary);
  border-color: var(--border-strong);
  background: var(--surface-glass);
}
@media (hover: hover) and (pointer: fine) {
  .read-action--english:hover {
    color: var(--text-secondary);
    border-color: var(--border-strong);
    background: var(--surface-glass);
  }
}

/* St5: clearer “English is on” without loud chrome */
.read-action--english.is-on,
.read-action--english[aria-pressed="true"] {
  color: var(--brand-deep);
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
  background: var(--brand-soft);
  font-weight: 650;
  font-size: 0.86rem;
  opacity: 1;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 12%, transparent);
}

@media (pointer: coarse) {
  .read-options {
    gap: 0.55rem;
  }

  .read-action {
    min-height: 50px;
  }

  .read-nav-btn {
    min-height: 50px;
  }
}

.read-reset-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.65rem;
  height: 1.65rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .read-reset-btn:hover:not(:disabled) {
    background: var(--brand-soft);
    color: var(--brand);
  }
}

.read-reset-btn:disabled {
  cursor: default;
}

@media (min-width: 721px) {
  /* - Desktop Read: sentence is hero; tabs only (no lockup); fit one viewport - */
  .app.read-focus {
    padding-top: 1.25rem;
    padding-bottom: 1.25rem;
  }

  .app.read-focus .header {
    margin-bottom: 0.65rem;
  }

  .read-shell {
    /* width owned by base .read-shell */
    padding: 1.1rem 1.3rem 1.05rem;
  }

  .read-header {
    gap: 0.35rem;
    margin-bottom: 0.55rem;
  }

  .read-title-row {
    min-height: 2.65rem;
    border-radius: 0.8rem;
  }

  .read-story-select {
    padding: 0.38rem 0.8rem 0.38rem 0.65rem;
    gap: 0.55rem;
  }

  .read-story-select-title {
    font-size: 1.05rem;
  }

  .read-progress-row {
    min-height: 1.5rem;
    gap: 0.35rem;
  }

  .read-progress-bar {
    height: 4px;
  }

  .read-context--before {
    height: 1.85rem;
    max-height: 1.85rem;
    margin-bottom: 0.45rem;
    padding: 0 0.55rem;
  }

  .read-context--before:not(:has(.read-context-track)) {
    height: 1.85rem;
    max-height: 1.85rem;
    margin-bottom: 0.45rem;
    padding: 0 0.55rem;
    background: transparent;
    opacity: 0.35;
  }

  .read-context-track {
    font-size: 0.9rem;
  }

  /* Sentence stage — room for ~2–3 lines; R1 slightly larger type without dead half-page */
  .read-focus {
    padding: 1.35rem 1.35rem 1.15rem;
    border-radius: var(--radius-sm);
  }

  .read-focus-nb {
    font-size: clamp(1.62rem, 2.3vw, 2.12rem);
    line-height: 1.48;
    padding: 0.32rem 0.2rem;
    /* Two lines + padding — nav stays put while clicking through stories */
    min-height: calc((2 * 1.48em) + 0.64rem);
  }

  .read-gloss-slot {
    margin-top: 0.3rem;
    min-height: 1.75rem;
  }

  .read-footer {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: nowrap;
    margin-top: 0.95rem;
    padding-top: 0.15rem;
  }

  .read-controls {
    flex: 0 0 auto;
    gap: 0.85rem;
  }

  .read-nav-btn {
    min-width: 3.25rem;
    min-height: 2.55rem;
    font-size: 1.15rem;
  }

  .read-progress {
    min-width: 4.75rem;
    font-size: 0.9rem;
  }

  /* Hear primary · English quieter - right-aligned on desktop */
  .read-options {
    flex: 0 1 auto;
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-end;
    align-items: stretch;
    gap: 0.45rem;
    width: auto;
    max-width: none;
    margin-inline: 0;
    margin-top: 0;
  }

  .read-action {
    min-height: 2.55rem;
    min-width: 5.75rem;
    width: auto;
    padding: 0.4rem 1rem;
    font-size: 0.9rem;
  }

  .read-action--english {
    min-width: 5.5rem;
    font-size: 0.86rem;
  }

  .read-menu {
    max-height: min(18rem, 48vh);
    padding: 0.4rem;
  }

  .read-menu-option {
    padding: 0.7rem 0.75rem;
  }

  .read-menu-option-title {
    font-size: 0.92rem;
  }
}

@media (max-width: 720px) {
  /*
   * Mobile Read: fill the visible viewport and scroll the sentence region.
   * Full flex chain (app → main → panel → shell → .read-focus) so Safari and
   * Chrome both get a real scrollport — locking only body without main:min-height:0
   * is a common Safari “can’t scroll” trap.
   */
  html:has(.app.read-focus),
  body:has(.app.read-focus) {
    height: 100%;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
  }

  body:has(.app.read-focus) {
    /* svh first (stable), dvh second when the browser UI collapses */
    max-height: 100svh;
    max-height: 100dvh;
  }

  .app.read-focus {
    height: 100%;
    height: 100dvh;
    max-height: 100svh;
    max-height: 100dvh;
    min-height: 0;
    overflow: hidden;
    overscroll-behavior: none;
    display: flex;
    flex-direction: column;
    /* Seat 6: homescreen Stories — all four safe-area insets */
    padding:
      max(0.65rem, env(safe-area-inset-top, 0px))
      max(0.9rem, env(safe-area-inset-right, 0px))
      max(0.55rem, env(safe-area-inset-bottom, 0px))
      max(0.9rem, env(safe-area-inset-left, 0px));
  }

  .app.read-focus .header {
    flex-shrink: 0;
    margin-bottom: 0.5rem; /* chrome handoff rhythm */
  }

  .app.read-focus main {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .app.read-focus #read-panel.active {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .app.read-focus .read-shell {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .app.read-focus .read-header,
  .app.read-focus .read-context--before,
  .app.read-focus .read-footer {
    flex-shrink: 0;
  }

  .app.read-focus .read-focus {
    flex: 1 1 auto;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    display: flex;
    flex-direction: column;
    /*
     * Pin content to the top of the stage. justify-content: center made the
     * whole Read box jump when English / gloss / line count changed height.
     */
    justify-content: flex-start;
    padding-top: 1.15rem;
  }

  /* - Mobile Read only: hero sentence, equal nav, options - */
  .read-shell {
    padding: 0.9rem 0.8rem 0.8rem;
  }

  .read-header {
    margin-bottom: 0.4rem;
    gap: 0.28rem;
  }

  .read-title-row {
    min-height: 44px;
    border-radius: 0.7rem;
  }

  .read-story-select {
    padding: 0.3rem 0.55rem 0.3rem 0.45rem;
    gap: 0.45rem;
  }

  .read-story-select-title {
    font-size: 0.94rem;
  }

  .read-progress-row {
    min-height: 1.4rem;
  }

  .read-progress-bar {
    height: 3.5px;
  }

  .read-context--before {
    height: 1.55rem;
    max-height: 1.55rem;
    margin-bottom: 0.35rem;
    padding: 0 0.45rem;
  }

  .read-context--before:not(:has(.read-context-track)) {
    height: 1.55rem;
    max-height: 1.55rem;
    margin-bottom: 0.35rem;
    padding: 0 0.45rem;
    background: transparent;
    opacity: 0.35;
  }

  .read-context-track {
    font-size: 0.82rem;
  }

  /* Sentence stage — room for lines, not empty scroll fodder (R1) */
  .read-focus {
    padding: 1.1rem 0.85rem 1rem;
  }

  .read-focus-nb {
    font-size: clamp(1.42rem, 6vw, 1.72rem);
    line-height: 1.46;
    padding: 0.22rem 0.1rem;
    /* Same 2-line reserve (footer is also flex-pinned on mobile) */
    min-height: calc((2 * 1.46em) + 0.44rem);
  }

  .read-gloss-slot {
    margin-top: 0.28rem;
    min-height: 2.35rem;
  }

  /* St1: keep EN reserve on phone so English toggle does not shove footer */
  .read-focus-en-slot {
    min-height: calc(2 * 1.4em + 0.8rem);
    margin-top: 0.4rem;
    padding-top: 0.4rem;
  }

  .read-focus-en {
    font-size: 0.95rem;
    min-height: calc(2 * 1.4em);
  }

  .read-progress-row {
    min-height: 2rem;
    grid-template-columns: minmax(0, 1fr) 2rem;
  }

  .read-progress-row .read-reset-btn {
    width: 2rem;
    height: 2rem;
    font-size: 1.05rem;
  }

  .read-footer {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    margin-top: 0.65rem;
    padding-top: 0;
  }

  /* Nav: equal prev/next thumbs, counter centered */
  .read-controls {
    width: 100%;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.45rem;
  }

  .read-nav-btn {
    width: 100%;
    min-height: 48px;
    max-width: none;
    font-size: 1.2rem;
    font-weight: 600;
  }

  .read-progress {
    flex: none;
    min-width: 3.75rem;
    font-size: 0.76rem;
    font-weight: 550;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
  }

  /* Hear + English - full-width pair on phones */
  .read-options {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem;
    width: 100%;
    max-width: none;
    margin-inline: 0;
    margin-top: 0;
  }

  .read-action {
    width: 100%;
    min-width: 0;
    min-height: 48px;
    padding: 0.4rem 0.5rem;
    font-size: 0.88rem;
  }

  .read-action--english {
    font-size: 0.84rem;
  }

  .read-menu {
    max-height: min(20rem, 58vh);
  }

  .read-menu-option {
    min-height: 48px;
    padding: 0.65rem 0.7rem;
  }
}

/*
 * Short desktop windows (user dragged the browser short - not necessarily
 * phone landscape). Collapse chrome so Review/Read stay usable.
 * Also covers classic short landscape phones (often >720px wide).
 */
@media (max-height: 700px) and (min-width: 721px) {
  .app {
    padding:
      max(0.85rem, env(safe-area-inset-top, 0px))
      max(1rem, env(safe-area-inset-right, 0px))
      max(0.85rem, env(safe-area-inset-bottom, 0px))
      max(1rem, env(safe-area-inset-left, 0px));
    min-height: 100dvh;
  }

  .header {
    margin-bottom: 0.75rem;
  }

  .brand {
    margin-bottom: 0.35rem;
    gap: 0.15rem;
  }

  .brand-logo {
    width: min(140px, 22vw);
    height: auto;
    margin-bottom: 0.1rem;
  }

  .app.practice-focus .brand-logo,
  .app.read-focus .brand-logo {
    width: min(120px, 18vw);
  }

  .tab {
    min-height: 2.15rem;
    padding: 0.4rem 0.9rem;
    font-size: 0.8rem;
  }

  .practice-goal-strip,
  .practice-meta {
    margin-bottom: 0.55rem;
  }

  #practice-panel.active:has(#practice-empty:not(.hidden)) {
    min-height: 0;
    justify-content: flex-start;
    padding-block: 0.35rem 0.5rem;
  }

  .read-focus-nb {
    min-height: calc((2 * 1.48em) + 0.5rem);
  }

  .read-focus {
    padding: 0.75rem 0.85rem 0.7rem;
  }

  .read-context--before {
    height: 1.5rem;
    margin-bottom: 0.35rem;
  }

  .app.read-focus .header {
    margin-bottom: 0.55rem;
  }
}

/* Very short / phone landscape - aggressive chrome collapse */
@media (max-height: 500px) and (orientation: landscape) {
  .app {
    padding:
      max(0.4rem, env(safe-area-inset-top, 0px))
      max(0.75rem, env(safe-area-inset-right, 0px))
      max(0.4rem, env(safe-area-inset-bottom, 0px))
      max(0.75rem, env(safe-area-inset-left, 0px));
    min-height: 100svh;
  }

  .header {
    margin-bottom: 0.4rem;
  }

  .brand {
    margin-bottom: 0.2rem;
    gap: 0.1rem;
  }

  .brand-logo {
    width: min(88px, 18vw);
    height: auto;
    margin-bottom: 0;
  }

  .app.practice-focus .brand-logo,
  .app.read-focus .brand-logo {
    width: min(72px, 15vw);
  }

  .tabs {
    padding: 0.18rem;
  }

  .tab {
    min-height: 2rem;
    padding: 0.35rem 0.7rem;
    font-size: 0.78rem;
  }

  .practice-goal-strip,
  .practice-meta {
    margin-bottom: 0.4rem;
    gap: 0.3rem;
  }

  /* Cancel wide-screen empty Review vertical centering (eats height) */
  #practice-panel.active:has(#practice-empty:not(.hidden)) {
    min-height: 0;
    justify-content: flex-start;
    padding-block: 0;
  }

  #practice-panel.active #practice-empty:not(.hidden) {
    width: min(100%, 20rem);
  }

  .progress-prefs {
    --prefs-h: 2.4rem;
    --prefs-font: 0.7rem;
    --prefs-gap: 0.25rem;
  }
  .progress-basics-glyphs {
    font-size: 0.8rem;
    line-height: 1.35;
  }

  .welcome-modal {
    padding:
      clamp(1.5rem, 8vh, 3rem)
      0.65rem
      max(0.75rem, env(safe-area-inset-bottom, 0px));
  }

  .welcome-card {
    min-height: min(68dvh, 30rem);
    padding-top: 0.5rem;
  }

  .welcome-logo {
    width: min(140px, 38vw);
    height: auto;
  }

  /* Open list must stay smaller than the short-landscape closed door */
  .category-picker--welcome:has(.category-picker-btn[aria-expanded="true"]) .welcome-logo {
    width: min(108px, 30vw);
    max-width: 6.85rem;
  }

  .welcome-card {
    padding: 0.85rem 0.65rem 1rem;
    width: min(100%, 16rem);
  }

  .category-picker-btn--welcome.welcome-door-btn {
    padding: 0.25rem;
  }

  .category-picker--welcome {
    margin-bottom: 0;
  }

  .empty-state {
    padding: 0.75rem 0.85rem 0.8rem;
  }

  .empty-state--actions {
    padding: 0.7rem 0.85rem 0.7rem;
  }

  .empty-actions {
    gap: 0.35rem;
  }

  .empty-home-status {
    gap: 0.4rem;
  }

  .about-logo {
    width: 2.35rem;
    height: auto;
    margin: 0 auto 0.4rem;
  }

  .about-card {
    max-height: min(94svh, 100%);
  }

  .about-card-head {
    margin-bottom: 0.15rem;
  }

  .about-body {
    padding-top: 0;
  }

  .about-section {
    margin-bottom: 0.5rem;
  }

  .about-section-title {
    margin-bottom: 0.25rem;
  }

  .read-shell {
    padding: 0.55rem 0.65rem 0.5rem;
  }

  .read-focus-nb {
    min-height: 2.75rem;
  }

  .read-focus {
    padding: 0.65rem 0.7rem 0.55rem;
  }

  .read-gloss-slot {
    min-height: 1.5rem;
    margin-top: 0.25rem;
  }

  .library-header {
    margin-bottom: 0.5rem;
  }
}


/* =============================================================================
 * Platform safety — agent-owned bar (Safari / Chrome · phone / tablet / desktop)
 * Founder cannot test every device. Prefer these patterns after any layout change.
 *
 * Cursor-only hover paint (LOCKED 2026-07-26 · permanent · founder · Agents.md):
 * Interactive :hover tints (brand soft blue, caution red, any hover transition)
 * live ONLY under @media (hover: hover) and (pointer: fine) — real cursor.
 * No cursor / finger-primary (hover: none or pointer: coarse): NO hover “over”
 * mode. Press uses :active; keyboard uses :focus-visible (outline/ring), not a
 * sticky soft fill without a pointer. Do not reintroduce bare (hover: hover)
 * without pointer:fine. Enforced by tools/platform-audit.py. Second founder
 * reminder — agents must not thrash this again.
 * ============================================================================= */

/*
 * Touch / coarse / no cursor (LOCKED 2026-07-26 · permanent · 2026-07-27 seal):
 * - No soft “over” paint from sticky :hover or :focus after a finger tap
 * - No paint transitions that look like hover mode without a cursor
 * - :active press feedback still OK; keyboard on fine pointer still gets rings
 * - NEVER wipe intentional selected / on / pressed / expanded / listening paint
 *   (sticky :hover with !important was killing Female/Male, SPEAK on, etc.)
 */
@media (hover: none), (pointer: coarse) {
  /*
   * One press language (anti double-flash):
   * 1) No grey WebKit tap flash
   * 2) No animated scale that pops back while selected paint lands
   * 3) Single quiet dim on :active; color belongs to selected/on states only
   */
  .tab,
  .btn,
  .filter-chip,
  .library-reset-btn,
  .progress-read-reset-all,
  .progress-basics-btn,
  .progress-about-btn,
  .category-picker-btn,
  .library-lang-cue,
  .study-lang-cue,
  .read-lang-cue,
  .answer-action,
  .page-float-top-btn,
  .library-jump-chip,
  .add-card-secondary-btn,
  .power-on-btn,
  .category-option,
  .read-lang-option,
  .read-action,
  .basics-word {
    transition: none !important;
    -webkit-tap-highlight-color: transparent;
  }

  .btn:active,
  .power-on-btn:active,
  .tab:active,
  .filter-chip:active,
  .answer-action:active,
  .progress-basics-btn:active,
  .progress-about-btn:active,
  .category-picker-btn:active,
  .library-jump-chip:active,
  .page-float-top-btn:active,
  .read-action:active,
  .library-reset-btn:active,
  .progress-read-reset-all:active {
    transform: none !important;
  }

  /* Brief press dim only — not a second color system fighting selected fill */
  .tab:active,
  .btn:active,
  .filter-chip:active,
  .answer-action:active,
  .progress-basics-btn:active,
  .progress-about-btn:active,
  .category-picker-btn:active,
  .library-jump-chip:active,
  .page-float-top-btn:active,
  .read-action:active,
  .library-lang-cue:active,
  .study-lang-cue:active,
  .read-lang-cue:active,
  .power-on-btn:active,
  .category-option:active,
  .read-lang-option:active,
  .basics-word:active {
    opacity: 0.88;
  }

  /* Power mark: no icon swap / background thrash on finger press (was a clear double flash) */
  .power-on-btn:active {
    border-color: rgba(54, 95, 207, 0.14) !important;
    background: linear-gradient(165deg, #ffffff 0%, #f3f6fd 100%) !important;
    box-shadow:
      0 8px 22px rgba(54, 95, 207, 0.11),
      0 0 0 1px rgba(255, 255, 255, 0.65) inset,
      inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
  }

  .power-on-btn:active .power-on-btn__glow {
    opacity: 0 !important;
  }

  .power-on-btn:active .power-on-btn__icon--off {
    opacity: 1 !important;
    transform: none !important;
  }

  .power-on-btn:active .power-on-btn__icon--on {
    opacity: 0 !important;
  }

  /* --- Rest seals: only unselected / off / closed --- */

  .tab:hover:not(.active),
  .tab:focus:not(.active),
  .tab:focus-visible:not(.active) {
    color: var(--text-secondary) !important;
    background: transparent !important;
    box-shadow: none !important;
  }

  .filter-chip:hover:not(.active),
  .filter-chip:focus:not(.active),
  .filter-chip:focus-visible:not(.active) {
    color: var(--text-secondary) !important;
    background: var(--surface-glass-strong) !important;
    border-color: var(--border-strong) !important;
    box-shadow: none !important;
  }

  /*
   * Ghost / secondary / Study tools: rest only when NOT an intentional on-state.
   * SPEAK is .btn.ghost.answer-action — must keep is-active / pressed / listening.
   */
  /*
   * Exclude .card-action--hear — library solid primary must not collapse to
   * ghost after a tap leaves :focus (was making one Hear blue, next ghost).
   */
  .btn.ghost:hover:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening):not(.card-action--hear),
  .btn.ghost:focus:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening):not(.card-action--hear),
  .btn.ghost:focus-visible:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening):not(.card-action--hear),
  .btn.secondary:hover:not([aria-pressed="true"]):not(.is-active),
  .btn.secondary:focus:not([aria-pressed="true"]):not(.is-active),
  .btn.secondary:focus-visible:not([aria-pressed="true"]):not(.is-active),
  .answer-action:hover:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening),
  .answer-action:focus:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening),
  .answer-action:focus-visible:not([aria-pressed="true"]):not(.is-active):not(.is-on):not(.listening),
  .answer-action--hear:hover:not([aria-pressed="true"]),
  .add-card-secondary-btn:hover,
  .add-card-secondary-btn:focus-visible {
    color: var(--text-secondary) !important;
    background: var(--surface-glass) !important;
    border-color: var(--border-strong) !important;
    box-shadow: none !important;
  }

  .btn.secondary:hover:not([aria-pressed="true"]),
  .btn.secondary:focus-visible:not([aria-pressed="true"]) {
    color: var(--brand-deep) !important;
    background: var(--surface-glass-strong) !important;
    border-color: var(--brand-ring) !important;
  }

  .progress-basics-btn:hover,
  .progress-basics-btn:focus,
  .progress-basics-btn:focus-visible,
  .progress-about-btn:hover,
  .progress-about-btn:focus,
  .progress-about-btn:focus-visible,
  .category-picker-btn.category-picker-btn--progress:hover:not([aria-expanded="true"]),
  .category-picker-btn.category-picker-btn--progress:focus:not([aria-expanded="true"]),
  .category-picker-btn.category-picker-btn--progress:focus-visible:not([aria-expanded="true"]) {
    color: var(--text-secondary) !important;
    background: var(--surface-glass-strong) !important;
    border-color: var(--border-strong) !important;
    box-shadow: none !important;
  }

  .progress-basics-btn:focus-visible .progress-basics-glyphs {
    color: inherit !important;
  }
  .read-lang-cue:hover:not([aria-expanded="true"]),
  .read-lang-cue:focus:not([aria-expanded="true"]),
  .read-lang-cue:focus-visible:not([aria-expanded="true"]) {
    background: color-mix(in srgb, var(--surface-2, #f4f6fb) 70%, white) !important;
    border-color: var(--border-strong) !important;
    box-shadow: none !important;
  }

  .library-lang-cue:hover:not([aria-expanded="true"]),
  .library-lang-cue:focus:not([aria-expanded="true"]),
  .library-lang-cue:focus-visible:not([aria-expanded="true"]),
  .study-lang-cue:hover:not([aria-expanded="true"]),
  .study-lang-cue:focus:not([aria-expanded="true"]),
  .study-lang-cue:focus-visible:not([aria-expanded="true"]) {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
  }

  .page-float-top-btn:hover,
  .page-float-top-btn:focus-visible {
    background: var(--surface-glass-strong) !important;
    border-color: var(--border-strong) !important;
    color: var(--brand-deep) !important;
    box-shadow: var(--shadow-md) !important;
  }

  .library-jump-chip:hover:not(.is-active),
  .library-jump-chip:focus:not(.is-active),
  .library-jump-chip:focus-visible:not(.is-active) {
    color: var(--text-tertiary) !important;
    background: transparent !important;
    border-color: transparent !important;
  }

  .library-reset-btn:hover,
  .library-reset-btn:focus,
  .library-reset-btn:focus-visible,
  .progress-read-reset-all:hover,
  .progress-read-reset-all:focus,
  .progress-read-reset-all:focus-visible {
    color: var(--text-tertiary) !important;
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
  }

  .progress-read-reset-all:hover,
  .progress-read-reset-all:focus-visible {
    border-color: var(--border-strong) !important;
  }

  .library-reset-btn:active,
  .progress-read-reset-all:active {
    color: color-mix(in srgb, var(--error, #d70015) 88%, var(--ink)) !important;
    background: color-mix(in srgb, var(--error, #d70015) 12%, transparent) !important;
    border-color: color-mix(in srgb, var(--error, #d70015) 18%, transparent) !important;
  }

  .library-theme-btn--remove:hover,
  .library-theme-btn--remove:focus-visible,
  .btn.ghost.library-theme-btn.library-theme-btn--remove:hover,
  .btn.ghost.library-theme-btn.library-theme-btn--remove:focus-visible {
    color: var(--text-tertiary) !important;
    background: transparent !important;
    border-color: transparent !important;
  }

  .category-option:hover:not(:disabled):not(.active),
  .category-option:focus:not(:disabled):not(.active),
  .category-option:focus-visible:not(:disabled):not(.active),
  .read-lang-option:hover:not(.active),
  .read-lang-option:focus:not(.active),
  .read-lang-option:focus-visible:not(.active) {
    background: transparent !important;
    color: var(--ink) !important;
  }

  .basics-word:hover,
  .basics-word:focus-visible {
    background: transparent !important;
    color: var(--brand-deep) !important;
  }

  .btn.primary:hover,
  .btn.primary:focus-visible {
    background: var(--brand-gradient) !important;
    color: #fff !important;
    box-shadow: var(--shadow-brand) !important;
  }

  /* --- Intentional on-states: sticky hover/focus must NOT win --- */

  .tab.active,
  .tab.active:hover,
  .tab.active:focus,
  .tab.active:focus-visible {
    color: #fff !important;
    background: var(--brand-gradient) !important;
    box-shadow: var(--shadow-brand) !important;
  }

  .filter-chip.active,
  .filter-chip.active:hover,
  .filter-chip.active:focus,
  .filter-chip.active:focus-visible {
    color: #fff !important;
    background: var(--brand-gradient) !important;
    border-color: transparent !important;
    box-shadow: none !important;
  }
  #speak-btn.is-active,
  #speak-btn[aria-pressed="true"]:not(.listening),
  #speak-btn.is-active:hover,
  #speak-btn[aria-pressed="true"]:not(.listening):hover,
  #speak-btn.is-active:focus,
  #speak-btn[aria-pressed="true"]:not(.listening):focus,
  #speak-btn.is-active:focus-visible,
  #speak-btn[aria-pressed="true"]:not(.listening):focus-visible {
    color: var(--brand-deep) !important;
    border-color: color-mix(in srgb, var(--brand) 28%, transparent) !important;
    background: var(--brand-soft) !important;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 12%, transparent) !important;
    font-weight: 650 !important;
  }

  #speak-btn.listening,
  #speak-btn.listening:hover,
  #speak-btn.listening:focus,
  #speak-btn.listening:focus-visible {
    color: #fff !important;
    border-color: transparent !important;
    background: var(--brand-gradient) !important;
    box-shadow: var(--shadow-brand) !important;
  }

  .read-action--english.is-on,
  .read-action--english[aria-pressed="true"],
  .read-action--english.is-on:hover,
  .read-action--english[aria-pressed="true"]:hover,
  .read-action--english.is-on:focus,
  .read-action--english[aria-pressed="true"]:focus,
  .read-action--english.is-on:focus-visible,
  .read-action--english[aria-pressed="true"]:focus-visible {
    color: var(--brand-deep) !important;
    border-color: color-mix(in srgb, var(--brand) 28%, transparent) !important;
    background: var(--brand-soft) !important;
    font-weight: 650 !important;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 12%, transparent) !important;
  }

  .library-jump-chip.is-active,
  .library-jump-chip.is-active:hover,
  .library-jump-chip.is-active:focus,
  .library-jump-chip.is-active:focus-visible {
    color: #fff !important;
    background: var(--brand-gradient) !important;
    border-color: transparent !important;
    box-shadow: none !important;
    font-weight: 650 !important;
  }

  .category-option.active,
  .category-option.active:hover,
  .category-option.active:focus,
  .category-option.active:focus-visible,
  .read-lang-option.active,
  .read-lang-option.active:hover,
  .read-lang-option.active:focus,
  .read-lang-option.active:focus-visible {
    background: linear-gradient(135deg, rgba(91, 154, 255, 0.14), rgba(54, 95, 207, 0.08)) !important;
    color: var(--brand-deep) !important;
  }

  .category-picker-btn.category-picker-btn--progress[aria-expanded="true"],
  .category-picker-btn.category-picker-btn--progress[aria-expanded="true"]:hover,
  .category-picker-btn.category-picker-btn--progress[aria-expanded="true"]:focus,
  .category-picker-btn.category-picker-btn--progress[aria-expanded="true"]:focus-visible {
    color: var(--brand-deep) !important;
    background: var(--brand-soft) !important;
    border-color: transparent !important;
  }

  .library-lang-cue[aria-expanded="true"],
  .library-lang-cue[aria-expanded="true"]:hover,
  .library-lang-cue[aria-expanded="true"]:focus,
  .study-lang-cue[aria-expanded="true"],
  .study-lang-cue[aria-expanded="true"]:hover,
  .study-lang-cue[aria-expanded="true"]:focus,
  .read-lang-cue[aria-expanded="true"],
  .read-lang-cue[aria-expanded="true"]:hover,
  .read-lang-cue[aria-expanded="true"]:focus {
    background: color-mix(in srgb, var(--brand-soft) 85%, transparent) !important;
  }
}

/*
 * Touch / iPad: primary controls stay ≥44px when “desktop” width still means fingers.
 * iPad often matches min-width: 721px but pointer: coarse.
 */
@media (pointer: coarse) {
  .tab {
    min-height: max(2.4rem, 44px);
  }

  .filter-chip {
    min-height: max(2.15rem, 44px);
  }

  .library-jump-chip {
    min-height: max(2rem, 44px);
  }

  .btn:not(.answer-action),
  .page-float-top-btn {
    min-height: max(2.55rem, 44px);
  }

  /*
   * Study card tools: keep Hear primary (≥48px); do not force SPEAK
   * up to the same floor as Hear (that was flattening the hierarchy).
   */
  .answer-actions .btn.answer-action--hear {
    min-height: max(3.05rem, 50px);
  }

  .answer-actions .btn.answer-action--speak,
  .answer-actions .btn.answer-action--match {
    min-height: max(2.35rem, 44px);
    height: max(2.35rem, 44px);
  }

  /*
   * Path prefs + language chips: desktop pills are ~2.35rem; fingers need ≥44px
   * even when iPad reports a “wide” layout (same law as Study/Cards tools).
   */
  .progress-prefs {
    --prefs-h: max(2.35rem, 44px);
  }

  .category-picker-btn.category-picker-btn--progress,
  .progress-basics-btn,
  .progress-about-btn {
    min-height: max(var(--prefs-h, 2.35rem), 44px);
    height: max(var(--prefs-h, 2.35rem), 44px);
    touch-action: manipulation;
  }

  /* Basics hear chips — real controls, not just underlined text */
  .basics-word {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 2.75rem;
    padding: 0.35rem 0.55rem;
    box-sizing: border-box;
  }

  /*
   * Pack tiles: keep compact equal pills. Global .btn 44px would make
   * Study+Remove tiles taller than Add-only even with a spacer.
   */
  .library-theme-actions .btn {
    min-height: 1.9rem;
    max-height: 1.9rem;
    height: 1.9rem;
  }

  .library-theme-actions .library-theme-btn--remove {
    min-height: 1.85rem;
    max-height: 1.85rem;
    height: 1.85rem;
  }
}

/*
 * Prefer reduced motion: already handled elsewhere; keep fixed chrome from fighting
 * safe areas on notched phones (home indicator / Dynamic Island).
 */
@supports (padding: env(safe-area-inset-bottom)) {
  body {
    /* Scrollport padding so last list rows clear the home indicator when needed */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
}

/* ─────────────────────────────────────────────────────────────
 * Match — bonus recognition
 * Entry: mid-session only, same row as Hear · SPEAK (icon)
 * Study home unchanged (no Match on power screen)
 * Never due · no progress count · no box promote
 * ───────────────────────────────────────────────────────────── */

/*
 * Match: right wing (grid column 3) — same seat height as SPEAK.
 * Rest: solid brand door. Cursor hover: soft brand fill.
 */
.answer-actions .btn.answer-action--match,
.answer-action--match {
  grid-column: 3;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  width: 2.75rem;
  min-height: 2.35rem;
  height: 2.35rem;
  padding: 0;
  margin: 0;
  color: var(--brand, #365fcf);
  opacity: 1;
  background: var(--surface-glass, rgba(255, 255, 255, 0.72));
  border-color: var(--border-strong, rgba(54, 95, 207, 0.16));
  box-sizing: border-box;
}

/* Match mark: square G board — slightly larger so it reads next to SPEAK type */
.answer-action-match-icon {
  width: 1.18rem;
  height: 1.18rem;
  display: block;
}

/* While Match room is open, hide card session UI */
#practice-panel.match-open #practice-empty,
#practice-panel.match-open #practice-active {
  display: none !important;
}

/*
 * Match room needs a real height chain inside the Study panel.
 * Top inset matches mid-session Study card panel so the language flag
 * does not jump when hopping Match ↔ Study (founder 2026-07-28 flow).
 */
#practice-panel.match-open {
  display: flex;
  flex-direction: column;
  min-height: min(70dvh, 36rem);
  /* Same as .app.practice-focus #practice-panel…#practice-active:not(.hidden) */
  padding-top: 0.65rem;
  padding-bottom: clamp(1.5rem, 8dvh, 4rem);
  box-sizing: border-box;
}

.match-room {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  width: 100%;
  max-width: 28rem;
  margin: 0 auto;
  /* Shared with Study card — flag hop Y law */
  padding: var(--study-mid-shell-pad-top) 0.65rem 0.85rem;
  box-sizing: border-box;
  /*
   * Residual B (2026-07-28): fully open room — no placard fill/border/shadow.
   * Only top bar + tiles sit on Study ambient. Flag Y/size still locked.
   */
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.match-room.hidden {
  display: none !important;
}

.match-room__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  /* Shared with Study .practice-card-top */
  min-height: var(--study-mid-flag-row);
  margin-bottom: var(--study-mid-flag-band-mb);
  flex-shrink: 0;
}

/*
 * Match → Study card: miniature power coin.
 * Sized to flag seat (2.15rem) so top bar weight is even (flag law stays).
 * Win over base .power-on-btn size with higher specificity + !important on box.
 */
#match-room .match-home-btn.power-on-btn {
  width: var(--study-mid-flag-seat) !important;
  height: var(--study-mid-flag-seat) !important;
  min-width: var(--study-mid-flag-seat) !important;
  min-height: var(--study-mid-flag-seat) !important;
  max-width: var(--study-mid-flag-seat) !important;
  max-height: var(--study-mid-flag-seat) !important;
  flex-shrink: 0;
  cursor: pointer;
  pointer-events: auto;
  box-sizing: border-box;
}

#match-room .match-home-btn.power-on-btn .power-on-btn__icon {
  width: 0.95rem !important;
  height: auto !important;
  max-width: 0.95rem;
}

#match-room .match-home-btn.power-on-btn .power-on-btn__glow {
  inset: -0.15rem;
}

/* Quiet blue mark on the coin (always “on” here — not black idle) */
#match-room .match-home-btn.power-on-btn .power-on-btn__icon--off {
  opacity: 0;
}

#match-room .match-home-btn.power-on-btn .power-on-btn__icon--on {
  opacity: 1;
  transform: scale(1);
}

@media (hover: hover) and (pointer: fine) {
  #match-room .match-home-btn.power-on-btn:hover .power-on-btn__glow {
    opacity: 0.45;
  }
}

#match-room .match-home-btn.power-on-btn:focus-visible {
  outline: 2px solid var(--brand, #365fcf);
  outline-offset: 2px;
}

/* Top bar: coin left · flag center · balance right (same width as coin) */
#match-room .match-room__top {
  align-items: center;
}

#match-room .match-room__spacer {
  width: var(--study-mid-flag-seat);
  min-width: var(--study-mid-flag-seat);
  max-width: var(--study-mid-flag-seat);
}

/* Center: language flag (not logo) — hop language, stay in Match */
.match-lang-picker {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  min-width: 0;
}

/* Same glyph + seat as Study .study-lang-cue (stable hop Match ↔ Study) */
.match-lang-cue {
  appearance: none;
  border: none;
  background: transparent;
  padding: 0;
  border-radius: 0.45rem;
  cursor: pointer;
  font-size: 1.55rem;
  line-height: 1;
  width: var(--study-mid-flag-seat);
  min-height: var(--study-mid-flag-seat);
  min-width: var(--study-mid-flag-seat);
  display: grid;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  font-family: inherit;
}

.match-lang-cue:focus-visible {
  outline: 2px solid var(--brand, #365fcf);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .match-lang-cue:hover {
    background: var(--brand-soft, rgba(54, 95, 207, 0.1));
  }
}

.match-lang-cue-flag {
  display: block;
  font-size: 1.55rem;
  line-height: 1;
  filter: drop-shadow(0 0.5px 0.5px rgba(15, 23, 42, 0.08));
}

/*
 * Match language list — Study/Cards parity:
 * dock under flag, capped height, scroll + edge fades + chevron cues.
 * Cues centered mid-panel; top cue points at the flag (JS fit centers panel).
 */
.match-lang-menu.library-lang-menu {
  /* base library-lang-menu chrome; open position set in fitCategoryMenuToViewport */
  z-index: 55;
}

.match-lang-menu.is-scrollable .category-picker-scroll-cue {
  display: flex;
}

.match-lang-menu.has-more-below .category-picker-scroll-cue--down {
  opacity: 1;
}

.match-lang-menu.has-more-above .category-picker-scroll-cue--up {
  opacity: 1;
}

/* While Match lang list is open, keep room above board chrome */
#match-room:has(#match-lang-menu:not(.hidden)),
#match-room:has(.match-lang-cue[aria-expanded="true"]) {
  z-index: 40;
}

.match-room__spacer {
  width: var(--study-mid-flag-seat);
  min-width: var(--study-mid-flag-seat);
  flex-shrink: 0;
}

.match-board {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem 0.55rem;
  align-content: start;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%;
}

.match-board.hidden {
  display: none !important;
}

/* Quieter tiles — Study placard family (B aesthetics · 2026-07-28) */
.match-tile {
  appearance: none;
  border: 1.5px solid rgba(54, 95, 207, 0.12);
  background: rgba(255, 255, 255, 0.92);
  border-radius: 16px;
  min-height: 2.85rem;
  padding: 0.5rem 0.55rem;
  font-family: inherit;
  font-size: 0.94rem;
  font-weight: 500;
  color: var(--text, #231f20);
  letter-spacing: -0.015em;
  line-height: 1.28;
  text-align: center;
  box-shadow: none;
  cursor: pointer;
  transition:
    border-color 0.15s var(--ease, ease),
    background 0.15s var(--ease, ease),
    box-shadow 0.15s var(--ease, ease),
    opacity 0.24s var(--ease, ease),
    transform 0.2s var(--ease, ease);
  -webkit-tap-highlight-color: transparent;
}

.match-tile:focus-visible {
  outline: 2px solid var(--brand, #365fcf);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .match-tile:hover:not(.selected):not(.wrong):not(.ok):not(:disabled) {
    border-color: rgba(54, 95, 207, 0.28);
  }
}

.match-tile.selected {
  border-color: var(--brand, #365fcf);
  background: var(--brand-soft, rgba(54, 95, 207, 0.1));
  box-shadow: 0 0 0 3px var(--brand-ring, rgba(54, 95, 207, 0.22));
  color: var(--brand-deep, #2849a8);
  font-weight: 600;
}

/*
 * Match wrong flash (B · 2026-07-28): both tiles same soft red.
 * No select blue, no brand focus ring — one miss voice, not red + blue.
 * No micro-shake (calm + photosensitive).
 */
.match-tile.wrong,
.match-tile.selected.wrong,
.match-tile.wrong:focus,
.match-tile.wrong:focus-visible,
.match-tile.wrong:hover {
  border-color: rgba(215, 0, 21, 0.34);
  background: rgba(215, 0, 21, 0.08);
  color: var(--text, #231f20);
  font-weight: 550;
  box-shadow: 0 0 0 3px rgba(215, 0, 21, 0.1);
  outline: none;
  animation: none;
}

.match-tile.ok {
  border-color: rgba(36, 138, 61, 0.42);
  background: rgba(36, 138, 61, 0.1);
  color: color-mix(in srgb, var(--success, #248a3d) 82%, var(--text, #231f20));
  font-weight: 600;
  box-shadow: 0 0 0 3px rgba(36, 138, 61, 0.12);
}

.match-tile.leaving {
  opacity: 0;
  transform: scale(0.94);
  pointer-events: none;
}

.match-tile.enter {
  animation: match-tile-enter 0.28s var(--ease, ease);
}

.match-tile:disabled {
  cursor: default;
}

@keyframes match-tile-enter {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .match-tile.wrong {
    /* paint only — no motion */
    opacity: 1;
  }
  .match-tile.enter {
    animation: none;
  }
  .match-tile {
    transition: border-color 0.01s, background 0.01s, box-shadow 0.01s, opacity 0.01s;
  }
  .match-tile.leaving {
    transform: none;
  }
}

.match-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.45rem;
  padding: 0.75rem 0.5rem 1rem;
  min-height: 0;
}

.match-empty.hidden {
  display: none !important;
}

.match-empty__title {
  margin: 0;
  font-size: 1.12rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--text, #231f20);
}

.match-empty__copy {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.4;
  color: var(--text-tertiary, #7a7a82);
  max-width: 16rem;
}

.match-empty .btn {
  margin-top: 0.75rem;
  max-width: 15rem;
  width: 100%;
}

@media (pointer: coarse) {
  .match-door {
    min-height: 2.85rem;
    min-width: 2.85rem;
  }
  .match-tile {
    min-height: 3.05rem;
  }
  .spar-exit {
    min-height: 44px;
    min-width: 44px;
  }
  .foundation-spar {
    min-height: 44px;
    min-width: 44px;
  }
  .foundation-spar__mark {
    min-height: 44px;
    min-width: 4.05rem;
    padding: 0.38rem 0.9rem;
  }
  .spar-input {
    min-height: 44px;
  }
}

/*
 * Spar room (2026-07-30). Full Study-panel takeover, same pattern as Match.
 *
 * The clock is never drawn. No countdown bar, no shrinking ring, no colour
 * turning red: that is the toy chrome the product refuses. The Master speaks,
 * then there is silence, and the silence is the pressure.
 *
 * Every band holds a reserved seat, so the stage cannot resize between
 * speaking, waiting, answering and reading out (stable shell law).
 */
/**
 * The room takes the screen (2026-08-02 · founder).
 *
 * It used to render inside the normal furniture — brand header and tab bar
 * still visible — so an encounter the learner can lose read as a form with a
 * lot of empty space under it. It now fills the viewport and the stage centres
 * in it, which is also what closes the ~700px of dead space below the input.
 */
.spar-room {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 0.4rem 0 1rem;
}

body.spar-open .spar-room {
  position: fixed;
  inset: 0;
  z-index: 60;
  /* Full-screen event: respect notch / home indicator (Home Screen + iPhone). */
  padding:
    max(0.4rem, env(safe-area-inset-top, 0px))
    max(0.75rem, env(safe-area-inset-right, 0px))
    max(0.75rem, env(safe-area-inset-bottom, 0px))
    max(0.75rem, env(safe-area-inset-left, 0px));
  background: var(--app-bg, linear-gradient(160deg, #eef2fb, #e6ecf9));
  box-sizing: border-box;
  /* Keyboard fit sets height/top from visualViewport (iOS does not shrink fixed inset). */
  overflow: hidden;
}

/*
 * Soft keyboard open (founder 2026-08-09 · mobile): keep L2 + English + field
 * in the visual viewport. Fixed full-screen was centering content under the
 * keyboard so context disappeared.
 */
body.spar-open .spar-room.is-keyboard-open {
  overflow: hidden;
}

body.spar-open .spar-room.is-keyboard-open .spar-room__top {
  padding-top: 0.35rem;
  padding-bottom: 0.2rem;
  min-height: 2.4rem;
  flex-shrink: 0;
}

body.spar-open .spar-room.is-keyboard-open .spar-stage {
  justify-content: flex-start;
  gap: 0.4rem;
  padding: 0.15rem 0.75rem 0.35rem;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  min-height: 0;
}

body.spar-open .spar-room.is-keyboard-open .talk-scene {
  min-height: 0;
  font-size: 0.68rem;
  opacity: 0.85;
}

body.spar-open .spar-room.is-keyboard-open .spar-master {
  width: 2.85rem;
  height: 2.85rem;
  flex-shrink: 0;
  opacity: 0.9;
}

body.spar-open .spar-room.is-keyboard-open .spar-master__mark {
  width: 26px;
}

body.spar-open .spar-room.is-keyboard-open .spar-line {
  font-size: 1.2rem;
  min-height: 0;
  line-height: 1.25;
  flex-shrink: 0;
}

body.spar-open .spar-room.is-keyboard-open .spar-readout {
  font-size: 0.82rem;
  min-height: 0;
  flex-shrink: 0;
}

body.spar-open .spar-room.is-keyboard-open .spar-form {
  flex-shrink: 0;
  margin-top: 0.15rem;
}

body.spar-open .spar-room.is-keyboard-open .speak-type-keys {
  margin-top: 0.35rem;
  gap: 0.28rem;
}

body.spar-open .spar-room.is-keyboard-open .speak-type-keys__key {
  min-width: 2.35rem;
  min-height: 2.35rem;
  font-size: 1.05rem;
}

body.spar-open .spar-room.is-keyboard-open .spar-miss,
body.spar-open .spar-room.is-keyboard-open .talk-model,
body.spar-open .spar-room.is-keyboard-open .spar-again,
body.spar-open .spar-room.is-keyboard-open .spar-study-first {
  min-height: 0;
}

@media (pointer: coarse) {
  body.spar-open .spar-room.is-keyboard-open .spar-room__top {
    flex-wrap: wrap;
    gap: 0.35rem 0.5rem;
  }

  body.spar-open .spar-room.is-keyboard-open .speak-mode-toggle__opt {
    min-height: 2rem;
    min-width: 3rem;
    padding: 0.22rem 0.55rem;
    font-size: 0.68rem;
  }
}

/* The furniture goes away: this is an event, not a tab. */
body.spar-open > .header,
body.spar-open .header,
body.spar-open .tabs {
  display: none;
}

.spar-room.hidden {
  display: none;
}

.spar-room__top {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.5rem;
  padding: 0.9rem 1rem 0.4rem;
  min-height: 2.75rem;
  /* Two seats: flag | actions. Actions may shrink; they must not cover the flag. */
  width: 100%;
  box-sizing: border-box;
}

/*
 * Phone top bar (Varde 875–876 · Kai 877).
 *
 * Flag is a reserved seat; actions take only the remaining flex track
 * (see .spar-room__top-actions). Size relief must cover real phones, not only
 * ≤380: 390 (iPhone 12–15) and 414 (Plus/Max) sat just above 876’s ceiling and
 * still pushed Speak under the flag. Touch-emulate when measuring — plain
 * headless matches the desktop (hover+fine) branch even at 320px.
 *
 * LEAVE most of all: still fully on-screen. RESUME min-width preserved.
 * Scoped under body.spar-open so room rules win.
 */
@media (max-width: 440px), (pointer: coarse) {
  body.spar-open .spar-room__top {
    gap: 0.3rem;
    padding-left: 0.45rem;
    padding-right: 0.45rem;
  }

  body.spar-open .speak-lang-picker--room {
    flex: 0 0 auto;
  }

  body.spar-open .speak-lang-cue {
    min-width: 2.5rem;
    min-height: 2.5rem;
    padding: 0.28rem 0.4rem;
  }

  body.spar-open .speak-lang-cue-flag {
    font-size: 1.2rem;
  }

  body.spar-open .spar-room__top-actions {
    flex: 1 1 0;
    min-width: 0;
    margin-left: 0;
    gap: 0.2rem;
    flex-wrap: nowrap;
  }

  body.spar-open .speak-mode-toggle {
    flex: 0 1 auto;
    padding: 0.1rem;
    gap: 0.04rem;
    min-width: 0;
  }

  body.spar-open .speak-mode-toggle__opt {
    min-height: 2rem;
    min-width: 2.35rem;
    padding: 0.16rem 0.36rem;
    font-size: 0.6rem;
    letter-spacing: 0.04em;
  }

  body.spar-open .spar-pause,
  body.spar-open .spar-exit {
    padding-left: 0.1rem;
    padding-right: 0.1rem;
    letter-spacing: 0.03em;
    font-size: 0.62rem;
    flex-shrink: 0;
  }

  body.spar-open .spar-pause {
    min-width: 4.35rem;
    margin-right: 0;
  }

  body.spar-open .speak-english-toggle {
    padding-left: 0.24rem;
    padding-right: 0.24rem;
    font-size: 0.58rem;
    min-height: 1.85rem;
    /* Allow a hair of shrink so Type × English do not collide at 320. */
    flex: 0 1 auto;
    min-width: 3.1rem;
  }
}

/* Tightest phones: extra compression so Type × English clear (Varde 877). */
@media (max-width: 360px) {
  body.spar-open .spar-room__top {
    gap: 0.22rem;
    padding-left: 0.32rem;
    padding-right: 0.32rem;
  }

  body.spar-open .spar-room__top-actions {
    gap: 0.14rem;
  }

  body.spar-open .speak-mode-toggle__opt {
    min-width: 2.2rem;
    padding: 0.14rem 0.3rem;
    font-size: 0.58rem;
  }

  body.spar-open .speak-english-toggle {
    min-width: 2.85rem;
    padding-left: 0.18rem;
    padding-right: 0.18rem;
    font-size: 0.55rem;
  }

  body.spar-open .spar-pause {
    min-width: 4.15rem;
  }

  body.spar-open .speak-lang-cue {
    min-width: 2.35rem;
    min-height: 2.35rem;
    padding: 0.22rem 0.32rem;
  }
}

/*
 * Desktop: one even cluster in the top center (founder 2026-08-09).
 * Mobile keeps edge layout so flag / leave stay easy to reach with thumbs.
 * Comes AFTER phone density so fine+hover restores comfortable desktop sizes.
 */
@media (hover: hover) and (pointer: fine) {
  .spar-room__top {
    justify-content: center;
    gap: 1.35rem;
    max-width: 40rem;
    width: 100%;
    margin-inline: auto;
    padding-inline: 1.25rem;
  }

  .spar-room__top-actions {
    flex: 0 1 auto;
    min-width: 0;
    margin-left: 0;
    gap: 1.1rem;
  }

  .speak-lang-picker--room {
    flex: 0 0 auto;
  }

  body.spar-open .speak-mode-toggle__opt {
    min-height: 2.15rem;
    min-width: 3.4rem;
    padding: 0.28rem 0.72rem;
    font-size: 0.72rem;
  }

  body.spar-open .speak-english-toggle {
    min-width: 0;
    flex: 0 0 auto;
    font-size: 0.72rem;
    padding: 0.28rem 0.62rem;
    min-height: 2.15rem;
  }

  body.spar-open .spar-pause {
    min-width: 5.35rem;
  }
}

/* No drawn clock. The window is real (SPAR_PATIENCE_MS) but it is the
   Master's patience, not a buzzer — it asks, then there is silence, and the
   silence is the pressure. A draining bar is the toy chrome this product
   refuses. The bar removed here was built 2026-08-02 for a mute Master;
   builds 729-731 gave it a voice. */

/* Round over, or nothing to type yet: keep the seat, drop the empty pill.
   visibility, never display — the stage must not resize (stable shell law). */
.spar-input:disabled {
  visibility: hidden;
}

/* Build 733 gave the input a wrapper so the mic could share its seat, and the
   wrapper carries the border and fill. Hiding only the input left the pill
   still drawn — an empty bordered lozenge sitting above the diagnosis, which is
   the same furniture the law above exists to remove. Hide the chrome, keep the
   box: min-height still holds the seat, so nothing moves. */
.spar-answer-seat:has(.spar-input:disabled) {
  border-color: transparent;
  background: transparent;
}

/* The exit is plainly not the opponent. It used to be a second bulb stacked
   directly above the Master's bulb, identical in shape and size.
   flex-shrink: 0 — LEAVE must never compress when Pause grows (build 868). */
.spar-exit {
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  cursor: pointer;
  padding: 0.35rem 0.45rem;
  min-height: 2.75rem;
  min-width: 2.75rem;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}

.spar-exit:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
  border-radius: 0.4rem;
}

@media (hover: hover) and (pointer: fine) {
  .spar-exit:hover {
    color: var(--brand-deep);
  }
}

.spar-stage {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  padding: 0.4rem 1rem 1.2rem;
}

/* A miss leaves a mark. Reserved seat so the stage never jumps. */
.spar-miss {
  margin: 0;
  min-height: 1.3rem;
  font-size: 0.88rem;
  line-height: 1.3rem;
  text-align: center;
  color: var(--text-tertiary);
}

.spar-miss.is-shown {
  color: var(--miss, #b4443c);
}

/* One pulse on a miss — presence, not a strobe (photosensitive-safe). */
.spar-room.is-missed .spar-master {
  animation: spar-missed 0.5s var(--ease) 1;
}

@keyframes spar-missed {
  50% {
    box-shadow: 0 6px 22px rgba(180, 68, 60, 0.45);
    filter: saturate(0.6);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spar-room.is-missed .spar-master {
    animation: none;
  }
}

/* The Master: a mark and a rhythm, never an avatar */
.spar-master {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.1rem;
  height: 5.1rem;
  border-radius: 50%;
  background: var(--brand-gradient);
  box-shadow: 0 6px 18px rgba(54, 95, 207, 0.22);
  /* Rest was 0.55 — read as broken/cloudy next to the line (founder 2026-08-09). */
  opacity: 0.88;
  transition: opacity 0.45s var(--ease);
}

/* Speaking is a lift in presence, never a flash (photosensitive-safe) */
.spar-room.is-speaking .spar-master {
  opacity: 1;
}

.spar-master__mark {
  width: 44px;
  height: auto;
  display: block;
}

/* Reserved seat: two lines, so a long prompt never moves the input.
   The prompt is the question — it carries the stage now, rather than sitting
   at the weight of a label. */
.spar-line {
  margin: 0;
  min-height: 3.4rem;
  display: flex;
  align-items: center;
  text-align: center;
  color: var(--ink);
  font-size: 1.65rem;
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.02em;
  /* Never inherit a wash from ancestors; pause uses a light fade only. */
  opacity: 1;
}

.spar-form {
  width: 100%;
  max-width: 22rem;
}

/* Input + mic share one pill seat so the stage never jumps (Build 733). */
.spar-answer-seat {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  min-height: 3rem;
  padding: 0.2rem 0.25rem 0.2rem 0.15rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-glass-strong);
  box-sizing: border-box;
}

/* Talk/Speak: no in-box mic — Speak|Type toggle is the only modality control. */
.spar-room.is-mic-free .spar-answer-seat {
  padding: 0.2rem 0.15rem;
}

.spar-room.is-mic-free .spar-input {
  padding: 0.5rem 1rem;
}

/* Belt-and-suspenders: never paint the seat mic in Talk (Speak or Type). */
.spar-room.is-mic-free .spar-mic,
.spar-room:not(.is-drill) .spar-mic {
  display: none !important;
}

.spar-input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  min-height: 2.6rem;
  margin: 0;
  padding: 0.5rem 0.75rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  /* 16px floor stops iOS zooming the shell on focus */
  font-size: 1rem;
  text-align: center;
  box-sizing: border-box;
}

.spar-input:focus {
  outline: none;
}

.spar-answer-seat:focus-within {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

.spar-mic {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.spar-mic:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 1px;
}

.spar-mic:active {
  color: var(--brand);
}

.spar-mic[hidden] {
  display: none;
}

/* Learner voice-in: quiet listening on the shared seat (732–733).
 * Talk hides the mic (Speak|Type owns modality) — seat ring is the live cue. */
.spar-room.is-listening .spar-answer-seat {
  border-color: color-mix(in srgb, var(--brand) 55%, var(--border-strong));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--brand) 22%, transparent),
    0 0 0 4px color-mix(in srgb, var(--brand) 10%, transparent);
}

.spar-room.is-listening .spar-mic {
  color: var(--brand);
}

/* Soft gap after silence/garble: seat calm, mic still present, no thrash pulse. */
.spar-room.is-voice-soft .spar-answer-seat {
  border-color: var(--border-strong);
  box-shadow: none;
}

.spar-room.is-voice-soft .spar-mic {
  color: color-mix(in srgb, var(--brand) 55%, var(--text-secondary));
  opacity: 0.85;
}

.spar-room.is-listening .spar-master {
  opacity: 0.94;
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--brand) 28%, transparent));
}

/* Talk is mic-free: a soft live wash on the master so “hearing you” is visible. */
.spar-room.is-talk.is-listening .spar-master {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .spar-room.is-talk.is-listening .spar-master {
    animation: spar-listen-breath 2.4s var(--ease, ease) infinite;
  }
}

@keyframes spar-listen-breath {
  0%,
  100% {
    filter: drop-shadow(0 0 6px color-mix(in srgb, var(--brand) 18%, transparent));
    transform: scale(1);
  }
  50% {
    filter: drop-shadow(0 0 14px color-mix(in srgb, var(--brand) 32%, transparent));
    transform: scale(1.03);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spar-room.is-talk.is-listening .spar-master {
    animation: none;
  }
}

@media (pointer: coarse) {
  .spar-mic {
    width: 2.85rem;
    height: 2.85rem;
  }
}

/* Reserved seat: the readout must not push the stage when it arrives */
.spar-readout {
  margin: 0;
  min-height: 1.2rem;
  max-width: min(22rem, 100%);
  padding: 0 0.75rem;
  box-sizing: border-box;
  /* Secondary was too soft on the light stage — English seat must stay readable. */
  color: color-mix(in srgb, var(--ink) 72%, var(--text-secondary));
  font-size: 0.88rem;
  font-weight: 550;
  letter-spacing: -0.01em;
  line-height: 1.35;
  text-align: center;
  opacity: 1;
  /* Full sentence — wrap, never ellipsis-clip (founder 2026-08-09). */
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/*
 * Reserved seat, not display:none. The Again button appearing at the end grew
 * the stage 266px -> 324px, which is precisely the reflow the stable shell law
 * forbids. It keeps its seat and only its visibility changes.
 */
/* Re-entry. It is the way back into the encounter, so it reads like the room:
   the same uppercase, letterspaced idiom as LEAVE, weighted as the action. */
.spar-again {
  visibility: visible;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Nothing held yet: the way out doubles as the message. Same idiom again. */
.spar-study-first {
  display: none;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  cursor: pointer;
  padding: 0.5rem 0.4rem;
  -webkit-tap-highlight-color: transparent;
}

.spar-study-first:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
  border-radius: 0.4rem;
}

/* Blocked is an entry state, not a mid-round transition, so the empty seats
   collapse rather than holding a shape nothing will fill. The stable shell law
   protects state CHANGES within a round; there is no round here. */
.spar-room.is-blocked .spar-line,
.spar-room.is-blocked .spar-form,
.spar-room.is-blocked .spar-miss,
.spar-room.is-blocked .spar-readout,
.spar-room.is-blocked .spar-again {
  display: none;
}

.spar-room.is-blocked .spar-study-first {
  display: inline-block;
}

.spar-again.is-idle {
  visibility: hidden;
  pointer-events: none;
}

/* ===========================================================================
 * Talk — the room's default mode (2026-08-03)
 * ===========================================================================
 * Walk a Story scene with the other side spoken. Quieter than the drill by
 * design: nothing here is a score, so nothing here is loud. The drill's own
 * furniture (Again, the diagnosis re-entry) has no job in a mode that cannot
 * end early, so it is hidden rather than left sitting idle.
 */

.spar-room.is-choosing .spar-stage {
  display: none;
}

.talk-chooser {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.15rem;
  padding: 0.4rem 1rem 2rem;
  text-align: center;
}

.talk-chooser[hidden] {
  display: none;
}

/* Chooser: English is seat help only (hidden via JS when is-choosing). */
.spar-room.is-choosing .speak-english-toggle {
  display: none;
}

.talk-chooser__line {
  margin: 0;
  min-height: 0;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text-secondary);
}

/* Silence when the marks carry the chooser (no restated "Choose a level"). */
.talk-chooser__line:empty {
  display: none;
}

/* One calm row. Wraps to two on the narrowest phones rather than shrinking
   the targets below the 2.75rem floor. */
.talk-levels {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: 0.5rem;
}

.talk-level {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 4.25rem;
  min-width: 4.6rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--hairline, rgba(20, 30, 50, 0.14));
  border-radius: var(--radius-sm, 0.6rem);
  background: var(--surface, rgba(255, 255, 255, 0.72));
  font-family: inherit;
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.18s var(--ease), transform 0.18s var(--ease);
}

.talk-level__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 1.15rem;
}

.talk-level__label {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}

/* The level you last walked, so "another one of those" is one tap. */
.talk-level.is-active {
  border-color: var(--brand, #3f6fd8);
  color: var(--brand-deep, #24447f);
}

.talk-level:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .talk-level:hover {
    border-color: var(--brand, #3f6fd8);
    transform: translateY(-1px);
  }
}

/* The old five-frame Spar, kept and demoted. Quiet on purpose: it is the
   option, not the room. */
.talk-drill {
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  cursor: pointer;
  padding: 0.5rem 0.6rem;
  min-height: 2.75rem;
  -webkit-tap-highlight-color: transparent;
}

.talk-drill:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
  border-radius: 0.4rem;
}

@media (hover: hover) and (pointer: fine) {
  .talk-drill:hover {
    color: var(--brand-deep);
  }
}

/*
 * Scene place-title — quiet place chip under the chrome
 * (founder 2026-08-09 · aesthetics pass). Soft glass pill, not bare grey text.
 * Sits away from the learning stack; readable without competing with L2.
 */
.talk-scene {
  flex: 0 0 auto;
  align-self: center;
  box-sizing: border-box;
  margin: 0.1rem auto 0.55rem;
  max-width: min(18rem, calc(100% - 2rem));
  padding: 0.38rem 1rem;
  min-height: 1.85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--brand) 14%, transparent);
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, #fff 92%, var(--brand-soft)) 0%,
      color-mix(in srgb, #fff 78%, var(--brand-soft)) 100%
    );
  box-shadow:
    0 1px 0 color-mix(in srgb, #fff 80%, transparent) inset,
    var(--shadow-sm);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
  text-align: center;
  color: color-mix(in srgb, var(--brand-deep) 72%, var(--ink));
  -webkit-font-smoothing: antialiased;
}

.talk-scene[hidden] {
  display: none;
}

body.spar-open .spar-room.is-keyboard-open .talk-scene {
  margin-bottom: 0.25rem;
  padding: 0.28rem 0.85rem;
  min-height: 1.55rem;
  font-size: 0.72rem;
}

/*
 * The line you were reaching for. A model, never a mark — so it does not take
 * the miss colour and does not shake the room. Reserved seat like every other
 * band in here.
 */
.talk-model {
  margin: 0;
  min-height: 1.3rem;
  font-size: 0.88rem;
  line-height: 1.3rem;
  text-align: center;
  color: var(--text-tertiary);
  opacity: 0;
  transition: opacity 0.22s var(--ease);
}

.talk-model.is-shown {
  opacity: 1;
  color: var(--text-secondary);
}

/* Soft-miss teach beat: L2 (spar-line) + English (spar-readout) as a pair. */
/*
 * The teach beat is not the conversation continuing.
 *
 * At a soft miss the stage line stops carrying THEIR words and starts carrying
 * the line YOU were reaching for — same element, same type, same seat. Nothing
 * on screen said the speaker had changed, which is the confusion the founder
 * already hit once from the other direction ("the prompts for what I'm supposed
 * to say don't seem to align with what I should say").
 *
 * The signal is a soft wash behind the pair rather than a label: he asked for
 * fewer words on this screen, not more, and a caption would be one more thing
 * to read at exactly the moment he is reading two sentences already.
 *
 * Background only — no border, no padding, no size change — so the stable shell
 * law holds and nothing reflows when the beat starts or ends.
 */
.spar-room.is-teaching .spar-stage {
  background: color-mix(in srgb, var(--brand, #4f6ef7) 6%, transparent);
  border-radius: 18px;
  transition: background 220ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .spar-room.is-teaching .spar-stage {
    transition: none;
  }
}

.spar-room.is-teaching .spar-line {
  color: var(--ink);
}

.spar-room.is-teaching .spar-readout {
  color: color-mix(in srgb, var(--ink) 68%, var(--text-secondary));
  font-size: 0.95rem;
  font-weight: 550;
}

/* Model seat always reserves height (opacity hide) — never display:none in Talk. */
.spar-room.is-talk .talk-model {
  visibility: visible;
}

/* Mode furniture: each mode hides what belongs to the other. */
.spar-room.is-talk .spar-again,
.spar-room.is-talk .spar-miss,
.spar-room.is-talk .spar-study-first {
  display: none;
}

.spar-room.is-drill .talk-scene,
.spar-room.is-drill .talk-model {
  display: none;
}

@media (max-width: 359px) {
  .talk-level {
    min-width: 4.1rem;
    padding: 0.55rem 0.5rem;
  }

  .talk-levels {
    gap: 0.4rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .talk-level,
  .talk-model {
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .spar-master {
    transition: none;
  }
}

/*
 * Talk entry on Path — head chip inside Foundation (go B 2026-08-05).
 *
 * History: own card above gauge → footer under hairline (2026-08-02) → compact
 * chip after the % (2026-08-05). Path is orientation; Talk is an elected room,
 * not the page hero. Status (% ) stays primary; door is quiet beside it.
 *
 * Stable shell: fixed min seat on the mark so is-called paint does not reflow.
 * Legacy label/line/note ids stay for renderSparEntry hooks (visually hidden).
 */
.foundation-spar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
  color: var(--text-secondary);
  -webkit-tap-highlight-color: transparent;
  border-radius: 999px;
}

/* Hidden: spans stay for stable ids / a11y hooks. */
.foundation-spar__text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.foundation-spar__note:empty {
  display: none;
}

.foundation-spar__label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--brand);
}

.foundation-spar__line {
  font-size: 0.8rem;
  line-height: 0;
  min-height: 0;
  height: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  color: var(--text-tertiary);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/*
 * Compact Talk chip (go B iterate 2026-08-05 · build 825).
 * Quiet outline by default so Path stays orientation-first; filled gradient
 * only when is-called (earned invitation finally paints). Always open.
 */
.foundation-spar__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 3.55rem;
  min-height: 1.75rem;
  padding: 0.26rem 0.72rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--brand) 26%, transparent);
  background: color-mix(in srgb, var(--brand) 7%, #fff);
  color: var(--brand-deep);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
  box-shadow: none;
  box-sizing: border-box;
}

/* Called: same seat, brand fill (waypoint earned). */
.foundation-spar.is-called {
  color: var(--brand-deep);
}

.foundation-spar.is-called .foundation-spar__mark {
  border-color: transparent;
  background: var(--brand-gradient);
  color: #fff;
  min-width: 3.55rem;
  box-shadow: var(--shadow-brand);
}

.foundation-spar__note {
  display: none;
  margin: 0;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* Cursor-only hover paint, per platform law. */
@media (hover: hover) and (pointer: fine) {
  .foundation-spar:hover .foundation-spar__mark {
    border-color: color-mix(in srgb, var(--brand) 38%, transparent);
    background: color-mix(in srgb, var(--brand) 12%, #fff);
  }
  .foundation-spar.is-called:hover .foundation-spar__mark {
    filter: brightness(1.05);
  }
}

.foundation-spar:active {
  transform: translateY(1px);
}

.foundation-spar:active .foundation-spar__mark {
  transform: scale(0.98);
}

.foundation-spar:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

/* A waypoint the learner has already passed reads as reached, not pending. */
.foundation-gauge-mark.is-passed {
  background: color-mix(in srgb, #fff 78%, transparent);
}


/* ===========================================================================
 * Pause · countdown · the mic invitation  (Speak room, 2026-08-09)
 * ======================================================================== */

/*
 * Speak English toggle (founder 2026-08-10 · Stories shape, Speak default on).
 * Quiet chrome beside Speak|Type; pressed/on = English of the seat is shown.
 */
.speak-english-toggle {
  appearance: none;
  border: 1px solid color-mix(in srgb, var(--border-strong) 65%, transparent);
  background: transparent;
  padding: 0.28rem 0.62rem;
  margin: 0;
  min-height: 2.15rem;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
  color: var(--text-tertiary);
  cursor: pointer;
  border-radius: 999px;
  line-height: 1;
  opacity: 0.92;
  -webkit-tap-highlight-color: transparent;
  flex: 0 0 auto;
}

.speak-english-toggle.is-on,
.speak-english-toggle[aria-pressed="true"] {
  color: var(--brand-deep);
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
  background: var(--brand-soft);
  font-weight: 650;
  opacity: 1;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 12%, transparent);
}

.speak-english-toggle:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .speak-english-toggle:hover:not(.is-on) {
    color: var(--text-secondary);
    border-color: var(--border-strong);
    background: var(--surface-glass);
  }
}

@media (max-width: 380px) {
  body.spar-open .speak-english-toggle {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
    font-size: 0.66rem;
    min-height: 2rem;
  }
}

/*
 * Pause sits beside Leave and reads the same way: quiet until you need it.
 * Leave ends the session; Pause holds it, so a distraction does not cost the
 * scene. Founder: "sometimes you just want to pause because of a distraction,
 * or there's something you need to think about."
 *
 * Stable width (founder 2026-08-10): PAUSE → RESUME is longer. Without a seat
 * reserved for the longer word, the top cluster reflows and LEAVE clips off
 * the phone edge. min-width fits RESUME; label stays centered for both states.
 */
.spar-pause {
  appearance: none;
  border: 0;
  background: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0.35rem;
  margin-right: 0.15rem;
  min-width: 5.35rem;
  min-height: 2.15rem;
  flex: 0 0 auto;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  color: var(--text-tertiary);
  cursor: pointer;
  border-radius: 999px;
  -webkit-tap-highlight-color: transparent;
}

.spar-pause:focus-visible {
  outline: 2px solid var(--brand, #4f6ef7);
  outline-offset: 2px;
}

/* Cursor-only hover paint law: a touch device must never get a stuck hover. */
@media (hover: hover) and (pointer: fine) {
  .spar-pause:hover {
    color: var(--text-secondary);
  }
}

/*
 * Held. The room is still there — a quiet pause, not fog.
 * 0.35 made L2 + English unreadable (founder screenshots, Type and Voice,
 * both while RESUME was showing). Soft hold only.
 */
.spar-room.is-paused .spar-line {
  opacity: 0.82;
}

.spar-room.is-paused .spar-readout {
  opacity: 0.78;
}

.spar-room.is-paused .spar-master {
  opacity: 0.72;
}

/*
 * The countdown seat: a readiness beat BEFORE the scene opens, never during a
 * turn. The "no clock is ever drawn" seal still governs the answer window —
 * once the conversation is running there is no timer anywhere.
 */
.spar-count {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--text-tertiary);
}

/*
 * 844 is-inviting pulse removed (2026-08-09 · voice-first).
 * Room opens listening when Voice is on; a "press me" breath is wrong then.
 */

/*
 * Voice | Type segment — both labels always visible so it reads as a switch
 * (founder 2026-08-09), not a single mode word.
 */
.speak-mode-toggle {
  display: inline-flex;
  align-items: stretch;
  flex: 0 0 auto;
  padding: 0.18rem;
  gap: 0.1rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--brand) 18%, transparent);
  background: color-mix(in srgb, #fff 88%, var(--brand-soft));
  box-shadow: var(--shadow-sm);
  -webkit-tap-highlight-color: transparent;
}

.speak-mode-toggle[hidden] {
  display: none;
}

.speak-mode-toggle__opt {
  border: 0;
  margin: 0;
  min-height: 2.15rem;
  min-width: 3.4rem;
  padding: 0.28rem 0.72rem;
  border-radius: 999px;
  background: transparent;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  cursor: pointer;
  line-height: 1;
}

.speak-mode-toggle__opt.is-active {
  background: var(--brand-gradient);
  color: #fff;
  box-shadow: var(--shadow-brand);
}

@media (hover: hover) and (pointer: fine) {
  .speak-mode-toggle__opt:hover:not(.is-active) {
    color: var(--brand-deep);
    background: color-mix(in srgb, var(--brand) 8%, transparent);
  }
}

.speak-mode-toggle__opt:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 1px;
}

.speak-mic-wait {
  margin: 0.35rem 0 0;
  min-height: 1.15rem;
  padding: 0 1rem;
  text-align: center;
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-secondary);
  letter-spacing: -0.01em;
}

/*
 * Type-mode special letters (founder 2026-08-09).
 * Shown only when Type is selected and the answer seat is open.
 */
.speak-type-keys {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  max-width: 22rem;
  margin: 0.55rem auto 0;
  padding: 0 0.15rem;
  box-sizing: border-box;
}

/* Force uppercase onto a second row (lower first, then upper). */
.speak-type-keys__break {
  flex-basis: 100%;
  width: 100%;
  height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
}

.speak-type-keys[hidden] {
  display: none;
}

.speak-type-keys__key {
  flex: 0 0 auto;
  min-width: 2.55rem;
  min-height: 2.55rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid color-mix(in srgb, var(--brand) 20%, transparent);
  border-radius: 0.7rem;
  background: #fff;
  color: var(--ink);
  font-family: inherit;
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) and (pointer: fine) {
  .speak-type-keys__key:hover {
    border-color: color-mix(in srgb, var(--brand) 38%, transparent);
    background: color-mix(in srgb, var(--brand) 6%, #fff);
  }
}

.speak-type-keys__key:active {
  transform: translateY(1px);
}

.speak-type-keys__key:focus-visible {
  outline: 2px solid var(--brand-ring);
  outline-offset: 2px;
}

@media (pointer: coarse) {
  .speak-type-keys__key {
    min-width: 2.75rem;
    min-height: 2.75rem;
  }
}

.speak-mic-wait[hidden] {
  display: none;
}

.spar-room.is-permission-wait .speak-mic-wait {
  color: var(--brand-deep);
}
