/* =============================================================================
   WORD PAGE — 寄り + 図録 + 絵巻 (E1: the page becomes a book)

   Every painting click on the gallery wall lands here. Two rooms in one
   scroller: viewport 1 is the YORI arrival — the painting full-bleed and
   PINNED (position:sticky), the word inscribed vertically as a gasan with a
   hand-pressed 言 seal, the placard re-set as ink bottom-left, no boxes
   anywhere. The washi catalog sheet (ZUROKU) slides OVER the pinned painting
   on scroll; its own top edge is the 続き lip that peeks at rest. Since E1
   the sheet is the SAME SCROLL CONTINUING: the painting's pigment tints the
   washi (--wp-washi, set per word), kasumi mist bands separate the scenes,
   the boxed cards are dissolved to ink on the tinted paper, and related
   words hang as real mini-paintings (the 対 antonym diptych faces you).

   ROOT SELECTOR: `.wp-root` (the element also carries id="wordPage" — only
   the CURRENT page owns the id; a fusuma exit clone keeps .wp-root so its
   styles hold mid-slide). Button rules carry the .wp-root prefix because
   components.css paints every bare <button> as a floating white pill with a
   hover lift — the reset below must keep winning (the round-3 specificity
   trap; word-page.css also loads after components.css so ties break our way).

   Ink legibility is PER REGION via js/zone-ink.js: .wp-rg-dark (white ink on
   sumi veil) / .wp-rg-light (sumi ink on washi veil) applied separately to
   the gasan, placard and back-button corners from bundle-precomputed zone
   luminances (img_lum); missing data falls to white-on-heavier-sumi (the
   safe floor — the dark treatment manufactures its own contrast).
   ============================================================================= */

.wp-root {
  position: fixed;
  inset: 0;
  z-index: 9000;            /* above nav + wall; below nothing it must yield to */
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #171310;
  font-family: 'Inter', sans-serif;
  color: var(--color-ink);
  -webkit-font-smoothing: antialiased;
  scrollbar-width: none;
  animation: wpArrive 0.36s ease-out;
}
.wp-root::-webkit-scrollbar { display: none; }
@keyframes wpArrive { from { opacity: 0; } to { opacity: 1; } }
body.wp-open { overflow: hidden; }

/* hop arrival (fusuma) — no entrance fade; the slide IS the entrance */
.wp-root.wp-noarrive { animation: none; }

.wp-root button {
  appearance: none;
  background: none;
  border: none;
  border-radius: 0;     /* components.css gives every button a 12px pill radius */
  box-shadow: none;     /* …and a floating white-pill shadow — both must die here */
  font: inherit;
  color: inherit;
  cursor: pointer;
  padding: 0;
  margin: 0;
}
/* …and a translateY(-2px) hover lift + glow (components.css:390) — the
   "buttons jump on hover" owner note. Buttons on this page REST. */
.wp-root button:hover,
.wp-root button:active {
  transform: none;
  box-shadow: none;
}
.wp-root button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 3px;
}
/* …and that 3px squares the ROUND ones. `.wp-root button:focus-visible` is
   (0,2,1); a plain `.wp-root .wp-oto` (0,2,0) loses to it, so every hanko
   chip on this page turned into a rounded tile the moment a keyboard reached
   it — the outline is drawn on the squared shape too. The discs claim their
   shape back here, beside the rule that takes it (2026-08-01; the audio chips
   carried this since they were born round, the room chip inherited it).
   They also take the app's one ring's 2px offset (desktop polish round 4,
   finding 6): the round doors into the sound and the room ring the same way
   the tile's discs and the panel's chips do. */
.wp-root .wp-oto:focus-visible,
.wp-root .wp-eaudio:focus-visible,
.wp-root .wp-crest:focus-visible { border-radius: 50%; outline-offset: 2px; }

/* ─── VIEWPORT 1 — the arrival stage, pinned ─── */
.wp-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* region ink regimes — set independently on the gasan + placard subtrees */
.wp-rg-dark {
  --ink: #F6F1E7;
  --inkdim: rgba(246, 241, 231, 0.80);
  --inkfaint: rgba(246, 241, 231, 0.58);
  --halo: 0 0 22px rgba(18, 14, 10, 0.55), 0 0 3px rgba(18, 14, 10, 0.35);
  --romaji-ink: var(--color-gold);
  --romaji-halo: 0 1px 12px rgba(18, 14, 10, 0.8), 0 0 3px rgba(18, 14, 10, 0.5);
  /* a live kanji's hover ink — indigo GRAMMAR kept, but bright + cool so it
     stays legible over a dark painting (a flat #3D5A80 would sink into the
     art — see the gasan note below). */
  --ink-hover: #BFCEE8;
}
.wp-rg-light {
  --ink: var(--color-ink);
  --inkdim: rgba(44, 44, 44, 0.80);
  --inkfaint: rgba(44, 44, 44, 0.56);
  --halo: 0 0 18px rgba(250, 247, 239, 0.78), 0 0 3px rgba(250, 247, 239, 0.5);
  --romaji-ink: #A8854B;
  --romaji-halo: 0 0 14px rgba(250, 247, 239, 0.85), 0 0 3px rgba(250, 247, 239, 0.6);
  /* light painting → the page's own interactive indigo reads cleanly */
  --ink-hover: var(--color-accent);
}

.wp-paint {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: pointer;          /* a press on the painting speaks the word */
}

/* painter's scrim — the painting darkening (or paling) at its edges, never a box.
   Colors are written inline per word from the zone regimes + img_tone. */
.wp-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, var(--wp-scrimC) 0%, var(--wp-scrimB) 20%, transparent 48%),
    linear-gradient(to bottom, var(--wp-topC) 0%, transparent 13%);
}
.wp-gasanveil {
  position: absolute;
  top: 0;
  right: 0;
  width: 560px;
  height: 680px;
  pointer-events: none;
  background: radial-gradient(120% 100% at 100% 0%,
    var(--wp-veilC) 0%, var(--wp-veilB) 40%, transparent var(--wp-veilReach, 68%));
}

/* the back button's own corner veil — top-LEFT, its own zone's regime.
   The gasan veil never reaches this corner; without this the back rides
   whatever the painting happens to put there (owner round 2: invisible
   on the kabuki costume). */
.wp-backveil {
  position: absolute;
  top: 0;
  left: 0;
  width: 380px;
  height: 200px;
  pointer-events: none;
  background: radial-gradient(140% 130% at 0% 0%,
    var(--wp-backC) 0%, var(--wp-backB) 45%, transparent 75%);
}

/* back — top-left. Reads '← 画廊 gallery' at the trail head and
   '← <previous word> previous' mid-walk (the 栞 trail). Sized up — it is
   the page's primary way home and was reading as a footnote. */
.wp-root .wp-back {
  position: absolute;
  top: 24px;
  left: 32px;
  display: flex;
  align-items: baseline;
  gap: 13px;
  padding: 8px 12px;
  color: var(--ink);
  text-shadow: var(--halo);
}
.wp-back .arr { font-size: 20px; }
.wp-back .jp { font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 19px; font-weight: 600; }
.wp-back .cap {
  font-size: 10.5px;
  letter-spacing: 0.22em;
  color: var(--inkfaint);
  text-transform: uppercase;
}
.wp-back:hover .cap { color: var(--inkdim); }

/* gasan — the inscription, set like a hanging-scroll 掛軸: one column for
   most words, TWO right-to-left columns for 8+ characters (real gasan
   break long inscriptions into columns — long phrases gain PRESENCE
   instead of shrinking to a thread). The parallel reading column is
   retired: the inscription is always exactly one thing, its reading
   riding it as ruby. */
.wp-gasan {
  position: absolute;
  top: 58px;
  right: 66px;
  display: flex;
  flex-direction: row;
  gap: 20px;
  align-items: flex-start;
}
.wp-gasan .wp-word {
  display: flex;
  flex-direction: row-reverse;   /* first column rightmost — the scroll's reading order */
  gap: 0.46em;                   /* the ruby channel between columns */
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  color: var(--ink);
  text-shadow: var(--halo);
  line-height: 1;
}
.wp-gasan .wp-wcol {
  writing-mode: vertical-rl;
  letter-spacing: 0.10em;
}
/* furigana rides each kanji (vertical ruby sits to the column's right) —
   the kana-to-kanji mapping a parallel reading column can't show. THE
   RUBY FLOOR (owner seed #1): no reading aid ever renders below 16px,
   however long the word — the clamp decouples it from the base size. */
.wp-gasan .wp-word rt {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: clamp(16px, 0.34em, 28px);
  letter-spacing: 0.18em;
  color: var(--ink);
  opacity: 1;
  text-shadow: var(--halo);
}
/* bottom-left ink placard */
.wp-placard {
  position: absolute;
  left: 64px;
  right: 64px;
  bottom: 74px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}
/* provenance whisper on hop arrival: '縁 — <previous> より' — tap = back one */
.wp-root .wp-via {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--inkfaint);
  text-shadow: var(--halo);
  margin-bottom: 12px;
}
.wp-via [lang="ja"] { font-family: 'Klee One', 'Noto Sans JP', sans-serif; }
.wp-via .dash { font-size: 11px; }
.wp-root .wp-via:hover { color: var(--inkdim); }
.wp-romaji {
  font-style: italic;
  font-size: 14.5px;
  letter-spacing: 0.05em;
  color: var(--romaji-ink);
  text-shadow: var(--romaji-halo);
  margin-bottom: 11px;
}
/* also written 〜 — the kana-displayed word's living kanji spelling
   (docs/ALT_SPELLING_SPEC.md). Sits with the reading, above the gloss:
   orthography belongs to the word's form, not its meaning. Page-gated
   kanji are doors (indigo = interactive, the locked inline semantic);
   uncovered kanji are plain ink until their activation wave. */
/* 別表記 — the spelling a kana-faced word keeps, seated in the painting's
   bottom-right corner (2026-08-07). It shares the corner with the rakkan marks
   and must not share their look: a mark is a framed glyph wearing a caption
   that says what that character means HERE, and this block deliberately makes
   no per-character claim at all (see js/grid-mode.js — 眼鏡 megane is read as a
   pair, and ~24 of these spellings are one character where a caption would only
   restate the gloss). So: the spelling whole, in ordinary ink, and one line of
   dimmer type saying how often it is used. No frames, no gold, no captions. */
/* ONE ROW: "sometimes written 是非" reads as a sentence, not as a headline with
   a label wedged under its descenders. The spelling is the only loud thing in
   it, and it is only a little louder than the words around it — the marks below
   are where the characters get their size. */
