/* ==========================================================================
   Smart Study AI — design system
   --------------------------------------------------------------------------
   Everything visual lives here. The idea is "Apple simple": one accent color,
   a lot of whitespace, and very few elements competing for attention.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. DESIGN TOKENS
   These are CSS custom properties ("variables"). Defining a color once here
   and referring to it everywhere else means changing the whole app's look is
   a one-line edit instead of a find-and-replace.
   -------------------------------------------------------------------------- */
:root {
  /* The system font stack. On a Mac/iPhone this resolves to San Francisco,
     Apple's own typeface — which is why the app feels native without us
     shipping any font files. */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
    Helvetica, Arial, sans-serif;

  /* Surfaces and text */
  --bg: #fbfbfd;          /* page background — very slightly warm, not pure white */
  --surface: #ffffff;     /* cards sitting on top of the background */
  --surface-alt: #f5f5f7; /* subtly recessed areas */
  --text: #1d1d1f;        /* near-black; true #000 looks harsh on screens */
  --text-muted: #6e6e73;  /* secondary text — labels, hints, captions */
  --border: #d2d2d7;

  /* The single accent color. Every interactive/primary element uses this and
     nothing else uses it, which is what makes buttons obviously clickable. */
  --accent: #0071e3;
  --accent-hover: #0077ed;
  --accent-soft: rgba(0, 113, 227, 0.1); /* translucent tint for selections */

  /* Feedback colors, only for right/wrong answers */
  --correct: #34c759;
  --correct-soft: rgba(52, 199, 89, 0.12);
  --wrong: #ff3b30;
  --wrong-soft: rgba(255, 59, 48, 0.12);

  /* Shape */
  --radius-card: 18px;
  --radius-input: 12px;
  --radius-pill: 980px; /* any radius larger than half the height = a full pill */

  --shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
  --shadow-lifted: 0 8px 32px rgba(0, 0, 0, 0.1);

  /* One easing curve for every animation, so motion feels consistent.
     This curve starts fast and settles gently — the iOS feel. */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* The text-size control multiplies this. Every font-size in the file is
     calc(<size> * var(--font-scale)), so one number resizes the whole app. */
  --font-scale: 1;

  --header-height: 56px;
  --content-width: 980px;
}

/* Dark mode. prefers-color-scheme reads the setting from macOS/iOS/Windows,
   so the app follows the user's system preference with no toggle needed.
   We only override the colors — every size, radius and animation stays. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #000000;
    --surface: #1c1c1e;
    --surface-alt: #2c2c2e;
    --text: #f5f5f7;
    --text-muted: #98989d;
    --border: #38383a;
    --accent: #0a84ff;
    --accent-hover: #409cff;
    --accent-soft: rgba(10, 132, 255, 0.16);
    --correct: #30d158;
    --correct-soft: rgba(48, 209, 88, 0.16);
    --wrong: #ff453a;
    --wrong-soft: rgba(255, 69, 58, 0.16);
    --shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
    --shadow-lifted: 0 8px 32px rgba(0, 0, 0, 0.5);
  }
}

/* --------------------------------------------------------------------------
   2. RESET / BASE
   Browsers ship their own default margins and font sizes that differ between
   them. Zeroing them out means our layout looks the same everywhere.
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box; /* padding counts INSIDE an element's width, which
                             makes sizing far more predictable */
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%; /* stop iOS Safari auto-inflating text */
}

body {
  font-family: var(--font);
  font-size: calc(1rem * var(--font-scale));
  line-height: 1.5;
  color: var(--text);
  background-color: var(--bg);
  min-height: 100vh;
  /* Smooths font rendering on macOS so text doesn't look overly bold */
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
}

/* Respect users who've asked their OS to reduce motion (vestibular disorders,
   motion sensitivity). Accessibility, and it costs us two lines. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   3. TOP MENU
   Like Word's ribbon but stripped to four items. Sticky so it's always
   reachable; translucent + blurred so content scrolling under it stays
   visible, which is a signature Apple treatment.
   -------------------------------------------------------------------------- */
.menu {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-height);
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0 1.5rem;
  border-bottom: 1px solid var(--border);

  /* color-mix lets us take our own --surface variable and make it 72%
     opaque, so it still adapts to dark mode instead of being hardcoded. */
  background-color: color-mix(in srgb, var(--surface) 72%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
}

