/* ==========================================================================
   Kanji Page — 漢字 the character's own room (kanji layer, second dress)
   The SECOND ROOM OF THE SAME MUSEUM: a right-anchored washi sheet soaked
   in the origin word's pigment (--kjp-tone, set per open by kanji-page.js),
   opened by a painting band — a close crop of the very painting the reader
   was just inside. Sections sit as ink on the washi (the word page's
   grammar); the watch-out keeps its earned gold card, the twin pair keeps
   its specimen tray. Slides in as a fusuma, like every door in the house.
   Palette = 和の感性 tokens: washi #FAF7EF · ink #2C2C2C (warmed in-panel to
   --kjp-ink #3A3633) · warm stone #57534e · indigo #3D5A80 · kintsugi gold #C9A96E.
   ========================================================================== */

/* the --kjp palette is hosted on BOTH roots that carry kanji content: the
   kanji page/drawer overlay itself, and the word panel's embedded full glance
   (.wpn-kbody — universal tap 2b), whose subtree renders the same spine via
   KanjiPage.embedBody. One palette, two hosts; --kjp-tone is set per-open by
   kanji-page.js on the overlay and per-render by word-panel.js on the kbody. */
.kjp-overlay,
.wpn-kbody,
.kw-brush-host {  /* the walk's borrowed writing block (KR2) shares the palette */
    /* Warm sumi for the panel's STRUCTURAL ink — the named things the eye lands
       on first (hero glyph, reading names, word lemmas, section labels, the
       kun'yomi/on'yomi term). A hair deeper than the prose #44403c so headings
       still outweigh body, and warm (R>G>B) so it sits on the washi instead of
       the cold neutral #2C2C2C that read as "plastic" beside the word page. */
    --kjp-ink: #3A3633;
    /* Warm hairline for the dividers/borders — re-tinted off the cold neutral so a
       "warm" panel doesn't still read clinical (fleet restraint watch-out). */
    --kjp-rule: rgba(64, 53, 40, 0.11);
    /* one group-break rhythm shared by the readings list + the sound family, so the
       three lists (readings / 声符 / 意符) pulse the same (owner consistency ask,
       2026-06-29). Tight, in the direction the owner already trended the gaps. */
    --kjw-grp-gap: 12px;

    /* integrate-hero-v2 palette (the won design). Warm sumi only — NEVER #000.
       Indigo reserved for meaning (readings / prove-the-reading), gold scarcity-
       gated. The sheet tone (--kjp-tone) is set per-open by kanji-page.js. */
    --kjp-ink-wet: #2f2b28;       /* the brush's wet tip — a momentary deepening */
    --kjp-prose: #44403c;         /* body prose */
    --kjp-stone: var(--color-stone);         /* secondary text */
    --kjp-ghost: #8c857b;         /* faint / operators (clears AA on the sheet) */
    --kjp-ghost-soft: #b3aca3;    /* hairline-weight accents only */
    --kjp-indigo: var(--color-accent);        /* teaching accent · prove-the-reading · the key */
    --kjp-gold: var(--color-gold);          /* kintsugi — earned only */
    --kjp-gold-deep: #8a6e35;     /* gold legible AS small type on washi */
    --kjp-paper: #FAF7EF;         /* the raw drawer washi */
    /* the drawer sheet = paper soaked 7% in the painting's tone (the app formula);
       used by the step-mode recede mix + the band fade-to-sheet. */
    --kjp-sheet: color-mix(in srgb, #FAF7EF 93%, var(--kjp-tone, #b0a090) 7%);
    --kjp-jp: 'Klee One', 'Noto Sans JP', serif;
    --kjp-ui: 'Inter', 'Noto Sans JP', system-ui, sans-serif;
    /* the scholar note's ONE earned non-sumi accent: a hand-pressed hanko red.
       Spent exactly once, on the 由来 cue seal (scarcity = "this is precious"). */
    --kjp-seal: #9e3b2c;
    --kjp-seal-deep: #76271c;
}
.kjp-overlay {
    position: fixed;
    inset: 0;
    z-index: 9100; /* above the 図録 word page overlay (word-page.css: 9000) */
    display: none;
    /* the whole page fades in/out (driven by .kjp-in on the root, added on rAF by
       open() and removed on close) — the word-page frame's own wpArrive is killed
       below so the two entrances never double up. */
    opacity: 0;
    transition: opacity 0.32s ease;
}
body.kanji-page-open .kjp-overlay { display: block; }
/* full-screen page: lock the surface underneath (word page / wall) the way the
   word page does (body.wp-open), so only the kanji page scrolls. */
body.kanji-page-open { overflow: hidden; }
/* the slide-OUT close: the overlay must stay painted one beat longer than the
   kanji-page-open class (which would display:none it in the same frame, so the
   sheet used to teleport away). .kjp-out keeps it visible + click-through (the room
   beneath is live) until the sheet finishes its exit transition, then JS clears it. */
.kjp-overlay.kjp-out { display: block; pointer-events: none; }

/* THE PILL/LIFT MUST DIE HERE — same trap word-page.css fights (lines 49-67):
   components.css paints every bare <button> as a floating white pill with a
   12px radius, a drop shadow, and a translateY(-2px) hover lift + glow
   (components.css:390). That lift is the "buttons shake on hover" the owner
   saw — the kanji overlay's buttons (.kjw-row, .kjr-more, .kjp-back,
   .kjp-part--door, .kjt-cell--twin) inherited it because this sheet, unlike
   the word page, had no scoped reset. Buttons in this room REST. Each button
   class re-states its intended look AFTER this reset in the cascade below. */
.kjp-overlay button {
    appearance: none;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    padding: 0;
    margin: 0;
}
.kjp-overlay button:hover,
.kjp-overlay button:active {
    transform: none;
    box-shadow: none;
}

/* the dimming behind the panel — the scrim drinks the tone. Kept TRANSLUCENT so
   the room the panel rose from (the word page, or the wall) stays visible beside
   it: a room next to the room, never a blackout. Only the .kjp-* drawer + the
   family side panel use this now; the full page dims with its own .wp-scrim.
   A click on the field's margins closes the panel, like clicking outside it. */
.kjp-scrim {
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, rgba(44, 44, 44, 0.42) 88%, var(--kjp-tone, #b0a090) 12%);
    opacity: 0;
    transition: opacity 0.28s ease;
}
.kjp-overlay.kjp-in .kjp-scrim { opacity: 1; }

/* the panel: a right-anchored washi sheet soaked in the origin word's pigment,
   sliding in as a fusuma from the edge. The room it rose from stays visible at
   the left through the translucent scrim — a room beside the room, not a modal
   blackout. The washi is the app's formula: paper soaked 7% in the tone. */
.kjp-sheet {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: auto;
    width: min(760px, 64vw);
    display: flex;
    flex-direction: column;
    background: color-mix(in srgb, #FAF7EF 93%, var(--kjp-tone, #b0a090) 7%);
    border-left: 1px solid var(--kjp-rule);
    box-shadow: -14px 0 40px rgba(15, 11, 7, 0.25);
    opacity: 0;
    transform: translateX(40px);
    transition: opacity 0.32s ease, transform 0.42s cubic-bezier(0.33, 0, 0.2, 1);
}
.kjp-overlay.kjp-in .kjp-sheet { opacity: 1; transform: translateX(0); }

/* the 声符/意符 family SIDE PANEL rides one layer up (above the full page at
   z 9100), so it stacks over the very page whose pill was tapped. It reuses this
   whole .kjp-* drawer dress; only its stacking order differs. */
.kjp-overlay.kjp-aside { z-index: 9200; }

/* 和紙 — the same paper as the word page / gallery / journey: one faint
   fractalNoise wash so the reading area reads as washi, not flat plastic. Copied
   verbatim from the app's shared grain (grid-mode.css). The painting band
   full-bleeds OVER it (content sits at z-index 1), so grain shows only where the
   eye actually rests — the reading lists, not the picture. */
.kjp-sheet::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: 0.05;
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 0;
}
/* the bar + scrolling body ride above the grain */
.kjp-bar, .kjp-body { position: relative; z-index: 1; }

/* ── top bar ──────────────────────────────────────────────────────────── */

/* the bar is no longer a toolbar strip — just a single quiet back-chevron
   floating at the top-left over the washi, so nothing competes with the glyph
   (no hairline, no stroke-count pill, no destination label). */
.kjp-bar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    padding: 12px 12px 0;
}
.kjp-back {
    appearance: none;
    background: none;
    border: 0;
    width: 36px;
    height: 36px;
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--kjp-ink);
    transition: background-color 0.18s ease;
}
.kjp-back:hover { background: rgba(58, 54, 51, 0.05); }   /* warm sumi, not cold neutral */
.kjp-back svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.kjp-sheet:focus { outline: none; }
.kjp-sheet:focus-visible { outline: none; }
/* (.kjp-bar-label + .kjp-bar-seal rules removed 2026-06-27 — the bar is intentionally
   a bare back-chevron (see .kjp-bar above); neither element was ever in the markup.) */

/* ── scrolling body ───────────────────────────────────────────────────── */

.kjp-body {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 0 28px 64px;
    color: var(--kjp-ink);
    font-family: 'Inter', 'Noto Sans JP', sans-serif;
}

/* 字を照らす — the word page's inline-JP law, shared: Japanese in prose
   is display Klee (spans minted by kanji-page.js wrapJP, text runs only) */
.kjp-body .wp-jp,
.wpn-kbody .wp-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 1.25em;
    color: var(--kjp-ink);
}

/* a faint tone wash bridges the top glyph zone and the painting's mount halo so
   the page reads as one continuously-toned washi surface (mockup O10). */
