/* ════════════════════════════════════════════════════════════════
   CALM COMPONENT VOCABULARY
   The shared design system for the redesigned (FEATURE_U7_CALM_CORE)
   screens under templates/core/calm/. Every calm screen composes
   ONLY these classes for colour, surface, type and spacing rhythm —
   Tailwind stays allowed for layout (flex/gap/margin) but never for
   colour, border or shadow, because hand-assembled utility strings
   are exactly how the previous attempts drifted apart screen by
   screen. If a screen needs something this file lacks, add it HERE
   rather than inventing a local variant.

   Loaded after app.css, so the few token overrides below intentionally
   win over the earlier calm-token block there.
   ════════════════════════════════════════════════════════════════ */

:root {
  /* Warmer than pure white — a card should read as paper resting on
     the parchment page, not as a hole punched through it. */
  --calm-surface: #fffdfa;
  /* Approved lighter accent. #b45309 was heavier than wanted; this is
     as light as the orange can go while white button text still clears
     WCAG AA (~4.5:1). Anything lighter needs dark text instead. */
  --calm-accent-focus: #b95d0a;
  /* The same orange as text. #b95d0a is tuned for white text ON it; as small
     text on parchment it is only ~4:1, so links and labels use this deeper
     step, which clears 4.5:1 on the page, the deep parchment and cards. */
  --calm-accent-text: #a3510a;
  /* Was #8b8177, which measured 3.4:1 on the parchment page — below the
     4.5:1 small text needs. This keeps the warm grey and clears 4.7:1 even
     on the deepest parchment. */
  --calm-text-muted: #6b6259;

  /* A hairline, not a rule. Translucent so it sits on whatever surface
     it crosses instead of stamping a grey line over it. */
  --calm-hair: rgba(44, 40, 37, .07);
  /* Depth without borders: a barely-there contact shadow plus a wide,
     soft ambient one. This pairing is what separates "considered
     minimal" from "unfinished minimal". */
  --calm-lift: 0 1px 2px rgba(44, 40, 37, .04), 0 12px 32px -12px rgba(44, 40, 37, .16);

  /* Right and wrong. Muted enough to sit inside a calm card, saturated
     enough to be the first thing the eye lands on — knowing whether you
     were right is the whole point of revealing the answer. */
  --calm-ok: #2f6b46;
  --calm-ok-bg: rgba(47, 107, 70, .10);
  --calm-ok-line: rgba(47, 107, 70, .34);
  --calm-no: #a4392a;
  --calm-no-bg: rgba(164, 57, 42, .09);
  --calm-no-line: rgba(164, 57, 42, .30);

  /* One spacing scale, used everywhere. Gaps were landing on 8, 12, 20,
     32 and 40px depending on which utility a screen happened to reach
     for, which is what makes a layout feel unconsidered even when every
     individual screen looks fine. */
  --calm-s1: 8px;   /* inside one thing */
  --calm-s2: 16px;  /* between related things */
  --calm-s3: 24px;  /* label to the control it names */
  --calm-s4: 34px;  /* between sections */
  --calm-edge-light: rgba(255, 255, 255, .7);
  --calm-control-shadow: 0 2px 3px rgba(72, 40, 15, .08);
  --calm-motion-ease: cubic-bezier(.2, .7, .3, 1);
}

html.dark {
  --calm-edge-light: rgba(255, 255, 255, .05);
  --calm-control-shadow: 0 2px 4px rgba(0, 0, 0, .18);
  --calm-surface: #292524;
  --calm-accent-focus: #f0a35a;
  --calm-accent-text: #f0a35a;
  --calm-text-muted: #a8a29e;
  --calm-hair: rgba(245, 245, 244, .09);
  --calm-lift: 0 1px 2px rgba(0, 0, 0, .3), 0 12px 32px -12px rgba(0, 0, 0, .55);
  --calm-ok: #8fcfa8;
  --calm-ok-bg: rgba(143, 207, 168, .13);
  --calm-ok-line: rgba(143, 207, 168, .34);
  --calm-no: #f0a08f;
  --calm-no-bg: rgba(240, 160, 143, .13);
  --calm-no-line: rgba(240, 160, 143, .32);
}

/* ── Page ─────────────────────────────────────────────────────── */
html { overflow-x:hidden; }
.calm-page { overflow-x:hidden; background: var(--calm-bg-parchment); color: var(--calm-text); }
/* Fixed study progress replaces the ordinary app bar for an active session.
   Remove only that page's top-bar spacer so the available region starts at
   the progress bar and cards can be centred precisely between it and mobile
   navigation. Other study-like pages retain the normal app bar. */
body[data-fixed-study-shell="1"] .calm-topbar-spacer { height:0; }

/* ── Surface ──────────────────────────────────────────────────── */
.calm-card {
  background: var(--calm-surface);
  border-radius: 22px;
  padding: 24px 22px 22px;
  box-shadow: var(--calm-lift);
}
.calm-card-tight { padding: 20px 20px 18px; }
/* A card that holds a list of rows edge to edge. */
.calm-card.p-0, .calm-card-flush { padding: 0; }
/* A fine paper edge adds depth without moving a reading surface. Keep the
   study card's own reveal and grading treatments in charge during recall. */
.calm-page:not([data-study-page="1"]) .calm-card {
  box-shadow: inset 0 1px 0 var(--calm-edge-light), inset 0 0 0 1px var(--calm-hair), var(--calm-lift);
}

/* ── Type ─────────────────────────────────────────────────────── */
.calm-eyebrow {
  /* Always the sans: an <h2 class="calm-eyebrow"> otherwise took Lora
     from the global h2 rule (app.css) and looked like another kind of label. */
  font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif); font-weight: 400;
  font-size: 11.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--calm-text-muted);
}
.calm-title {
  font-family: Lora, Georgia, serif;
  font-size: 31px;
  line-height: 1.14;
  font-weight: 500;
  margin: 9px 0 8px;
  color: var(--calm-text);
}
.calm-h2 {
  font-family: Lora, Georgia, serif;
  font-size: 22px;
  font-weight: 500;
  color: var(--calm-text);
}
.calm-label {
  font-family: Lora, Georgia, serif;
  font-size: 15px;
  font-weight: 600;
  color: var(--calm-text-soft);
  margin: 0 2px 4px;
}
.calm-meta { font-size: 13.5px; color: var(--calm-text-soft); }
/* A meta line assembled from optional parts. Putting the separator in the
   template means a missing first part leaves a dangling "· 6 questions";
   here the separator only exists between two parts that both rendered. */
.calm-seq > span + span::before { content: " · "; }
.calm-note { font-size: 13.5px; line-height: 1.55; color: var(--calm-text-soft); }
.calm-quiet { font-size: 13.5px; color: var(--calm-text-muted); }

/* ── Actions ──────────────────────────────────────────────────── */
.calm-btn {
  /* The primary button always follows something it acts on — a title, a
     meta line, a field — and every screen was choosing its own gap, or
     none, which is what made cards read as cramped. One default, which a
     utility class can still override where a button belongs tight to a
     field. */
  margin-top: 24px;
  display: block;
  width: 100%;
  background: var(--calm-accent-focus);
  color: #fff;
  border: 0;
  border-radius: 14px;
  padding: 15px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .2px;
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  transition: filter var(--u-motion-fast, 120ms) var(--u-motion-ease, ease);
}
.calm-btn:hover { filter: brightness(1.06); }
.calm-btn { box-shadow:inset 0 1px 0 var(--calm-edge-light), var(--calm-control-shadow); }
.calm-btn:disabled { cursor:default; }
.calm-btn:disabled:hover { filter:none; }
/* In dark mode the accent is light, so white-on-accent would fail
   contrast — flip the label to ink instead. */
html.dark .calm-btn { color: #241f1a; }

/* Secondary actions are text, never a second filled button competing
   with the primary one. */
.calm-links { display: flex; gap: 22px; justify-content: center; margin-top: var(--calm-s2); flex-wrap: wrap; }
/* Descendant, not child, because rows of quiet links often wrap a button
   in its own <form>. The exclusions matter: anything that has asked to be
   a real button must stay one, and a two-class selector here silently beat
   .calm-btn — which is how "Send feedback" ended up as invisible dark text
   on a dark modal. */
.calm-links a:not(.calm-btn):not(.calm-btn-quiet), .calm-links button:not(.calm-btn):not(.calm-btn-quiet) {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 13px;
  color: var(--calm-text-muted);
  text-decoration: none;
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
}
.calm-link { font-size: 13px; color: var(--calm-accent-text); text-decoration: none; }

/* A small button that sits beside a heading (e.g. "Add a subject"
   next to Subjects) — deliberately not full-width and not filled, so
   it never competes with the screen's one primary action. */
.calm-btn-quiet {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 44px;
  padding: 7px 13px;
  border-radius: 11px;
  border: 1px solid var(--calm-hair);
  background: var(--calm-surface);
  color: var(--calm-text-soft);
  font-size: 13px;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
}
.calm-btn-quiet[aria-pressed="true"] {
  border-color: var(--calm-accent-focus);
  color: var(--calm-accent-text);
  box-shadow: inset 0 0 0 1px var(--calm-accent-focus);
}

/* Equal-weight choices — flashcard grading and similar. Not the accent
   button: four filled buttons would be four competing primary actions.
   Sized to the 44px touch target the rest of the app respects. */
.calm-choice {
  /* Left-aligned, because every use of this is something you read before
     you press it — a topic with a checkbox, an answer option, a point on
     the grading scale. Centring put checkboxes in the middle of the row. */
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  /* <button> defaults to centred text, which flex alignment does not undo
     for a child that fills the row. */
  text-align: left;
  width: 100%;
  min-height: 44px;
  padding: 11px 12px;
  border: 1px solid var(--calm-hair);
  border-radius: 12px;
  background: var(--calm-surface);
  color: var(--calm-text);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: border-color var(--u-motion-fast, 120ms) var(--u-motion-ease, ease);
}
.calm-choice:hover { border-color: var(--calm-accent-focus); }
/* A chosen option says so: the accent edge and a faint tint, not only the
   small control inside it. */
.calm-choice:has(input:checked) { border-color: var(--calm-accent-focus); background: rgba(185, 93, 10, .05); }
html.dark .calm-choice:has(input:checked) { background: rgba(240, 163, 90, .08); }
@media (prefers-reduced-motion: reduce) { .calm-choice { transition: none; } }

/* A grading scale is one dimension, so it is laid out along one: worst at
   the top, best at the bottom, one per line. The 2x2 grid it replaces read
   as a menu of four unrelated options, which is the wrong mental model for
   "how well did you know it". */
.calm-scale { display: grid; gap: 8px; }

/* ── Fields ───────────────────────────────────────────────────── */
/* A rule under the text, not a box around it: the answer the user types is
   the content, and a box would make it look like a form to fill in. */
.calm-input,
.calm-field {
  border: 0; border-bottom: 1px solid rgba(44, 40, 37, .18);
  border-radius: 0; background: transparent; padding: 10px 2px;
  color: var(--calm-text); font: inherit; outline: none;
}
.calm-input:focus, .calm-field:focus { border-bottom-color: var(--calm-accent-focus); }
.calm-input::placeholder, .calm-field::placeholder { color: var(--calm-text-muted); }
html.dark .calm-input, html.dark .calm-field { color: var(--calm-text) !important; background: transparent !important; border-bottom-color: rgba(245, 245, 244, .20); }
/* Height is set by script as the user types, so an inner scrollbar would
   only ever appear at the cap. */
.calm-grow { overflow: hidden; }
/* .calm-field was written into several templates before it existed as a
   component, so those selects and textareas were rendering as unstyled
   browser controls. It is .calm-input that fills its line. */
.calm-field { width: 100%; }
/* A dropdown's height comes from the system font: 44px on Windows, 43px on
   Linux and so, most likely, on Android. Hold it at the tap-target size. */
select.calm-box, select.calm-field, select.calm-input { min-height: 44px; }
.calm-field:not(select) { resize: vertical; }

/* Disclosures are quiet links, so they must not also carry the browser's
   default triangle — which inherits the link colour and becomes the most
   saturated mark on an otherwise calm screen. */
summary.calm-link,
summary.calm-label,
summary.calm-sub,
summary.calm-note { list-style: none; cursor: pointer; }
summary.calm-link::-webkit-details-marker,
summary.calm-label::-webkit-details-marker,
summary.calm-sub::-webkit-details-marker,
summary.calm-note::-webkit-details-marker { display: none; }

/* Answer options, one per line. Distinct from .calm-choice: choosing an
   answer is reading a list, not pressing one of four buttons. */
.calm-pick { display: block; padding: 13px 2px; color: var(--calm-text); cursor: pointer; }
.calm-pick + .calm-pick { border-top: 1px solid var(--calm-hair); }
/* Used as a <label> around a radio on the practice screen and as a submit
   <button> in the palace recall quiz and onboarding. A button brings its own
   chrome and centred text, which onboarding was patching with a local copy of
   exactly these rules. */
button.calm-pick {
  width: 100%; text-align: left; background: transparent; border: 0;
  font: inherit; color: var(--calm-text);
}

/* The revealed answer is the payload of the solution screen, so it is set
   like a heading rather than like body text under a heavier label. */
.calm-answer {
  font-family: Lora, Georgia, serif; font-size: 20px; line-height: 1.4;
  font-weight: 500; color: var(--calm-text);
}

/* Your answer beside the expected one, with the differing words marked on
   both sides. Side by side once there is room for it, because that is when
   the comparison is easiest; stacked on a phone, where two narrow columns
   would break every sentence into ribbons. */
.calm-diff { display: grid; gap: 20px; }
@media (min-width: 640px) { .calm-diff { grid-template-columns: 1fr 1fr; gap: 24px; } }
.calm-diff-text {
  font-size: 16px; line-height: 1.55; color: var(--calm-text);
  white-space: pre-wrap; word-break: break-word;
}
/* Marked, not struck through: what you wrote is still your answer, and the
   words that differ are the only thing worth looking at. */
.calm-diff-off {
  color: var(--calm-no); background: var(--calm-no-bg);
  border-radius: 4px; padding: 0 2px;
}
.calm-diff-want {
  color: var(--calm-ok); background: var(--calm-ok-bg);
  border-radius: 4px; padding: 0 2px;
}

/* The gap in a fill-in-the-blank prompt. The AI writes a literal run of
   underscores and the count varies by whoever generated it, so students
   read it as a hint about the length of the answer. One fixed-width rule
   says "a word goes here" and nothing more. */
.calm-blank {
  display: inline-block; width: 5.5em; max-width: 60%;
  border-bottom: 2px solid var(--calm-text-muted);
  margin: 0 4px; vertical-align: baseline;
}

/* ── Lists ────────────────────────────────────────────────────── */
/* Sections are separated by space, not by rules. 28px rather than 34:
   with three or four short sections on a phone the page was mostly air,
   and the gap only has to be clearly larger than the 16px used between
   related things to do its job. */
.calm-sect { margin-top: 28px; }
.calm-row { display: flex; align-items: center; gap: 12px; padding: 13px 2px; position: relative; }
.calm-row-lg { padding: 15px 2px; }
/* A row that goes somewhere says so, and the mark gives the right-hand
   side something to hold — a column of left-aligned labels against an
   empty half-screen is what makes a list look unplanned. */
a.calm-row::after {
  content: "›"; flex: 0 0 auto; margin-left: 2px;
  color: var(--calm-text-muted); font-size: 17px; line-height: 1;
}
a.calm-row > .calm-nm { flex: 1; }
/* The hairline belongs BETWEEN siblings only, inset from both edges,
   so a list reads as grouped text rather than as a table. */
.calm-row + .calm-row::before {
  content: "";
  position: absolute;
  top: 0; left: 2px; right: 2px;
  height: 1px;
  background: var(--calm-hair);
}
.calm-nm { font-size: 15px; flex: 1; min-width: 0; color: var(--calm-text); }
.calm-sub { font-size: 13px; color: var(--calm-text-muted); }
/* A disclosure's summary can carry the current value of a setting under its
   Lora title (Account). A value is not a heading: the body face, unbolded. */
details.app-disclosure > summary.calm-label .calm-sub { font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif); font-weight: 400; }
/* ...on its own line under the title. Beside it, on a phone, the title and
   the value each wrapped to two squeezed lines; stacked, the title keeps the
   row and the chevron stays level with it. */
body[data-u7-calm-core="1"] details.app-disclosure > summary.calm-label:has(> .calm-sub.block) { flex-wrap: wrap; }
details.app-disclosure > summary.calm-label:has(> .calm-sub.block)::after { order: 1; }
details.app-disclosure > summary.calm-label > .calm-sub.block { order: 2; flex-basis: 100%; }
/* A count sitting at the end of a row is a fixed marker, not text competing
   for space: it keeps its own width and stays on one line, so the numbers
   down a list line up with each other instead of wrapping at their own
   pace. Only inside a row -- .calm-sub is also used for form labels. */
.calm-row > .calm-sub { flex: 0 0 auto; text-align: right; white-space: nowrap; }

/* ── Page head ────────────────────────────────────────────────── */
/* Back stays in the page header. A floating mobile control repeatedly covered
   the last row or footer and looked like an unexplained fifth navigation tab. */
.calm-head { display: flex; align-items: flex-start; gap: 10px; margin-top: 14px; }
.calm-back {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 36px; height: 36px; margin: 2px 0 0 -8px;
  border-radius: 50%; color: var(--calm-text-muted);
  font-size: 17px; line-height: 1; text-decoration: none;
}
.calm-back:hover { background: var(--calm-hair); color: var(--calm-text); }
.calm-back-label { display: none; }
.calm-head-text { flex: 1; min-width: 0; }
.calm-head-text > .calm-title, .calm-head-text > .calm-h2 { margin-top: 2px; }

@media (max-width: 767px) {
  .calm-head { gap: 10px; }
  .calm-back {
    position: fixed; z-index: 34;
    left: max(14px, env(safe-area-inset-left, 0px));
    bottom: var(--calm-back-bottom, calc(76px + env(safe-area-inset-bottom, 0px)));
    width: 46px; height: 46px; margin: 0;
    color: var(--calm-text-soft); font-size: 18px;
    background: var(--calm-surface); box-shadow: var(--calm-lift);
  }
  .calm-back:hover, .calm-back:focus-visible { color: var(--calm-text); }
  .calm-back:active { transform: scale(.94) translateY(0); }
  @media (prefers-reduced-motion: reduce) { .calm-back:active { transform: none; } }
  /* Slides away while the page scrolls down so it never sits over the text
     being read; base.html brings it back on any scroll up, when scrolling
     stops, near the end of the page and on focus. */
  .calm-back.is-tucked { opacity: 0; transform: translateY(12px); pointer-events: none; }
  @media (prefers-reduced-motion: no-preference) { .calm-back { transition: opacity .18s ease, transform .18s ease; } }
}

@media (min-width: 768px) {
  /* Pointer, not thumb: back belongs beside the thing it goes back from.
     Reordered rather than reversed — row-reverse also flips any action a
     page puts in its head (the subject screen's "Add a topic"), and it
     landed on the far left. Ordering leaves the DOM alone, so tab order
     still reaches back before the page body. The text does not grow, so
     the arrow stays next to the title instead of being pushed to the far
     edge; a trailing action takes the right edge with margin-left:auto. */
  .calm-head { gap: 18px; }
  .calm-head-text { order: 1; flex: 0 1 auto; }
  /* Labelled on a wide screen: a lone arrow floating beside a title reads
     as a stray glyph rather than a control. */
  .calm-back {
    order: 2; margin: 7px 0 0 0;
    width: auto; height: 34px; padding: 0 14px;
    grid-auto-flow: column; gap: 8px;
    border: 1px solid var(--calm-hair); border-radius: 999px;
    font-size: 15px;
  }
  .calm-back-label { display: inline; font-size: 13.5px; }
  .calm-head > :not(.calm-head-text):not(.calm-back) { order: 3; margin-left: auto; }
}
.calm-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  /* subject.accent_hex is the app's existing, more saturated palette;
     ease it toward this one instead of duplicating the mapping. */
  filter: saturate(.72);
}
/* Subject dots are the only thing telling subjects apart at a glance, so
   they are sized to be seen, and lifted in dark mode, where the darker
   hues (indigo, violet, slate) fell to ~2:1 against the page. */
.calm-row > .calm-dot, .flex > .calm-dot { width: 9px; height: 9px; }
html.dark .calm-dot { filter: saturate(.85) brightness(1.5); }

/* Subject strength: a hairline meter, never a chunky bar. */
.calm-meter { height: 3px; border-radius: 2px; background: rgba(44, 40, 37, .06); overflow: hidden; margin-top: 9px; }
html.dark .calm-meter { background: rgba(245, 245, 244, .08); }
.calm-meter > i { display: block; height: 100%; border-radius: 2px; }

/* ── Chrome ───────────────────────────────────────────────────── */
.calm-topbar {
  background: var(--calm-bg-parchment);
  border-bottom: 1px solid var(--calm-hair);
}
/* The wordmark is the one place the brand colour belongs, and the signed-out
   pages (landing, privacy) have always used it. In the app it was plain
   ink, so the same product looked like two. */
.calm-brand { font-family: Lora, Georgia, serif; font-size: 19px; color: var(--calm-accent-text); }
.calm-navbar {
  /* Opaque, not translucent: page content scrolling underneath showed
     through as a smear of half-legible text behind the tabs. */
  background: var(--calm-surface);
  border-top: 1px solid var(--calm-hair);
}
/* Pagey's own cell at the end of the phone tab bar (the "dock" in
   companion-rig.js). An inert part of the bar: the figure is drawn into it and
   the companion button over it is the only thing to press, so Pagey is always
   there without covering the page. Pages without a companion keep four tabs. */
.calm-navbar.has-pagey-seat { grid-template-columns: repeat(4, minmax(0, 1fr)) 56px; }
body:not([data-companion-page="1"]) .calm-navbar.has-pagey-seat { grid-template-columns: repeat(4, minmax(0, 1fr)); }
body:not([data-companion-page="1"]) .calm-pagey-seat { display: none; }
.calm-navbar a { color: var(--calm-text-muted); }
.calm-navbar a.is-active { color: var(--calm-accent-text); }
.calm-navbar a.is-active svg { background:var(--calm-hair); border-radius:8px; box-shadow:0 0 0 5px var(--calm-hair); }
/* How much is due, on the Review tab. A quiet number in the accent, not a
   red alert dot: it tells you the size of today's review, not that you are
   behind. */
.calm-tab-count {
  display: inline-grid; min-width: 18px; height: 18px; place-items: center;
  margin-left: 6px; padding: 0 5px; border-radius: 999px;
  background: var(--calm-surface); color: var(--calm-accent-text);
  font-size: 11px; font-weight: 600; line-height: 1; vertical-align: 1px;
}
html.dark .calm-tab-count { background: rgba(240, 163, 90, .16); }
.calm-tab-with-count { position: relative; }
.calm-tab-with-count .calm-tab-count { position: absolute; top: 5px; left: calc(50% + 7px); margin-left: 0; font-size: 10px; min-width: 17px; height: 17px; background: var(--calm-surface); box-shadow: inset 0 0 0 1px rgba(185, 93, 10, .35); }
html.dark .calm-tab-with-count .calm-tab-count { box-shadow: inset 0 0 0 1px rgba(240, 163, 90, .4); }

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

/* ── Visibility guard ─────────────────────────────────────────── */
/* Every component above sets `display`, which quietly beats Tailwind's
   `.hidden` on the same element — so a script that hid a control by adding
   the class left it fully visible. (That is how "Keep only JSON" stayed on
   screen for pastes that had no extra text to strip.) Restate the intent at
   the end of the file rather than making each component defend itself. */
