/* study.css - the study runner (#/review, #/new: js/screens/review.js, js/study/*), Study, the quick quiz and drills
   (their feedback sheet and ⚙), and the grammar pages (#/grammar: js/screens/grammar.js). Only what the design system
   (app.css) does not have already: the question card's faces, the teacher's red stamp on a right answer, the ★ parts,
   the feedback sheet, the meet cards, the grammar lists and lesson parts. Colours and sizes only through the tokens in
   app.css, so light and dark come for free; 44 px to press (48 px or more to answer), 14 px text at the least, 16 px
   inputs; nothing wider than the page at 320 px; on a phone the buttons that go on and the sheet after an answer hold
   to the foot of the screen (docs/mobile-plan.md 1.7). */

/* ---- answer choices (the quiz, the runner, quick checks, reading and listening questions) ---- */
/* The dot and the words on one row: a long answer wraps beside its dot, never under it (app.css lets a phone's
   buttons wrap their content; a choice is the one that must not). */
.page .choices > .choice:not(.icon) { flex-wrap: nowrap; }
.choice > .dot + * { flex: 1 1 auto; min-width: 0; text-align: left; overflow-wrap: anywhere; }

/* ---- the runner's frame ---- */
.rv .rv-title { margin: 0; font-size: var(--fs-20); }
.rv-offline { margin: 0 0 var(--s-3); padding: var(--s-2) var(--s-4); border-radius: var(--r-2); background: var(--warn-soft); color: var(--warn-text); font-weight: 700; font-size: var(--fs-14); }

/* ---- the question card ---- */
.rv-card { cursor: default; min-height: 240px; gap: var(--s-2); padding-top: 60px; }
/* The kind chip says the task in a few words ("Fill the blank", "Reading, in kana"): in the card's flow at its top
   left, two lines when it must, clear of the speaker and the teacher's ○ in the top right corner. */
.flash.rv-card { padding-top: var(--s-4); }
.flash.rv-card > .kind { position: static; align-self: flex-start; max-width: calc(100% - 104px); margin-bottom: var(--s-2); white-space: normal; text-align: left; line-height: 1.3; }
.rv-card .front { display: flex; flex-direction: column; align-items: center; gap: var(--s-2); width: 100%; }
.rv-glyph { font-family: var(--font-hand); font-weight: 400; font-size: clamp(72px, 16vw, 112px); line-height: 1.1; color: var(--ink); }
.rv-glyph.rv-model { margin-top: var(--s-3); color: var(--accent-text); }
.rv-ja { font-size: clamp(32px, 7vw, 44px); line-height: var(--lh-ruby-big); }
.rv-en { font-weight: 700; font-size: clamp(22px, 4.2vw, 30px); line-height: 1.3; overflow-wrap: anywhere; }
.rv-reading { font-size: var(--fs-20); color: var(--ink-2); }
.rv-tags { justify-content: center; }
.flash .front .rv-sentence, .rv-sentence { font-size: var(--fs-26); line-height: var(--lh-ruby); margin: 0; text-align: left; align-self: stretch; }
.rv-sub { margin: 0; color: var(--ink-2); font-size: var(--fs-18); text-align: left; align-self: stretch; }
.rv-card .hint { margin-top: var(--s-2); }
.rv-listen { display: inline-flex; flex-direction: column; align-items: center; gap: var(--s-2); min-height: 96px; min-width: 96px; padding: var(--s-4); border-radius: 50%;
  border: 0; background: var(--accent-soft); color: var(--accent-text); font-weight: 700; font-size: var(--fs-14); }
.rv-listen svg { width: 36px; height: 36px; }
@media (hover: hover) { .rv-listen:hover { background: var(--dye-1); } }
.rv-steps { align-self: stretch; text-align: left; }
.rv-stepline { display: flex; align-items: center; gap: var(--s-2); margin: var(--s-2) 0 0; font-size: var(--fs-14); color: var(--ink-2); }
.rv-note { margin: var(--s-3) 0 0; color: var(--ink-2); }
.rv-due { margin: var(--s-2) 0 0; color: var(--ink-3); font-size: var(--fs-14); }
/* A hint and Don't know: two separate 44 px buttons on the page's gutter, with the row's gap between them */
.rv-tools { margin-top: var(--s-2); gap: var(--s-2) var(--s-3); }
/* A hint, Another hint, Don't know, Start again: one soft 44 px button in every session (Review, Drill, a grammar
   lesson's practice), never bare bold words */
.hint-btn { min-height: var(--tap); padding: 0 var(--s-4); background: var(--surface-2); border-color: transparent; color: var(--ink); font-weight: 700; }
@media (hover: hover) { .hint-btn:hover:not(:disabled) { background: var(--line); border-color: transparent; } }
.rv-answer .kana-hint { margin: var(--s-2) 0 0; }
.rv-hintbox { margin-top: var(--s-3); }
.rv-hintbox p + p { margin-top: var(--s-2); }
.rv-opt-glyph { font-family: var(--font-hand); font-size: var(--fs-30); line-height: 1.2; }

