/* app/styles/app.css — Math Driller student UI. Light theme, no framework.
   Indigo accent, teal secondary, 12px cards, 44px touch targets for iPads. */

:root {
  --ink:        #111827;
  --ink-soft:   #4b5563;
  --ink-faint:  #6b7280;
  --line:       #e5e7eb;
  --line-soft:  #f1f2f6;
  --paper:      #ffffff;
  --bg:         #f6f7fb;

  --accent:     #4f46e5;
  --accent-dk:  #4338ca;
  --accent-bg:  #eef2ff;
  --teal:       #0f766e;
  --teal-bg:    #f0fdfa;

  --ok:         #15803d;
  --warn:       #b45309;
  --bad:        #b91c1c;

  --radius:     12px;
  --shadow:     0 1px 2px rgba(17, 24, 39, .05), 0 4px 16px rgba(17, 24, 39, .06);
  --tap:        44px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 16px/1.5 var(--font);
  color: var(--ink);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 { margin: 0; font-weight: 650; line-height: 1.25; }
p { margin: 0; }
.wrap { width: 100%; max-width: 860px; margin: 0 auto; padding: 0 16px; }
.muted { color: var(--ink-faint); }
[hidden] { display: none !important; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* --------------------------------------------------------------- chrome */

.app-header { background: var(--paper); border-bottom: 1px solid var(--line); }
.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 14px 0;
}
.brand-title { font-size: 1.3rem; letter-spacing: -.01em; }
.brand-sub { font-size: .85rem; color: var(--ink-faint); }
.teacher-link {
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--teal-bg);
  color: var(--teal);
  font-size: .9rem;
  font-weight: 600;
  text-decoration: none;
}
.teacher-link:hover { text-decoration: underline; }

#main { padding-top: 20px; padding-bottom: 88px; }
.app-footer { padding: 18px 0 28px; font-size: .8rem; color: var(--ink-faint); text-align: center; }

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.badge, .chip {
  display: inline-block;
  border-radius: 999px;
  font-weight: 650;
  white-space: nowrap;
}
.badge { padding: 2px 8px; background: var(--accent-bg); color: var(--accent-dk); font-size: .74rem; }
/* "Notes" link in a topic header (skill-picker.js, Topic.notes) — a small
   outlined chip so it reads as a door out of the picker, not as a badge. */
.topic-notes { margin-left: auto; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--accent); color: var(--accent-dk);
  font-size: .76rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