.calm-btn.hidden,
.calm-btn-quiet.hidden,
.calm-links.hidden,
.calm-choice.hidden,
.calm-scale.hidden,
.calm-pick.hidden,
.calm-row.hidden,
.calm-card.hidden,
.calm-dot.hidden { display: none; }
/* Same conflict, the other direction: `.calm-row block` is how the repair
   list asks a row to stack its topic, question and disclosure vertically.
   Losing that turned every row into three squeezed columns, the last of
   which wrapped "Check the answer" onto three lines at 375px. */
.calm-row.block,
.calm-choice.block,
.calm-links.block { display: block; }

/* ── Verdict ──────────────────────────────────────────────────── */
/* Whether you were right is the answer screen's headline, not something
   to be inferred by comparing two blocks of text. */
/* Words and a mark, not a badge. A filled pill made the verdict look like
   a status chip pinned onto the card; the answer screen only ever has one
   verdict, so it does not need to be labelled as one — it needs to be
   read. */
.calm-verdict {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-size: 15px; font-weight: 600; letter-spacing: .1px;
}
.calm-verdict-ok { color: var(--calm-ok); }
.calm-verdict-no { color: var(--calm-no); }
.calm-verdict > [aria-hidden] { font-size: 14px; }

/* Applied to the option or step the learner chose, and to the right one,
   after the answer is revealed.

   No fill. An option row spans the whole width of the card's content, so a
   tinted background became a band running edge to edge — it read as colour
   leaking out from under the card rather than as a marked answer. The
   colour lives in the text and in a rule down the left edge, which is the
   same treatment the verdict line above it uses. */
.is-right, .is-wrong { border-radius: 10px; }
.calm-pick.is-right, .calm-pick.is-wrong,
.calm-order-pill.is-right, .calm-order-pill.is-wrong { padding-left: 12px; }
.calm-pick.is-right, .calm-order-pill.is-right { box-shadow: inset 3px 0 0 var(--calm-ok); }
.calm-pick.is-wrong, .calm-order-pill.is-wrong { box-shadow: inset 3px 0 0 var(--calm-no); }
.is-right { border-color: var(--calm-ok-line); color: var(--calm-ok); }
.is-wrong { border-color: var(--calm-no-line); color: var(--calm-no); }
.is-dimmed { opacity: .42; }
/* .calm-pick is a block, not a flex row, so the tick needs its own space
   rather than relying on a gap that never applies. */
.calm-mark { flex: 0 0 auto; margin-left: 8px; font-weight: 700; }

/* ── Motion ───────────────────────────────────────────────────── */
/* Revealing an answer used to be an instant substitution, which reads as
   a glitch rather than a transition. This is short enough not to delay
   anyone and long enough for the eye to follow where the answer came
   from. */
@keyframes calm-rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
.calm-enter { animation: calm-rise .26s cubic-bezier(.33, .1, .2, 1) both; }
.calm-fade { transition: opacity .18s ease, transform .18s ease; }
/* Feedback follows the pointer or keyboard. No looping decoration, entrance
   cascades or movement of the question/answer while someone is studying. */
.calm-page :is(.calm-btn,.calm-btn-quiet,a.calm-row,.calm-choice):focus-visible {
  outline:2px solid var(--calm-accent-focus); outline-offset:4px;
}
@media (hover:hover) and (pointer:fine) {
  .calm-page:not([data-study-page="1"]) a.calm-row:hover { background:var(--calm-hair); border-radius:10px; }
  .calm-btn-quiet:not(:disabled):hover { border-color:var(--calm-accent-focus); }
}
@media (prefers-reduced-motion:no-preference) {
  .calm-btn,.calm-btn-quiet { transition:filter .16s ease,box-shadow .16s ease,border-color .16s ease,transform .16s var(--calm-motion-ease); }
  .calm-page:not([data-study-page="1"]) :is(.calm-btn,.calm-btn-quiet):not(:disabled):active { transform:translateY(1px); box-shadow:inset 0 1px 2px rgba(44,40,37,.12); }
  .calm-page:not([data-study-page="1"]) a.calm-row { transition:background-color .16s ease; }
  .calm-box { transition:border-color .16s ease,box-shadow .16s ease; }
}
.calm-box:focus { box-shadow:0 0 0 3px var(--calm-hair); }
.calm-page .submit-loading-card { border-radius:22px; border-color:var(--calm-hair); background:var(--calm-surface); box-shadow:inset 0 1px 0 var(--calm-edge-light),var(--calm-lift); }
.calm-page .submit-loading-spinner { width:28px; height:28px; margin-top:4px; border-width:2px; border-color:var(--calm-hair); border-top-color:var(--calm-accent-focus); animation-duration:1.4s; }
/* htmx sets this on the element that issued the request while it is in
   flight, so the press is acknowledged immediately even if the server
   takes a moment. */
.htmx-request.calm-btn { opacity: .62; }
@media (prefers-reduced-motion: reduce) {
  .calm-enter { animation: none; }
  .calm-fade { transition: none; }
}

/* ── Field affordance ─────────────────────────────────────────── */
/* An underline alone reads as a caption when it sits under a label and
   above a button, which is how "A note, if useful" was being missed
   entirely. Inside a form that asks for prose, give the box edges. */
.calm-box {
  width: 100%; border: 1px solid var(--calm-hair); border-radius: 12px;
  background: var(--calm-bg-parchment); padding: 11px 12px;
  color: var(--calm-text); font: inherit; outline: none; resize: vertical;
}
.calm-box:focus { border-color: var(--calm-accent-focus); }
.calm-box::placeholder { color: var(--calm-text-muted); }
/* A native select paints its own dropdown from the UA colour scheme, so
   in dark mode a transparent field gave white text on a white popup.
   An explicit surface plus color-scheme fixes both the closed control
   and the open list. */
select.calm-field, select.calm-box {
  background: var(--calm-bg-parchment); color: var(--calm-text);
  border-radius: 12px; padding: 11px 12px;
  border: 1px solid var(--calm-hair);
}
/* The closed control draws its own quiet chevron instead of the browser's
   heavy one, the same in both themes. */
select.calm-field, select.calm-box {
  -webkit-appearance: none; appearance: none; padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8178' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px 16px;
}
html.dark select.calm-field, html.dark select.calm-box { color-scheme: dark; }
html.dark select.calm-field option, html.dark select.calm-box option {
  background: var(--calm-surface); color: var(--calm-text);
}

/* ── Paste field ──────────────────────────────────────────────── */
/* Paste belongs on the box it fills, in the corner every other app puts
   it. In a row of quiet links underneath, it was invisible to anyone who
   did not already know it was there. */
/* A prompt, shown only when asked for. Every screen that offers one used a
   near-identical local copy of this. */
.calm-prompt-text {
  max-height: 15rem; overflow: auto; margin-top: 12px;
  background: var(--calm-bg-parchment); border-radius: 12px; padding: 14px;
  font-size: 12.5px; line-height: 1.5; white-space: pre-wrap;
  color: var(--calm-text-soft);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Where to take a prompt.
   Promoted out of session_prompt.html: every screen that hands you a prompt
   offers the same three assistants, and on the other screens they were plain
   quiet links that read as fine print rather than as the thing to press. */
.ai-targets { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--calm-s2); }
.ai-target {
  display: inline-flex; align-items: center; min-height: 38px; padding: 8px 13px;
  border: 1px solid var(--calm-hair); border-radius: 11px; background: var(--calm-surface);
  color: var(--calm-text-soft); font-size: 13px; text-decoration: none;
  cursor: pointer;
}
.ai-target:hover { border-color: var(--calm-accent-focus); color: var(--calm-text); }
.ai-copied { margin-top: 12px; }

.paste-wrap { position: relative; }
.paste-wrap .paste-box { padding-right: 92px; }
.paste-in-corner {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 5px 13px; border-radius: 9px;
  border: 1px solid var(--calm-hair); background: var(--calm-surface);
  color: var(--calm-text-soft); font: inherit; font-size: 12.5px; cursor: pointer;
}
.paste-in-corner:hover { border-color: var(--calm-accent-focus); color: var(--calm-text); }

/* ── Rendered notes ───────────────────────────────────────────── */
/* Notes arrive full of Markdown. Rendered as plain text, their "###" and
   "**" showed up on the page as punctuation. */
/* ── Camera sheet ─────────────────────────────────────────────── */
/* A card over the page rather than a full-screen mode. Photographing a
   page is a small errand in the middle of writing notes; the page stays
   visible behind it so dismissing puts you back where you were. */
.cam { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 18px; }
.cam[hidden] { display: none; }
.cam-scrim { position: absolute; inset: 0; background: rgba(20, 17, 15, .55); backdrop-filter: blur(2px); }
.cam-card {
  position: relative; width: 100%; max-width: 440px;
  max-height: calc(100vh - 36px); overflow-y: auto;
  background: var(--calm-surface); border-radius: 22px;
  padding: 18px 18px 20px; box-shadow: var(--calm-lift);
  animation: cam-rise .22s cubic-bezier(.4, .2, .2, 1);
}
@keyframes cam-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cam-card { animation: none; } }
.cam-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cam-x {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  border: 0; background: transparent; color: var(--calm-text-muted);
  font-size: 22px; line-height: 1; cursor: pointer;
}
.cam-x:hover { background: var(--calm-bg-parchment); color: var(--calm-text); }

/* The viewfinder. A portrait frame, because a page is taller than it is
   wide and a landscape box would waste most of the card. */
.cam-stage {
  position: relative; margin-top: 12px; border-radius: 16px; overflow: hidden;
  background: #14110f; aspect-ratio: 3 / 4;
}
.cam-stage video, .cam-stage canvas { width: 100%; height: 100%; object-fit: cover; display: block; }
.cam-stage canvas[hidden] { display: none; }

.cam-busy {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 12px; padding: 20px;
  background: rgba(20, 17, 15, .62); backdrop-filter: blur(1px); color: #fff;
}
.cam-busy[hidden] { display: none; }
.cam-busy-text { font-size: 13.5px; text-align: center; }
.cam-spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .28); border-top-color: #fff;
  animation: cam-spin .8s linear infinite;
}
@keyframes cam-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cam-spinner { animation-duration: 2.4s; } }
.cam-meter { width: 130px; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .22); overflow: hidden; }
.cam-meter i { display: block; height: 100%; width: 0; background: #fff; transition: width .2s ease; }

/* What it read, before you commit it to the notes. */
.cam-text {
  max-height: 34vh; overflow: auto; margin-top: 10px; padding: 14px;
  border-radius: 12px; background: var(--calm-bg-parchment);
  font-size: 14px; line-height: 1.6; color: var(--calm-text);
  white-space: pre-wrap; word-break: break-word;
}

/* Notes are the one thing here that is read rather than scanned, so this
   is set for reading: a measure that stops lines running the full width of
   a card, headings far enough above the body to build a hierarchy, and
   more air before a heading than after it, so a heading belongs to what
   follows it. Before this the body and the headings were within 2px of
   each other and every line ran the full 628px, which is what made a page
   of notes read as text that had simply been pasted in. */
.calm-prose { font-size: 15.5px; line-height: 1.72; color: var(--calm-text-soft); max-width: 36em; }
.calm-prose > * + * { margin-top: 14px; }
.calm-prose h2, .calm-prose h3, .calm-prose h4, .calm-prose h5, .calm-prose h6 {
  font-family: Lora, Georgia, serif; font-weight: 500; color: var(--calm-text); line-height: 1.25;
}
.calm-prose h2 { font-size: 25px; margin-top: 34px; }
.calm-prose h3 { font-size: 20px; margin-top: 30px; }
.calm-prose h4, .calm-prose h5, .calm-prose h6 { font-size: 16.5px; margin-top: 26px; }
.calm-prose h2 + *, .calm-prose h3 + *, .calm-prose h4 + *,
.calm-prose h5 + *, .calm-prose h6 + * { margin-top: 10px; }
.calm-prose > :first-child { margin-top: 0; }
.calm-prose ul, .calm-prose ol { padding-left: 20px; }
.calm-prose ul { list-style: disc; }
.calm-prose ol { list-style: decimal; }
.calm-prose li { padding-left: 3px; }
.calm-prose li + li { margin-top: 7px; }
.calm-prose li::marker { color: var(--calm-text-muted); }
.calm-prose strong { color: var(--calm-text); font-weight: 600; }
/* A first paragraph that introduces the note, given a little more presence
   than the body that follows it. */
.calm-prose > p:first-child { font-size: 16.5px; color: var(--calm-text); }
/* A link inside a paragraph keeps the paragraph's size: .calm-link's 13px
   is for links standing on their own. */
.calm-prose .calm-link, .calm-note .calm-link, .calm-prose a { font-size: inherit; }
.calm-prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92em;
  background: var(--calm-bg-parchment); border-radius: 5px; padding: 1px 5px;
}
/* A block of code keeps its lines and scrolls sideways on its own. */
.calm-prose pre {
  overflow-x: auto; background: var(--calm-bg-parchment); border-radius: 10px;
  padding: 12px 14px; font-size: 13px; line-height: 1.55;
}
.calm-prose pre code { background: none; padding: 0; font-size: inherit; white-space: pre; }
/* Notes full of "term | definition" arrive as tables. The wrapper scrolls on
   its own so a wide one never pushes the page sideways on a phone; rows are
   separated by hairlines rather than boxed in, so a table reads as part of
   the note instead of as a spreadsheet dropped into it. */
.calm-prose-table { overflow-x: auto; margin-top: 14px; }
.calm-prose table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
.calm-prose th, .calm-prose td {
  padding: 8px 12px 8px 0; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--calm-hair);
}
.calm-prose th {
  font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--calm-text-muted); font-weight: 600; white-space: nowrap;
}
.calm-prose td { color: var(--calm-text-soft); }
.calm-prose tbody tr:last-child td { border-bottom: 0; }

/* Read-only operational tables: open rows and inset hairlines rather than
   boxed spreadsheet cells. The wrapper owns horizontal overflow on phones. */
.calm-table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 13px; }
.calm-table th, .calm-table td { padding: 11px 12px; text-align: left; border-bottom: 1px solid var(--calm-hair); }
.calm-table th { color: var(--calm-text-muted); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; font-weight: 600; }
.calm-table td { color: var(--calm-text-soft); }
.calm-table tbody tr:last-child td { border-bottom: 0; }

/* ── File input ───────────────────────────────────────────────── */
/* A bare file input renders its button in the browser's own chrome, which
   on this page was indistinguishable from the label above it. */
.calm-file { display: block; width: 100%; font-size: 13px; color: var(--calm-text-soft); }
.calm-file::file-selector-button {
  margin-right: 12px; min-height: 36px; padding: 7px 13px;
  border: 1px solid var(--calm-hair); border-radius: 11px;
  background: var(--calm-surface); color: var(--calm-text-soft);
  font: inherit; font-size: 13px; cursor: pointer;
}
.calm-file::file-selector-button:hover { border-color: var(--calm-accent-focus); color: var(--calm-text); }

/* ── More menu ────────────────────────────────────────────────── */
/* A dropdown is a list of destinations, not a page section, so its rows do
   not take the chevron a.calm-row carries elsewhere. */
.calm-menu { padding: 0; overflow: hidden; }
.calm-menu-who { padding: 14px 16px 12px; border-bottom: 1px solid var(--calm-hair); }
.calm-menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 12px 16px; min-height: 44px;
  background: none; border: 0; text-align: left;
  color: var(--calm-text); font: inherit; font-size: 14px;
  text-decoration: none; cursor: pointer;
}
.calm-menu-item:hover { background: var(--calm-hair); }
.calm-menu-split { height: 1px; margin: 4px 0; background: var(--calm-hair); }
.calm-menu-out { color: var(--calm-no); }

/* ── Study actions and focused cards ─────────────────────────── */

/* Source evidence and issue reporting are temporary focused cards over the
   current study screen, rather than expanding the question until its layout
   loses shape. Shared because readings, exercises and flashcards all use it. */
.calm-study-modal[hidden] { display: none; }
.calm-study-modal { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 20px; }
.calm-study-modal-veil { position: absolute; inset: 0; background: rgba(35,31,27,.36); }
.calm-study-modal-card { position: relative; width: min(560px,100%); max-height: min(680px,calc(100vh - 40px)); overflow: auto; overscroll-behavior: contain; background: var(--calm-surface); border-radius: 22px; box-shadow: var(--calm-lift); padding: 24px 22px 22px; }
/* The way out stays in the corner while a long card scrolls under it. It
   floats, so a long title wraps beside it instead of running beneath. */
.calm-study-modal-close { position: sticky; top: -14px; z-index: 2; float: right; width: 44px; height: 44px; margin: -14px -10px 0 8px; border-radius: 50%; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); color: var(--calm-text-muted); font-size: 20px; line-height: 1; }
/* While a card, the lookup drawer or the chat is open the page behind stays
   put. Without this a scroll over the card moved the question underneath,
   and the card itself appeared to scroll through nothing. The page scrolls
   on <html>, so hiding overflow on <body> alone (as the chat does) left it
   moving. */
html:has(.calm-study-modal:not([hidden])), html:has(#lookup-drawer:not(.hidden)), html:has(#companion-chat-panel.open) { overflow: hidden; }
/* "Look it up" is offered inside the source card, so the drawer opens over it. */
#lookup-drawer { z-index: 85; }
#lookup-results { overscroll-behavior: contain; }
.calm-source-evidence { margin-top: 18px; padding: 16px; border-radius: 16px; background: rgba(91,122,90,.09); }
html.dark .calm-source-evidence { background: rgba(139,168,137,.10); }
.calm-source-quote { margin-top: 6px; font: 500 16px/1.5 Lora,Georgia,serif; color: var(--calm-text); }
.calm-source-context { margin-top: 12px; }
.calm-source-context > summary { display: flex; min-height: 44px; align-items: center; color: var(--calm-text-muted); font-size: 13px; cursor: pointer; list-style: none; }
.calm-source-context > summary::-webkit-details-marker { display: none; }
.calm-source-context > summary::after { content: '+'; margin-left: 7px; font-size: 16px; }
.calm-source-context[open] > summary::after { content: '−'; }
.calm-source-notes { max-height: min(340px, 46vh); overflow: auto; margin-top: 8px; padding: 16px 17px; border-radius: 14px; background: var(--calm-bg-parchment); scroll-padding-block:80px; overscroll-behavior: contain; }
/* The passage the answer comes from: one continuous band, so it reads as
   "this part" at a glance inside the surrounding notes. No side padding, so
   the pieces a bold or italic word splits it into join without seams. */
.calm-source-notes mark { background: rgba(91,122,90,.26); color: inherit; border-radius: 3px; padding: 2px 0; box-decoration-break:clone; -webkit-box-decoration-break:clone; }
html.dark .calm-source-notes mark { background: rgba(127,176,124,.3); }
@media (prefers-reduced-motion: no-preference) {
  @keyframes calm-passage-arrive { 0% { background-color: rgba(91,122,90,.55); } 100% { background-color: rgba(91,122,90,.24); } }
  .calm-source-notes mark.is-arriving { animation: calm-passage-arrive 1.2s ease-out 1; }
}
.calm-source-notes p, .calm-source-notes li { font-size:13.5px; line-height:1.62; }
.calm-source-notes p + p, .calm-source-notes ul + p, .calm-source-notes ol + p { margin-top:10px; }
.calm-source-reason { margin-top: 18px; padding-top: 2px; }
.calm-source-status { display:inline-flex; margin-top:12px; padding:5px 9px; border-radius:999px; background:var(--calm-hair); color:var(--calm-text-muted); font-size:11.5px; font-weight:600; }
.calm-report-sent { margin-top:18px; padding:16px; border-radius:16px; background:rgba(91,122,90,.09); }
html.dark .calm-report-sent { background:rgba(139,168,137,.10); }
.calm-source-actions { justify-content: flex-start; gap: 16px; margin-top: 16px; }
/* The source and reporting under a card or answer: two equal, quiet
   actions side by side, so neither looks like the next step. */
.calm-study-tools-actions { display: flex; flex-wrap: wrap; justify-content: center; width: min(100%,420px); gap: 2px 14px; margin: 16px auto 0; }
.calm-study-tools-actions button { display: inline-flex; min-width: 0; min-height: 44px; align-items: center; justify-content: center; gap: 7px; padding: 8px 10px; border-radius: 11px; background: transparent; color: var(--calm-text-soft); font-size: 13.5px; }
.calm-study-tools-actions button:hover { background: var(--calm-hair); }
.calm-study-tools-single { display:flex; width:auto; justify-content:center; }
.calm-study-tools-single button { min-width:min(100%,190px); }
.calm-study-tools-single button:first-child,
html.dark .calm-study-tools-single button:first-child { background:transparent; }
.calm-upload-choice { display:flex; align-items:center; gap:10px; margin:16px 0 12px; color:var(--calm-text-muted); font-size:12px; }
.calm-upload-choice::before, .calm-upload-choice::after { content:''; height:1px; flex:1; background:var(--calm-hair); }
.calm-voice-answer { display:flex; align-items:center; justify-content:center; gap:12px; margin-top:10px; }
.calm-voice-answer .calm-btn-quiet { flex:0 0 auto; min-height:44px; }
.calm-voice-answer .calm-btn-quiet svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; }
.calm-voice-answer .calm-sub { max-width:290px; }
@media (max-width:480px) { .calm-voice-answer { align-items:stretch; flex-direction:column; gap:7px; text-align:center; } }
.calm-study-tools-actions svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ── Shared study-stage geometry ─────────────────────────────── */
/* Session, deck and mixed-review screens deliberately share one visual
   grammar. Keeping it here prevents a template-local tweak from shrinking
   controls or reintroducing a nested-card layout on only one study mode. */