.menu__brand {
  font-size: calc(1rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-right: auto; /* pushes everything after it to the right side */
  white-space: nowrap;
}

.menu__item {
  /* Reset the browser's ugly default button styling */
  appearance: none;
  border: none;
  background: none;
  font-family: inherit;
  font-size: calc(0.875rem * var(--font-scale));
  color: var(--text-muted);
  padding: 0.5rem 0.875rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
  white-space: nowrap;
}

.menu__item:hover {
  color: var(--text);
  background-color: var(--surface-alt);
}

/* aria-current is set by JS on the active screen's menu item. Styling the
   ARIA attribute rather than a CSS class means the visual state and the
   screen-reader state can never drift apart. */
.menu__item[aria-current="page"] {
  color: var(--accent);
  font-weight: 600;
}

/* The A− / A+ text size cluster */
.menu__sizer {
  display: flex;
  align-items: center;
  gap: 0.125rem;
  padding: 0.125rem;
  background-color: var(--surface-alt);
  border-radius: var(--radius-pill);
  margin: 0 0.25rem;
}

.menu__sizer button {
  appearance: none;
  border: none;
  background: none;
  font-family: inherit;
  color: var(--text);
  cursor: pointer;
  width: 30px;
  height: 26px;
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  transition: background-color 0.2s var(--ease);
}

.menu__sizer button:hover {
  background-color: var(--surface);
}

/* Disabled at the min/max end of the scale */
.menu__sizer button:disabled {
  opacity: 0.3;
  cursor: default;
}

.menu__sizer button:first-child { font-size: 0.75rem; }
.menu__sizer button:last-child  { font-size: 1.05rem; }

/* --------------------------------------------------------------------------
   4. SCREENS
   The whole app is one HTML page. Each "screen" is a <section> and JS shows
   exactly one at a time by toggling the hidden attribute. No page reloads,
   no router library.
   -------------------------------------------------------------------------- */
.screen {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 3rem 1.5rem 4rem;
  animation: screen-in 0.35s var(--ease);
}

/* [hidden] normally works on its own, but .screen sets display, which would
   override it. !important guarantees hiding always wins. */
.screen[hidden] {
  display: none !important;
}

@keyframes screen-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* A screen whose content should sit centered in the viewport (the home hero
   and the results screen). Flexbox centering on both axes. */
.screen--centered {
  min-height: calc(100vh - var(--header-height));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding-top: 1.5rem;
}

/* --------------------------------------------------------------------------
   STUDY CHAT
   -------------------------------------------------------------------------- */
.chat-screen {
  min-height: calc(100vh - var(--header-height));
  display: grid;
  place-items: center;
  padding-top: 2rem;
}

.chat-shell {
  width: 100%;
  max-width: 760px;
  display: flex;
  flex-direction: column;
  min-height: min(680px, calc(100vh - 10rem));
}

.chat-intro {
  text-align: center;
  margin: auto auto 2.25rem;
}

.chat-intro__mark,
.chat-avatar {
  display: grid;
  place-items: center;
  color: var(--accent);
  background: var(--accent-soft);
  font-weight: 700;
}

.chat-intro__mark {
  width: 44px;
  height: 44px;
  margin: 0 auto 1rem;
  border-radius: 15px;
  font-size: 1.3rem;
}

.chat-intro h1 { margin-bottom: 0.45rem; }
.chat-intro p { color: var(--text-muted); font-size: calc(1.0625rem * var(--font-scale)); }

.chat-messages {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.chat-message {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  max-width: 82%;
  font-size: calc(0.975rem * var(--font-scale));
}

.chat-message p { padding: 0.8rem 1rem; border-radius: 18px; overflow-wrap: anywhere; }
.chat-message--assistant p { background: var(--surface-alt); border-top-left-radius: 5px; }
.chat-avatar { width: 30px; height: 30px; flex: 0 0 30px; border-radius: 10px; font-size: 0.9rem; }
.chat-message--user { align-self: flex-end; }
.chat-message--user p { color: #fff; background: var(--accent); border-top-right-radius: 5px; }

.chat-composer {
  display: flex;
  align-items: flex-end;
  gap: 0.65rem;
  padding: 0.6rem 0.65rem 0.6rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: var(--shadow);
}

.chat-composer:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.chat-composer textarea { flex: 1; max-height: 160px; resize: none; border: 0; outline: 0; background: transparent; color: var(--text); font: inherit; line-height: 1.45; padding: 0.5rem 0; }
.chat-composer textarea::placeholder { color: var(--text-muted); }
.chat-send { appearance: none; border: 0; width: 36px; height: 36px; flex: 0 0 36px; border-radius: 12px; color: #fff; background: var(--accent); font: inherit; font-size: 1.35rem; line-height: 1; cursor: pointer; }
.chat-send:hover { background: var(--accent-hover); }
.chat-send:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.chat-disclaimer { margin-top: 0.7rem; color: var(--text-muted); font-size: calc(0.75rem * var(--font-scale)); text-align: center; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* --------------------------------------------------------------------------
   5. TYPOGRAPHY
   Tight negative letter-spacing on large text is the strongest single trick
   for making headings look designed rather than default.
   -------------------------------------------------------------------------- */
h1 {
  font-size: calc(3rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin-bottom: 0.75rem;
}

h2 {
  font-size: calc(1.75rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin-bottom: 0.5rem;
}

h3 {
  font-size: calc(1.125rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 0.375rem;
}

.subtitle {
  font-size: calc(1.1875rem * var(--font-scale));
  color: var(--text-muted);
  max-width: 34ch; /* ch = width of a "0". Capping line length around 34-70
                      characters is the single biggest readability win. */
  margin: 0 auto 2.5rem;
}

.text-muted {
  color: var(--text-muted);
  font-size: calc(0.875rem * var(--font-scale));
}

/* --------------------------------------------------------------------------
   6. BUTTONS
   Big, bold, fully rounded. The pill shape plus a solid accent fill makes it
   unmistakable that these are tappable.
   -------------------------------------------------------------------------- */
.btn {
  appearance: none;
  border: none;
  font-family: inherit;
  font-size: calc(1.0625rem * var(--font-scale));
  font-weight: 600;
  padding: 1rem 2.5rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color 0.25s var(--ease), transform 0.15s var(--ease),
    box-shadow 0.25s var(--ease), opacity 0.25s var(--ease);
  /* Stops a double-tap on mobile from zooming the page instead of clicking */
  touch-action: manipulation;
}

.btn--primary {
  background-color: var(--accent);
  color: #fff;
}

/* The micro-interaction that does the most work: a 1px lift plus a shadow
   that grows. It reads as the button rising toward your cursor. Tiny, fast,
   and it's most of the difference between "styled" and "designed". */
.btn--primary:hover {
  background-color: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 32%, transparent);
}

.btn--secondary {
  background-color: transparent;
  color: var(--accent);
  border: 1px solid var(--border);
}

.btn--secondary:hover {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  transform: translateY(-1px);
}

/* :active fires while the mouse/finger is held down. Dropping the lift and
   shrinking slightly gives the button a physical "press" feel. The shorter
   transition makes the press feel immediate while the release still eases. */
.btn:active {
  transform: scale(0.97);
  box-shadow: none;
  transition-duration: 0.08s;
}

/* Keyboard focus ring. :focus-visible shows it for keyboard users but NOT for
   mouse clicks — so keyboard navigation stays usable without adding visual
   noise for everyone else. */
.btn:focus-visible,
.menu__item:focus-visible,
.answer:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.btn--large {
  font-size: calc(1.1875rem * var(--font-scale));
  padding: 1.125rem 3rem;
}

/* --------------------------------------------------------------------------
   7. QUIZ SCREEN
   -------------------------------------------------------------------------- */

/* Progress bar — a wrapper track with an inner fill whose width JS animates */
.progress {
  height: 6px;
  background-color: var(--surface-alt);
  border-radius: var(--radius-pill);
  overflow: hidden; /* keeps the fill's corners inside the rounded track */
  margin-bottom: 0.75rem;
}

.progress__fill {
  height: 100%;
  width: 0%;
  background-color: var(--accent);
  border-radius: var(--radius-pill);
  transition: width 0.4s var(--ease);
}

.quiz__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 2.5rem;
  font-size: calc(0.875rem * var(--font-scale));
  color: var(--text-muted);
}

.quiz__question {
  font-size: calc(1.875rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  margin-bottom: 2rem;
  /* Long words / URLs in pasted material shouldn't overflow the screen */
  overflow-wrap: break-word;
}

/* Stacked answer list — one full-width button per row, as you chose */
.answers {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-bottom: 2rem;
}

.answer {
  /* Full-width tappable row */
  width: 100%;
  display: flex;
  align-items: center;
  gap: 1rem;
  text-align: left;
  appearance: none;
  font-family: inherit;
  font-size: calc(1.0625rem * var(--font-scale));
  color: var(--text);
  background-color: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.125rem 1.25rem;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease),
    transform 0.15s var(--ease);
  touch-action: manipulation;
}

.answer:hover:not(:disabled) {
  border-color: var(--accent);
  background-color: var(--accent-soft);
}

.answer:active:not(:disabled) {
  transform: scale(0.99);
}

/* The A/B/C/D circle at the left of each answer */
.answer__letter {
  flex-shrink: 0; /* never let the circle squash when text is long */
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background-color: var(--surface-alt);
  color: var(--text-muted);
  font-size: calc(0.8125rem * var(--font-scale));
  font-weight: 600;
  display: grid;
  place-items: center;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.answer__text {
  flex: 1; /* take all remaining width */
  overflow-wrap: break-word;
  min-width: 0; /* lets flex children actually shrink so text can wrap */
}

/* After answering, JS adds .is-correct / .is-wrong and disables the buttons */
.answer:disabled {
  cursor: default;
}

.answer.is-correct {
  border-color: var(--correct);
  background-color: var(--correct-soft);
}

.answer.is-correct .answer__letter {
  background-color: var(--correct);
  color: #fff;
}

.answer.is-wrong {
  border-color: var(--wrong);
  background-color: var(--wrong-soft);
}

.answer.is-wrong .answer__letter {
  background-color: var(--wrong);
  color: #fff;
}

/* Answers that were neither picked nor correct fade back so the eye goes
   straight to the two that matter */
.answer.is-muted {
  opacity: 0.45;
}

/* The explanation panel that slides in after answering */
.feedback {
  border-radius: var(--radius-card);
  padding: 1.125rem 1.25rem;
  margin-bottom: 2rem;
  background-color: var(--surface-alt);
  animation: feedback-in 0.3s var(--ease);
}

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

.feedback__verdict {
  font-weight: 600;
  font-size: calc(1rem * var(--font-scale));
  margin-bottom: 0.25rem;
}

.feedback--correct .feedback__verdict { color: var(--correct); }
.feedback--wrong   .feedback__verdict { color: var(--wrong); }

.feedback__explanation {
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--text-muted);
  overflow-wrap: break-word;
}

/* Right-aligned Next / See results button */
.quiz__actions {
  display: flex;
  justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   8. RESULTS SCREEN
   -------------------------------------------------------------------------- */
.score {
  font-size: calc(4.5rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--accent);
  margin-bottom: 0.25rem;
}

.results__actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 2rem;
}

/* Per-question review list */
.review {
  width: 100%;
  text-align: left;
  margin-top: 3.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.review__item {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.125rem 1.25rem;
  /* A colored left edge gives an at-a-glance right/wrong scan without
     needing to read anything */
  border-left: 4px solid var(--border);
}

.review__item--correct { border-left-color: var(--correct); }
.review__item--wrong   { border-left-color: var(--wrong); }

.review__question {
  font-weight: 600;
  font-size: calc(1rem * var(--font-scale));
  margin-bottom: 0.5rem;
  overflow-wrap: break-word;
}

.review__line {
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--text-muted);
  overflow-wrap: break-word;
}

.review__line strong {
  color: var(--text);
  font-weight: 500;
}

/* --------------------------------------------------------------------------
   9. AUTH — login, sign up, and guest mode
   -------------------------------------------------------------------------- */

/* The stack of choices on the home screen: Create Account / Log In / Guest.
   Constraining the width keeps them from stretching into ugly wide bars on a
   desktop monitor. */
.auth-choices {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
  max-width: 22rem;
  margin: 0 auto;
}

.auth-choices .btn {
  width: 100%;
}

/* "Continue as guest" is deliberately the quietest option on the screen —
   a plain text link rather than a button. Visual weight communicates which
   path we actually recommend without needing a sentence to say so. */
.link-button {
  appearance: none;
  border: none;
  background: none;
  font-family: inherit;
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--accent);
  cursor: pointer;
  padding: 0.75rem;
  border-radius: var(--radius-input);
  transition: background-color 0.2s var(--ease);
}

.link-button:hover {
  background-color: var(--accent-soft);
}

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

/* A small print note under the guest option */
.auth-note {
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
  max-width: 24rem;
  margin: 0.25rem auto 0;
  line-height: 1.4;
}

/* --- The login / sign up form --- */
.auth-form {
  width: 100%;
  max-width: 22rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  text-align: left;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.field label {
  font-size: calc(0.8125rem * var(--font-scale));
  font-weight: 600;
  color: var(--text-muted);
}

.field input {
  font-family: inherit;
  /* 16px minimum on mobile — anything smaller makes iOS Safari zoom the page
     in when the field is focused, which is jarring and hard to undo. */
  font-size: max(16px, calc(1rem * var(--font-scale)));
  color: var(--text);
  background-color: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-input);
  padding: 0.875rem 1rem;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
  width: 100%;
}

.field input:focus {
  outline: none; /* replaced by the ring below, which matches our accent */
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.field input::placeholder {
  color: var(--text-muted);
  opacity: 0.7;
}

/* Message strip under the form — used for both errors and successes, with
   the modifier class deciding the color. */
.auth-message {
  font-size: calc(0.875rem * var(--font-scale));
  padding: 0.75rem 1rem;
  border-radius: var(--radius-input);
  line-height: 1.4;
  animation: feedback-in 0.25s var(--ease);
}

.auth-message--error {
  background-color: var(--wrong-soft);
  color: var(--wrong);
}

.auth-message--success {
  background-color: var(--correct-soft);
  color: var(--correct);
}

.auth-message--info {
  background-color: var(--surface-alt);
  color: var(--text-muted);
}

/* The "Don't have an account? Sign up" line under the form */
.auth-switch {
  text-align: center;
  font-size: calc(0.875rem * var(--font-scale));
  color: var(--text-muted);
  margin-top: 0.25rem;
}

.auth-switch .link-button {
  padding: 0.25rem 0.375rem;
  font-size: inherit;
}

/* A button that's mid-request. Dimmed and unclickable so the form can't be
   submitted twice while the first attempt is still in flight. */
.btn:disabled,
.btn.is-loading {
  opacity: 0.6;
  cursor: default;
}

/* --------------------------------------------------------------------------
   10. CARDS
   -------------------------------------------------------------------------- */
.card {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 2rem;
  box-shadow: var(--shadow);
  text-align: center;
  max-width: 34rem;
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   11. HOME SCREEN ANIMATION
   --------------------------------------------------------------------------
   The whole trick to making motion look professional is restraint: short
   (under ~450ms), small travel (~14px, not half the screen), and a slight
   stagger so elements arrive in sequence instead of all at once. Anything
   that bounces, spins, or slides in from off-screen reads as amateur.
   -------------------------------------------------------------------------- */

/* Elements marked with this class start invisible and slightly low, then
   animate into place. `both` fill mode is what keeps them hidden during the
   delay — without it they'd flash at full opacity before the delay elapses. */
.rise {
  opacity: 0;
  animation: rise-in 0.55s var(--ease) both;
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* The stagger. Each step is 80ms — long enough to read as a sequence, short
   enough that the whole cascade finishes in about half a second. */
.rise--1 { animation-delay: 0.00s; }
.rise--2 { animation-delay: 0.08s; }
.rise--3 { animation-delay: 0.16s; }
.rise--4 { animation-delay: 0.24s; }
.rise--5 { animation-delay: 0.32s; }
.rise--6 { animation-delay: 0.40s; }

/* --------------------------------------------------------------------------
   12. THE DEMO CARD
   A small mock quiz that answers itself on a loop, so a first-time visitor
   understands the product without reading anything.
   -------------------------------------------------------------------------- */
.demo {
  width: 100%;
  max-width: 25rem;
  margin: 3.5rem auto 0;
  text-align: left;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lifted);
  overflow: hidden;
  /* Not interactive — it's a picture that moves. Without this, the cursor
     would change over it and people would try to click the fake answers. */
  pointer-events: none;
  user-select: none;
}

/* The three dots along the top. A tiny visual cue that says "this is a
   screen, not a real control you should be poking at." */
.demo__chrome {
  display: flex;
  gap: 0.375rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  background-color: var(--surface-alt);
}

.demo__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: var(--border);
}

.demo__body {
  padding: 1.25rem;
}

.demo__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: calc(0.75rem * var(--font-scale));
  color: var(--text-muted);
  margin-bottom: 0.875rem;
}

.demo__track {
  width: 72px;
  height: 4px;
  background-color: var(--surface-alt);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.demo__fill {
  height: 100%;
  width: 0%;
  background-color: var(--accent);
  border-radius: var(--radius-pill);
  transition: width 0.6s var(--ease);
}

.demo__question {
  font-size: calc(1.0625rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin-bottom: 1rem;
  min-height: 2.6em; /* reserves space so shorter questions don't make the
                        card jump in height between loops */
}

.demo__options {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.demo__option {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--text);
  background-color: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-input);
  padding: 0.625rem 0.75rem;
  transition: border-color 0.35s var(--ease), background-color 0.35s var(--ease),
    opacity 0.35s var(--ease), transform 0.35s var(--ease);
}

/* The little circle that becomes a checkmark */
.demo__bullet {
  flex-shrink: 0;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  display: grid;
  place-items: center;
  font-size: 10px;
  color: transparent; /* the checkmark is there but invisible until correct */
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease),
    color 0.35s var(--ease);
}

/* The brief moment where the answer is "being considered", just before it
   resolves. This half-second of hesitation is what makes it feel like
   someone is using the app rather than a slideshow advancing. */
.demo__option.is-considering {
  border-color: var(--accent);
  background-color: var(--accent-soft);
}

.demo__option.is-correct {
  border-color: var(--correct);
  background-color: var(--correct-soft);
}

.demo__option.is-correct .demo__bullet {
  background-color: var(--correct);
  border-color: var(--correct);
  color: #fff;
}

.demo__option.is-dimmed {
  opacity: 0.4;
}

/* Options fade up one after another as the "question loads" */
.demo__option.is-entering {
  animation: rise-in 0.4s var(--ease) both;
}

/* --------------------------------------------------------------------------
   REDUCED MOTION
   Some people get motion sickness from animation, and their OS has a setting
   to say so. We honor it: the demo card still shows a fully answered
   question, it just stops moving. The information survives; the motion goes.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .rise,
  .demo__option.is-entering {
    animation: none;
    opacity: 1;
    transform: none;
  }

  .btn:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   13. RESPONSIVE
   Only two breakpoints. Everything above scales fluidly because it's built
   from flexbox and relative units rather than fixed pixel widths.
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .screen {
    padding: 2rem 1.25rem 3rem;
  }

  h1 { font-size: calc(2.25rem * var(--font-scale)); }

  .quiz__question { font-size: calc(1.5rem * var(--font-scale)); }

  .score { font-size: calc(3.5rem * var(--font-scale)); }

  .subtitle { font-size: calc(1.0625rem * var(--font-scale)); }

  /* Full-width buttons are much easier to hit with a thumb */
  .btn--large,
  .results__actions .btn {
    width: 100%;
  }

  .quiz__actions .btn { width: 100%; }
}

@media (max-width: 600px) {
  .menu {
    padding: 0 0.875rem;
    gap: 0;
  }

  .menu__brand {
    /* Hide the "Smart Study AI" wordmark so the four controls always fit */
    font-size: calc(0.9375rem * var(--font-scale));
  }

  .menu__item {
    padding: 0.5rem 0.625rem;
    font-size: calc(0.8125rem * var(--font-scale));
  }
}

/* --------------------------------------------------------------------------
   CHAT — generated quiz results
   The composer now holds a question-count picker alongside the send button,
   and assistant replies can carry a button plus explanatory notes.
   -------------------------------------------------------------------------- */

.chat-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* The bubble body wraps text plus any buttons, so they stack tidily. */
.chat-message__body {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  min-width: 0; /* lets long pasted text wrap instead of stretching the bubble */
}

.chat-start {
  align-self: flex-start;
}

.chat-note {
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
}

.chat-error {
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--wrong);
}

/* A disabled composer while a request is in flight, so it's obvious that
   pressing send again won't help. */
.chat-composer textarea:disabled,
.chat-send:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* The chip that says what a follow-up message will do. */

/* Setting display on an element that also uses the `hidden` attribute breaks
   hidden, because a display rule outranks the browser's built-in
   [hidden] { display: none }. This restores it. Any element in this file that
   JS toggles with .hidden needs the same guard. */
.chat-context[hidden] {
  display: none;
}

.chat-context {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
  background-color: var(--surface-alt);
  border-radius: var(--radius-pill);
  padding: 0.4rem 0.5rem 0.4rem 0.9rem;
  margin-bottom: 0.5rem;
}

/* --------------------------------------------------------------------------
   LANDING PAGE
   The first screen a new visitor sees. Same restraint as the rest of the app:
   one accent colour, generous space, no gradients or emoji.
   -------------------------------------------------------------------------- */
.landing {
  max-width: 60rem;
  margin: 0 auto;
  padding: 4rem 1.5rem 5rem;
  text-align: center;
}

/* Small capsule above the title. */
.landing__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: calc(0.75rem * var(--font-scale));
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  background-color: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.375rem 0.875rem;
  margin-bottom: 1.75rem;
}

.landing__badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--accent);
}