.topic-notes:hover { background: var(--accent); color: #fff; }
.topic-notes::after { content: ' \2192'; }
.chip {
  padding: 4px 10px;
  background: var(--line-soft);
  color: var(--ink-soft);
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
}
.chip-score { background: var(--teal-bg); color: #0f766e; }
.chip-streak.is-hot { background: #fff7ed; color: var(--warn); }

/* -------------------------------------------------------------- buttons */

.btn {
  min-height: var(--tap);
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: 10px;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
  background: var(--line-soft);
  color: var(--ink);
}
.btn:hover { filter: brightness(.97); }
.btn:disabled { opacity: .55; cursor: default; }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-dk); filter: none; }
/* The quiet primary-sized button. "Show answer" has to be as easy to hit as
   "Try again" — same height, same target — while reading as the smaller of the
   two choices, because it is the one that ends the question. Outline, not
   colour: a second filled button beside the first makes the pair a coin toss. */
.btn-ghost {
  background: var(--paper);
  color: var(--ink-soft);
  box-shadow: inset 0 0 0 1px var(--line);
}
.btn-ghost:hover { background: var(--line-soft); color: var(--ink); filter: none; }
.btn-start { background: var(--accent-bg); color: var(--accent-dk); white-space: nowrap; }
.btn-start:hover { background: var(--accent); color: #fff; }

.linkish {
  min-height: var(--tap);
  padding: 8px 4px;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.linkish:hover { text-decoration: underline; }
.linkish.subtle { color: var(--ink-faint); font-weight: 500; font-size: .9rem; }

/* "← Change skill" — the in-app back affordance, and the twin of the site
   chrome's "← Main menu". It sits on the page background (not on a card), so
   an accent TINT would be invisible there (#eef2ff on #f6f7fb is 1.04:1);
   the outline is what makes it read as a button. Secondary on purpose:
   filling it solid indigo would out-shout "Check", the real primary. */
.btn-back {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 8px 14px;
  border: 2px solid var(--accent);
  border-radius: 10px;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(17, 24, 39, .06);
  font: inherit;
  font-weight: 650;
  color: var(--accent-dk);
  cursor: pointer;
  white-space: nowrap;
}
.btn-back:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Deep link to a slug that is not a skill: say so instead of a blank picker. */
.route-note {
  margin-bottom: 14px;
  padding: 12px 14px;
  border: 1px solid #fde68a;
  border-left: 4px solid var(--warn);
  border-radius: 10px;
  background: #fffbeb;
  color: #78350f;
  font-size: .92rem;
}

/* --------------------------------------------------------- skill picker */

.picker-intro { margin-bottom: 16px; }
.picker-intro h2 { font-size: 1.15rem; margin-bottom: 4px; }
.picker-intro .muted { font-size: .9rem; max-width: 60ch; }

.level-tabs { display: flex; gap: 6px; margin-bottom: 16px; overflow-x: auto; padding-bottom: 2px; }
.level-tab {
  min-height: var(--tap);
  padding: 8px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  font: inherit;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}
.level-tab.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.level-tab.is-empty { opacity: .45; cursor: not-allowed; }

.topic-card { margin-bottom: 14px; overflow: hidden; }
/* The card a notes page's "Driller" button deep-linked to (?topic=…): marked
   once, on arrival, so the student sees which chapter they landed on. */
.topic-card.is-linked { box-shadow: 0 0 0 3px var(--accent); scroll-margin-top: 12px; }
.topic-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, #fbfbfe, var(--paper));
}
.topic-title { font-size: 1rem; }
.skill-list { display: flex; flex-direction: column; }

.skill-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 14px;
  padding: 12px 16px;
  border-top: 1px solid var(--line-soft);
  cursor: pointer;
}
.skill-row:first-child { border-top: 0; }
.skill-row:hover { background: #fafaff; }
.skill-row.is-last { background: var(--accent-bg); }
.skill-main { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; flex: 1 1 16ch; }
.skill-title { font-weight: 600; }
.skill-tags { font-size: .78rem; color: var(--ink-faint); }
.skill-tags .skill-tag { white-space: nowrap; }
/* Syllabus level pills beside the skill title (skill-picker.js LEVEL_TAG). One
   colour per stream so a row can be read at a glance: indigo = G3 Pure,
   teal = G3 ScChem, amber = G2 ScChem; anything new is neutral grey until it
   gets a rule here. Same hues the score/streak chips already use. */
.skill-levels { display: inline-flex; flex-wrap: wrap; gap: 4px; align-self: center; }
.lvl-pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: .68rem; font-weight: 700;
  letter-spacing: .02em; line-height: 1.5; white-space: nowrap; background: #f3f4f6; color: var(--ink-soft); border: 1px solid #e5e7eb; }
.lvl-pill.lvl-g3-pure { background: var(--accent-bg); color: var(--accent-dk); border-color: #c7d2fe; }
.lvl-pill.lvl-g3-scchem { background: var(--teal-bg); color: var(--teal); border-color: #99f6e4; }
.lvl-pill.lvl-g2-scchem { background: #fff7ed; color: var(--warn); border-color: #fed7aa; }
/* The same two hues for the physics and biology Science streams: teal = G3
   Science, amber = G2 Science, whatever the subject — the stream, not the
   subject, is what the colour tells a student. */
.lvl-pill.lvl-g3-scphy, .lvl-pill.lvl-g3-scbio { background: var(--teal-bg); color: var(--teal); border-color: #99f6e4; }
.lvl-pill.lvl-g2-scphy, .lvl-pill.lvl-g2-scbio { background: #fff7ed; color: var(--warn); border-color: #fed7aa; }
/* Stream filter above the topic cards (skill-picker.js): All + one button per
   level tag the bank carries. The active button takes its stream's pill hue. */
.stream-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: -4px 0 14px; }
.stream-filter__lbl { font-size: .8rem; color: var(--ink-faint); margin-right: 2px; }
.stream-btn { border: 1px solid #e5e7eb; background: #fff; border-radius: 999px; padding: 3px 11px; font-size: .78rem;
  font-weight: 600; color: var(--ink-soft); cursor: pointer; line-height: 1.5; }
.stream-btn:hover { border-color: var(--accent); color: var(--accent-dk); }
.stream-btn.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.stream-btn.is-on.lvl-g3-scchem { background: var(--teal); border-color: var(--teal); }
.stream-btn.is-on.lvl-g2-scchem { background: var(--warn); border-color: var(--warn); }
.stream-btn.is-on.lvl-g3-scphy, .stream-btn.is-on.lvl-g3-scbio { background: var(--teal); border-color: var(--teal); }
.stream-btn.is-on.lvl-g2-scphy, .stream-btn.is-on.lvl-g2-scbio { background: var(--warn); border-color: var(--warn); }
.tag { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--accent-dk); }
.skill-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.tier-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.seg {
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 6px 10px;
  border: 0;
  border-left: 1px solid var(--line);
  background: var(--paper);
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
}
.seg:first-child { border-left: 0; }
.seg:hover { background: var(--line-soft); }
.seg.is-on { background: var(--teal); color: #fff; }

.empty-note { color: var(--ink-faint); padding: 20px 4px; }

/* ---------------------------------------------------------------- drill */

.drill-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.session-stats { display: flex; gap: 6px; }

.drill-head { margin-bottom: 12px; }
.drill-skill { font-size: 1.15rem; }
.drill-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: .85rem;
  color: var(--ink-soft);
}
.drill-meta .muted { font-size: .8rem; }

.question-card { padding: 18px 16px 16px; }
.q-head { margin-bottom: 8px; }
.q-num { font-size: .78rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--accent); }
.stem { font-size: 1.12rem; line-height: 1.7; }
.note { margin-top: 6px; font-size: .86rem; color: var(--ink-faint); }

.answer-slot { margin: 16px 0 14px; }
.actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* ----------------------------------------------------------------- figure
   The diagram, between the stem and the answer input.
   app/components/figure.js writes .fig / .fig__cap; the SVG is self-contained
   (presentation attributes only, hairline black on white), so all this file
   decides is how big it is allowed to be and where it sits.

   BOTH caps matter, and the SVG carries a viewBox, so height:auto lets either
   one drive and the other follow: the picture is always scaled, never cropped
   or distorted.

   max-width keeps a wide archetype inside a narrow phone.

   max-height keeps the answer field and the Check button above the fold on a
   SHORT screen. 490px is what the drill screen costs above and below the
   figure — header, drill bar, heading, stem, answer field, actions — measured,
   not guessed; the rest of the window is the figure's budget. On a 768px-tall
   laptop (viewport ~640px after browser chrome) that budget is 150px and every
   archetype scales to about 0.8; from roughly 730px of viewport upwards the
   budget exceeds the tallest template (241px) and nothing is scaled at all.
   max() only ever SHRINKS a replaced element, so the tall-window case costs
   nothing. The 150px floor stops a phone in landscape reducing the diagram to
   an unreadable smear — there, scrolling is the better answer. */
.q-figure { margin-top: 14px; }
.q-figure .fig { display: flex; flex-direction: column; align-items: center; margin: 0; }
.q-figure svg {
  display: block;
  max-width: 100%;
  max-height: max(150px, calc(100vh - 490px));
  height: auto;
}
.q-figure .fig__cap {
  margin-top: 7px;
  font-size: .82rem;
  font-style: italic;
  color: var(--ink-faint);
}

/* --------------------------------------------------------- answer input */

.ai-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-row-wrap { row-gap: 10px; }
.ai-slot { display: inline-flex; align-items: center; gap: 6px; }
.ai-join { color: var(--ink-faint); font-size: .9rem; padding: 0 2px; }
.ai-affix { font-size: 1.2rem; color: var(--ink); white-space: nowrap; }
.ai-suffix { color: var(--ink-soft); }

/* `quantity` unit picker. Sized to sit BESIDE the math field on one line and
   deliberately quieter than it: the number is the answer being worked out, the
   unit is the label being chosen for it. var(--tap) tall so it is still a full
   touch target on a phone. */
.ai-unit {
  min-height: var(--tap);
  padding: 4px 10px;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  font: inherit;
  font-size: 1.05rem;
  color: var(--ink);
  cursor: pointer;
}
.ai-unit:focus { border-color: var(--accent); outline: 3px solid rgba(79, 70, 229, .22); }
.ai-unit:disabled { opacity: .55; cursor: default; }

math-field {
  font-size: 1.4rem;
  min-width: 10ch;
  min-height: var(--tap);
  padding: 6px 10px;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  --caret-color: var(--accent);
  --selection-background-color: #dbeafe;
  --primary: var(--accent);
}
math-field:focus,
math-field:focus-within {
  border-color: var(--accent);
  outline: 3px solid rgba(79, 70, 229, .22);
  outline-offset: 0;
}
math-field[read-only] { background: #fafafa; border-style: dashed; }
.ai.none-active math-field { opacity: .45; }
.ai.is-locked { cursor: default; }
.ai.is-locked math-field:focus,
.ai.is-locked math-field:focus-within { outline-color: rgba(107, 114, 128, .25); border-color: var(--line); }

.ai-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.chip-btn {
  min-height: var(--tap);
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  font: inherit;
  font-size: .95rem;
  color: var(--ink-soft);
  cursor: pointer;
}
.chip-btn:hover { border-color: var(--accent); color: var(--accent-dk); }
.chip-btn:disabled { opacity: .5; cursor: default; }
.chip-none { font-weight: 650; border-style: dashed; color: var(--teal); border-color: #99f6e4; }
.chip-none.is-active { background: var(--teal); border-color: var(--teal); color: #fff; }

/* `choice` answers: a row of word chips acting as one radiogroup. Sized like
   the answer field it replaces (var(--tap) tall, 1.1rem) rather than like the
   small template chips above a field — this IS the answer, not a shortcut to
   typing one. Wraps on a phone; each chip stays a full tap target. */
.ai-choices { display: flex; flex-wrap: wrap; gap: 8px; }
.choice-btn {
  padding: 6px 16px;
  border-width: 2px;
  border-radius: 10px;
  font-size: 1.1rem;
  color: var(--ink);
}
.choice-btn.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 650;
}
.choice-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-dk); }
.choice-btn.is-active:hover:not(:disabled) { color: #fff; }
.choice-btn:focus-visible {
  outline: 3px solid rgba(79, 70, 229, .35);
  outline-offset: 2px;
  border-color: var(--accent);
}
/* A locked choice keeps the answer legible: greying every chip to .5 hides
   which one the student actually picked, which is the first thing they look
   at when the feedback appears. */
.ai.is-locked .choice-btn:disabled { opacity: .55; }
.ai.is-locked .choice-btn.is-active:disabled { opacity: 1; }

/* ---------------------------------------------------------- answer toolbar
   The symbol buttons above the field (app/components/answer-input.js, and
   app/keyboard-layouts.js toolbarFor() for what is on them and why).

   SMALLER THAN A CHIP, ON PURPOSE. .chip-btn is var(--tap) tall because it is
   an ANSWER (a choice option, a "no solution"); a toolbar key is a shortcut to
   something the keyboard also has, so it must not outweigh the field it sits
   over. 36px keeps it a comfortable touch target on an iPad without the row
   reading as the main event — and the keys are square, so a row of them scans
   as a keyboard strip rather than as a row of little buttons.

   It WRAPS: the chemistry pads are the widest (a balanced-equation answer needs
   the arrows, the states and the electron) and at phone width they take two
   rows. Two rows of symbols is the honest cost of a chemistry answer; the
   alternative was a horizontal scroller, where the keys past the edge are keys
   nobody finds — which is the exact failure the toolbar exists to fix. */
.ai-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 8px;
}
.tb-key {
  min-width: 36px;
  height: 36px;
  padding: 0 7px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
}
.tb-key:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-bg); }
.tb-key:active:not(:disabled) { background: var(--accent-bg); transform: translateY(1px); }
.tb-key:focus-visible { outline: 3px solid rgba(79, 70, 229, .35); outline-offset: 1px; }
.tb-key:disabled { opacity: .45; cursor: default; }
/* The rendered maths on a keycap is a LABEL, not a formula in a sentence: it
   must not inherit the field's display sizing or push the key out of square.
   MathLive's convertLatexToMarkup writes a .ML__latex wrapper. */
.tb-key .ML__latex { font-size: 1rem; }
.tb-key sup, .tb-key sub { font-size: .7em; }

/* --------------------------------------------------------------- hints
   The panel the Hint button fills, one hint per press
   (app/components/hints.js). Left rule and a tinted ground so it reads as an
   ASIDE about the question — visibly not the question, and visibly not the
   verdict panel below it, which is coloured by outcome. */
.hints { margin: 0 0 14px; }
.hint {
  padding: 10px 12px;
  margin-bottom: 8px;
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  background: var(--accent-bg);
}
.hint:last-child { margin-bottom: 0; }
.hint-label {
  display: block;
  margin-bottom: 4px;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--accent-dk);
}
.hint-body { font-size: 1rem; line-height: 1.6; color: var(--ink); }

/* Keycap labels inside MathLive's virtual keyboard (light DOM). */
.mdk-mixed sup, .mdk-exp10 sup { font-size: .7em; }
.mdk-mixed sub { font-size: .7em; }

/* ------------------------------------------------------------- feedback */

.feedback {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--line-soft);
}
.fb-banner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fb-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: var(--ink-faint);
  color: #fff;
  font-size: .85rem;
  font-weight: 700;
  line-height: 1;
}
.fb-title { font-weight: 700; }
.fb-msg { margin-top: 6px; font-size: .92rem; color: var(--ink-soft); }
/* "Not scored — this question was already marked." Quieter than the message,
   because it is bookkeeping and the message is the teaching. */
