/* Lexend, self-hosted.
   Drawn specifically to reduce visual stress and improve reading proficiency,
   which is a defensible choice for a reading product rather than a decorative
   one - wider apertures, unambiguous b/d/p/q, generous counters. One 39 KB
   variable file covers 300-800, so there is no weight-by-weight download and
   no third-party request on any page. */
@font-face {
  font-family: "Lexend";
  src: url("/static/fonts/lexend-var.woff2") format("woff2");
  font-weight: 300 800;
  font-display: swap;
}
:root {
  /* INK & PARCHMENT.
     The palette this inherited was Math Ladder's: cool navy ground, amber
     accent. Same product wearing a different name. This one is ink - a warm
     near-black with blue in it, the color of a written page at night - lit
     by terracotta rather than amber, with paper-warm text instead of the old
     blue-white. */
  --bg: #14110f;
  --panel: #1e1a17;
  --panel2: #272220;
  --line: #3a332e;
  --text: #f2ece3;
  --muted: #a89b8c;
  --accent: #c96f4a;
  --accent2: #d9a441;
  --good: #6a9b6e;
  --bad: #c9564b;
  --radius: 12px;
  /* inputs sit RECESSED below the card surface - clearly a place to type,
     not another panel. Darker fill + brighter edge = contrast both ways. */
  --input-bg: #0e0c0b;
  --input-line: #55483f;
  /* the wash behind an organizer, a quote block or a callout.
     Tokenized because it was hardcoded as rgba(90,130,255,..) -
     Math Ladder's blue - in litkit and six unit modules, which no
     amount of recoloring the stylesheet would have reached. */
  --tint: rgba(201,111,74,.10);
}
/* Light mode — an opt-in palette (toggle in the navbar). Same variable names,
   so every component recolors automatically; buttons keep dark text on the
   amber accent, which reads on both themes. */
:root[data-theme="light"] {
  /* the parchment half: warm paper, ink text, the same terracotta accent */
  --bg: #f6f1e8;
  --panel: #fffdf9;
  --panel2: #efe8dc;
  --line: #ddd2c2;
  --text: #241f1b;
  --muted: #6b5f52;
  --accent: #a8502c;
  --accent2: #8a6516;
  --good: #3f7a48;
  --bad: #b03a2e;
  /* light cards are near-white, so inputs get a tinted fill + stronger border */
  --input-bg: #f3ece0;
  --input-line: #c3b39c;
  --tint: rgba(168,80,44,.07);
}
:root[data-theme="light"] body { background: linear-gradient(180deg,#faf6ee,#f2ebdf); }
:root[data-theme="light"] code { background: #ece3d4; }
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Base fill behind everything, so a page wider than the viewport (or a fixed
   reward background that only paints the viewport) never shows white gutters. */
html { background: var(--bg); }
body {
  background: var(--bg);
  color: var(--text);
  font: 16px/1.65 "Lexend", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  min-height: 100vh;
}
a { color: var(--accent2); text-decoration: none; }
a:hover { text-decoration: underline; }
code { background: var(--panel2); padding: 1px 6px; border-radius: 5px; }

nav {
  display: flex; align-items: center; gap: 22px;
  padding: 14px 28px;
  padding-left: max(28px, env(safe-area-inset-left));
  padding-right: max(28px, env(safe-area-inset-right));
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 10;
  /* with only four top-level items the nav wraps instead of scrolling — a
     scroll container would clip the dropdown menus (and never widens the
     page, which would leave the fixed background unpainted at the edge) */
  flex-wrap: wrap; overflow: visible;
}
nav .navlink, nav .brand, nav .user, nav .btn { flex-shrink: 0; }
nav .brand { font-weight: 800; font-size: 19px; color: var(--text); letter-spacing: .3px; }
nav .brand .brand-text > span { color: var(--accent); }
nav a.navlink { color: var(--muted); font-weight: 600; font-size: 14px; }
nav a.navlink:hover { color: var(--text); text-decoration: none; }
nav .spacer { flex: 1; }
nav .user { color: var(--muted); font-size: 14px; }
nav .admin-command-link {
  border: 1px solid color-mix(in srgb, var(--accent) 58%, var(--line));
  border-radius: 999px;
  padding: 7px 11px;
  color: var(--accent2);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
nav .admin-command-link:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}

/* ---- nav dropdown menus (Practice ▾ / ⋯ More) — native <details>, no JS
   required to open; a little JS closes on outside click. ---- */
nav details.navmenu { position: relative; flex-shrink: 0; }
nav details.navmenu > summary {
  list-style: none; cursor: pointer; user-select: none;
  color: var(--muted); font-weight: 600; font-size: 14px; padding: 6px 2px;
}
nav details.navmenu > summary::-webkit-details-marker { display: none; }
nav details.navmenu > summary:hover,
nav details.navmenu[open] > summary { color: var(--text); }
nav .navdrop {
  position: absolute; top: calc(100% + 10px); left: -8px;
  min-width: 210px; z-index: 80;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 14px; padding: 8px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .35);
}
nav .navdrop a {
  color: var(--muted); font-weight: 600; font-size: 14px;
  padding: 9px 10px; border-radius: 9px; white-space: nowrap;
}
nav .navdrop a:hover { background: var(--panel2); color: var(--text); text-decoration: none; }
nav .navbadge {
  position: absolute; top: -4px; right: -14px;
  background: var(--accent); color: #fff; font-size: 10px; font-weight: 800;
  border-radius: 999px; padding: 1px 5px; min-width: 14px; text-align: center;
}

/* Account cluster: four separate links on a wide screen, one menu once the
   nav runs out of room. Exactly one of the pair is ever displayed. The
   wrapper is display:contents so its children stay direct flex items of the
   nav and keep the nav's gap - a plain block would collapse them together. */
nav .nav-account-full { display: contents; }
nav details.nav-account-compact { display: none; }
nav details.nav-account-compact > summary { font-size: 15px; }
nav details.nav-account-compact .avimg { height: 1.15em; }

.wrap { max-width: 1060px; margin: 0 auto; padding: 28px 20px 60px; }
.grid { display: grid; gap: 18px; }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 800px) { .grid.cols-3, .grid.cols-2 { grid-template-columns: 1fr; } }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 22px;
}
.card h2 { margin: 0 0 10px; font-size: 16px; color: var(--muted); font-weight: 700;
  text-transform: uppercase; letter-spacing: .8px; }