.calm-session-card { padding:28px 26px 25px; }
.calm-session-card.calm-study-depth { box-shadow:0 7px 0 -3px var(--calm-surface),0 12px 0 -6px rgba(44,40,37,.075),var(--calm-lift); }
.calm-session-card > .calm-title { max-width:36rem; }
.calm-answer-action, .calm-flashcard-primary, .calm-word-primary { max-width:330px; margin-left:auto; margin-right:auto; }
.calm-prompt-long { font-size:25px; line-height:1.22; }
.calm-order-title { font-size:25px; line-height:1.18; }
.calm-help { width:min(100%,340px); margin:14px auto 0; text-align:center; }
.calm-help > summary { display:inline-flex; min-height:44px; align-items:center; padding:8px 12px; color:var(--calm-text-muted); font-size:13px; cursor:pointer; list-style:none; }
.calm-help > summary::-webkit-details-marker { display:none; }
.calm-help > summary::after { content:'+'; margin-left:7px; font-size:16px; line-height:1; }
.calm-help[open] > summary::after { content:'−'; }
.calm-help-actions { display:flex; justify-content:center; gap:2px; padding:4px; border-radius:14px; background:rgba(44,40,37,.04); text-align:center; }
html.dark .calm-help-actions { background:rgba(245,245,244,.05); }
.calm-help-actions button { display:inline-flex; min-width:0; min-height:44px; align-items:center; justify-content:center; gap:6px; padding:8px 10px; border:0; border-radius:11px; background:transparent; color:var(--calm-text-muted); font:500 11.5px/1.2 inherit; }
.calm-help-actions svg { width:15px; height:15px; flex:0 0 auto; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.calm-help-actions button:hover, .calm-help-actions button:focus-visible { background:var(--calm-surface); color:var(--calm-text); }
.calm-hint-stack { display:grid; gap:8px; }
.calm-hint-slip { position:relative; padding:13px 14px 13px 17px; border-radius:14px; background:rgba(91,122,90,.085); color:var(--calm-text); }
.calm-hint-slip::before { content:''; position:absolute; left:0; top:12px; bottom:12px; width:3px; border-radius:999px; background:#5b7a5a; opacity:.62; }
.calm-hint-slip.is-new { animation:calm-hint-in 520ms var(--u-motion-ease,ease) both; }
@keyframes calm-hint-in { from { opacity:0; transform:translateX(18px) rotate(.5deg); } to { opacity:1; transform:none; } }
.calm-order-list { margin-top:16px; overflow:hidden; border-radius:14px; background:rgba(44,40,37,.035); }
html.dark .calm-order-list { background:rgba(245,245,244,.045); }
.calm-order-pill { display:flex; align-items:center; gap:10px; padding:11px 10px 11px 12px; }
.calm-order-pill + .calm-order-pill { border-top:1px solid var(--calm-hair); }
.calm-order-rank { display:grid; flex:0 0 24px; width:24px; height:24px; place-items:center; border-radius:50%; background:rgba(44,40,37,.07); color:var(--calm-text-muted); font-size:12px; font-weight:600; }
html.dark .calm-order-rank { background:rgba(245,245,244,.10); }
.calm-order-text { flex:1; min-width:0; color:var(--calm-text); font-size:13.5px; line-height:1.35; }
.calm-order-moves { display:flex; flex:0 0 auto; gap:2px; align-items:center; }
.calm-order-move { display:grid; width:32px; height:32px; place-items:center; color:var(--calm-text-muted); border-radius:9px; font-size:16px; }
.calm-order-move:focus-visible, .calm-order-move:hover { background:rgba(44,40,37,.07); color:var(--calm-text); }
.calm-order-move:disabled { cursor:default; opacity:.25; background:transparent; }
.calm-order-grip { display:grid; flex:0 0 26px; width:26px; height:34px; place-items:center; color:var(--calm-text-muted); font-size:15px; cursor:grab; touch-action:none; }
.calm-order-pill.is-dragging { position:relative; z-index:2; background:var(--calm-surface); box-shadow:var(--calm-lift); border-radius:12px; cursor:grabbing; }
.calm-order-list.is-reordering { cursor:grabbing; }
#mc-options .calm-pick { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:10px; padding-left:10px; padding-right:10px; }
#mc-options .calm-pick.is-right { background:var(--calm-ok-bg); color:var(--calm-ok); box-shadow:none; }
#mc-options .calm-pick.is-wrong { background:var(--calm-no-bg); color:var(--calm-no); box-shadow:none; }
#mc-options .calm-pick.is-right input, #mc-options .calm-pick.is-wrong input { display:none; }
#mc-options .calm-pick.is-right, #mc-options .calm-pick.is-wrong { grid-template-columns:minmax(0,1fr) auto; }
#mc-options .calm-mark { display:grid; width:22px; height:22px; place-items:center; margin-left:0; }
#mc-options .calm-mark svg { width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:2.3; stroke-linecap:round; stroke-linejoin:round; }
/* Picking an option checks it at once; this is the brief moment between the
   tap and the verdict, so the tap visibly landed. */
#mc-options .calm-pick.is-chosen:not(.is-right):not(.is-wrong) { background:rgba(44,40,37,.06); }
html.dark #mc-options .calm-pick.is-chosen:not(.is-right):not(.is-wrong) { background:rgba(245,245,244,.08); }
/* With options on screen the reveal is only the "I don't know" exit, so it
   is quiet and centred rather than a second primary action. */
.calm-reveal-unsure { display:flex; margin-left:auto; margin-right:auto; }
.calm-reason { color:var(--calm-text); max-width:36rem; }
/* Keyboard hints appear only where there is a keyboard to use them. */
.calm-kbd { display:none; }
@media (hover:hover) and (pointer:fine) {
  .calm-kbd { display:inline-grid; min-width:20px; height:20px; place-items:center; padding:0 5px; border:1px solid var(--calm-hair); border-radius:6px; font:600 11px/1 inherit; color:var(--calm-text-muted); background:rgba(44,40,37,.03); }
  .calm-choice .calm-kbd { margin-left:auto; }
  .calm-btn .calm-kbd { margin-left:8px; border-color:rgba(255,255,255,.35); color:inherit; background:transparent; opacity:.8; vertical-align:1px; }
  html.dark .calm-kbd { background:rgba(245,245,244,.05); }
}
.calm-flashcard-page { width:100%; max-width:44rem; min-height:calc(100dvh - var(--session-progress-h, 88px) - var(--session-nav-h, 62px)); display:flex; flex-direction:column; justify-content:center; }
.calm-flashcard-wrap { --calm-flashcard-height:clamp(260px,calc(100dvh - var(--session-progress-h, 88px) - var(--session-nav-h, 62px) - 72px),400px); position:relative; display:flex; min-height:calc(var(--calm-flashcard-height) + 36px); flex-direction:column; justify-content:center; padding:24px 0 12px; perspective:1000px; }
/* Short cards stay centered; long cards grow and use normal page scrolling. */
.calm-flashcard-stage { position:relative; z-index:3; display:flex; width:100%; min-height:var(--calm-flashcard-height); flex-direction:column; justify-content:center; background:var(--calm-surface); border-radius:26px; box-shadow:var(--calm-lift); padding:30px 28px 28px; touch-action:pan-y; transform-origin:50% 90%; }
/* The cards still to come, drawn as real cards under the current one: solid,
   outlined, only as many as are actually left (the template adds has-next /
   has-more), and never faded on reveal. While the top card is dragged
   (--swipe-progress, 0..1, set by study-swipes.js) the next card rises toward
   the front, and on commit it arrives there — so a swiped card always
   uncovers the next one instead of empty space. The last card has nothing
   under it, truthfully. */
.calm-flashcard-wrap.has-next::after, .calm-flashcard-wrap.has-more::before { content:''; position:absolute; left:0; right:0; top:calc(50% + 6px); height:var(--calm-flashcard-height); border-radius:26px; background:var(--calm-surface); border:1px solid var(--calm-hair, rgba(44,40,37,.08)); box-shadow:0 1px 2px rgba(44,40,37,.04),0 10px 24px -14px rgba(44,40,37,.22); pointer-events:none; transform-origin:50% 100%; }
.calm-flashcard-wrap.has-next::after { z-index:2; transform:translateY(-50%) translateY(calc(9px * (1 - var(--swipe-progress, 0)))) scale(calc(.965 + .035 * var(--swipe-progress, 0))); }
.calm-flashcard-wrap.has-more::before { z-index:1; background:var(--calm-bg-parchment, var(--calm-surface)); transform:translateY(-50%) translateY(17px) scale(.93); }
.calm-flashcard-wrap.has-next::after { transition:transform 220ms var(--u-motion-ease,ease); }
.calm-flashcard-wrap:has(.is-swiping)::after { transition:none; }
.calm-flashcard-wrap.is-swipe-committing.has-next::after { transition:transform 190ms var(--u-motion-ease,ease); transform:translateY(-50%); }
.calm-flashcard-stage.is-swiping { transition:none; cursor:grabbing; }
.calm-flashcard-stage.is-swipe-settling { transition:transform 220ms var(--u-motion-ease,ease); }
.calm-flashcard-wrap.is-swipe-committing .calm-flashcard-stage { transition:transform 220ms var(--u-motion-ease,ease),opacity 220ms ease; opacity:.0; }
.calm-flashcard-wrap.is-swipe-committing-left .calm-flashcard-stage { transform:translate3d(-115vw,0,0) rotate(-7deg)!important; }
.calm-flashcard-wrap.is-swipe-committing-right .calm-flashcard-stage { transform:translate3d(115vw,0,0) rotate(7deg)!important; }
/* The grade colour lives ON the moving card, so it fills exactly the card's
   frame and travels with it. (A full-screen wash used to sit inside the
   wrap, whose perspective made it a containing block, so the "screen" tint
   was a stray rectangle the size of the wrap.) */
.calm-flashcard-stage { --swipe-strength:0; background-image:linear-gradient(rgba(var(--swipe-rgb, 65,133,83), calc(var(--swipe-strength) * .26)), rgba(var(--swipe-rgb, 65,133,83), calc(var(--swipe-strength) * .26))); box-shadow:var(--calm-lift), inset 0 0 0 calc(var(--swipe-strength) * 2px) rgba(var(--swipe-rgb, 65,133,83), calc(var(--swipe-strength) * .7)); }
.calm-flashcard-stage[data-swipe-direction="left"] { --swipe-rgb:181,76,66; }
.calm-flashcard-stage[data-swipe-direction="right"] { --swipe-rgb:65,133,83; }
html.dark .calm-flashcard-stage[data-swipe-direction="left"] { --swipe-rgb:214,110,98; }
html.dark .calm-flashcard-stage[data-swipe-direction="right"] { --swipe-rgb:110,176,122; }
.calm-swipe-cue { position:absolute; z-index:5; top:50%; min-width:72px; padding:7px 10px; border-radius:999px; color:white; font-size:12px; font-weight:700; text-align:center; pointer-events:none; opacity:0; transform:translateY(-50%); }
.calm-swipe-cue-left { left:12px; background:#9f4b43; }
.calm-swipe-cue-right { right:12px; background:#4c7655; }
.calm-swipe-note { color:var(--calm-text-muted); font-size:11.5px; text-align:center; }
.calm-flashcard-stage .calm-title { max-width:34rem; margin-left:auto; margin-right:auto; }
.calm-flashcard-answer { margin-top:26px; padding-top:22px; border-top:1px solid var(--calm-hair); }
.calm-flashcard-source { margin-top:12px; padding:0 8px 18px; }
.calm-review-stage { display:flex; flex-direction:column; justify-content:center; min-height:calc(100vh - 260px); }
.calm-word-wrap { display:flex; min-height:0; flex:1; align-items:center; }
.calm-word-wrap.is-revealed { min-height:0; align-items:center; }
.calm-word-card { width:100%; padding:34px 28px 30px; text-align:center; }
.calm-word { font:500 clamp(31px,7vw,44px)/1.12 Lora,Georgia,serif; color:var(--calm-text); overflow-wrap:anywhere; }
.calm-speak { display:inline-grid; width:44px; height:44px; place-items:center; margin-left:4px; border-radius:50%; color:var(--calm-text-muted); vertical-align:middle; }
.calm-speak:hover, .calm-speak:focus-visible { background:var(--calm-hair); color:var(--calm-text); }
.calm-speak svg { width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:1.8; }
.calm-word-tools { display:flex; min-height:44px; align-items:center; justify-content:center; gap:18px; margin-top:14px; color:var(--calm-text-muted); font-size:13px; }
.calm-prompt-text { min-height:8rem; }

/* Generation keeps the current page perceptible instead of replacing it
   with an opaque wait screen. Pagey works at this one quiet status card. */
.calm-page #submit-loading-cover { background:rgba(246,241,231,.58); backdrop-filter:blur(4px); }
html.dark .calm-page #submit-loading-cover { background:rgba(20,18,16,.58); }
.calm-page .submit-loading-card { border:0; border-radius:22px; background:var(--calm-surface); box-shadow:var(--calm-lift); padding:22px; }
.calm-page #submit-loading-cover[data-companion-crafting="1"] .submit-loading-card { margin-top:48px; }
.calm-page .submit-loading-spinner { width:32px; height:32px; border-width:2px; }
.calm-generation-card { min-height:310px; display:flex; flex-direction:column; justify-content:center; padding:34px 30px; }
.calm-generation-orbit { position:relative; width:54px; height:32px; margin-bottom:22px; }
.calm-generation-orbit i { position:absolute; top:12px; width:8px; height:8px; border-radius:50%; background:var(--calm-text-muted); animation:calm-generation-pulse 1.35s ease-in-out infinite; }
.calm-generation-orbit i:nth-child(1) { left:3px; animation-delay:-.22s; }
.calm-generation-orbit i:nth-child(2) { left:23px; }
.calm-generation-orbit i:nth-child(3) { left:43px; animation-delay:.22s; }
@keyframes calm-generation-pulse { 0%,100% { opacity:.28; transform:translateY(0); } 50% { opacity:.9; transform:translateY(-7px); } }
.calm-generation-steps { display:grid; gap:0; counter-reset:generation; }
.calm-generation-steps li { position:relative; min-height:42px; padding:3px 0 12px 30px; color:var(--calm-text-muted); font-size:13px; }
.calm-generation-steps li::before { content:''; position:absolute; left:4px; top:4px; width:12px; height:12px; border-radius:50%; background:var(--calm-hair); box-shadow:0 0 0 4px var(--calm-bg-parchment); }
.calm-generation-steps li:not(:last-child)::after { content:''; position:absolute; left:9.5px; top:20px; bottom:2px; width:1px; background:var(--calm-hair); }
.calm-generation-steps li.is-done::before { background:#5b7a5a; }
.calm-generation-steps li.is-current { color:var(--calm-text); font-weight:600; }
.calm-generation-steps li.is-current::before { background:#b95d0a; animation:calm-generation-dot 1.25s ease-in-out infinite; }
@keyframes calm-generation-dot { 50% { box-shadow:0 0 0 7px rgba(185,93,10,.12); } }

/* Exercise navigation belongs to the session, not to the card. Keeping it
   fixed makes Question n of m and Exit available while the learner works;
   the question/answer card can then remain centred in the space beneath it. */
.calm-session-progress {
  position:fixed; inset:0 0 auto; z-index:35;
  padding:14px 20px 12px;
  background:var(--calm-surface);
  border-bottom:1px solid var(--calm-hair);
  box-shadow:0 5px 16px rgba(44,40,37,.05);
}
.calm-session-progress-inner { width:100%; }
/* --session-progress-h / --session-nav-h are set from the real measured
   heights by positionStudySpacing() in calm/base.html (same pattern as
   --calm-back-bottom) rather than guessed here: a hardcoded 88px assumed a
   taller bar than it actually renders at, leaving a dead gap under the
   fixed header that then also skewed the flex-centering below it, so the
   card ended up noticeably closer to the bottom nav than to the header
   instead of centred between them. The literal px fallbacks only apply
   before that JS has run once (or if it's unavailable). */
body[data-study-page="1"] #main { padding-top:var(--session-progress-h, 88px); }
.calm-study-viewport {
  min-height:calc(100dvh - var(--session-progress-h, 88px) - var(--session-nav-h, 62px));
  display:flex;
  flex-direction:column;
  justify-content:center;
}
.calm-study-viewport .calm-session-card { width:100%; }

@media (min-width:640px) { .calm-flashcard-stage { padding:36px 42px 32px; } .calm-flashcard-source { padding:0 18px 18px; } }
@media (min-width:768px) { .calm-review-stage { min-height:calc(100vh - 230px); } }
/* On a tall phone, a short prompt used to sit at the top of the screen while
   its source/report actions were far above the thumb zone or separated by a
   large empty field. Keep the whole study unit centred in the usable space.
   Long answers naturally exceed the minimum and retain ordinary scrolling. */
@media (min-height:720px) and (max-width:767px) {
  .calm-study-viewport, .calm-flashcard-page {
    display:flex; min-height:calc(100dvh - var(--session-progress-h, 82px) - var(--session-nav-h, 62px) - 10px); flex-direction:column; justify-content:center;
  }
  body[data-study-page="1"] #main { padding-top:var(--session-progress-h, 82px); }
  .calm-flashcard-source { width:min(100%,420px); align-self:center; }
}
@media (max-width:480px) {
  .calm-session-card { padding:24px 20px 22px; }
  .calm-prompt-long { font-size:22px; line-height:1.25; }
  .calm-answer-action, .calm-flashcard-primary, .calm-word-primary { max-width:none; }
  .calm-flashcard-page { width:calc(100% + 16px); max-width:none; margin-left:-8px; margin-right:-8px; }
  .calm-flashcard-stage { padding:26px 20px 24px; }
  .calm-word-wrap, .calm-word-wrap.is-revealed { min-height:0; }
  .calm-word-card { padding:28px 20px 25px; }
}
@media (prefers-reduced-motion:reduce) { .calm-hint-slip.is-new, .calm-generation-orbit i, .calm-generation-steps li.is-current::before { animation:none; } .calm-flashcard-wrap, .calm-word-wrap, .calm-flashcard-stage, .calm-flashcard-wrap.is-swipe-committing .calm-flashcard-stage, .calm-flashcard-wrap.is-swipe-committing.has-next::after { transition:none; } }

/* ── The landing page (landing.html) ──────────────────────────────
   One column on a phone; on a wide screen the hero sits beside the
   lesson that runs in it. One heading size below the hero, one gap
   between sections, and a tinted band to set the test plan apart. */
.lp-wrap { width: 100%; max-width: 1080px; margin: 0 auto; padding-left: 20px; padding-right: 20px; }
.lp-top { min-height: 64px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.lp-nav { display: flex; align-items: center; gap: 18px; }
.lp-nav-link { color: var(--calm-text-soft); font-size: 14.5px; text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.lp-nav-link:hover { color: var(--calm-text); }
.lp-wide { display: none; }
.lp-link { color: var(--calm-accent-text); font-size: 15px; text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; background: none; border: 0; padding: 0; cursor: pointer; }
.lp-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.lp-hero { display: grid; gap: 36px; padding-top: 36px; padding-bottom: 48px; align-items: start; overflow-x: clip; }
.lp-title { font-family: Lora, Georgia, serif; font-weight: 500; letter-spacing: -.015em; color: var(--calm-text); font-size: clamp(38px, 6.4vw, 62px); line-height: 1.06; margin: 12px 0 0; max-width: 13ch; }
.lp-lede { color: var(--calm-text-soft); font-size: 17.5px; line-height: 1.6; margin-top: 18px; max-width: 32rem; }
.lp-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; margin-top: 26px; }
.lp-cta { width: auto; min-width: 230px; padding-left: 28px; padding-right: 28px; text-decoration: none; margin: 0; }
.lp-cta-center { display: flex; width: fit-content; margin: 26px auto 0; }

/* The brand with Pagey's mark; the word in the title swept with a
   highlighter; three plain facts under the button. */
.lp-brand { display: inline-flex; align-items: center; gap: 9px; }
.lp-brand img { width: 26px; height: 26px; border-radius: 7px; box-shadow: var(--calm-control-shadow); }
.lp-mark { background: linear-gradient(transparent 60%, color-mix(in srgb, var(--calm-accent-focus) 30%, transparent) 60%, color-mix(in srgb, var(--calm-accent-focus) 30%, transparent) 92%, transparent 92%) no-repeat 0 0 / 100% 100%; padding: 0 .06em; border-radius: 4px; }
.lp-facts { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 18px; padding: 0; margin: 18px 0 0; }
.lp-facts li { display: inline-flex; align-items: center; gap: 7px; color: var(--calm-text-soft); font-size: 13.5px; }
.lp-facts li::before { content: ""; width: 16px; height: 16px; border-radius: 50%; background: var(--calm-ok-bg) no-repeat center / 10px 10px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='%232f6b46' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
/* The lesson lies on a small stack of paper, in a warm pool of light,
   with Pagey looking over its top edge. */
.lp-hero-visual { position: relative; padding-top: 34px; }
.lp-hero-visual::before { content: ""; position: absolute; inset: 10% -14% -6% -14%; z-index: -1; pointer-events: none; background: radial-gradient(closest-side, color-mix(in srgb, var(--calm-accent-focus) 13%, transparent), transparent); }
.lp-hero-visual > .lp-demo { position: relative; z-index: 1; }
.lp-under { position: absolute; inset: 34px 0 0 0; z-index: 0; border-radius: 20px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair), var(--calm-lift); transform: rotate(2.6deg) translate(8px, 6px); pointer-events: none; }
.lp-under + .lp-under { transform: rotate(-1.8deg) translate(-6px, 4px); opacity: .7; }
.lp-pagey { position: absolute; z-index: 0; width: 70px; height: 74px; overflow: visible; }
.lp-pagey-peek { top: -16px; right: 34px; }
.lp-pagey-sheet { fill: #fffdf7; stroke: #7e6750; stroke-width: 1.2; }
.lp-pagey-fold { fill: #dfcaa7; stroke: #7e6750; stroke-width: 1.1; stroke-linejoin: round; }
.lp-pagey-shine { fill: none; stroke: #fff; stroke-width: 1.3; stroke-linecap: round; }
.lp-pagey-eyes { fill: #42372b; }
.lp-pagey-smile, .lp-pagey-arm { fill: none; stroke: #7e6750; stroke-width: 1.3; stroke-linecap: round; }
.lp-pagey-arm { stroke-width: 1.6; }
.lp-pagey-wave { position: relative; display: block; width: 76px; height: 80px; margin: -6px auto 6px; }
.lp-pagey-eyes ellipse { transform-box: fill-box; transform-origin: center; }

/* The lesson card. */
.lp-demo { padding: 22px 22px 18px; scroll-margin-top: 80px; }
.lp-demo-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.lp-demo-meter { height: 4px; border-radius: 2px; background: var(--calm-hair); margin-top: 12px; overflow: hidden; }
.lp-demo-meter > i { display: block; height: 100%; width: 0; background: var(--calm-ok); border-radius: 2px; }
.lp-demo:not(.is-live) .lp-demo-meter, .lp-demo:not(.is-live) [data-demo-next], .lp-demo:not(.is-live) .lp-again { display: none; }
.lp-demo:not(.is-live) .lp-step + .lp-step { border-top: 1px solid var(--calm-hair); }
.lp-step { padding-top: 18px; }
.lp-step[hidden] { display: none; }
.lp-step-h { font-family: Lora, Georgia, serif; font-weight: 500; font-size: 21px; line-height: 1.28; color: var(--calm-text); }
.lp-step-h:focus { outline: none; }
.lp-step-btn { margin-top: 20px; }
.lp-demo-foot { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--calm-hair); }
/* Notes as they were taken: a ruled page in a hand-ish slant. */
.lp-scrawl { margin-top: 14px; padding: 6px 14px 8px; border-radius: 10px; background: var(--calm-ok-bg); background: color-mix(in srgb, var(--calm-text) 4%, transparent);
  background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 29px, var(--calm-hair) 29px, var(--calm-hair) 30px); }
.lp-scrawl p { font-family: "Segoe Print", "Bradley Hand", "Comic Neue", "Chalkboard SE", cursive; font-size: 15px; line-height: 30px; color: var(--calm-text-soft); transform: rotate(-.4deg); }
.lp-scrawl p:last-child { text-decoration: line-through; text-decoration-color: var(--calm-text-muted); opacity: .75; }
.lp-study { margin-top: 12px; }
.lp-covered { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.lp-covered-mark { flex: none; width: 52px; height: 52px; }
.lp-sheet-under { fill: var(--calm-hair); }
.lp-sheet-lines { fill: none; stroke: var(--calm-text-muted); stroke-width: 1.4; stroke-linecap: round; opacity: .45; }
.lp-sheet-over { fill: var(--calm-surface); stroke: var(--calm-text-muted); stroke-width: 1.4; }
.lp-lined { display: block; width: 100%; margin-top: 12px; padding: 0; border: 0; border-radius: 0; background: transparent; color: var(--calm-text); font: inherit; font-size: 16px; line-height: 30px; resize: none;
  background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 29px, var(--calm-hair) 29px, var(--calm-hair) 30px); background-attachment: local; min-height: 92px; }
html.dark textarea.lp-lined { background-color: transparent !important; color: var(--calm-text) !important; }
.lp-lined:focus { outline: none; box-shadow: inset 0 -2px 0 var(--calm-accent-focus); }
.lp-lined::placeholder { color: var(--calm-text-muted); }
.lp-ticks { display: grid; margin-top: 10px; }
.lp-tick { display: flex; gap: 12px; align-items: flex-start; min-height: 44px; padding: 10px 2px; border-bottom: 1px solid var(--calm-hair); color: var(--calm-text-soft); font-size: 15px; line-height: 1.45; cursor: pointer; }
.lp-tick:last-child { border-bottom: 0; }
.lp-tick input { flex: none; width: 20px; height: 20px; margin-top: 1px; accent-color: var(--calm-ok); }
.lp-options { display: grid; gap: 8px; margin-top: 14px; }
.lp-option { width: 100%; justify-content: flex-start; text-align: left; }
.lp-option.is-right { border-color: var(--calm-ok-line); background: var(--calm-ok-bg); color: var(--calm-ok); }
.lp-option.is-wrong { border-color: var(--calm-no-line); background: var(--calm-no-bg); color: var(--calm-no); }
.lp-option:disabled { cursor: default; opacity: 1; }
.lp-feedback { margin-top: 12px; font-size: 15px; line-height: 1.5; min-height: 0; }
.lp-feedback.is-right { color: var(--calm-ok); }
.lp-feedback.is-wrong { color: var(--calm-no); }
.lp-timeline { list-style: none; margin: 14px 0 0; padding: 0; position: relative; }
.lp-timeline::before { content: ""; position: absolute; left: 6px; top: 12px; bottom: 12px; width: 2px; background: var(--calm-hair); }
.lp-timeline li { position: relative; display: grid; grid-template-columns: 112px 1fr; gap: 10px; padding: 8px 0 8px 24px; font-size: 15px; color: var(--calm-text); }
.lp-timeline li::before { content: ""; position: absolute; left: 1px; top: 14px; width: 12px; height: 12px; border-radius: 50%; background: var(--calm-surface); border: 2px solid var(--calm-text-muted); }
.lp-timeline li.is-done::before { background: var(--calm-ok); border-color: var(--calm-ok); }
.lp-timeline li.is-test::before { border-color: var(--calm-accent-focus); }
.lp-when { color: var(--calm-text-muted); font-size: 13.5px; padding-top: 1px; }
.lp-again { margin-top: 4px; text-align: center; }

/* The sections below the hero are the pages of a book: paper with a spine
   on the left, a stack of pages under it, a folio at the foot and a corner
   to turn. With .is-book (the script ran, motion is welcome) each page
   turns down onto the stack about its spine as it scrolls in: --turn goes
   from 1 (standing up, mid-turn) to 0 (lying flat). */
.lp-book { overflow-x: clip; padding: 8px 0 24px; perspective: 1800px; perspective-origin: 30% 50%; }
.lp-page { --turn: 0; position: relative; padding: 18px 16px; }
.lp-leaf {
  position: relative; max-width: 1040px; margin: 0 auto; padding: 40px 26px 52px 34px;
  border-radius: 6px 20px 20px 6px; background: var(--calm-surface); color: var(--calm-text);
  /* The pages under this one, and the shadow the book casts. */
  box-shadow: 2px 2px 0 -1px var(--calm-surface), 3px 3px 0 -1px var(--calm-hair), 5px 5px 0 -2px var(--calm-surface), 6px 6px 0 -2px var(--calm-hair), var(--calm-lift);
  transform-origin: left center; transform-style: preserve-3d; backface-visibility: hidden;
}
/* The spine: a fold of shade along the left edge. */
.lp-leaf::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 34px; border-radius: 6px 0 0 6px; pointer-events: none;
  background: linear-gradient(to right, color-mix(in srgb, var(--calm-text) 12%, transparent), color-mix(in srgb, var(--calm-text) 3%, transparent) 40%, transparent);
}
/* The corner to turn, at the foot of the page. */
.lp-leaf::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 34px; height: 34px; border-radius: 0 0 20px 0; pointer-events: none;
  background: linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--calm-text) 10%, var(--calm-surface)) 50%, var(--calm-surface) 75%);
  box-shadow: -3px -3px 6px -4px rgba(44, 40, 37, .35);
}
.lp-chapter { font-family: Lora, Georgia, serif; font-style: italic; color: var(--calm-accent-text); font-size: 15px; text-align: center; }
.lp-split .lp-chapter { text-align: left; }
.lp-folio { position: absolute; left: 0; right: 0; bottom: 16px; text-align: center; font-family: Lora, Georgia, serif; font-size: 13px; color: var(--calm-text-muted); letter-spacing: .1em; }
.lp-folio::before, .lp-folio::after { content: "—"; margin: 0 8px; opacity: .6; }
.lp-chapter + .lp-h { margin-top: 6px; }
body.is-book .lp-leaf {
  transform: rotateY(calc(var(--turn) * -72deg)) translateZ(0);
  opacity: calc(1 - var(--turn) * .55);
  will-change: transform;
}
/* The light falling on a page as it turns: darker the more it stands up. */
body.is-book .lp-page::after {
  content: ""; position: absolute; inset: 18px 16px; max-width: 1040px; margin: 0 auto; border-radius: 6px 20px 20px 6px; pointer-events: none;
  background: linear-gradient(to left, rgba(44, 40, 37, .28), rgba(44, 40, 37, 0) 70%);
  opacity: calc(var(--turn) * 1.2); transform-origin: left center; transform: rotateY(calc(var(--turn) * -72deg));
}
.lp-close .lp-leaf { text-align: center; }
/* Under the hero: a page corner that lifts, inviting the first turn. */
.lp-turn-cue { display: flex; align-items: center; justify-content: center; gap: 10px; width: fit-content; margin: -8px auto 8px; min-height: 44px; padding: 0 14px; color: var(--calm-text-soft); font-size: 14px; text-decoration: none; transition: opacity .4s ease; }
.lp-turn-cue.is-gone { opacity: 0; pointer-events: none; }
.lp-corner { position: relative; width: 22px; height: 26px; border-radius: 2px 4px 4px 2px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair), 2px 2px 0 -1px var(--calm-surface), 3px 3px 0 -1px var(--calm-hair); overflow: hidden; }
.lp-corner::after { content: ""; position: absolute; right: 0; bottom: 0; width: 10px; height: 10px; background: linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--calm-text) 18%, var(--calm-surface)) 50%); transform-origin: right bottom; }
.lp-cue-narrow { display: none; }
@media (pointer: coarse) { .lp-cue-wide { display: none; } .lp-cue-narrow { display: inline; } }
/* How far through the book: a bookmark ribbon across the top. */
.lp-ribbon { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 60; pointer-events: none; }
.lp-ribbon > i { display: block; height: 100%; background: var(--calm-accent-focus); transform: scaleX(0); transform-origin: left center; }
/* The lesson as a notebook: ring holes down its left edge, and each step
   turning in like the next page. */
.lp-demo { position: relative; padding-left: 40px !important; }
.lp-demo::before {
  content: ""; position: absolute; left: 12px; top: 20px; bottom: 20px; width: 12px; pointer-events: none;
  background: radial-gradient(circle at 6px 6px, var(--calm-hair) 0 4.5px, transparent 5px) 0 0 / 12px 30px repeat-y;
}
@media (prefers-reduced-motion: no-preference) {
  .lp-step.is-turning { transform-origin: left center; animation: lp-page-in .55s cubic-bezier(.2, .7, .25, 1) both; }
}
@keyframes lp-page-in {
  from { transform: perspective(1200px) rotateY(-68deg); opacity: 0; filter: brightness(.92); }
  60% { opacity: 1; }
  to { transform: none; opacity: 1; filter: none; }
}
.lp-h { font-family: Lora, Georgia, serif; font-weight: 500; letter-spacing: -.01em; font-size: clamp(26px, 3.4vw, 34px); line-height: 1.18; color: var(--calm-text); text-align: center; }
.lp-h-left { text-align: left; margin-top: 8px; }
.lp-h3 { font-family: Lora, Georgia, serif; font-weight: 600; font-size: 17.5px; color: var(--calm-text); margin-top: 12px; }
.lp-how { list-style: none; padding: 0; margin: 30px 0 0; display: grid; gap: 26px; }
.lp-how li .calm-note { margin-top: 6px; }
.lp-num { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; font-family: Lora, Georgia, serif; font-size: 16px; font-weight: 600; color: var(--calm-accent-text); background: var(--calm-surface); border: 1px solid var(--calm-hair); box-shadow: var(--calm-control-shadow); }
/* Each step drawn, numbered at its corner, and joined to the next by a
   dashed line on a wide screen. */
.lp-how li { position: relative; }
@media (max-width: 639px) {
  .lp-how li { display: grid; grid-template-columns: 54px 1fr; column-gap: 16px; align-items: start; }
  .lp-how li .lp-step-icon { grid-row: span 2; }
  .lp-how li .lp-h3 { margin-top: 2px; }
}
.lp-step-icon { position: relative; display: inline-grid; place-items: center; width: 54px; height: 54px; border-radius: 16px; background: color-mix(in srgb, var(--calm-accent-focus) 10%, var(--calm-surface)); box-shadow: 0 0 0 1px var(--calm-hair); }
.lp-step-icon svg { width: 26px; height: 26px; fill: none; stroke: var(--calm-accent-text); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lp-step-icon b { position: absolute; top: -7px; right: -7px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-family: Lora, Georgia, serif; font-size: 12.5px; font-weight: 600; color: #fff; background: var(--calm-accent-focus); box-shadow: 0 0 0 3px var(--calm-surface); }
html.dark .lp-step-icon b { color: #241f1a; }
/* Why it works: three research-backed principles. */
.lp-why { display: grid; gap: 22px; margin-top: 30px; }
.lp-why article { position: relative; padding: 18px 18px 16px; border-radius: 16px; background: color-mix(in srgb, var(--calm-text) 3%, transparent); }
.lp-why-mark { position: absolute; top: -6px; left: 14px; font-family: Lora, Georgia, serif; font-size: 54px; line-height: 1; color: color-mix(in srgb, var(--calm-accent-focus) 45%, transparent); }
.lp-why .lp-h3 { margin-top: 18px; }
.lp-why .calm-note { margin-top: 6px; }
.lp-why-src { margin-top: 10px; font-family: Lora, Georgia, serif; font-style: italic; font-size: 13px; color: var(--calm-text-muted); }
.lp-split { display: grid; gap: 28px; align-items: center; }
.lp-split-text { margin-top: 14px; max-width: 30rem; }
.lp-week { padding: 8px 20px; }
.lp-day { display: grid; grid-template-columns: 48px 1fr; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--calm-hair); }
.lp-day:last-child { border-bottom: 0; }
.lp-day-name { font-family: Lora, Georgia, serif; font-weight: 600; color: var(--calm-text-muted); font-size: 15px; }
.lp-day-task { color: var(--calm-text); font-size: 15px; line-height: 1.4; }
.lp-day-task .calm-sub { display: block; margin-top: 2px; }
.lp-day.is-revision .lp-day-name, .lp-day.is-revision .lp-day-task { color: var(--calm-accent-text); }
.lp-day.is-test .lp-day-name { color: var(--calm-text); }
.lp-features { display: grid; gap: 14px; margin-top: 30px; }
.lp-feature { padding: 20px; border-radius: 16px; background: var(--calm-surface); border: 1px solid var(--calm-hair); }
.lp-feature svg { width: 26px; height: 26px; fill: none; stroke: var(--calm-accent-text); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lp-feature .lp-h3 { margin-top: 10px; }
.lp-feature .calm-note { margin-top: 4px; }
.lp-close { padding-bottom: 48px; }
.lp-foot { padding-top: 24px; padding-bottom: 32px; justify-content: center; align-items: center; border-top: 1px solid var(--calm-hair); }
@media (min-width: 640px) {
  .lp-wide { display: inline-flex; }
  .lp-how { grid-template-columns: repeat(3, 1fr); gap: 32px; }
  .lp-how li:not(:last-child)::after { content: ""; position: absolute; top: 27px; left: 70px; right: -20px; border-top: 1.5px dashed color-mix(in srgb, var(--calm-text) 18%, transparent); }
  .lp-page { padding: 26px 24px; }
  .lp-leaf { padding: 56px 48px 64px 60px; }
  body.is-book .lp-page::after { inset: 26px 24px; }
  .lp-features { grid-template-columns: repeat(2, 1fr); }
  .lp-demo { padding: 26px 28px 20px; }
}
@media (min-width: 960px) {
  .lp-hero { grid-template-columns: 1.05fr .95fr; gap: 56px; padding-top: 72px; padding-bottom: 72px; align-items: center; }
  .lp-try-link { display: none; }
  .lp-split { grid-template-columns: 1fr 1fr; gap: 56px; }
  .lp-features { grid-template-columns: repeat(4, 1fr); }
  .lp-why { grid-template-columns: repeat(3, 1fr); gap: 20px; }
  .lp-pagey-peek { right: 46px; }
  .lp-page { padding: 34px 32px; }
  body.is-book .lp-page::after { inset: 34px 32px; }
}
@media (prefers-reduced-motion: no-preference) {
  .lp-mark { animation: lp-mark-in .9s cubic-bezier(.33, .1, .2, 1) .35s both; }
  @keyframes lp-mark-in { from { background-size: 0% 100%; } }
  .lp-pagey-eyes ellipse { animation: lp-blink 5.5s ease-in-out infinite; }
  @keyframes lp-blink { 0%, 46%, 50%, 100% { transform: none; } 48% { transform: scaleY(.12); } }
  .lp-pagey-peek .lp-pagey-body { animation: lp-peek 6s ease-in-out infinite; transform-origin: 50% 100%; }
  @keyframes lp-peek { 0%, 100% { transform: translateY(6px); } 40%, 70% { transform: translateY(0) rotate(-4deg); } }
  .lp-pagey-arm { animation: lp-wave 1.6s ease-in-out infinite; transform-origin: 17.5px 2px; transform-box: view-box; }
  @keyframes lp-wave { 0%, 100% { transform: rotate(0); } 50% { transform: rotate(-22deg); } }
  .lp-corner::after { animation: lp-corner-lift 2.6s ease-in-out infinite; }
  @keyframes lp-corner-lift { 0%, 60%, 100% { transform: none; } 75% { transform: scale(1.8); } }
  .lp-demo-meter > i { transition: width .35s var(--calm-motion-ease); }
}
@media (max-width: 480px) {
  .calm-study-modal { padding: 14px 14px 78px; align-items: end; }
  .calm-study-modal-card { max-height: min(620px,calc(100vh - 92px)); padding: 22px 18px 18px; }
}

/* ── Progress: answers each day ───────────────────────────────── */
/* Seven thin bars on one baseline. A single series, so no legend: the
   label above names it. Colour validated for data marks against both
   surfaces (the sage used for progress meters reads as grey at bar size). */
.calm-week-chart { --calm-week-bar: #3a8a4f; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; margin: 0; padding: 0; list-style: none; }
html.dark .calm-week-chart { --calm-week-bar: #5f9c63; }
.calm-week-day { position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; border-radius: 10px; outline: none; cursor: default; }
.calm-week-day:focus-visible { box-shadow: 0 0 0 2px var(--calm-accent-focus); }
.calm-week-plot { position: relative; display: flex; width: 100%; height: 112px; padding-top: 20px; align-items: flex-end; justify-content: center; border-bottom: 1px solid var(--calm-hair); }
.calm-week-bar { display: block; width: min(26px, 70%); border-radius: 4px 4px 0 0; background: var(--calm-week-bar); }
.calm-week-bar.is-empty { background: var(--calm-hair); border-radius: 1px; }
.calm-week-peak { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-size: 11px; font-weight: 600; color: var(--calm-text-soft); }
.calm-week-label { font-size: 11px; color: var(--calm-text-soft); white-space: nowrap; }
.calm-week-day.is-today .calm-week-label { color: var(--calm-text); font-weight: 600; }
.calm-week-tip {
  position: absolute; bottom: calc(100% - 18px); left: 50%; z-index: 3;
  padding: 6px 9px; border-radius: 9px; white-space: nowrap;
  background: var(--calm-text); color: var(--calm-surface);
  font-size: 12px; line-height: 1.2; pointer-events: none;
  opacity: 0; transform: translate(-50%, 4px);
  transition: opacity var(--u-motion-fast, 120ms) ease, transform var(--u-motion-fast, 120ms) ease;
}
.calm-week-day:first-child .calm-week-tip { left: 0; transform: translate(0, 4px); }
.calm-week-day:last-child .calm-week-tip { left: auto; right: 0; transform: translate(0, 4px); }
.calm-week-day:hover .calm-week-tip, .calm-week-day:focus-visible .calm-week-tip, .calm-week-day:focus .calm-week-tip { opacity: 1; transform: translate(-50%, 0); }
.calm-week-day:first-child:hover .calm-week-tip, .calm-week-day:first-child:focus .calm-week-tip,
.calm-week-day:last-child:hover .calm-week-tip, .calm-week-day:last-child:focus .calm-week-tip { transform: none; }
@media (prefers-reduced-motion: reduce) { .calm-week-tip { transition: none; } }
@media (forced-colors: active) { .calm-week-bar { background: CanvasText; } .calm-week-bar.is-empty { background: GrayText; } }

/* ── Account: danger zone ─────────────────────────────────────── */
/* Specific enough to win over the general card shadow, which hid this edge. */
.calm-page .calm-danger-zone .calm-card,
.calm-page:not([data-study-page="1"]) .calm-danger-zone .calm-card { box-shadow: inset 0 0 0 1px var(--calm-no-line), var(--calm-lift); }
.calm-danger-link { display: inline-flex; min-height: 44px; align-items: center; color: var(--calm-no); font-size: 14px; font-weight: 600; text-decoration: none; }
.calm-danger-link:hover, .calm-danger-link:focus-visible { text-decoration: underline; }

/* ── Option cards (onboarding) ────────────────────────────────── */
/* A choice you tap, drawn as one: an icon, the words, and either an arrow
   (the tap moves you on) or a check that fills once it is the selected
   one. The radio stays a real radio stretched over the card, so keyboard,
   screen readers and the form post behave exactly as before. */
.calm-options { display: grid; gap: 8px; }
.calm-options-pair { grid-template-columns: 1fr 1fr; }
.calm-fieldset { border: 0; margin-left: 0; margin-right: 0; padding: 0; min-width: 0; }
.calm-fieldset > legend { padding: 0; margin-bottom: 2px; }
.calm-option { position: relative; display: block; width: 100%; padding: 0; border: 0; background: none; font: inherit; text-align: left; color: var(--calm-text); cursor: pointer; }
.calm-option-input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.calm-option-body {
  display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 11px 14px;
  border: 1px solid var(--calm-hair); border-radius: 14px; background: var(--calm-surface);
  transition: border-color var(--u-motion-fast, 120ms) ease, background-color var(--u-motion-fast, 120ms) ease;
}
.calm-option:hover .calm-option-body { border-color: rgba(185, 93, 10, .45); }
.calm-option:focus-visible .calm-option-body, .calm-option-input:focus-visible + .calm-option-body { box-shadow: 0 0 0 2px var(--calm-accent-focus); }
.calm-option-glyph { flex: 0 0 auto; width: 34px; height: 34px; padding: 7px; border-radius: 10px; background: rgba(185, 93, 10, .09); fill: none; stroke: var(--calm-accent-focus); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
html.dark .calm-option-glyph { background: rgba(240, 163, 90, .12); }
.calm-option-text { flex: 1; min-width: 0; font-size: 15px; line-height: 1.3; }
.calm-option-arrow { flex: 0 0 auto; width: 16px; height: 16px; fill: none; stroke: var(--calm-text-muted); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.calm-option-check { display: grid; flex: 0 0 auto; width: 22px; height: 22px; place-items: center; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--calm-hair); color: transparent; }
.calm-option-check svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.calm-option-input:checked + .calm-option-body { border-color: var(--calm-accent-focus); background: rgba(185, 93, 10, .05); }
html.dark .calm-option-input:checked + .calm-option-body { background: rgba(240, 163, 90, .08); }
.calm-option-input:checked + .calm-option-body .calm-option-check { background: var(--calm-accent-focus); box-shadow: none; color: #fff; }
html.dark .calm-option-input:checked + .calm-option-body .calm-option-check { color: #241f1a; }
@media (prefers-reduced-motion: reduce) { .calm-option-body { transition: none; } }

/* ── Phone fit and finish ─────────────────────────────────────────
   The floating Back control is kept on purpose (thumb reach), so the page
   makes room for it instead: at the end of a scroll the last line always
   sits above it, never under it. --calm-back-bottom is measured by
   positionFloatingBack() in calm/base.html; 46px is the control itself.
   The tab bar grows into the home-indicator area where there is one, and
   text fields stay at 16px so iOS does not zoom the page on focus. */
@media (max-width: 767px) {
  body:has(.calm-back) #main {
    padding-bottom: calc(var(--calm-back-bottom, calc(76px + env(safe-area-inset-bottom, 0px))) + 46px + 20px);
  }
  .calm-navbar { padding-bottom: env(safe-area-inset-bottom, 0px); }
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
  textarea, select { font-size: max(16px, 1em); }
}

/* An exam is answered without the tabs: leaving it is "Finish early". */
@media (max-width: 767px) { body[data-exam-page="1"] > .calm-navbar { display: none; } }
/* An answer option is the control and its words on one line. */
label.calm-pick { display: flex; align-items: center; gap: 12px; }

/* Radio buttons and checkboxes, drawn in the calm palette everywhere.
   The browser's own were grey discs in dark mode and a different blue on
   every platform. Visually hidden inputs (sr-only, the option cards' input)
   keep their own rules; display is never set here, so `hidden` still hides. */
.calm-page input[type="radio"]:not(.sr-only):not(.calm-option-input),
.calm-page input[type="checkbox"]:not(.sr-only):not(.calm-option-input) {
  -webkit-appearance: none; appearance: none; flex: none;
  width: 18px; height: 18px; vertical-align: -3px; cursor: pointer;
  border: 1.5px solid var(--calm-text-muted); border-radius: 50%;
  background: var(--calm-surface) no-repeat center / 12px 12px;
  transition: border-color .15s ease, background-color .15s ease;
}
.calm-page input[type="checkbox"]:not(.sr-only):not(.calm-option-input) { border-radius: 5px; }
.calm-page input[type="radio"]:not(.sr-only):not(.calm-option-input):checked {
  border-color: var(--calm-ok); background: radial-gradient(circle, var(--calm-ok) 0 4px, var(--calm-surface) 4.5px);
}
.calm-page input[type="checkbox"]:not(.sr-only):not(.calm-option-input):checked {
  border-color: var(--calm-ok); background-color: var(--calm-ok);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fffdfa' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
html.dark .calm-page input[type="checkbox"]:not(.sr-only):not(.calm-option-input):checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23292524' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
.calm-page input[type="radio"]:not(.sr-only):not(.calm-option-input):hover,
.calm-page input[type="checkbox"]:not(.sr-only):not(.calm-option-input):hover { border-color: var(--calm-ok); }
.calm-page input[type="radio"]:focus-visible, .calm-page input[type="checkbox"]:focus-visible { outline: 2px solid var(--calm-accent-focus); outline-offset: 2px; }
.calm-page input[type="radio"]:disabled, .calm-page input[type="checkbox"]:disabled { opacity: .5; cursor: default; }

/* Per-subject memory bar on Progress. The meter is a <span> inside a row
   link, so it has to be made a block to take a height. */
.calm-meter-memory { display: block; max-width: 240px; }

/* ── The answer moment ────────────────────────────────────────────
   Marking an option eases in instead of snapping, the mark itself grows
   into place, and an option you got right settles once, by a hair. A
   wrong pick gets no shake: the right option is shown and that is all.
   The revealed answer takes focus (for the keyboard), without an outline
   ring around the whole block. */
#mc-options .calm-pick { transition: background-color .2s ease, color .2s ease, opacity .2s ease; }
#mc-options .calm-mark { animation: calm-mark-in .22s cubic-bezier(.33, .1, .2, 1) both; }
#mc-options .calm-pick.was-chosen { animation: calm-settle .34s cubic-bezier(.33, .1, .2, 1); }
@keyframes calm-mark-in { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
@keyframes calm-settle { 0% { transform: scale(1); } 45% { transform: scale(1.015); } 100% { transform: scale(1); } }
#calm-solution:focus { outline: none; }
@media (prefers-reduced-motion: reduce) {
  #mc-options .calm-pick { transition: none; }
  #mc-options .calm-mark, #mc-options .calm-pick.was-chosen { animation: none; }
}
[data-study-back]:focus { outline: none; }

/* ── Faster copy and paste ────────────────────────────────────────
   The assistant used last leads the row and carries the accent, so the
   usual route is one obvious press. When you come back from it, Paste is
   lit and focused (ai-handoff.js). Assistant buttons are full thumb size. */
.ai-target { min-height: 44px; }
.ai-target.is-last-used { border-color: var(--calm-accent-focus); color: var(--calm-accent-text); font-weight: 600; }
.paste-in-corner.is-ready {
  border-color: var(--calm-accent-focus); color: var(--calm-accent-text); font-weight: 600;
  box-shadow: 0 0 0 3px rgba(185, 93, 10, .14);
}
html.dark .paste-in-corner.is-ready { box-shadow: 0 0 0 3px rgba(240, 163, 90, .18); }

/* Subject icons beside a subject's name are how a subject is recognised at a
   glance, so they are drawn to be seen: a full-strength glyph on its own
   tinted disc (app.css), never a faded smudge next to the text. */
.subject-fingerprint-inline > .subject-fingerprint { opacity: 1; }
html.dark .subject-fingerprint-inline > .subject-fingerprint { opacity: 1; }


/* Tap targets (SCORECARD.md: mobile.target-44, a11y.target-24). A
   standalone link or icon button is at least 44px in its short side, the
   size a thumb can hit without zooming. The extra space is padding inside
   the target, so the visible text and icons stay where they were. Links
   inside a sentence are exempt and don't use these. */
.calm-target { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; }
.calm-icon-target { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; }
/* A slider's thumb is the target: the browser draws the track about 16px
   tall, so the recall-horizon slider on Progress failed a11y.target-24.
   The extra height is touch area around the same track. */
input[type="range"] { min-height: 44px; }

/* ── Signed-out forms (login, sign-up) ────────────────────────────
   The first screens a new student sees, so they speak the same calm
   language as the landing page they came from: parchment page, one paper
   card, underline fields and the one accent button. Fields are 44px tall
   and every standalone link is a full target (SCORECARD.md). */
.calm-auth { width: 100%; max-width: 24rem; margin: 0 auto; }
.calm-auth-label { display: block; margin-top: var(--calm-s2); font-size: 13.5px; font-weight: 600; color: var(--calm-text-soft); }
.calm-auth-label:first-of-type { margin-top: 0; }
.calm-auth .calm-field { min-height: 44px; }
.calm-auth-hint { margin-top: 6px; font-size: 12.5px; line-height: 1.5; color: var(--calm-text-muted); }
.calm-auth-bad { margin-top: 6px; font-size: 12.5px; color: var(--calm-no); }
.calm-auth-alert {
  margin-bottom: var(--calm-s2); padding: 10px 14px; border-radius: 12px;
  background: var(--calm-no-bg); box-shadow: inset 0 0 0 1px var(--calm-no-line);
  color: var(--calm-no); font-size: 13.5px;
}
.calm-auth-note {
  margin-bottom: var(--calm-s2); padding: 10px 14px; border-radius: 12px; text-align: center;
  background: var(--calm-ok-bg); color: var(--calm-ok); font-size: 13.5px;
}
.calm-auth-or { display: flex; align-items: center; gap: 12px; margin-top: var(--calm-s3); font-size: 12.5px; color: var(--calm-text-muted); }
.calm-auth-or::before, .calm-auth-or::after { content: ""; flex: 1; border-top: 1px solid var(--calm-hair); }
.calm-btn-google {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  min-height: 48px; margin-top: var(--calm-s2); border-radius: 14px;
  border: 1px solid rgba(44, 40, 37, .18); background: var(--calm-surface);
  color: var(--calm-text); font-size: 15px; font-weight: 600; text-decoration: none;
}
html.dark .calm-btn-google { border-color: rgba(245, 245, 244, .20); }
.calm-btn-google:hover { border-color: var(--calm-accent-focus); }
/* Live password checklist on sign-up: a hollow ring that fills when a rule
   is met. Colours come from the calm right/wrong tokens, so dark mode and
   contrast follow them. */
.pw-req { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--calm-text-muted); }
.pw-req-dot { width: 14px; height: 14px; flex-shrink: 0; border-radius: 999px; border: 2px solid var(--calm-text-muted); display: inline-flex; align-items: center; justify-content: center; }
.pw-req-check { display: none; width: 9px; height: 9px; color: var(--calm-surface); }
.pw-req.pw-req-met { color: var(--calm-text); font-weight: 600; }
.pw-req.pw-req-met .pw-req-dot { background: var(--calm-ok); border-color: var(--calm-ok); }
.pw-req.pw-req-met .pw-req-check { display: block; }
.pw-strength { display: flex; gap: 4px; margin-top: 10px; }
.pw-strength-seg { height: 4px; flex: 1; border-radius: 999px; background: var(--calm-hair); }
.pw-match-msg { display: none; margin-top: 6px; font-size: 12.5px; font-weight: 600; }
.pw-match-msg.pw-match-ok { display: block; color: var(--calm-ok); }
.pw-match-msg.pw-match-bad { display: block; color: var(--calm-no); }

/* Main learning journey: a quiet, consistent decision area. */
.journey-next { padding:clamp(22px,4vw,32px); border:1px solid var(--calm-hair); box-shadow:none; }
.journey-next .calm-title { font-size:clamp(26px,5vw,36px); line-height:1.22; letter-spacing:-.02em; }
.journey-next .paper-card-art { align-items:center; gap:16px; }
.journey-next .paper-icon-slot { width:60px; height:60px; flex:0 0 60px; }
.journey-next .calm-note { margin-top:12px; }
.journey-next .calm-btn { margin-top:22px; gap:10px; }
.practice-setup fieldset { min-width:0; }
.practice-setup .calm-choice { border:0; border-bottom:1px solid var(--calm-hair); border-radius:0; min-height:48px; }
.practice-fields { display:grid; grid-template-columns:1fr 1fr; gap:20px 16px; margin:24px 0; }
.practice-fields label { display:flex; flex-direction:column; gap:8px; font-size:14px; color:var(--calm-text-soft); }
.practice-fields input,.practice-fields select,.practice-setup textarea { width:100%; min-height:48px; border:1px solid var(--calm-hair); border-radius:12px; padding:10px; background:var(--calm-bg-parchment); color:var(--calm-text); font-size:16px; }
.topic-options { margin-left:auto; font-size:13px; }
.topic-options summary { min-height:44px; display:flex; align-items:center; cursor:pointer; }
.topic-options-menu { display:flex; flex-wrap:wrap; gap:8px 18px; padding:8px 0; }
.topic-options-menu a,.topic-options-menu button { min-height:44px; display:inline-flex; align-items:center; }
.calm-page [data-recall-advance-form] .calm-btn,.calm-page [data-study-continue] { min-height:48px; }
.calm-page [data-recall-error] { margin-top:12px; color:var(--calm-no); line-height:1.5; }
@media(max-width:400px) { .practice-fields { grid-template-columns:1fr; } .journey-next .paper-icon-slot { width:44px; height:44px; flex-basis:44px; } }

/* ── Explain a highlighted passage (notes-explain.js) ─────────────
   One accent button beside the selection, the other assistants behind the
   arrow. Fixed to the viewport so it can sit over a study modal, and kept
   inside the 16px gutter at phone width. */
.notes-explain {
  position: fixed; z-index: 90; display: flex; flex-wrap: wrap; align-items: stretch;
  max-width: calc(100vw - 32px); border-radius: 12px; background: var(--calm-surface);
  box-shadow: var(--calm-lift), 0 0 0 1px var(--calm-hair);
}
.notes-explain[hidden] { display: none; }
.notes-explain button { font: inherit; cursor: pointer; }
.notes-explain-go {
  min-height: 44px; padding: 8px 14px; border: 0; border-radius: 12px 0 0 12px;
  background: var(--calm-accent-focus); color: #fff; font-size: 14px; font-weight: 600;
}
html.dark .notes-explain-go { color: #241f1a; }
.notes-explain-more {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; min-height: 44px;
  border: 0; border-radius: 0 12px 12px 0; background: transparent; color: var(--calm-text-soft);
}
.notes-explain-more svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.notes-explain-more[aria-expanded="true"] svg { transform: rotate(180deg); }
.notes-explain-menu { display: flex; flex-direction: column; flex-basis: 100%; padding: 4px; border-top: 1px solid var(--calm-hair); }
.notes-explain-menu[hidden] { display: none; }
.notes-explain-menu button {
  min-height: 44px; padding: 8px 12px; border: 0; border-radius: 9px; background: transparent;
  color: var(--calm-text); text-align: left; font-size: 14px;
}
.notes-explain-menu button:hover, .notes-explain-menu button:focus-visible { background: var(--calm-hair); }
.notes-explain-note { flex-basis: 100%; max-width: 280px; margin: 0; padding: 8px 12px 10px; color: var(--calm-text-soft); font-size: 13px; line-height: 1.4; }
.notes-explain-note[hidden] { display: none; }
@media (hover: hover) { .notes-explain-go:hover { filter: brightness(1.06); } }
/* The explanation made in the app: a panel by the passage on a wide
   screen, a sheet from the bottom on a phone. */
.notes-explain-panel {
  position: fixed; z-index: 91; max-height: min(70vh, 520px); overflow: auto; overscroll-behavior: contain;
  border-radius: 16px; background: var(--calm-surface); color: var(--calm-text);
  box-shadow: var(--calm-lift), 0 0 0 1px var(--calm-hair);
}
.notes-explain-panel.is-sheet { left: 0; right: 0; bottom: 0; top: auto; width: auto; max-height: 72vh; border-radius: 18px 18px 0 0; padding-bottom: env(safe-area-inset-bottom); }
.notes-explain-panel-head { position: sticky; top: 0; display: flex; align-items: flex-start; gap: 8px; padding: 14px 8px 8px 18px; background: var(--calm-surface); }
.notes-explain-panel-quote { flex: 1; min-width: 0; margin: 0; padding-top: 8px; color: var(--calm-text-muted); font-size: 13.5px; line-height: 1.4; font-style: italic; overflow-wrap: anywhere; }
.notes-explain-close { flex: none; display: inline-grid; place-items: center; width: 44px; height: 44px; border: 0; border-radius: 10px; background: transparent; color: var(--calm-text-soft); cursor: pointer; }
.notes-explain-close svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.notes-explain-panel-body { padding: 0 18px 6px; }
.notes-explain-text { margin: 0 0 10px; font-size: 15.5px; line-height: 1.55; }
.notes-explain-working { margin: 6px 0 14px; color: var(--calm-text-soft); font-size: 15px; }
.notes-explain-failed { margin: 6px 0 14px; color: var(--calm-text-soft); font-size: 14.5px; line-height: 1.45; }
.notes-explain-label { margin: 0 0 4px; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--calm-text-muted); }
.notes-explain-example { margin: 4px 0 12px; padding: 10px 12px; border-radius: 12px; background: var(--calm-ok-bg); font-size: 14.5px; line-height: 1.5; }
.notes-explain-example p { margin: 0; }
.notes-explain-card { margin: 4px 0 10px; padding: 12px; border-radius: 12px; border: 1px dashed var(--calm-hair); }
.notes-explain-card-front { margin: 0; font-weight: 600; font-size: 14.5px; line-height: 1.45; }
.notes-explain-card-back { margin: 4px 0 0; color: var(--calm-text-soft); font-size: 14.5px; line-height: 1.45; }
.notes-explain-keep { margin-top: 10px; min-height: 40px; padding: 6px 14px; border-radius: 10px; border: 1px solid var(--calm-hair); background: var(--calm-surface); color: var(--calm-text); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: var(--calm-control-shadow); }
.notes-explain-keep.is-kept { color: var(--calm-ok); border-color: var(--calm-ok-line); background: var(--calm-ok-bg); box-shadow: none; }
.notes-explain-panel-foot { padding: 4px 18px 14px; }
.notes-explain-elsewhere { min-height: 44px; padding: 0; border: 0; background: none; color: var(--calm-accent-text); font: inherit; font-size: 14px; cursor: pointer; }
@media (prefers-reduced-motion: no-preference) {
  .notes-explain-panel { animation: notes-explain-in .2s var(--calm-motion-ease) both; }
  .notes-explain-panel.is-sheet { animation-name: notes-explain-up; }
  @keyframes notes-explain-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
  @keyframes notes-explain-up { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
  .notes-explain-working { animation: notes-explain-pulse 1.4s ease-in-out infinite; }
  @keyframes notes-explain-pulse { 50% { opacity: .45; } }
}

/* ── Session complete (calm/session_done.html) ───────────────────── */
.session-score { display: flex; align-items: center; gap: 12px; }
.session-score-bar { flex: 1; height: 8px; margin-top: 0; border-radius: 4px; }
.session-score-bar > i { border-radius: 4px; }
.session-missed { list-style: none; margin: 0; padding: 0; }
.session-missed-item { padding: 12px 0; }
.session-missed-item + .session-missed-item { border-top: 1px solid var(--calm-hair); }
.session-missed-q { margin: 0; color: var(--calm-text); line-height: 1.45; overflow-wrap: anywhere; }
.session-missed-tag { font-weight: 600; color: var(--calm-ok); }
.session-more-links { justify-content: flex-start; }

/* ── Tidy pass, 8 Oct ─────────────────────────────────────────────
   A filled button that sits at the end of a row, a left-aligned
   disclosure for lists, and the quiet rows that follow a main button. */
.calm-btn.calm-btn-inline { display: inline-flex; width: auto; min-height: 44px; align-items: center; margin-top: 0; padding: 9px 16px; font-size: 13.5px; border-radius: 11px; }
.calm-help.calm-help-start { width: 100%; margin: 6px 0 0; text-align: left; }
.calm-help.calm-help-start > summary { padding-left: 0; }
.calm-review-sizes { gap: 6px; align-items: center; }
.calm-report-row .calm-study-tools-actions { margin-top: 6px; }
/* "Sure or not sure?" before an answer: two small choices, never a gate. */
.calm-sure { margin-top: 18px; }
.calm-sure-picks { display: flex; gap: 8px; margin-top: 2px; }
.calm-sure-pick { display: inline-flex; align-items: center; min-height: 44px; cursor: pointer; }
.calm-sure-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.calm-sure-pick span { padding: 7px 14px; border: 1px solid var(--calm-hair); border-radius: 999px; font-size: 13px; color: var(--calm-text-soft); background: var(--calm-surface); }
.calm-sure-pick input:checked + span { border-color: var(--calm-accent-focus); color: var(--calm-text); box-shadow: inset 0 0 0 1px var(--calm-accent-focus); }
.calm-sure-pick input:focus-visible + span { outline: 2px solid var(--calm-accent-focus); outline-offset: 2px; }

/* ── Session action bar (calm/session_exercise.html) ──────────────
   The next step is always in the same place: the bottom of the screen on a
   phone, straight under the card on a wide screen. Help is on the left, the
   way forward on the right.

   On a phone the bar takes the place of the four tabs. The tab bar itself
   stays in the page, emptied, because Pagey stands on it and is measured
   against it (companion-rig.js); only its links are put away. Leaving a
   session is "Exit", top right, which asks first. */
.calm-session-actions { position: relative; margin-top: 14px; }
.calm-session-actions-inner { display: flex; align-items: center; gap: 10px; min-height: 52px; }
.calm-session-actions .calm-help { flex: 0 0 auto; width: auto; margin: 0; text-align: left; }
.calm-session-actions .calm-help > summary { padding-left: 4px; }
.calm-session-actions .calm-help-actions {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 2;
  flex-wrap: wrap; border: 1px solid var(--calm-hair); background: var(--calm-surface); box-shadow: var(--calm-lift);
}
html.dark .calm-session-actions .calm-help-actions { background: var(--calm-surface); }
.calm-session-actions .calm-help-actions button { flex: 1 1 auto; font-size: 12.5px; }
.calm-btn.calm-session-main { flex: 1 1 140px; width: auto; min-height: 52px; margin-top: 0; }
.calm-session-actions .calm-reveal-unsure { margin: 0 0 0 auto; }
.calm-session-grade { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; width: 100%; }
.calm-session-feel { display: flex; flex: 0 0 auto; gap: 6px; }
.calm-session-selfgrade { width: 100%; }
.calm-session-selfgrade > .calm-sub { margin: 0 0 6px; text-align: center; }
/* Practice uses the flashcards' three self-grades (partials/recall_choices
   .html styles them). When a typed answer shares no word with the expected
   one, "Not yet" is outlined as a suggestion; nothing is chosen for you. */
.calm-session-selfgrade .recall-choices button.is-suggested { border-color: var(--calm-no); box-shadow: inset 0 0 0 1px var(--calm-no); }
/* The report dialog before the answer is opened from "Need help?"; its own
   button is not shown, the dialog beside it is. */
.calm-report-held > [data-calm-study-tools] > .calm-study-tools-actions { display: none; }
.calm-instruction { margin: 4px 0 10px; }
/* The answer box, with the microphone at its end and nothing else. */
.calm-answer-box { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; align-items: end; }
.calm-answer-box .calm-voice-answer { display: contents; }
.calm-answer-box .calm-voice-answer[hidden] { display: none; }
.calm-voice-button {
  display: inline-grid; place-items: center; width: 44px; height: 44px; border: 1px solid var(--calm-hair);
  border-radius: 50%; background: var(--calm-surface); color: var(--calm-text-soft); cursor: pointer;
}
.calm-voice-button svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
.calm-voice-button[aria-pressed="true"] { border-color: var(--calm-accent-focus); color: var(--calm-accent-text); box-shadow: inset 0 0 0 1px var(--calm-accent-focus); }
.calm-answer-box [data-speech-status] { grid-column: 1 / -1; max-width: none; margin-top: 8px; }
.calm-answer-box [data-speech-status]:empty { display: none; }
.calm-answer-optional { margin-top: 8px; }
@media (max-width: 767px) {
  .calm-session-actions {
    position: fixed; inset: auto 0 0; z-index: 41; margin: 0;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--calm-surface); border-top: 1px solid var(--calm-hair);
  }
  .calm-session-actions .calm-help-actions { left: 12px; right: 12px; }
  body:has(.calm-session-actions) > .calm-navbar > a { display: none; }
  body:has(.calm-session-actions) > .calm-navbar { min-height: calc(72px + env(safe-area-inset-bottom, 0px)); border-top-color: transparent; background: transparent; }
  body:has(.calm-session-actions) > .calm-navbar:not(.has-pagey-seat),
  body:not([data-companion-page="1"]):has(.calm-session-actions) > .calm-navbar { display: none; }
  body[data-companion-page="1"]:has(.calm-navbar.has-pagey-seat) .calm-session-actions { padding-right: 64px; }
  body:has(.calm-session-actions) .calm-study-viewport { padding-bottom: 28px; }
}
@media (max-width: 767px) {
  /* With the links put away the seat would be the bar's first cell, and
     Pagey would stand on the left, over "Need help?". */
  body:has(.calm-session-actions) > .calm-navbar { pointer-events: none; }
  body:has(.calm-session-actions) > .calm-navbar > .calm-pagey-seat { grid-column: 5; }
}

/* ── What a session changed, drawn (partials/session_picture.html) ──
   Squares are answers, dots are things on the schedule. Filled held,
   hollow was missed: the same two marks on every end screen. Shape and
   outline carry the meaning, so it reads without colour too. */
.session-picture { margin-top: 18px; }
.session-squares { display: flex; flex-wrap: wrap; gap: 6px; }
.session-squares > i { width: 18px; height: 18px; border-radius: 5px; box-sizing: border-box; }
.session-squares > i.is-held, .session-dots > i.is-held, .session-picture-key > i.is-held { background: var(--calm-week-bar, #3a8a4f); }
.session-squares > i.is-missed, .session-dots > i.is-missed, .session-picture-key > i.is-missed { border: 2px solid var(--calm-accent-focus); background: transparent; }
html.dark .session-squares > i.is-held, html.dark .session-dots > i.is-held { background: #5f9c63; }
.session-returns-title { margin: 22px 0 8px; }
.session-returns { display: grid; gap: 2px; }
.session-returns-row { display: grid; grid-template-columns: 92px minmax(0, 1fr); align-items: center; min-height: 30px; }
.session-returns-row + .session-returns-row { border-top: 1px solid var(--calm-hair); }
.session-returns-when { font-size: 13px; color: var(--calm-text-soft); }
.session-returns-row.is-empty .session-returns-when { color: var(--calm-text-muted); }
.session-dots { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 7px 0; min-height: 12px; }
.session-dots > i, .session-picture-key > i { width: 12px; height: 12px; border-radius: 50%; box-sizing: border-box; flex: 0 0 auto; }
.session-picture-key { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
@media (forced-colors: active) {
  .session-squares > i.is-held, .session-dots > i.is-held { background: CanvasText; }
  .session-squares > i.is-missed, .session-dots > i.is-missed, .session-picture-key > i.is-missed { border-color: CanvasText; }
}
@media (prefers-reduced-motion: no-preference) {
  .session-picture { animation: calm-rise .3s cubic-bezier(.33, .1, .2, 1) both; }
}
/* The card screens' grades carry the same one-word consequence. */
.recall-choices button { gap: 4px; }
.recall-choices button small { font-size: 11px; line-height: 1.1; color: var(--calm-text-muted); font-weight: 400; }

/* Welcome, step 1: each reason for being here says in a few words what it
   means, so nobody has to guess between "Class support" and "Catch-up". */
.calm-option-hint { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.35; color: var(--calm-text-muted); font-weight: 400; }

/* ── Polish pass: sheets, the help menu, the end-of-session panel ──
   Source, report and the scratchpad all arrive the same way on a phone:
   a sheet that rises from the bottom edge with a small handle, over a
   dimmed page. One gesture to learn, and it never hides behind a header. */
.session-picture { padding: 18px 20px 16px; border-radius: 20px; background: var(--calm-surface); box-shadow: var(--calm-lift); }
.session-picture-title { margin: 0 0 10px; }
.session-returns-title { margin: 20px 0 6px; }
.session-picture-key { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--calm-hair); }
[data-session-next] .calm-btn { margin-top: 0; }
.calm-session-actions .calm-help-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; padding: 6px; border-radius: 16px; }
.calm-session-actions .calm-help-actions button { justify-content: flex-start; padding: 10px 12px; font-size: 13px; }
/* A closed menu lays its buttons out inside the closed disclosure, which is
   only as wide as its label: two columns there are slivers. They are not
   on screen, so they take no box at all. */
.calm-session-actions .calm-help:not([open]) .calm-help-actions { display: none; }
.scratchpad-head-actions { display: inline-flex; align-items: center; gap: 14px; }
.scratchpad-done { min-height: 32px; padding: 4px 12px; border: 1px solid var(--calm-hair); border-radius: 999px; background: var(--calm-surface); color: var(--calm-text); font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1; cursor: pointer; }
@keyframes calm-sheet-up { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes calm-veil-in { from { opacity: 0; } to { opacity: 1; } }
@media (max-width: 767px) {
  .calm-study-modal { padding: 0; align-items: end; }
  .calm-study-modal-card {
    width: 100%; max-height: 86dvh; padding: 26px 20px calc(22px + env(safe-area-inset-bottom, 0px));
    border-radius: 24px 24px 0 0;
  }
  .calm-study-modal-card::before, body[data-study-page="1"] #scratchpad-panel:not([hidden])::before {
    content: ''; position: absolute; top: 9px; left: 50%; width: 38px; height: 4px; margin-left: -19px;
    border-radius: 2px; background: var(--calm-hair);
  }
  body[data-study-page="1"] #scratchpad-panel:not([hidden]) {
    position: fixed; inset: auto 0 0; z-index: 45; margin: 0; max-height: 78dvh; overflow-y: auto;
    padding: 26px 18px calc(18px + env(safe-area-inset-bottom, 0px));
    border: 0; border-radius: 24px 24px 0 0; background: var(--calm-surface);
    box-shadow: 0 -10px 40px rgba(44, 40, 37, .18);
  }
}
@media (prefers-reduced-motion: no-preference) {
  .calm-study-modal:not([hidden]) .calm-study-modal-veil { animation: calm-veil-in .18s ease both; }
  .calm-study-modal:not([hidden]) .calm-study-modal-card { animation: calm-sheet-up .24s cubic-bezier(.33, .1, .2, 1) both; }
  @media (max-width: 767px) { body[data-study-page="1"] #scratchpad-panel:not([hidden]) { animation: calm-sheet-up .24s cubic-bezier(.33, .1, .2, 1) both; } }
}

/* Asked once where the free first set gives way to copy and paste: would
   the learner pay to keep one-tap generation. Quiet, and easy to pass by. */
.calm-pay-question { margin-top: 14px; padding: 16px; border-radius: 16px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); }
.calm-pay-options { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.calm-pay-options button { min-height: 44px; padding: 8px 14px; border: 1px solid var(--calm-hair); border-radius: 999px; background: var(--calm-surface); color: var(--calm-text); font: inherit; font-size: 13.5px; cursor: pointer; }
.calm-pay-options button:hover { border-color: var(--calm-text-muted); }
.calm-pay-options .calm-pay-skip { border-color: transparent; background: transparent; color: var(--calm-text-muted); }

/* The card screens use the same action bar: reveal, then the grades. */
.calm-card-actions .calm-session-actions-inner { display: block; }
.calm-card-actions .calm-card-reveal { display: flex; }
.calm-card-actions [hidden] { display: none; }
.calm-card-actions .recall-guide { margin: 0 0 8px; text-align: center; font-size: 13px; }
.calm-card-actions .recall-choices button { min-height: 54px; }
/* A quiet paper margin separates the explanation from the question.
   Keep it neutral: an ungraded answer must not imply success or failure. */
#calm-solution { border-inline-start:2px solid var(--calm-hair); padding-inline-start:16px; }
.calm-answer-box { position:relative; }
.calm-answer-box::after { content:""; position:absolute; inset-inline:0; top:0; height:2px; background:var(--calm-accent-focus); opacity:0; pointer-events:none; }
.calm-answer-box:focus-within::after { opacity:1; }
.calm-answer-box textarea { caret-color:var(--calm-accent-focus); }
/* Never transform the swipe stage or move the question as someone types.
   Only the newly visible answer and explicit controls receive motion. */
@media (prefers-reduced-motion:no-preference) {
  .calm-flashcard-stage [data-study-back]:not([hidden]) .calm-flashcard-answer {
    animation:calm-rise 200ms var(--u-motion-ease,ease);
  }
  .calm-answer-box::after { transition:opacity 140ms ease; }
  .calm-session-actions button { transition:transform 120ms ease; }
  .calm-session-actions button:active:not(:disabled) { transform:scale(.98); }
}
@media (forced-colors:active) {
  .calm-flashcard-answer, #calm-solution { border-color:CanvasText; }
  .calm-answer-box::after { background:Highlight; }
}
@media (min-width: 768px) {
  .calm-card-actions { width: min(100%, 420px); margin: 16px auto 0; }
}
@media (max-width: 767px) {
  body:has(.calm-card-actions) .calm-flashcard-page { padding-bottom: 40px; }
}

/* ── Session complete (session_done.html): the reward ─────────────────
   A seal that draws itself to the share right, paper confetti for a good
   result, the answers settling in as squares, and what it counts
   towards. Everything moves once on load, and nothing moves with reduced
   motion. */
.done-hero { overflow-x: clip; position: relative; display: flex; flex-direction: column; align-items: center; text-align: center; padding-top: 12px; }
.done-hero .calm-note { max-width: 30rem; }
.done-title { margin-top: 4px; }
.done-seal { position: relative; width: 132px; height: 132px; margin-bottom: 14px; }
.done-seal svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.done-seal-track { fill: var(--calm-surface); stroke: var(--calm-hair); stroke-width: 9; }
.done-seal-fill { fill: none; stroke: var(--calm-ok); stroke-width: 9; stroke-linecap: round; }
.done-seal.is-perfect .done-seal-fill { stroke: var(--calm-accent-focus); }
.done-seal-center { position: absolute; inset: 0; display: flex; align-items: baseline; justify-content: center; padding-top: 44px; gap: 3px; font-family: Lora, Georgia, serif; color: var(--calm-text); }
.done-seal-num { font-size: 40px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.done-seal-of { font-size: 18px; color: var(--calm-text-muted); }
.done-seal.is-check .done-seal-center { align-items: center; padding-top: 0; }
.done-seal-tick { width: 52px; height: 52px; fill: none; stroke: var(--calm-ok); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; transform: none !important; }
.done-seal-badge { position: absolute; right: 4px; top: 6px; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--calm-accent-focus); box-shadow: 0 0 0 4px var(--calm-bg-parchment), var(--calm-control-shadow); }
.done-seal-badge svg { width: 18px; height: 18px; transform: none; fill: none; stroke: #fff; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
html.dark .done-seal-badge svg { stroke: #241f1a; }
/* Paper confetti, falling from above the seal. */
.done-confetti { position: absolute; left: -16px; right: -16px; top: -40px; height: 0; pointer-events: none; z-index: 2; }
.done-confetti > i { position: absolute; top: 0; left: var(--x); width: 8px; height: 13px; border-radius: 2px; opacity: 0; animation: done-fall var(--fall) cubic-bezier(.25, .5, .4, 1) var(--delay) forwards; }
.done-confetti > i.is-round { width: 9px; height: 9px; border-radius: 50%; }
@keyframes done-fall {
  0% { opacity: 0; transform: translate(0, -10px) rotate(0); }
  10% { opacity: 1; }
  85% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--drift), 430px) rotate(var(--spin)); }
}
/* The answers, bigger here: they are the picture of what was done. */
.done-page .session-picture { text-align: center; }
.done-page .session-picture-title { margin-left: 0; }
.session-squares.is-big { justify-content: center; gap: 8px; margin-top: 8px; }
.session-squares.is-big > i { width: 24px; height: 24px; border-radius: 7px; }
.done-page .session-picture details { text-align: left; }
/* Small facts of a lesson. */
.done-facts { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; padding: 0; margin: 22px 0 0; }
.done-facts li { padding: 6px 12px; border-radius: 999px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); color: var(--calm-text-soft); font-size: 13.5px; }
.done-page > .calm-sub { text-align: center; }
.done-tile, .done-plan { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border-radius: 16px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair), var(--calm-control-shadow); color: var(--calm-text); text-decoration: none; }
.done-tile:hover, .done-plan:hover { box-shadow: 0 0 0 1px var(--calm-ok-line), var(--calm-control-shadow); }
.done-tile-icon, .done-plan-icon { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--calm-ok-bg); }
.done-tile-icon svg, .done-plan-icon svg { width: 22px; height: 22px; fill: none; stroke: var(--calm-ok); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* Today's practice, and the test's plan. */
.done-counts { display: grid; gap: 12px; }
.done-goal { padding: 14px 16px; border-radius: 16px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); }
.done-goal-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.done-goal-bar { height: 8px; margin-top: 10px; border-radius: 4px; background: var(--calm-hair); overflow: hidden; }
.done-goal-bar > i { display: block; height: 100%; width: calc(var(--goal) * 1%); border-radius: 4px; background: var(--calm-ok); }
.done-goal.is-reached .done-goal-bar > i { background: var(--calm-accent-focus); }
.done-goal.is-reached .calm-nm::before { content: "✓ "; color: var(--calm-accent-text); }
/* What was missed: numbered, each a way into the review. */
.done-missed-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.done-missed-head .calm-label { margin-left: 0; }
.done-missed-list { list-style: none; padding: 0; margin: 10px 0 0; }
.done-missed-list li { border-top: 1px solid var(--calm-hair); }
.done-missed-list li:first-child { border-top: 0; }
.done-missed-list li > a, .done-missed-list li:not(:has(a)) { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 10px 2px; color: var(--calm-text); text-decoration: none; font-size: 15.5px; line-height: 1.4; }
.done-missed-n { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 12.5px; font-weight: 600; color: var(--calm-accent-text); border: 1.5px solid var(--calm-accent-focus); }
.done-missed-q { flex: 1; min-width: 0; }
.done-missed-go { color: var(--calm-text-muted); font-size: 20px; }
.done-missed-list li > a:hover .done-missed-q { text-decoration: underline; text-underline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .done-ready .done-seal-fill { animation: done-ring 1.1s cubic-bezier(.3, .7, .2, 1) .15s both; }
  @keyframes done-ring { from { stroke-dashoffset: var(--pct); } to { stroke-dashoffset: 0; } }
  .done-ready .done-seal { animation: done-pop .5s cubic-bezier(.3, 1.4, .5, 1) both; }
  @keyframes done-pop { from { transform: scale(.85); opacity: 0; } to { transform: none; opacity: 1; } }
  .done-ready .done-seal-badge { animation: done-pop .45s cubic-bezier(.3, 1.6, .5, 1) 1.05s both; }
  .done-ready .done-seal-tick path { animation: done-tick .6s ease-out .5s both; }
  @keyframes done-tick { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
  .done-ready .session-squares.is-big > i { animation: done-square .35s cubic-bezier(.3, 1.5, .5, 1) both; animation-delay: calc(.6s + var(--i, 0) * 70ms); }
  @keyframes done-square { from { transform: scale(.2); opacity: 0; } to { transform: none; opacity: 1; } }
  .done-ready .done-goal-bar > i { animation: done-goal 1s cubic-bezier(.3, .7, .2, 1) .9s both; }
  @keyframes done-goal { from { width: 0; } }
}
@media (forced-colors: active) {
  .done-seal-fill { stroke: Highlight; }
  .done-goal-bar > i { background: Highlight; }
}


/* ── Session review (session_review.html): the missed answers ─────────
   One card each: the question, your answer beside the right one, the
   reason, and "Got it" to tick it off; a bar counts the cards looked at,
   and the page says so when every one is. */
.review-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
/* A missed square takes a tick once its card has been looked at. */
.session-squares > i.is-missed.is-looked { display: grid; place-items: center; border-color: var(--calm-accent-focus); background: var(--calm-accent-focus); }
.session-squares > i.is-missed.is-looked::after { content: ""; width: 8px; height: 4px; margin-top: -2px; border: solid #fff; border-width: 0 0 2px 2px; transform: rotate(-45deg); }
html.dark .session-squares > i.is-missed.is-looked::after { border-color: #1c1917; }
.miss-card { position: relative; scroll-margin-top: 90px; transition: box-shadow .3s ease, opacity .3s ease; }
.miss-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.miss-n { flex: none; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 600; color: var(--calm-accent-text); border: 1.5px solid var(--calm-accent-focus); }
.miss-topic { padding: 3px 10px; border-radius: 999px; background: var(--calm-hair); color: var(--calm-text-soft); font-size: 12.5px; }
.miss-q { margin-top: 14px; font-family: Lora, Georgia, serif; font-weight: 500; font-size: 20px; line-height: 1.35; color: var(--calm-text); overflow-wrap: anywhere; }
.miss-compare { display: grid; gap: 10px; margin-top: 16px; }
@media (min-width: 560px) { .miss-compare { grid-template-columns: 1fr 1fr; } }
.miss-side { padding: 12px 14px; border-radius: 14px; }
.miss-yours { background: var(--calm-no-bg); box-shadow: inset 0 0 0 1px var(--calm-no-line); }
.miss-right { background: var(--calm-ok-bg); box-shadow: inset 0 0 0 1px var(--calm-ok-line); }
.miss-label { font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--calm-text-muted); margin-right: 6px; }
.miss-yours .miss-label { color: var(--calm-no); }
.miss-right .miss-label { color: var(--calm-ok); }
.miss-text { margin-top: 4px; color: var(--calm-text); font-size: 16px; line-height: 1.45; overflow-wrap: anywhere; }
.miss-yours .miss-text { text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--calm-no) 55%, transparent); text-decoration-thickness: 1.5px; }
.miss-right .miss-text.calm-answer { margin-top: 4px; font-size: 18px; }
.miss-none { color: var(--calm-text-muted); font-style: italic; }
.miss-yours .miss-text:has(.miss-none) { text-decoration: none; }
.miss-why { display: flex; gap: 10px; align-items: flex-start; margin-top: 12px; padding: 12px 14px; border-radius: 14px; background: color-mix(in srgb, var(--calm-text) 4%, transparent); color: var(--calm-text); font-size: 15px; line-height: 1.5; }
.miss-why svg { flex: none; width: 20px; height: 20px; margin-top: 1px; fill: none; stroke: var(--calm-accent-text); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* The card's foot: "Got it" on the left, the small tools on the right. */
.miss-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--calm-hair); }
.miss-tools { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.miss-tools > [data-calm-study-tools], .miss-tools .calm-study-tools-actions { display: contents; }
.miss-tools button, .miss-tools .calm-study-tools-actions button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-width: 40px; min-height: 40px; padding: 0 8px; border: 0; border-radius: 10px; background: none; color: var(--calm-text-soft); font: inherit; font-size: 13px; cursor: pointer; white-space: nowrap; }
.miss-tools button:hover, .miss-tools .calm-study-tools-actions button:hover { background: var(--calm-hair); }
.miss-tools svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.calm-study-tools-icons .calm-tool-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* The way on, at the end of the review. */
.review-end { display: grid; gap: 14px; }
.review-end-ai { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border-radius: 16px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); color: inherit; text-decoration: none; }
.review-end .calm-links[hidden] { display: none; }
.miss-got { display: inline-flex; flex: none; white-space: nowrap; align-items: center; gap: 10px; min-height: 44px; padding: 7px 16px 7px 10px; border-radius: 12px; border: 1px solid var(--calm-hair); background: var(--calm-surface); color: var(--calm-text); font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer; box-shadow: var(--calm-control-shadow); }
.miss-got[hidden] { display: none; }
.miss-got-box { width: 22px; height: 22px; border-radius: 7px; display: grid; place-items: center; border: 1.5px solid var(--calm-text-muted); }
.miss-got-box svg { width: 15px; height: 15px; fill: none; stroke: #fff; stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.miss-card.is-got .miss-got { border-color: var(--calm-ok-line); background: var(--calm-ok-bg); color: var(--calm-ok); box-shadow: none; }
.miss-card.is-got .miss-got-box { background: var(--calm-ok); border-color: var(--calm-ok); }
html.dark .miss-card.is-got .miss-got-box svg { stroke: #1c1917; }
.miss-card.is-got .miss-got-box svg { opacity: 1; }
.miss-card.is-got { box-shadow: 0 0 0 1.5px var(--calm-ok-line), var(--calm-lift); }
.review-finished { text-align: center; padding: 28px 20px; border-radius: 20px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-ok-line), var(--calm-lift); }
.review-finished[hidden] { display: none; }
.review-finished-mark { display: inline-grid; place-items: center; width: 56px; height: 56px; margin-bottom: 10px; border-radius: 50%; background: var(--calm-ok); }
.review-finished-mark svg { width: 30px; height: 30px; fill: none; stroke: #fff; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
html.dark .review-finished-mark svg { stroke: #1c1917; }
.review-finished .calm-btn { max-width: 280px; margin-left: auto; margin-right: auto; text-decoration: none; }
.review-right { align-items: flex-start; }
.review-right::after { display: none; }
.review-right-mark { flex: none; width: 22px; height: 22px; margin-top: 1px; border-radius: 50%; display: grid; place-items: center; background: var(--calm-ok-bg); }
.review-right-mark svg { width: 13px; height: 13px; fill: none; stroke: var(--calm-ok); stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: no-preference) {
  .miss-card.is-got .miss-got-box { animation: done-pop .35s cubic-bezier(.3, 1.6, .5, 1) both; }
  .review-finished.is-new { animation: done-pop .5s cubic-bezier(.3, 1.4, .5, 1) both; }
  .review-finished.is-new .review-finished-mark svg path { animation: done-tick .6s ease-out .25s both; }
}

/* ── Today as one run: Up next, the rest of today, the day's close ──
   (services/today_queue.py). The next part of the day sits on a finish
   page as a quiet card; it becomes the page's main step when there is
   nothing else to do there. */
.up-next { padding: 20px 20px 18px; border-radius: 22px; background: var(--calm-surface); box-shadow: inset 0 0 0 1px var(--calm-hair), var(--calm-lift); }
.up-next-head { display: flex; align-items: flex-start; gap: 14px; }
.up-next-icon { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--calm-ok-bg); }
.up-next-icon svg { width: 22px; height: 22px; fill: none; stroke: var(--calm-ok); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.up-next form .calm-btn, .up-next form .calm-btn-quiet { width: 100%; justify-content: center; text-align: center; }
.today-run { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.today-run-dots { display: inline-flex; gap: 4px; }
.today-run-dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--calm-hair); }
.today-run-dots i:first-child { background: var(--calm-ok); }
/* Number tiles: a figure and what it counts. Used on Today is done,
   Progress and wherever a couple of numbers would otherwise sit in a
   sentence. */
.day-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.day-stat:last-child:nth-child(odd) { grid-column: 1 / -1; }
.day-stat { padding: 14px 16px; border-radius: 16px; background: var(--calm-surface); box-shadow: 0 0 0 1px var(--calm-hair); }
.day-stat b { display: block; font-size: 26px; line-height: 1.1; font-weight: 600; color: var(--calm-text); font-variant-numeric: tabular-nums; }
.day-stat span { display: block; margin-top: 4px; font-size: 13.5px; color: var(--calm-text-soft); }

/* The finish screen, kept to what matters: the answers sit straight under
   the score with no card or caption of their own, and today's practice is
   one quiet line rather than a card with a bar. */
.done-page .session-picture { background: none; box-shadow: none; padding: 0; margin-top: 22px; }
.done-page .session-picture-title { display: none; }
.done-page .session-picture .calm-more { display: inline-block; margin-top: 10px; }
.done-goal-line { margin-top: 18px; text-align: center; font-size: 13.5px; color: var(--calm-text-soft); }
.done-goal-line .goal-mini { margin-left: 10px; vertical-align: middle; }
.done-goal-mark { color: var(--calm-ok); margin-right: 6px; }

/* A missed question in the review, with few labels: the topic as plain
   small text, the right answer on a green rule, what was written quietly
   under it, the reason as a sentence. */
.miss-head { display: flex; align-items: center; gap: 10px; }
.miss-answer { margin-top: 16px; padding: 2px 0 2px 14px; border-left: 3px solid var(--calm-ok); }
.miss-answer .calm-answer { font-size: 19px; }
.miss-yours-line { margin-top: 6px; font-size: 14px; color: var(--calm-text-muted); }
.miss-yours-text { color: var(--calm-text-soft); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--calm-no) 55%, transparent); text-decoration-thickness: 1.5px; }
.miss-why-text { margin-top: 14px; font-size: 15px; line-height: 1.55; color: var(--calm-text-soft); }
.miss-card .calm-source-details, .miss-card details { margin-top: 14px; }
.review-progress { box-shadow: none; padding-left: 2px; padding-right: 2px; background: color-mix(in srgb, var(--calm-bg-parchment) 94%, transparent); }

/* Today's parts as a row of segments (partials/day_track.html): filled
   when done, outlined for the next, quiet for the rest, centred under the
   card that starts the next one. */
.day-track { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.day-track-cells { display: flex; gap: 6px; width: 100%; max-width: 280px; }
.day-track-cells > i { flex: 1 1 0; min-width: 10px; height: 8px; border-radius: 999px; background: var(--calm-hair); }
html.dark .day-track-cells > i { background: rgba(245, 245, 244, .12); }
.day-track-cells > i.is-done, .day-track-cells > i.is-fresh { background: var(--calm-ok); }
.day-track-cells > i.is-next { background: transparent; box-shadow: inset 0 0 0 1.5px var(--calm-accent-focus); }
.day-track-caption { font-size: 13.5px; color: var(--calm-text-soft); text-align: center; font-variant-numeric: tabular-nums; }
.up-next .day-track { margin: 0 0 18px; padding-bottom: 16px; border-bottom: 1px solid var(--calm-hair); }
.done-hero .day-track { margin-top: 18px; }

/* Quiet lines that carry a fact, each with its own small mark instead of
   running on as plain text: the catch-up note on the day's plan, and the
   optional daily goal with a short bar beside its count. */
/* A fact line: one quiet sentence with a small line icon in front of it
   (partials/fact_icon.html), for "when", "how long", "already done" and
   "good to know" lines that used to run on as plain grey text. A run of
   them stacks as a short list. .plan-note is the same thing by an older
   name. */
.calm-fact, .plan-note { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; line-height: 1.5; color: var(--calm-text-soft); }
.calm-fact + .calm-fact { margin-top: 8px; }
.calm-fact svg, .plan-note svg { flex: none; width: 16px; height: 16px; margin-top: 2px; fill: none; stroke: var(--calm-text-muted); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.calm-fact.is-ok svg { stroke: var(--calm-ok); }
.calm-fact.is-accent svg { stroke: var(--calm-accent-focus); }
.calm-fact strong { color: var(--calm-text); font-weight: 600; }
.calm-fact.is-centered { justify-content: center; text-align: left; }
.goal-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 44px; list-style: none; cursor: pointer; font-size: 13.5px; color: var(--calm-text-soft); }
.goal-summary::-webkit-details-marker { display: none; }
.goal-summary-end { display: inline-flex; align-items: center; gap: 10px; font-variant-numeric: tabular-nums; }
.goal-mini { display: inline-block; width: 56px; height: 6px; border-radius: 999px; background: var(--calm-hair); overflow: hidden; }
html.dark .goal-mini { background: rgba(245, 245, 244, .12); }
.goal-mini > i { display: block; height: 100%; max-width: 100%; border-radius: 999px; background: var(--calm-ok); }

/* The day's plan card (partials/combined_study_plan.html): the estimate
   right under the title, the button, then one footer row with the time
   left and "Finish for now" lined up on either side. The fold lists the
   steps with numbers on the left and minutes lined up on the right. */
.plan-card-title { margin-top: 6px; }
.plan-card-meta { margin-top: 6px; }
.plan-card-notes { display: grid; gap: 8px; margin-top: 14px; }
.plan-card-notes .calm-fact + .calm-fact { margin-top: 0; }
.plan-card-go { margin-top: 20px; }
.plan-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--calm-hair); }
.plan-card-foot .calm-fact { margin: 0; min-width: 0; }
.plan-card-stop { flex: none; min-height: 44px; padding: 0 2px; border: 0; background: none; font: inherit; font-size: 13.5px; color: var(--calm-text-soft); cursor: pointer; white-space: nowrap; }
.plan-card-stop:hover { color: var(--calm-text); text-decoration: underline; text-underline-offset: 3px; }
.plan-card .plan-card-more { margin-top: 0; }
.plan-steps { list-style: none; margin: 2px 0 0; padding: 0; }
.plan-step { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--calm-hair); }
.plan-step:last-child { border-bottom: 0; }
.plan-step-n { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 600; color: var(--calm-text-muted); box-shadow: inset 0 0 0 1.5px var(--calm-hair); }
html.dark .plan-step-n { box-shadow: inset 0 0 0 1.5px rgba(245, 245, 244, .16); }
.plan-step.is-next .plan-step-n { color: var(--calm-accent-text); box-shadow: inset 0 0 0 1.5px var(--calm-accent-focus); }
.plan-step-name { min-width: 0; font-size: 15px; color: var(--calm-text); overflow-wrap: anywhere; }
.plan-step-count { color: var(--calm-text-muted); }
.plan-step-min { font-size: 13px; color: var(--calm-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.plan-budget { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--calm-hair); }
.plan-budget fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.plan-budget legend { padding: 0; margin-bottom: 10px; font-size: 13px; color: var(--calm-text-soft); }

/* Card anatomy, from the day's plan card and shared by every card: a
   head (eyebrow, title, the estimate under it), notes as fact lines, one
   action with room above it, and a footer row with a fact on the left and
   a quiet action on the right. A list of steps or items inside a card is
   numbered on the left with its figure lined up on the right. A label
   inside a card is the small uppercase eyebrow, not loose grey text. */
.card-head > .calm-eyebrow + :is(.calm-title, .calm-h2) { margin-top: 6px; }
.card-head > .calm-meta { margin-top: 6px; }
.card-notes { display: grid; gap: 8px; margin-top: 14px; }
.card-notes > .calm-fact + .calm-fact { margin-top: 0; }
.card-go { margin-top: 20px; }
.card-go + .calm-links { margin-top: 10px; }
.card-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 4px 12px; margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--calm-hair); }
.card-foot > .calm-fact { margin: 0; min-width: 0; flex: 1 1 0; }
.card-foot > :is(a, button, form) { flex: none; }
.card-quiet { min-height: 44px; display: inline-flex; align-items: center; padding: 0 2px; border: 0; background: none; font: inherit; font-size: 13.5px; color: var(--calm-text-soft); cursor: pointer; white-space: nowrap; text-decoration: none; }
.card-quiet:hover { color: var(--calm-text); text-decoration: underline; text-underline-offset: 3px; }
.card-quiet[hidden], .card-quiet.hidden { display: none; }
.card-label { font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--calm-text-muted); margin: 0 0 6px; font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif); font-weight: 400; }
* + .card-label { margin-top: 18px; }
.step-list { list-style: none; margin: 2px 0 0; padding: 0; }
.step-list > li { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--calm-hair); }
.step-list > li:last-child { border-bottom: 0; }
.step-list .step-n { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 600; color: var(--calm-text-muted); box-shadow: inset 0 0 0 1.5px var(--calm-hair); }
html.dark .step-list .step-n { box-shadow: inset 0 0 0 1.5px rgba(245, 245, 244, .16); }
.step-list > li.is-next .step-n { color: var(--calm-accent-text); box-shadow: inset 0 0 0 1.5px var(--calm-accent-focus); }
.step-list > li.is-done .step-n { color: var(--calm-ok); box-shadow: inset 0 0 0 1.5px var(--calm-ok-line); }
.step-list .step-name { min-width: 0; font-size: 15px; color: var(--calm-text); overflow-wrap: anywhere; }
.step-list .step-name .calm-sub { display: block; margin-top: 2px; }
.step-list .step-end { font-size: 13px; color: var(--calm-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
/* A count as a row of fields that fill (partials/fields.html). */
.calm-fields { display: flex; gap: 5px; width: 100%; max-width: 300px; margin-top: 12px; }
.calm-fields.is-centered { margin-inline: auto; justify-content: center; }
.calm-fields > i, .calm-fields-bar { flex: 1 1 0; height: 8px; max-width: 44px; border-radius: 4px; background: rgba(44, 40, 37, .10); }
.calm-fields > i.is-on { background: var(--calm-ok); }
.calm-fields > i.is-half { background: linear-gradient(90deg, var(--calm-ok) 50%, rgba(44, 40, 37, .10) 50%); }
.calm-fields > i.is-now { background: transparent; box-shadow: inset 0 0 0 1.5px var(--calm-accent-focus); }
.calm-fields-bar { display: block; max-width: none; overflow: hidden; }
.calm-fields-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--calm-ok); }
.calm-fields.is-small { max-width: 132px; gap: 3px; margin-top: 7px; }
.calm-fields.is-small > i, .calm-fields.is-small .calm-fields-bar { height: 5px; border-radius: 3px; }
.calm-fields.is-inline { display: inline-flex; width: 72px; margin: 0 8px 0 0; vertical-align: middle; }
html.dark .calm-fields > i, html.dark .calm-fields-bar { background: rgba(245, 245, 244, .14); }
html.dark .calm-fields > i.is-on, html.dark .calm-fields-bar > i { background: var(--calm-ok); }
html.dark .calm-fields > i.is-half { background: linear-gradient(90deg, var(--calm-ok) 50%, rgba(245, 245, 244, .14) 50%); }
html.dark .calm-fields > i.is-now { background: transparent; }
.calm-fields-key { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 8px; }