.fb-note { margin-top: 6px; font-size: .82rem; font-style: italic; color: var(--ink-faint); }

.fb-correct    { background: #f0fdf4; border-color: #bbf7d0; }
.fb-correct .fb-icon  { background: var(--ok); }
.fb-correct .fb-title { color: var(--ok); }
.fb-almost     { background: #fffbeb; border-color: #fde68a; }
.fb-almost .fb-icon   { background: var(--warn); }
.fb-almost .fb-title  { color: var(--warn); }
.fb-wrong      { background: #fef2f2; border-color: #fecaca; }
.fb-wrong .fb-icon    { background: var(--bad); }
.fb-wrong .fb-title   { color: var(--bad); }
.fb-incomplete { background: var(--line-soft); border-color: var(--line); }
.fb-incomplete .fb-title { color: var(--ink-faint); }

.fb-answer {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
  font-size: .92rem;
  color: var(--ink-soft);
}
.fb-answer-label { font-weight: 600; }
.fb-answer-math { font-size: 1.2rem; color: var(--ink); }

.fb-working { margin-top: 10px; }
/* padding, not min-height: `display:flex` here would eat the disclosure marker */
.fb-working > summary {
  padding: 11px 0;
  cursor: pointer;
  font-size: .9rem;
  font-weight: 600;
  color: var(--accent);
}
.fb-working-body { margin-top: 6px; }
.sol-line {
  padding: 4px 0 4px 12px;
  border-left: 3px solid var(--line);
  font-size: 1.02rem;
  color: var(--ink-soft);
}
.sol-line:first-child { border-left-color: var(--accent); }

/* ------------------------------------------------------------ narrow UI */

@media (max-width: 560px) {
  .header-inner { padding-top: 10px; padding-bottom: 10px; }
  .brand-title { font-size: 1.15rem; }
  .teacher-link { font-size: .82rem; padding: 8px 10px; }
  .skill-row { align-items: stretch; }
  .skill-controls { width: 100%; justify-content: space-between; }
  .btn-start { flex: 1 1 auto; }
  .question-card { padding: 14px 12px; }
  .stem { font-size: 1.05rem; }
  /* Every action is full-width-ish; the basis keeps Try again and Show answer
     an even pair when they share the row, rather than letting the longer label
     take the larger half. */
  .actions .btn { flex: 1 1 40%; }
  /* A hair tighter so the chemistry pads still come out at two rows on a
     narrow phone rather than three, without going under a 36px target. */
  .ai-toolbar { gap: 4px; }
  .tb-key { min-width: 34px; padding: 0 5px; }
}

@media (prefers-reduced-motion: no-preference) {
  .feedback { animation: fb-in .16s ease-out; }
  @keyframes fb-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
}