.wp-altw {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 8px;
  text-shadow: var(--halo);
}
.wp-altw .jp {
  font-family: var(--font-jp, 'Klee One'), sans-serif;
  font-size: 19px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: 0.04em;
}
.wp-altw .cap {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--inkdim);
}
/* the row is a caption for the marks, so it needs the gap a caption needs —
   at 3px the uppercase sat directly on the glyphs above it */
.wp-root .wp-plright.alt .wp-plmarks { margin-top: 13px; }
/* ⛔ .wp-root needed. Bare `.wp-altk` (0,1,0) loses to the `.wp-root button`
   reset (0,1,1) three hundred lines up, which sets `border: none; color:
   inherit` — so from #825 until 2026-08-07 these doors rendered pixel-identical
   to a character with no page: same colour, zero underline. The whole point of
   the block is that a door means "there is a room here" and its absence means
   "this character is not yours to learn", and neither half was visible. The
   word PANEL never had the bug; it scoped its twin as `.wpn-overlay .wpn-altk`.

   The door is an UNDERLINE IN THE INK, not the app's indigo. Indigo is the
   interactive colour (locked #313) and it is right in the panel, whose drawer
   is light paper — but this placard sits on the painting, where the ink is
   cream and #3D5A80 is close to unreadable. An underline adds no colour to the
   scheme and reads as a door on any painting. */
.wp-root .wp-altk {
  appearance: none;
  background: none;
  padding: 0 1px;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: none;
  border-bottom: 1px solid color-mix(in srgb, currentColor 38%, transparent);
  transition: border-color 0.15s ease;
}
.wp-root .wp-altk:hover { border-bottom-color: currentColor; }
.wp-gloss {
  font-size: 29px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
  text-shadow: var(--halo);
  max-width: 680px;
  margin-bottom: 21px;
  /* two lines before the ellipsis — one line amputated real glosses
     (owner 2026-06-12); the catalog below still restates it in full */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wp-acts {
  display: flex;
  align-items: center;
  gap: 22px;
  /* last resort at narrow desktop: the VERB PAIR drops to its own line
     rather than the labels breaking mid-word. The placard is bottom-
     anchored (position:absolute; bottom), so a second line grows UP into
     the painting and nothing below it moves. */
  flex-wrap: wrap;
  row-gap: 12px;
}
/* the round tools travel as a pair — hear it, open its room — held closer
   to each other than to the framed verbs, so the row reads as two groups */
.wp-chips {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;   /* two 44px discs; the row's give comes from elsewhere */
}
/* the two decisions travel as a pair too, so a wrapping row drops BOTH
   verbs together — a lone hanging 覚える reads as a mistake, not a choice */
.wp-verbs {
  display: flex;
  align-items: center;
  gap: 22px;
}
/* the 音 chip wears the brand seal's clothes (owner 2026-06-11: the plain
   white circle read as an off-brand logo): washi disc, brushed sumi ring,
   the logo's small gold dot under the glyph */
.wp-root .wp-oto {
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #F7F2E6;
  border: 1.6px solid rgba(44, 44, 44, 0.72);
  color: var(--color-ink);
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(44, 44, 44, 0.06);
}
.wp-root .wp-oto svg { width: 18px; height: 18px; display: block; }
.wp-root .wp-oto:hover { box-shadow: 0 1px 3px rgba(44, 44, 44, 0.06); }
.wp-root .wp-oto::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  transform: translateX(-50%);
  background: var(--color-gold);
}
.wp-root .wp-oto.playing { border-color: var(--color-gold); color: #A8854B; }

/* SAVE 残す / SKIP 流す — real presence (owner seed #3): framed ghost
   buttons with a quiet color identity in the app-wide grammar — amber =
   still learning (save), moss = known (skip), same as the wall's status
   dots. The accents are MIXED WITH the region's own ink so they keep
   contrast on both regimes (cream tints on dark paintings, deep on light). */
.wp-root .wp-verb {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 11px 22px 12px;
  border: 1.5px solid color-mix(in srgb, var(--vac, var(--ink)) 62%, transparent);
  border-radius: 3px;
  color: var(--ink);
  text-shadow: var(--halo);
}
.wp-root .wp-save { --vac: color-mix(in srgb, var(--color-amber, #A07850) 55%, var(--ink) 45%); }
.wp-root .wp-skip { --vac: color-mix(in srgb, var(--color-moss, #6B7F5C) 55%, var(--ink) 45%); }
.wp-root .wp-verb:hover {
  border-color: var(--vac, var(--ink));
  background: color-mix(in srgb, var(--vac, var(--ink)) 12%, transparent);
}
.wp-root .wp-verb.active {
  border-color: var(--vac, var(--ink));
  background: color-mix(in srgb, var(--vac, var(--ink)) 22%, transparent);
}
/* a fixed two-word label is a LABEL, not prose: it never breaks. Under
   narrow-desktop pressure the row used to snap "SAVE TO / PRACTICE" apart
   and split 残 / す down the middle of one word (2026-08-01). */
.wp-verb .cap {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}
.wp-verb .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 15px;
  color: var(--inkdim);
  white-space: nowrap;
}
/* 残響 — the wall's grade receipt, spoken on the page: one quiet echo line
   under the mark buttons, in the placard's own regime ink (the grid's fixed
   stone/accent would sink into a dark painting). Base echo behaviour
   (flex, fade in/out) comes from .grid-card-echo in grid-mode.css. */
.wp-root .wp-grade-echo {
  justify-content: flex-start;
  min-height: 0;
  padding: 10px 0 0;
  font-size: 12.5px;
  color: var(--inkdim);
  text-shadow: var(--halo);
}
.wp-root .wp-grade-echo .grid-echo-jp,
.wp-root .wp-grade-echo .grid-echo-text { color: var(--inkdim); }
.wp-root .wp-grade-echo .grid-echo-undo {
  color: var(--ink);
  text-shadow: var(--halo);
  text-decoration-color: color-mix(in srgb, var(--ink) 40%, transparent);
}
.wp-root .wp-grade-echo .grid-echo-undo:hover {
  text-decoration-color: var(--ink);
}
/* 壁書き — the wall label's opening line (owner seed #2): what KIND of
   thing this is, placed where the eye already reads. The old bottom-right
   corner is deleted; the painting's fourth corner returns to the painting. */
.wp-eyebrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--inkdim);
  text-shadow: var(--halo);
}
.wp-eyebrow .pj {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 14px;
  letter-spacing: 0.1em;
  color: var(--ink);
}
/* POS-English, separators and the rank all read at the eyebrow base brightness
   (--inkdim), same as the register — so VERB / CORE 1K / HONORIFIC are equally
   legible over the painting. (Was --inkfaint, which washed out the rank on the
   brighter parts of the hero image.) Only the JP head (動詞, .pj) sits brighter. */
.wp-eyebrow .sep,
.wp-eyebrow .pe { color: var(--inkdim); }
/* The freq badge reuses the grid's FreqTier markup (same "Core 1K" content),
   but here it wears the SAME quiet eyebrow voice as POS/category — not the
   freq-tier's own hue, opacity, serif numeral or tracking. So it reads as one
   more word in the line ("… NOUN · CORE 1K"), not a visiting badge. */
.wp-eyebrow .freq-tier,
.wp-eyebrow .freq-tier[data-freq-tier] {
  position: static;
  top: auto;
  right: auto;
  pointer-events: auto;            /* let the rank tooltip surface on hover */
  color: var(--inkdim);            /* match .pe (the POS English) + register */
  opacity: 1;
  font-family: inherit;
  font-weight: 600;
  font-size: inherit;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-shadow: var(--halo);
}
/* Flatten the tier-1 "Core / 1 / K" flourish to the same eyebrow type so it
   reads "CORE 1K" in the line's voice (no serif, no hue, no size shift).
   The [data-freq-tier] qualifier is load-bearing: freq-tier.css loads AFTER
   word-page.css and its `.freq-tier[data-freq-tier="1"] .num` rule ties this
   one at (0,3,0), so without the extra attribute here the serif numeral wins
   on source order and "CORE 1K" reverts to the visiting-badge look. */
.wp-eyebrow .freq-tier[data-freq-tier] .pre,
.wp-eyebrow .freq-tier[data-freq-tier] .num,
.wp-eyebrow .freq-tier[data-freq-tier] .unit {
  font-family: inherit;
  font-size: 1em;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: inherit;
  opacity: 1;
  margin: 0;
  vertical-align: baseline;
  text-transform: uppercase;
}
.wp-eyebrow .freq-tier[data-freq-tier] .pre { margin-right: 0.22em; }

/* 礼 — politeness register in the eyebrow (sparse: only register-marked
   words — keigo / casual / slang). Replaces the old category chip; category
   now lives only in the colophon. Same quiet monochrome eyebrow voice as
   POS — the register HUE belongs to the POLITENESS section below, so the
   eyebrow stays one calm line. cursor:help surfaces the tooltip affordance. */
.wp-eyebrow .wp-reg {
  color: var(--inkdim);
  cursor: help;
}

/* ─── 落款 RAKKAN — the painting's signature marks ───
   The word's page-gated kanji sign the canvas: outlined square seals,
   glyph + first keyword sense, in the placard's regime ink (sumi on
   light floors, paper on dark — never a fixed color on art). They press
   in one by one AFTER the kigō inscription settles, the way a painter
   signs last. Doors into the kanji room; gold only on intent (hover).
   window._wpHeroKanjiLeft = true trades the bottom-right cluster for
   framed doors inside the left placard stack (the owner's hypothesis). */
/* the cluster is a COLUMN: the 別表記 spelling (on a kana-faced word) over the
   seals. The composition line no longer sits here: its one seat is the 字
   section, after the character rows (desktop polish 2026-10-12). */
.wp-plright {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  margin-left: 32px;
}
.wp-plmarks {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 14px;
}
.wp-root .wp-rakkan,
.wp-root .wp-kdoor {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--ink);
  text-shadow: var(--halo);
}
.wp-rakkan .kg {
  width: 46px;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid color-mix(in srgb, var(--ink) 55%, transparent);
  border-radius: 10px;
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 24px;
  transition: border-color 0.18s ease, background-color 0.18s ease, transform 0.12s ease;
}
/* The caption is the character's OWN name, its first keyword (desktop polish
   2026-10-12, owner-approved): the seal is a door into the character. It had
   carried the sense the character lends THIS word, a phrase as often as a
   word, and was cut at two lines under the seal ("COUNTER / FOR LONG.."); that
   sense now leads the character's row in the 字 section. One line, never cut:
   a keyword longer than 14 characters prints no caption at all (js markBtn),
   so nothing here needs a clamp. (The kanji page's 陽 room seal shares this
   class; its count caption was already one line and stays one.) */
.wp-rakkan .kc,
.wp-kdoor .kc {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  line-height: 1.32;
  text-transform: uppercase;
  text-align: center;
  color: var(--inkdim);
  white-space: nowrap;
}
.wp-rakkan .go,
.wp-kdoor .go {
  position: absolute;
  top: -5px;
  right: -7px;
  font-size: 10px;
  color: var(--color-gold);
  opacity: 0;
  transition: opacity 0.18s ease;
}
.wp-root .wp-rakkan:hover .kg,
.wp-root .wp-rakkan:focus-visible .kg,
.wp-rakkan.glint .kg {
  border-color: var(--ink);
  background: color-mix(in srgb, var(--ink) 8%, transparent);
}
/* no lift: the tinted .kg above and the gold .go arrow below already say
   "awake", and a 1px lift vacates the door's own bottom edge (see the hover
   law in css/components.css). */
.wp-root .wp-rakkan:hover .go,
.wp-root .wp-kdoor:hover .go,
.wp-root .wp-rakkan:focus-visible .go,
.wp-root .wp-kdoor:focus-visible .go { opacity: 1; }
.wp-rakkan.pressed .kg { transform: scale(0.94); }

/* ─── 字組み WORD COMPOSITION — the struck mark (the line: 字 section) ───
   A character can sit in a word for its SOUND (頑張る ganbaru, whose 頑 only
   spells gan) or as an ENDING (可能性 kanousei, whose 性 is English -ness).
   It has no meaning to give, and the card used to hand the learner one anyway.
   The keyword STAYS and wears a line through it: the learner will meet "enemy"
   on 敵 somewhere else, and "you will find this, it is not in play here" is a
   truer thing to be shown than a blank. One mark, one statement, no caption —
   the strike says it, and the 字 section says the rest. */
.wp-rakkan.snd .kc,
.wp-kdoor.snd .kc {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--ink) 62%, transparent);
  opacity: 0.66;
}

/* the owner's bottom-left variant: framed door pills after SAVE/SKIP */
.wp-kdoors {
  display: flex;
  gap: 14px;
  margin-top: 18px;
  overflow: hidden;
  white-space: nowrap;
}
.wp-root .wp-kdoor {
  padding: 8px 13px 9px;
  border: 1px solid color-mix(in srgb, var(--ink) 38%, transparent);
  border-radius: 2px;
  transition: border-color 0.18s ease, background-color 0.18s ease, transform 0.12s ease;
}
.wp-kdoor .kg {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 30px;
  line-height: 1.1;
}
.wp-root .wp-kdoor:hover,
.wp-root .wp-kdoor:focus-visible,
.wp-kdoor.glint {
  border-color: var(--ink);
  background: color-mix(in srgb, var(--ink) 8%, transparent);
}
.wp-kdoor.pressed { transform: scale(0.96); }

/* the marks press in only after the inscription finishes (delays written
   per-mark by JS as --sd; inert unless mount() sets .wp-kigo) */
@keyframes wpMarkPress {
  from { opacity: 0; transform: scale(1.15); }
  to   { opacity: 1; transform: none; }
}
.wp-kigo .wp-rakkan,
.wp-kigo .wp-kdoor {
  opacity: 0;
  animation: wpMarkPress 0.45s ease-out forwards;
  animation-delay: var(--sd, 0ms);
}

@media (max-width: 1280px) {
  .wp-rakkan .kg { width: 40px; height: 40px; font-size: 22px; }
}

/* 揮毫 — the inscription inks on, unit by unit, its furigana landing a
   beat after its kanji. The class is set by JS on fresh wall-opens only
   (never on fusuma slides or trail restores) and never under
   prefers-reduced-motion; opacity-only, compositor-friendly. */
@keyframes wpGuOn { from { opacity: 0; } to { opacity: 1; } }
.wp-kigo .wp-gu {
  opacity: 0;
  animation: wpGuOn 0.32s ease-out forwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}
.wp-kigo .wp-gu rt {
  opacity: 0;
  animation: wpGuOn 0.26s ease-out forwards;
  animation-delay: calc(var(--i, 0) * 45ms + 200ms);
}

/* ─── THE SHEET — the scroll continuing (EMAKI) ───
   --wp-washi (the painting's pigment soaked 7% into the paper) and
   --wp-tone (the raw tone, for kasumi bands) are written inline per word. */
.wp-sheet {
  position: relative;
  z-index: 5;
  margin-top: -52px;            /* the lip overlaps the stage = the peek */
  background: var(--wp-washi, #FAF7EF);
  border-radius: 14px 14px 0 0;
  box-shadow: 0 -14px 40px rgba(15, 11, 7, 0.30), 0 -2px 8px rgba(15, 11, 7, 0.12);
  min-height: 100vh;
  color: var(--color-ink);
}

/* the rolled lip — the sheet's own top edge; running head once stuck */
.wp-lip {
  position: sticky;
  top: 0;
  z-index: 8;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--wp-washi, #FAF7EF);
  border-radius: 14px 14px 0 0;
  border-bottom: 1px solid rgba(44, 44, 44, 0);
  transition: border-color 0.25s;
}
.wp-lip::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.55);
  border-radius: 14px 14px 0 0;
}
.wp-cue {
  display: flex;
  align-items: center;
  gap: 13px;
  color: var(--color-stone);
}
.wp-cue .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 13.5px;
  letter-spacing: 0.12em;
  color: #44403a;
}
.wp-cue .cap {
  font-size: 9px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #8d877b;
}
.wp-cue .tick { width: 22px; height: 1px; background: #c2bbab; }
.wp-run {
  display: none;
  width: 100%;
  padding: 0 40px;
  align-items: baseline;
  justify-content: space-between;
}
/* 探す — the lookup's door on the running head (search slice 2). Grouped
   on the RIGHT with the catalog mark: the left band after the back chevron
   belongs to the 栞 trail stones (absolutely positioned at left:170px —
   a left-grouped button sat under them and lost its clicks to trail
   navigation). Styles for the button itself live in vocab-palette.css
   (.sagasu-btn — the one shared control). */
.wp-run .wp-rright { display: flex; align-items: baseline; gap: 16px; }
.wp-root .wp-run .wp-rback {
  display: flex;
  align-items: baseline;
  gap: 10px;
  color: var(--color-stone);
}
.wp-run .wp-rback .jp { font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 15px; font-weight: 600; }
.wp-run .wp-rback .cap {
  font-size: 10.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #8d877b;
}
.wp-run .wp-rback:hover .cap { color: var(--color-stone); }
.wp-run .wp-rword { display: flex; align-items: baseline; gap: 12px; }
.wp-run .wp-rword .w {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 19px;
  font-weight: 600;
  color: var(--color-ink);
}
.wp-run .wp-rword .r {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 14px;
  color: #6d675c;
}
.wp-run .wp-rcap {
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #8d877b;
}
.wp-run .wp-rcap .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 11.5px;
  letter-spacing: 0.3em;
  color: var(--color-stone);
}
.wp-lip.stuck { border-bottom-color: rgba(44, 44, 44, 0.08); }
.wp-lip.stuck .wp-cue { display: none; }
.wp-lip.stuck .wp-run { display: flex; }