/* "How to learn with cards" above a card (partials/card_guide.html), and
   its link beside Exit. */
.card-guide { margin: 12px 0 18px; }
.card-guide .step-list > li { grid-template-columns: 24px minmax(0, 1fr); align-items: start; }
.card-guide-links { display: inline-flex; align-items: center; gap: 18px; }
.card-guide-links button.calm-link { border: 0; background: none; padding: 0; font-family: inherit; cursor: pointer; }
.card-guide .card-go .calm-btn-quiet { justify-content: center; text-align: center; }
/* A quiet action at the end of a step row ("Learn it anyway"). */
.step-act { min-height: 40px; padding: 0 2px; border: 0; background: none; font: inherit; font-size: 13px; color: var(--calm-accent-text); cursor: pointer; white-space: nowrap; }
.step-act:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Rows never squeeze their name into a narrow column: on a phone the name
   keeps at least about half the row and a long note on the right wraps
   within its own side instead. */
@media (max-width: 480px) {
  .calm-row > .calm-nm { min-width: min(52%, 13rem); }
  .calm-row > .calm-sub { max-width: 44%; }
}

/* Today opens with the day itself: the date as an eyebrow and the
   greeting in the serif of the titles, with room before the first card.
   Rows of things waiting carry a small icon tile, so the list reads at a
   glance, and "A test is coming?" is a row with its own line of help. */