/* the site's done mark (a tick cut out of a filled tokiwa-green circle; the double one for quick and sure), stamped
   on the card's corner when an answer is right: never an open ring, which reads as an empty radio button */
.rv-stamp { position: absolute; top: var(--s-4); right: 56px; width: 48px; height: 48px; pointer-events: none; transform: rotate(-8deg);
  background: var(--good); -webkit-mask: var(--i-done) center / contain no-repeat; mask: var(--i-done) center / contain no-repeat; }
.rv-stamp.maru-2 { -webkit-mask-image: var(--i-done-2); mask-image: var(--i-done-2); }
@media (prefers-reduced-motion: no-preference) { .rv-stamp { animation: rv-stamp .28s cubic-bezier(.2, 1.4, .4, 1) both; } }
@keyframes rv-stamp { from { transform: rotate(-30deg) scale(1.6); opacity: 0; } }

/* what shows after answering */
.rv-more { margin-top: var(--s-4); padding: var(--s-4) var(--s-5); border: 1px solid var(--line); border-radius: var(--r-2); background: var(--surface); display: grid; gap: var(--s-3); }
.rv-more p { margin: 0; }
.rv-more .well { margin: 0; }
.rv-more-row { display: flex; align-items: center; gap: var(--s-4); min-width: 0; }
.rv-kana { font-family: var(--font-hand); font-size: 56px; line-height: 1.1; flex: none; }
.rv-big-en { font-size: var(--fs-20); font-weight: 700; line-height: 1.35; overflow-wrap: anywhere; }
.rv-word { font-size: var(--fs-30); line-height: var(--lh-ruby-big); }
.rv-pitch { max-width: 100%; overflow-x: auto; }
.rv-pitch svg { display: block; }
.rv-ex.ex { padding: var(--s-3) 0 0; border-top: 1px solid var(--line); }
.rv-tells { margin: var(--s-2) 0 0; padding-left: 1.2em; }
.rv-tells li + li { margin-top: var(--s-1); }