/* ─── 栞 trail stones — the walk made visible in the lip ───
   One stone per visited word in its painting's own tone; the current stone
   wears the only ink ring; ghosts (the forward stack) are re-walkable. */
.wp-stones {
  position: absolute;
  left: 170px;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  z-index: 9;
}
.wp-root .wp-stone {
  position: relative;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--stone, #b0a090);
  box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.06);
}
.wp-root .wp-stone:hover { box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.06); }
.wp-root .wp-stone.current {
  box-shadow: 0 0 0 2px var(--wp-washi, #FAF7EF), 0 0 0 3.5px var(--color-ink);
}
.wp-root .wp-stone.ghost { opacity: 0.35; }
.wp-stone-more {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 11px;
  color: #8d877b;
  margin-right: 2px;
}
/* hover bloom: the visited painting lifts out of its stone */
.wp-stone-bloom {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  width: 104px;
  padding: 5px 5px 6px;
  background: #FBF8F1;
  border: 1px solid rgba(44, 44, 44, 0.14);
  border-radius: 4px;
  box-shadow: 0 6px 18px rgba(15, 11, 7, 0.20);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s ease, transform 0.16s ease;
  z-index: 20;
}
.wp-lip.stuck .wp-stone-bloom {
  bottom: auto;
  top: 24px;
  transform: translateX(-50%) translateY(-3px);
}
.wp-root .wp-stone:hover .wp-stone-bloom,
.wp-root .wp-stone:focus-visible .wp-stone-bloom {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.wp-stone-bloom .im {
  display: block;
  width: 94px;
  height: 63px;
  border-radius: 2px;
  background-size: cover;
  background-position: center;
  background-color: var(--stone, #b0a090);
}
.wp-stone-bloom .lw {
  display: block;
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink);
  text-align: center;
  margin-top: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wp-stone-bloom .lr {
  display: block;
  font-size: 9px;
  font-style: italic;
  color: #8d877b;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* (the 運 running-title rail is retired — the stuck lip's running head
   already carries word, reading and 図録 within 200px of where it stood;
   two simultaneous running titles is information worn twice.) */

/* ─── catalog entry column (the ZUROKU re-set on the tinted washi) ─── */
.wp-entry {
  max-width: 780px;
  margin: 0 auto;
  padding: 64px 24px 96px;
}

/* 扉 — the plate title. The headword carries title scale and its own ruby
   (the stacked reading/listen/kana rows are collapsed into one composed
   lockup: headword, then romaji with the 音 chip inline, then the gloss). */
.wp-eword {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 64px;
  line-height: 1.22;
  letter-spacing: 0.01em;
  margin: 0 0 6px;
  color: var(--color-ink);
}
/* THE RUBY-FLOOR LAW (page invariant): no reading aid on the washi ever
   renders below 13px — the headword's own ruby holds a 14px floor; the
   hero gasan keeps its separate 16px on-art floor. A reading aid a
   beginner cannot read is decoration wearing a teacher's clothes. */
.wp-eword rt {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 400;
  font-size: clamp(14px, 0.30em, 22px);
  letter-spacing: 0.1em;
  color: var(--color-stone);
}
.wp-eword.long { font-size: 46px; }
.wp-eword.verylong { font-size: 36px; }
.wp-eromaji {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 16px;
  letter-spacing: 0.045em;
  color: #A8854B;
}
.wp-eromaji .ro { font-style: italic; font-weight: 500; }
/* the 音 chip in the brand hanko dress, inline at the romaji's right —
   the LISTEN cap is dropped (the convention is established on arrival);
   the ::before halo keeps the hit target at 46px */
.wp-root .wp-eaudio {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #F7F2E6;
  border: 1.4px solid rgba(44, 44, 44, 0.55);
  color: var(--color-ink);
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 14px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 2px rgba(44, 44, 44, 0.06);
}
.wp-root .wp-eaudio svg { width: 14px; height: 14px; display: block; }
.wp-root .wp-eaudio::before {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
}
.wp-root .wp-eaudio::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 5px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  transform: translateX(-50%);
  background: var(--color-gold);
}
.wp-root .wp-eaudio:hover { border-color: rgba(44, 44, 44, 0.85); box-shadow: 0 1px 2px rgba(44, 44, 44, 0.06); }
.wp-root .wp-eaudio.playing { border-color: var(--color-gold); color: #A8854B; }
.wp-egloss {
  font-size: 22px;
  line-height: 1.55;
  color: var(--color-ink);
  margin-top: 18px;
  max-width: 42ch;
}

/* 字 folded into the head — a single-kanji word has no "built from" section;
   its kanji's origin story hangs here off the gloss as one quiet tappable line
   into the kanji page. Mirrors the anat .astory voice; the gold arrow rests as
   the door cue and warms to indigo on intent. (owner 2026-06-16) */
.wp-root .wp-ji-head {
  display: block;
  margin-top: 18px;
  /* wide enough that a typical shape-story sits on ONE line (46ch wrapped even
     short ones to 2 rows — owner 2026-06-16); still within the gloss's box and
     a readable measure. text-wrap:pretty keeps any genuinely long story from
     leaving a stubby orphan last line. */
  max-width: 56ch;
  text-align: left;
  cursor: pointer;
}
.wp-ji-head .astory {
  font-size: 15px;
  line-height: 1.65;
  color: #44403c;
  text-wrap: pretty;
}
/* inline (not inline-block) so the arrow can never orphan onto its own line —
   with no whitespace before it, it stays glued to the last word; warms to
   indigo on intent (transform-shift dropped with inline-block). */
.wp-ji-head .astory .ago {
  display: inline;
  margin-left: 7px;
  font-size: 14px;
  color: var(--color-gold);
  transition: color 0.15s ease;
}
.wp-root .wp-ji-head:hover .astory .ago,
.wp-root .wp-ji-head:focus-visible .astory .ago { color: var(--color-accent); }

/* 字を照らす — inline Japanese inside English prose is DISPLAY type, not
   body type (the reading-room law: a beginner reads Japanese as pictures
   first; it was the smallest type on the page). Spans are minted by
   wrapJP() in grid-mode.js — text runs only, never markup. */
.wp-entry .wp-jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 500;
  font-size: 1.25em;
  color: var(--color-ink);
}
.wp-entry .wp-jp rt {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 400;
  font-size: 13px;
  color: var(--color-stone);
}

/* addressable headword kanji — the reveal wire (.lit: a 字 row under hover
   lights its character in the word above) and the homecoming glow
   (.lit-home: returning from the kanji room, the character settles from
   indigo back to ink — the first-word-I-ever-read moment) */
.wp-kch { transition: color 0.2s ease; }
.wp-kch.lit { color: var(--color-accent); }
@keyframes wpHomeGlow { from { color: var(--color-accent); } to { color: var(--color-ink); } }
.wp-kch.lit-home { animation: wpHomeGlow 1.4s ease-out 1; }

/* 字をたたく — a page-gated kanji met where the word is set large is its own
   door. Quiet, regime-safe affordance: every .wp-kt is a pointer, no movement
   anywhere (no transforms — kanji on this page REST, like the buttons). */
.wp-kt { cursor: pointer; }
/* THE HINT AT REST (owner 2026-06-12, round 2 — "the characters themselves
   should hint, dots add noise"): a live kanji wears a quiet indigo-leaning
   INK instead of plain sumi — the character itself is the affordance, in the
   page's interactive grammar (the reveal wire's indigo family). Hover/focus
   completes it to full indigo. No underlines, no marks, no movement. */
.wp-entry .wp-kt {
  transition: color 0.15s ease;
  color: color-mix(in srgb, var(--color-ink) 68%, var(--color-accent) 32%);
}
.wp-entry .wp-kt:hover,
.wp-entry .wp-kt:focus-visible { color: var(--color-accent); }
/* the focusable spans (role=button) miss the .wp-root button:focus-visible
   rule above — give them the page's standard keyboard ring directly. */
.wp-kt:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* GASAN (the inscription ON the art): deliberately NO rest tint — partially
   tinted characters would patchwork the one inscription, and the 落款 seals
   below already advertise these same kanji. The tap stays a quiet bonus:
   hover shifts the live kanji to the regime's interactive ink — the same
   indigo grammar the rest of the page speaks (owner 2026-06-16: drop the
   underline, align with the colour highlight below). Regime-aware so it never
   sinks into the art: full indigo on light paintings, a bright cool indigo on
   dark ones. The legibility halo carries over from --ink. */
.wp-gasan .wp-kt:hover {
  color: var(--ink-hover, #3D5A80);
}

/* ─── 字 BUILT FROM — the specimen monument. Each kanji of the headword
   set at display scale with its keyword, its reading in THIS word, its
   shape story's opening clause reprinted in place, and an honest door
   into the kanji room. Page-gated kanji are whole-row doors; keyword-only
   kanji rest as plain ink (no door, no pretense). */
.wp-anat { max-width: 660px; }
.wp-root .wp-anat-e {
  display: grid;
  grid-template-columns: 96px 1fr;
  column-gap: 18px;
  align-items: start;
  width: 100%;
  padding: 18px 0;
  text-align: left;
}
.wp-anat-e + .wp-anat-e { border-top: 1px solid rgba(44, 44, 44, 0.06); }
span.wp-anat-e { cursor: default; }
span.wp-anat-e.still { opacity: 0.8; }
.wp-anat-e .ak {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 72px;
  line-height: 1.05;
  color: var(--color-ink);
  transition: color 0.15s ease;
}
.wp-anat-e .atx {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 6px;
}
.wp-anat-e .akw {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-stone);
}
/* 字組み on the monument: the sense leads, the character's own range follows
   quietly, and a character carrying no meaning wears its keyword struck with
   the job named underneath. The hero mark had no room for that job text; this
   row does, which is the whole reason the two surfaces differ. */
.wp-anat-e .akw.snd {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--color-stone) 60%, transparent);
  opacity: 0.6;
}
.wp-anat-e .akwjob {
  font-size: 12.5px;
  color: rgba(87, 83, 78, 0.9);
}
.wp-anat-e .akwrest {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: rgba(87, 83, 78, 0.72);
}
.wp-anat-e .ard {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-stone);
}
.wp-anat-e .ard b {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--color-ink);
  margin-left: 7px;
  vertical-align: -0.12em;
}
.wp-anat-e .astory {
  font-size: 15px;
  line-height: 1.65;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: #44403c;
  margin-top: 2px;
}
.wp-anat-e .asim b,
.wp-anat-note b {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
}
.wp-anat-e .asim { font-size: 12.5px; color: rgba(87, 83, 78, 0.85); }
.wp-anat-e .asim .sj {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  margin-right: 7px;
  color: var(--color-stone);
}
/* the gold arrow ends the story teaser — "the story continues", which is
   literally what the tap delivers (the labelled door line + word count are
   retired; the count already opens the kanji room). Gold at rest = a real
   door; indigo on intent. */
