@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400..700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&family=Source+Sans+3:wght@400;500;600;700&display=swap');

/* ==========================================================
   Theme tokens — light (default) and dark ("focus mode")
   ========================================================== */
:root {
  --bg: #F4F7FC;
  --surface: #FFFFFF;
  --surface-sunken: #E7EFFA;
  --ink: #16212F;
  --ink-soft: #47586D;
  --muted: #7C8CA1;
  --border: #DCE6F2;

  --accent: #2F63D6;
  --accent-ink: #1F49AC;
  --accent-soft: #DCE7FB;

  --accent2: #12798A;
  --accent2-ink: #0B5A67;
  --accent2-soft: #DCF0F1;

  --warn: #A6791E;
  --warn-soft: #F6EDD6;
  --danger: #B03F3F;
  --danger-soft: #F8E4E4;
  --good: #3F7D53;
  --good-soft: #E4F1E7;

  --header-bg: #101B2E;
  --header-fg: #EAF1FB;
  --header-fg-soft: #A9BEDA;
  --header-timer-warn: #DCB05F;
  --header-timer-danger: #E29494;

  --shadow-card: 0 1px 2px rgba(16, 27, 46, 0.05), 0 4px 14px rgba(16, 27, 46, 0.07);
  --shadow-composite: 0 10px 26px rgba(31, 73, 172, 0.28);
  --shadow-composite2: 0 10px 26px rgba(11, 90, 103, 0.25);

  /* Ethereal/glass motif — a soft gradient wash behind the page, and
     translucent-blur variants of "surface" and the sidebar used across the
     dashboard. Kept separate from --header-bg/--header-fg (unchanged, still
     dark navy) -- turns out the real digital SAT's in-exam chrome is light,
     not dark (confirmed from reference screenshots), so .exam-header/
     .exam-toolbar/.exam-tool-btn were moved onto --surface/--ink instead;
     --header-bg/--header-fg now only back the deliberately-dark floating
     bits (the highlight/note selection popup, the footer's black
     "Question N of M" pill) that should stay dark against the light bar. */
  --bg-gradient:
    radial-gradient(1100px 760px at 88% -8%, rgba(47, 99, 214, 0.10), transparent 60%),
    radial-gradient(900px 680px at -8% 108%, rgba(18, 121, 138, 0.08), transparent 55%),
    linear-gradient(160deg, #F8FAFF 0%, #EFF3FC 45%, #F3EFFA 100%);

  --glass-surface-1: rgba(255, 255, 255, 0.86);
  --glass-surface-2: rgba(255, 255, 255, 0.56);
  --glass-border: rgba(255, 255, 255, 0.75);
  --glass-shadow: 0 1px 2px rgba(16, 27, 46, 0.04), 0 10px 28px rgba(16, 27, 46, 0.07);
  --glass-shadow-hover: 0 4px 4px rgba(16, 27, 46, 0.03), 0 16px 34px rgba(16, 27, 46, 0.09);

  --sidebar-glass-1: rgba(255, 255, 255, 0.85);
  --sidebar-glass-2: rgba(255, 255, 255, 0.55);
  --sidebar-border: rgba(255, 255, 255, 0.7);
  --sidebar-hairline: rgba(16, 27, 46, 0.07);
  --sidebar-hover-bg: rgba(255, 255, 255, 0.6);
  --sidebar-shadow: 10px 0 32px rgba(16, 27, 46, 0.05);
  --sidebar-active-bg: linear-gradient(135deg, rgba(47, 99, 214, 0.16), rgba(47, 99, 214, 0.05));
  --sidebar-active-border: rgba(47, 99, 214, 0.16);
  --sidebar-active-shadow: 0 2px 10px rgba(47, 99, 214, 0.14);

  --radius: 16px;
  --radius-lg: 18px;
  --radius-md: 13px;
  --radius-sm: 9px;

  --font-display: 'Fraunces', serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  /* The official SAT uses Minion Pro (serif) / Myriad Pro (sans) -- both
     commercial Adobe fonts we can't license or embed. Source Serif 4 /
     Source Sans 3 are Adobe's own free, open-source counterparts explicitly
     designed in that same tradition (Source Sans as a Myriad-inspired UI
     face, Source Serif as its Minion-like reading partner), so they're the
     closest available match rather than an arbitrary substitute. Scoped to
     the exam chrome only (see .exam-* rules below) -- the rest of the app
     keeps Fraunces/Inter. */
  --font-exam-serif: 'Source Serif 4', Georgia, serif;
  --font-exam-sans: 'Source Sans 3', 'Inter', sans-serif;

  --ease-standard: cubic-bezier(.4, 0, .2, 1);

  /* Page-enter sheen (see .page-enter::after below) — a bright white streak
     reads as light catching glass on a pale background, but the same white
     streak on a dark background just looks like a stray flash. Dark theme
     swaps it for a dark streak instead, so it still reads as glass, not a
     mistake. */
  --page-sheen-gradient: linear-gradient(100deg,
    transparent 35%,
    rgba(255, 255, 255, 0.55) 47%,
    rgba(255, 255, 255, 0.85) 50%,
    rgba(255, 255, 255, 0.55) 53%,
    transparent 65%);
}

html[data-theme='dark'] {
  --bg: #18151C;
  --surface: #221F27;
  --surface-sunken: #29252F;
  --ink: #EAE7EE;
  --ink-soft: #B7B0C0;
  --muted: #86818E;
  --border: #322E3A;

  --accent: #9186BE;
  --accent-ink: #7A6CA8;
  --accent-soft: #2E2838;

  --accent2: #4C7E85;
  --accent2-ink: #3D666C;
  --accent2-soft: #1A2B2C;

  --warn: #C2A473;
  --warn-soft: #322A1E;
  --danger: #BE8B8B;
  --danger-soft: #332628;
  --good: #7A9C82;
  --good-soft: #212821;

  --header-bg: #100E13;
  --header-fg: #EAE7EE;
  --header-fg-soft: #96909D;
  --header-timer-warn: #C2A473;
  --header-timer-danger: #BE8B8B;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.35);
  --shadow-composite: 0 12px 30px rgba(122, 108, 168, 0.24);
  --shadow-composite2: 0 12px 30px rgba(61, 102, 108, 0.22);

  /* Dark, not light — a bright white sheen sweeping over dark surfaces
     reads as a stray flash rather than glass catching light. */
  --page-sheen-gradient: linear-gradient(100deg,
    transparent 35%,
    rgba(0, 0, 0, 0.45) 47%,
    rgba(0, 0, 0, 0.65) 50%,
    rgba(0, 0, 0, 0.45) 53%,
    transparent 65%);

  /* Same glass motif, dark-toned — a dark theme should stay dark, not turn
     pale, so this frosts the existing dark surfaces instead of lightening
     them. */
  --bg-gradient:
    radial-gradient(1100px 760px at 88% -8%, rgba(145, 134, 190, 0.10), transparent 60%),
    radial-gradient(900px 680px at -8% 108%, rgba(76, 126, 133, 0.09), transparent 55%),
    linear-gradient(160deg, #18151C 0%, #1B1820 45%, #1A1721 100%);

  --glass-surface-1: rgba(41, 37, 47, 0.82);
  --glass-surface-2: rgba(24, 21, 28, 0.62);
  --glass-border: rgba(255, 255, 255, 0.07);
  --glass-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 28px rgba(0, 0, 0, 0.32);
  --glass-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.28), 0 18px 36px rgba(0, 0, 0, 0.36);

  --sidebar-glass-1: rgba(34, 31, 39, 0.88);
  --sidebar-glass-2: rgba(24, 21, 28, 0.7);
  --sidebar-border: rgba(255, 255, 255, 0.06);
  --sidebar-hairline: rgba(255, 255, 255, 0.07);
  --sidebar-hover-bg: rgba(255, 255, 255, 0.06);
  --sidebar-shadow: 10px 0 32px rgba(0, 0, 0, 0.35);
  --sidebar-active-bg: linear-gradient(135deg, rgba(145, 134, 190, 0.30), rgba(145, 134, 190, 0.08));
  --sidebar-active-border: rgba(145, 134, 190, 0.30);
  --sidebar-active-shadow: 0 2px 10px rgba(145, 134, 190, 0.22);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg-gradient);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  transition: color 0.15s ease;
}

#app {
  display: flex;
  align-items: stretch;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

a { color: var(--accent); }
a:hover { color: var(--accent-ink); }

/* ---------- Sidebar ---------- */
.sidebar-root { display: contents; }

.sidebar {
  width: 232px;
  flex-shrink: 0;
  height: 100%;
  background: linear-gradient(180deg, var(--sidebar-glass-1), var(--sidebar-glass-2));
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  border-right: 1px solid var(--sidebar-border);
  box-shadow: var(--sidebar-shadow);
  color: var(--ink-soft);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: width 0.22s var(--ease-standard), transform 0.22s var(--ease-standard);
}

.sidebar.collapsed { width: 64px; }

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 14px 17px 18px;
  border-bottom: 1px solid var(--sidebar-hairline);
  flex-shrink: 0;
  white-space: nowrap;
  overflow: hidden;
}

.sidebar.collapsed .sidebar-brand { padding: 20px 0; justify-content: center; }

/* Collapsed only: the whole brand row is the expand button. */
.sidebar-brand-collapsed {
  appearance: none;
  border: none;
  background: none;
  width: 100%;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 0.16s var(--ease-standard);
}
.sidebar-brand-collapsed:hover { background: var(--sidebar-hover-bg); }

.brand-icon { display: flex; flex-shrink: 0; }
/* Picks which of brandIcon()'s two duotone filters tints the logo image --
   see the big comment above that function in app.js for why this can't
   just be one filter with CSS-var stops. */
