/* ==========================================================================
   Sentence tokens (.st-*) — an example sentence read as WORDS
   --------------------------------------------------------------------------
   Two surfaces, both cut from material the app already owns:

     THE LINE — the sentence keeps the 例文 dress exactly (.wp-ex-jp still sets
     the type). Tokens add NO resting decoration: a beginner's sentence would
     light up almost end to end, and a mark that fires everywhere says nothing
     (owner, 2026-08-02). Only two words ever carry ink — the one the page is
     about, and the one under the pointer.

     THE GLANCE — the same washi slip as the kanji peek, down to the pigment
     formula and the 3px PRINT corner, because it is the same gesture one tier
     over, and like that peek it holds no door: the app's ladder is
     hover = remind me · click = the panel, so the TOKEN's click opens the
     word's 図録 panel and the slip only ever says the reading and the meaning.

   KANA MODE gets word spacing — 分かち書き. Applied as margin BETWEEN tokens,
   never as literal spaces in the text, so a copied sentence stays the sentence
   and no gap opens before the full stop.
   ========================================================================== */

/* ── the line ────────────────────────────────────────────────────────────── */

.st-tk {
  border-radius: 2px;
  /* the reading rides above the line; a background must not crowd it */
  padding: 0 0.02em;
  transition: background-color 140ms var(--ease-page, ease),
              box-shadow 140ms var(--ease-page, ease);
}
.st-tk:not(.st-tk--inert) { cursor: pointer; }

/* the word the page is ABOUT — the reason this sentence is on the page.
   A hairline seat under the word, never a highlight over it: the sentence
   stays a sentence and the ruby above stays legible. */
.st-tk--target {
  box-shadow: inset 0 -2px 0 -1px rgba(61, 90, 128, 0.42);
}

/* under the pointer / open. Warm paper-shadow rather than a selection blue —
   the word is being LIFTED off the page, not selected in a text field.

   ⛔ :hover is GATED on hover capability, on exactly the query the JS uses
   (`HOVER_OK`, js/sentence-tokens.js). Ungated, CSS and JS disagreed about what
   a touch device is: iPad — a PRIMARY device on the desktop product — leaves
   :hover latched on the last thing tapped, so a word the learner had already
   closed went on wearing the OPEN tint. `.is-open` is the honest signal there
   and stays ungated: it is set and cleared by the glance itself. */
.st-tk.is-open {
  background-color: rgba(201, 169, 110, 0.16);
}
@media (hover: hover) and (pointer: fine) {
  .st-tk:not(.st-tk--inert):hover {
    background-color: rgba(201, 169, 110, 0.16);
  }
}
.st-tk.is-open { box-shadow: inset 0 -2px 0 -1px rgba(201, 169, 110, 0.85); }