.kjp-body::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 680px;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(120% 64% at 56% -4%,
            color-mix(in srgb, var(--kjp-tone, #b0a090) 16%, transparent) 0%,
            color-mix(in srgb, var(--kjp-tone, #b0a090) 6%, transparent) 34%,
            transparent 64%),
        radial-gradient(90% 30% at 50% 56%,
            color-mix(in srgb, var(--kjp-tone, #b0a090) 5%, transparent) 0%,
            transparent 70%);
}
.kjp-body > * { position: relative; z-index: 1; }

/* ── the painting band — you are still inside the picture (band-on only) ──
   In v2 the band is a thin crop ABOVE the writing hero (the hero glyph no longer
   sits inside it). When window._wpKanjiBand === false the band is simply absent
   and the hero opens straight onto the bare-washi axis. */
.kjp-band--withhero {
    position: relative;
    height: 150px;
    margin: 0 -28px 6px;        /* full-bleed across the sheet */
    background-color: var(--kjp-tone, #b0a090);   /* load guard */
    background-size: 200%;
    background-repeat: no-repeat;
}
.kjp-band--withhero::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom,
        transparent 0%,
        color-mix(in srgb, var(--kjp-sheet, #FAF7EF) 88%, var(--kjp-tone, #b0a090) 12%) 92%);
}

/* ════════════════════════════════════════════════════════════════════════
   THE WRITING HERO — integrate-hero-v2 (the glyph IS the control).
   ════════════════════════════════════════════════════════════════════════ */
/* the hero is a COLUMN that centres each child on one meditative spine:
   glyph, keyword, hint each sit as their own centred block. */
.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 16px 0 0;
}

/* THE GLYPH STAGE — the resting debossed Klee glyph and the stroke SVG share
   ONE fixed box, stacked, at the same scale; a tap cross-fades them IN PLACE so
   the page never reflows and the writing reads as the SAME character re-inking. */
.glyph-stage {
    position: relative;
    display: flex; align-items: center; justify-content: center;
    margin-inline: auto;
    width: clamp(138px, 18.5vw, 184px);
    height: clamp(138px, 18.5vw, 184px);
    cursor: pointer; border-radius: 14px;
    background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit;
    -webkit-tap-highlight-color: transparent;
    /* pressed INTO the sheet — a directional deboss pair + a soft ink-bloom; the
       drop-shadow FILTER lets the same pressed-in light wrap the inked strokes. */
    filter:
        drop-shadow(0 1.5px 0 rgba(255, 251, 243, 0.85))
        drop-shadow(0 -1px 0 rgba(58, 40, 20, 0.08))
        drop-shadow(0 2px 26px rgba(58, 54, 51, 0.07));
}
.glyph-stage--static { cursor: default; }
.glyph-stage:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 6px; }
.glyph-stage:focus { outline: none; }

/* the resting text glyph — scaled to FILL the shared box so it lines up with the
   SVG it cross-fades to. On hover/focus at rest it warms a hair (colour only). */
.glyph-rest {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--kjp-jp); font-size: clamp(138px, 19.4vw, 192px); line-height: 1;
    color: var(--kjp-ink); font-weight: 400; user-select: none;
    transition: opacity 0.4s ease, color 0.3s ease;
}
.glyph-stage:not(.glyph-stage--static):not(.is-writing):hover .glyph-rest,
.glyph-stage:not(.glyph-stage--static):not(.is-writing):focus-visible .glyph-rest { color: var(--kjp-ink-wet); }

/* the writing surface — the SVG of strokes, same box, hidden at rest. An under-
   bloom so wet ink reads as set INTO the sheet, matching the rest glyph's bloom. */
.glyph-ink {
    position: absolute; inset: 0; opacity: 0; pointer-events: none;
    transition: opacity 0.25s ease;
    filter: drop-shadow(0 2px 14px rgba(58, 54, 51, 0.06));
}
.glyph-ink.is-finishing { animation: kjpInkSettle 0.5s ease both; }
@keyframes kjpInkSettle {
    0%   { filter: drop-shadow(0 2px 14px rgba(58, 54, 51, 0.06)); }
    42%  { filter: drop-shadow(0 3px 20px rgba(58, 54, 51, 0.12)); }
    100% { filter: drop-shadow(0 2px 14px rgba(58, 54, 51, 0.06)); }
}
.glyph-ink svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* when writing: the text glyph dissolves slowly + a touch late, lingering under
   the first wet strokes; the ink layer's own fade-in is short (crisp over it). */
.glyph-stage.is-writing .glyph-rest { opacity: 0; transition: opacity 0.8s ease 0.08s; }
.glyph-stage.is-writing .glyph-ink { opacity: 1; pointer-events: auto; }

/* the ghost of the finished glyph, very faint — step / reduced-motion only */
.glyph-ink .ghost path {
    fill: none; stroke: rgba(58, 54, 51, 0.16);
    stroke-width: 5.8; stroke-linecap: round; stroke-linejoin: round;
    opacity: 0; transition: opacity 0.35s ease;
}
.glyph-ink.show-ghost .ghost path { opacity: 1; }
/* the LIVE strokes — warm sumi; scaling stroke-width (viewBox units) reads as the
   same heavy Klee ink the rest glyph carries, so the cross-fade is the SAME glyph. */
.glyph-ink .live path {
    fill: none; stroke: var(--kjp-ink);
    stroke-width: 5.8; stroke-linecap: round; stroke-linejoin: round;
    transition: stroke 0.42s ease, stroke-width 0.5s cubic-bezier(.2, .7, .2, 1);
}
/* the ACTIVE stroke — wet warm sumi + a touch heavier (brush pressure), eased
   back to settled sumi on land. NEVER indigo (reserved for the readings). */
.glyph-ink .live path.is-wet { stroke: var(--kjp-ink-wet); stroke-width: 7.4; transition: none; }
/* step-mode three-tier depth: TAUGHT strokes recede so the current one leads */
.glyph-ink.is-stepping .live path.is-done {
    stroke: color-mix(in srgb, var(--kjp-ink) 60%, var(--kjp-sheet, #FAF7EF));
    stroke-width: 5.4;
}
.glyph-ink .live path.is-current { stroke: var(--kjp-ink-wet); stroke-width: 6.8; }

/* the keyword line — its own centred block on the hero spine, held by framing
   rules that are dense at the words and fade to the margin. */
.hero .kw {
    display: flex; width: fit-content; margin-inline: auto;
    align-items: center; gap: 13px; margin-top: 15px;
    /* the meaning is the headline answer to "what is this kanji" — lift it a hair
       above the coloured reading glance below it (was 13.5px/stone). */
    font: 500 15px var(--kjp-ui); color: var(--kjp-prose); letter-spacing: 0.05em;
}
.hero .kw .kw-words { display: inline; }
.hero .kw .sep { font-style: normal; color: var(--kjp-ghost-soft); margin: 0 0.42em; }
.hero .kw::before, .hero .kw::after {
    content: ''; width: 26px; height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--kjp-tone, #b0a090) 46%, transparent));
}
.hero .kw::after { background: linear-gradient(90deg, color-mix(in srgb, var(--kjp-tone, #b0a090) 46%, transparent), transparent); }

/* THE WHISPER + AFTER-LINE — the only new affordance, hide-until-intent. ONE
   reserved row beneath the keyword so nothing ever reflows. */
:where(#kanjiPage) .hint {
    height: 26px; margin-top: 8px;
    display: flex; align-items: center; justify-content: center;
}
:where(#kanjiPage) .hint .rest {
    display: inline-flex; align-items: center; gap: 8px;
    font: 600 10.5px var(--kjp-ui); letter-spacing: 0.14em; text-transform: uppercase;
    /* hover-only (owner): hidden at rest, revealed on hero hover / glyph focus. */
    color: var(--kjp-stone); opacity: 0; transition: opacity 0.26s ease; pointer-events: none;
}
:where(#kanjiPage) .hint .rest [lang="ja"] {
    font-family: var(--kjp-jp); font-size: 13px; letter-spacing: 0.02em;
    color: var(--kjp-ink); text-transform: none; opacity: 0.82;
}
:where(#kanjiPage) .hint .rest .brush { width: 13px; height: 13px; flex: 0 0 auto; display: block; }
:where(#kanjiPage) .hint .rest .brush svg {
    width: 13px; height: 13px; fill: none; stroke: var(--kjp-gold-deep);
    stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
.hero:hover .hint .rest, .glyph-stage:focus-visible ~ .hint .rest { opacity: 1; }
/* on touch the giant glyph is the control but there's no hover — rest the whisper
   softly visible (a calm cue), suppressed once the glyph is open. */
@media (hover: none) {
    :where(#kanjiPage) .hint .rest { opacity: 0.7; }
    .glyph-stage.is-writing ~ .hint .rest { opacity: 0; }
}
:where(#kanjiPage) .hint .after {
    display: none; align-items: center; justify-content: center; gap: 18px;
    opacity: 0; transition: opacity 0.4s ease; pointer-events: none;
}
.glyph-stage.is-writing ~ .hint .rest { display: none; }
.glyph-stage.is-writing ~ .hint .after { display: inline-flex; }
:where(#kanjiPage) .hint .after.show { opacity: 1; pointer-events: auto; }
.hero:hover .glyph-stage.is-writing ~ .hint .after,
.glyph-stage.is-writing:focus-visible ~ .hint .after { opacity: 1; pointer-events: auto; }
.ink-link {
    appearance: none; background: none; border: 0; cursor: pointer; font: inherit;
    padding: 12px 2px;
    display: inline-flex; align-items: baseline; gap: 7px;
    color: var(--kjp-stone); transition: color 0.18s ease;
}
.ink-link [lang="ja"] { font-family: var(--kjp-jp); font-size: 13px; color: var(--kjp-ink); transition: color 0.18s ease; }
.ink-link .en { font: 400 11px var(--kjp-ui); letter-spacing: 0.04em; }
.ink-link:hover, .ink-link:hover [lang="ja"] { color: var(--kjp-indigo); }
.ink-link:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 3px; border-radius: 4px; }
.ink-link.on [lang="ja"], .ink-link.on .en { color: var(--kjp-indigo); }
:where(#kanjiPage) .hint .stepper {
    display: inline-flex; align-items: center; gap: 8px;
    opacity: 0; transition: opacity 0.26s ease; pointer-events: none;
}
:where(#kanjiPage) .hint.stepping .stepper { opacity: 1; pointer-events: auto; }
.step-arrow {
    appearance: none; background: none; border: 0; cursor: pointer; font: inherit;
    position: relative; width: 44px; height: 44px; line-height: 1; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--kjp-ink); transition: color 0.18s ease;
}
.step-arrow::before {
    content: ''; position: absolute; left: 50%; top: 50%; width: 26px; height: 26px;
    transform: translate(-50%, -50%); border-radius: 50%;
    background: transparent; transition: background-color 0.18s ease;
}
.step-arrow svg {
    position: relative; width: 13px; height: 13px; fill: none; stroke: currentColor;
    stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; display: block;
}
.step-arrow:hover { color: var(--kjp-indigo); }
.step-arrow:hover::before { background: rgba(61, 90, 128, 0.06); }
.step-arrow:focus-visible { outline: none; }
.step-arrow:focus-visible::before { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; }
.step-arrow[disabled] { color: var(--kjp-ghost-soft); opacity: 0.45; cursor: default; pointer-events: none; }
:where(#kanjiPage) .hint .ord {
    display: inline-flex; align-items: baseline; gap: 3px;
    min-width: 42px; justify-content: center;
    font: 600 12px var(--kjp-ui); letter-spacing: 0.04em;
    color: var(--kjp-stone); font-variant-numeric: tabular-nums lining-nums;
}
:where(#kanjiPage) .hint .ord .now { color: var(--kjp-indigo); }
:where(#kanjiPage) .hint .ord .tot { color: var(--kjp-ghost); }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── THE MOUNTED PRINT — the etymology painting set into a passe-partout ── */
.story { display: flex; flex-direction: column; align-items: center; padding: 22px 0 4px; }
.story .mount-wrap { position: relative; width: min(486px, 94%); }
.story .mount-wrap::before {
    content: ''; position: absolute; inset: -32px -26px -28px -26px; z-index: 0;
    pointer-events: none; border-radius: 26px;
    background: radial-gradient(62% 78% at 40% 28%,
        color-mix(in srgb, var(--kjp-tone, #b0a090) 27%, transparent) 0%, transparent 72%);
    opacity: 0.52; filter: blur(9px);
}
.story .mount {
    position: relative; z-index: 1; padding: 26px; border-radius: 4px; margin: 0;
    background: linear-gradient(150deg,
        color-mix(in srgb, var(--kjp-paper) 96%, #fff) 0%,
        var(--kjp-paper) 42%,
        color-mix(in srgb, var(--kjp-paper) 92%, var(--kjp-tone, #b0a090) 8%) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 251, 243, 0.85),
        inset 0 0 0 1px rgba(120, 90, 60, 0.10),
        0 1px 2px rgba(58, 40, 20, 0.04),
        0 6px 18px rgba(58, 40, 20, 0.05);
}
.story .plate {
    position: relative; z-index: 1; width: 100%; aspect-ratio: 3 / 2;
    border-radius: 2px; overflow: hidden;
    background:
        radial-gradient(120% 90% at 28% 22%, color-mix(in srgb, var(--kjp-tone, #b0a090) 24%, var(--kjp-paper)) 0%, transparent 56%),
        radial-gradient(110% 100% at 78% 84%, color-mix(in srgb, var(--kjp-tone, #b0a090) 16%, var(--kjp-paper)) 0%, transparent 60%),
        color-mix(in srgb, var(--kjp-tone, #b0a090) 11%, var(--kjp-paper));
    box-shadow:
        inset 1px 1px 0 rgba(255, 251, 243, 0.55),
        inset -1px -1px 0 rgba(58, 40, 20, 0.10),
        /* gold inner edge dropped — the .bevel warm-brown ring already frames the
           plate, and gold is reserved for the earned watch-out (scarcity). */
        inset 0 2px 10px rgba(58, 40, 20, 0.10),
        inset 0 0 50px rgba(120, 90, 60, 0.05);
}
.story .plate .fallback { position: absolute; inset: 0; pointer-events: none; }
.story .plate .fallback .g {
    position: absolute; font-family: var(--kjp-jp); font-weight: 400;
    line-height: 1; filter: blur(0.3px); user-select: none; color: rgba(120, 90, 60, 0.16);
}
.story .plate .fallback .g.g-a { font-size: clamp(46px, 11vw, 80px); top: 13%; left: 21%; }
.story .plate .fallback .g.g-b { font-size: clamp(92px, 20vw, 150px); bottom: 5%; right: 11%; }
/* one-part / no-part fallback: centre one calm glyph instead of jamming it into the
   bottom-right corner (a position tuned for the two-component evocation). */
.story .plate .fallback--solo .g-b {
    top: 50%; left: 50%; right: auto; bottom: auto;
    transform: translate(-50%, -50%);
    font-size: clamp(72px, 16vw, 110px);
}
.story .plate .fallback .disc {
    position: absolute; top: 18%; left: 27%;
    width: clamp(34px, 7vw, 56px); height: clamp(34px, 7vw, 56px); border-radius: 50%;
    /* a soft tone disc (the "sun" reads by its shape, not by gold) — gold is reserved
       for the earned watch-out, so the image-less fallback no longer spends it. */
    background: radial-gradient(circle at 42% 40%, color-mix(in srgb, var(--kjp-tone, #b0a090) 38%, transparent), color-mix(in srgb, var(--kjp-tone, #b0a090) 10%, transparent) 70%, transparent);
}
.story .plate .art {
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
    opacity: 0; transition: opacity 0.5s ease;
}
.story .plate .art.loaded { opacity: 1; }
.story .plate .art.art-b { z-index: 2; }
.story .plate .bevel {
    position: absolute; inset: 0; pointer-events: none; z-index: 3; border-radius: 2px;
    box-shadow:
        inset 1px 1px 0 rgba(255, 251, 243, 0.40),
        inset -1px -1px 0 rgba(58, 40, 20, 0.18),
        inset 0 0 0 1px rgba(120, 90, 60, 0.14);
}
.story .plate .tag {
    position: absolute; top: 12px; left: 12px; z-index: 4;
    font: 600 9px var(--kjp-ui); letter-spacing: 0.15em; text-transform: uppercase;
    color: var(--kjp-stone);
    background: rgba(250, 247, 239, 0.80); border: 1px solid var(--kjp-rule);
    border-radius: 2px; padding: 3px 9px;
    display: inline-flex; align-items: center; gap: 7px; backdrop-filter: blur(2px);
}
.story .plate .tag .nib { width: 5px; height: 5px; border-radius: 50%; background: var(--kjp-indigo); opacity: 0.55; }

/* the component caption under the print — the etymology named through its parts:
   the two component glyphs flank, the part names sit between (demo parity). */
.story .mount .caption {
    margin-top: 16px;
    text-align: center;
    font: 400 10px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--kjp-stone);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    flex-wrap: wrap;
}
.story .mount .caption [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--kjp-ink);
}
.story .mount .caption .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--kjp-ghost-soft); opacity: 0.8; }   /* neutral mote, not earned gold */

/* the kanji-TYPE label as the painting's caption (owner 2026-06-26) — a short one-row
   tag in the old caption slot: the KIND in small-caps, the 六書 term as a quiet Klee
   companion, a gold dot between. Replaces both the old part-naming caption and the
   former type eyebrow; the action line is gone (the painting + prose + sum token teach). */
.story .mount .kjp-type-cap,
.wpn-kbody > .kjp-type-cap {
    margin-top: 14px;
    display: flex; align-items: baseline; justify-content: center; gap: 8px; flex-wrap: wrap;
    text-align: center;
}
.kjp-type-cap .nm {
    font: 600 11px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--kjp-stone);
}
.kjp-type-cap.kjp-type--fused .nm { color: #7a6a52; }
.kjp-type-cap .jp {
    font: 400 13px 'Klee One', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ink); letter-spacing: 0.03em;
}
/* the 六書 term's romaji gloss (house rule: new JP copy carries romaji) */
.kjp-type-cap .rom {
    font: 400 10px 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ghost); letter-spacing: 0.04em; margin-left: -3px;
}
/* the caption separator is a neutral mote, not earned gold (gold = watch-out only) */
.kjp-type-cap .dot {
    width: 3px; height: 3px; border-radius: 50%;
    background: var(--kjp-ghost-soft); opacity: 0.8; align-self: center;
}

/* ── the shape story (prose) + the part-doors (borrowed-light component tie-in) ── */
.shape { text-align: center; padding: 28px 0 2px; }
.shape .prose {
    font-family: var(--kjp-jp); font-size: 18px; line-height: 1.92;
    color: var(--kjp-prose); max-width: 444px; margin: 0 auto; text-wrap: pretty;
}
.shape .prose b { color: var(--kjp-ink); font-weight: 600; font-style: normal; }
.shape .prose i { color: var(--kjp-indigo); font-style: normal; font-weight: 600; }
.shape .prose .wp-jp { color: var(--kjp-ink); }
/* the parts row — v2 doors. The existing door physics (button[data-kanji]) are
   preserved; this is the dress + the writing-led warm (borrowed light). */
.kjp-parts.parts {
    display: flex; justify-content: center; gap: 16px; margin-top: 24px;
    flex-wrap: wrap; align-items: center;
}
.parts .door {
    display: inline-flex; align-items: center; gap: 10px;
    background: none; border: 1px solid var(--kjp-rule); border-radius: 6px;
    padding: 7px 14px 7px 12px; text-decoration: none; cursor: pointer; font: inherit;
    transition: transform 0.2s ease, border-color 0.42s ease, background 0.42s ease;
}
/* an ungated part is not interactive — rest it without hover affordances */
.parts span.door { cursor: default; }
/* a tappable door (button) carries a quiet indigo edge AT REST so it reads as
   openable without waiting for hover — material, not an always-on arrow. The dead
   chips (span.door) keep the plain rule hairline, so the two are distinct at a glance. */
.parts button.door { border-color: rgba(61, 90, 128, 0.22); background: rgba(61, 90, 128, 0.02); }
button.parts, .parts button.door:hover {
    transform: translateY(-1px); border-color: rgba(61, 90, 128, 0.32); background: rgba(61, 90, 128, 0.025);
}
.parts span.door:hover { transform: none; border-color: var(--kjp-rule); background: none; }
.parts .door:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; }
.parts .door .g { font-family: var(--kjp-jp); font-size: 30px; color: var(--kjp-ink); line-height: 1; transition: color 0.35s ease; }
.parts .door .n { font: 400 11px var(--kjp-ui); color: var(--kjp-stone); letter-spacing: 0.02em; }
/* the hop arrow is navigation, so it wears the indigo teaching accent (matching the
   glyph's own hover colour), never the earned gold. */
.parts .door .go { font: 400 13px var(--kjp-ui); color: var(--kjp-indigo); opacity: 0; transition: opacity 0.2s ease; margin-left: -3px; }
button.parts.door:hover .g, button.parts.door:focus-visible .g,
.parts button.door:hover .g, .parts button.door:focus-visible .g { color: var(--kjp-indigo); }
.parts button.door:hover .go, .parts button.door:focus-visible .go { opacity: 1; }
/* the writing-led warm: while a component's strokes draw, its door glows the same
   indigo a hover gives — borrowed light, calm and brief. */
.parts .door.writing .g { color: var(--kjp-indigo); }
.parts .door.writing { border-color: rgba(61, 90, 128, 0.22); background: rgba(61, 90, 128, 0.02); }
/* touch has no hover: keep the hop arrow softly present so a door still signals it
   opens a kanji page (mirrors the hero whisper's touch treatment). */
@media (hover: none) { .parts button.door .go { opacity: 0.4; } }

/* ── THE THRESHOLD — 間 (ma): a band of breath, the gear-change ── */
.threshold {
    position: relative; height: 108px; margin-top: 12px;
    display: flex; align-items: center; justify-content: center;
}
.threshold::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 78%; height: 58px; transform: translate(-50%, -50%);
    background: radial-gradient(60% 50% at 50% 50%,
        color-mix(in srgb, var(--kjp-tone, #b0a090) 16%, transparent) 0%, transparent 72%);
    opacity: 0.85; pointer-events: none;
}
.threshold .mark { position: relative; z-index: 1; display: flex; align-items: center; gap: 13px; }
.threshold .mark .ln {
    width: clamp(34px, 9vw, 64px); height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--kjp-tone, #b0a090) 40%, transparent));
}
.threshold .mark .ln.r { background: linear-gradient(90deg, color-mix(in srgb, var(--kjp-tone, #b0a090) 40%, transparent), transparent); }
.threshold .mark .ch { font-family: var(--kjp-jp); font-size: 18px; color: var(--kjp-ink); opacity: 0.62; line-height: 1; }
.threshold .mark .lbl { font: 600 9.5px var(--kjp-ui); letter-spacing: 0.24em; text-transform: uppercase; color: var(--kjp-stone); }

/* ── sections: ink on the washi (the word page's grammar) ─────────────── */

.kjp-sec { padding: 30px 0 0; }
.kjp-sec + .kjp-sec,
.kjp-sec + .kjp-card,
.kjp-sec ~ .kjp-card { margin-top: 30px; }
/* the labels are gone (なりたち / あなたのことばの中で were self-explanatory),
   so the scenes must read apart on whitespace + the band + the READ AS group
   eyebrows alone. The shape story opens just under the band as its own scene
   (a touch more air than a labelled section once gave); the words section then
   sits a full scene-gap below, its first group eyebrow doing the framing. */
.kjp-story { padding-top: 34px; }
.kjp-story + .kjp-words { margin-top: 34px; }

/* ── 例文 examples — the kanji met in real sentences, reusing the example set
   the words already carry. Calm stacked rows; the page kanji (and its reading)
   light indigo inside each sentence so the eye finds the character it came for. */
.kje-list { display: flex; flex-direction: column; gap: 18px; }
.kje-jp {
    margin: 0 0 6px;
    font-family: 'Klee One', 'Noto Sans JP', serif;
    font-size: 20px;
    line-height: 2.15;                 /* headroom for the ruby */
    color: var(--kjp-ink);
}
.kje-jp ruby rt {
    font: 400 10px 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--kjp-stone);
    letter-spacing: 0.02em;
}
/* the studied kanji, lit inside the sentence — warm indigo ink (the panel's
   teaching accent) + a little more weight (Klee One 600), no box, no underline:
   the glyph the reader came for reads a different COLOUR from the sentence around
   it, calmly (和の感性 restraint). Its reading above matches ONLY when the ruby
   group is exactly this one kanji (word-level furigana can't be split per char). */
.kje-jp .kje-hl { color: var(--kjp-indigo); font-weight: 600; }
.kje-jp ruby.kje-rb-hl rt { color: var(--kjp-indigo); font-weight: 600; }
/* every OTHER gated kanji in the sentence is a door deeper into the trail
   (universal tap). The affordance is hover-only: a resting tint on every
   live glyph would patchwork the sentence and bury the studied character's
   own highlight — the sentence's one point. Pointer users discover it the
   way they discover the word page's example doors. */
@media (hover: hover) {
    .kje-jp .kje-kt { cursor: pointer; transition: color 0.15s ease; }
    .kje-jp .kje-kt:hover { color: var(--kjp-indigo); }
}
.kje-ro {
    display: block;
    font: 400 12.5px 'Inter', 'Noto Sans JP', sans-serif;
    font-style: italic;
    color: var(--kjp-ghost);
}
.kje-en {
    display: block;
    margin-top: 2px;
    font: 400 14px 'Inter', 'Noto Sans JP', sans-serif;
    line-height: 1.5;
    color: var(--kjp-prose);
}
/* held-back examples wait behind the "Show N more" tap, then grow in calmly
   (same transform-only reveal the reading groups use — safe under reduced-motion) */
.kje-ex--hid { display: none; }
.kje-ex--reveal { animation: kjwReveal 0.24s ease both; }
/* the "Show N more" disclosure. MUST be scoped under .kjp-overlay so it out-
   specifies the `.kjp-overlay button` reset (which otherwise leaves it as plain
   16px ink body text — the un-native look) and reads as a small tracked ghost
   affordance with the panel's caret: a quiet "there's more", not a line of prose. */
.kjp-overlay .kje-more,
.wpn-kbody .kje-more {
    appearance: none;
    background: none;
    border: 0;
    margin: 8px 0 0;
    padding: 6px 8px 6px 2px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border-radius: 6px;
    font: 500 12px 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ghost);
    cursor: pointer;
    transition: color 0.18s ease;
}
.kjp-overlay .kje-more:hover,
.wpn-kbody .kje-more:hover { color: var(--kjp-stone); }
.kjp-overlay .kje-more:active,
.wpn-kbody .kje-more:active { color: var(--kjp-ink); }
.kjp-overlay .kje-more:focus-visible,
.wpn-kbody .kje-more:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; }
/* (the .kjp-howto / 読み方 orientation rules were removed 2026-06-27 with the dead
   howtoHTML() that emitted them — never rendered; the reading standfirsts teach it.) */
.kjp-slabel {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 12px;
    color: var(--color-stone);
}
.kjp-slabel [lang="ja"] {
    font: 600 15px 'Klee One', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ink);
}
.kjp-slabel span:not([lang]) {
    font: 600 10.5px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--color-stone);
}

/* the one box that remains earned: the gold watch-out card (and the twin
   specimen tray below) — everything else reads as ink on the paper */
.kjp-card {
    background: var(--color-card);
    border: 1px solid var(--kjp-rule);
    border-radius: 3px;
    box-shadow: 0 1px 3px rgba(58, 40, 20, 0.05);   /* warm sumi shadow, not cold neutral */
    padding: 20px 22px;
    margin: 30px 0 0;
}
.kjp-card .kjp-slabel [lang="ja"] { font-size: 13px; }

/* prose <b>/<i> + the shared Klee-bold for prose/watch/twin emphasis. (The shape
   prose itself is styled in the v2 hero block above as .shape .prose; this keeps
   the shared bold rule for the watch-out / twin lines that also carry <b>.) */
.kjp-story b, .kjp-watch b, .kjt-note b {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-weight: 600;
}
/* the v2 part-doors are styled in the hero block above (.parts .door .g/.n/.go +
   the borrowed-light .writing warm). The renderer now emits .kjp-part-name as
   .n and the glyph as .g, so the old flat-typography part rules are retired. */

/* ── reading groups + word rows ───────────────────────────────────────── */

.kjr-group { margin-top: var(--kjw-grp-gap); }   /* shared group rhythm (was 14px; owner consistency 2026-06-29) */
.kjr-group:first-of-type { margin-top: 0; }
.kjr-eyebrow {
    /* the section's teaching title (Japanese/Chinese reading) — lifted out of the
       9.5px basement so the kun/on distinction reads as a real heading, still
       distinct from the 10px band-metadata caption. */
    font: 600 12px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #78716c;
    margin-bottom: 16px;
    line-height: 1.5;
    text-wrap: pretty;
}
/* the explanation drops to its OWN line as a standfirst deck (the dictionary
   sense-body under the headword) — shares the de-badged type eyebrow's deck voice. */
.kjr-eb-note {
    display: block;
    margin-top: 6px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    font-size: 12px;
    line-height: 1.55;
    color: var(--color-stone);
    max-width: 60ch;
    text-wrap: pretty;
}
.kjr-eb-note::before { content: none; }
.kjr-eb-note [lang="ja"] { font-family: 'Klee One', 'Noto Sans JP', sans-serif; color: var(--kjp-ink); }
/* the romaji pronunciation (kun'yomi / on'yomi) — set tight beside 訓読み like furigana
   (term + pronunciation = one word in two scripts), upright, and the ONLY token on the
   head line that wears the reading's accent (kun = indigo, on = terracotta). */
.kjr-eb-rom {
    font: 400 11.5px 'Inter', 'Noto Sans JP', sans-serif;
    text-transform: none; letter-spacing: 0.02em;
    color: var(--rd-accent, var(--kjp-indigo));
}
/* a house middot introduces the English gloss — scoped to the adjacent sibling so the
   'read as' (neu, no romaji) eyebrow never gets an orphan leading dot. */
.kjr-eb-rom + .kjr-eb-en::before {
    content: '·'; margin: 0 8px; color: var(--kjp-ghost-soft); font-weight: 400; letter-spacing: 0;
}
/* the kanji term before the English (訓読み / 音読み / まるごと) — Klee, ink, no
   tracking, a hair faded, so it reads as the native label leading the heading. */
.kjr-eyebrow .jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 16px;
    letter-spacing: 0;
    color: var(--kjp-ink);
    text-transform: none;
    margin-right: 7px;
    opacity: 1;
}
/* a hairline under the reading header anchors the reading name to its word list
   (so とき / じ / とけい don't float orphaned); the lines BETWEEN rows and BETWEEN
   sections are gone — only this header rule remains. */
.kjr-head {
    display: flex;
    align-items: baseline;
    gap: 11px;
    /* match the word rows' 5px side padding so the reading name sits on the tile
       column and "N words" lines up over the rank rail (was flush, 5px adrift). */
    padding: 0 5px 8px;
    border-bottom: 1px solid var(--kjp-rule);
    margin-bottom: 12px;
}
/* glance jump landing: a brief accent wash on the reading head you jumped to confirms
   the tap took you to the right reading (added in JS after the scroll settles). */
@keyframes kjrArrive {
    0%   { background-color: transparent; }
    25%  { background-color: color-mix(in srgb, var(--rd-accent, var(--kjp-indigo)) 13%, transparent); }
    100% { background-color: transparent; }
}
.kjr-head--arrive { animation: kjrArrive 0.7s ease; }
/* the reading-family head (とき / じ) — indigo because the readings ARE the lesson
   (the teaching accent, matching the won v2 .gname). Sumi is reserved for the glyph,
   labels, and word rows; here the kun/on name carries the indigo teaching signal. */
.kjr-name { font: 600 22px 'Klee One', 'Noto Sans JP', sans-serif; color: var(--rd-accent, var(--color-accent)); }
.kjr-name--whole { font-size: 14px; color: var(--color-stone); }
.kjr-sub { font: 400 11.5px 'Inter', 'Noto Sans JP', sans-serif; color: var(--color-stone); }
.kjr-head .kjr-sub { margin-left: auto; }       /* the word count rests at the right */

/* reading FAMILIES — native (kun) · borrowed (on) · まるごと. The eyebrow names the
   family in plain English; the def teaches the term + when the reading fires. Ink
   on the washi: the family is typography + the head's hairline, never a box.
   v2: a soft vertical rule to the left — gold-tipped fading to tone for kun/on,
   indigo for まるごと — gives each family its own quiet spine. */
.kjr-family { position: relative; margin-top: 22px; padding-left: 22px; --rd-accent: var(--color-accent); }   /* tightened (owner 2026-06-29; was 36px) */
/* reading-type accent — one variable drives every per-type colour:
   native (kun'yomi) = indigo (default), borrowed (on'yomi) = terracotta,
   fused combo (まるごと) = bronze. */
.kjr-family--on { --rd-accent: #9E5E43; }
.kjr-family--whole { --rd-accent: #8A6A33; }
/* unclassified readings ("read as" / "in your words") must NOT borrow kun-indigo —
   colour means a real classification. Warm stone reads as honestly unclaimed. */
.kjr-family--neu { --rd-accent: var(--kjp-stone); }
.kjr-family:first-of-type { margin-top: 0; }
.kjr-family .kjr-group:first-of-type { margin-top: 0; }
/* the family spine echoes the locked reading accent (kun indigo / on terracotta /
   まるごと bronze / neu stone) instead of a decorative gold tip — so a glance down
   the spine reads the kun/on structure, and gold stays earned (watch-out only). */
.kjr-family::before {
    content: ''; position: absolute; left: 0; top: 3px; bottom: 6px;
    width: 2px; border-radius: 2px;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--rd-accent) 38%, transparent),
        color-mix(in srgb, var(--rd-accent) 8%, transparent));
}
.kjr-def {
    margin: 2px 0 13px;
    max-width: 66ch;                            /* fits each one-line def on a single row */
    font: 400 12.5px/1.55 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--color-stone);
    text-wrap: pretty;                          /* clean wrap on narrow viewports */
}
.kjr-def b { font-weight: 600; color: var(--kjp-ink); }
.kjr-def [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 1.05em;
    color: var(--kjp-ink);
}
/* the reading's romaji — a quiet companion beside the kana name. #6b6358 matches the
   row romaji + clears AA (was #78716c, which read lighter than the smaller row romaji). */
.kjr-romaji { font: 400 13px 'Inter', 'Noto Sans JP', sans-serif; color: #6b6358; }
/* rendaku: this reading is the family's base with a voiced first sound, not new */
.kjr-voiced { font: 400 11.5px 'Inter', 'Noto Sans JP', sans-serif; color: #6b6358; }
.kjr-voiced [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 1.15em;
    color: var(--color-stone);
}

/* まるごと block: the fused unit named before its words — "時 + 計 → とけい · clock".
   The kanji combine (the current one tinted indigo like a row highlight), arrow to
   the fused reading, then the plain meaning. One header per distinct block, so
   different jukujikun units never read as a single pooled reading. */
.kjr-group--juku { margin-top: 12px; }   /* tightened (owner 2026-06-29; was 18px) */
.kjr-juku-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 7px;
    padding: 0 5px 8px;     /* on the row grid, like .kjr-head */
    margin-bottom: 4px;
    border-bottom: 1px solid var(--kjp-rule);
}
/* the fused pair → its sound, as one indigo "equation" on the washi. BOTH kanji
   carry the same indigo (together they make the reading — neither is "the source"),
   and the fused READING is the larger indigo result the eye lands on. No black: the
   formula reads as a calm label, distinct from the warm word rows it heads. */
.kjr-juku-k { font: 600 18px 'Klee One', 'Noto Sans JP', sans-serif; color: var(--rd-accent, var(--color-accent)); }
.kjr-juku-op { font: 400 13px 'Inter', sans-serif; color: #b3aca3; align-self: center; }
.kjr-juku-read {
    font: 600 20px 'Klee One', 'Noto Sans JP', sans-serif;
    color: var(--rd-accent, var(--color-accent));           /* the fused sound — the result, no black */
    margin-left: 2px;
}
.kjr-juku-mean { font: 400 13px 'Inter', 'Noto Sans JP', sans-serif; color: var(--color-stone); }

.kjw-row {
    appearance: none;
    background: none;
    border: 0;
    border-radius: 0;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 11px 5px;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    color: inherit;
    transition: background-color 0.18s ease;
}
/* The overlay button-reset (.kjp-overlay button, 0,1,1) zeroes padding and
   outranks .kjw-row (0,1,0) — but only the BUTTON rows match it, so image rows
   lost their padding while the no-card DIV rows kept it. That was the entire
   cross-section height drift. Re-assert at matching specificity so every row
   (button or div) carries the same vertical padding. */
.kjp-overlay .kjw-row,
.wpn-kbody .kjw-row { padding: 11px 5px; }
/* rows tint only on hover/press (warm sumi) — the 4px slide is dropped so every
   tappable surface shares one calm vocabulary (like the twin cell). */
.kjw-row:hover { background: rgba(58, 54, 51, 0.03); }
.kjw-row:active { background: rgba(58, 54, 51, 0.05); }
.kjw-row:last-of-type { border-bottom: none; }
.kjw-row--hid { display: none; }

/* live mastery dot — which of these words the learner already holds. Off the
   thumbnail (never deface the art), at the row's right edge beside the rank
   chip; the placard's own status colours (amber Saved · moss Resting · bright
   Coming back). New rows — most of any list — stay unmarked: the mark must
   earn its place. */
.kjw-dot {
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
}
.kjw-dot--learning { background: var(--color-amber, #A07850); }
.kjw-dot--learned { background: var(--color-moss, #6B7F5C); }
.kjw-dot--comeback { background: var(--color-moss-bright, #5B8C5A); }

/* the row placard — a solid muted tone tile (the word's own img_tone via --rowtone),
   not a photo thumbnail: the calm reading-room look (demo parity). A faint washi
   grain + a top-left sheen sit it on the same paper as the sheet. */
.kjw-tile {
    width: 94px;
    height: 67px;
    border-radius: 8px;
    flex: 0 0 auto;
    position: relative;
    overflow: hidden;
    background: var(--rowtone, #b0a090);
    box-shadow:
        inset 0 0 0 1px rgba(120, 90, 60, 0.10),
        0 1px 4px rgba(58, 40, 20, 0.07);
}
.kjw-tile::after {
    content: '';
    position: absolute;
    inset: 0;
    mix-blend-mode: multiply;
    opacity: 0.06;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><filter id='kjt'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='1'/></filter><rect width='100%25' height='100%25' filter='url(%23kjt)'/></svg>");
}
.kjw-tile::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: radial-gradient(120% 100% at 26% 18%, rgba(250, 247, 239, 0.30), transparent 62%);
}
/* the real word painting fills the tile (the tone swatch behind is the load
   guard); fades in on load, hidden on error so the swatch shows instead. */
.kjw-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    z-index: 2;
    opacity: 0;
    transition: opacity 0.4s ease;
}
.kjw-thumb.loaded { opacity: 1; }
.kjw-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
/* word rows read at a calm medium weight (matches the まるごと no-card examples) —
   the per-type highlight carries the emphasis, not a heavy stroke. */
.kjw-jp { font: 500 27px 'Klee One', 'Noto Sans JP', sans-serif; line-height: 1.5; }
.kjw-hl { color: var(--rd-accent, var(--color-accent)); }
/* alt-spelling rows (the かな shelf): the kanji dress the word would wear,
   quiet beside the kana headword — the page kanji lit inside it is the row's
   teaching point. */
.kjw-alt {
    font: 400 17px 'Klee One', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ghost-soft, #a8a299);
    margin-left: 9px;
}
.kjw-alt .kjw-hl { color: var(--rd-accent, var(--color-accent)); }
/* romaji, one quiet line under the word (the reading; kana furigana removed 2026-06-26).
   It now CARRIES the whole pronunciation, so it must clear AA — #6b6358 is ~5.5:1 on
   the washi (the old ghost #8c857b was ~3.4:1, a fail), still quieter than the lemma. */
.kjw-ro {
    font: 500 12.5px 'Inter', 'Noto Sans JP', sans-serif;
    color: #6b6358;
    letter-spacing: 0.04em;
}
.kjw-ro-note { letter-spacing: 0; color: var(--kjp-ghost-soft, #a8a299); }
.kjw-ro-note [lang="ja"] { font-family: 'Klee One', 'Noto Sans JP', sans-serif; }
.kjw-kana {
    font: 400 14px 'Klee One', 'Noto Sans JP', sans-serif;
    color: var(--color-stone);
    margin-left: 9px;
}
/* prove the reading: the kana this kanji contributes, lit to match the kanji in
   the lemma above it (時 indigo → じ indigo) so the sound↔shape link is visible.
   v2: a hand-laid sumi stitch under the kana (indigo underline) rather than a bare
   colour swap — it reads as the teacher tracing where the sound sits. */
.kjw-kana-hl {
    color: var(--rd-accent, var(--color-accent));
    background-image: linear-gradient(
        color-mix(in srgb, var(--rd-accent, var(--color-accent)) 78%, transparent),
        color-mix(in srgb, var(--rd-accent, var(--color-accent)) 78%, transparent));
    background-repeat: no-repeat;
    background-position: 0 calc(100% - 1px);
    background-size: 100% 1.6px;
    padding-bottom: 2.5px;
}
.kjw-en {
    font: 400 13px 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--color-stone);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* the frequency chip at the row's right edge (demo parity): #N for a ranked word,
   or the quiet "common" eyebrow when it carries no number. A faint tabular numeral —
   orientation, never the loud thing the eye lands on. */
.kjw-row .rank {
    flex: 0 0 auto;
    align-self: center;
    font: 600 10.5px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.04em;
    color: var(--kjp-ghost);
    font-variant-numeric: tabular-nums lining-nums;
    text-align: right;
    min-width: 42px;
}
.kjw-row .rank b { color: var(--kjp-stone); font-weight: 600; }
/* "rare" — the one qualitative end of the frequency scale (unranked rows show nothing;
   #N digits carry the rest). A tiny uppercase key in the same right slot, so a word never
   competes with a numeral in the numeric column. #6b6358 clears AA (the ghost token did
   not at this size). */
.kjw-row .rank.is-rare {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #6b6358;
    white-space: nowrap;
}

/* "Show N more" — a considered disclosure, not orphan text in the tile gutter.
   Indented to the lemma column (row pad 5 + tile 94 + gap 18 = 117px) so it reads as
   the list continuing; a caret + plain English + the same faint warm hover the rows
   carry make it legibly pressable at rest. Caret/ink stay ghost→stone (never gold).
   MUST be scoped under both hosts (same reason as .kje-more below): the
   `.kjp-overlay button` / `.wpn-kbody button` resets are (0,1,1) and a bare
   .kjr-more (0,1,0) loses to them — it shipped as 16px ink body text. */
.kjp-overlay .kjr-more,
.wpn-kbody .kjr-more {
    appearance: none;
    background: none;
    border: 0;
    margin-left: 112px;
    padding: 9px 5px 5px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border-radius: 6px;
    font: 500 12px 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--kjp-ghost);
    cursor: pointer;
    transition: color 0.18s ease, background-color 0.18s ease;
}
.kjp-overlay .kjr-more:hover,
.wpn-kbody .kjr-more:hover { color: var(--kjp-stone); background: rgba(58, 54, 51, 0.03); }
.kjp-overlay .kjr-more:active,
.wpn-kbody .kjr-more:active { color: var(--kjp-ink); }
.kjp-overlay .kjr-more:focus-visible,
.wpn-kbody .kjr-more:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; }
.kjr-more-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;
}
/* open folds point their caret back up — the same line now offers the way closed */
.kjr-more.is-open .kjr-more-caret,
.kje-more.is-open .kjr-more-caret { transform: rotate(180deg); }
/* the revealed rows fade up rather than snapping in (wired in render(), reduced-motion-guarded) */
/* transform-only (same safe-degrade reason as kjp-reg-rise): a frozen "Show N more"
   reveal stays legible — at worst the new rows sit 4px low, never invisible. */
@keyframes kjwReveal { from { transform: translateY(4px); } to { transform: none; } }
.kjw-row--reveal { animation: kjwReveal 0.24s ease both; }

/* rarer readings rest behind one quiet line at the family's tail (K4) — same
   voice as "Show N more" but flush left (it discloses whole reading groups,
   not rows in the lemma column). The folded readings' names ride on the line
   so completeness is visible before the tap (and label the "Hide" line once open). */
.kjp-overlay .kjr-rarefold,
.wpn-kbody .kjr-rarefold { margin-left: 0; margin-top: 4px; }
.kjr-fold-names { display: inline-flex; align-items: baseline; gap: 7px; margin-left: 4px; }
.kjr-fold-name { color: var(--kjp-ghost); }
.kjr-fold-name [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    color: var(--kjp-stone);
}
.kjr-fold-dot { color: var(--kjp-ghost-soft, #a8a299); }
.kjr-rare--reveal { animation: kjwReveal 0.24s ease both; }

/* ── watch-out (earned gold) ──────────────────────────────────────────── */

/* the watch-out dissolves to gold-marked ink on the washi — the earned gold rule
   stays, the frame/fill/shadow go (the twin tray keeps its frame: a side-by-side
   specimen genuinely earns one). Mirrors how the word page dissolved its cards. */
.kjp-watch {
    background: none;
    border: 0;
    border-left: 3px solid var(--color-gold);
    border-radius: 0;
    box-shadow: none;
    padding: 2px 0 2px 18px;
}
.kjp-watch .kjp-slabel { color: var(--color-gold); }
.kjp-watch .kjp-slabel span:not([lang]) { opacity: 1; }
/* the leading gold seal dot (demo parity) */
.kjp-watch .kjp-slabel .seal {
    align-self: center;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--kjp-gold);
    flex: 0 0 auto;
}
.kjp-watch p { font-size: 15px; line-height: 1.7; color: #44403c; margin: 0; }

/* ── the closing colophon — one gold dot + the KanjiVG credit, a whisper ── */
.foot {
    min-height: 90px;
    padding: 8px 0 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 13px;
}
.foot .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--kjp-ghost-soft); opacity: 0.6; }   /* a neutral mote — gold is reserved for the earned watch-out */
.foot .colophon {
    font: 400 9px 'Inter', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.1em;
    color: var(--kjp-ghost);
    opacity: 0.7;
    text-align: center;
}

/* ── the scholar note (由来) — real etymology, behind a tap ────────────── */
/* NATIVE rework: one uninterrupted washi column. Each register is free prose
   under a readings-row-echo label, parted only by air + a single hairline — no
   coloured callout cards, no spine, no ochre ground, no ALL-CAPS eyebrows. The
   honesty signal is a ghost-ink scholar's mark (scarcity-gated); the lineage is
   a faded older form, never a ＋/→ flowchart. */
.kjp-scholar { margin-top: 22px; }
.kjp-story + .kjp-scholar { margin-top: 20px; }

/* the cue: a CENTERED ornament flanked by two short rules (the hero keyword's own
   "— year —" language), so it reads as part of the panel, never a full-width UI
   accordion bar. No top hairline; the flanking rules carry the separation. */
/* 朱筆 the vermilion margin-note (redesign 2026-06-29). A left-anchored annotation
   row on the panel's OWN running hairline, no filled shape: the maroon chip read as
   a pasted sticker (the one solid block on an ink-on-washi panel), so the red now
   lives only as ink. 由来 in cinnabar, a fine dotted vermilion baseline (the footnote
   tell), the plain words + a right-edge caret carrying the tap. Touch-first: the ink,
   the words, and the caret already invite at rest with no hover. */
.kjp-scholar-cue {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 11px;
    padding: 13px 2px;
    border-top: 1px solid var(--kjp-rule);   /* the page's own running rule */
    min-height: 44px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}
.kjp-scholar-cue::-webkit-details-marker { display: none; }
.kjp-scholar-cue::marker { content: ""; }
.kjp-scholar > .kjp-scholar-cue:focus-visible {
    outline: 2px solid var(--kjp-indigo);
    outline-offset: 3px;
    border-radius: 2px;
}
/* 由来 as vermilion brush-ink — the glyphs ARE the red, no box. */
.kjp-sc-mark {
    position: relative; align-self: center;
    font: 600 15.5px 'Klee One', 'Noto Sans JP', sans-serif;
    letter-spacing: 0.14em; line-height: 1;
    color: var(--kjp-seal);
    transition: color 0.2s ease, transform 0.12s ease;
}
/* the footnote tell: one fine dotted vermilion baseline under 由来 only (same hue,
   so glyph + line read as ONE mark, not two reds) */
.kjp-sc-mark::after {
    content: ""; position: absolute; left: 0; right: 0.04em; bottom: -4px; height: 0;
    border-bottom: 1px dotted color-mix(in srgb, var(--kjp-seal) 52%, transparent);
    transition: border-color 0.2s ease;
}
.kjp-sc-where { font: 400 13px 'Inter', 'Noto Sans JP', sans-serif; color: var(--kjp-stone); letter-spacing: 0.01em; }
/* lightest open affordance: a hairline caret pushed to the right edge */
.kjp-sc-turn {
    margin-left: auto; align-self: center; flex: none;
    width: 6px; height: 6px;
    border-right: 1.4px solid var(--kjp-ghost);
    border-bottom: 1.4px solid var(--kjp-ghost);
    transform: rotate(45deg) translateY(-1px);
    transition: transform 0.28s cubic-bezier(0.22,1,0.36,1), border-color 0.2s ease;
}
.kjp-scholar[open] > .kjp-scholar-cue .kjp-sc-turn { transform: rotate(-135deg) translateY(1px); }
.kjp-scholar-cue:active .kjp-sc-mark { transform: translateY(0.5px); }
/* hover = additive only (desktop); touch already fully invites */
@media (hover: hover) {
    .kjp-scholar-cue:hover .kjp-sc-mark { color: var(--kjp-seal-deep); }
    .kjp-scholar-cue:hover .kjp-sc-mark::after { border-bottom-color: color-mix(in srgb, var(--kjp-seal-deep) 70%, transparent); }
    .kjp-scholar-cue:hover .kjp-sc-turn { border-color: var(--kjp-stone); }
}

/* the opened note is an aged-washi LEAF laid into the sheet: a hair warmer/lighter
   paper with a soft inset top-shadow (paper lifting off), so it reads as a special
   page, not a coloured callout box. No border ring. */
.kjp-scholar-body {
    margin-top: 4px;
    padding: 16px 20px 10px;
    background: color-mix(in srgb, var(--kjp-paper) 72%, var(--kjp-sheet));
    border-radius: 3px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.5),
        inset 0 18px 26px -24px rgba(58, 40, 20, 0.20);
}

/* a register: free prose on the leaf. The two are parted by a brushed sumi rule. */
.kjp-reg { position: relative; margin: 0; }
.kjp-reg + .kjp-reg { margin-top: 24px; padding-top: 22px; }
/* the brushed divider — a tapered sumi stroke, not a flat hairline */
.kjp-reg + .kjp-reg::before {
    content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 88px; height: 2px; border-radius: 2px;
    background: linear-gradient(90deg, transparent,
        color-mix(in srgb, var(--kjp-ink) 32%, transparent) 24%,
        color-mix(in srgb, var(--kjp-ink) 48%, transparent) 50%,
        color-mix(in srgb, var(--kjp-ink) 32%, transparent) 76%, transparent);
}
.kjp-reg-label {
    display: flex; align-items: baseline; gap: 7px;
    margin: 0 0 12px; font-weight: 400;
}
.kjp-reg-label .jp {
    position: relative;
    font: 600 14.5px 'Klee One', 'Noto Sans JP', sans-serif; color: var(--kjp-ink); line-height: 1; letter-spacing: 0.03em;
}
/* a faint brush-tapered underline gives the JP headword ink character */
.kjp-reg-label .jp::after {
    content: ""; position: absolute; left: 1px; right: -2px; bottom: -5px; height: 1.5px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--kjp-ink) 44%, transparent),
        color-mix(in srgb, var(--kjp-ink) 14%, transparent) 70%, transparent);
}
.kjp-reg-label .rom { font: 400 11.5px 'Inter', sans-serif; color: var(--kjp-stone); }
.kjp-reg-label .sep { color: var(--kjp-ghost-soft); }
.kjp-reg-label .en { font: 400 12px 'Inter', 'Noto Sans JP', sans-serif; color: var(--kjp-stone); }

/* the reading measure (~62ch), generous leading to absorb the taller inline JP. */
.kjp-reg-prose {
    font: 400 14.5px/1.78 'Inter', 'Noto Sans JP', sans-serif;
    color: var(--kjp-prose);
    margin: 0; max-width: min(100%, 62ch);
    text-wrap: pretty; hyphens: none; -webkit-hyphens: none;
    hanging-punctuation: first last;
    font-feature-settings: "liga" 1, "calt" 1, "onum" 1;
}
.kjp-reg-prose .wp-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-weight: 500; color: var(--kjp-ink);
    font-size: 1.04em; letter-spacing: 0.015em;
}

/* the honesty mark — ghost-ink, scarcity-gated, no bordered badge. */
.kjp-cert {
    margin: 13px 0 0;
    font: 400 12.5px/1.6 'Inter', sans-serif; color: var(--kjp-stone);
    display: flex; align-items: baseline; gap: 8px; text-wrap: balance;
}
.kjp-cert .mark { flex: none; color: var(--kjp-ghost); }
.kjp-cert .mark .jp { font-family: 'Klee One', 'Noto Sans JP', sans-serif; }
.kjp-cert .mark .rom { font-size: 11px; }
.kjp-cert .t { font-style: italic; }

/* the ancient-form IMPRESSION — the real older glyph stands large + very faint in
   the journey's right margin, captioned. Says "old and deep" AND teaches; sumi
   ink only, no colour cost. Rendered only where a single older form exists
   (JS gates on strip.from.length === 1); the journey reserves a right gutter. */
.kjp-reg--impressed .kjp-reg-prose { padding-right: 118px; }
.kjp-impression {
    position: absolute; top: 26px; right: -2px; width: 108px;
    display: flex; flex-direction: column; align-items: center; text-align: center; gap: 9px;
    pointer-events: none;
}
.kjp-impression .g {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 96px; line-height: 0.88; color: var(--kjp-ink); opacity: 0.07;
}
.kjp-impression .cap { font: 400 11px 'Inter', 'Noto Sans JP', sans-serif; color: var(--kjp-stone); line-height: 1.4; }
.kjp-impression .cap .og { font-family: 'Klee One', 'Noto Sans JP', sans-serif; color: var(--kjp-prose); font-size: 13px; }

/* the open gesture — one quiet upward rise. */
@media (prefers-reduced-motion: no-preference) {
    .kjp-scholar[open] .kjp-reg--journey .kjp-reg-prose  { animation: kjp-reg-rise 0.4s cubic-bezier(0.16,1,0.3,1) both; }
    .kjp-scholar[open] .kjp-reg--journey .kjp-impression { animation: kjp-reg-rise 0.5s cubic-bezier(0.16,1,0.3,1) 0.08s both; }
    .kjp-scholar[open] .kjp-reg--journey .kjp-cert       { animation: kjp-reg-rise 0.4s cubic-bezier(0.16,1,0.3,1) 0.12s both; }
    .kjp-scholar[open] .kjp-reg--world                   { animation: kjp-reg-rise 0.4s cubic-bezier(0.16,1,0.3,1) 0.14s both; }
}
/* TRANSFORM-ONLY rise (no opacity fade) so the note is legible EVEN IF the animation
   never completes: the battery-saver (html.app-backgrounded *{animation-play-state:
   paused}) freezes animations, and with an opacity keyframe + `both` fill a tab
   backgrounded mid-open used to hold the `from` state (opacity:0) — the scholar
   note's first half rendered invisible and didn't recover on return. Animating only
   the transform means a frozen reveal is at worst 6px low, always readable. */
@keyframes kjp-reg-rise {
    from { transform: translateY(6px); }
    to { transform: translateY(0); }
}
@media (pointer: coarse) { .kjp-scholar-cue { min-height: 44px; } }
@media (max-width: 560px) {
    .kjp-reg--impressed .kjp-reg-prose { padding-right: 0; }
    .kjp-impression { display: none; }
}
@media (max-width: 440px) { .kjp-reg-prose { max-width: none; } }

/* ── look-alikes (似ている字) — quiet distinction, not a matchup ─────────── */
/* Two glyphs set calmly apart under a readings-row label, divided by ONE faint
   vertical hairline. The current character rests flat ("this character"); the
   look-alike is a tappable door into its own page (dashed under-brush + a gentle
   warm hover wash + 1px lift). No "VS", no arrow, no indigo navigation. */
.kjt-head { margin: 0 0 2px; }
.kjt-pair {
    display: grid;
    grid-template-columns: 1fr 1px 1fr;
    align-items: stretch;
    margin: 4px 0 0;
}
/* the single faint seam — a paper-fold, not a versus mote */
.kjt-seam { width: 1px; background: var(--kjp-rule); margin: 16px 0; }
.kjt-side {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
    padding: 18px 10px 14px;
    background: none;
    border: 0;
    font-family: inherit;
    color: inherit;
}
.kjt-g { font: 400 clamp(50px, 11vw, 68px)/1 'Klee One', 'Noto Sans JP', serif; color: var(--kjp-ink); }
.kjt-kw { margin-top: 7px; font: 600 13px 'Inter', 'Noto Sans JP', sans-serif; color: var(--kjp-ink); }
.kjt-tell { font: 400 12px 'Inter', 'Noto Sans JP', sans-serif; color: var(--kjp-stone); }
.kjt-role { margin-top: 5px; font: 400 11px 'Inter', sans-serif; color: var(--kjp-ghost); letter-spacing: 0.02em; }
/* the look-alike side = a door into its own page; rests flat, lifts gently on
   hover with a warm wash, its cue brightening. Dashed under-brush = tappable. */
.kjt-side--twin { cursor: pointer; border-radius: 8px; transition: background-color 0.18s ease, transform 0.18s ease; }
.kjt-side--twin .kjt-open {
    margin-top: 6px;
    font: 400 11px 'Inter', sans-serif; color: var(--kjp-stone);
    border-bottom: 1px dashed var(--kjp-ghost-soft); padding-bottom: 2px;
    transition: color 0.18s ease, border-color 0.18s ease;
}
.kjt-side--twin:hover { background: rgba(58, 54, 51, 0.035); transform: translateY(-1px); }
.kjt-side--twin:active { background: rgba(58, 54, 51, 0.05); transform: none; }
.kjt-side--twin:hover .kjt-open,
.kjt-side--twin:focus-visible .kjt-open { color: var(--kjp-ink); border-color: var(--kjp-stone); }
.kjt-note {
    font-size: 14px;
    line-height: 1.7;
    color: var(--kjp-prose);
    margin: 16px 0 0;
    padding-top: 16px;
    border-top: 1px solid var(--kjp-rule);
    max-width: min(100%, 62ch);
}

/* (the .kjc-chip pill kit is retired — the hero entry is the word page's
   落款 rakkan marks in word-page.css; paper stickers never reached the art) */

/* ── gallery seam glyph → kanji page affordance ───────────────────────── */

button.grid-seam-kanji {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    transition: color 0.18s ease;
}
button.grid-seam-kanji:hover { color: var(--color-accent); }

/* ── focus + reduced motion + small screens ───────────────────────────── */

.kjp-back:focus-visible,
.kjw-row:focus-visible,
.kjr-more:focus-visible,
.kjt-side--twin:focus-visible,
button.kjp-part--door:focus-visible,
button.grid-seam-kanji:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

@media (max-width: 768px) {
    /* full-bleed page on small screens — no side gutters, hairlines or float shadow */
    .kjp-sheet { width: 100%; border-left: 0; border-right: 0; box-shadow: none; }
    .kjp-body { padding: 0 16px 56px; }
    .kjp-band { height: 170px; margin: 0 -16px; }
    .kjp-band .kjp-glyph, .kjp-inkhead .kjp-glyph { font-size: 88px; }
    /* the versus tray stays side-by-side on mobile — comparing the two shapes is the point */
    .kjp-back { width: 44px; height: 44px; }   /* the primary exit clears the 44px touch min */
}

/* narrow phones: tighten the rows + drop the rank column (demo parity) */
@media (max-width: 560px) {
    .kjw-row { gap: 11px; }
    .kjw-tile { width: 62px; height: 41px; }
    .kjw-jp { font-size: 20px; }
    .kjw-row .rank { display: none; }
    .kjr-head .kjr-sub { display: none; }    /* no rank rail for rows to echo → drop the head count */
    .kjr-more { margin-left: 73px; }         /* re-align to the shrunk lemma column (5+62+11) */
}

@media (prefers-reduced-motion: reduce) {
    /* a scoped blanket reset — the old enumerated allow-list had drifted (the glyph
       cross-fade, image fades, glance pills, reveal + the smooth-scroll still moved).
       Neutralize everything inside the overlay; the JS smooth-scroll is guarded too. */
    .kjp-overlay *, .kjp-overlay *::before, .kjp-overlay *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }
    .kjp-sheet { transform: none; }
    button.grid-seam-kanji { transition: none; }
}

/* ── TYPE signal — what KIND of kanji + what to DO (owner: the valuable part) ──
   A calm centred line at the head of the shape scene: a quiet mark, the plain
   bucket name, the 六書 term whispered, then a plain-English action line. The
   mark vocabulary is always paired with its word, never decoded alone. */
.kjp-type {
    display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
    column-gap: 8px; row-gap: 2px; margin: 0 0 16px;
}
/* the boxy mark is retired — the name carries the type signal now (de-badge) */
.kjp-tmark { display: none; }
.kjp-type--picture .kjp-tmark { border: 1.5px solid var(--kjp-indigo);
    background: color-mix(in srgb, var(--kjp-indigo) 42%, transparent); }
.kjp-type--combine .kjp-tmark::before { content: "+"; position: absolute; inset: -2px 0 0;
    display: flex; align-items: center; justify-content: center; font: 700 16px var(--kjp-ui); color: var(--kjp-indigo); }
.kjp-type--sound .kjp-tmark { border: 1.5px solid var(--kjp-indigo);
    background: linear-gradient(90deg, color-mix(in srgb, var(--kjp-indigo) 50%, transparent) 0 50%, transparent 50%); }
.kjp-type--memory .kjp-tmark { border: 1.5px solid var(--kjp-indigo); border-radius: 50%; }
.kjp-type--fused .kjp-tmark { border: 1.5px dashed var(--kjp-ghost);
    background: color-mix(in srgb, var(--kjp-ghost) 20%, transparent); }
/* the English bucket name LEADS the eyebrow — for a beginner 象形/会意 is unreadable
   jargon, so the plain word is the lesson (the reading eyebrow leads with 訓読み because
   THERE the JP term is the lesson; kinship is shared voice, not identical lead-order). */
.kjp-tname { font: 600 14px var(--kjp-ui); color: var(--kjp-ink); letter-spacing: 0.01em; }
.kjp-type--fused .kjp-tname { color: #7a6a52; }
/* the 六書 term is a quiet Klee companion, not a basement whisper */
.kjp-tjp { font: 400 12.5px var(--kjp-jp); color: var(--kjp-stone); opacity: 0.85; letter-spacing: 0.04em; }
/* the action is the standfirst/deck — colour-matched to .kjr-eb-note so the type
   eyebrow and the reading eyebrows share one note voice */
.kjp-tact { flex-basis: 100%; text-align: center; font: 400 12px var(--kjp-ui);
    color: var(--color-stone); line-height: 1.5; margin-top: 3px; }

/* a phonetic-only part wears a quiet SOUND tag; its chip a faint indigo edge */
.kjp-snd { font: 700 9px var(--kjp-ui); letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--kjp-indigo); background: rgba(61, 90, 128, 0.09); border-radius: 4px;
    padding: 2px 5px; margin-left: 1px; }
.parts .door.kjp-part--sound { border-color: rgba(61, 90, 128, 0.30); }
/* the meaning part wears a calm neutral tag — the borrowed SOUND part stays the
   one accent, so the eye reads "this side means, that side only sounds" */
.kjp-mng { font: 700 9px var(--kjp-ui); letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--kjp-stone); background: rgba(64, 53, 40, 0.06); border-radius: 4px;
    padding: 2px 5px; margin-left: 1px; }
.parts .door.kjp-part--meaning { border-color: rgba(64, 53, 40, 0.18); }

/* the quiet line that frames the meaning/sound pills now that the 形声 header is
   gone — a beginner reads what the two pills mean before scanning the chips. The
   two words tint to echo their pills: meaning = sumi, sound = the indigo accent. */
.kjp-parts-cap {
    text-align: center; margin: 0 0 14px;
    font: 400 12.5px var(--kjp-ui); color: var(--kjp-stone); letter-spacing: 0.01em;
}
.kjp-parts-cap b { font-weight: 600; }
.kjp-parts-cap .kjp-cap-m { color: var(--kjp-ink); }
.kjp-parts-cap .kjp-cap-s { color: var(--kjp-indigo); }

/* a fused part is a worn-down leftover, not a meaning piece: dashed + faded, no door */
.parts .door.kjp-part--ghost { border-style: dashed; border-color: rgba(64, 53, 40, 0.26); }
.parts .door.kjp-part--ghost .g,
.parts .door.kjp-part--ghost .n { color: var(--kjp-ghost); }

/* the sum token: two meanings visibly add up to the kanji (日 + 月 → 明) */
.kjp-plus { font: 600 17px var(--kjp-jp); color: var(--kjp-ghost-soft); }
.kjp-eq { font: 400 15px var(--kjp-ui); color: var(--kjp-ghost); }
.kjp-sum-k { font-family: var(--kjp-jp); font-size: 30px; color: var(--kjp-ink); line-height: 1; }

/* a reading's un-activated example: a real word with no card yet, rendered as a
   TEXT FRAME — reading + gloss + rank, no thumbnail slot (K4: the reserved grey
   plate read as a broken image; the word page's meet-later frames are the
   precedent). Flush left, quieter ink — a lighter entry in the same list. */
.kjw-row--nocard { cursor: default; }
/* rendaku note on a まるごと top-up row (voiced from とけい) — a quiet third line
   under the gloss, same register as the kun/on voiced note. */
.kjw-voiced {
    display: block;
    margin-top: 1px;
    font: 400 11px 'Inter', 'Noto Sans JP', sans-serif;
    color: #8a847b;
}
.kjw-voiced [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 1.1em;
    color: var(--color-stone);
}
.kjw-row--nocard:hover { background: none; padding-left: 5px; }
.kjw-row--nocard .kjw-jp { font-weight: 500; color: var(--kjp-prose); }

/* the homograph note — one quiet line under the gloss on a same-spelling twin
   (何時 なんどき names なんじ as the usual reading). The word page's 同 "written
   the same" lesson, inlined; kana in Klee, romaji italic (romaji-only rule). */
.kjw-note {
    display: block;
    margin-top: 2px;
    font: 400 12px 'Inter', 'Noto Sans JP', sans-serif;
    color: #8a847b;
}
.kjw-note b[lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-weight: 500;
    font-size: 1.15em;
    color: var(--color-stone);
}
.kjw-note i { font-style: italic; }
/* no painting yet → a PRIMED PLATE (owner pick C): the frame is reserved and washed
   faint warm in the room's pigment, reading as a blank canvas waiting for its painting
   (the word just isn't activated yet) — never a broken/loading box, never an empty void.
   Same soft frame + top-left sheen as a real tile; grain off so the plate stays clean.
   (Owner 2026-06-29: kept as the no-painting frame for word rows AND kanji-family rows —
   a reserved frame reads as "a picture goes here", more useful than empty space.) */
.kjw-tile--empty {
    background: color-mix(in srgb, var(--kjp-tone, #b0a090) 13%, var(--kjp-paper));
    /* inset hairline only — no outer drop shadow: a primed plate is a recess pressed
       INTO the washi, not a floating card. */
    box-shadow: inset 0 0 0 1px rgba(120, 90, 60, 0.10);
}
.kjw-tile--empty::after { display: none; }   /* grain off — the sheen (::before) stays */
/* (.rank.is-nocard removed 2026-06-27 — dead: no JS ever emitted it; rankChip uses
   is-freq/is-rare for the no-numeral states.) */

/* readings at a glance — the helicopter view of all readings, under the keyword */
.kjp-glance { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
    column-gap: 18px; row-gap: 8px; margin-top: 11px; }   /* wider gap separates kun vs on families */
/* the group is now just a colour-scoped container (no 訓/音 label, no tap); each reading
   inside is its own tap button. kun = indigo, on = terracotta — the colour carries the
   kun/on distinction the labels used to. */
.kjg-grp { display: inline-flex; align-items: baseline; gap: 6px; --rd-accent: var(--color-accent); }
.kjg-grp--on { --rd-accent: #9E5E43; }
/* each reading is its own tap target → jumps to that reading's word list */
.kjg-pair { display: inline-flex; align-items: baseline; gap: 4px;
    appearance: none; border: 0; background: none; font: inherit; color: inherit;
    cursor: pointer; padding: 4px 6px; margin: -4px 0; border-radius: 7px;
    transition: background-color 0.18s ease; }
.kjg-pair.kjg-tap:hover { background: rgba(58, 54, 51, 0.05); }
.kjg-pair.kjg-tap:active { background: rgba(58, 54, 51, 0.08); }
.kjg-pair:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; }
.kjg-r { font: 400 16px var(--kjp-jp); color: var(--rd-accent, var(--kjp-ink)); }
/* (no under-rule on the glance readings — owner: the per-reading colour + the hover
   wash carry the tappable tell; the underline read as clutter.) */
.kjg-ro { font: 400 11px var(--kjp-ui); color: #6b6358; letter-spacing: 0.02em; }
.kjg-dot { color: var(--kjp-ghost-soft); }
/* (.kjg-gap divider removed — kun/on now separate by colour + the wider column-gap, so
   nothing orphans when the glance line wraps.) */

/* ════════════════════════════════════════════════════════════════════════════
   声符 SOUND FAMILY — kanji that share this kanji's phonetic component, grouped
   by reading. Opened by tapping the SOUND pill in the shape story; rows reuse the
   reading-list .kjw-* look. Indigo = the selection/eyebrow accent, terracotta
   (#9E5E43, the on'yomi colour) = readings, NO gold. Design locked 2026-06-28.
   ════════════════════════════════════════════════════════════════════════════ */
/* Tier-2: the SOUND pill is a DOOR into the sound family room. Its cue is a static
   forward chevron ("step in"), echoing the component-door go-arrow. */
.kjp-snd.kjsf-pill { display: inline-flex; align-items: baseline; gap: 3px; }
.kjp-snd.kjsf-pill::after {
    content: '\203A'; font-weight: 700; font-size: 10px; color: var(--kjp-ghost);
}
/* the sound chip, now a family door, gets a quiet indigo ring on hover (scoped past
   the overlay button-reset so it is not zeroed) */
.kjp-overlay .kjp-part--sound.kjsf-door:hover,
.wpn-kbody .kjp-part--sound.kjsf-door:hover {
    box-shadow: inset 0 0 0 1px rgba(61, 90, 128, 0.5);
}

/* ══════════════════════════════════════════════════════════════════════════════
   THE FAMILY ROOM (Tier-2 view-swap) — the panel body becomes one focused family,
   entered from a story pill and left by the sheet's back chevron. A compact header
   anchors WHOSE family this is (時 › 寺) so the reader keeps the thread; the family's
   own eyebrow + note + roster render below (the .kjsf / .kjmf inner, reused verbatim).
   ══════════════════════════════════════════════════════════════════════════════ */
.kjfam-room { animation: kjfamRoomIn 0.28s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes kjfamRoomIn { from { transform: translateY(5px); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .kjfam-room { animation: none; } }
.kjfam-head {
    display: flex; align-items: center; gap: 9px;
    padding: 2px 0 14px; margin-bottom: 4px;
    border-bottom: 1px solid var(--kjp-rule);
}
.kjfam-glyph {
    font-family: var(--kjp-jp); font-size: 30px; line-height: 1; color: var(--kjp-ink);
}
.kjfam-arrow { font: 400 16px var(--kjp-ui); color: var(--kjp-ghost-soft); }
/* the shared piece, tinted by family: terracotta = the sound key, indigo = meaning */
.kjfam-piece { font-family: var(--kjp-jp); font-size: 26px; line-height: 1; }
.kjfam-room--sound   .kjfam-piece { color: #9E5E43; }
.kjfam-room--meaning .kjfam-piece { color: var(--kjp-indigo); }

/* the sound family renders inside the family room (familyRoomHTML); no standalone
   section margin or hidden state any more (it is summoned, never resting in the spine) */
.kjsf { margin-top: 0; }
.kjsf[hidden] { display: none; }
/* NEVER overflow:hidden here — it clips the picture-less rows and eats the rank chip */
.kjsf-inner { padding-top: 4px; }

/* the eyebrow names the sound piece (the 寺 family) as a door to its own page */
.kjsf-eb {
    /* shares the reading section's teaching-title spec (.kjr-eyebrow): same colour
       #78716c + 0.12em tracking, so 訓読み / 音読み / 声符 / なかま read as one family
       of section titles instead of four slightly-different eyebrows. */
    font: 600 11px var(--kjp-ui); letter-spacing: 0.12em; text-transform: uppercase;
    color: #78716c; margin-bottom: 10px;
    display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
}
.kjsf-eb .jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 15px;
    letter-spacing: 0; color: var(--kjp-ink); text-transform: none;
}
.kjsf-ebpiece {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 16px;
    color: var(--kjp-ink); text-transform: none; letter-spacing: 0;
}
/* the eyebrow piece is a button → re-assert past the overlay reset. Underlined in the
   sound family's own colour (terracotta = the on'yomi/sound side), so the 声符 eyebrow
   reads as the SOUND room and the 意符 eyebrow (indigo) as the MEANING room. */
.kjp-overlay button.kjsf-ebpiece,
.wpn-kbody button.kjsf-ebpiece {
    cursor: pointer; text-decoration: underline;
    text-decoration-color: rgba(158, 94, 67, 0.40); text-underline-offset: 3px;
}
.kjp-overlay button.kjsf-ebpiece:hover,
.wpn-kbody button.kjsf-ebpiece:hover { text-decoration-color: #9E5E43; }
.kjp-overlay button.kjsf-ebpiece:focus-visible,
.wpn-kbody button.kjsf-ebpiece:focus-visible { outline: 2px solid #9E5E43; outline-offset: 2px; border-radius: 3px; }

/* the honesty heads-up (look-alike / worn-down / hidden marker) */
.kjsf-honest { margin: 10px 0 0; font: 400 12.5px/1.6 var(--kjp-ui); color: var(--kjp-stone); }
.kjsf-honest .wp-jp { font-family: 'Klee One', 'Noto Sans JP', sans-serif; color: var(--kjp-prose); }

/* reading groups — each echoes the panel's reading groups: a terracotta on'yomi
   header + romaji, with one full-width hairline under it (NOT a line per row) */
.kjsf-grp { margin-top: var(--kjw-grp-gap); }   /* shared group rhythm (was 10px; owner consistency 2026-06-29) */
.kjsf-ghead {
    display: flex; align-items: baseline; gap: 9px; margin: 0 0 4px; padding: 0 2px 9px;
    border-bottom: 1px solid var(--kjp-rule);
}
.kjsf-ghead .rd { font: 400 19px 'Klee One', 'Noto Sans JP', sans-serif; color: #9E5E43; }
.kjsf-ghead .ro { font: 400 12px var(--kjp-ui); color: var(--kjp-stone); }
.kjsf-ghead .cnt { font: 400 11px var(--kjp-ui); color: var(--kjp-ghost); margin-left: auto; }
.kjsf-foot { margin: 16px 0 0; font: 400 12.5px/1.5 var(--kjp-ui); font-style: italic; color: var(--kjp-stone); }

/* ── ONE shared kanji-family member row (声符 sound family + 意符 meaning family) ──
   The panel's word-row look, tuned for a single glyph: a painting placard (the
   kanji's story image, or a primed-plate frame when it has none) · glyph · reading ·
   meaning · rank. Both families share this one row grammar so a learner meets it
   once; the only structural delta is the SEPARATION — the sound family leans on its
   reading-group hairline (no per-row border), the meaning family is a flat list
   (a faint per-row rule). The reading chip (.kjw-rd) + the current-kanji wash
   (.kjw-here) were byte-identical kjsf-*/kjmf-* twins — collapsed here. */
.kjw-row--kanji {
    align-items: center; overflow: visible;
    width: 100%; box-sizing: border-box; border-bottom: none;
}
.kjw-row--kanji .kjw-jp { font-size: 26px; line-height: 1.2; }
.kjw-row--kanji .kjw-main { gap: 2px; }
.kjw-gl-row { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
/* the member's reading: on'yomi romaji beside the glyph, in the on'yomi terracotta —
   colour carries the reading type, shared by both families. */
.kjw-rd { font: 400 13px var(--kjp-ui); color: #9E5E43; letter-spacing: 0.01em; }
/* kanji freq ranks run to 4 digits — give the chip room and never wrap it */
.kjw-row--kanji .rank { min-width: 52px; white-space: nowrap; flex: 0 0 auto; }
/* a "meet later" member (not in the app yet) rests a hair quieter */
.kjsf .kjw-row--nocard, .kjmf .kjw-row--nocard { opacity: 0.92; }
/* the current kanji, marked silently: a soft WARM rest-wash, fully rounded, no bar
   (owner 2026-06-29). The [data-here] selector also catches the meet-later DIV rows,
   which carried the attribute but had no matching CSS — so the current kanji could
   render unmarked on a picture-less row. */
.kjw-row--kanji.kjw-here,
.kjw-row--kanji.kjw-here:hover,
.kjw-row--kanji[data-here] {
    background: color-mix(in srgb, var(--kjp-tone, #b0a090) 16%, transparent);
    border-radius: 10px;
}
/* sound family: rows sit under the group's reading hairline — no per-row border */
.kjsf .kjw-row--kanji { border-top: none; }

/* ════════════════════════════════════════════════════════════════════════════
   意符 MEANING FAMILY (なかま nakama) — kanji that share this kanji's MEANING
   piece, a flat neighbourhood. The DELIBERATELY weaker sibling of the sound
   family: indigo accent (the calm meaning-side colour, echoing the kun reading)
   and NO terracotta reading headers — that flat shape is the honest signal it is
   a different kind of tool. Opened by tapping the MEANING pill.
   ════════════════════════════════════════════════════════════════════════════ */
/* the MEANING pill is a DOOR into the meaning family room: a static forward chevron
   ("step in"), matching the SOUND pill so both families open the same way. */
.kjp-mng.kjmf-pill { display: inline-flex; align-items: baseline; gap: 3px; }
.kjp-mng.kjmf-pill::after {
    content: '\203A'; font-weight: 700; font-size: 10px; color: var(--kjp-ghost);
}
/* the meaning chip, now a family door, gets a quiet indigo ring on hover (scoped
   past the overlay button-reset so it is not zeroed) */
.kjp-overlay .kjp-part--meaning.kjmf-door:hover,
.wpn-kbody .kjp-part--meaning.kjmf-door:hover {
    box-shadow: inset 0 0 0 1px rgba(61, 90, 128, 0.45);
}

/* the family, revealed below the sound family */
.kjmf { margin-top: 0; }
.kjmf[hidden] { display: none; }
.kjmf-inner { padding-top: 4px; }   /* never overflow:hidden — it clips rank chips */

/* the eyebrow: なかま nakama · the 日 family, with the plain-English concept */
.kjmf-eb {
    /* same shared teaching-title spec as .kjsf-eb / .kjr-eyebrow */
    font: 600 11px var(--kjp-ui); letter-spacing: 0.12em; text-transform: uppercase;
    color: #78716c; margin-bottom: 4px;
    display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
}
.kjmf-eb .jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 15px;
    letter-spacing: 0; color: var(--kjp-ink); text-transform: none;
}
.kjmf-ebpiece {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif; font-size: 16px;
    color: var(--kjp-ink); text-transform: none; letter-spacing: 0;
}
.kjmf-concept {
    text-transform: none; letter-spacing: 0; font-weight: 400; font-style: italic;
    color: var(--kjp-indigo); margin-left: 2px;   /* the meaning-side accent (kun colour) */
}
/* the eyebrow piece is a button → re-assert past the overlay reset */
.kjp-overlay button.kjmf-ebpiece,
.wpn-kbody button.kjmf-ebpiece {
    cursor: pointer; text-decoration: underline;
    text-decoration-color: rgba(61, 90, 128, 0.35); text-underline-offset: 3px;
}
.kjp-overlay button.kjmf-ebpiece:hover,
.wpn-kbody button.kjmf-ebpiece:hover { text-decoration-color: var(--kjp-indigo); }
.kjp-overlay button.kjmf-ebpiece:focus-visible,
.wpn-kbody button.kjmf-ebpiece:focus-visible { outline: 2px solid var(--kjp-indigo); outline-offset: 2px; border-radius: 3px; }

/* the honest asymmetry line (and the "looks like the moon" heads-up) */
.kjmf-honest { margin: 10px 0 0; font: 400 12.5px/1.6 var(--kjp-ui); color: var(--kjp-stone); }
.kjmf-honest .wp-jp { font-family: 'Klee One', 'Noto Sans JP', sans-serif; color: var(--kjp-prose); }
/* the nikuzuki / funazuki note earns a faint indigo left-rail — a real heads-up */
.kjmf-lookalike {
    padding: 8px 0 8px 12px; margin-top: 12px;
    box-shadow: inset 2px 0 0 rgba(61, 90, 128, 0.30);
}

/* ── 意符 MEANING family PERSONA (owner 2026-06-29: the two families read identical;
   give each its own honest voice). The sound family predicts a reading (terracotta,
   grouped). The meaning family only gathers a topic, so it leads with the MEANING and
   makes NO reading claim. Two subtractive moves carry it:
   1. DROP the per-row hairline — it was the real cause of the "tighter than the others"
      feeling (a dense ledger). The flat run now breathes on the same row pitch as the
      sound family's grouped rows; nothing fences every neighbour.
   2. The English gloss LEADS (inked, a touch larger/heavier) and the per-row reading
      falls to a neutral grey whisper — never terracotta, because terracotta means
      "a reading you can predict" and this family predicts none. The visible grey
      variety (ji / sei / sho ...) is itself the honest proof the meaning piece does
      not fix the reading. */
.kjmf .kjw-row--kanji { border-top: none; }
.kjmf .kjw-en { color: var(--kjp-prose); font-size: 13.5px; font-weight: 500; }
.kjmf .kjw-rd { color: var(--kjp-ghost); font-size: 11.5px; }
/* a faded member: a quiet uppercase tag by the glyph + its one-line truth note
   under the gloss. The kanji is a real member; only the meaning LINK is faded, so
   the row stays fully legible — the tag and note do the honest work. */
.kjmf-tag {
    font: 700 9px var(--kjp-ui); letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--kjp-stone); background: rgba(64, 53, 40, 0.07);
    border-radius: 4px; padding: 2px 5px; align-self: center;
}
.kjmf-note {
    display: block; margin-top: 2px;
    font: 400 11.5px/1.5 var(--kjp-ui); font-style: italic; color: var(--kjp-stone);
}
/* (the current-kanji wash + the reading chip are now the shared .kjw-here /
   .kjw-rd rules in the sound-family block above — kjmf-here / kjmf-rd were
   byte-identical twins, collapsed.) */

/* =============================================================================
   FULL-PAGE FRAME (revision #2) — the kanji page IS the word page, kanji content
   -----------------------------------------------------------------------------
   The root carries BOTH .wp-root (the word-page frame from css/word-page.css:
   the fixed scroller, the pinned .wp-stage hero, the rising .wp-sheet catalog
   and its cue↔running-head lip) AND .kjp-overlay (so every kanji-content rule
   scoped `.kjp-overlay …` plus the CSS-var block keep matching). These few rules
   reconcile the two frames and dress the kanji hero variant. The former drawer
   rules (.kjp-scrim / .kjp-sheet / .kjp-bar / .kjp-back) are now inert — no
   element carries those classes.
   ============================================================================= */

/* sit above the word page (z 9000); kill wp-root's wpArrive so only the .kjp-in
   opacity fade runs the entrance. */
.wp-root.kjp-overlay { z-index: 9100; animation: none; }
.kjp-overlay.kjp-in { opacity: 1; }

/* the content column: .wp-entry (from word-page.css) owns the centred width +
   padding; .kjp-body keeps only the content typography and its tone-wash
   ::before, so shed the old drawer role (its own scroll + drawer padding). */
.wp-root .kjp-body {
    position: relative;   /* the .kjp-body::before tone wash anchors to the column */
    flex: none;
    overflow: visible;
    padding: 0;
}

/* ── the pinned hero, kanji variant ──────────────────────────────────────── */
/* one big glyph inscribed top-right like a gasan — no multi-column ruby machine */
.kjp-hero .wp-gasan { top: 44px; right: 60px; }
.kjp-hero .wp-word {
    font-size: clamp(140px, 25vh, 300px);
    line-height: 0.86;
    writing-mode: horizontal-tb;   /* a single character needs no vertical column */
}
/* the keyword sits in the placard's gloss slot; quiet its · separators */
.kjp-hero .kjp-kw-sep { opacity: 0.5; }
/* a gated kanji always ships art, but guard the empty case with a toned plate */
.kjp-paint--empty { position: absolute; inset: 0; background: var(--kjp-tone, #b0a090); }

@media (max-width: 768px) {
    .kjp-hero .wp-gasan { top: 24px; right: 24px; }
    .kjp-hero .wp-word { font-size: clamp(96px, 20vh, 200px); }
}