.brand-icon-tint { filter: url(#bi-duo-light); }
html[data-theme='dark'] .brand-icon-tint { filter: url(#bi-duo-dark); }

/* Same duotone-tinted logo mark as the sidebar (see renderLogoMarkSvg in
   app.js), just a second instance at hero size on the signed-out Home
   page -- its own id prefix/class since SVG filter ids must be unique
   page-wide and both instances are ever on screen at once. */
.home-hero-logo-tint { filter: url(#home-hero-duo-light); }
html[data-theme='dark'] .home-hero-logo-tint { filter: url(#home-hero-duo-dark); }

.brand-text { display: flex; flex-direction: column; gap: 1px; overflow: hidden; flex: 1; min-width: 0; }

/* Expanded only: small collapse arrow next to the wordmark. */
.brand-collapse-btn {
  appearance: none;
  border: none;
  background: none;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.16s var(--ease-standard), color 0.16s var(--ease-standard);
}
.brand-collapse-btn:hover { background: var(--sidebar-hover-bg); color: var(--accent-ink); }

.brand-mark {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.brand-mark span { color: var(--accent); }

.brand-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.sidebar-nav {
  position: relative; /* containing block for .nav-indicator */
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

/* The sliding highlight behind the active nav item — see syncNavIndicator()
   in app.js, which plays a Web Animations API .animate() call to make it
   slide (this element is brand new on every render(), so a plain CSS
   transition has no previously-painted frame to detect a change against).
   Absolutely positioned so it doesn't take up flex space of its own;
   inserted before the nav-item buttons in the DOM so their icon/label
   paint on top of it with no z-index needed. left/right match .nav-item's
   own full-width sizing — only top/height are set from JS, since those are
   the only two that differ per item. */
.nav-indicator {
  position: absolute;
  left: 10px;
  right: 10px;
  border-radius: var(--radius-sm);
  background: var(--sidebar-active-bg);
  border: 1px solid var(--sidebar-active-border);
  box-shadow: var(--sidebar-active-shadow);
  pointer-events: none;
}

/* .nav-item / .account-row are both <button>s (so keyboard/screen-reader
   users can reach them, unlike a plain onclick-div) — reset the UA button
   chrome once, shared. */
.nav-item, .account-row {
  appearance: none;
  border: none;
  background: none;
  margin: 0;
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: background 0.18s var(--ease-standard), color 0.18s var(--ease-standard),
    border-color 0.18s var(--ease-standard), transform 0.18s var(--ease-standard),
    box-shadow 0.22s var(--ease-standard);
}

.nav-item:hover { background: var(--sidebar-hover-bg); color: var(--ink); transform: translateX(2px); }
.nav-item:active { transform: translateX(2px) scale(0.97); }
/* Background/border/shadow for the active state now live on the sliding
   .nav-indicator behind it instead of here — only the text/icon color
   still switches directly on the button itself. */
.nav-item.active { color: var(--accent-ink); }

.nav-icon { display: flex; flex-shrink: 0; width: 20px; height: 20px; align-items: center; justify-content: center; }
.nav-label { overflow: hidden; text-overflow: ellipsis; }

.sidebar.collapsed .nav-item { justify-content: center; padding: 11px; }
.sidebar.collapsed .nav-item:hover { transform: none; }
.sidebar.collapsed .nav-label { display: none; }

/* Non-interactive section headers (Practise / Track) between otherwise-flat
   nav items -- see the `{ group: true, label }` markers in renderSidebar()'s
   navDefs. Hidden entirely when collapsed: a 64px icon-only rail doesn't
   have room for section dividers, and the icons alone are close enough
   together that losing the grouping there isn't a real loss. */
.sidebar-nav-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 14px 12px 4px;
  white-space: nowrap;
}
.sidebar.collapsed .sidebar-nav-label { display: none; }

.sidebar-bottom {
  flex-shrink: 0;
  padding: 10px;
  border-top: 1px solid var(--sidebar-hairline);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.account-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.18s var(--ease-standard);
  white-space: nowrap;
  overflow: hidden;
}
.account-row:hover { background: var(--sidebar-hover-bg); }
.sidebar.collapsed .account-row { justify-content: center; padding: 8px; }

.account-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  color: #fff;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(47, 99, 214, 0.28);
}

.account-info { display: flex; flex-direction: column; gap: 0; overflow: hidden; flex: 1; min-width: 0; }
.sidebar.collapsed .account-info { display: none; }
.account-name { font-size: 13px; font-weight: 600; color: var(--ink); }

.account-chevron { display: flex; flex-shrink: 0; color: var(--muted); transition: transform 0.22s var(--ease-standard); }
.account-chevron.open { transform: rotate(180deg); }
.sidebar.collapsed .account-chevron { display: none; }

/* ---------- Account popup (avatar click: account/billing/theme/sign out) ---------- */
/* position:fixed rather than anchored inside .sidebar -- the sidebar has
   overflow:hidden (for the rail-collapse/scroll clipping), which would
   clip an absolutely-positioned popup regardless of collapsed/mobile
   state. The account row is always flush against the bottom of a
   full-height sidebar, so a fixed bottom offset holds up in every state. */
.account-popup-scrim {
  position: fixed;
  inset: 0;
  background: transparent;
  z-index: 47;
}
@keyframes popup-pop-in {
  0% { opacity: 0; transform: scale(0.94) translateY(4px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}
.account-popup {
  position: fixed;
  left: 12px;
  bottom: 72px;
  width: 224px;
  z-index: 48;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  transform-origin: bottom left;
  animation: popup-pop-in 160ms cubic-bezier(.22, 1, .36, 1) both;
}
.account-popup-item {
  appearance: none;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  transition: background 0.12s, color 0.12s;
}
.account-popup-item:hover { background: var(--surface-sunken); color: var(--ink); }
.account-popup-item.danger { color: var(--danger); }
.account-popup-item.danger:hover { background: var(--danger-soft); color: var(--danger); }
.account-popup-divider { height: 1px; background: var(--border); margin: 5px 4px; }
.account-popup-theme-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 4px 10px 6px;
}
.theme-segmented {
  position: relative; /* containing block for .theme-indicator */
  display: flex;
  gap: 3px;
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 3px;
  margin: 0 4px 2px;
}
/* The sliding highlight behind the active theme segment (light/dark/auto)
   -- same FLIP approach as .nav-indicator (see syncThemeIndicator() in
   app.js): the account popup is rebuilt from scratch on every render(), so
   a plain CSS transition has no previously-painted frame to detect a
   change against; a WAAPI .animate() call drives the slide instead.
   Inserted before the segment buttons so their icon/label paint on top of
   it with no z-index needed. left/width are set from JS since those are
   the only two that differ per segment. */
.theme-indicator {
  position: absolute;
  top: 3px;
  bottom: 3px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-card);
  pointer-events: none;
}
.theme-segment {
  position: relative; /* stack above .theme-indicator */
  appearance: none;
  border: none;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 4px 6px;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.12s;
}
.theme-segment:hover { color: var(--ink-soft); }
/* Background/shadow for the active state now live on the sliding
   .theme-indicator behind it instead of here -- only the text color still
   switches directly on the button itself. */
.theme-segment.active { color: var(--ink); }

.mobile-menu-btn {
  display: none;
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 45;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  color: var(--ink-soft);
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--glass-shadow);
  transition: border-color 0.16s var(--ease-standard), color 0.16s var(--ease-standard), box-shadow 0.2s var(--ease-standard);
}
.mobile-menu-btn:hover { border-color: var(--accent); color: var(--accent); box-shadow: var(--glass-shadow-hover); }

/* Only ever in the DOM while state.mobileNavOpen is true (see
   renderSidebar) — same conditional-render pattern the old nav-scrim
   used, so no CSS visibility toggling is needed here. */
.sidebar-scrim {
  position: fixed;
  inset: 0;
  background: rgba(16, 27, 46, 0.35);
  z-index: 44;
}

@media (max-width: 900px) {
  /* renderSidebar() forces collapsed=false whenever this breakpoint is
     active, so the rail-collapse CSS (.sidebar.collapsed, .brand-text
     etc. display:none) never even applies here — just position it as an
     off-canvas drawer. */
  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 236px;
    transform: translateX(-100%);
    z-index: 46;
  }
  .sidebar.mobile-open { transform: translateX(0); }
  .mobile-menu-btn { display: flex; }
  .main-content-inner { padding-top: 64px; }
}

/* ---------- Main content ---------- */
.main-content {
  flex: 1;
  min-width: 0;
  height: 100%;
  overflow-y: auto;
}

.main-content-inner {
  width: 100%;
  padding: 28px 40px 90px;
}

@media (max-width: 640px) {
  .main-content-inner { padding-left: 18px; padding-right: 18px; padding-bottom: 70px; }
}

/* ---------- Page-change transition ("liquid glass" sheen) ----------
   Applied only when navigating between actual screens outside a live test
   (see render()'s pageTransition flag) — a quick settle-in plus a soft
   diagonal light sweep, like the page catching a ray of light as it slides
   into place. Never applied during renderTesting(), the real exam screen,
   by design. .page-enter-clip briefly clips the sheen to the container so
   it doesn't bleed past rounded corners of cards near the edge; removed
   right after the animation finishes (see the animationend listener in
   render()) so it never fights a popover that opens a moment later. */
@keyframes page-enter-settle {
  0% { opacity: 0; transform: translateY(8px) scale(0.985); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes page-enter-sheen {
  0% { transform: translateX(-60%) skewX(-14deg); opacity: 0; }
  12% { opacity: 0.5; }
  55% { opacity: 0.22; }
  100% { transform: translateX(160%) skewX(-14deg); opacity: 0; }
}
.page-enter {
  animation: page-enter-settle 360ms cubic-bezier(.22, 1, .36, 1) both;
  position: relative;
}
.page-enter-clip { overflow: hidden; }
.page-enter::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--page-sheen-gradient);
  mix-blend-mode: overlay;
  pointer-events: none;
  animation: page-enter-sheen 620ms cubic-bezier(.4, 0, .2, 1) both;
}

/* ---------- Theme-switch transition (sunset / sunrise wash) ----------
   Toggling light<->dark used to just snap instantly. This plays a band of
   color that physically travels down the screen for light->dark ("sunset")
   or up the screen for dark->light ("sunrise") instead -- not a flat
   overlay that fades in and out in place. The band is much taller than the
   viewport (160vh) with the actual color concentrated in its middle and
   transparent ends, translated well past both edges of the viewport
   (-160vh to 100vh, or reversed) so it enters from fully offscreen, sweeps
   fully across, and exits fully offscreen the other side. Because it's a
   single rigid band moving one direction, whichever edge it reaches FIRST
   is also the edge it clears FIRST -- sweeping down means the top of the
   screen darkens first and the reveal of the new theme also starts from
   the top, spreading down, like dusk falling from the sky; sweeping up
   means the new theme is revealed from the bottom first, like dawn
   brightening up from the horizon.
   See playThemeTransition()/transitionEffectiveTheme() in app.js: the
   element is created fresh on JS-side and appended directly to
   document.body -- outside the #app tree render() tears down and rebuilds,
   and outside any single screen, since a theme change can happen from
   anywhere. The actual data-theme attribute flips while the band is at
   full coverage, before it starts revealing anything, so the instant color
   swap underneath is masked rather than visible as a seam. z-index sits
   above literally everything else in the app, including the floating
   calculator/reference panels (z-index 70) -- briefly covering them is
   expected. */
.theme-transition-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 160vh;
  z-index: 200;
  pointer-events: none;
}
@keyframes theme-wash-down {
  0% { transform: translateY(-160vh); }
  100% { transform: translateY(100vh); }
}
@keyframes theme-wash-up {
  0% { transform: translateY(100vh); }
  100% { transform: translateY(-160vh); }
}
.theme-transition-overlay.sunset {
  background: linear-gradient(to bottom,
    transparent 0%,
    rgba(255, 178, 102, 0.85) 18%,
    rgba(232, 106, 84, 0.72) 30%,
    rgba(126, 62, 110, 0.6) 42%,
    rgba(45, 30, 66, 0.82) 55%,
    rgba(9, 7, 15, 0.95) 68%,
    rgba(9, 7, 15, 0.95) 78%,
    transparent 100%);
  animation: theme-wash-down 680ms cubic-bezier(.4, 0, .2, 1) both;
}
.theme-transition-overlay.sunrise {
  background: linear-gradient(to bottom,
    transparent 0%,
    rgba(213, 224, 244, 0.7) 18%,
    rgba(173, 160, 210, 0.55) 30%,
    rgba(255, 173, 145, 0.68) 45%,
    rgba(255, 214, 153, 0.85) 58%,
    rgba(255, 244, 224, 0.95) 70%,
    rgba(255, 244, 224, 0.95) 80%,
    transparent 100%);
  animation: theme-wash-up 680ms cubic-bezier(.4, 0, .2, 1) both;
}

/* ---------- Cards / layout ---------- */
.card {
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  padding: 26px;
  margin-bottom: 18px;
}

.card h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  margin: 0 0 5px;
  letter-spacing: -0.01em;
}

.card .sub {
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.55;
  margin: 0 0 18px;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
}

.grid-dash {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 14px;
}

/* auto-fit/minmax, not a fixed 1fr/1.5fr split -- the available width here
   depends on the sidebar (collapsed or not) and the Account sub-nav's own
   200px column, neither of which a plain viewport-width @media query can
   see. A fixed ratio let "Previous test scores" collapse to ~200px in the
   very ordinary 900-1200px window range, wrapping its 4-field score form
   into an unreadable vertical stack instead of the intended 2-per-row.
   Auto-collapsing to one column below 320px per card fixes that at every
   sidebar/viewport combination, not just below one guessed breakpoint. */
.grid-dash.test-info-top { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); align-items: start; }

.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

@media (max-width: 640px) {
  .grid-2 { grid-template-columns: 1fr; }
  .grid-3 { grid-template-columns: 1fr; }
  .grid-dash { grid-template-columns: 1fr; }
  .grid-dash.test-info-top { grid-template-columns: 1fr; }
  .grid-4 { grid-template-columns: 1fr 1fr; }
}

/* ---------- Your-score card (Home) ---------- */
.your-score-card { background: linear-gradient(150deg, color-mix(in srgb, var(--good) 18%, transparent), var(--glass-surface-2) 72%); }
.your-score-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.your-score-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--good);
}
.your-score-goal { text-align: right; }
.your-score-goal-value { font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--ink); }
.your-score-row { display: flex; align-items: flex-end; gap: 32px; flex-wrap: wrap; }
.your-score-stat { display: flex; flex-direction: column; gap: 4px; }
.your-score-value { font-family: var(--font-display); font-weight: 600; font-size: 22px; color: var(--ink); }
.your-score-value.muted { color: var(--muted); font-weight: 500; }
.your-score-stat.primary .your-score-value { font-size: 38px; letter-spacing: -0.02em; }
.your-score-sublabel { font-size: 12.5px; color: var(--muted); }