.today-head { margin: 10px 0 22px; }
.today-head .calm-eyebrow { margin: 0; }
.today-hello { margin-top: 4px; font-family: Lora, Georgia, serif; font-size: 27px; line-height: 1.2; font-weight: 500; color: var(--calm-text); overflow-wrap: anywhere; }
.today-row { gap: 14px; }
.today-ico { flex: none; width: 34px; height: 34px; border-radius: 11px; display: grid; place-items: center; background: var(--calm-surface); box-shadow: inset 0 0 0 1px var(--calm-hair); }
.today-ico svg { width: 17px; height: 17px; fill: none; stroke: var(--calm-text-soft); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.today-entry .today-ico { background: var(--calm-ok-bg); box-shadow: none; }
.today-entry .today-ico svg { stroke: var(--calm-ok); }

/* ── Small touches: paper and ink ─────────────────────────────────
   Nothing here adds a step or a reward. Each one shows what just happened
   the way pen and paper would: a mark is drawn, a passage is highlighted, a
   button gives under the finger, a card leaves the way it came. All of it
   is off under reduced motion, where every state simply appears. */
@media (prefers-reduced-motion: no-preference) {
  /* The question settles a step smaller as its answer arrives (the answer
     panel; a revealed flashcard), rather than jumping. */
  .calm-session-card > .calm-title, .calm-session-card > .calm-instruction,
  .calm-flashcard-stage > .calm-title { transition: font-size .22s var(--calm-motion-ease), color .22s ease; }

  /* The reason and the ordering feedback settle in under a revealed
     answer (partials/answer_reason.html, session_solution.html). */
  .calm-why, .calm-order-feedback { animation: calm-why-in .28s var(--calm-motion-ease) both; }
  @keyframes calm-why-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
  [data-answer-reason] { animation: calm-reason-in 160ms ease-out; }
  @keyframes calm-reason-in { from { opacity: .4; } to { opacity: 1; } }

  /* The tick or cross is drawn in one stroke instead of popping in. */
  #mc-options .calm-mark { animation: none; }
  #mc-options .calm-mark path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: calm-ink-draw .42s cubic-bezier(.4, 0, .2, 1) .06s forwards; }
  @keyframes calm-ink-draw { to { stroke-dashoffset: 0; } }

  /* The passage an answer comes from is swept by a highlighter, left to
     right, once. It ends as the same band the notes always showed. */
  .calm-source-notes mark.is-arriving {
    background-color: transparent; background-repeat: no-repeat;
    background-image: linear-gradient(rgba(91, 122, 90, .26), rgba(91, 122, 90, .26));
    animation: calm-highlighter .75s cubic-bezier(.33, .1, .2, 1) .18s both;
  }
  html.dark .calm-source-notes mark.is-arriving { background-color: transparent; background-image: linear-gradient(rgba(127, 176, 124, .3), rgba(127, 176, 124, .3)); }
  @keyframes calm-highlighter { from { background-size: 0% 100%; } to { background-size: 100% 100%; } }

  /* Buttons and answers give a little under the finger. */
  .calm-btn { transition: filter var(--u-motion-fast, 120ms) var(--u-motion-ease, ease), transform 90ms ease; }
  /* The same give as the action bar's own buttons, further up this file. */
  .calm-btn:active:not(:disabled) { transform: scale(.98); }
  .calm-pay-options button, .calm-option-body { transition: transform 90ms ease, border-color var(--u-motion-fast, 120ms) ease, background-color var(--u-motion-fast, 120ms) ease; }
  .calm-pay-options button:active, .calm-option:active .calm-option-body { transform: scale(.985); }
  #mc-options label.calm-pick:active { transform: scale(.992); }

  /* A row that goes somewhere leans that way when it is about to. */
  a.calm-row::after { transition: transform .16s ease; }
  a.calm-row:hover::after, a.calm-row:active::after, a.calm-row:focus-visible::after { transform: translateX(3px); }

  /* A progress bar grows from where the last question left it (or from
     nothing, for the day's goal) instead of appearing at its new length. */
  .calm-meter > i[style*="--calm-fill-from"], .goal-mini > i[style*="--calm-fill-from"] { transform-origin: left center; animation: calm-fill-grow .55s cubic-bezier(.33, .1, .2, 1) both; }
  @keyframes calm-fill-grow { from { transform: scaleX(calc(var(--calm-fill-from, 0) / 100)); } }

  /* A card being closed slides back down as its veil clears. */
  .calm-study-modal.is-closing .calm-study-modal-veil { animation: calm-veil-out .16s ease both; }
  .calm-study-modal.is-closing .calm-study-modal-card { animation: calm-sheet-down .16s ease-in both; }
  @keyframes calm-veil-out { to { opacity: 0; } }
  @keyframes calm-sheet-down { to { transform: translateY(18px); opacity: 0; } }

  .lookup-waiting i { animation: calm-waiting 1.1s ease-in-out infinite alternate; }
  .lookup-waiting i:nth-child(2) { animation-delay: .15s; }
  .lookup-waiting i:nth-child(3) { animation-delay: .3s; }
  @keyframes calm-waiting { from { opacity: .45; } to { opacity: 1; } }

  /* A fold's chevron turns over as it opens. */
  .calm-more > summary::after { transition: transform .16s var(--calm-motion-ease, ease); }

  /* What the end of a session does, in smaller ways everywhere: the main
     card of Today and the next part of the day settle in, a box gives a
     small pop when it is ticked (small-touches.js marks only a fresh tick,
     never one already ticked on load), and the day's figures rise in one
     after another while their numbers count up. */
  .journey-next, .up-next { animation: calm-rise .34s cubic-bezier(.33, .1, .2, 1) both; }
  .calm-just-ticked { animation: calm-tick-pop .24s cubic-bezier(.3, 1.6, .5, 1); }
  @keyframes calm-tick-pop { from { transform: scale(.78); } to { transform: none; } }
  .day-stat { animation: calm-rise .32s cubic-bezier(.33, .1, .2, 1) both; }
  .day-stat:nth-child(2) { animation-delay: .06s; }
  .day-stat:nth-child(3) { animation-delay: .12s; }
  .day-stat:nth-child(4) { animation-delay: .18s; }
  /* A part of today finished since the last screen fills in, left to
     right, a moment after the page settles. */
  .day-track-cells > i.is-fresh { transform-origin: left center; animation: calm-track-fill .6s cubic-bezier(.33, .1, .2, 1) .3s both; }
  @keyframes calm-track-fill { from { transform: scaleX(0); } to { transform: none; } }
}
/* While "Look it up" is fetching: three quiet lines where the text will be. */
.lookup-waiting { display: grid; gap: 10px; padding-top: 4px; }
.lookup-waiting i { display: block; height: 11px; border-radius: 6px; background: var(--calm-hair); }
.lookup-waiting i:nth-child(1) { width: 46%; height: 14px; }
.lookup-waiting i:nth-child(3) { width: 72%; }

/* The top bar's edge is drawn only once something has scrolled under it, so
   a page at rest starts as one clean sheet. Where the browser cannot tie
   this to scrolling, the edge stays as it was. */
@supports (animation-timeline: scroll()) {
  .calm-topbar { border-bottom-color: transparent; animation: calm-topbar-edge linear both; animation-timeline: scroll(root); animation-range: 0 28px; }
  @keyframes calm-topbar-edge { to { border-bottom-color: var(--calm-hair); box-shadow: 0 8px 18px -16px rgba(44, 40, 37, .45); } }
}

/* Shared first-use surfaces and resilient action rows. */
.calm-milestone { padding:16px 18px; border-left:3px solid var(--calm-ok); background:var(--calm-surface); border-radius:0 14px 14px 0; }
.calm-deadline { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:12px 0; border-block:1px solid var(--calm-hair); }
.calm-deadline > :first-child { min-width:0; }
.calm-deadline > .calm-sub { flex-shrink:0; }
/* Every "more" fold is the same quiet row: a hairline above, the label on
   the left, the .app-disclosure chevron on the right. It replaces the
   browser's small triangle beside grey text, which sat wherever the fold
   happened to be and read as a stray note rather than something to open.
   A run of folds reads as one list, so the ones after the first close up. */
.calm-more { border-top:1px solid var(--calm-hair); }
.calm-more + .calm-more { margin-top:0; }
.calm-more > summary { display:flex; width:100%; min-height:48px; align-items:center; justify-content:space-between; gap:12px; padding:12px 2px; cursor:pointer; list-style:none; color:var(--calm-text-soft); font-size:14px; line-height:1.45; overflow-wrap:anywhere; }
.calm-more > summary::-webkit-details-marker { display:none; }
.calm-more > summary::after { content:""; flex:0 0 auto; width:.8rem; height:.8rem; background-color:currentColor; opacity:.5;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat; }
.calm-more[open] > summary::after { transform:rotate(180deg); }
.calm-more[open] { padding-bottom:14px; }
.calm-more > summary:hover { color:var(--calm-text); }
.calm-more > summary:focus-visible { outline:2px solid var(--calm-accent-focus); outline-offset:3px; border-radius:4px; }
@media (forced-colors: active) { .calm-more > summary::after { background-color:CanvasText; opacity:1; forced-color-adjust:none; } }
.calm-form-actions { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.calm-form-actions > .calm-btn { flex:1 1 160px; width:auto; margin-top:0; }
.calm-form-actions > .calm-link { display:inline-flex; align-items:center; justify-content:center; min-height:44px; padding:10px 14px; }
.calm-page :is(.calm-title,.calm-h2,.calm-nm) { overflow-wrap:anywhere; }
.calm-row > .calm-sub { flex:0 1 auto; max-width:48%; white-space:normal; overflow-wrap:anywhere; }
@media (max-width:480px) {
  .calm-form-actions { margin-top:16px; }
  .calm-deadline { gap:10px; }
}
/* First-use polish: utility pages stay compact without shrinking tap targets. */
.calm-footer { margin-top:28px; padding-top:16px; }
.calm-auth .calm-field,
html.dark .calm-auth .calm-field {
  min-height:46px; padding:11px 13px; border:1px solid rgba(44, 40, 37, .22) !important;
  border-radius:12px !important; background:var(--calm-bg-parchment) !important;
  color:var(--calm-text) !important;
}
/* A clear edge without the near-black outline: the same box as .calm-box
   on in-app forms, a step firmer so a sign-in field is never missed. */
html.dark .calm-auth .calm-field { border-color: rgba(245, 245, 244, .22) !important; }
.calm-auth .calm-field:focus { border-color: var(--calm-accent-focus) !important; }
.calm-auth .calm-field:focus-visible { outline:2px solid var(--calm-accent-focus); outline-offset:3px; }
.calm-page :is(.calm-btn, .calm-btn-quiet, .calm-choice, .calm-link, .calm-back):focus-visible {
  outline:2px solid var(--calm-accent-focus); outline-offset:3px;
}
.calm-position-range { width:100%; min-height:44px; accent-color:var(--calm-accent-focus); }
.calm-back[data-personal-position="1"] {
  position:fixed; z-index:34; left:var(--back-x); top:var(--back-y); bottom:auto;
  width:46px; height:46px; padding:0; margin:0; background:var(--calm-surface); box-shadow:var(--calm-lift);
}
.calm-back[data-personal-position="1"] .calm-back-label { display:none; }
body:not([data-study-page="1"]) #companion-widget[data-help-label]:not([data-help-label=""]):not([hidden])::after {
  content:attr(data-help-label); position:absolute; left:50%; bottom:-5px; transform:translateX(-50%);
  color:var(--calm-text-muted); background:var(--calm-surface); border-radius:6px;
  padding:1px 5px; font:500 11px/1.4 Inter, sans-serif; white-space:nowrap;
}
@media (max-width:767px), (hover:none) {
  .calm-page kbd, .calm-page .calm-kbd { display:none !important; }
}

.calm-menu { max-height:calc(100dvh - 76px); overflow-y:auto; overscroll-behavior:contain; }

[data-compare] .calm-row > .calm-sub { flex:0 1 54%; white-space:normal; }

/* Management uses the laptop width; question and reading pages stay focused. */
.calm-workspace { max-width: 72rem; }
.subject-workspace > * { min-width: 0; }
[data-notes-toc] li a { display: inline-flex; align-items: center; min-height: 44px; padding: .25rem 0; overflow-wrap: anywhere; }
@media (min-width: 1024px) {
  .subject-workspace { display: grid; grid-template-columns: minmax(0, 1fr) minmax(18rem, 23rem); gap: 3rem; align-items: start; }
  .subject-next { grid-column: 2; grid-row: 1; }
  .subject-materials { grid-column: 1; grid-row: 1; }
  .subject-materials > .calm-sect:first-child { margin-top: 0; }
}
@media (max-width: 380px) {
  .calm-head { flex-wrap: wrap; }
  .calm-row { column-gap: .6rem; }
  .calm-row > .calm-sub { overflow-wrap: anywhere; }
}

/* Keep supporting study controls next to their context, with readable spacing. */
.calm-study-actions { display:flex; align-items:center; flex-wrap:wrap; gap:8px 16px; }
.calm-study-actions > form { margin:0; }
.calm-study-actions .calm-btn-quiet { margin-top:0; }
.calm-study-actions .calm-target { justify-content:flex-start; text-align:left; }
.calm-study-stats { margin-top:12px; }
.calm-study-stats > div { display:flex; align-items:baseline; justify-content:space-between; gap:16px; padding:10px 0; border-bottom:1px solid var(--calm-hair); }
.calm-study-stats dt { min-width:0; color:var(--calm-text-muted); font-size:14px; }
.calm-study-stats dd { margin:0; flex-shrink:0; font-variant-numeric:tabular-nums; }
.calm-study-context { max-width:62ch; }

/* Small groups have equal visual weight; reading and form labels stay aligned
   with their content. Allow labels to wrap instead of shrinking touch targets. */
.calm-heading-row { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:12px 16px; margin-top:12px; }
.calm-heading-row > div { flex:1 1 8rem; min-width:0; }
.calm-heading-row > .calm-btn-quiet { flex:0 1 auto; justify-content:center; text-align:center; }
.calm-shortcuts { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,6.5em),1fr)); gap:8px; margin:24px auto; max-width:36rem; font-size:13px; }
.calm-shortcuts > a { display:flex; align-items:center; justify-content:center; min-height:48px; padding:10px 8px; border:1px solid var(--calm-hair); border-radius:12px; background:var(--calm-surface); color:var(--calm-text-soft); font-size:13px; line-height:1.5; text-align:center; text-decoration:none; overflow-wrap:anywhere; }
.calm-shortcuts > a:focus-visible { outline:2px solid var(--calm-accent-focus); outline-offset:3px; }
@media (hover:hover) { .calm-shortcuts > a:hover { border-color:var(--calm-accent-focus); color:var(--calm-accent-text); } }
.calm-choice-row { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,5.5em),1fr)); gap:8px; margin-top:8px; font-size:13px; }
.calm-choice-row > .calm-btn-quiet { justify-content:center; text-align:center; padding-inline:8px; min-width:0; overflow-wrap:anywhere; }
.calm-action-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,10rem),1fr)); gap:12px; align-items:stretch; }
.calm-action-grid > form { display:flex; min-width:0; margin:0; }
.calm-action-grid .calm-btn-quiet { width:100%; justify-content:center; text-align:center; margin:0; overflow-wrap:anywhere; }
.calm-search-row { display:flex; align-items:stretch; flex-wrap:wrap; gap:12px; }
.calm-search-row > input { flex:1 1 12rem; min-width:0; }
.calm-search-row > button { flex:0 0 auto; min-width:96px; justify-content:center; }
.paper-card-art.calm-subject-heading { flex-wrap:wrap; }
.paper-card-art.calm-subject-heading > :last-child { flex:1 1 10em; }