.wp-anat-e .astory .ago {
  display: inline-block;
  margin-left: 9px;
  font-size: 14px;
  color: var(--color-gold);
  transition: transform 0.18s ease, color 0.15s ease;
}
button.wp-anat-e:hover .ak { color: var(--color-accent); }
button.wp-anat-e:hover .astory .ago {
  color: var(--color-accent);
  transform: translateX(3px);
}

/* ─── 字組み THE LINE — why the word wears these characters ───
   One sentence, ONE seat (desktop polish 2026-10-12): the 字 section, after
   the character rows. The rows explain the characters, then the line explains
   the word, so it spans the section's full measure under the hairline the
   rows already use, never indented under one character's text. A word that
   IS its one kanji has no 字 section (owner 2026-06-16) and sets the line in
   the head, after its folded 字 line, in that line's voice. About a third of
   covered words earn no line, and silence renders as nothing at all. */
.wp-root .wp-comp {
  position: relative;
  display: block;
  width: 100%;
  max-width: 660px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.65;
  text-align: left;
  color: #44403c;
  text-wrap: pretty;
}
.wp-root .wp-anat + .wp-comp {
  padding-top: 18px;
  border-top: 1px solid rgba(44, 44, 44, 0.06);
}
.wp-root .wp-ehead .wp-comp {
  max-width: 56ch;
  margin-top: 10px;
}
/* where the line had to skip a middle, it becomes the door to the note */
.wp-root .wp-comp.more { cursor: help; }
/* the 字 rows' gold arrow, reused: on this page it already means "the story
   continues", which is exactly what resting here delivers; indigo on intent,
   ink only (the arrow never moves) */
.wp-root .wp-comp .ago {
  margin-left: 7px;
  font-size: 14px;
  color: var(--color-gold);
  transition: color 0.15s ease;
}
.wp-root .wp-comp.more:hover .ago,
.wp-root .wp-comp.more:focus-visible .ago,
.wp-root .wp-comp.more[aria-expanded="true"] .ago { color: var(--color-accent); }
/* the note: a slip of washi laid on the page in the sentence glance's own dress
   (css/sentence-tokens.css .st-glance: lighter than the paper it lies on, no
   ring, one lifted shadow thrown a little left). Absolutely positioned under
   the line, so opening it never moves the line the pointer rests on. */