/* ---------- Weekly activity chart (Home) ---------- */
.weekly-count { font-family: var(--font-display); font-size: 38px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); }
.weekly-chart-numbers { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-top: 14px; }
.weekly-chart-num { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--muted); text-align: center; }
.weekly-chart-num.today { color: var(--ink); }
.weekly-chart { display: grid; grid-template-columns: repeat(7, 1fr); align-items: end; gap: 8px; height: 92px; margin-top: 4px; }
.weekly-bar-col { display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; justify-content: flex-end; }
.weekly-bar { position: relative; width: 20px; border-radius: 5px 5px 2px 2px; background: var(--surface-sunken); overflow: hidden; }
.weekly-bar.today { background: var(--accent-soft); }
.weekly-bar-correct { position: absolute; left: 0; right: 0; bottom: 0; background: var(--good); }
.weekly-day-label { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); text-align: center; }
.weekly-day-label.today { color: var(--ink); font-weight: 700; }
.weekly-legend { display: flex; gap: 16px; margin-top: 14px; font-size: 11.5px; color: var(--muted); }
.weekly-legend-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.weekly-legend-swatch.total { background: var(--surface-sunken); border: 1px solid var(--border); }
.weekly-legend-swatch.correct { background: var(--good); }

/* ---------- Colored stat tiles (Home) ---------- */
.stat-tile-c {
  border-radius: var(--radius);
  padding: 18px 20px;
  position: relative;
  overflow: hidden;
  transition: transform 0.22s var(--ease-standard), box-shadow 0.26s var(--ease-standard);
}
/* A soft corner sheen on top of the tint — the "frosted" highlight a real
   glass surface catches, echoed across every colored tile. */
.stat-tile-c::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 140% at 12% -10%, rgba(255, 255, 255, 0.55), transparent 60%);
  pointer-events: none;
}
.stat-tile-c:hover { transform: translateY(-2px); box-shadow: 0 14px 26px rgba(16, 27, 46, 0.08); }
.stat-tile-c.c-accent { background: var(--accent-soft); }
.stat-tile-c.c-good { background: var(--good-soft); }
.stat-tile-c.c-warn { background: var(--warn-soft); }
.stat-tile-c.c-accent2 { background: var(--accent2-soft); }
/* The icon markup is a raw-HTML span with no layout of its own — as a
   plain inline element it picks up baseline/line-height spacing that
   flexbox centering on the parent alone doesn't fully cancel out, so the
   icon reads as visibly off-center inside its badge. Forcing the span
   (and the svg's own inline default) to block-level flex removes that
   inline-metrics gap entirely. */
.stat-tile-icon { position: relative; width: 34px; height: 34px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; margin-bottom: 12px; background: color-mix(in srgb, var(--surface) 65%, transparent); }
.stat-tile-icon > span { display: flex; align-items: center; justify-content: center; }
.stat-tile-icon svg { display: block; }
.c-accent .stat-tile-icon { color: var(--accent-ink); }
.c-good .stat-tile-icon { color: var(--good); }
.c-warn .stat-tile-icon { color: var(--warn); }
.c-accent2 .stat-tile-icon { color: var(--accent2-ink); }
.stat-tile-c-label { position: relative; font-family: var(--font-body); font-weight: 600; font-size: 13px; color: var(--ink); margin-bottom: 10px; }
.stat-tile-c-value { position: relative; font-family: var(--font-display); font-weight: 600; font-size: 28px; color: var(--ink); letter-spacing: -0.01em; }
.stat-tile-c-sub { position: relative; font-size: 12px; color: var(--ink-soft); margin-top: 4px; }

/* ---------- Progress panel (Home) ---------- */
.progress-row { display: flex; justify-content: space-between; align-items: center; padding: 12px 0; border-top: 1px solid var(--border); }
.progress-row:first-child { border-top: none; padding-top: 0; }
.progress-row-label { font-size: 13.5px; color: var(--ink-soft); font-weight: 600; }
.progress-row-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.progress-row-value { font-family: var(--font-mono); font-size: 15px; font-weight: 700; color: var(--ink); }

/* ---------- My Stats ---------- */
.domain-accuracy-cell { background: var(--surface-sunken); border-radius: var(--radius-md); padding: 14px 16px; }

.heatmap-wrap { overflow-x: auto; }
.heatmap-grid { display: grid; grid-auto-rows: 12px; gap: 3px; margin-bottom: 4px; }
.heatmap-month-label { grid-row: 1; font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.heatmap-cell { width: 11px; height: 11px; border-radius: 2px; background: var(--surface-sunken); }
.heatmap-cell.tier-1 { background: color-mix(in srgb, var(--good) 30%, var(--surface-sunken)); }
.heatmap-cell.tier-2 { background: color-mix(in srgb, var(--good) 55%, var(--surface-sunken)); }
.heatmap-cell.tier-3 { background: color-mix(in srgb, var(--good) 80%, var(--surface-sunken)); }
.heatmap-cell.tier-4 { background: var(--good); }
.heatmap-legend { display: flex; align-items: center; justify-content: flex-end; gap: 5px; margin-top: 8px; font-size: 11px; color: var(--muted); }
.heatmap-legend .heatmap-cell { width: 10px; height: 10px; }

.topic-domain-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); margin: 16px 0 8px; }
.topic-domain-label:first-child { margin-top: 0; }
.topic-pill-row { display: flex; flex-wrap: wrap; gap: 8px; }
.topic-pill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 7px 12px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  background: var(--surface-sunken); color: var(--muted); border: 1px solid transparent;
}
.topic-pill.tier-good { background: var(--good-soft); color: var(--good); }
.topic-pill.tier-mid { background: var(--warn-soft); color: var(--warn); }
.topic-pill.tier-low { background: var(--danger-soft); color: var(--danger); }
.topic-pill-pct { font-family: var(--font-mono); }

.mini-stat-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.mini-stat-cell { display: flex; align-items: flex-start; gap: 10px; }
.mini-stat-icon { display: flex; flex-shrink: 0; width: 28px; height: 28px; border-radius: var(--radius-sm); background: var(--surface-sunken); color: var(--ink-soft); align-items: center; justify-content: center; }
.mini-stat-icon > span { display: flex; align-items: center; justify-content: center; }
.mini-stat-icon svg { display: block; }
.mini-stat-label { font-size: 11.5px; color: var(--muted); margin-bottom: 2px; }
.mini-stat-value { font-family: var(--font-display); font-weight: 600; font-size: 17px; color: var(--ink); }
@media (max-width: 640px) { .mini-stat-grid { grid-template-columns: 1fr 1fr; } }

.mini-toggle {
  appearance: none; border: none; background: none; cursor: pointer;
  padding: 6px 12px; border-radius: 999px; font-size: 12px; font-weight: 600; color: var(--muted);
}
.mini-toggle.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card); }

.activity-bar-chart { display: flex; align-items: end; gap: 3px; height: 90px; }
.activity-bar-col { flex: 1; height: 100%; display: flex; align-items: flex-end; }
.activity-bar { width: 100%; border-radius: 2px 2px 0 0; background: var(--good); min-height: 2px; }

.avgtime-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.avgtime-label { width: 64px; flex-shrink: 0; font-size: 12.5px; color: var(--ink-soft); }
.avgtime-value { width: 34px; flex-shrink: 0; text-align: right; font-family: var(--font-mono); font-size: 12.5px; color: var(--ink); }

/* ---------- Option tiles (mode / section pickers) ---------- */
.option-tile {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 17px;
  cursor: pointer;
  background: var(--surface);
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
}

.option-tile:hover { border-color: var(--accent); }

.option-tile.selected {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent);
}

.option-tile .tile-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15.5px;
  color: var(--ink);
}

.option-tile .tile-desc {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.45;
}

.option-tile.selected .tile-title { color: var(--accent-ink); }

/* Quick Practice's subject tiles: violet border/ring (unchanged) but a teal
   fill on selection, matching the design file's accent2-tinted variant. */
.option-tile.selected.tile-accent2 { background: var(--accent2-soft); }
.option-tile.selected.tile-accent2 .tile-title { color: var(--ink); }

/* ---------- Practice setup: Focus areas domain/skill picker ---------- */
/* `pp-` prefix keeps these scoped to renderPracticeSetup() -- distinct from
   Question Bank's own qbank- picker, which is a plain filter dropdown, not
   this multi-select two-pane component. */
.pp-optional-tag {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted);
}
.pp-summary-pills { display: flex; flex-wrap: wrap; gap: 10px 16px; justify-content: flex-end; }
.pp-summary-pill { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; }
.pp-summary-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.pp-summary-empty { font-size: 12.5px; color: var(--muted); }

.pp-picker {
  display: grid; grid-template-columns: 280px 1fr; gap: 0;
  border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; background: var(--surface);
}
@media (max-width: 640px) {
  /* The fixed 280px domain column doesn't shrink on its own -- below the
     width it needs, the 1fr skill pane gets crushed to a sliver instead.
     Stack the two panes instead of trying to fit them side by side. */
  .pp-picker { grid-template-columns: 1fr; }
  .pp-picker-pane + .pp-picker-pane { border-left: none; border-top: 1px solid var(--border); }
}
.pp-picker-pane { max-height: 380px; overflow-y: auto; padding: 8px; }
.pp-picker-pane + .pp-picker-pane { border-left: 1px solid var(--border); }
.pp-group-label {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); padding: 12px 10px 6px;
}
.pp-group-label:first-child { padding-top: 6px; }

.pp-all-row {
  display: flex; align-items: center; padding: 9px 10px; border-radius: 7px; cursor: pointer;
  font-size: 13.5px; color: var(--ink-soft); transition: background 0.12s var(--ease-standard), color 0.12s var(--ease-standard);
}
.pp-all-row:hover { background: var(--surface-sunken); color: var(--ink); }
.pp-all-row.active { color: var(--accent-ink); font-weight: 600; }