/* the foot: Next (one wide button, 52 px), or the four grades of a card turned over */
.rv-foot .rv-wide, .rv-foot .rv-over, .rv-foot .rv-ask-grade { grid-column: 1 / -1; }
.rv-foot .rv-over { justify-self: center; min-height: var(--tap); }
.rv-foot .rv-wide { min-height: 52px; }
.rv-foot.rv-self { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.rv-ask-grade { margin: 0; text-align: center; color: var(--ink-3); font-size: var(--fs-14); }
@media (max-width: 520px) { .rv-foot.rv-self { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---- the feedback sheet (docs/mobile-plan.md 1.7): after an answer, the verdict, the sentence with the answer in
   it, the lesson, Ask Tomo why on a miss, and Next, in one place. Study (.study-sheet), the quiz and drills use it
   too (.answer-sheet). On a phone it holds to the foot of the screen (above the home indicator in a session, above
   the keyboard if one is up), so the verdict and Next are in sight together; what it covers scrolls clear of it. */
.rv-sheet, .study-sheet { min-width: 0; }
.rv-sheet > .grades, .study-sheet > .grades { margin-top: var(--s-3); }
.answer-sheet { display: grid; gap: var(--s-3); margin-top: var(--s-4); padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-3); background: var(--surface); text-align: left; }
.answer-sheet > :empty { display: none; }
.answer-sheet .verdict, .answer-sheet > .grades, .answer-sheet .rv-due, .answer-sheet .row { margin: 0; }
.answer-sheet .rv-due { margin-top: calc(-1 * var(--s-2)); }
.rv-sheet-more { display: grid; gap: var(--s-2); min-width: 0; }
.rv-sheet-note { margin: 0; }
/* the lesson and Ask Tomo why share one row; a long pattern's name gives way (ellipsis), never the row */
.rv-links.row { flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: var(--s-3); margin: 0; }
.rv-links .go { flex: 0 1 auto; min-width: 0; }
.rv-linkwords { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rv-links .link { flex: none; min-height: var(--tap); }
.answer-sheet .ask-why { justify-self: start; min-height: var(--tap); }
/* the buttons that go on, the full width: Next alone, or I was right and Next side by side */
.answer-sheet .study-next { display: grid; grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--s-2); }
.answer-sheet .study-next > button { min-height: 52px; }
/* the quiz's sheet is the foot of its card: a hairline over it, no card in a card */
.flash > .answer-sheet { margin-top: var(--s-4); padding: var(--s-3) 0 0; border: 0; border-top: 1px solid var(--line); border-radius: 0; background: var(--surface); }
.flash > #after.answer-sheet .verdict { margin-top: 0; }
@media (max-width: 720px), (max-height: 500px) {
  /* the grades are the sheet's own row, never a sticky bar of their own (app.css makes .study .grades one) */
  .study :is(.rv-sheet, .study-sheet, .answer-sheet) > .grades { position: static; margin-top: 0; padding: 0; background: none; }
}
/* A phone on its side: the sheet holds to the foot of the screen (above the keyboard if one is up). An upright phone
   docks it instead (the dock, below). */
@media (max-height: 500px) {
  .study .rv-sheet:has(> .rv-foot:not([hidden])), .study .study-sheet:has(> .grades), .study .answer-sheet {
    position: sticky; z-index: 5; bottom: max(calc(var(--tab-h) + env(safe-area-inset-bottom)), var(--kb, 0px)); }
  .study .rv-sheet:not(.answer-sheet):has(> .rv-foot:not([hidden])), .study .study-sheet:not(.answer-sheet) { margin-top: var(--s-2); padding: var(--s-2) 0; background: var(--bg); }
  .study .answer-sheet { margin-top: var(--s-3); padding: var(--s-3) var(--s-4) var(--s-4); box-shadow: var(--shadow-lg); }
  .study .flash > .answer-sheet { padding: var(--s-3) 0; box-shadow: none; }
  /* what is focused or brought into view above the sheet is never left under it */
  html:has(#main .study .answer-sheet) { scroll-padding-bottom: calc(var(--tab-h) + env(safe-area-inset-bottom) + min(46vh, 340px)); }
}

/* ---- the dock (docs/mobile-plan.md 1.7): on an upright phone a session's one main action sits at the foot of the
   screen, as a running mock's Previous and Next do: Turn it over, Show the answer, Start, I know it and Now write it,
   JLPT practice's Check, and after an answer the feedback sheet with Next. The session's frame (.dock-frame) runs from
   under the bar to the screen's foot, its card (.dock-grow) takes the room that is left (a quiz's card keeps its
   choices and Next at its own foot), and the dock (.dock) is one full-width bar there, above the home indicator, or
   the tab bar on a page that has one. While a box waits for typing the card does not grow, so the box stays under
   the question when the keyboard comes up. A phone on its side and a computer keep these in the page's flow. ---- */
@media (max-width: 720px) and (min-height: 501px) {
  :root { --dock-at: 0px; --dock-pad: env(safe-area-inset-bottom); }
  :root:has(#tabbar:not([hidden])) { --dock-at: calc(var(--tab-h) + env(safe-area-inset-bottom)); --dock-pad: 0px; }
  #main:has(> .dock-frame) { --frame-foot: calc(var(--dock-at) + var(--dock-pad) + var(--s-4)); padding-bottom: var(--frame-foot); }
  #main:has(> .dock-frame .dock) { --frame-foot: var(--dock-at); }
  .dock-frame { min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - var(--s-4) - var(--frame-foot)); }
  .dock-frame:has(.dock, .dock-grow):not(:has(.typeans)) { display: flex; flex-direction: column; }
  .dock-frame:has(.dock, .dock-grow):not(:has(.typeans)) .dock-fill { flex: 1 0 auto; display: flex; flex-direction: column; min-width: 0; }
  .dock-frame:has(.dock, .dock-grow):not(:has(.typeans)) .dock-grow { flex: 1 0 auto; }
  .dock-frame .dock { order: 9; position: sticky; z-index: 5; bottom: var(--dock-at);
    margin: auto calc(-1 * var(--gut-r)) 0 calc(-1 * var(--gut-l)); padding: var(--s-3) var(--gut-r) calc(var(--s-3) + var(--dock-pad)) var(--gut-l);
    border: 0; border-top: 1px solid var(--line); border-radius: 0; background: var(--surface); box-shadow: none; }
  .dock-frame .dock.grades { gap: var(--s-2); }
  .dock-frame .dock :is(.primary, .quiet, .again, .got) { min-height: 52px; }
  /* what is focused or brought into view is never left under the dock */
  html:has(#main .dock-frame .dock) { scroll-padding-bottom: calc(var(--dock-at) + 100px); }
  html:has(#main .dock-frame .dock.answer-sheet) { scroll-padding-bottom: calc(var(--dock-at) + min(46vh, 340px)); }
  /* a typed question's card keeps its own height after the answer too (the box was under it), so the sentence stays
     where the learner just read it and only the verdict comes under it */
  .dock-frame .rv-card.rv-still.dock-grow { flex: 0 0 auto; }
  /* a flashcard's short front (six characters or fewer) is set large: the one thing on the card; four or fewer at 64
     to 72 px. On the flash card (study.js) the front and what is under it sit about 40% of the way down the card
     (spacers of 2 and 3), not in its middle. */
  .study .flash .front.es.short { font-size: clamp(40px, 13vw, 64px); }
  .study .flash .front.es.short.tiny { font-size: clamp(56px, 18vw, 72px); line-height: 1.25; }
  .study .flash.fc-card.dock-grow { justify-content: flex-start; }
  .study .flash.fc-card.dock-grow::before { content: ""; flex: 2 1 0; }
  .study .flash.fc-card.dock-grow::after { content: ""; flex: 3 1 0; }
  /* a quiz's card: the question in the middle of what is left, the choices and then Next at the card's foot */
  .study.quiz .flash.dock-grow { justify-content: flex-start; }
  .study.quiz .flash.dock-grow > .front { margin-block: auto; padding-block: var(--s-4); }
}
/* a main action that waits (Check before an answer is chosen) reads as waiting, not broken: the quiet fill and words
   of the disabled token, at full strength, at every width */
:is(.dock, .jl-acts, .study-next) > .primary:disabled { opacity: 1; background: var(--surface-2); border-color: var(--line); color: var(--ink-3); }
/* a drill: no empty card around a short prompt; a fill-in's English under it; the hints one at a time; the sentence
   set to the left, as a review's is */
.flash.drill-card { min-height: 160px; align-items: stretch; text-align: left; }
.drill-card > .kind { align-self: flex-start; }
.drill-card .front { font-size: clamp(22px, 4vw, 30px); text-align: left; align-self: stretch; }
.drill-en { margin: var(--s-2) 0 0; color: var(--ink-2); font-size: var(--fs-18); text-align: left; }
.drill-hints { margin: var(--s-3) 0 0; align-self: stretch; text-align: left; }
.drill-hints p { margin: 0; }
.drill-tools { gap: var(--s-2); }
/* Undo and ⚙ beside the count (lent to the bar on an upright phone, with their ids) */
.study-tools { display: inline-flex; align-items: center; gap: var(--s-1); flex: none; }
.study-top .study-set svg { width: 20px; height: 20px; }
/* How cards ask, on its sheet */
.study-how { display: grid; gap: var(--s-3); justify-items: start; }
.study-how p { margin: 0; }
.study-how .seg { width: 100%; }
.study-how .seg button { flex: 1 1 0; min-height: 48px; }

/* ★: the sentence with its places, and the parts to tap into them */
.rv-orderline { text-align: left; }
.rv-slot { display: inline-flex; align-items: center; justify-content: center; position: relative; min-width: 3.2em; min-height: var(--tap); margin: 2px 3px; padding: 0 var(--s-2);
  border: 0; border-bottom: 3px solid var(--accent); border-radius: var(--r-1) var(--r-1) 0 0; background: var(--surface-2); color: var(--ink); font: inherit; line-height: var(--lh-ruby); vertical-align: middle; }
.rv-slot.star { border-bottom-width: 5px; border-bottom-color: var(--accent-text); color: var(--ink-3); }
.rv-slot.full { background: var(--accent-soft); color: var(--ink); }
.rv-starmark { position: absolute; top: -.2em; right: -.1em; font-size: var(--fs-14); color: var(--accent-text); }
.rv-parts { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
.rv-part { display: inline-flex; align-items: center; gap: var(--s-2); min-height: 52px; padding: 0 var(--s-4); font-size: var(--fs-20); line-height: var(--lh-ruby); }
.rv-part.used { opacity: .35; }
.rv-part kbd { font: 700 var(--fs-14) var(--mono); padding: 2px 6px; border-radius: var(--r-1); background: color-mix(in srgb, currentColor 12%, transparent); }

/* writing in a review or while meeting a kana or kanji */
.rv-padcol { width: min(100%, 360px); margin: var(--s-3) auto 0; display: grid; gap: var(--s-2); }

/* ---- the end of a round, and the start of meeting new items ---- */
.rv-end { display: grid; justify-items: center; gap: var(--s-2); }
.rv-end .score { display: flex; align-items: baseline; gap: var(--s-2); }
.rv-end .score .of { font-size: var(--fs-24); color: var(--ink-3); }
.rv-end h1, .rv-end h2 { margin: var(--s-2) 0 0; }
.rv-end .list { justify-self: stretch; text-align: left; margin: var(--s-2) 0; }
.rv-end .list .main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s-3); }
.rv-end-acts { justify-content: center; margin-top: var(--s-3); }
.rv-next-due { color: var(--ink-2); margin: var(--s-2) 0 0; }
.rv-hello { justify-self: stretch; text-align: left; margin-bottom: var(--s-3); }
.rv-hello:empty { display: none; }
.rv-words { justify-self: stretch; text-align: left; margin-top: var(--s-3); }
.rv-intro { display: grid; gap: var(--s-4); }
.rv-intro h2 { margin: 0; }
.rv-intro .well { margin: 0; }
.rv-intro-tiles { justify-content: center; }
.rv-intro .rv-intro-tiles { justify-content: flex-start; }
.rv-tile { display: inline-grid; justify-items: center; gap: 2px; }
/* the lesson's kana and kanji as plain large glyphs (no boxes that look like buttons), its words as plain words */
.rv-intro-tiles { gap: var(--s-2) var(--s-4); }
.rv-intro-tiles .kt { width: auto; height: auto; min-width: 0; border: 0; border-radius: 0; background: none; }
.rv-tile.glyph .kt { font-family: var(--font-hand); font-size: 40px; line-height: 1.2; }
.rv-kt-word { font-size: var(--fs-20); font-weight: 700; line-height: 1.5; }
.rv-tile-mark { min-height: 22px; font-size: var(--fs-18); }

/* Before the first item, and while meeting one, the buttons that go on (Start; I know it and Now write it) are the
   dock on an upright phone (above). */
.rv-startbar { margin-top: var(--s-4); }

/* ---- meeting one new item ---- */
.rv-meet .card-head h2 { overflow-wrap: anywhere; }
.rv-meet .card-body { display: grid; gap: var(--s-4); }
.mt-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-5); align-items: start; }
.mt-glyphs { display: grid; gap: var(--s-3); justify-items: center; }
.mt-pic { width: 132px; aspect-ratio: 1; object-fit: cover; border-radius: var(--r-2); border: 1px solid var(--line); background: var(--surface-2); }
/* in dark the cream picture sits in a --surface-2 tile, framed and dimmed a little, so it never glares from the dark
   page */
@media (prefers-color-scheme: dark) { :root:not([data-theme=light]) .mt-pic { box-sizing: border-box; padding: 6px; background: var(--surface-2); border-color: var(--line-strong); filter: brightness(.85); } }
:root[data-theme=dark] .mt-pic { box-sizing: border-box; padding: 6px; background: var(--surface-2); border-color: var(--line-strong); filter: brightness(.85); }
/* a kana's card has no head on screen (its name is for screen readers): its body keeps the card's own top padding,
   so the stroke tile never touches the card's border */
.rv-meet > .card-head.sr + .card-body { padding-top: var(--s-5); }
/* the kana's tile and its picture: the same size (one over the other on a computer; side by side on a phone, their
   tops on one line) */
.mt-kana > .mt-pic { box-sizing: border-box; width: 168px; }
/* a hook to remember it by: plain words under a small heading, never a box */
.mt-tip { min-width: 0; }
.mt-tip-h { margin: 0 0 var(--s-1); font-size: var(--fs-16); color: var(--ink-2); }
.mt-tip p { margin: 0; }
.mt-info, .mt-word, .mt-write { display: grid; gap: var(--s-3); min-width: 0; }
.mt-info p, .mt-word p, .mt-info .well, .mt-word .kmeaning, .mt-info .kmeaning { margin: 0; }
.mt-info .kwords, .mt-word .kwords { margin-top: 0; }
.rv-meet .kword { align-items: center; }
/* a kana's words as full-width rows: the word, its English, and its sound at the row's end */
.rv-meet .mt-info .kwords { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; padding-top: 0; border-top: 0; }
.rv-meet .mt-info .kword { display: flex; width: 100%; min-height: 52px; gap: var(--s-3); padding: var(--s-1) 0; border-radius: 0; background: none; border-top: 1px solid var(--line); font-size: var(--fs-16); }
.rv-meet .mt-info .kword:last-child { border-bottom: 1px solid var(--line); }
.rv-meet .mt-info .kword > .btn-play { margin-left: auto; }
.mt-sound { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.mt-romaji { font-size: var(--fs-40); font-weight: 700; line-height: 1.1; }
/* a kana met: the kana on its tile of 方眼 paper is the biggest thing on the card; its sound small beside Play */
.mt-hero { width: 168px; }
.mt-hero .model { font-size: 120px; }
.mt-romaji.small-romaji { font-size: var(--fs-24); color: var(--ink-2); }
.mt-looks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.mt-info details.mt-fold { margin-top: 0; }
.mt-fold .mt-looks { margin: var(--s-1) 0 var(--s-2); }
.mt-strokes { margin: 0; }
.mt-looks li { display: flex; align-items: center; gap: var(--s-3); color: var(--ink-2); }
.mt-look { flex: none; display: inline-grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--line-strong); border-radius: var(--r-1); font-family: var(--font-hand); font-size: 30px; color: var(--ink); }
.mt-word .ja-xl { margin: 0; }
.mt-word .ex { padding: var(--s-3) 0 0; border-top: 1px solid var(--line); }
.mt-form { color: var(--ink-2); }
.mt-form .eyebrow { display: block; }
@media (max-width: 720px) {
  .mt-grid { grid-template-columns: minmax(0, 1fr); }
  .mt-glyphs { grid-template-columns: auto auto; justify-content: start; align-items: center; }
  .mt-pic { width: 112px; }
  .mt-kana { justify-content: center; }
  .rv-meet > .card-head.sr + .card-body { padding-top: var(--s-4); }
  .mt-hero { width: min(168px, 42vw); }
  .mt-hero .model { font-size: min(120px, 30vw); }
  .mt-kana .mt-pic { width: min(112px, 30vw); }
  .mt-kana:has(> .mt-pic:not([hidden])) { grid-template-columns: repeat(2, minmax(0, 168px)); align-items: start; justify-content: center; }
  .mt-kana:has(> .mt-pic:not([hidden])) > :is(.mt-hero, .mt-pic) { width: 100%; }
  .rv-stamp { width: 40px; height: 40px; right: 52px; top: var(--s-3); }
  .rv-sentence, .flash .front .rv-sentence { font-size: var(--fs-22); }
  .rv-more { padding: var(--s-3) var(--s-4); }
}

/* ---- grammar: a level's points ---- */
/* the title with the level chip beside it; the one main action, and the other as a link centred under it on a phone
   (as Kanji and Words have them) */
.gp-titlerow { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
.gp-titlerow h1 { margin: 0; }
.gp-level .pagehead p { margin: var(--s-1) 0 0; }
.gp-go { align-items: center; gap: var(--s-2) var(--s-4); }
.gp-golink { display: inline-flex; align-items: center; min-height: var(--tap); font-weight: 700; }
/* due: a small ōdo dot and the word, no chip */
.gp-due { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-14); font-weight: 700; color: var(--ink-2); }
.gp-due::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--warn-text); }
.gp-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-3); }
.gp-search { flex: 1 1 260px; max-width: 440px; }
.gp-known { display: inline-grid; place-items: center; width: 28px; height: 28px; font-size: var(--fs-18); }
.gp-dot { display: inline-block; width: .6em; height: .6em; border-radius: 50%; background: currentColor; margin-right: 4px; vertical-align: .05em; }
.chip .maru, .chip .sankaku, .chip .gp-dot { margin-right: 6px; }
/* the sets of eight: flat fold rows (as on Words), hairlines between them; the one being worked on open, the others
   one row each with a preview of their points */