.big { font-size: 40px; font-weight: 800; line-height: 1.1; }
.sub { color: var(--muted); font-size: 14px; }

.btn {
  display: inline-block; cursor: pointer;
  background: var(--accent); color: #1a1205;
  border: 0; border-radius: 10px;
  font-size: 16px; font-weight: 800;
  padding: 12px 26px;
}
.btn:hover { filter: brightness(1.08); text-decoration: none; }
.btn.secondary { background: var(--panel2); color: var(--text); border: 1px solid var(--line); }
.btn.big-btn { font-size: 19px; padding: 16px 38px; }
.btn:disabled { opacity: .5; cursor: default; }

/* Style text-like inputs, INCLUDING bare <input> with no type attribute —
   an attribute selector like [type=text] does NOT match an input that omits
   the attribute, which is why the username/email boxes rendered smaller than
   the password box. `input:not([type])` catches those. */
input[type=text], input[type=password], input[type=number],
input[type=email], input[type=search], input:not([type]),
textarea.ans-input, select.ans-input {
  background: var(--input-bg); color: var(--text);
  border: 1.5px solid var(--input-line); border-radius: 10px;
  padding: 12px 14px; font-size: 17px; width: 100%;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .25);
}
:root[data-theme="light"] input[type=text],
:root[data-theme="light"] input:not([type]),
:root[data-theme="light"] textarea.ans-input {
  box-shadow: inset 0 1px 2px rgba(23, 33, 58, .08);
}
/* Placeholders are italic and clearly dimmed so hint text can never be
   mistaken for a pre-typed answer (a real report from an 80+ tester). */
input::placeholder, textarea::placeholder {
  color: var(--muted); opacity: .55; font-style: italic;
}
input:focus, textarea.ans-input:focus {
  outline: 2px solid var(--accent2); border-color: transparent;
}

.progressbar { background: var(--panel2); border-radius: 99px; height: 10px; overflow: hidden; }
.progressbar > div { background: var(--accent2); height: 100%; border-radius: 99px; transition: width .4s; }
.progressbar.gold > div { background: var(--accent); }

.badge { display: inline-block; padding: 3px 10px; border-radius: 99px; font-size: 12px;
  font-weight: 700; letter-spacing: .5px; text-transform: uppercase; }