.pp-domain-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px 9px 8px; border-radius: 7px; cursor: pointer;
  transition: background 0.12s var(--ease-standard);
}
.pp-domain-row:hover { background: var(--surface-sunken); }
.pp-domain-bar { width: 3px; align-self: stretch; border-radius: 2px; flex-shrink: 0; }
.pp-domain-name { flex: 1; min-width: 0; font-size: 13.5px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pp-domain-row.engaged { background: var(--pp-tint-soft); }
.pp-domain-row.engaged .pp-domain-name { color: var(--ink); font-weight: 600; }
.pp-domain-count { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; color: var(--muted); flex-shrink: 0; }
.pp-domain-row.engaged .pp-domain-count { color: var(--pp-tint-ink); }

.pp-skill-group-head { display: flex; align-items: center; gap: 7px; padding: 12px 10px 6px; }
.pp-skill-group-head:first-child { padding-top: 6px; }
.pp-skill-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.pp-skill-group-name {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
}
.pp-skill-row { display: flex; align-items: center; gap: 11px; padding: 8px 10px; border-radius: 7px; cursor: pointer; transition: background 0.12s var(--ease-standard); }
.pp-skill-row:hover { background: var(--surface-sunken); }
.pp-skill-box {
  width: 19px; height: 19px; border-radius: 5px; border: 1.5px solid var(--border); background: var(--surface);
  flex-shrink: 0; display: flex; align-items: center; justify-content: center; transition: background 0.12s var(--ease-standard), border-color 0.12s var(--ease-standard);
}
/* Default fill for a checked box -- Question Bank's Skill filter (one
   domain at a time, no per-domain color coding) uses this as-is; Practice's
   picker overrides it per-domain via an inline style, which wins. */
.pp-skill-box.checked { border-color: transparent; background: var(--accent); }
.pp-skill-label { font-size: 13.5px; color: var(--ink); }
.pp-empty { padding: 40px 20px; text-align: center; color: var(--muted); font-size: 13px; }

.pp-difficulty-row { display: flex; gap: 10px; }
.pp-diff-chip {
  display: flex; align-items: center; gap: 8px; padding: 10px 18px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--border); background: var(--surface); font-size: 13.5px; font-weight: 600; color: var(--muted);
  transition: background 0.12s var(--ease-standard), border-color 0.12s var(--ease-standard), color 0.12s var(--ease-standard);
}
.pp-diff-swatch { width: 8px; height: 8px; border-radius: 50%; background: currentColor; opacity: 0.5; }
.pp-diff-chip.on { color: #fff; }
.pp-diff-chip.on .pp-diff-swatch { opacity: 1; background: #fff; }
.pp-diff-chip.easy.on { border-color: var(--good); background: var(--good); }
.pp-diff-chip.medium.on { border-color: var(--accent); background: var(--accent); }
.pp-diff-chip.hard.on { border-color: var(--danger); background: var(--danger); }

/* ---------- Buttons ---------- */
/* Same glass recipe as .dash-panel/.exam-header/etc. (gradient wash +
   backdrop blur + translucent border + --glass-shadow) applied to every
   button variant, so buttons read as part of the same liquid-glass surface
   language as the cards/panels around them instead of looking like flat
   UI-kit buttons dropped on top. Colored variants (.btn-primary and its
   .accent2/.btn-danger siblings) keep their accent hue — color-mixed into
   the glass gradient rather than a flat fill — so they still read clearly
   as the "important" button. */
.btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  border-radius: 999px;
  padding: 11px 22px;
  border: 1px solid transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  transition: background 0.16s var(--ease-standard), border-color 0.16s var(--ease-standard),
    color 0.16s var(--ease-standard), transform 0.16s var(--ease-standard),
    box-shadow 0.2s var(--ease-standard);
}

.btn:hover { transform: translateY(-1px); box-shadow: var(--glass-shadow-hover); }
.btn:active { transform: translateY(0) scale(0.97); box-shadow: var(--glass-shadow); }

.btn-primary {
  background: linear-gradient(155deg, color-mix(in srgb, var(--accent) 85%, white 18%), color-mix(in srgb, var(--accent) 96%, black 8%));
  border-color: color-mix(in srgb, var(--accent) 45%, white 55%);
  color: #F7F7FF;
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.btn-primary:hover { background: linear-gradient(155deg, color-mix(in srgb, var(--accent-ink) 85%, white 14%), color-mix(in srgb, var(--accent-ink) 96%, black 6%)); }
.btn-primary:disabled { background: var(--muted); border-color: transparent; box-shadow: none; color: var(--surface); cursor: not-allowed; transform: none; }

.btn-primary.accent2 {
  background: linear-gradient(155deg, color-mix(in srgb, var(--accent2) 85%, white 18%), color-mix(in srgb, var(--accent2) 96%, black 8%));
  border-color: color-mix(in srgb, var(--accent2) 45%, white 55%);
  color: #F5FAFD;
}
.btn-primary.accent2:hover { background: linear-gradient(155deg, color-mix(in srgb, var(--accent2-ink) 85%, white 14%), color-mix(in srgb, var(--accent2-ink) 96%, black 6%)); }

.btn-secondary {
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  border-color: var(--glass-border);
  color: var(--ink);
  box-shadow: var(--glass-shadow);
}
.btn-secondary:hover { border-color: var(--accent); color: var(--accent-ink); }

.btn-danger {
  background: linear-gradient(155deg, color-mix(in srgb, var(--danger) 24%, var(--glass-surface-1)), var(--glass-surface-2) 80%);
  border-color: color-mix(in srgb, var(--danger) 32%, var(--glass-border));
  color: var(--danger);
  box-shadow: var(--glass-shadow);
}
.btn-danger:hover { background: var(--danger); border-color: var(--danger); color: #F7F7FF; }

.btn-block { width: 100%; justify-content: center; }

/* ---------- Checkbox / toggle rows ---------- */
.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}

.toggle-row:first-child { border-top: none; }

.switch {
  position: relative;
  width: 40px;
  height: 22px;
  border-radius: 999px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
}

.switch.on { background: var(--accent); border-color: var(--accent); }

.switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: white;
  transition: left 0.15s;
}

.switch.on::after { left: 20px; }

/* ---------- Test-taking / exam chrome (full test, Quick Practice, diagnostic) ---------- */
/* Flex column, not a fixed height:100% — that used to cap the box at the
   viewport even when the actual question was taller (e.g. a wide-but-short
   window), so the old position:sticky footer's "bottom" stuck to that
   truncated box instead of the real content bottom and ended up
   overlapping the last ~150px of the question instead of sitting below it.
   exam-scroll-area (flex:1) + a plain (non-sticky) footer sibling below
   handles both cases correctly: short content stretches the scroll area,
   pinning the footer to the bottom; long content just flows normally,
   never overlapping. */
.main-content-inner.focus-mode { display: flex; flex-direction: column; min-height: 100%; padding: 0; }
.exam-scroll-area { flex: 1 0 auto; display: flex; flex-direction: column; }
.exam-scroll-area .exam-body-single,
.exam-scroll-area .exam-split { flex: 1 0 auto; }

/* Purely decorative, matching the real digital SAT's own chrome — but also
   IS the header's bottom boundary / the footer's top boundary now, in place
   of a plain 1px border (see .exam-header/.exam-footer below, which no
   longer draw their own), so it runs full-bleed edge to edge rather than
   stopping at the header/footer's own horizontal padding. The one under the
   per-question toolbar (nested inside .exam-split-pane/.exam-body-single,
   which already pad the content) shares the same padding:0 for the same
   reason, just bounded by that container's own width instead of the
   viewport's. No functional meaning (not progress, not status); see
   renderExamTileStrip() in app.js. Tiles are a fixed 21px (the width they
   naturally came out to under the old flex:1 -- keep that exact size, just
   fixed now) so every strip's individual tiles match regardless of the
   strip's own width. The narrower one under the toolbar just shows fewer
   whole tiles (the rest clipped via overflow:hidden) instead of squishing
   all of them thinner to fill its shorter row -- that squishing (~12px
   tiles there vs ~21px in the top/bottom strips under the old flex:1) was
   the actual problem being fixed.
   min-width:0 matters here: the top/bottom strips are flex ITEMS of
   .exam-scroll-area (a column flex container), and a flex item's default
   min-width is auto, not 0 -- with 100 non-shrinking 21px tiles inside
   (2397px of content), that default let the strip refuse to shrink below
   its content's width even though overflow:hidden was already clipping
   what got PAINTED, dragging .exam-scroll-area and .main-content along
   with it and forcing the whole exam screen to scroll horizontally on any
   viewport narrower than ~2400px. min-width:0 lets the flex item actually
   shrink to the space it's given, same fix as .exam-split-pane uses below
   for the same reason. As little of its own vertical padding as still
   reads as a strip (1px, not 6px) -- the tiles should sit right at the
   header/footer/toolbar's edge, not floating in a visible gap below it. */
.exam-tile-strip { display: flex; gap: 3px; padding: 1px 0; overflow: hidden; min-width: 0; }
/* Only the strip directly under the toolbar (a direct child of the question
   pane/single-body wrapper -- the other two tile strips, above the header
   and at the very bottom of the exam, are direct children of
   .exam-scroll-area instead, so this doesn't touch them) gets extra room
   below it, so the question itself doesn't start right on top of the
   toolbar row. The toolbar stays flush against the strip itself (see the
   .exam-toolbar comment above) -- this is space after the strip, not
   between the toolbar and the strip. */
.exam-split-question > .exam-tile-strip,
.exam-body-single > .exam-tile-strip { margin-bottom: 14px; }
.exam-tile { flex: 0 0 21px; height: 4px; border-radius: 1px; opacity: 0.55; }

.exam-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 24px;
  background: var(--surface);
  color: var(--ink);
}
.exam-header-title { min-width: 0; }
.exam-title { font-family: var(--font-exam-sans); font-weight: 600; font-size: 16px; color: var(--ink); }
.exam-directions-link {
  background: none; border: none; padding: 0; margin-top: 3px; cursor: pointer;
  font-size: 12.5px; color: var(--accent); font-family: var(--font-exam-sans);
}