.gp-sets { display: grid; grid-template-columns: minmax(0, 1fr); border-top: 1px solid var(--line); }
.gp-set { padding: 0; border-bottom: 1px solid var(--line); }
.gp-sethead { display: flex; align-items: center; gap: var(--s-3); min-height: 60px; padding: var(--s-2) var(--s-2); cursor: pointer; list-style: none; }
.gp-setwords { flex: 1; display: grid; gap: 2px; min-width: 0; }
.gp-setpeek { font-size: var(--fs-16); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: var(--lh-ja); }
.gp-sethead::-webkit-details-marker { display: none; }
.gp-sethead::after { content: ""; flex: none; width: 18px; height: 18px; background: var(--ink-3); -webkit-mask: var(--i-chev) center / 18px no-repeat; mask: var(--i-chev) center / 18px no-repeat; transition: transform .15s; }
.gp-set[open] > .gp-sethead::after { transform: rotate(180deg); }
.gp-setname { font-size: var(--fs-18); font-weight: 700; }
.gp-setmet { font-size: var(--fs-14); color: var(--ink-3); white-space: nowrap; }
.gp-set[open] > .gp-sethead { border-bottom: 1px solid var(--line); }
.gp-list { list-style: none; margin: 0; padding: 0; }
.gp-list > li + li { border-top: 1px solid var(--line); }
.gp-row { display: grid; grid-template-columns: 3ch minmax(7em, 16em) minmax(0, 1fr) auto; align-items: center; gap: var(--s-2) var(--s-4); min-height: 60px;
  padding: var(--s-2) var(--s-2); color: var(--ink); text-decoration: none; }