.badge.lesson { background: #274b8a; color: #bcd6ff; }
.badge.review { background: #594520; color: #ffd9a0; }
.badge.quiz { background: #294d3f; color: #a8f0cf; }
.badge.consolidate { background: #4a2d63; color: #e3c8ff; }

/* Fluid reading sizes: scale the question and lesson text with the viewport
   so a big desktop screen (where the learning column sits in lots of empty
   space) reads large and comfortable, while phones stay compact. clamp()
   floors/ceilings the growth so it never gets silly at either extreme. */
/* The question, boxed.
   It used to be nothing but a larger font, so on the diagnostic the page read
   as one continuous column: the instructions about the knowledge frontier, the
   progress line, and the question a child is being asked to answer, all in the
   same voice. Now the question sits on its own surface with an accent edge, so
   the eye finds "what am I being asked" without reading the paragraph above it
   first. Used by the diagnostic, learn, notebook, duels, quest, challenge and
   the guided retry, so all of them gain the same landmark. */
.q-card {
  font-size: clamp(20px, 1.05rem + 0.8vw, 30px); line-height: 1.45;
  margin: 18px 0 14px; padding: 18px 20px 20px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
}
.q-card > :first-child { margin-top: 0; }
.q-card > :last-child { margin-bottom: 0; }
/* a passage inside a question keeps its own card look, so drop the nesting */
.q-card .passage { background: transparent; border: 0; padding: 0; }
@media (max-width: 620px) { .q-card { padding: 14px 15px 16px; } }
.feedback { font-weight: 700; margin-top: 10px; min-height: 24px; }
.feedback.ok { color: var(--good); }
.feedback.no { color: var(--bad); }

.lesson-body { font-size: clamp(16px, 0.95rem + 0.4vw, 21px); line-height: 1.6; }
.lesson-body p { margin: 10px 0; }
/* answer box tracks the question size (element+class matches the base input
   specificity and comes later, so it wins) */
input.ans-input, textarea.ans-input, select.ans-input {
  font-size: clamp(17px, 0.95rem + 0.5vw, 22px);
}

.ring { position: relative; width: 130px; height: 130px; margin: 6px auto; }
.ring svg { transform: rotate(-90deg); }
.ring .mid { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; }
.ring .mid b { font-size: 26px; }

table.simple { width: 100%; border-collapse: collapse; font-size: 15px; }
table.simple td { padding: 7px 4px; border-bottom: 1px solid var(--line); }

.hero { text-align: center; padding: 70px 20px 40px; }
.hero h1 { font-size: 46px; margin: 0 0 14px; line-height: 1.15; }
.hero h1 span { color: var(--accent); }
.hero p { color: var(--muted); font-size: 19px; max-width: 900px; margin: 0 auto 30px; }

.footer { text-align: center; color: var(--muted); font-size: 13px; padding: 30px; }

.legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 13px; color: var(--muted); }
.legend .dot { display: inline-block; width: 11px; height: 11px; border-radius: 99px; margin-right: 5px; }


/* ---- touch & small screens (phones, iPad portrait split-view) ---------- */

.btn, button.btn { min-height: 44px; }         /* Apple HIG touch target */
nav a.navlink { padding: 6px 2px; }

/* Tablets and phones. Every iPad in portrait - Mini 744, Air 820, Pro 11 834 -
   sits above the old 720px phone breakpoint, so all of them were served the
   desktop nav, ran out of width, and wrapped: two rows on an iPad with the
   theme, settings and log-out links orphaned onto the second, three rows on
   an iPhone. Folding the account cluster into one menu and dropping the
   completion estimate reclaims enough width for a single row on a tablet. */
@media (max-width: 900px) {
  nav { gap: 14px; padding: 12px 18px; }
  nav .nav-account-full { display: none; }
  nav details.nav-account-compact { display: block; }
  /* anchor menus to the right edge if they'd overflow a narrow screen */
  nav .navdrop { left: auto; right: -8px; }
  nav .hdr-eta { display: none; }
}

@media (max-width: 720px) {
  /* four items fit; wrapping (not scrolling) keeps the dropdowns unclipped */
  nav { gap: 12px; padding: 10px 14px; }
  nav .brand { font-size: 17px; }
  nav a.navlink, nav .user { flex-shrink: 0; }
  nav .admin-command-link { font-size: 12px; padding: 6px 9px; }

  .wrap { padding: 16px 12px 48px; }
  .card { padding: 16px 14px; }
  .big { font-size: 30px; }
  .q-card { font-size: 19px; }
  .hero { padding: 44px 14px 28px; }
  .hero h1 { font-size: 31px; }
  .hero p { font-size: 16px; }
  .btn.big-btn { font-size: 17px; padding: 14px 26px; width: 100%; }

  /* wide tables scroll inside themselves rather than stretching the page */
  table.simple { display: block; overflow-x: auto; }
}

/* Phones. A 390px iPhone cannot hold the wordmark, the beta chip and five
   destinations on one line, so the wordmark drops to the ladder mark, which
   still links home and still carries the name as its alt text. */
@media (max-width: 500px) {
  nav { gap: 11px; padding: 10px 12px; }
  nav .brand-text { display: none; }
  nav .brand-ladder { margin-right: 0; height: 1.6em; }
  nav .nav-beta-chip { display: none; }
  nav .admin-command-link { font-size: 11px; padding: 5px 8px; }
}

@media (max-width: 400px) {
  .grid { gap: 12px; }
  .big { font-size: 26px; }
}

/* Self-hosted avatar images (identical on every OS) */
.avimg { display:inline-block; vertical-align:-0.18em; object-fit:contain }

/* Top dashboard columns: the last card in each stack stretches so all three
   columns finish at the same horizontal level. Scoped to the nested column
   divs — pages that put cards directly in a cols-3 grid are untouched. */
.grid.cols-3 > div > .card:last-child { flex: 1 }

/* ---- Course ladder ------------------------------------------------------
   The ladder is the brand, so it keeps its shape: two rails with rungs
   between them. It does NOT keep the literal wood browns it used to be drawn
   in, which belonged to no palette in the product and read as a muddy slab
   against the navy surfaces around it.

   The rails are now brushed steel in the same blues as the rest of the app,
   lit warm at the summit so the eye is drawn UP the ladder - the one place
   gold appears in the frame. The rungs are ordinary cards, the same surface
   and border as every other card on the page, so tier is carried by the
   label color and a single accent stripe rather than by the whole slab
   changing color. Everything is expressed in palette variables, so light
   mode recolors with no second definition.

   One block, both dashboards: .ladder-* is the classic view and
   .mission-ladder-* the mission view. They were drifting apart. */
.ladder-stack,
.mission-ladder {
  position: relative; isolation: isolate;
  padding: 16px 34px; border-radius: 16px;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--accent) 7%, transparent),
      transparent 34%),
    linear-gradient(90deg,
      color-mix(in srgb, var(--accent2) 8%, transparent),
      transparent 22%, transparent 78%,
      color-mix(in srgb, var(--accent2) 8%, transparent));
}
.ladder-stack::before, .ladder-stack::after,
.mission-ladder::before, .mission-ladder::after {
  content: ""; position: absolute; z-index: -1; top: 0; bottom: 0;
  width: 14px; border-radius: 8px;
  /* a rail: dark edges, a bright spine down the middle, warm at the top */
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--accent) 78%, transparent) 0%,
      transparent 12%),
    linear-gradient(90deg,
      color-mix(in srgb, var(--line) 62%, #000) 0%,
      color-mix(in srgb, var(--accent2) 16%, var(--panel2)) 26%,
      color-mix(in srgb, var(--accent2) 58%, var(--panel2)) 50%,
      color-mix(in srgb, var(--accent2) 16%, var(--panel2)) 74%,
      color-mix(in srgb, var(--line) 62%, #000) 100%);
  border: 1px solid color-mix(in srgb, var(--accent2) 40%, var(--line));
  box-shadow:
    inset 1px 0 0 color-mix(in srgb, #fff 14%, transparent),
    inset -2px 0 3px rgba(0, 0, 0, .35),
    0 6px 16px rgba(0, 0, 0, .28);
}
.ladder-stack::before { left: 8px }
.ladder-stack::after  { right: 8px }
.mission-ladder::before { left: 8px }
.mission-ladder::after  { right: 8px }

.ladder-rung, .mission-ladder-rung {
  position: relative; z-index: 1;
  margin: 0 0 15px; padding: 11px 13px 13px;
  border: 1px solid var(--line); border-radius: 10px;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--panel2) 92%, var(--accent2)), var(--panel));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 7%, transparent),
    0 4px 14px rgba(0, 0, 0, .22);
}
/* the stub of rail each rung appears bolted to */
.ladder-rung::before, .ladder-rung::after,
.mission-ladder-rung::before, .mission-ladder-rung::after {
  content: ""; position: absolute; z-index: -1; top: 50%;
  width: 30px; height: 9px; border-radius: 3px;
  transform: translateY(-50%);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent2) 30%, var(--panel2)),
    var(--line) 65%, color-mix(in srgb, var(--line) 65%, #000));
  border: 1px solid color-mix(in srgb, var(--accent2) 34%, var(--line));
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 16%, transparent);
}
.ladder-rung::before { left: -32px }
.ladder-rung::after  { right: -32px }
.mission-ladder-rung::before { left: -33px }
.mission-ladder-rung::after  { right: -33px }