.exam-timer-wrap { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.exam-timer {
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.exam-timer.untimed { font-size: 14px; font-weight: 500; color: var(--ink-soft); }
.exam-timer.warn { color: var(--warn); }
.exam-timer.danger { color: var(--danger); }
.exam-timer.timer-concealed { visibility: hidden; }
.exam-timer-toggle {
  background: none; border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  padding: 3px 12px; color: var(--ink-soft); font-family: var(--font-exam-sans); font-size: 11px; font-weight: 600;
}
.exam-timer-toggle:hover { color: var(--ink); border-color: var(--ink-soft); }

.exam-header-tools { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.exam-tool-btn {
  display: flex; align-items: center; gap: 6px;
  background: none; border: none; cursor: pointer;
  padding: 6px 10px; border-radius: var(--radius-sm);
  color: var(--ink-soft); font-family: var(--font-exam-sans); font-size: 12.5px; font-weight: 500;
  white-space: nowrap;
}
.exam-tool-btn:hover { background: var(--surface-sunken); color: var(--ink); }
.exam-tool-btn.active { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent-ink); }
.exam-tool-icon { display: flex; }
.exam-tool-more-wrap { position: relative; }
.exam-tool-btn.icon-only { padding: 7px; border-radius: 7px; }
.exam-tool-btn.icon-only.active { background: var(--accent); color: #fff; }
.exam-tool-btn.icon-only.active:hover { background: var(--accent-ink); }

.exam-more-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card); min-width: 180px; padding: 6px; display: flex; flex-direction: column;
}
.exam-more-item {
  text-align: left; background: none; border: none; cursor: pointer;
  padding: 9px 10px; border-radius: 6px; font-size: 13.5px; color: var(--ink);
}
.exam-more-item:hover { background: var(--surface-sunken); }

/* Lives inside the question pane now (see .exam-split-question below), not
   as a bar spanning the full header width above both passage and question —
   the real digital SAT's Mark for Review/eliminator row sits over the
   question only, and reads as belonging to it rather than as a continuation
   of the header/nav chrome above. Boxed with its own border, matching the
   real digital SAT's toolbar bar -- shared by every question screen (full
   tests, Practice, Diagnostic alike). No bottom border/radius of its own --
   the decorative tile strip right after it in the DOM (belowToolbar in
   app.js) sits flush against it and serves as its bottom edge instead. */
.exam-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--surface);
  margin-top: 20px;
  margin-bottom: 0;
}
.exam-toolbar-left { display: flex; align-items: center; gap: 14px; }
/* --header-bg/--header-fg, not --ink/#fff -- those two stay a fixed
   dark-bg/light-text pair in BOTH app themes (see the "deliberately-dark
   floating bits" comment up in :root), unlike --ink itself, which flips to
   a near-white color in dark mode. Using --ink here used to mean a
   near-white badge with hardcoded white text in dark mode -- the numeral
   unreadable against its own background, and the badge itself glaring
   against the dark toolbar around it. */
.exam-question-number {
  display: flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; padding: 0 4px;
  background: var(--header-bg); color: var(--header-fg); border-radius: 5px;
  font-family: var(--font-exam-sans); font-size: 13px; font-weight: 700;
}
.exam-mark-btn {
  display: flex; align-items: center; gap: 7px;
  background: none; border: none; cursor: pointer; padding: 4px 6px;
  font-size: 13px; font-weight: 500; color: var(--ink-soft); font-family: var(--font-exam-sans);
}
.exam-mark-btn:hover { color: var(--ink); }
.exam-mark-btn.active { color: var(--warn); }

/* width:100% (not just max-width+margin:auto) matters here: each is a flex
   item of .exam-scroll-area (a column flex container), and a flex item with
   auto cross-axis margins doesn't stretch to fill the container the way
   margin:0 auto centering normally implies on a plain block element --
   without an explicit width, it instead sizes to its own content/max-width
   (landing at the 1400px cap) regardless of how much space is actually
   available, forcing the whole exam screen to scroll horizontally on any
   viewport narrower than that instead of reflowing narrower. min-width:0
   is the usual companion fix for a flex item that shouldn't be held to its
   content's width as a floor either (matching .exam-tile-strip and
   .exam-split-pane below), though width:100% is what actually matters here. */
.exam-body-single, .exam-split { padding: 30px 24px 100px; width: 100%; min-width: 0; }
.exam-body-single { max-width: 900px; margin: 0 auto; }
.exam-split { display: flex; gap: 0; max-width: 1400px; margin: 0 auto; align-items: stretch; }
.exam-split-pane { min-width: 0; padding: 0 22px; }
.exam-split-passage { flex: 0 0 50%; padding-right: 26px; }
.exam-split-question { flex: 1 1 auto; }
/* Draggable divider between the two panes — a wide invisible hit-area
   (col-resize cursor) with a thin visible line down its center, matching
   the real digital SAT's resizable split view. Drag logic lives in
   attachSplitResizer() in app.js; this element is rebuilt every render like
   the rest of the exam chrome, so the drag itself uses scoped mousemove/
   mouseup listeners added on mousedown and removed on mouseup, rather than
   the permanent window listeners makeDraggable() uses for the floating
   calculator/reference panels (those live outside the render tree and are
   only ever built once; this one isn't). */
.exam-split-resizer { flex: 0 0 auto; width: 9px; margin: 0 -4px; cursor: col-resize; position: relative; z-index: 1; }
.exam-split-resizer::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 1px;
  background: var(--border); transform: translateX(-50%);
}
.exam-split-resizer:hover::after, .exam-split-resizer.dragging::after { background: var(--accent); width: 2px; }

/* Drops the boxed/shaded-card look .passage carries elsewhere (review and
   results screens, where several stacked questions benefit from a visible
   boundary between them) -- on the live exam it's the only thing on screen,
   so it just reads as plain text on the pane's own background, matching the
   real digital SAT. .question-card gets the same treatment just below,
   scoped to the exam's own containers for the same reason. Individual
   answer choices (.choice) keep their own border on purpose -- that matches
   Bluebook's own bordered choice pills, not a "box around text" in the same
   sense as these two container-level ones. */
.passage.highlightable {
  cursor: text;
  background: none; border-left: none; border-radius: 0; padding: 0; margin-bottom: 20px;
}
.passage.highlightable::selection, .passage.highlightable *::selection { background: var(--warn-soft); }
.exam-split-question .question-card, .exam-body-single .question-card {
  background: none; border: none; border-radius: 0; box-shadow: none; padding: 0; margin-bottom: 0;
}
mark.user-highlight { background: #FDE68A; color: inherit; border-radius: 2px; padding: 0 1px; cursor: pointer; }
html[data-theme='dark'] mark.user-highlight { background: #8A6D1F; color: var(--ink); }
mark.user-highlight.has-note { box-shadow: inset 0 -2px 0 var(--accent-ink); }

/* ---------- Selection menu / note editor / notes panel ---------- */
.selection-menu-scrim { position: fixed; inset: 0; z-index: 65; background: transparent; }
.selection-menu {
  position: fixed; z-index: 66; display: flex; gap: 4px;
  background: var(--header-bg); border-radius: var(--radius-sm); box-shadow: var(--shadow-card);
  padding: 6px;
}
.selection-menu-btn {
  display: flex; align-items: center; gap: 6px;
  background: none; border: none; cursor: pointer; padding: 7px 10px;
  border-radius: 6px; color: var(--header-fg); font-size: 12.5px; font-weight: 500; white-space: nowrap;
}
.selection-menu-btn:hover { background: rgba(255, 255, 255, 0.12); }
.note-editor {
  position: fixed; z-index: 66; width: 240px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 12px;
}
.note-editor-quote { font-size: 12px; color: var(--muted); font-style: italic; margin-bottom: 8px; }
.note-editor-input {
  width: 100%; font-family: var(--font-body); font-size: 13px; color: var(--ink);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px; resize: vertical;
  background: var(--surface); margin-bottom: 10px;
}
.note-editor-input:focus { outline: none; border-color: var(--accent); }
.note-editor-actions { display: flex; justify-content: flex-end; gap: 8px; }
.notes-panel-item { padding: 12px 0; border-bottom: 1px solid var(--border); }
.notes-panel-item:last-child { border-bottom: none; }
.notes-panel-quote { font-size: 13.5px; color: var(--ink); font-style: italic; }
.notes-panel-note { font-size: 13px; color: var(--ink-soft); margin-top: 6px; padding: 8px 10px; background: var(--surface-sunken); border-radius: var(--radius-sm); }

/* No border-top -- the tile strip right above it in the DOM serves as that
   boundary instead, full-bleed. */
.exam-footer {
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 24px; background: var(--surface);
}
/* Always on (every exam screen) — the question pill sits dead-center in the
   bar regardless of how wide the Back/Next buttons on the right are, or
   whether the pill itself is interactive (Quick Practice/diagnostic disable
   it — no free navigation in the reveal-immediately drill model — but it
   still centers the same as a full test's clickable one). */
.exam-footer.centered-nav { position: relative; justify-content: flex-end; }
.exam-footer.centered-nav .exam-footer-nav {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
}
.exam-footer-nav { position: relative; }
.exam-footer-name { margin-right: auto; font-family: var(--font-exam-sans); font-size: 13px; color: var(--ink-soft); }
.exam-nav-pill {
  display: flex; align-items: center; gap: 8px;
  background: var(--header-bg); color: var(--header-fg);
  border: none; border-radius: 10px; padding: 9px 16px;
  font-family: var(--font-mono); font-size: 12.5px; cursor: pointer;
}
.nav-pill-chevron { display: flex; transition: transform 0.15s; }
.nav-pill-chevron.open { transform: rotate(180deg); }

.exam-nav-pill:disabled { cursor: default; opacity: 0.85; }
.exam-footer-actions { display: flex; gap: 10px; }

.exam-nav-dropdown {
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 16px; width: 320px; z-index: 40;
}
.exam-nav-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin-bottom: 12px; }
.exam-nav-cell {
  position: relative;
  width: 36px; height: 36px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--ink-soft); font-family: var(--font-mono); font-size: 12px; cursor: pointer;
}
.exam-nav-cell.answered { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink); }
.exam-nav-cell.current { outline: 2px solid var(--ink); outline-offset: 1px; }
.exam-nav-cell.marked::after {
  content: ''; position: absolute; top: -3px; right: -3px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--warn);
}
.exam-nav-legend { display: flex; flex-direction: column; gap: 6px; font-size: 11.5px; color: var(--muted); }
.exam-nav-swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  border: 1px solid var(--border); background: var(--surface); margin-right: 5px; vertical-align: -1px;
}
.exam-nav-swatch.answered { background: var(--accent-soft); border-color: var(--accent); }
.exam-nav-swatch.marked { background: var(--warn); border-color: var(--warn); }

/* ---------- Exam modal (Directions / Reference Sheet) ---------- */
.exam-modal-scrim {
  position: fixed; inset: 0; background: rgba(16, 27, 46, 0.45);
  z-index: 60; display: flex; align-items: center; justify-content: center; padding: 20px;
}
.exam-modal {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-card);
  max-width: 620px; width: 100%; max-height: 82vh; display: flex; flex-direction: column; overflow: hidden;
}
.exam-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.exam-modal-head h2 { font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--ink); margin: 0; }
.exam-modal-close { background: none; border: none; font-size: 22px; line-height: 1; color: var(--muted); cursor: pointer; padding: 2px 6px; }
.exam-modal-close:hover { color: var(--ink); }
.exam-modal-body { padding: 20px; overflow-y: auto; font-size: 14px; line-height: 1.6; color: var(--ink-soft); }
.exam-modal-body p { margin: 0 0 12px; }
.exam-modal-body p:last-child { margin-bottom: 0; }

/* ---------- Reference sheet content ---------- */
.ref-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 30px 20px; margin-bottom: 28px; }
.ref-item { text-align: center; min-width: 0; }
.ref-figure { color: var(--ink-soft); display: flex; align-items: center; justify-content: center; height: 100px; }
.ref-figure svg { width: 100%; max-width: 108px; height: auto; max-height: 100px; }
/* Pin an explicit serif font on the diagram labels instead of leaving them
   to inherit the body sans-serif font -- reported as rendering in stray
   blue/orange on at least one Windows setup, consistent with the OS
   substituting a color font for a glyph it doesn't have a match for. */
.ref-figure svg text { font-family: Georgia, 'Times New Roman', serif; }
/* Special Right Triangles has 9 labels crammed into one figure -- give it
   the whole row instead of squeezing it into a single 108px grid column
   like every other (much simpler) diagram. */