.st-tk:focus-visible {
  outline: 2px solid var(--color-indigo, #3D5A80);
  outline-offset: 1px;
}

/* a kanji door inside a token keeps travelling — the word owns the glance,
   the character still owns its page. Nothing to restyle; just never let the
   token's own hover erase the door's affordance. */
.st-tk .wp-kt { border-radius: 2px; }

/* (the 分かち書き spaced-kana rule left with the kana display mode,
   2026-08-20 — no renderer emits .st-line--spaced any more) */

/* ── the invitation (retired for good, 12 October 2026) ──────────────────── */

/* inviteHTML prints nothing now (js inviteOpen: the design is never
   captioned, and iPad, its reason, is deferred). The rule stays, inert, so a
   revival is one line in the js. When it spoke it was said once per BLOCK,
   never per word, in the section head, each surface in its own dress; all
   three shared only this: the line never breaks in two. */
.st-invite { white-space: nowrap; }

/* ── the glance ──────────────────────────────────────────────────────────── */

/* A SLIP OF WASHI laid over the page — the word lifted out of the sentence for
   a moment. RE-CUT 2026-10-12 (owner: "not aesthetic, not sleek"). What was
   wrong, read off the frames rather than the comments:
     · the paper was mixed to the PAGE'S OWN VALUE (88% #FAF7EF + 12% clay
       lands within a hair of the stone it lies on), so the only thing that
       separated slip from page was a 1px grey ring — the OS-tooltip tell by
       another route, and the one thing the old comment said it had avoided;
     · the headword wore a 10px ruby, SMALLER than the sentence's own 13px
       reading two lines below it — a reminder harder to read than the thing
       it reminded of;
     · a 26px rule-stub floated between word and meaning, too short to be a
       rule and too long to be a mark;
     · 16/20px padding round three short lines left the card mostly air, and
       three lines of the same grey left nothing crisp.
   What stands now:
     · VALUE, NOT A STROKE — the sheet is lighter than the stone (#FFFDF8
       soaked 6% in the subject's own pigment) and the ring is gone: a lifted
       sheet is read by its lightness and the shadow under it, never by an
       outline. The shadow is the constellation peek's — the one slip the
       owner calls beautiful — thrown a little left, so the sheet has a side;
     · the READING IS A LINE — kana and romaji on one quiet row under the
       word in every mode (a kana word prints romaji alone), the peek's own
       grammar. The ruby went with the mode-dependence: the glance exists to
       answer "how is this read", so it answers in a readable size, and the
       card is the same shape under every setting;
     · NO RULE — the meaning sits in ink under a quiet reading; two ranks of
       ink separate themselves;
     · it READS FROM THE LEFT, as a dictionary slip does, and js place()
       stands the card's word directly over the sentence's word (a column
       gets it beside, level with the token's first character).
   Everything here is the house's own token — no new colour enters. */
.st-glance {
  position: fixed;
  z-index: 9998;              /* the peek's tier: under the 9999 play popover */
  display: none;              /* js open() lays the sheet down, close() lifts it after the fade */
  max-width: 256px;           /* a gloss wraps at about five words */
  min-width: 0;               /* the sheet hugs its lines; は wa is a small slip */
  padding: 12px 16px 13px;

  --slip-pigment: color-mix(in srgb, var(--slip-tone, #b0a090) 62%, #b0a090);
  background-color: color-mix(in srgb, var(--slip-paper, #FFFDF8) 94%, var(--slip-pigment) 6%);
  border: 0;
  border-radius: 3px;         /* a PRINT corner, not a 10px UI radius */
  /* thickness, never an outline: a lit top lip, a contact line under the
     sheet, and the lifted shadow thrown a little to the left. The stock's
     own (css/tokens.css), and since round 4 the kanji peek's too */
  box-shadow: var(--slip-lip), var(--slip-contact), var(--slip-lift);

  color: var(--slip-quiet, #6E6860);
  font: 400 12px/1.5 var(--font-ui);
  text-align: left;
  opacity: 0;
  transition: opacity var(--slip-in, 190ms) var(--ease-page, ease);
}
/* LAID DOWN, NOT POPPED (round 4, 14 October 2026). This rule used to flip
   display and opacity together, so the sheet popped in and cut out. Now js
   open() shows the sheet at 0 and measures it there, .is-open lifts it on
   the peek's tempo while the air shadow settles, and close() lets it fade
   before it goes. A sheet on its way out never takes the pointer from the
   line beneath it. */
.st-glance.is-open { opacity: 1; }
.st-glance:not(.is-open) { pointer-events: none; }

/* the grain, MULTIPLIED into the fibres rather than laid over them */
.st-glance::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background-image: var(--slip-grain);
  opacity: 0.06; mix-blend-mode: multiply; pointer-events: none;
}
/* THE LANDING — the house signature. The slip arrives with its in-the-air
   shadow lit and that shadow fades as it comes to rest. No transform: paper
   is not slid across a surface, it is laid down. */
.st-glance::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: var(--slip-air); opacity: 1; pointer-events: none;
  transition: opacity var(--slip-land, 300ms) var(--ease-settle, ease);
}
.st-glance.is-open::after { opacity: 0; }
.st-glance > * { position: relative; }

/* THREE RANKS, TWO INKS. The word and its meaning in warm sumi — the thing
   pointed at and the answer; the reading between them in the one quiet grey.
   Nothing else: no label, no rule, no door. */

/* the WORD — the subject, in the sentence's own brush, a size up from it */
.st-g-word {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 27px;
  line-height: 1.22;
  letter-spacing: 0.01em;
  color: var(--slip-ink, #3A3633);
}
/* a long word steps down rather than widening the slip into a banner */
.st-g-word--long { font-size: 22px; }

/* the SOUND — kana and romaji on one row, baseline to baseline; the romaji
   is the app-wide italic caption to the kana, never its twin */
.st-g-sound {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 1px 9px;
  margin-top: 4px;
}
.st-g-read {
  font-family: 'Noto Sans JP', sans-serif;
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: 0.04em;
  color: var(--slip-quiet, #6E6860);
}
.st-g-ro {
  font-family: var(--font-ui);
  font-style: italic;
  font-size: 12px;
  line-height: 1.35;
  letter-spacing: 0.05em;
  color: var(--slip-quiet, #6E6860);
}

/* the MEANING — in ink, the crisp second line of the card */
.st-g-en {
  margin-top: 8px;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--slip-ink, #3A3633);
  text-wrap: pretty;
}
/* a word with no gloss at all — kept quiet, never an apology */
.st-g-none {
  margin-top: 8px;
  font-style: italic;
  font-size: 12px;
  line-height: 1.45;
  color: var(--slip-quiet, #6E6860);
}

@media (prefers-reduced-motion: reduce) {
  .st-tk, .st-glance, .st-glance::after { transition: none; }
  .st-glance::after { opacity: 0; }   /* Reduce Motion must LAND the end state */
}

/* ── R1 S2 — the cloze GAP + the scaffold's pre-explanation ──────────────── */

/* The gap (design §5.5): a due word seated for the BUILD is veiled as a slot,
   and the word's English gloss stands IN the slot — the cue, printed where
   the answer will land. Indigo dashes = interactive, the locked inline
   language; the gloss is quiet EN italic, unmistakably not Japanese. */
.st-gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.2em;
  padding: 0 0.45em;
  border-bottom: 2px dashed rgba(61, 90, 128, 0.55);
  border-radius: 2px;
}
.st-gap i {
  font: italic 400 0.56em var(--font-ui, 'Inter', sans-serif);
  color: var(--color-stone, #57534e);
  letter-spacing: 0.01em;
  white-space: nowrap;
  max-width: 11em;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The scaffold (design §5.1, the inversion's other half): a never-met word
   arrives PRE-EXPLAINED — its reading rides above as ruby in every written
   mode (a lesson is not a test), and romaji + gloss stand in a small stack
   under the word, printed free. Quiet on purpose: the lesson is a gift,
   the sentence stays the subject. */
/* THE SEAT (2026-09-16). The first cut hung the note OUT of layout
   (position:absolute, one nowrap line centred under the word) so the
   sentence's typography stayed untouched, and three never-met words in a
   row (もっとゆっくり話してください) printed "yukkuri slowly / hanashite to
   speak / kudasai to give" on top of each other: an absolute note knows
   nothing of its neighbour, and a note wider than its word overhangs both
   sides. Two traps had already ruled out the obvious in-flow dresses: a
   flex column split the token's ruby run and trailing kana into stacked
   pieces (分かりません in three), and inline-block lifted the word off the
   line's baseline (an inline-block's baseline is its LAST line's, i.e. the
   note's). So the seat is the third dress: the token is an INLINE GRID whose
   first row is the word (one wrapper, .st-w, so ruby + kana stay one piece)
   and whose second row is the note. A grid's first baseline is its FIRST
   row's, so the word stays on the line with its neighbours; the note is IN
   flow, so it can never cross a neighbour's; and it stacks romaji OVER gloss
   (the "small stack" the design asked for), which keeps it narrower than
   its word nearly always. When it is not, the word gains exactly the
   overhang on each side and the sentence spaces itself — a beginner's
   分かち書き — instead of printing two notes on one spot. The line box grows
   by the note's height on a scaffolded line; that is the honest cost, paid
   where the lesson is, never on a sentence without one. */
.st-tk--scaffold {
  display: inline-grid;
  justify-items: center;
  vertical-align: baseline;
}
.st-sc {
  display: grid;
  justify-items: center;
  row-gap: 1px;
  line-height: 1;
  /* the note rides up into the line's slack under the word, where the
     hanging note used to sit; the word row keeps the line's own leading */
  margin-top: -0.55em;
  /* a gutter that only bites when the note is the wider row: two
     neighbours' notes wider than their words would otherwise print edge
     to edge ("to look at carefullyto speak"); a note narrower than its
     word costs the sentence nothing */
  padding: 0 0.3em;
  text-align: center;
}
.st-sc-ro {
  font: italic 400 0.5em var(--font-ui, 'Inter', sans-serif);
  color: var(--color-faint-warm, #8a8378);
  white-space: nowrap;
}
.st-sc-en {
  font: 400 0.52em var(--font-ui, 'Inter', sans-serif);
  line-height: 1.15;
  color: var(--color-stone, #57534e);
  /* a long cue WRAPS — never clips (a beginner reads the whole cue) and
     never widens the sentence past this. ⚠ this em is the gloss's OWN
     0.52em, not the sentence's: 10em ≈ 125px under the walk's 1.5rem line,
     about five characters of sentence — the most a note may ask of it */
  max-width: 10em;
}

/* THE WORD KEEPS ITS DRESSES; THE NOTE WEARS NONE. The token's box now holds
   the note, so its hover wash, open seat and focus ring would paint a three-
   row chip and seat the hairline under the English (the review that caught
   it: 2026-09-16). The file's own law is "a hairline seat under the word,
   never a highlight over it" — so on a scaffold the three dresses move to
   .st-wi, the inline word inside the row, whose painted box is the font's
   content area: the same box a plain neighbour paints. Same guards as the
   originals: the hover half stays behind the hover-capability query (the
   iPad latched-hover law above). Later in the file + equal or higher
   specificity, so these win. */
.st-tk--scaffold:not(.st-tk--inert):hover,
.st-tk--scaffold.is-open { background-color: transparent; box-shadow: none; }
.st-tk--scaffold:focus-visible { outline: none; }
.st-wi {
  border-radius: 2px;
  transition: background-color 140ms var(--ease-page, ease),
              box-shadow 140ms var(--ease-page, ease);
}
.st-tk--scaffold.is-open .st-wi {
  background-color: rgba(201, 169, 110, 0.16);
  box-shadow: inset 0 -2px 0 -1px rgba(201, 169, 110, 0.85);
}
.st-tk--scaffold:focus-visible .st-wi {
  outline: 2px solid var(--color-indigo, #3D5A80);
  outline-offset: 1px;
}
@media (hover: hover) and (pointer: fine) {
  .st-tk--scaffold:not(.st-tk--inert):hover .st-wi {
    background-color: rgba(201, 169, 110, 0.16);
  }
}
@media (prefers-reduced-motion: reduce) { .st-wi { transition: none; } }

/* A NOTE WIDER THAN ITS WORD must not open paper between the word and the
   mark or particle that closes on it — the file's own law says no gap opens
   before the full stop, and 分かち書き glues a particle to its word. When the
   next token is punctuation or a particle the word pins to the column's END
   and the whole overhang falls BEFORE the word, where a beginner's text puts
   its spaces anyway. The note pins with it — word and note share a right
   edge, so a wide note still reads as THIS word's, not as a caption under
   the space before it. */
.st-tk--scaffold:has(+ .st-tk--punct),
.st-tk--scaffold:has(+ .st-tk[data-st-pid$="Particle"]) { justify-items: end; }
.st-tk--scaffold:has(+ .st-tk--punct) .st-sc,
.st-tk--scaffold:has(+ .st-tk[data-st-pid$="Particle"]) .st-sc {
  justify-items: end;
  text-align: right;
}