.ladder-rung .sub, .ladder-rung a { color: var(--muted) }
.ladder-rung a:hover { color: var(--accent2) }
.ladder-rung .progressbar { background: color-mix(in srgb, var(--line) 52%, transparent) }

/* Tier reads from a stripe and the label, not from recoloring the whole card:
   gold for mastery, blue for the core course, quiet for prerequisites. */
.ladder-rung, .mission-ladder-rung { border-left: 3px solid var(--line) }
.ladder-rung.mastery, .mission-ladder-rung.mastery {
  border-left-color: var(--accent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent),
              0 0 0 1px color-mix(in srgb, var(--accent) 26%, transparent),
              0 4px 16px rgba(0, 0, 0, .24);
}
.mission-ladder-rung.mastery small { color: var(--accent) }
.ladder-rung.core, .mission-ladder-rung.core { border-left-color: var(--accent2) }
.mission-ladder-rung.core small { color: var(--accent2) }

/* Brand ladder mark: nav logo, rung icons in counters */
.brand-ladder { height:1.35em; width:auto; vertical-align:-0.28em; margin-right:7px }
.rung-icon { height:.8em; width:auto; vertical-align:-0.05em; margin:0 2px }
.ladder-hero { width:96px; height:96px; filter:drop-shadow(0 6px 18px rgba(240,180,41,.25)) }