@media (hover: hover) { .gp-row:hover { background: var(--surface-2); } }
.gp-n { color: var(--ink-3); font-size: var(--fs-14); }
.gp-key { font-size: var(--fs-20); font-weight: 700; line-height: var(--lh-ruby); overflow-wrap: anywhere; }
.gp-mean { color: var(--ink-2); min-width: 0; overflow-wrap: anywhere; }
.gp-state { justify-self: end; white-space: nowrap; }
.gp-none { text-align: center; padding: var(--s-5); }
@media (max-width: 720px) {
  /* the title and the level chip share a line; a pattern and its English sit close */
  .gp-titlerow { flex-wrap: nowrap; }
  .gp-titlerow h1 { min-width: 0; }
  .gp-go { width: 100%; justify-content: center; }
  .gp-go > .primary { flex: 1 1 100%; }
  .gp-sethead { padding: var(--s-2) 0; }
  .gp-row { grid-template-columns: 3ch minmax(0, 1fr) auto; grid-template-areas: "n key state" "n mean mean"; gap: 0 var(--s-3); min-height: 56px; padding: var(--s-2) 0; }
  .gp-key:not(:has(ruby)) { line-height: 1.5; }
  .gp-n { grid-area: n; align-self: start; padding-top: 4px; }
  .gp-key { grid-area: key; }
  .gp-mean { grid-area: mean; }
  .gp-state { grid-area: state; }
}