.ref-item:nth-child(5) { grid-column: 1 / -1; }
.ref-item:nth-child(5) .ref-figure { height: 150px; }
.ref-item:nth-child(5) .ref-figure svg { max-width: 340px; max-height: 150px; }
.ref-formula { font-size: 16px; margin-top: 8px; color: var(--ink); }
.ref-caption { font-size: 13px; margin-top: 6px; color: var(--muted); }
.ref-facts { border-top: 1px solid var(--border); padding-top: 20px; font-size: 15px; color: var(--ink-soft); line-height: 1.9; }

/* ---------- Reference sheet floating panel ---------- */
.refsheet-panel {
  /* Anchored to the LEFT by default (Calculator anchors right, below) --
     Calculator and Reference can both be open at once now, and starting
     them in opposite corners means a fresh open of both doesn't land one
     exactly on top of the other. Each is still freely draggable afterward. */
  position: fixed; top: 90px; left: 24px; z-index: 70;
  width: 740px; height: 620px; display: none; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); overflow: hidden;
  resize: both; min-width: 480px; min-height: 360px; max-width: 96vw; max-height: 90vh;
}
.refsheet-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; background: var(--surface-sunken); border-bottom: 1px solid var(--border);
  cursor: move; flex-shrink: 0;
}
.refsheet-panel-header h2 { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--ink); margin: 0; }
.refsheet-panel-close { background: none; border: none; font-size: 18px; line-height: 1; color: var(--muted); cursor: pointer; padding: 2px 8px; }
.refsheet-panel-close:hover { color: var(--ink); }
.refsheet-mount { flex: 1; min-height: 0; overflow-y: auto; padding: 22px 24px; }

/* ---------- Desmos calculator floating panel ---------- */
.desmos-panel {
  position: fixed; top: 90px; right: 24px; z-index: 70;
  width: 460px; height: 420px; display: none; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); overflow: hidden;
  resize: both; min-width: 320px; min-height: 280px; max-width: 96vw; max-height: 90vh;
}
.desmos-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px; background: var(--surface-sunken); border-bottom: 1px solid var(--border);
  cursor: move; flex-shrink: 0;
}
.desmos-mode-toggle { display: flex; gap: 4px; }
.desmos-mode-toggle button {
  font-family: var(--font-body); font-size: 12px; font-weight: 600;
  padding: 5px 10px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--ink-soft); cursor: pointer;
}
.desmos-mode-toggle button.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.desmos-panel-close { background: none; border: none; font-size: 18px; color: var(--muted); cursor: pointer; padding: 2px 8px; }
.desmos-panel-close:hover { color: var(--ink); }
.desmos-mount { flex: 1; min-height: 0; }

/* ---------- Diagnostic intro ---------- */
.diag-intro { max-width: 760px; margin: 20px auto 0; text-align: center; }
.diag-intro-title { font-family: var(--font-display); font-size: 30px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
.diag-intro-sub { color: var(--muted); font-size: 14.5px; margin: 0 0 28px; }
.diag-intro-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card); padding: 40px 36px;
}
.diag-intro-icon {
  width: 64px; height: 64px; border-radius: var(--radius-md);
  background: var(--accent-soft); color: var(--accent-ink);
  display: flex; align-items: center; justify-content: center; margin: 0 auto 18px;
}
/* The icon markup is a <span> wrapping raw SVG — as an inline element its
   box includes descender space below the SVG's baseline, which throws off
   vertical centering inside the flex parent even with align-items:center.
   Making the span itself a flex box collapses that phantom space so the
   SVG centers exactly. */
.diag-intro-icon span { display: flex; align-items: center; justify-content: center; }
.diag-intro-icon svg { width: 30px; height: 30px; }
.diag-intro-card h2 { font-family: var(--font-display); font-size: 22px; font-weight: 600; color: var(--ink); margin: 0 0 12px; }
.diag-intro-desc { color: var(--ink-soft); font-size: 14px; line-height: 1.6; max-width: 520px; margin: 0 auto 28px; }
.diag-feature-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 28px; }
.diag-feature { background: var(--surface-sunken); border-radius: var(--radius-md); padding: 18px 16px; text-align: center; }
.diag-feature-icon {
  width: 44px; height: 44px; border-radius: var(--radius-sm); background: var(--surface);
  color: var(--ink); display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;
  box-shadow: 0 1px 3px rgba(16, 27, 46, 0.08);
}
.diag-feature-icon span { display: flex; align-items: center; justify-content: center; }
.diag-feature-icon svg { width: 24px; height: 24px; }
.diag-feature-title { font-weight: 600; font-size: 13.5px; color: var(--ink); margin-bottom: 4px; }
.diag-feature-desc { font-size: 12px; color: var(--muted); line-height: 1.5; }

/* ---------- Module "Check Your Work" review screen (before submit) ---------- */
.module-review { max-width: 640px; margin: 0 auto; padding: 20px 24px 0; }
.module-review-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; margin: 20px 0; }
.module-review-legend { display: flex; gap: 18px; font-size: 12.5px; color: var(--muted); flex-wrap: wrap; }

@media (max-width: 760px) {
  .module-review-grid { grid-template-columns: repeat(5, 1fr); }
  .exam-split { flex-direction: column; }
  /* Stacked, not side-by-side -- the drag ratio (a %-width flex-basis, set
     inline by attachSplitResizer()) doesn't apply to a column layout, and
     the resizer itself has nothing meaningful to drag here. */
  .exam-split-passage { flex: none !important; border-bottom: 1px solid var(--border); padding-right: 22px; padding-bottom: 20px; margin-bottom: 6px; }
  .exam-split-resizer { display: none; }
  .exam-nav-grid { grid-template-columns: repeat(5, 1fr); }
  .desmos-panel { width: calc(100vw - 24px); right: 12px; left: 12px; }
  .refsheet-panel { width: calc(100vw - 24px); right: 12px; left: 12px; }
  .diag-feature-grid { grid-template-columns: 1fr; }
  .ref-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.question-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 28px;
  margin-bottom: 18px;
}

.passage {
  background: var(--surface-sunken);
  border-left: 3px solid var(--accent-soft);
  border-radius: 0 8px 8px 0;
  padding: 16px 19px;
  font-family: var(--font-exam-serif);
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--ink);
  margin-bottom: 20px;
}

/* The College-Board-style editorial lead-in ("The following text is
   from...", scene-setting) that some passages carry ahead of the actual
   quoted excerpt — see splitPassageIntro() in app.js. Styled apart so it
   doesn't read as part of the source text being quoted. */
.passage-intro {
  font-style: italic;
  color: var(--muted);
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px dashed var(--border);
}

/* A handful of imported questions store a data table as flattened
   "Col1 | Col2 | Col3" text inside the passage instead of a real table —
   see extractEmbeddedTable() in app.js. Rendered as an actual <table>,
   set apart from the surrounding passage's sunken background so it reads
   as the distinct data element it is. */
.passage-table-wrap { overflow-x: auto; margin: 2px 0 14px; }
.passage-table-title { font-weight: 700; color: var(--ink); margin-bottom: 8px; font-size: 13.5px; }
.passage-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.passage-table th, .passage-table td {
  padding: 6px 12px; border: 1px solid var(--border); text-align: left; white-space: nowrap;
  background: var(--surface);
}

.passage-table th { font-weight: 700; color: var(--ink); }
.passage-table td { color: var(--ink); }
.passage-table th.num, .passage-table td.num { text-align: right; }

/* Figure crops from the source PDF — always a white card regardless of
   theme, since these are raster images with their own (light) background,
   not theme-colored UI. */
.figure-card {
  background: #FFFFFF;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px;
  margin-bottom: 16px;
  text-align: center;
}

.figure-card img {
  max-width: 100%;
  max-height: 320px;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

.figure-card.choice-figure {
  margin-bottom: 0;
  padding: 10px;
  max-width: 280px;
}

.question-text {
  font-family: var(--font-exam-serif);
  font-weight: 500;
  font-size: 17.5px;
  line-height: 1.5;
  margin-bottom: 20px;
  color: var(--ink);
}

.choice {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 1.5px solid var(--ink-soft);
  border-radius: var(--radius-sm);
  padding: 13px 16px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}

.choice:hover { border-color: var(--accent); }

.choice.selected { border-color: var(--accent); background: var(--surface); }

.choice.correct { border-color: var(--good); background: var(--good-soft); }
.choice.incorrect { border-color: var(--danger); background: var(--danger-soft); }

.choice-letter {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 12.5px;
  width: 23px;
  height: 23px;
  border-radius: 50%;
  border: 1.5px solid var(--ink-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--muted);
  background: var(--surface);
}

.choice.selected .choice-letter { border-color: var(--accent); color: #fff; background: var(--accent); }
.choice.correct .choice-letter { border-color: var(--good); color: var(--good); }
.choice.incorrect .choice-letter { border-color: var(--danger); color: var(--danger); }

.choice-text { font-family: var(--font-exam-serif); font-size: 15px; line-height: 1.45; padding-top: 1px; color: var(--ink); }

/* ---------- Answer Eliminator (cross out choices) ---------- */
.choice-elim-row { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.choice-elim-cell { flex: 1; min-width: 0; }
.choice-elim-cell .choice { margin-bottom: 0; }
/* Eliminated: the whole row washes out (border, letter, text all fade
   together) and a single line strikes straight across the box — not just
   the text — matching the real digital SAT's Answer Eliminator. */
.choice-elim-cell.eliminated .choice {
  position: relative;
  cursor: default;
  border-color: var(--border);
  background: none;
  opacity: 0.5;
}
.choice-elim-cell.eliminated .choice::after {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  border-top: 1.5px solid var(--ink-soft);
}
.choice-elim-cell.eliminated .choice-text { color: var(--muted); }
.choice-elim-cell.eliminated .choice-letter { color: var(--muted); border-color: var(--border); }
.choice-elim-cell.eliminated .choice:hover { border-color: var(--border); }
/* Always struck through, not just on hover/after use -- otherwise it's just
   a bare letter with no visual hint that clicking it crosses the choice
   out, unlike the header/toolbar's own "ABC" eliminator icon (ICON_ELIMINATOR
   in app.js), which already draws its own line for exactly that reason. */
.eliminator-btn {
  flex-shrink: 0;
  width: 23px; height: 23px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--border); border-radius: 50%;
  padding: 0; cursor: pointer; color: var(--muted);
  font-family: var(--font-mono); font-weight: 700; font-size: 11.5px;
  text-decoration: line-through; text-decoration-thickness: 1.5px;
}
.eliminator-btn:hover { border-color: var(--accent); color: var(--accent-ink); }
.eliminator-undo-btn {
  flex-shrink: 0;
  background: none; border: none; cursor: pointer; padding: 0;
  color: var(--accent); font-size: 12px; font-weight: 600; text-decoration: underline;
  white-space: nowrap;
}
.eliminator-undo-btn:hover { color: var(--accent-ink); }

.grid-in-wrap { margin-bottom: 10px; }

.grid-in-input {
  width: 100%;
  max-width: 220px;
  font-family: var(--font-mono);
  font-size: 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  background: var(--surface);
  color: var(--ink);
}

.grid-in-input:focus { outline: none; border-color: var(--accent); }
.grid-in-input.correct { border-color: var(--good); background: var(--good-soft); }
.grid-in-input.incorrect { border-color: var(--danger); background: var(--danger-soft); }
.grid-in-input:disabled { opacity: 1; }

.test-select {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14.5px;
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  background: var(--surface);
  cursor: pointer;
}

.test-select:focus { outline: none; border-color: var(--accent); }

.nav-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

/* ---------- Score ruler (signature element) ---------- */
.score-ruler {
  margin: 14px 0 6px;
}

.ruler-track {
  position: relative;
  height: 8px;
  background: var(--surface-sunken);
  border-radius: 999px;
  margin: 24px 0 6px;
}

.ruler-fill {
  position: absolute;
  top: 0; left: 0; height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--good));
  border-radius: 999px;
}