/* Long-form info pages: full-width, justified reading text */
.prose { text-align: justify; hyphens: auto; }
.prose p { max-width: none; }

/* Portal-wide native dropdown treatment. Every <select>, including controls
   injected by JavaScript, inherits the same recessed surface, focus ring,
   typography, and themed option menu. Keep width intrinsic by default;
   .ans-input dropdowns retain the full-width behavior above. */
select {
  appearance: none;
  -webkit-appearance: none;
  min-height: 44px;
  max-width: 100%;
  padding: 10px 42px 10px 14px;
  border: 1.5px solid var(--input-line);
  border-radius: 10px;
  background-color: var(--input-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='8' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%238fa1c4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 14px 8px;
  color: var(--text);
  font: inherit;
  font-size: 16px;
  line-height: 1.25;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .25);
  cursor: pointer;
}
select:hover { border-color: color-mix(in srgb,var(--input-line) 55%,var(--accent2)); }
select:focus {
  outline: 2px solid var(--accent2);
  outline-offset: 1px;
  border-color: transparent;
}
select:disabled { opacity: .55; cursor: not-allowed; }
.select-compact {
  min-height: 36px;
  padding: 7px 36px 7px 10px;
  font-size: 13px;
}
select option, select optgroup {
  background: var(--panel);
  color: var(--text);
  font: inherit;
}
:root[data-theme="light"] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='8' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%235b6b8c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  box-shadow: inset 0 1px 2px rgba(23, 33, 58, .08);
}

/* ---- step-through explainer ("watch it built") ---------------------------- */
.explainer-card {
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
  border-radius: 18px; padding: 16px 18px 14px;
  background: radial-gradient(circle at 90% 6%,
      color-mix(in srgb, var(--accent) 12%, transparent), transparent 40%),
    linear-gradient(150deg, color-mix(in srgb, var(--panel2) 94%, var(--accent)),
      var(--panel));
}
.explainer-head { display: flex; justify-content: space-between;
  align-items: baseline; gap: 10px; margin-bottom: 6px }
.explainer-count { color: var(--muted); font-size: 12px; font-weight: 700 }
.explainer-stage { min-height: 10px }
.explainer-narration { margin: 10px 2px 4px; font-size: 17px; line-height: 1.5 }
.explainer-dots { display: flex; gap: 7px; margin: 10px 2px }
.explainer-dot { width: 9px; height: 9px; border-radius: 50%;
  background: var(--line); cursor: pointer; transition: background .18s,
  transform .18s }