/* ---- grammar: one point's lesson ---- */
.gp-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--s-4); margin-bottom: var(--s-5); }
.gp-head .grow { flex: 1 1 320px; min-width: 0; }
.gp-head .eyebrow { display: flex; align-items: center; gap: var(--s-2); margin: 0; }
.gp-head .title-ja { overflow-wrap: anywhere; }
.gp-side { display: grid; gap: var(--s-3); justify-items: end; }
.gp-state-box .row { justify-content: flex-end; }
.gp-state-line { margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); justify-content: flex-end; color: var(--ink-2); }
/* a point's sections: one line each ("The pattern かたち"), no numbers */
.gp-lesson .sec-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 var(--s-2); align-self: start; }
.gp-lesson .sec-head h2 { margin: 0; }
.gp-lesson .sec-head .sec-ja { margin: 0; }
.gp-attach { margin: var(--s-4) 0 0; padding-left: 1.2em; }
.gp-attach li { line-height: var(--lh-ruby); }
/* The pattern's lines and the register are English with Japanese in them: a line with no reading in it is set as
   English (--lh-body), never on the ruby band (it would look double-spaced); only a line that carries furigana gets
   the band. */
.gp-attach li:not(:has(ruby)) { line-height: var(--lh-body); }
.gp-attach li + li { margin-top: var(--s-1); }
.gp-subhead { margin: var(--s-5) 0 0; font-size: var(--fs-16); font-weight: 700; color: var(--ink); line-height: 1.4; }
.gp-register { margin: var(--s-1) 0 0; color: var(--ink-2); line-height: var(--lh-ruby); }
.gp-register:not(:has(ruby)) { line-height: var(--lh-body); }
.ftile .gp-en { font-size: var(--fs-20); font-weight: 700; line-height: 1.3; }
.gp-note { margin: var(--s-1) 0 0; }
/* an example line with no readings over it keeps a normal Japanese line (--lh-ja), not the ruby band */
.gp-lesson :is(.ex .ja-lg, .gp-try .ja-lg, .gp-cline):not(:has(ruby)) { line-height: var(--lh-ja); }
/* The one callout (the trap, how friends say it): a soft tint, no border, never a box in a box. */
.gp-lesson .gp-callout { margin: 0; padding: var(--s-4) var(--s-5); border: 0; border-radius: var(--r-2); background: var(--accent-soft); color: var(--ink); min-width: 0; }
.gp-callout h3 { margin: 0; font-size: var(--fs-18); line-height: 1.4; }
.gp-callout p { margin: var(--s-2) 0 0; color: var(--ink-2); }
.gp-callout-sub { font-size: var(--fs-14); }
.gp-casual { margin-top: var(--s-5); }
.gp-clines { list-style: none; margin: var(--s-3) 0 0; padding: 0; display: grid; gap: var(--s-3); }
.gp-callout .gp-cline { margin: 0; font-size: var(--fs-20); line-height: var(--lh-ruby); color: var(--ink); }
.gp-callout .gp-cline-en { margin: 0; font-size: var(--fs-14); }
/* What can wait folds: In plain English, the culture note, Related points (one 52 px row each, a chevron) */
.gp-lesson .gp-fold > summary { display: flex; align-items: baseline; flex-wrap: nowrap; gap: 0 var(--s-2); min-height: 52px; padding-block: var(--s-2); cursor: pointer; list-style: none; border-radius: var(--r-1); }
.gp-fold > summary::-webkit-details-marker { display: none; }
.gp-fold > summary h2 { min-width: 0; }
.gp-fold > summary::after { content: ""; flex: none; align-self: center; width: 20px; height: 20px; margin-left: auto; background: var(--ink-3);
  -webkit-mask: var(--i-chev) center / 20px no-repeat; mask: var(--i-chev) center / 20px no-repeat; transition: transform .15s; }