/* Reading must never depend on swipe initialization. Short cards retain their
   centered composition; long cards grow in the document and scroll normally. */
.calm-flashcard-wrap.has-next::after, .calm-flashcard-wrap.has-more::before { height:calc(100% - 36px); }
.calm-flashcard-stage > * { flex-shrink:0; }
.calm-answer.calm-answer-prose { text-align:left; font-family:inherit; font-size:17px; font-weight:400; line-height:1.65; }
/* What you can do after an answer: optional grade changes, the source and
   report row, then one fold of advice. */
.calm-study-support { display:grid; gap:4px; margin-top:16px; text-align:left; }
.calm-study-support > .calm-study-check { justify-self:center; }
.calm-study-support > .calm-remedies { margin-top:12px; }
.calm-answer-options { display:grid; gap:10px; margin-top:4px; }
.calm-answer-options > .calm-sub { text-align:center; }
.calm-feel-pair { display:grid; grid-template-columns:1fr 1fr; gap:10px; width:min(100%,360px); margin-inline:auto; }
.calm-feel-pair > .calm-btn-quiet { justify-content:center; margin:0; min-width:0; }
.calm-remedy-list { display:grid; gap:16px; padding-top:4px; }
.calm-remedy-list > section + section { border-top:1px solid var(--calm-hair); padding-top:16px; }
.calm-remedy-title { font-size:14px; font-weight:600; color:var(--calm-text); }
.calm-remedy-list .calm-link { display:inline-flex; margin-top:6px; }
.calm-study-check { display:flex; align-items:flex-start; gap:10px; min-height:44px; padding:10px 0; color:var(--calm-text-muted); font-size:13px; line-height:1.6; }
.calm-study-check > input { flex:0 0 auto; margin-top:4px; accent-color:var(--calm-accent-focus); }
.calm-session-card #calm-solution { padding-inline-start:0; border-inline-start:0; }
.calm-session-card #calm-solution > .mt-6 { margin-top:20px; }
.calm-review-activities > section, .calm-review-activities > details { margin-top:20px; padding-top:20px; border-top:1px solid var(--calm-hair); }
@media (max-width:480px) {
  .calm-review-activities .calm-review-topic { grid-template-columns:auto minmax(0,1fr); align-items:start; gap:10px 12px; }
  .calm-review-topic > :is(button,a.calm-btn-quiet) { grid-column:2; justify-content:center; }
}
@media (max-width:767px) {
  body:has(.calm-session-actions) #main { padding-bottom:calc(var(--session-actions-h, 140px) + 32px); }
  body:has(.calm-session-actions) .calm-study-viewport { min-height:calc(100dvh - var(--session-progress-h, 88px) - var(--session-actions-h, 140px)); }
  .calm-flashcard-wrap { --calm-flashcard-height:clamp(220px,calc(100dvh - var(--session-progress-h, 88px) - var(--session-actions-h, 140px) - 160px),400px); }
}