.explainer-dot.seen { background: color-mix(in srgb, var(--accent) 45%, var(--line)) }
.explainer-dot.on { background: var(--accent); transform: scale(1.35) }
.explainer-controls { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px }
.explainer-controls .btn { padding: 7px 15px; font-size: 14px }
.explainer-play { min-width: 104px }
@media (max-width: 520px) {
  .explainer-narration { font-size: 16px }
  .explainer-controls .btn { flex: 1 1 auto }
}


/* ===================================================================
   Reading passages, organizers and the read-aloud button.

   A passage is the single most-read element in this product, so it gets
   real typographic care: a wider measure, generous leading, and a serif
   face. Children read connected text markedly better in a serif at a
   larger size than in the interface sans, and the passage is the one
   place where the text is the content rather than the chrome.
   =================================================================== */

.passage {
  margin: 12px 0 16px;
  padding: 16px 20px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
}
.passage-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.passage-genre {
  font-size: 11px; font-weight: 800; letter-spacing: 1px;
  text-transform: uppercase; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 999px; padding: 2px 9px;
  white-space: nowrap;
}
.passage-title { margin: 0; font-size: 17px; font-weight: 700; }
.passage-p {
  font-family: Georgia, "Iowan Old Style", "Times New Roman", serif;
  font-size: 17.5px; line-height: 1.78; margin: 0 0 12px;
  max-width: 66ch;
}
.passage-p:last-of-type { margin-bottom: 0; }
/* Verse keeps its own line breaks and never justifies. */
.passage-verse { white-space: normal; font-style: normal; }
/* Paragraph numbers, from grade 4 up, so a question can say "paragraph 3"
   and mean something. Hanging in the margin, out of the reading line. */
.passage-num {
  display: inline-block; min-width: 22px; margin-left: -30px;
  margin-right: 8px; text-align: right;
  font-family: "Lexend", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 12px; font-weight: 700; color: var(--muted);
  user-select: none;
}
@media (max-width: 620px) {
  .passage { padding: 14px 14px; }
  .passage-num { margin-left: 0; min-width: 18px; }
}
.passage-tools { margin-top: 12px; }
.passage-prompt {
  font-size: 17px; line-height: 1.6; font-weight: 600; margin: 14px 0 4px;
}

/* Read aloud. The whole point of a K-2 literacy product is that a child who
   cannot yet decode a prompt can still answer the question in it. */
.speak-btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 8px 15px;
  background: transparent; color: var(--accent2);
  border: 1px solid var(--accent2); border-radius: 999px;
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
}
.speak-btn:hover { background: color-mix(in srgb, var(--accent2) 12%, transparent); }
.speak-btn[aria-pressed="true"] {
  background: var(--accent2);
  color: var(--bg);
}
.speak-btn:disabled { opacity: .45; cursor: default; }

/* Phonics notation: a SOUND is /k/, a LETTER is <c>. Keeping the two visually
   distinct is not decoration - conflating them is the exact confusion that
   phonics instruction exists to prevent. */
.phoneme {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  padding: 0 5px; border-radius: 5px;
}
.grapheme {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700; color: var(--accent2);
  background: color-mix(in srgb, var(--accent2) 14%, transparent);
  padding: 0 5px; border-radius: 5px;
}

.lit-organizer { max-width: 100%; overflow-x: auto; }
.lit-organizer table { min-width: 0; }

/* Placement report: strand bars and the reading-stage ribbon. */
.strand-row {
  display: flex; align-items: center; gap: 12px; padding: 9px 0;
  border-top: 1px solid var(--line);
}
.strand-row:first-child { border-top: 0; }
.strand-name { flex: 0 0 190px; font-weight: 600; font-size: 14px; }
.strand-bar {
  flex: 1; height: 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--line) 60%, transparent);
  overflow: hidden;
}
.strand-fill { height: 100%; border-radius: 999px; background: var(--accent); }
.strand-fill.strong { background: var(--good); }
.strand-fill.weak { background: var(--bad); }
.strand-pct { flex: 0 0 46px; text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: 14px; }
@media (max-width: 560px) {
  .strand-name { flex-basis: 120px; font-size: 13px; }
}
.stage-ribbon {
  display: inline-block; padding: 5px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border: 1px solid var(--accent); color: var(--accent);
  font-weight: 800; font-size: 13px; letter-spacing: .4px;
}