.gp-fold[open] > summary::after { transform: rotate(180deg); }
.gp-fold-n { margin-left: auto; font-size: var(--fs-14); color: var(--ink-3); }
.gp-fold > summary:has(.gp-fold-n)::after { margin-left: var(--s-2); }
.gp-fold-body { padding: var(--s-1) 0 var(--s-4); }
.gp-fold-body > p:first-child { margin-top: 0; }
.gp-fold + .gp-fold { border-top: 1px solid var(--line); }
.gp-lesson .sec.gp-folds { display: block; padding-block: var(--s-2); }
.gp-lesson .sec.gp-sec-mean { padding-block: var(--s-2); }
.gp-lesson .sec.gp-sec-mean:has(> .trap) { padding-bottom: var(--s-6); }
.gp-sec-mean > .gp-fold { grid-column: 1 / -1; min-width: 0; }
@media (min-width: 901px) {
  /* on a computer a fold's words and the trap line up with the other sections' bodies (the 4th of 12 columns) */
  .gp-sec-mean > .trap { grid-column: 4 / -1; max-width: var(--measure); }
  .gp-fold-body { margin-left: calc((100% - 11 * var(--grid-gap)) * 3 / 12 + 3 * var(--grid-gap)); }
}
/* Practise this (4): on a phone, held at the foot of the screen until Your turn is in view (grammar.js) */
.gp-practise-bar { display: none; }
.gp-related { max-width: 640px; }
.gp-related .gp-rel-key { font-size: var(--fs-20); line-height: 1.4; }
.gp-also { margin: var(--s-2) 0 0; line-height: var(--lh-ruby); }
/* any Japanese line on the lesson with no reading over it keeps Japanese's own line height, never the ruby band */
.gp-lesson :is(p, li):lang(ja):not(:has(ruby)), .gp-also:not(:has(ruby)) { line-height: var(--lh-ja); }
.gp-lesson .gp-attach li:lang(ja):not(:has(ruby)), .gp-lesson .gp-register:lang(ja):not(:has(ruby)) { line-height: var(--lh-body); }
.gp-practice { list-style: none; margin: 0 0 var(--s-4); padding: 0; display: grid; gap: var(--s-5); }
.gp-try { display: grid; gap: var(--s-2); padding-top: var(--s-5); border-top: 1px solid var(--line); }
.gp-try:first-child { padding-top: 0; border-top: 0; }
.gp-try .ja-lg, .gp-try .en { margin: 0; }
.gp-try .typeans { margin-top: var(--s-1); max-width: 520px; }
.gp-try-tools:empty { display: none; }
.gp-verdict .verdict { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }
.gp-verdict .btn-play { margin-left: auto; }
.gp-pn { margin-top: var(--s-5); }
.gp-count { margin: 0 0 var(--s-2); }
.gp-count:empty { display: none; }
.gp-practice-go { gap: var(--s-2) var(--s-4); }
.gp-practice-go:not(:has(> :not([hidden]))) { display: none; }
/* Other sentences and Grammar reviews: two full rows at Your turn's foot (ul.list.links) */
.gp-morerows { margin: var(--s-3) 0 0; max-width: 640px; border-top: 1px solid var(--line); }
.gp-morerows > li + li { border-top: 1px solid var(--line); }
/* Aa: the page's display choices (furigana) on a sheet; lent to the bar on an upright phone */
.aa-btn { font: 700 var(--fs-18)/1 var(--font-sans); letter-spacing: -.02em; color: var(--ink-2); }
.aa-sheet { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-3); }
.aa-sheet p { margin: 0; }
.aa-sheet .seg { width: 100%; }
.aa-sheet .seg button { flex: 1 1 0; min-height: 48px; }
.aa-sheet .switch { min-height: var(--tap); }
@media (max-width: 720px) {
  .gp-side, .gp-state-box .row, .gp-state-line { justify-items: start; justify-content: flex-start; }
  /* a point on a phone: no card around the lesson, flat sections with space between them */
  .gp-lesson .sheet { border: 0; border-radius: 0; background: none; padding: 0; }
  .gp-lesson .sec { padding-block: var(--s-5); }
  .gp-lesson .sec.gp-folds, .gp-lesson .sec.gp-sec-mean { padding-block: var(--s-2); }
  .gp-lesson .sec.gp-sec-mean:has(> .trap) { padding-bottom: var(--s-5); }
  .gp-lesson .gp-callout { padding: var(--s-4); }
  /* the sessions' bottom bar: a solid band of the page's own background, a hairline over it, from the edges down to
     the tab bar, so no line of an example shows through under it */
  .gp-practise-bar { display: block; position: fixed; z-index: 20; left: 0; right: 0; bottom: calc(var(--tab-h) + env(safe-area-inset-bottom)); margin: 0;
    padding: var(--s-2) max(var(--gutter), env(safe-area-inset-right)) var(--s-2) max(var(--gutter), env(safe-area-inset-left));
    background: var(--bg); border-top: 1px solid var(--line); transition: opacity .2s, transform .2s, visibility .2s; }
  .gp-practise-bar .gp-practise { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 52px; margin: 0; }
  .gp-practise-bar.away { opacity: 0; visibility: hidden; transform: translateY(var(--s-3)); }
  .gp-lesson:has(> .gp-practise-bar) { padding-bottom: calc(52px + var(--s-4) + var(--s-5)); }
  /* Practise this is the page's one call: Your turn (with its own Check) waits folded away until it is pressed */
  .gp-lesson:has(> .gp-practise-bar) .gp-turn:not(.open) { display: none; }
}
@media (prefers-reduced-motion: reduce) { .gp-practise-bar { transition: none; } }
.bar-tool > .aa-btn { font-size: var(--fs-18); }