/* A test's plan, day by day (partials/test_plan_days.html): the day and its
   time on one row, its steps under it in quiet text. */
.test-plan-day { border-bottom: 1px solid var(--calm-hair); padding-bottom: 8px; }
.test-plan-day > .calm-row { border-bottom: 0; padding-bottom: 2px; }
.test-plan-tasks { margin: 0; padding: 0; list-style: none; }
.test-plan-tasks > li { padding: 2px 0; }


/* ── Study sheets (study_sheet.html): the clean notes written while a
   topic was learned, per topic or for a whole test. Printing keeps only
   the notes. ── */
.sheet-topic + .sheet-topic { margin-top: 40px; }
.sheet-step + .sheet-step { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--calm-hair); }
.sheet-step-title { font-family: Lora, Georgia, serif; font-size: 19px; line-height: 1.3; color: var(--calm-text); }
.sheet-own { display: inline-block; margin-left: 6px; font-size: 12.5px; color: var(--calm-text-muted); font-weight: 400; }
.sheet-remember { margin-top: 14px; padding: 12px 14px; border-radius: 12px; background: var(--calm-ok-bg); }
.sheet-remember ul { list-style: none; padding: 0; margin: 6px 0 0; display: grid; gap: 6px; }
.sheet-remember li { position: relative; padding-left: 18px; color: var(--calm-text); font-size: 15px; line-height: 1.45; }
.sheet-remember li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 7px; height: 7px; border-radius: 50%; background: var(--calm-ok); }
.sheet-hook { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--calm-hair); color: var(--calm-text); font-size: 14.5px; line-height: 1.45; }
.sheet-hook .calm-eyebrow { margin-right: 6px; }
.sheet-actions { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; }
@media print {
  body:has(.sheet-page) :is(.calm-topbar, .calm-nav, nav, footer, .calm-back, [data-companion-root]),
  [data-sheet-noprint] { display: none !important; }
  body:has(.sheet-page) { background: #fff !important; color: #000 !important; }
  .sheet-page .calm-card { box-shadow: none !important; border: 0 !important; padding: 0 !important; background: none !important; }
  .sheet-topic { break-inside: auto; }
  .sheet-step { break-inside: avoid; }
  .sheet-remember { background: none; border-left: 3px solid #5b7a5a; border-radius: 0; }
}

/* ── Account & tools pages (audit, Oct 20) ────────────────────────
   Signed-out forms: a label sat flush on its field, so the focus ring
   drew through the label text. Study pattern: the observations are one
   list in one card (calm/study_pattern.html), each with its toggle at
   the row's end. */
.calm-auth-label { margin-bottom: 8px; }
.study-signal { align-items: flex-start; }
.study-signal-value { margin-top: 2px; font-size: 16px; font-weight: 600; color: var(--calm-text); }
.calm-links.study-signal-toggle { flex: 0 0 auto; margin-top: 0; }

/* ── Audit 3: flashcards, words, decks, reading, palace ───────────
   A row's secondary actions (edit, mark known, remove) sit behind a "⋯"
   menu, the same shape deck_manage uses for cards, instead of a second
   line of links under every row. */
.calm-row-menu { position: relative; flex: 0 0 auto; margin-left: auto; }
.calm-row-menu > summary { list-style: none; cursor: pointer; color: var(--calm-text-soft); }
.calm-row-menu > summary::-webkit-details-marker { display: none; }
.calm-row-menu > summary svg { width: 20px; height: 20px; }
.calm-row-menu-list { position: absolute; right: 0; top: 100%; z-index: 20; width: 12rem; }
.calm-row-menu-list form { margin: 0; }
/* .calm-label sets its own margin, which beats a Tailwind mt-* on the
   same element; a label that needs space above it uses this. */
.calm-label.calm-label-gap { margin-top: 24px; }
/* A one-line row whose only control is a 44px menu target: the target
   gives it its height, so the row's own padding is trimmed. */
.calm-row.calm-row-compact { padding-top: 3px; padding-bottom: 3px; }


/* ---- Ordering feedback (session_solution.html, markRevealedAnswer) ----
   Only the steps out of place are marked, each with where it belongs; the
   rest of the learner's order is left plain. The right order follows, each
   step with what the answer says about it, such as its date. */
.calm-order-pill.is-in-order { color: var(--calm-text); }
.calm-order-pill.is-wrong { background: var(--calm-no-bg); }
.calm-order-pill.is-right { background: var(--calm-ok-bg); }
.calm-order-goes {
  flex: 0 0 auto; margin-left: auto; padding: 3px 9px; border-radius: 999px;
  background: var(--calm-surface); border: 1px solid var(--calm-no-line);
  color: var(--calm-no); font-size: 12px; font-weight: 600; white-space: nowrap;
}
.calm-order-summary { color: var(--calm-text); font-size: 15px; line-height: 1.5; max-width: 36rem; }
.calm-order-key .calm-order-pill { padding-top: 10px; padding-bottom: 10px; }
.calm-order-key .calm-order-rank { background: var(--calm-ok-bg); color: var(--calm-ok); }
/* Under the step, whole: a long period ("stredná doba bronzová") was cut to
   "stredná doba bronzo…" when it sat on the right. */
.calm-order-detail {
  display: table; margin-top: 4px; padding: 2px 9px; border-radius: 999px;
  background: rgba(44, 40, 37, .06); color: var(--calm-text-muted);
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.4;
}
html.dark .calm-order-detail { background: rgba(245, 245, 244, .09); }

/* ---- Why the answer is right (partials/answer_reason.html) ----
   A soft paper card with a small bulb: easy to read at a glance and easy to
   pass over. Warm in both verdicts, so it explains rather than judges. */
.calm-why {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: start;
  max-width: 38rem; padding: 14px 16px 15px 14px; border-radius: 16px;
  background: linear-gradient(180deg, rgba(185, 93, 10, .07), rgba(185, 93, 10, .035));
  border: 1px solid rgba(185, 93, 10, .16);
}
html.dark .calm-why {
  background: linear-gradient(180deg, rgba(240, 163, 90, .10), rgba(240, 163, 90, .05));
  border-color: rgba(240, 163, 90, .20);
}
.calm-why-icon {
  display: grid; width: 30px; height: 30px; place-items: center; border-radius: 10px;
  background: var(--calm-surface); color: var(--calm-accent-text);
  box-shadow: var(--calm-control-shadow);
}
.calm-why-icon svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.calm-why-label {
  color: var(--calm-accent-text); font-size: 11.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; line-height: 30px;
}
.calm-why-text { margin-top: 2px; color: var(--calm-text); font-size: 15px; line-height: 1.55; }
.calm-why-compact { padding: 10px 12px 11px 10px; gap: 10px; border-radius: 13px; }
.calm-why-compact .calm-why-icon { width: 26px; height: 26px; border-radius: 8px; }
.calm-why-compact .calm-why-label { line-height: 26px; }
.calm-why-compact .calm-why-text { font-size: 14px; }

/* ---- Design pass: states, text links and quiet buttons ----
   A state a row is in ("New", "3 ready", "Suspended") is a small chip, so it
   reads at a glance down a list instead of as more grey text. */
.calm-chip {
  display: inline-flex; flex: 0 0 auto; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600;
  line-height: 1.25; white-space: nowrap; vertical-align: 1px;
}
.calm-chip-new { background: rgba(185, 93, 10, .11); color: var(--calm-accent-text); }
.calm-chip-ready { background: var(--calm-ok-bg); color: var(--calm-ok); }
.calm-chip-muted { background: rgba(44, 40, 37, .07); color: var(--calm-text-muted); }
html.dark .calm-chip-new { background: rgba(240, 163, 90, .14); }
html.dark .calm-chip-muted { background: rgba(245, 245, 244, .09); }
.calm-row > .calm-chip + .calm-sub { margin-left: -4px; }

/* Text links under a card read as plain grey text: a soft underline and a
   little more weight say they can be tapped, still well below the primary
   button. */
.calm-links a:not(.calm-btn):not(.calm-btn-quiet), .calm-links button:not(.calm-btn):not(.calm-btn-quiet) {
  color: var(--calm-text-soft); font-weight: 500;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
  text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
}
.calm-links a:not(.calm-btn):not(.calm-btn-quiet):hover, .calm-links button:not(.calm-btn):not(.calm-btn-quiet):hover {
  color: var(--calm-text); text-decoration-color: currentColor;
}

/* A quiet button had a 7% border and no depth, so a full-width one ("Make a
   set") looked like a text field. A visible edge, a hairline of depth and
   centred text when it is full width. */
.calm-btn-quiet {
  border-color: rgba(44, 40, 37, .14); box-shadow: var(--calm-control-shadow);
  color: var(--calm-text); font-weight: 600;
}
html.dark .calm-btn-quiet { border-color: rgba(245, 245, 244, .16); }
.calm-btn-quiet.w-full, .card-go > .calm-btn-quiet, .card-go form > .calm-btn-quiet { justify-content: center; text-align: center; }
.calm-btn-quiet:hover { border-color: rgba(44, 40, 37, .24); }
html.dark .calm-btn-quiet:hover { border-color: rgba(245, 245, 244, .26); }
/* Under "Did you remember it?": what the choice decides, on its own quiet
   line so the question stays one line. */
.calm-grade-hint { display: block; margin-top: 2px; font-size: 12px; color: var(--calm-text-muted); }
/* A run of folds is one list (Account's preferences, a topic's tools): the
   hairline between them is the separation, so the ones after the first
   close up instead of each opening a new 28px section. */
details.app-disclosure.calm-sect + details.app-disclosure.calm-sect,
details.app-disclosure.calm-sect + form > details.app-disclosure.calm-sect:first-child { margin-top: 0; }
/* A chip that carries a sentence (the sample lesson's note) wraps. */
.calm-chip-wrap { display: flex; white-space: normal; border-radius: 10px; padding: 6px 10px; margin-bottom: 12px; line-height: 1.4; }
/* The danger link as a form button (subject settings). */
button.calm-danger-link { background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit; }
/* Session setup's dropdowns: the same quiet chevron as every other form
   (select.calm-box above), not the browser's heavy arrow. */
.practice-fields select {
  -webkit-appearance: none; appearance: none; padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8178' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px 16px;
}
html.dark .practice-fields select { color-scheme: dark; }
/* One look for every fold: the quiet row ("Plan details and study time",
   "More ways to practise"). A fold whose summary carried the serif section
   title read as one more section heading, so pages with a few of them
   (a task, Friends, Focus, subject settings) looked like stacks of
   headings. Section titles that are not folds keep the serif. */
body[data-u7-calm-core="1"] details.app-disclosure > summary.calm-label {
  font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
  font-size: 14px; font-weight: 400; letter-spacing: 0; line-height: 1.45;
  color: var(--calm-text-soft);
}
body[data-u7-calm-core="1"] details.app-disclosure > summary.calm-label:hover { color: var(--calm-text); }
/* Premium's planned prices while not on sale: a quiet list. */
.calm-price-list { border-block: 1px solid var(--calm-hair); }

/* ── One search field ─────────────────────────────────────────────
   The Search page's rounded box with a magnifier, used by every search
   (Search, Your words, Shared libraries, a deck's cards). Two of them were
   underlined lines, one a filled box. A row holds the field and its button
   at the same height. */
.calm-search-input {
  width: 100%; min-height: 52px; padding: 11px 14px 11px 44px;
  border: 1px solid var(--calm-hair); border-radius: 15px;
  background: var(--calm-surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8178' stroke-width='1.7' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.3-4.3'/%3E%3C/svg%3E") no-repeat 15px center / 19px 19px;
  box-shadow: 0 1px 2px rgba(44, 40, 37, .03);
  color: var(--calm-text); font: inherit; font-size: 16px;
}
.calm-search-input::placeholder { color: var(--calm-text-muted); }
.calm-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.calm-search-input:focus { outline: 2px solid var(--calm-accent-focus); outline-offset: 2px; }
.calm-search-input.has-clear { padding-right: 46px; }
.calm-search-line { display: flex; align-items: stretch; gap: 8px; }
.calm-search-line > .calm-search-input, .calm-search-line > .calm-search-field { flex: 1 1 auto; min-width: 0; }
.calm-search-line > .calm-btn-quiet { flex: 0 0 auto; min-height: 52px; margin: 0; justify-content: center; }

/* More time today? (more_time.html): one card a step, its length and its
   action on one row at the foot. */
.more-time-steps { display: grid; gap: 12px; }
.more-time-step-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.more-time-step-foot > .calm-btn { width: auto; flex: 0 1 auto; margin: 0; padding-inline: 20px; }
.more-time-step-foot > .calm-btn-quiet { margin: 0; }

/* ── Quieter study cards ──────────────────────────────────────────
   A question or a card shows one thing large (what to work on) and as
   little else as it can. Where the item is from (topic, language) sits in
   the progress line above the card, after the count, and is cut short there
   rather than wrapping. The instruction is one short line in the accent
   colour, read as "the task", directly above the prompt. The labels over a
   revealed answer ("Answer", "Correction", "You wrote") are small capitals
   that name the part without competing with it, and the card guide is a
   "?" beside Exit rather than a second link in words. */
.calm-session-where { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.calm-session-topic { color: var(--calm-text-muted); }
.calm-session-card .calm-instruction {
  margin: 0 0 12px; font-size: 14px; font-weight: 500; line-height: 1.45; color: var(--calm-accent-text);
}
.calm-session-card .calm-instruction + .calm-title { margin-top: 0; }
.calm-session-card > .calm-title:first-child,
.calm-session-card > .calm-instruction:first-child { margin-top: 2px; }
.calm-session-card .calm-answer-box { margin-top: 28px; }
.calm-session-card .calm-answer-optional { margin-top: 10px; font-size: 12.5px; }
.calm-session-card .calm-sure { margin-top: 20px; }
.calm-flashcard-answer .calm-label,
#calm-solution .calm-label,
.calm-flashcard-stage .calm-label {
  font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
  font-size: 11.5px; font-weight: 500; letter-spacing: .09em; text-transform: uppercase;
  color: var(--calm-text-muted); margin: 0 0 2px;
}
.calm-flashcard-answer { margin-top: 30px; padding-top: 24px; }
.card-guide-links { gap: 10px; }
.card-guide-links .card-guide-help {
  display: inline-grid; place-items: center; width: 44px; height: 44px; margin: -10px -6px -10px 0;
  border-radius: 50%; font-size: 14px; font-weight: 600;
}
.card-guide-links .card-guide-help > span {
  display: inline-grid; place-items: center; width: 24px; height: 24px;
  border: 1px solid currentColor; border-radius: 50%; line-height: 1; opacity: .85;
}
.card-guide-links .card-guide-help:hover > span, .card-guide-links .card-guide-help:focus-visible > span { opacity: 1; }

/* ── The answer panel (calm/session_solution.html) ────────────────
   After the reveal the answer is the point of the screen, so it gets one
   surface of its own and the question steps back. The panel reads top to
   bottom: the verdict as a pill, the answer large, then why, as a section
   of the same panel rather than a second card. Its left edge carries the
   verdict's colour (green right, red not right, neutral when you grade it
   yourself), so the result is clear before a word is read, without
   flooding the answer in red. */
.calm-session-card:has(#calm-solution) > .calm-title { font-size: 21px; line-height: 1.32; color: var(--calm-text-soft); margin-bottom: 0; }
.calm-session-card:has(#calm-solution) > .calm-title.calm-order-title { font-size: 19px; }
.calm-session-card:has(#calm-solution) > .calm-instruction { color: var(--calm-text-muted); margin-bottom: 8px; }
.calm-session-card #calm-solution { margin-top: 20px; }

.calm-reveal-panel {
  --reveal-edge: rgba(44, 40, 37, .2);
  position: relative; padding: 18px 18px 20px 21px; border-radius: 16px;
  background: rgba(44, 40, 37, .035);
}
html.dark .calm-reveal-panel { --reveal-edge: rgba(245, 245, 244, .24); background: rgba(245, 245, 244, .045); }
.calm-reveal-panel::before {
  content: ""; position: absolute; left: 0; top: 16px; bottom: 16px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--reveal-edge);
}
.calm-reveal-panel.is-ok { --reveal-edge: var(--calm-ok); background: linear-gradient(180deg, var(--calm-ok-bg), rgba(47, 107, 70, .02) 140px); }
html.dark .calm-reveal-panel.is-ok { background: linear-gradient(180deg, var(--calm-ok-bg), rgba(143, 207, 168, .03) 140px); }
.calm-reveal-panel.is-no { --reveal-edge: var(--calm-no); }
.calm-reveal-panel.is-bare { padding: 0; background: none; }
.calm-reveal-panel.is-bare::before { display: none; }

.calm-reveal-verdict { margin: 0 0 14px; }
.calm-reveal-verdict .calm-verdict {
  align-items: center; gap: 6px; padding: 5px 12px 5px 10px; border-radius: 999px;
  font-size: 14px; line-height: 1.2;
}
.calm-reveal-verdict .calm-verdict-ok { background: var(--calm-ok-bg); }
.calm-reveal-verdict .calm-verdict-no { background: var(--calm-no-bg); }
.calm-reveal-aside { margin: -4px 0 14px; font-size: 13.5px; line-height: 1.5; color: var(--calm-text-soft); }

.calm-reveal-answer .calm-label { margin-bottom: 6px; }
.calm-reveal-answer .calm-answer { font-size: 21px; line-height: 1.42; }
.calm-reveal-answer .calm-answer.calm-answer-prose { font-size: 16.5px; line-height: 1.65; }
.calm-reveal-compare { display: grid; gap: 16px; }
.calm-reveal-yours { padding-top: 14px; border-top: 1px dashed var(--calm-hair); }
html.dark .calm-reveal-yours { border-top-color: rgba(245, 245, 244, .16); }
.calm-reveal-yours .calm-diff-text { font-size: 15px; color: var(--calm-text-soft); }

/* Inside the answer, the marked words are coloured and underlined (put
   in) or struck (taken out) rather than set on coloured blocks, which at
   answer size turned the sentence into a row of tiles. */
.calm-reveal-answer .calm-diff-want {
  background: none; padding: 0; color: var(--calm-ok);
  text-decoration: underline 2px var(--calm-ok-line); text-underline-offset: 5px;
}
.calm-reveal-answer .calm-diff-off { background: none; padding: 0; color: var(--calm-no); }
.calm-reveal-answer del.calm-diff-off { text-decoration-thickness: 1.5px; opacity: .85; }
.calm-reveal-yours .calm-diff-off { text-decoration: underline 1.5px var(--calm-no-line); text-underline-offset: 4px; }

/* Why, as the panel's closing section: a small bulb and label, then the
   reason at full width in an easy reading size. */
.calm-reveal-panel .calm-why {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 7px; align-items: center;
  max-width: none; margin-top: 18px; padding: 16px 0 0; border: 0; border-top: 1px solid var(--calm-hair);
  border-radius: 0; background: none;
}
html.dark .calm-reveal-panel .calm-why { background: none; border-top-color: rgba(245, 245, 244, .12); }
.calm-reveal-panel > .calm-why:first-child,
.calm-reveal-panel > .sr-only:first-child + .calm-why { margin-top: 0; padding-top: 0; border-top: 0; }
.calm-reveal-panel .calm-why-body { display: contents; }
.calm-reveal-panel .calm-why-icon { width: 18px; height: 18px; background: none; box-shadow: none; border-radius: 0; }
.calm-reveal-panel .calm-why-icon svg { width: 17px; height: 17px; }
.calm-reveal-panel .calm-why-label { line-height: 18px; letter-spacing: .09em; }
.calm-reveal-panel .calm-why-text { grid-column: 1 / -1; margin-top: 7px; font-size: 16px; line-height: 1.65; max-width: 36rem; }

/* What else you can do sits under the panel, quieter than it. */
#calm-solution > .calm-study-check { margin-top: 10px; }
#calm-solution > .calm-study-support { margin-top: 12px; }
#calm-solution > .calm-study-support .calm-study-tools-actions { margin-top: 2px; }

/* A revealed card: the question settles a step smaller and the answer
   grows into the space, so the two read as question and answer rather
   than as two headings. */
.calm-flashcard-wrap.is-revealed .calm-flashcard-stage > .calm-title { font-size: 24px; line-height: 1.25; color: var(--calm-text-soft); }
.calm-flashcard-wrap.is-revealed .calm-flashcard-answer .calm-answer:not(.calm-answer-prose) { font-size: 23px; line-height: 1.38; }
.calm-flashcard-answer .calm-answer + .calm-note { margin-top: 14px; font-style: italic; }
@media (max-width: 380px) { .calm-reveal-panel { padding: 15px 14px 16px 17px; } .calm-reveal-panel:not(.is-bare) { margin-inline: -4px; } }

/* ── One way through a question ───────────────────────────────────
   "How sure are you?" is one compact row straight under the question, the
   same on every kind of question: the words on the left, the two choices
   on the right. */
.calm-session-card .calm-sure {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 4px 12px;
  margin-top: 16px; padding: 2px 0;
}
.calm-session-card .calm-sure > .calm-sub { font-size: 13.5px; color: var(--calm-text-soft); }
.calm-session-card .calm-sure-picks { margin-top: 0; gap: 6px; }
.calm-session-card .calm-sure-pick span { padding: 6px 14px; }
.calm-session-card .calm-sure + #mc-options { margin-top: 14px; }
.calm-session-card .calm-sure + .calm-answer-box,
.calm-session-card .calm-sure ~ .calm-answer-box { margin-top: 18px; }

/* Going over the set again (session_done.html): two quiet buttons side by
   side, an icon and a word each, instead of a fold that hid only them. */
.done-again-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.done-again-btn {
  display: flex; align-items: center; justify-content: center; gap: 9px; min-height: 52px; padding: 12px 14px;
  border-radius: 15px; background: var(--calm-surface); color: var(--calm-text); text-decoration: none;
  font-size: 14.5px; font-weight: 500; box-shadow: 0 0 0 1px var(--calm-hair), var(--calm-control-shadow);
}
.done-again-btn:hover { box-shadow: 0 0 0 1px var(--calm-accent-focus), var(--calm-control-shadow); }
.done-again-btn:focus-visible { outline: 2px solid var(--calm-accent-focus); outline-offset: 2px; }
.done-again-btn svg { width: 19px; height: 19px; flex: none; fill: none; stroke: var(--calm-accent-text); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.done-fresh { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 10px; margin-top: 12px; text-align: center; }
.done-fresh button.calm-link { border: 0; background: none; padding: 0 4px; font: inherit; font-size: 13.5px; cursor: pointer; }
/* Session review, every card ticked: the next part of today continues the
   finished card as its lower half, not as a card inside a card. */
.review-finished-next .up-next { margin-top: 22px; padding: 20px 0 0; border-radius: 0; background: none; box-shadow: none; border-top: 1px solid var(--calm-hair); text-align: left; }
.review-finished-next + .calm-links { margin-top: 14px; }
