/* =============================================================================
   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;
}

/* ─── 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. */
.wp-altw {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin: -4px 0 11px;
  text-shadow: var(--halo);
}
.wp-altw .cap {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--inkdim);
}
.wp-altw .jp {
  font-family: var(--font-jp, 'Klee One'), sans-serif;
  font-size: 17px;
  color: var(--ink);
}
.wp-altw .freq {
  font-size: 11px;
  font-style: italic;
  color: var(--inkdim);
}
.wp-altk {
  appearance: none;
  border: none;
  background: none;
  padding: 0 1px;
  margin: 0;
  font: inherit;
  color: var(--indigo, #3D5A80);
  cursor: pointer;
  border-bottom: 1px solid color-mix(in srgb, var(--indigo, #3D5A80) 35%, transparent);
  transition: border-color 0.15s ease;
}
.wp-altk:hover { border-bottom-color: var(--indigo, #3D5A80); }
.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;
}
/* 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);
}
.wp-verb .cap { font-size: 12px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; }
.wp-verb .jp {
  font-family: 'Klee One', 'Noto Sans JP', sans-serif;
  font-size: 15px;
  color: var(--inkdim);
}
/* 残響 — 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). */
.wp-plright {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 14px;
  margin-left: 32px;
}
.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;
}
.wp-rakkan .kc,
.wp-kdoor .kc {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--inkdim);
  max-width: 88px;
  overflow: hidden;
  text-overflow: ellipsis;
  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);
}
.wp-root .wp-rakkan:hover,
.wp-root .wp-kdoor:hover { transform: translateY(-1px); }
.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); }

/* 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; }
  .wp-rakkan .kc { max-width: 72px; }
}

/* 揮毫 — 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);
}
.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);
}

/* 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 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 {
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: rgba(120, 113, 108, 0.8);
  margin-left: 6px;
}
/* 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. */
.wp-ex-set.tategaki {
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-start;
  align-items: stretch;       /* equal heights → feet share one baseline */
  gap: 72px;
  padding-top: 10px;
}
.wp-ex-set.tategaki .wp-ex {
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  min-width: 0;
}
.wp-ex-set.tategaki .wp-ex-foot { margin-top: auto; }
.wp-ex-set.tategaki .wp-ex + .wp-ex { border-top: none; }
.wp-ex-set.tategaki .wp-ex-jp {
  writing-mode: vertical-rl;
  max-height: 640px;
  font-size: 26px;
  line-height: 2.0;
  letter-spacing: 0.05em;
}
.wp-ex-set.tategaki .wp-ex-foot { max-width: 200px; text-align: center; }
.wp-ex-set.tategaki .wp-ex-ro { margin-top: 0; }

/* conjugation: ink table on the washi (box dissolved) */
.wp-conj { padding: 0 2px; }
.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: rgba(87, 83, 78, 0.45);
}
.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.) */

/* ─── 陽だまり CREST — the door to the word's graph room, at the related
   section's foot (triptych S3). A washi slip holding a small pool of
   sunlight: warm light tones only — no relation hues out here (the dose
   rule), no red (seals are the kanji's), no gold (nothing is earned).
   Hover warms the light; the hover is also the module's preload. */
.wp-root .wp-crest {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  margin-top: 14px;
  padding: 11px 14px;
  background: linear-gradient(174deg, rgba(255, 253, 246, 0.85), rgba(250, 244, 230, 0.75));
  border: 1px solid rgba(126, 100, 58, 0.16);
  border-radius: 3px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.wp-root .wp-crest:hover,
.wp-root .wp-crest:focus-visible {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(96, 72, 36, 0.08), 0 10px 24px rgba(96, 72, 36, 0.10);
}
.wp-root .wp-crest-sun {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: radial-gradient(closest-side, #FFEEBC 0%, rgba(255, 238, 188, 0.45) 62%, rgba(255, 238, 188, 0) 100%);
  font-family: var(--font-jp, 'Klee One', cursive);
  font-weight: 600;
  font-size: 17px;
  color: #8A6E35;
  transition: filter 0.35s ease;
}
.wp-root .wp-crest:hover .wp-crest-sun,
.wp-root .wp-crest:focus-visible .wp-crest-sun {
  filter: brightness(1.06) saturate(1.15);
}
.wp-root .wp-crest-tx { flex: 1; min-width: 0; }
.wp-root .wp-crest-tx .l1 {
  display: flex;
  align-items: baseline;
  gap: 9px;
}
.wp-root .wp-crest-tx .l1 [lang="ja"] {
  font-family: var(--font-jp, 'Klee One', cursive);
  font-weight: 600;
  font-size: 14px;
  color: var(--color-sumi, #2C2C2C);
}
.wp-root .wp-crest-tx .l1 .cap {
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #a3957c;
}
.wp-root .wp-crest-tx .l2 {
  display: block;
  margin-top: 3px;
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: #8d8069;
}
.wp-root .wp-crest-go {
  flex: 0 0 auto;
  font-size: 13px;
  color: #b0552f;
  transition: transform 0.25s ease;
}
.wp-root .wp-crest:hover .wp-crest-go,
.wp-root .wp-crest:focus-visible .wp-crest-go {
  transform: translateX(3px);
}
@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; }
}

@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; }
}