.landing__title {
  font-size: calc(3.25rem * var(--font-scale));
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
  margin-bottom: 1rem;
}

.landing__tagline {
  font-size: calc(1.1875rem * var(--font-scale));
  color: var(--text-muted);
  max-width: 32rem;
  margin: 0 auto 2.5rem;
  line-height: 1.5;
}

.landing__cta {
  margin-bottom: 4rem;
}

/* Feature cards. Column counts are set explicitly at each breakpoint further
   down, so all four always fill their row. */
.landing__features {
  list-style: none;
  display: grid;
  /* Fixed counts, not auto-fit: with exactly four cards auto-fit lands on
     three columns at most desktop widths and orphans the fourth on a row
     of its own. Explicit steps keep every row full. */
  grid-template-columns: 1fr;
  gap: 1rem;
  text-align: left;
  margin-bottom: 3rem;
}

.feature {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.5rem;
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease),
    box-shadow 0.25s var(--ease);
}

.feature:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

.feature h3 {
  font-size: calc(1rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
}

.feature p {
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--text-muted);
  line-height: 1.5;
}

.landing__note {
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
}

/* The staggered entrance, reused from the old home screen. */
.rise {
  opacity: 0;
  animation: rise-in 0.55s var(--ease) both;
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

.rise--1 { animation-delay: 0.00s; }
.rise--2 { animation-delay: 0.08s; }
.rise--3 { animation-delay: 0.16s; }
.rise--4 { animation-delay: 0.24s; }
.rise--5 { animation-delay: 0.32s; }
.rise--6 { animation-delay: 0.40s; }

@media (prefers-reduced-motion: reduce) {
  .rise { animation: none; opacity: 1; transform: none; }
  .feature:hover { transform: none; }
}

@media (max-width: 600px) {
  .landing { padding: 2.5rem 1.25rem 3rem; }
  .landing__title { font-size: calc(2.25rem * var(--font-scale)); }
}

/* --------------------------------------------------------------------------
   VOID FIELD
   The three.js particle canvas behind the landing page. Sits underneath the
   content and ignores the pointer, so it can never intercept a click.
   -------------------------------------------------------------------------- */
.landing {
  position: relative; /* makes this the anchor the canvas positions against */
  z-index: 0;
}

.constellation {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.constellation canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* Keep the landing content above the canvas. */
.landing > *:not(.constellation) {
  position: relative;
  z-index: 1;
}

/* Choice buttons inside an assistant reply. */
.chat-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.chat-choice {
  font-size: calc(0.875rem * var(--font-scale));
  padding: 0.5rem 1rem;
}

.quiz__meta-right {
  display: flex;
  align-items: center;
  gap: 0.875rem;
}

.quiz__shuffle {
  appearance: none;
  font: inherit;
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.25rem 0.75rem;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}

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

/* Chat replies are inserted as plain text, so newlines need preserving or a
   multi-paragraph answer collapses into one run-on line. pre-wrap keeps line
   breaks while still wrapping long lines normally. */
.chat-message__body p {
  white-space: pre-wrap;
}

/* --------------------------------------------------------------------------
   QUIZ — list layout
   Every question on the page at once, answerable in any order.
   -------------------------------------------------------------------------- */

/* The bar stays put while you scroll a long quiz, so the score and Submit are
   always one glance away. */
.quiz__bar {
  position: sticky;
  top: var(--header-height);
  z-index: 50;
  background-color: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--border);
  margin-bottom: 2rem;
}

.quiz__bar-inner {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0.875rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: calc(0.875rem * var(--font-scale));
  color: var(--text-muted);
}

.quiz__submit {
  padding: 0.5rem 1.25rem;
  font-size: calc(0.875rem * var(--font-scale));
}

.questions {
  list-style: none;
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.qcard {
  position: relative;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.5rem 1.5rem 1.5rem 3.75rem;
  transition: border-color 0.25s var(--ease);
}

/* The number sits in the padding gutter, so long question text wraps cleanly
   underneath itself instead of around the number. */
.qcard__number {
  position: absolute;
  left: 1.25rem;
  top: 1.5rem;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background-color: var(--surface-alt);
  color: var(--text-muted);
  font-size: calc(0.8125rem * var(--font-scale));
  font-weight: 600;
  display: grid;
  place-items: center;
}

.qcard__text {
  font-size: calc(1.0625rem * var(--font-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.4;
  margin-bottom: 1rem;
}

.qcard.is-revealed {
  border-color: color-mix(in srgb, var(--text-muted) 40%, transparent);
}

/* The option you picked, before any right/wrong is shown. This is what makes
   "answer now, find out later" mode legible — otherwise you cannot tell which
   ones you have already done. */
.answer.is-chosen {
  border-color: var(--accent);
  background-color: var(--accent-soft);
}

.answer.is-correct {
  border-color: var(--correct);
  background-color: var(--correct-soft);
}

.answer.is-wrong {
  border-color: var(--wrong);
  background-color: var(--wrong-soft);
}

.answer:disabled {
  cursor: default;
}

.quiz__actions {
  max-width: var(--content-width);
  margin: 2.5rem auto 4rem;
  padding: 0 1.5rem;
  display: flex;
  justify-content: center;
}

/* Results — only the questions that were missed. */
.review__item {
  text-align: left;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.25rem;
  margin-bottom: 1rem;
}

.review__question { font-weight: 600; margin-bottom: 0.625rem; }
.review__yours    { color: var(--wrong); font-size: calc(0.9375rem * var(--font-scale)); }
.review__correct  { color: var(--correct); font-size: calc(0.9375rem * var(--font-scale)); }
.review__why      { color: var(--text-muted); font-size: calc(0.9375rem * var(--font-scale)); margin-top: 0.5rem; }

@media (max-width: 600px) {
  .qcard { padding: 1.25rem 1rem 1.25rem 3.25rem; }
  .qcard__number { left: 0.875rem; top: 1.25rem; }
  .quiz__bar-inner { padding: 0.75rem 1rem; flex-wrap: wrap; }
}

/* --------------------------------------------------------------------------
   LANDING HERO — dark treatment
   The particle scene uses additive blending, where overlapping points brighten
   each other. That only reads as a glow against something dark, so the landing
   is dark in both light and dark mode. The rest of the app still follows the
   system setting; this one screen is deliberately its own thing.
   -------------------------------------------------------------------------- */
.landing {
  background-color: #05070d;
  color: #f5f7fa;
  /* Cover the full viewport under the sticky header so there's no pale strip
     at the bottom on short pages. */
  min-height: calc(100vh - var(--header-height));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: 3rem;
  padding-bottom: 3rem;
}

.landing .landing__title {
  color: #ffffff;
  /* Slightly tighter and heavier than the app default — at this size on black
     it otherwise reads as thin. */
  font-weight: 700;
  letter-spacing: -0.035em;
}

.landing .landing__tagline,
.landing .landing__note {
  color: #9aa7bd;
}

.landing .landing__badge {
  color: #93a7c4;
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.1);
}

.landing .landing__badge-dot {
  background-color: var(--accent);
}

/* Cards read as glass over the scene rather than solid blocks.
   No backdrop-filter: it was written when the canvas ran the full height of
   the landing, but the canvas is the hero only now, so what sits behind these
   cards is a flat dark background. Blurring a flat colour returns the same
   flat colour — it cost four blurred layers, recomputed as the page scrolls
   beneath them, to change nothing on screen. */
.landing .feature {
  background-color: rgba(255, 255, 255, 0.035);
  border-color: rgba(255, 255, 255, 0.09);
}

.landing .feature:hover {
  border-color: rgba(255, 255, 255, 0.22);
  background-color: rgba(255, 255, 255, 0.05);
}

.landing .feature h3 { color: #eaf2ff; }
.landing .feature p  { color: #93a3ba; }

/* No glow. A halo around the button was the loudest thing left on the page,
   and buttons in serious software don't emit light. */
.landing .btn--primary {
  background-color: var(--accent);
  color: #ffffff;
  font-weight: 600;
  box-shadow: none;
}

.landing .btn--primary:hover {
  background-color: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4);
}

/* A vignette so the text always has contrast, however bright the particles
   behind it happen to be at that moment. */
.landing::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse at 50% 42%,
    rgba(5, 7, 13, 0.9) 0%,
    rgba(5, 7, 13, 0.7) 32%,
    rgba(5, 7, 13, 0.25) 55%,
    rgba(5, 7, 13, 0) 78%
  );
}

/* Fallback when the scene can't run (no WebGL, or reduced motion): a static
   gradient, so the landing still looks deliberate rather than plain black. */


/* --------------------------------------------------------------------------
   LANDING — hero gets the screen to itself
   The particle bust needs empty space to be legible. Cards sitting on top of
   it hid the head entirely, so the hero now fills the viewport and the cards
   sit below it.
   -------------------------------------------------------------------------- */
.landing {
  display: block;          /* was flex-centred; the two blocks now stack */
  padding-top: 0;
  padding-bottom: 0;
  min-height: auto;
}

.landing__hero {
  position: relative;
  z-index: 1;
  min-height: calc(100vh - var(--header-height));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem 4rem;
  /* Sit the text in the upper half, leaving the lower half for the shoulders
     to sweep through unobstructed. */
  padding-bottom: 22vh;
}

.landing__below {
  position: relative;
  z-index: 1;
  padding: 0 1.5rem 4rem;
}

/* The canvas covers the whole landing section, hero and cards alike. */
.constellation {
  position: absolute;
  inset: 0;
  z-index: 0;
}

@media (max-width: 600px) {
  .landing__hero {
    min-height: calc(100svh - var(--header-height));
    padding-bottom: 18vh;
  }
}

/* Back-to-chat button in the quiz bar. */
.quiz__bar-left {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  min-width: 0;
}

.quiz__back {
  appearance: none;
  font: inherit;
  font-size: calc(0.8125rem * var(--font-scale));
  color: var(--text-muted);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.25rem 0.75rem;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}

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

/* --------------------------------------------------------------------------
   GRADIENT RING HERO
   The canvas paints the headline itself, so the hero content sits lower and
   the ring gets the middle of the screen.
   -------------------------------------------------------------------------- */
.constellation canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* The headline is ordinary HTML again, so the hero is a normal centred stack. */
.landing__hero {
  justify-content: center;
  padding-bottom: 4rem;
}

.landing__hero .landing__tagline {
  max-width: 34rem;
}

/* Visually hidden but still read aloud and indexed — the page must have a
   real <h1>, even though the visible one is painted on canvas. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The canvas fills the hero's height only, not the whole scrollable landing —
   but it breaks out of the 60rem text column so the field reaches both edges
   of the screen instead of stopping short on a wide monitor.

   The landing is the one screen that runs edge to edge. Every other screen is
   capped at a readable column by .screen, and that cap was cutting the field
   off at 960px on a wide monitor. Rather than break the canvas out with 100vw
   — which counts the scrollbar and left the page scrollable 8px sideways — the
   cap moves off the section and onto the content inside it. The canvas can
   then just fill the hero, and the hero is the width of the display. */
.landing {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}

/* The cards keep the readable column the section gave up. The hero doesn't
   need one: its children are already centred and individually capped. */
.landing__below {
  max-width: 60rem;
  margin-left: auto;
  margin-right: auto;
}

.landing__hero { position: relative; }

.landing__hero > .constellation {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.landing__hero > *:not(.constellation) { position: relative; z-index: 1; }

/* The background is faint now, so the tagline needs no shadow to survive it. */
.landing__hero .landing__tagline {
  color: #9aa7bd;
}

/* --------------------------------------------------------------------------
   HEADER OVER THE LANDING
   The landing is dark in both themes. In light mode the header would
   otherwise be a white bar sitting on top of a black page.
   -------------------------------------------------------------------------- */
.on-landing .menu {
  background-color: rgba(5, 7, 13, 0.72);
  border-bottom-color: rgba(255, 255, 255, 0.08);
}

.on-landing .menu__brand { color: #f1f5fb; }

.on-landing .menu__item { color: #93a2b8; }

.on-landing .menu__item:hover {
  color: #ffffff;
  background-color: rgba(255, 255, 255, 0.07);
}

.on-landing .menu__item[aria-current="page"] { color: #ffffff; }

.on-landing .menu__sizer {
  background-color: rgba(255, 255, 255, 0.07);
}

.on-landing .menu__sizer button { color: #e6ecf5; }

.on-landing .menu__sizer button:hover {
  background-color: rgba(255, 255, 255, 0.12);
}

/* The page ends where the landing ends, so match the page behind it — without
   this a pale strip shows under the dark section while scrolling past. */
.on-landing {
  background-color: #05070d;
}

/* On a real phone the five controls plus the wordmark need more room than a
   375px screen has (they total ~443px even after the 600px tightening above).
   The hero already says "Smart Study AI" in 40px type, so the wordmark is the
   one thing here that can go without costing the user anything. */
@media (max-width: 540px) {
  .menu {
    padding: 0 0.75rem;
    justify-content: space-between;
  }

  .menu__brand { display: none; }

  .menu__item {
    padding: 0.5rem 0.5rem;
  }

  .menu__sizer { margin: 0; }

  .menu__sizer button {
    width: 26px;
    height: 24px;
  }
}

/* Feature cards: 1 → 2 → 4 across, so the four cards always fill their row.
   Written mobile-first (min-width) to match the fixed base of 1fr above. */
@media (min-width: 560px) {
  .landing__features { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1000px) {
  .landing__features { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   SIGN IN UNDER THE HERO BUTTON
   Quieter than "Start studying" on purpose — signing in is the secondary
   path, and a second loud button beside the first makes neither one read as
   the thing to do.
   -------------------------------------------------------------------------- */
/* Signing in is the quieter of the two, so it's a line of text rather than a
   second button — one clear primary action, with the alternative underneath. */
.landing__signin {
  margin: 1.25rem 0 0;
  font-size: calc(0.9375rem * var(--font-scale));
  color: var(--text-muted);
}

.landing__signin .link-button {
  /* Tight enough to read as part of the sentence rather than a control. */
  padding: 0.125rem 0.375rem;
  font-size: inherit;
  font-weight: 600;
  position: relative;
}

/* That tight padding leaves a 22px-tall tap target, half what a thumb needs.
   An invisible overlay grows the hit area to 44px without moving anything or
   inflating the hover pill. The gap to the button above is 20px, so it can't
   swallow taps meant for "Create an account". */
.landing__signin .link-button::after {
  content: "";
  position: absolute;
  inset: -11px -4px;
}

/* The landing is dark in both themes, so the muted grey and accent chosen for
   light backgrounds would both nearly vanish here. */
.on-landing .landing__signin { color: #93a2b8; }

.on-landing .landing__signin .link-button { color: #5aa9ff; }

.on-landing .landing__signin .link-button:hover {
  background-color: rgba(90, 169, 255, 0.14);
}

/* This whole block is hidden for signed-in users, and .landing__cta has no
   display rule of its own — but state it, so a future layout change here
   can't silently defeat [hidden]. */
.landing__cta[hidden] { display: none; }

/* The Account item is hidden for guests now that signing in lives on the
   landing. Buttons aren't display:flex, but a stray display rule elsewhere
   would silently defeat [hidden], so state it. */
.menu__item[hidden] { display: none; }

/* --------------------------------------------------------------------------
   NO ACCIDENTAL SELECTION IN THE HERO
   The canvas is pointer-events: none so it can never swallow a click on the
   button. That means a drag across it lands on the text underneath, and
   moving the mouse to play with the field highlighted the headline in blue.

   Suppressing selection here costs only the ability to drag-select marketing
   copy, which nobody needs. The text is still ordinary HTML — user-select
   affects the mouse alone, so screen readers and search engines are unchanged.
   Scoped to the hero: quiz questions and chat replies stay selectable, since
   copying those is a real thing to want.
   -------------------------------------------------------------------------- */
.landing__hero {
  -webkit-user-select: none; /* Safari, including iOS */
  user-select: none;

  /* A tap shouldn't flash a grey highlight box over the hero. */
  -webkit-tap-highlight-color: transparent;

  /* iOS shows its own selection UI on a press-and-hold — the magnifier and
     the Copy/Look Up bar — and it fires on the hero text before the finger
     has moved far enough to count as a drag. Pressing to play with the field
     kept summoning it. user-select above stops the selection itself; this is
     the separate switch for the callout. */
  -webkit-touch-callout: none;

  /* touch-action: none was tried, on the reasoning that a click-drag needs
     every direction free. It broke worse: the hero measures TALLER than the
     viewport on a real phone (788px hero in an 844px screen, bottom edge at
     852px) — meaning the hero already covers the ENTIRE visible screen on
     load. With the whole visible area off-limits to panning, there was no
     square inch left to start a scroll from. Not a tuning problem — a trap,
     confirmed by measuring hero height against viewport height directly.

     Scrolling has to win, unconditionally — a page that won't scroll is a
     broken page under any interpretation, however the decoration behaves.
     touch-action stays pan-y: a short press still reaches lines toward the
     touch point (see js/constellation.js) until the drag travels far enough
     for the browser to claim it as a scroll, same as a light touch does on
     desktop before you move away. Continuous full-screen drag control of the
     field isn't achievable on a phone at the same time as a guaranteed
     ability to scroll away from a hero that size — they are the same
     gesture. That's a real product trade-off, not a bug to keep patching. */
  touch-action: pan-y;
}

/* The third and quietest option on the landing: no account at all. Smaller and
   greyer than the sign-in line above it, so the order of preference reads
   top to bottom without any of the three being hidden. */
.landing__guest {
  margin: 0.5rem 0 0;
  font-size: calc(0.875rem * var(--font-scale));
}

.landing__guest .link-button {
  padding: 0.125rem 0.375rem;
  font-size: inherit;
  font-weight: 500;
  color: var(--text-muted);
  position: relative;
}

/* Same 44px hit area as the sign-in link — the visible text is only ~20px
   tall, which is fine for a mouse and awkward for a thumb. */
.landing__guest .link-button::after {
  content: "";
  position: absolute;
  inset: -12px -4px;
}

.on-landing .landing__guest .link-button { color: #7d8ba1; }

.on-landing .landing__guest .link-button:hover {
  color: #cfe0f5;
  background-color: rgba(255, 255, 255, 0.07);
}

/* The header is translucent with a 20px blur so content stays visible sliding
   under it. Over the landing that blur sits directly on top of a canvas that
   repaints every frame, so the browser has to re-run it every frame too — a
   full-width gaussian blur, 60 times a second, on a phone.

   On the landing the bar is near-black over a near-black page, so the blur is
   buying nothing you can see. Making it opaque there drops both the blur and
   the need to composite the canvas underneath it. Every other screen keeps
   the translucent treatment. */
.on-landing .menu {
  background-color: #05070d;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* --------------------------------------------------------------------------
   MY FILES — saved quizzes
   -------------------------------------------------------------------------- */
.file-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 40rem;
  margin: 0 auto;
}

.file-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.25rem 1.5rem;
  text-align: left;
}

.file-card__info h3 {
  font-size: calc(1.0625rem * var(--font-scale));
  margin-bottom: 0.25rem;
}

.file-card__info p {
  font-size: calc(0.875rem * var(--font-scale));
}

.file-card__actions {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* A smaller footprint than the standard pill button, for actions that sit
   inside a list row rather than standing alone. */
.btn--small {
  padding: 0.5rem 1rem;
  font-size: calc(0.8125rem * var(--font-scale));
}

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

.btn--danger:hover {
  background-color: color-mix(in srgb, var(--wrong) 12%, transparent);
  border-color: var(--wrong);
}

@media (max-width: 480px) {
  .file-card { flex-direction: column; align-items: stretch; }
  .file-card__actions { justify-content: flex-end; }
}