.wp-root .wp-comp-note {
  position: absolute;
  left: 0;
  top: calc(100% + 10px);
  z-index: 6;
  width: 360px;
  max-width: 100%;
  padding: 12px 16px 13px;
  border-radius: 3px;
  background: color-mix(in srgb, #FFFDF8 94%, var(--wp-tone, #b0a090) 6%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.65),
    0 1px 2px rgba(58, 46, 32, 0.05),
    -8px 16px 36px -8px rgba(58, 46, 32, 0.16);
  color: #44403c;
  font-size: 13.5px;
  line-height: 1.6;
  text-align: left;
  text-wrap: pretty;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.18s ease;
  pointer-events: none;
}
.wp-root .wp-comp.more:hover .wp-comp-note,
.wp-root .wp-comp.more:focus-visible .wp-comp-note,
.wp-root .wp-comp.more[aria-expanded="true"] .wp-comp-note {
  opacity: 1;
  visibility: visible;
}
@media (prefers-reduced-motion: reduce) {
  .wp-root .wp-comp-note { transition: none; }
}

/* section heads: ink kanji + placard caps. The hairline rules are gone —
   sections now close with a kasumi (霞) mist band of the painting's own
   tone, the emaki scene-break. */
.wp-sec { position: relative; margin-top: 88px; }
.wp-sec::before {
  content: '';
  position: absolute;
  top: -60px;
  left: -14%;
  right: -14%;
  height: 46px;
  pointer-events: none;
  background: linear-gradient(to bottom,
    transparent 0%,
    color-mix(in srgb, var(--wp-tone, #b0a090) 5%, transparent) 30%,
    color-mix(in srgb, var(--wp-tone, #b0a090) 8%, transparent) 52%,
    color-mix(in srgb, var(--wp-tone, #b0a090) 4%, transparent) 74%,
    transparent 100%);
  -webkit-mask-image: radial-gradient(120% 300% at 30% 46%, #000 22%, transparent 70%);
  mask-image: radial-gradient(120% 300% at 30% 46%, #000 22%, transparent 70%);
}
/* every band a differently-shaped cloud — mist, not a printed rule */
.wp-sec:nth-of-type(even)::before {
  -webkit-mask-image: radial-gradient(130% 260% at 64% 54%, #000 26%, transparent 74%);
  mask-image: radial-gradient(130% 260% at 64% 54%, #000 26%, transparent 74%);
  height: 40px;
  top: -56px;
}
.wp-sec:nth-of-type(3n)::before {
  -webkit-mask-image: radial-gradient(110% 320% at 44% 42%, #000 20%, transparent 66%);
  mask-image: radial-gradient(110% 320% at 44% 42%, #000 20%, transparent 66%);
}
.wp-sechead {
  display: flex;
  align-items: baseline;
  gap: 11px;
  margin-bottom: 15px;
}
.wp-ink {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 15px;
  color: var(--color-ink);
}
.wp-seclabel {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-stone);
}

/* story: ink directly on the tinted washi (the boxed card dissolved).
   ONE voice — the old 15.5px-lead / 14px-rest split is deleted; the whole
   story reads at reading scale. */
.wp-paper { padding: 0 2px; }
.wp-story-sec { display: flex; gap: 16px; padding: 21px 0; }
.wp-story-sec + .wp-story-sec { border-top: 1px solid rgba(44, 44, 44, 0.06); }
.wp-story-mark { flex: none; width: 60px; padding-top: 4px; }
.wp-story-mark .wp-ink { font-size: 16px; display: block; }
/* the story signed in its painting's pigment (cut-first candidate: revert
   this one rule to return the markers to pure sumi) */
.wp-story-mark .wp-ink { color: color-mix(in srgb, var(--color-ink) 86%, var(--wp-tone, #b0a090) 14%); }
.wp-story-mark .sub {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(87, 83, 78, 0.55);
  display: block;
  margin-top: 3px;
}
.wp-story-body { font-size: 16.5px; line-height: 1.85; color: #44403c; }

/* examples: furigana ruby on the washi itself (ruby-floor law: 13px) */
.wp-ex { padding: 17px 2px; }
.wp-ex + .wp-ex { border-top: 1px solid rgba(44, 44, 44, 0.07); }
.wp-ex-jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 24px;
  line-height: 2.0;
  color: var(--color-ink);
}
.wp-ex-jp rt {
  font-family: 'Noto Sans JP', sans-serif;
  font-size: 13px;
  color: var(--color-stone);
}
.wp-ex-ro {
  font-style: italic;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: rgba(87, 83, 78, 0.78);
  margin-top: 3px;
}
.wp-ex-en { font-size: 15px; line-height: 1.5; color: #44403c; margin-top: 5px; }

/* 訳 — the reader ASKS for the romaji + translation (owner 2026-08-02).
   Quiet by construction: it must read as an offer at the foot of the
   sentence, never as a button competing with it. Same ink and weight the
   direction switch already uses, so the 例 section keeps one control voice. */
.wp-root .wp-ex-ask {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 9px;
  padding: 2px 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-ui);
  color: rgba(87, 83, 78, 0.62);
  transition: color 160ms var(--ease-page);
}
.wp-root .wp-ex-ask:hover { color: var(--color-ink); }
/* THE [hidden] RESET (tests/css/hidden_reset_test.js). The `display` above is
   author origin and beats the UA's `[hidden]{display:none}` outright, so
   without this the spent offer stays painted — and stays clickable, and stays
   a tab stop — directly above the romaji + meaning it just revealed, captioning
   them. Sixth strike on this law; the guard names the fix. */
.wp-root .wp-ex-ask[hidden] { display: none; }
.wp-ex-ask-ink {
  font-family: 'Klee One', 'Noto Sans JP', serif;
  font-size: 14px;
  color: var(--color-indigo);
}
.wp-ex-ask-cap {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
/* the ten-character lesson that unlocks the whole vertical form — an
   italic whisper (the romaji voice) beside the section label, so it can
   never be mistaken for the control across the line */
.wp-ex-cue,
.wp-ex-tap {
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: rgba(120, 113, 108, 0.8);
  margin-left: 6px;
}
/* the two reading whispers ride the same slot, so they need a join — but only
   when the direction cue is actually standing. It is [hidden] the moment the
   learner picks the horizontal stack, and setExOrient() flips that live, so the
   dot has to be conditional in CSS rather than baked into either string. */
.wp-ex-cue:not([hidden]) + .wp-ex-tap { margin-left: -6px; }   /* 11px flex gap → 5px each side of the dot */
.wp-ex-cue:not([hidden]) + .wp-ex-tap::before {
  content: '·';
  margin: 0 5px 0 0;
  color: rgba(120, 113, 108, 0.55);
}
/* sechead tail: the direction switch alone at the right edge — the
   learner's remembered choice (kotoba_exOrient); it renders only when
   the vertical form actually fits. */
.wp-ex-tail {
  margin-left: auto;
  display: inline-flex;
  align-items: baseline;
}
.wp-ex-switch { display: inline-flex; align-items: baseline; gap: 7px; }
.wp-root .wp-ex-dir {
  background: none;
  border: none;
  padding: 1px 2px;
  font-family: 'Inter', sans-serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(120, 113, 108, 0.48);
  cursor: pointer;
}
.wp-root .wp-ex-dir:hover { color: var(--color-stone); }
.wp-root .wp-ex-dir.on { color: #44403c; cursor: default; }
.wp-ex-sep {
  font-size: 10px;
  color: rgba(120, 113, 108, 0.4);
}

/* tategaki (EMAKI): short sentences set as true vertical columns, read
   right to left, furigana riding each column; romaji + English foot each
   column horizontally. JS gates this on sentence length + viewport.
   ONE BASELINE, CENTRED (desktop polish 2026-10-12). The set is a grid of two
   shared rows: every column stands in row one, whose height is the longest
   column's, and every 訳 door in row two, so the doors share one line at the
   longest column's foot (each used to sit at its own column's foot: three
   sentences, three heights). The tracks are one fixed width, centred, with
   one gap, so two sentences no longer huddle at the right with the left half
   empty. A foot that opens takes its own door's seat, under its own column;
   it cannot re-centre the set (fixed tracks) or move another door (each door
   sits at the top of the shared row).
   The first sentence stands rightmost: the grid runs right to left and each
   column takes left-to-right back, since a vertical line under rtl would run
   bottom to top. */
.wp-ex-set.tategaki {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 192px;
  grid-template-rows: auto auto;
  justify-content: center;
  column-gap: 32px;
  row-gap: 28px;
  direction: rtl;
  padding-top: 10px;
}
.wp-ex-set.tategaki .wp-ex {
  direction: ltr;
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  justify-items: center;
  align-items: start;
  padding: 0;
  min-width: 0;
}
.wp-ex-set.tategaki .wp-ex + .wp-ex { border-top: none; }
.wp-ex-set.tategaki .wp-ex-jp {
  grid-row: 1;
  writing-mode: vertical-rl;
  max-height: 640px;
  font-size: 26px;
  line-height: 2.0;
  letter-spacing: 0.05em;
}
.wp-root .wp-ex-set.tategaki .wp-ex-ask { grid-row: 2; margin-top: 0; }
.wp-ex-set.tategaki .wp-ex-foot { grid-row: 2; width: 100%; text-align: center; }
.wp-ex-set.tategaki .wp-ex-ro { margin-top: 0; }

/* sechead tail: the 活用 fold — the same right-edge slot the 例 direction
   switch uses, and the same quiet voice. A caret plus plain English saying
   how much is folded away ("7 forms"), flipping to "hide" once open: the
   one line both opens and closes, so what was revealed can be put away. */
.wp-root .wp-fold {
  margin-left: auto;
  appearance: none;
  background: none;
  border: 0;
  padding: 3px 2px 3px 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 12px 'Inter', 'Noto Sans JP', sans-serif;
  letter-spacing: 0.02em;
  color: rgba(120, 113, 108, 0.9);
  cursor: pointer;
  transition: color 0.18s ease;
}
.wp-root .wp-fold:hover { color: var(--color-ink); }
.wp-fold-caret {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.18s ease;
}
/* an open fold points its caret back up — the line now offers the way closed */
.wp-root .wp-fold.is-open .wp-fold-caret { transform: rotate(180deg); }

/* 活用 FOLDED gives up its own room (desktop polish 2026-10-12). Closed, the
   section is one line that says "closed", and it kept a whole room for it:
   its own mist band and the full 88px of section air, about 200px of paper.
   Folded, it draws no band and sits 44px under the examples as a quiet row,
   their foot; the band of the section after it still opens the next scene.
   Opened, it is a full section again, band and 88px (setConjOpen keeps the
   row under the hand while the paper above gives way). The fold itself stays
   (owner ruling 2026-08-01). */
.wp-sec.wp-sec-conj.is-folded { margin-top: 44px; }
.wp-sec.wp-sec-conj.is-folded::before { display: none; }

/* ── ローマ字 on the word page: SHOWN ─────────────────────────────────────────
   Owner ruling 2026-08-06 round 7, closing six rounds of trying to hide it well.
   The reading MODE still decides what is PRINTED as Japanese; romaji is not that
   — it is the support beside it, and on a page the reader deliberately opened it
   simply shows.

   The concealment earned its keep on the WALL and nowhere else: ~21 romaji lines
   on screen at once, skimmed past without ever meeting a kana (css/grid-mode.css
   keeps that, with a hover to wake it). On a word page the hiding was paid for
   twice — a labelled control that changed its wording per mode, then the 音 chip,
   which works but which the owner could not find. A gesture nobody can find is
   worse than the crutch it replaced.

   So nothing here gates `.ro` any more. The one rule left is the placard's
   layout, and it is SCOPED TO ITS OWN MODIFIER because `.wp-romaji` is ALSO the
   kanji page's hero reading line (js/kanji-page.js heroReadingLine — kana, not
   romaji) and the kanji page's shell carries .wp-root, so every rule in this file
   reaches it. A bare `.wp-romaji { display: flex }` turned that line's inline `·`
   separators into flex items with a 10px gap either side. A container-scoped rule
   drifts BOTH ways: scope to what you OWN. */
.wp-romaji--ask { display: flex; align-items: baseline; gap: 10px; }

/* conjugation: ink table on the washi (box dissolved) */
.wp-conj { padding: 0 2px; }
/* [hidden] RESET LAW (tests/css/hidden_reset_test.js): the folded table is
   hidden through the attribute, so the component claims the reset itself —
   the day any rule gives .wp-conj a display, `hidden` must still bite. */
.wp-conj[hidden] { display: none; }
.wp-conj-row {
  display: grid;
  grid-template-columns: 122px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
}
.wp-conj-row + .wp-conj-row { border-top: 1px solid rgba(44, 44, 44, 0.05); }
.wp-conj-form .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--color-ink);
  display: block;
}
.wp-conj-form .en {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(87, 83, 78, 0.6);
  display: block;
  margin-top: 2px;
}
.wp-conj-kana {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 17.5px;
  color: var(--color-ink);
}
.wp-conj-kana .ro {
  font-style: italic;
  font-weight: 400;
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  color: rgba(87, 83, 78, 0.7);
  margin-left: 10px;
}
.wp-root .wp-conj-on {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 11px;
  color: rgba(87, 83, 78, 0.55);
  border: 1px solid rgba(44, 44, 44, 0.1);
  border-radius: 3px;
  padding: 2px 6px;
  background: rgba(250, 247, 239, 0.6);
}
.wp-root .wp-conj-on svg { width: 12px; height: 12px; display: block; }
.wp-root .wp-conj-on:hover { color: var(--color-ink); border-color: rgba(44, 44, 44, 0.25); }
.wp-root .wp-conj-on.playing { color: #A8854B; border-color: var(--color-gold); }

/* counter reference 数え方 — ink grid on the washi (box dissolved) */
.wp-cnt {
  padding: 0 2px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 44px;
}
.wp-cnt-cell {
  display: grid;
  grid-template-columns: 22px 64px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
}
.wp-cnt-cell:nth-child(n+3) { border-top: 1px solid rgba(44, 44, 44, 0.05); }
.wp-cnt-n {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: #6b6358;              /* the quiet ink: the 0.45 grey failed AA (panel builder, round 1) */
}
.wp-cnt-kanji {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 16px;
  color: var(--color-ink);
}
.wp-cnt-kana {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 14px;
  color: var(--color-stone);
}

/* ─── 礼 — register family: one meaning across politeness levels ───
   A quiet ladder sitting between 活用 (how the word bends) and 縁 (what is
   near in meaning): casual at the top, formal below. Each rung carries a
   plain-English role (the WHO) so a beginner reads the politeness choice at
   a glance. Ink on the washi, no boxes — the page's own voice. The current
   word is marked with a single gold rule (you-are-here); every other rung is
   a door to its card. */
.wp-reg-anchor {
  font-size: 13.5px;
  line-height: 1.5;
  color: rgba(87, 83, 78, 0.92);
  margin: -4px 2px 16px;
}
.wp-reg-ladder { padding: 0 2px; }
.wp-reg-rung {
  display: grid;
  grid-template-columns: 144px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
}
.wp-reg-rung + .wp-reg-rung { border-top: 1px solid rgba(44, 44, 44, 0.05); }
.wp-reg-role { min-width: 0; }
.wp-reg-role .tag {
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--color-ink);
  display: block;
}
.wp-reg-role .who {
  font-size: 11px;
  line-height: 1.35;
  color: rgba(87, 83, 78, 0.72);
  display: block;
  margin-top: 3px;
}
.wp-reg-word { min-width: 0; }
.wp-reg-word .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 19px;
  color: var(--color-ink);
}
.wp-reg-word .jp rt {
  font-family: 'Noto Sans JP', sans-serif;
  font-size: 13px;
  color: var(--color-stone);
}
.wp-reg-word .ro {
  font-style: italic;
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  color: rgba(87, 83, 78, 0.7);
  margin-left: 10px;
}
/* a member rung is a door to its card — same wire as the 縁 rows */
.wp-root .wp-reg-mem { position: relative; cursor: pointer; border-radius: 2px; }
.wp-root .wp-reg-mem:hover .jp { color: var(--color-accent); }
.wp-root .wp-reg-mem:hover .tag { color: var(--color-accent); }
.wp-root .wp-reg-mem:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* you-are-here: a single quiet ink rule, no colour — gold is earned-only on
   this page (the 凡例 crest a few lines below literally bans it), and
   wayfinding is not an achievement. The current rung is also not a link. */
.wp-reg-rung.is-current {
  border-left: 2px solid rgba(44, 44, 44, 0.28);
  padding-left: 16px;
  margin-left: -16px;
}
.wp-reg-rung.is-current + .wp-reg-rung { border-top: none; }
@media (max-width: 600px) {
  .wp-reg-rung {
    grid-template-columns: 1fr auto;
    gap: 4px 14px;
  }
  .wp-reg-role { grid-column: 1 / -1; }
  .wp-reg-role .who { display: inline; margin-top: 0; }
  .wp-reg-role .tag { display: inline; margin-right: 8px; }
}

/* ─── 縁 — 凡例 HANREI, the dictionary's legend ───
   Related words are dictionary lines under a fixed legend gutter: the
   relation kanji (対 alone in vermilion — scarcity) with a small-caps
   ENGLISH carrier beneath it. Text on PLAIN washi; the painting lives
   only in the fixed-size tone chip at the line's end. One continuous
   vertical margin rule is the only ruling — groups separate by air. */
.wp-dict { position: relative; }
.wp-dict::before {
  content: '';
  position: absolute;
  left: 68px;
  top: 4px;
  bottom: 4px;
  width: 1px;
  background: rgba(44, 44, 44, 0.10);
}
.wp-dict-g {
  display: grid;
  grid-template-columns: 68px 1fr;
  column-gap: 18px;
  padding: 18px 0;
  /* legend centers against its group — with the taller chips a top-pinned
     label floated above the words (owner round 1, 2026-06-12) */
  align-items: center;
}
.wp-dict-g:first-child { padding-top: 4px; }
/* the divider between subgroups (owner 2026-07-01): a soft rule that DISSOLVES
   at both ends into the washi — the page's own scrim language, never a hard
   table line. Inset from the spine and the right edge so it floats as a breath
   between groups, not a border ruled across them. */
.wp-dict-g { position: relative; }
.wp-dict-g:not(:first-child)::before {
  content: '';
  position: absolute;
  top: 0;
  left: 88px;
  right: 26px;
  height: 1px;
  background: linear-gradient(to right, transparent 0%,
    rgba(60, 53, 40, 0.15) 24%, rgba(60, 53, 40, 0.15) 76%, transparent 100%);
}
.wp-dict-m {
  text-align: right;
  padding-right: 14px;
}
.wp-dict-m .g {
  display: block;
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 15px;
  color: var(--color-ink);
}
.wp-dict-m .g.tai { color: var(--rel-opposite); } /* token holds this exact hex — no visible change */
.wp-dict-m .c {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--color-stone);
}
.wp-dict-list { min-width: 0; }
/* .wp-root needed: the .wp-root button reset (margin:0) outguns a bare
   > * + * — without it rows stack flush and a hover-grown chip lands on
   its neighbour (owner round 2: "images overlap when expanded") */
.wp-root .wp-dict-list > * + * { margin-top: 10px; }

/* a dictionary line */
.wp-root .wp-dict-e {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 48px;
  padding: 6px 0;
  text-align: left;
}
.wp-dict-tx { flex: 1; min-width: 0; display: block; }
.wp-dict-tx .l1 { display: block; }
.wp-dict-tx .lw {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 22px;
  color: var(--color-ink);
}
.wp-dict-e.soft .lw { font-weight: 500; }
.wp-dict-tx .lr {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 13px;
  color: var(--color-stone);
  margin-left: 9px;
}
.wp-dict-tx .l2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 2px;
  line-height: 1.45;
}
.wp-dict-tx .ro {
  font-size: 12px;
  font-weight: 500;
  font-style: italic;
  letter-spacing: 0.02em;
  color: #44403A;
}
.wp-dict-tx .dash { color: rgba(44, 44, 44, 0.35); margin: 0 6px; }
.wp-dict-tx .gl { font-size: 13px; color: #44403A; }
/* The tone chip — a held stamp, not a painting (owner refinement
   2026-06-12: "a bit larger" than the old 48×32, NOT a tile). Vars so
   size rounds are a one-line tweak. On hover/focus the chip micro-
   expands toward the text — a glance at the scene, never a reveal —
   then settles back. transform (not width) so rows never reflow. */
.wp-dict-chip {
  flex: none;
  margin-left: auto;
  width: var(--wp-relchip-w, 96px);
  height: var(--wp-relchip-h, 64px);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.10);
  transform-origin: right center;
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.wp-dict-chip img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* ── frame (meet-later) relation: a glossed word the corpus knows but hasn't
   been built into a full card yet. The painted cards carry the warmth; a frame
   has no picture, so it recedes as a lighter, text-only entry — an ABSENT
   painting is the signal, never an empty plate (which read as a broken image).
   The row is inert (rendered without role/tabindex/data-rel-pid, so the tap
   handlers skip it). The .wp-dict-chip span is still emitted but hidden here,
   so a future "whisper token" restyle is a one-rule change. ── */
.wp-root .wp-dict-e.is-frame { cursor: default; min-height: 40px; }
.wp-dict-chip.is-frame { display: none; }
.wp-root .wp-dict-e.is-frame .lw { font-weight: 500; color: #736c66; }
.wp-root .wp-dict-e.is-frame .lr { color: #9a938c; }
.wp-root .wp-dict-e.is-frame .ro,
.wp-root .wp-dict-e.is-frame .gl { color: #6f6862; }
.wp-root .wp-dict-e.is-frame:hover .lw { color: #736c66; }
/* the frequency chip at a row's right edge — the SAME honest scale as the kanji
   panel: a faint tabular #N, or a quiet uppercase "rare" past the 5-digit cliff,
   blank if unranked. Orientation for the learner, never the thing the eye lands
   on (so a common word stands out and a "rare" one quietly says "skip me"). */
.wp-dict-rank {
  flex: 0 0 auto;
  align-self: center;
  min-width: 46px;
  text-align: right;
  font: 600 10.5px 'Inter', 'Noto Sans JP', sans-serif;
  letter-spacing: 0.04em;
  color: #a49c94;
  font-variant-numeric: tabular-nums lining-nums;
}
.wp-dict-rank b { color: var(--color-stone); font-weight: 600; }
.wp-dict-rank.is-rare {
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: #8a827b;
}
.wp-root .wp-dict-e { position: relative; cursor: pointer; }
/* the row is a div[role=button] (hosts the nested 音 chip) — it misses the
   .wp-root button:focus-visible rule, so give it the standard ring here */
.wp-root .wp-dict-e:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* bare speaker — a universally read icon (the 音 kanji asked beginners
   to already know the word for sound); no chip frame (owner pick F) */
.wp-root .wp-dict-on {
  margin-left: 10px;
  padding: 2px;
  vertical-align: 1px;
  color: rgba(87, 83, 78, 0.55);
  transition: color 0.15s ease;
}
.wp-root .wp-dict-on svg { width: 14px; height: 14px; display: block; }
.wp-root .wp-dict-on:hover { color: var(--color-ink); }
.wp-root .wp-dict-on.playing { color: #A8854B; }
.wp-root .wp-dict-e:hover .lw { color: var(--color-accent); }
.wp-root .wp-dict-e:hover,
.wp-root .wp-dict-e:focus-visible { z-index: 2; }
/* grow 1.25 = the most the 76px row band + 10px row gap can host without
   the grown chip (or its shadow) reaching the neighbour's image (owner
   round 2). 1.5 overlapped. */
.wp-root .wp-dict-e:hover .wp-dict-chip,
.wp-root .wp-dict-e:focus-visible .wp-dict-chip {
  transform: scale(var(--wp-relchip-grow, 1.25));
  box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.10), 0 4px 12px rgba(44, 44, 44, 0.06);
}
/* a precise kanji door inside a 縁 row is its OWN target — pointing at it tints
   just that kanji (the .wp-entry .wp-kt indigo grammar) and CALMS the row so it
   stops reading as a whole-row highlight: the lemma's other glyphs hold their
   ink and the thumbnail stops growing. The hovered kanji keeps its indigo (a
   direct rule on the .wp-kt element beats this inherited .lw colour). The row's
   word-link affordance returns the instant the pointer leaves the kanji. (owner
   2026-06-16 — align related words with the example sentences' per-kanji doors;
   :has() is well-supported in the Chrome the app targets.) */
.wp-root .wp-dict-e:has(.wp-kt:hover) .lw { color: var(--color-ink); }
.wp-root .wp-dict-e:has(.wp-kt:hover) .wp-dict-chip {
  transform: none;
  box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.10);
}

/* (対 self-entry + ⇔ arrow retired 2026-06-12 — owner asked in every
   round: the vermilion 対 glyph + OPPOSITE carrier hold the meaning
   alone; you are already on this word's page.) */

/* (音/同 shared heads + member indents retired 2026-06-13 — every group
   now speaks the same self-contained two-row line: lemma + kana reading,
   then romaji — gloss.) */

/* ─── 陽だまり — the door to the word's graph room, now a chip on the
   painting beside the 音 chip (owner 2026-08-01). It used to be a washi
   slip at the 縁 section's foot, a full screen of scrolling away from the
   hand: a door at the bottom of a long entry is a door nobody opens.
   It wears the 音 chip's clothes exactly — washi disc, brushed sumi ring,
   the logo's gold dot — because the two are one set of quiet tools (hear
   it · open its room) sitting apart from the framed grade verbs. The only
   difference is the gallery card's warm-brown 陽: same weight, a hair
   warmer, never a glow (an amber sun-disc out-shouted the speaker on the
   card and was cut there in 2026-06; the same rule holds here).
   The MARK IS 陽 (yō, "sun"), the first character of the room's name,
   陽だまり, on every door into the room (desktop polish round 4, 14 October
   2026: the word doors wore 間 and the kanji doors 陽 until then). */
.wp-root .wp-crest {
  position: relative;
  appearance: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  background: #F7F2E6;
  border: 1.6px solid rgba(44, 44, 44, 0.72);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(44, 44, 44, 0.06);
}
.wp-root .wp-crest-sun {
  font-family: var(--font-jp, 'Klee One', cursive);
  font-weight: 600;
  font-size: 17px;
  line-height: 1;
  color: #6F5524;
  transition: filter 0.35s ease;
}
/* the brand seal's gold dot, in the same place it sits on the 音 chip */
.wp-root .wp-crest::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  transform: translateX(-50%);
  background: var(--color-gold);
}
/* the wake is the glyph warming, not a lift — cards rest, they don't float
   (the box-shadow restatement is load-bearing: .wp-root button:hover kills
   shadows, and this rule has to out-specify it) */
.wp-root .wp-crest:hover,
.wp-root .wp-crest:focus-visible { box-shadow: 0 2px 6px rgba(44, 44, 44, 0.10); }
.wp-root .wp-crest:hover .wp-crest-sun,
.wp-root .wp-crest:focus-visible .wp-crest-sun { filter: brightness(1.07) saturate(1.18); }
@media (max-width: 768px) { .wp-root .wp-crest { display: none; } }

/* ─── 細部 DETAIL — the sparse page's plate: the painting again, closer.
   One tight crop of the already-cached hero (no new requests), aimed at
   the zone with the most visual incident. Caption in plate-label caps. */
.wp-plate-im {
  height: 300px;
  border-radius: 2px;
  background-size: 260%;
  background-color: var(--wp-tone, #b0a090);
  box-shadow: inset 0 0 0 1px rgba(44, 44, 44, 0.10);
}
.wp-plate-cap {
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: 9px;
  margin-top: 9px;
}
.wp-plate-cap .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: #44403a;
}
.wp-plate-cap .cap {
  font-size: 9px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #8d877b;
}

/* colophon 奥付 */
.wp-colo {
  margin-top: 58px;
  padding-top: 20px;
  border-top: 1px solid rgba(44, 44, 44, 0.11);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
}
.wp-colo-lines {
  font-size: 10.5px;
  font-weight: 500;
  line-height: 2.1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(87, 83, 78, 0.78);
}
.wp-colo-lines .dim { color: rgba(87, 83, 78, 0.5); }
.wp-coloseal {
  flex: none;
  width: 38px;
  height: 38px;
  border: 1.5px solid rgba(44, 44, 44, 0.22);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-weight: 600;
  font-size: 16px;
  color: rgba(44, 44, 44, 0.35);
  transform: rotate(-4deg);
}
.wp-coloseal.known { border-color: var(--color-gold); color: var(--color-gold); }

/* 白紙 — the deliberate way back to New (the only unmark since the claims
   law retired the grade-button toggle, owner 2026-07-14). A quiet dotted
   line in the colophon's own meta voice; arming warms it amber. */
.wp-restart-line { margin-top: 4px; }
.wp-restart {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: rgba(87, 83, 78, 0.55);
  border-bottom: 1px dotted rgba(87, 83, 78, 0.35);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.wp-restart:hover,
.wp-restart:focus-visible,
.wp-restart[data-armed="1"] {
  color: var(--color-amber-deep, #8A6E35);
  border-bottom-color: currentColor;
}
.wp-restart-line.wp-restart-done { color: rgba(87, 83, 78, 0.78); text-transform: none; }
.wp-restart-undo {
  background: none;
  border: 0;
  padding: 0;
  margin-left: 10px;
  cursor: pointer;
  font: inherit;
  color: var(--color-accent, #3D5A80);
  border-bottom: 1px solid currentColor;
}

/* 息 — a same-state claim answers with one quiet breath on the lit verb
   (nothing changed, nothing written; claims law, owner 2026-07-14) */
.wp-verb.verb-affirm { animation: verb-affirm-breath 0.55s ease-out; }
@keyframes verb-affirm-breath {
  0%   { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); }
  40%  { box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 22%, transparent); }
  100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .wp-verb.verb-affirm { animation: none; }
}

/* ─── 襖 fusuma — a hop slides the room sideways instead of teleporting.
   The outgoing page keeps .wp-root (its styles) but loses the id; both
   animate as solid rooms, transform-only. Order matters: these rules sit
   AFTER .wp-noarrive so the incoming slide wins the animation slot. */
@keyframes wpFusumaOutLeft  { to { transform: translateX(-9%); opacity: 0.22; } }
@keyframes wpFusumaOutRight { to { transform: translateX(9%);  opacity: 0.22; } }
@keyframes wpFusumaInRight  { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes wpFusumaInLeft   { from { transform: translateX(-100%); } to { transform: translateX(0); } }
.wp-root.wp-fusuma-out-left  { animation: wpFusumaOutLeft 0.42s cubic-bezier(0.33, 0, 0.2, 1) forwards; z-index: 8999; pointer-events: none; }
.wp-root.wp-fusuma-out-right { animation: wpFusumaOutRight 0.42s cubic-bezier(0.33, 0, 0.2, 1) forwards; z-index: 8999; pointer-events: none; }
.wp-root.wp-fusuma-in-right  { animation: wpFusumaInRight 0.42s cubic-bezier(0.33, 0, 0.2, 1); }
.wp-root.wp-fusuma-in-left   { animation: wpFusumaInLeft 0.42s cubic-bezier(0.33, 0, 0.2, 1); }

/* narrower desktops: the placard and gasan breathe in */
@media (max-width: 1200px) {
  .wp-placard { left: 40px; right: 40px; bottom: 56px; }
  .wp-gasan { right: 44px; }
  .wp-gloss { font-size: 24px; }
  .wp-stones { left: 150px; }
}

/* the narrow-desktop band (iPad portrait lives here at 820): the placard's
   left column shares one row with the kanji doors on its right, and a
   three-kanji word leaves the action row about 50px short. The row buys that
   back by breathing in — tighter gaps, tighter verb padding — instead of
   letting anything break or drop. Measured at 800/820/850 on 可能性 /
   日本語 / 自転車 / 小学校 (the three-door worst case). */
@media (max-width: 900px) {
  .wp-acts, .wp-verbs { gap: 14px; }
  .wp-chips { gap: 8px; }
  .wp-root .wp-verb { padding: 11px 15px 12px; gap: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .wp-root { animation: none; }
  .wp-root * { transition: none !important; animation: none !important; }
  /* belt-and-braces: JS never adds .wp-kigo under reduced motion, but if
     the class ever appears its opacity:0 bases must not hide the word —
     nor the rakkan marks waiting on their press-in delays */
  .wp-kigo .wp-gu,
  .wp-kigo .wp-gu rt { opacity: 1 !important; }
  .wp-kigo .wp-rakkan,
  .wp-kigo .wp-kdoor { opacity: 1 !important; animation: none !important; }
}

/* ── 単語帳 THE COURSE PROFILE (the owner's item 8, 19 October 2026; js/grid-mode.js buildHTML's course arm) ──────────
   The app's full word page over a word of the course's flashcards: the course portrait, the course's story, sentences,
   forms, 字 rows and related words. The portrait is a square painted on bare paper, so the stage is that paper and the
   portrait rests whole between the way home and the placard, never cropped under them (the app's painting is a scene
   that bleeds to the edges; this one is an object on a sheet). */
.wp-root.wp-course { background: #FCFAF2; }
.wp-course .wp-paint {
  inset: 64px 0 188px 0;
  width: 100%;
  height: calc(100% - 252px);
  object-fit: contain;
  object-position: center;
}
/* ⭐ THE DESIGN ELEVATION, STEPS 1 AND 2 (1 November 2026; css/course-lesson.css #kotobaLesson says the palette), ON THE
   COURSE'S OWN PAGES (this word page and css/kanji-page.css .kjp-course): ONE PAPER. The stage is the rooms' 白練
   (shironeri) #FCFAF2 and the sheet that rises over it a slip, 胡粉 (gofun) #FFFFFB, lighter than the page and told by a
   light shadow (the app's 0.30 fall was the heaviest shadow in the course); the painting sits on the house's one lift and
   multiply, as every room seats it, so no paper square shows round it. The page re-points the app's inks for its
   lifetime (the hall's own word page keeps them): the sumi #2A231F for the Japanese and the cold #2C2C2C both, the stone
   and the one quiet ink; the light regime prints its ink, its dim and its faint opaque (sumi, stone, quiet: no fade), and
   its reading line in the quiet ink (the gold #A8854B printed 2.84:1). */
.wp-root.wp-course, .wp-root.kjp-course {
  --color-ink: #2A231F;
  --color-jp-text: #2A231F;
  --color-stone: #514A44;
  --color-faint: #69625A;
  --color-faint-warm: #69625A;
}
.wp-root.wp-course .wp-rg-light, .wp-root.kjp-course .wp-rg-light {
  --ink: #2A231F;
  --inkdim: #514A44;
  --inkfaint: #69625A;
  --romaji-ink: #69625A;
  --halo: 0 0 18px rgba(255, 255, 251, 0.78), 0 0 3px rgba(255, 255, 251, 0.5);
}
.wp-root.wp-course .wp-paint, .wp-root.kjp-course .wp-paint { filter: url(#cl-washi); mix-blend-mode: multiply; }
.wp-root.wp-course .wp-sheet, .wp-root.kjp-course .wp-sheet { box-shadow: 0 -8px 28px rgba(42, 35, 31, 0.10), 0 -1px 3px rgba(42, 35, 31, 0.05); }
.wp-root.wp-course .wp-cue .jp, .wp-root.kjp-course .wp-cue .jp { color: var(--color-jp-text); }
.wp-root.wp-course .wp-cue .cap, .wp-root.kjp-course .wp-cue .cap { color: var(--color-faint-warm); }   /* 続き MORE: 3.31 → 5.99:1 on the slip */
/* the sentence's own clip, beside its line; the word's own seat in it underlined; a taught word a press to its page */
.wp-course .wp-ex-line { display: flex; align-items: center; gap: 14px; }
.wp-course .wp-ex-line .wp-ex-jp { flex: 1 1 auto; min-width: 0; }
.wp-root .wp-ex-hear {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #F7F2E6;
  border: 1.2px solid rgba(44, 44, 44, 0.42);
  color: var(--color-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.wp-root .wp-ex-hear svg { width: 13px; height: 13px; display: block; }
.wp-root .wp-ex-hear::before { content: ''; position: absolute; inset: -7px; border-radius: 50%; }
.wp-root .wp-ex-hear:focus-visible { border-radius: 50%; outline-offset: 2px; }
.wp-course .wp-ex-own { box-shadow: inset 0 -1px 0 rgba(61, 90, 128, 0.55); }
/* a line read in a homework piece names its piece under it, quiet, as the side panel's 読み物 Texts read · place (the
   owner, 20 October 2026); the kanji in the JP face, the rest a micro-label */
.wp-course .wp-ex-src {
    display: flex;
    align-items: baseline;
    gap: 0.5em;
    margin-top: 6px;
    font-size: 11px;
    line-height: 1.4;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-stone, #8A8580);
}
.wp-course .wp-ex-src [lang="ja"] { font-family: var(--font-jp, 'Klee One', serif); font-size: 12px; letter-spacing: 0.02em; text-transform: none; }
.wp-course .wp-ex-w {
  color: var(--color-indigo, #3D5A80);
  cursor: pointer;
  border-radius: 3px;
  box-shadow: inset 0 -1px 0 rgba(61, 90, 128, 0.22);
  transition: background-color 160ms ease;
}
.wp-course .wp-ex-w:hover { background-color: rgba(61, 90, 128, 0.07); }
.wp-course .wp-ex-w:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }
/* a form as the course writes it, its kana after it in the quiet voice (never romaji) */
.wp-course .wp-conj-r {
  font-size: 13px;
  color: var(--color-faint-warm);   /* the quiet ink, opaque (the elevation: was the stone at 75 per cent) */
  margin-left: 12px;
}
/* a related word's chip is the course's square portrait */
.wp-course .wp-dict-chip img { object-fit: cover; }
/* ⭐ THE DESIGN ELEVATION, THE REVIEW ROUND (1 November 2026): BELOW THE FOLD. The step's proofs stopped at the fold, and under
   it the course's own word and kanji pages still faded: their readings at base.css's 0.55 (こんしゅう over 今週 and いそが over
   忙 printed 2.74:1 on the slip), the 英語 English ask at 62 per cent, the colophon at 78 and 50, the seal 言 at 35, and the
   sticky way home's captions in the app's faint #8d877b (3.56:1). Under the course's scopes alone (the hall's own page keeps
   its fades): every reading opaque, in the one quiet ink where the page named the stone (the reading over the painting keeps
   its own ink and halo); the ask in the quiet ink, the ink under the hand; the colophon a step apart in two opaque inks, the
   stone and the quiet; the seal in the quiet ink on a sumi ring; the run's captions and its reading in the quiet ink. */
.wp-root.wp-course rt,
.wp-root.kjp-course rt { opacity: 1; }
.wp-root.wp-course .wp-eword rt,
.wp-root.wp-course .wp-entry .wp-jp rt,
.wp-root.wp-course .wp-ex-jp rt,
.wp-root.wp-course .wp-reg-word .jp rt { color: var(--color-faint-warm); }
.wp-root.wp-course .wp-ex-ask { color: var(--color-faint-warm); }
.wp-root.wp-course .wp-ex-ask:hover { color: var(--color-ink); }
.wp-root.wp-course .wp-colo-lines { color: var(--color-stone); }
.wp-root.wp-course .wp-colo-lines .dim { color: var(--color-faint-warm); }
.wp-root.wp-course .wp-coloseal:not(.known) { color: var(--color-faint-warm); border-color: rgba(42, 35, 31, 0.22); }
.wp-root.wp-course .wp-run .wp-rback .cap,
.wp-root.kjp-course .wp-run .wp-rback .cap,
.wp-root.wp-course .wp-run .wp-rcap,
.wp-root.kjp-course .wp-run .wp-rcap,
.wp-root.wp-course .wp-run .wp-rword .r,
.wp-root.kjp-course .wp-run .wp-rword .r { color: var(--color-faint-warm); }
.wp-root.wp-course .wp-run .wp-rback:hover .cap,
.wp-root.kjp-course .wp-run .wp-rback:hover .cap { color: var(--color-stone); }
/* (the shelf on the new paper, 1 November 2026) the story's 文化 CULTURE caption, opaque in the quiet ink (55 per cent of the
   stone printed 2.59:1 on the slip); and the trail's stones: every course word's tone is the paper now, so a stone would
   vanish on the slip: a pebble of the quiet ink, 3:1, the current one ringed as ever */
.wp-root.wp-course .wp-story-mark .sub { color: var(--color-faint-warm); }
.wp-root.wp-course .wp-stone { background: color-mix(in srgb, var(--color-faint-warm) 70%, transparent); }
/* the optional お's brackets and the press that opens a word's forms, opaque in the quiet ink (base.css's 0.58 printed 3.94:1, the
   fold's #78716C at 90 per cent 3.93:1) */
.wp-root.wp-course .opt-mark,
.wp-root.kjp-course .opt-mark { opacity: 1; color: var(--color-faint-warm); }
.wp-root.wp-course .wp-fold { opacity: 1; color: var(--color-faint-warm); }
.wp-root.wp-course .wp-fold:hover { color: var(--color-ink); }
/* ⭐ (the shelf on the new paper) ON THE PIXEL, at 1x: Klee One 400 at 13 and 14 px never reaches its ink (3.5 to 4.2:1, the darkest
   pixel of the stroke), so a course page's small readings and kana-duets take the weight every small reading of the lesson and
   the card already wears, as the wall's and the kanji page's did (STEP12 finding 11); kana are full-width, nothing moves */
.wp-root.wp-course .wp-ex-jp rt,
.wp-root.wp-course .wp-story-body rt,
.wp-root.wp-course .wp-ex-ask-ink,
.wp-root.wp-course .wp-via [lang="ja"] { font-weight: 600; }
.wp-root.wp-course .wp-via { color: var(--color-stone); }
.wp-root.wp-course .wp-via:hover { color: var(--color-ink); }
/* the arrow a word's kanji row points on with: the app's gold printed 2.23:1 on the slip */
.wp-root.wp-course .ago { color: var(--color-faint-warm); }
/* a course row ends on its lone arrow (no story teaser before it), so the arrow stands flush with the row's text: the app's 9 px,
   the margin it keeps after its teaser, set it in alone and read as a misalignment */
.wp-root.wp-course .wp-anat-e .astory .ago { margin-left: 0; }
/* a Japanese word inside the story's English stays whole, as on the card (病|院 and its reading split across two lines on 27 of the
   184 pages); the English still wraps, and a run too long for its line may still break rather than leave the sheet */
.wp-root.wp-course .wp-story-body { word-break: keep-all; overflow-wrap: anywhere; }