.ruler-marker {
  position: absolute;
  top: -21px;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  color: var(--ink);
}

.ruler-ticks {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--muted);
}

/* Goal-score tick on the "Your score" card's ruler — the one place two
   values (current score, goal score) plot on the same 400–1600 scale. */
.ruler-goal-marker {
  position: absolute; top: -5px; bottom: -5px; width: 2px;
  background: var(--ink); border-radius: 1px; transform: translateX(-50%);
}
.ruler-goal-marker::after {
  content: ''; position: absolute; top: -5px; left: 50%; transform: translateX(-50%);
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink);
}

.score-block {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 2px;
}

.score-big {
  font-family: var(--font-display);
  font-size: 42px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.score-label {
  font-size: 13px;
  color: var(--muted);
}

.score-raw {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-soft);
}

.composite-card {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-ink) 100%);
  color: #F7F7FF;
  border-radius: var(--radius);
  box-shadow: var(--shadow-composite);
  padding: 26px 28px;
  margin-bottom: 18px;
}

.composite-card.accent2 {
  background: linear-gradient(135deg, var(--accent2) 0%, var(--accent2-ink) 100%);
  color: #F5FAFD;
  box-shadow: var(--shadow-composite2);
}

.composite-card .score-label { color: rgba(248, 246, 255, 0.75); }
.composite-card .score-big { color: #F7F7FF; }
.composite-card .ruler-track { background: rgba(248, 246, 255, 0.22); }
.composite-card .ruler-fill { background: #F7F7FF; }
.composite-card .ruler-marker { color: #F7F7FF; }
.composite-card .ruler-ticks { color: rgba(248, 246, 255, 0.65); }
.composite-card.accent2 .score-label { color: rgba(245, 250, 253, 0.75); }
.composite-card.accent2 .score-big { color: #F5FAFD; }
.composite-card.accent2 .ruler-track { background: rgba(245, 250, 253, 0.22); }
.composite-card.accent2 .ruler-fill { background: #F5FAFD; }
.composite-card.accent2 .ruler-marker { color: #F5FAFD; }
.composite-card.accent2 .ruler-ticks { color: rgba(245, 250, 253, 0.65); }

.est-note {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 10px;
  line-height: 1.5;
}

.composite-card .est-note { color: rgba(248, 246, 255, 0.7); }
.composite-card.accent2 .est-note { color: rgba(245, 250, 253, 0.7); }

/* ---------- Review list ---------- */
.review-item {
  border-top: 1px solid var(--border);
  padding: 14px 0;
}

.review-item:first-child { border-top: none; }

.review-item .rq {
  font-size: 14px;
  margin-bottom: 6px;
  font-weight: 500;
  color: var(--ink);
}

.review-item.clickable, .history-mini.clickable { cursor: pointer; transition: background 0.12s; }
.review-item.clickable:hover, .history-mini.clickable:hover { background: var(--surface-sunken); }
.review-row { display: flex; align-items: center; justify-content: space-between; }
.review-detail-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.tag.warn { background: var(--warn-soft); color: var(--warn); }

.explain-panel { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.explain-text { font-size: 13.5px; line-height: 1.6; color: var(--ink-soft); white-space: pre-line; }
.explain-block { margin-bottom: 12px; }
.explain-block:last-child { margin-bottom: 0; }
.explain-heading {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}
.explain-panel-personalized { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); }

/* Per-question follow-up chat (renderTutorFollowup) -- plain stacked
   Q&A blocks reusing .explain-block/.explain-text above, just the input
   row below is new. */
.tutor-followup-row { display: flex; gap: 8px; margin-top: 10px; }
.tutor-followup-input { flex: 1; }

/* ---------- AI Tutor (standalone chat page) ---------- */
/* Only used for the logged-out gate now -- the real chat UI is the
   sidebar+pane .tutor-layout below. */
.tutor-card { max-width: 480px; margin: 40px auto; }

.tutor-layout {
  display: flex;
  gap: 20px;
  align-items: stretch;
  height: calc(100vh - 160px);
  min-height: 480px;
}

.tutor-sidebar {
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  padding: 16px;
  overflow-y: auto;
}
.tutor-conv-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 4px;
}
.tutor-conv-list { display: flex; flex-direction: column; gap: 2px; }
.tutor-conv-item {
  appearance: none;
  border: none;
  background: none;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
  text-align: left;
  transition: background 0.16s var(--ease-standard), color 0.16s var(--ease-standard);
}
.tutor-conv-item:hover { background: var(--sidebar-hover-bg); color: var(--ink); }
.tutor-conv-item.active { background: var(--sidebar-active-bg); border: 1px solid var(--sidebar-active-border); color: var(--accent-ink); font-weight: 600; }
.tutor-conv-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tutor-conv-remove {
  flex-shrink: 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  padding: 2px 5px;
  border-radius: 4px;
  opacity: 0;
  transition: opacity 0.14s var(--ease-standard), background 0.14s var(--ease-standard), color 0.14s var(--ease-standard);
}
.tutor-conv-item:hover .tutor-conv-remove { opacity: 1; }
.tutor-conv-remove:hover { background: var(--danger-soft); color: var(--danger); }

.tutor-chat-pane {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  padding: 20px 22px;
}

/* Haiku/Sonnet -- plain .active-class highlight, not the sliding-indicator
   FLIP treatment the theme segmented control uses (syncThemeIndicator in
   app.js): that machinery is keyed to one specific DOM location and not
   worth duplicating for a second, unrelated toggle. */
.tutor-model-toggle {
  display: inline-flex;
  gap: 3px;
  align-self: flex-start;
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 3px;
  margin-bottom: 14px;
  flex-shrink: 0;
}
.tutor-model-btn {
  appearance: none;
  border: none;
  background: transparent;
  padding: 6px 14px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: background 0.16s var(--ease-standard), color 0.16s var(--ease-standard);
}
.tutor-model-btn:hover:not(:disabled) { color: var(--ink-soft); }
.tutor-model-btn.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card); }
.tutor-model-btn:disabled { cursor: not-allowed; opacity: 0.55; }
.tutor-model-lock { font-size: 10px; }

@media (max-width: 760px) {
  .tutor-layout { flex-direction: column; height: auto; min-height: 0; }
  .tutor-sidebar { width: 100%; flex-direction: row; align-items: center; overflow-x: auto; }
  .tutor-sidebar .tutor-conv-label { display: none; }
  .tutor-sidebar .tutor-conv-list { flex-direction: row; }
  .tutor-sidebar .tutor-conv-item { white-space: nowrap; }
  .tutor-sidebar .tutor-conv-title { max-width: 140px; }
  .tutor-chat-pane { height: 70vh; }
}

.tutor-messages {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-bottom: 4px;
}
.tutor-bubble {
  max-width: 82%;
  padding: 11px 15px;
  border-radius: var(--radius-md);
  font-size: 13.5px;
  line-height: 1.55;
  white-space: pre-line;
}
.tutor-bubble.user {
  align-self: flex-end;
  background: var(--accent);
  color: #F7F7FF;
  border-bottom-right-radius: 4px;
}
.tutor-bubble.assistant {
  align-self: flex-start;
  background: var(--surface-sunken);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}
.tutor-bubble.loading { color: var(--muted); font-style: italic; }
.tutor-input-row {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.tutor-input {
  flex: 1;
  resize: none;
  font-family: var(--font-body);
  font-size: 14px;
  padding: 10px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
}

.pro-section { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--border); }
.pro-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--good-soft);
  color: var(--good);
  margin-bottom: 6px;
}

.question-browser {
  padding: 0 0 18px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
  padding-top: 16px;
}

.question-browser .question-card {
  box-shadow: none;
  padding: 20px;
}

.tag {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 8px;
  border-radius: 999px;
  margin-right: 8px;
}

.tag.good { background: var(--good-soft); color: var(--good); }
.tag.bad { background: var(--danger-soft); color: var(--danger); }
.tag.mod { background: var(--accent-soft); color: var(--accent-ink); }

/* ---------- Library / import ---------- */
.test-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0;
  border-top: 1px solid var(--border);
}

.test-row:first-child { border-top: none; }

.test-row .name { font-weight: 600; font-size: 14.5px; color: var(--ink); }
.test-row .meta { font-size: 12px; color: var(--muted); font-family: var(--font-mono); }

/* ---------- Question Bank: left filter panel + right results ---------- */
.qbank-layout { display: flex; gap: 20px; align-items: flex-start; }
.qbank-filter-card { width: 220px; flex-shrink: 0; position: sticky; top: 28px; }
.qbank-results-card { flex: 1; min-width: 0; }
.qbank-filter-panel { display: flex; flex-direction: column; gap: 18px; }
.qbank-filter-field select { width: 100%; }
.qbank-skill-list {
  max-height: 220px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 4px;
}
@media (max-width: 860px) {
  .qbank-layout { flex-direction: column; }
  .qbank-filter-card { width: 100%; position: static; }
  .qbank-filter-panel { flex-direction: row; flex-wrap: wrap; gap: 12px; }
  .qbank-filter-field { flex: 1 1 160px; }
}

/* Page controls centered as one unit in their own bottom bar, matching the
   reference layout -- not left-aligned like a plain "Show more" button. */
.qbank-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.qbank-page-btn {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-soft);
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.16s var(--ease-standard), color 0.16s var(--ease-standard), border-color 0.16s var(--ease-standard);
}
.qbank-page-btn:hover:not(:disabled) { background: var(--surface-sunken); color: var(--ink); border-color: var(--accent); }
.qbank-page-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.qbank-page-label {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 12px;
  white-space: nowrap;
}

/* ---------- Question Bank / Mistakes list rows ---------- */
.qbank-row { border-top: 1px solid var(--border); padding: 12px 0; }
.qbank-row-main { cursor: pointer; display: flex; flex-direction: column; gap: 6px; }
.qbank-row-stem {
  font-size: 14px;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

textarea.json-input {
  width: 100%;
  min-height: 160px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px;
  background: var(--surface-sunken);
  color: var(--ink);
  resize: vertical;
}

select, input[type=text] {
  font-family: var(--font-body);
  font-size: 14px;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
}

.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--muted);
}

.empty-state .big-icon {
  font-family: var(--font-display);
  font-size: 34px;
  color: var(--border);
  margin-bottom: 8px;
}

.pill-row { display: flex; gap: 8px; flex-wrap: wrap; }

.history-mini {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
}
.history-mini:first-child { border-top: none; }
.history-mini .hm-name { color: var(--ink-soft); }
.history-mini .hm-score { font-family: var(--font-mono); font-weight: 700; color: var(--ink); }
.history-mini .hm-right { display: flex; align-items: center; gap: 10px; }

.hm-remove {
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.hm-remove:hover { color: var(--danger); background: var(--danger-soft); }

.attempts-card { padding: 8px 26px; }
.attempts-card .history-mini { padding: 16px 0; }

.guest-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 12px 16px;
  margin-bottom: 18px;
  font-size: 13px;
  color: var(--ink-soft);
}
.guest-banner .panel-link { font-size: 13px; margin-left: 2px; }

.page-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 24px;
  margin: 0 0 16px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* ---------- Home dashboard ---------- */
.home-hero-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.home-hero { margin-bottom: 22px; }
.home-section { margin-bottom: 20px; }
.home-hero h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 27px;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.home-hero p { margin: 0; color: var(--muted); font-size: 14px; }

.test-date-badge {
  flex-shrink: 0;
  text-align: right;
  background: linear-gradient(160deg, color-mix(in srgb, var(--good) 16%, transparent), var(--glass-surface-2));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid color-mix(in srgb, var(--good) 20%, transparent);
  border-radius: var(--radius-md);
  padding: 10px 16px;
  cursor: pointer;
  transition: border-color 0.18s var(--ease-standard), transform 0.18s var(--ease-standard), box-shadow 0.22s var(--ease-standard);
}
.test-date-badge:hover { border-color: var(--good); transform: translateY(-1px); box-shadow: 0 8px 20px rgba(63, 125, 83, 0.14); }
.test-date-badge-label {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--good); margin-bottom: 2px;
}
.test-date-badge-value { font-family: var(--font-display); font-size: 14.5px; font-weight: 600; color: var(--ink); }

.cta-card {
  text-align: left;
  cursor: pointer;
  border: none;
  border-radius: var(--radius-lg);
  padding: 24px;
  color: #F7F7FF;
  box-shadow: var(--shadow-composite);
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-ink) 100%);
  transition: transform 0.18s var(--ease-standard), box-shadow 0.22s var(--ease-standard);
}
.cta-card:hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(31, 73, 172, 0.30); }
.cta-card:active { transform: translateY(0) scale(0.99); }
.cta-card.accent2 {
  color: #F5FAFD;
  box-shadow: var(--shadow-composite2);
  background: linear-gradient(135deg, var(--accent2) 0%, var(--accent2-ink) 100%);
}
.cta-card.accent2:hover { box-shadow: 0 16px 34px rgba(11, 90, 103, 0.28); }
.cta-card .cta-eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.75;
  margin-bottom: 10px;
}
.cta-card .cta-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  margin-bottom: 6px;
}
.cta-card .cta-desc { font-size: 13px; opacity: 0.85; line-height: 1.5; }

.stat-tile {
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  padding: 16px 18px;
}
.stat-tile .stat-label { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.stat-tile .stat-value { font-family: var(--font-display); font-weight: 600; font-size: 26px; color: var(--ink); }

/* ---------- Signed-out Home (renderHomeLoggedOut) ---------- */
/* Same composite-card gradient/shadow language as the rest of the app
   (see .composite-card) -- this just lays it out as text-left/visual-right
   instead of a single stacked column, and adds the decorative logo mark. */
.guest-hero {
  display: flex;
  align-items: center;
  gap: 36px;
  padding: 40px 44px;
  overflow: hidden;
}
.guest-hero-text { flex: 1 1 auto; min-width: 0; }
.guest-hero-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase;
  color: rgba(247, 247, 255, 0.85);
  background: rgba(247, 247, 255, 0.14); border: 1px solid rgba(247, 247, 255, 0.22);
  padding: 5px 12px; border-radius: 999px; margin-bottom: 16px;
}
.guest-hero-badge .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--good); box-shadow: 0 0 0 2px rgba(247, 247, 255, 0.12); }
.guest-hero h1 {
  font-family: var(--font-display); font-weight: 700; font-size: 30px; line-height: 1.18;
  letter-spacing: -0.01em; color: #F7F7FF; margin: 0 0 12px; max-width: 480px;
}
.guest-hero p { font-size: 14px; line-height: 1.6; color: rgba(247, 247, 255, 0.88); max-width: 460px; margin: 0 0 24px; }
.guest-hero-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.guest-hero-visual {
  position: relative; flex: 0 0 176px; height: 176px;
  display: flex; align-items: center; justify-content: center;
}
.guest-hero-orb {
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.32), rgba(255, 255, 255, 0.03) 60%, transparent 72%);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.guest-hero-visual .brand-icon { position: relative; }
.guest-hero-visual .brand-icon svg { width: 104px; height: 104px; filter: drop-shadow(0 12px 22px rgba(9, 20, 46, 0.35)); }
@media (max-width: 720px) {
  .guest-hero { flex-direction: column; align-items: flex-start; padding: 30px 26px; }
  .guest-hero-visual { display: none; }
}

/* ---------- Signed-out Home: account-vs-guest checklist ---------- */
.guest-checklist-label {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 12px 4px;
}
.guest-checklist {
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border); border-radius: var(--radius); box-shadow: var(--glass-shadow);
  overflow: hidden;
}
.guest-checklist-head, .guest-checklist-row {
  display: grid; grid-template-columns: 1fr 168px 168px; align-items: center;
}
.guest-checklist-head { background: linear-gradient(135deg, var(--accent) 0%, var(--accent-ink) 100%); }
.guest-checklist-head > div { padding: 16px 20px; }
.guest-checklist-task-head { font-size: 12.5px; font-weight: 700; color: #F7F7FF; }
.guest-checklist-col-head {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 700; color: #F7F7FF; text-align: center;
}
.guest-checklist-col-icon {
  width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: rgba(247, 247, 255, 0.16); border: 1px solid rgba(247, 247, 255, 0.28);
}
.guest-checklist-row { border-top: 1px solid var(--border); transition: background 0.14s var(--ease-standard); }
.guest-checklist-row:nth-child(even) { background: rgba(255, 255, 255, 0.38); }
.guest-checklist-row:hover { background: rgba(255, 255, 255, 0.65); }
html[data-theme='dark'] .guest-checklist-row:nth-child(even) { background: rgba(255, 255, 255, 0.03); }
html[data-theme='dark'] .guest-checklist-row:hover { background: rgba(255, 255, 255, 0.06); }
.guest-checklist-label-cell { font-size: 13.5px; font-weight: 600; color: var(--ink); line-height: 1.4; padding: 16px 20px; }
.guest-checklist-mark-cell { display: flex; align-items: center; justify-content: center; padding: 14px 12px; }
.guest-checklist-mark { flex-shrink: 0; width: 30px; height: 30px; background-repeat: no-repeat; background-position: center; background-size: contain; }
.guest-checklist-mark.check { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='15' fill='%23E4F1E7'/%3E%3Cpath d='M10 16.5l4 4 8-9' fill='none' stroke='%233F7D53' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.guest-checklist-mark.cross { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='15' fill='%23F8E4E4'/%3E%3Cpath d='M11.5 11.5l9 9M20.5 11.5l-9 9' fill='none' stroke='%23B03F3F' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E"); }
@media (max-width: 640px) {
  .guest-checklist-head, .guest-checklist-row { grid-template-columns: 1fr 76px 76px; }
  .guest-checklist-head > div, .guest-checklist-label-cell { padding: 12px 8px; }
  .guest-checklist-col-head { font-size: 10.5px; }
  .guest-checklist-col-icon { width: 26px; height: 26px; }
  .guest-checklist-mark { width: 24px; height: 24px; }
}

/* ---------- Account sub-nav (Profile / Billing / Test Info / …) ---------- */
.account-subnav-layout { display: grid; grid-template-columns: 200px 1fr; gap: 24px; align-items: start; }
.account-subnav { display: flex; flex-direction: column; gap: 2px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 8px; position: sticky; top: 0; }
.account-subnav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: none;
  border: none;
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.account-subnav-item:hover { background: var(--surface-sunken); }
.account-subnav-item.active { background: var(--good-soft); color: var(--good); font-weight: 600; }
.account-subnav-content { min-width: 0; }
.plan-badge-icon {
  display: flex; flex-shrink: 0; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--radius-md);
  background: var(--good-soft); color: var(--good);
}
.pill-active {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em;
  padding: 2px 8px; border-radius: 999px;
  background: var(--good-soft); color: var(--good);
}
@media (max-width: 720px) {
  .account-subnav-layout { grid-template-columns: 1fr; }
  .account-subnav { flex-direction: row; overflow-x: auto; position: static; }
  .account-subnav-item { flex-shrink: 0; }
}

/* ---------- Unfinished-session bar (Home, signed in) ---------- */
.unfinished-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: var(--radius-md);
  padding: 13px 16px;
  flex-wrap: wrap;
}
.unfinished-text { font-size: 13px; color: var(--ink-soft); }
.unfinished-text b { color: var(--ink); }
.unfinished-time { font-family: var(--font-mono); }

.dash-panel {
  background: linear-gradient(155deg, var(--glass-surface-1), var(--glass-surface-2));
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  padding: 22px;
  transition: transform 0.22s var(--ease-standard), box-shadow 0.26s var(--ease-standard);
}
.dash-panel:hover { transform: translateY(-2px); box-shadow: var(--glass-shadow-hover); }
.dash-panel h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  margin: 0;
  color: var(--ink);
}
.dash-panel .panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
}
.dash-panel .panel-note { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.panel-link {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}

.activity-row {
  display: flex;
  justify-content: space-between;
  padding: 9px 0;
  border-top: 1px solid var(--border);
  font-size: 13px;
}
.activity-row:first-child { border-top: none; }
.activity-row .a-name { color: var(--ink-soft); }
.activity-row .a-score { font-family: var(--font-mono); font-size: 12.5px; font-weight: 700; color: var(--ink); }

.field-label {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 9px;
}

.mini-tile {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 10px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
  background: var(--surface);
  color: var(--ink);
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.mini-tile:hover { border-color: var(--accent); }
.mini-tile.selected { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }

/* ---------- Setup wizard: step dots ---------- */
/* ---------- "What's on every SAT test" format box (Start a Test) ---------- */
.format-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 20px 24px;
  margin-bottom: 16px;
}
.format-box-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.format-box-head h2 { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--ink); margin: 0; }
.format-box-total { font-family: var(--font-mono); font-size: 12px; color: var(--muted); white-space: nowrap; }
.format-box-groups { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.format-group-label {
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; margin-bottom: 10px;
}
.format-group-label.rw { color: var(--accent-ink); }
.format-group-label.math { color: var(--accent2-ink); }
.format-group-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.format-tile {
  border-radius: var(--radius-md);
  padding: 14px 18px;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.format-tile:hover { transform: translateY(-1px); box-shadow: var(--shadow-card); }
.format-tile.rw { background: var(--accent-soft); }
.format-tile.math { background: var(--accent2-soft); }
.format-tile-label {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; margin-bottom: 8px;
}
.format-tile.rw .format-tile-label { color: var(--accent-ink); opacity: 0.75; }
.format-tile.math .format-tile-label { color: var(--accent2-ink); opacity: 0.75; }
.format-tile-value { display: flex; align-items: baseline; gap: 10px; font-family: var(--font-display); font-size: 14.5px; font-weight: 600; }
.format-tile.rw .format-tile-value { color: var(--accent-ink); }
.format-tile.math .format-tile-value { color: var(--accent2-ink); }
.format-tile-pair { display: inline-flex; align-items: baseline; gap: 3px; }
.format-tile-num { font-size: 17px; }
.format-tile-unit { font-size: 11px; font-weight: 500; opacity: 0.8; }
.format-tile-sep { opacity: 0.4; font-size: 12px; }

@media (max-width: 640px) {
  .format-box-groups { grid-template-columns: 1fr; }
}

.step-dots { display: flex; gap: 8px; margin-bottom: 22px; }
.step-dot {
  height: 8px;
  border-radius: 999px;
  background: var(--border);
  transition: width 0.15s, background 0.15s;
}
.step-dot.active { background: var(--accent); width: 22px; }
.step-dot:not(.active) { width: 8px; }

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