/* =============================================================================
   study-walk.css — the 稽古 (keiko) SESSION ROOM dress
   -----------------------------------------------------------------------------
   Port of the owner-locked 舞台 room (design-mockups/keiko-room/ma.html +
   room.css, commit 8dafd534a4). The transient answer: no standing furniture.
   During an ask the room is EMPTY on purpose (the inhale — retrieval gets
   stillness); at the reveal the word's material settles around the card as
   loose washi slips (the exhale), and departs with the card.

   Tokens ride in from css/tokens.css; the room adds only its own AA raises
   and the warm shadow system (--sh: every shadow cast in sumi-brown, never
   neutral gray — a gray halo on warm paper is the "floating div" tell).
   ============================================================================= */

/* ── the room replaces the wall while the walk is up ──────────────────────── */
.keiko-walk-active #gridCards { display: none; }
/* the session lintel claims row 2: the wall's under-beam furniture (the +Filter
   strip, the 蔵 reference board + status subtabs + study count, the Hide tool)
   stands down while the walk is up; the Browse|Study tabs stay (the way back).
   Precedent: body.chat-mode chrome-hide. Post-#687 homes: #toolStrip holds the
   filter group, #browseSubrow the board/subtabs/count, .kamoi-right the Hide. */
body.keiko-walk-active #toolStrip,
body.keiko-walk-active #browseSubrow,
body.keiko-walk-active .kamoi-left #filterAddBtn,
body.keiko-walk-active .kamoi-right .tool-group-hide { display: none !important; }
/* (the journey title wall's hide rule left with the wall itself —
   retired app-wide, nav rethink 2026-07-16) */

#keikoWalk {
    /* the room's light + hands */
    --sh: 67, 50, 30;
    --moss-aa: #5E7050;
    --amber-aa: #7A6230;
    --track-eyebrow: 0.12em;
    /* the kanji family inks — ONE source for the locked reading colours
       (kun = native indigo / on = borrowed terracotta) and the clay marker
       ink (注/由来/似); these were ~10 raw hex repeats before S3.5-C */
    --kw-kun: var(--color-accent);
    --kw-on: #9E5E43;
    --kw-clay: #A05C3B;
    /* IMMERSIVE SCALE (owner 2026-07-08): the room grows with the viewport —
       card, painting, type, tiles, slips and stones ride the same breath. */
    --kw-card-w: clamp(560px, 36vw, 748px);
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - 210px);
}

/* ── the lintel — the session board on the nav's ROW 2, in the Browse
   board's exact slot AND CLASS: #kwLintel wears .browse-subrow, so its
   geometry has ONE definition (ink-wash-tabs.css), and its number/label
   ride the beam's shared stamp rules there too — the walk's row 2 is the
   Browse board with the volume turned down, never a pixel-twin. Contents
   (nav rethink, owner-approved 2026-07-16): place mark · one number
   (position mid-walk; the live ledger line at the close) · the leave chip.
   The deal's pile cells moved to the threshold shape line + card stamps.
   (Headless fallback — the lintel inside #keikoWalk — renders undressed;
   only tests mount it there.) ─────────────────────────────────────────── */
/* the mark wears the room boards' exact dress (.jsp-jp / .jsp-romaji /
   .jsp-name, home-hall.css) — row 2 names the place in ONE voice whether
   the room browses or practices; only the word changes (道 / 蔵 / 稽古). */
.kw-lintel-mark { display: inline-flex; align-items: baseline; gap: 7px; }
.kw-lintel-mark .jp { font-family: var(--font-jp); font-size: 12px; color: var(--color-amber-deep); line-height: 1; }
.kw-lintel-mark i { font: italic 9.5px var(--font-ui); color: var(--color-amber-deep); margin-left: -3px; }
.kw-lintel-mark .tx {
    font: 600 13px var(--font-ui);
    letter-spacing: -0.1px;
    color: var(--color-ink);
    max-width: min(340px, 24vw);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* the one number slot — [hidden] must out-rank the flex display */
.kw-lintel-mid { display: inline-flex; align-items: center; gap: 18px; }
.kw-lintel-mid[hidden] { display: none; }
.kw-lintel-cell { display: inline-flex; align-items: center; gap: 5px; }
.kw-lintel-leave {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-full);
    padding: 2px 11px;
    font: 400 11px var(--font-ui);
    color: var(--color-stone);
    transition: border-color 0.18s, color 0.18s;
}
.kw-lintel-leave:hover { border-color: var(--color-faint); color: var(--color-ink); }
/* the two-step Escape guard points here (round D) */
.kw-lintel-leave.kw-esc-armed {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}
/* 戻る leads the chip (one JP-led leaving voice across the walk) */
.kw-lintel-leave .jp { font-family: var(--font-jp); margin-right: 5px; }

/* ── the stage column ─────────────────────────────────────────────────────── */
.kw-stagecol {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    position: relative;
    width: 100%;
    max-width: 1560px;
    margin: 0 auto;
    padding: 0 clamp(14px, 2vw, 30px);
}
/* the ground rides a fixed short reach under the card — the stone rests ON
   its floor, never above a distant viewport-bottom band. min-height damps
   ask↔reveal jitter without unmooring. */
.kw-stage {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(8px, 1.5vh, 18px) 0 16px;
    position: relative;
    min-height: clamp(430px, 52vh, 690px);
}
.kw-stage > * { animation: kwArrive 0.5s var(--ease-brush) both; }
.kw-stage > .kw-slipcol { animation: none; }   /* slips time their own arrival */
@keyframes kwArrive { from { opacity: 0; transform: translateY(11px); } to { opacity: 1; transform: none; } }

/* the ground plane — a horizon, not a drawn rule: warm, ends dissolved */
.kw-ground {
    flex: none;
    position: relative;
    border-top: 1px solid rgba(var(--sh), 0.12);
    margin: 6px 8% 0;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.kw-ground::before { /* the faint earth shadow below the line — a floor, not a band */
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 26px;
    background: linear-gradient(180deg, rgba(var(--sh), 0.05), transparent);
    pointer-events: none;
}
/* the close hides the stray horizon; the TRAIL stays on the floor as the
   night's receipt (nav rethink, owner-approved 2026-07-16) — every stamp,
   crack and gold seam inked, settled and non-interactive. On short windows
   it fades rather than pushing the close's own doors below the fold. */
#keikoWalk.kw-closing .kw-ground { display: none; }
#keikoWalk.kw-closing .kw-trail { opacity: 0.85; pointer-events: none; }
/* a caught-up night never built a path — no blank floor reserved for one */
#keikoWalk.kw-closing .kw-trail:empty { display: none; }
@media (max-height: 820px) {
    #keikoWalk.kw-closing .kw-trail { opacity: 0.35; }
}

/* screen-reader status node (stone position + verdict announcements) */
.kw-live {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ── the compact 飛び石 trail — orientation in-walk; the record spreads at
   the close. Width rides the card; stones rest half-on the horizon. ───────── */
.kw-trail {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    /* a real composer deck can deal 20-30 stones (session size 30 / All) —
       the path WRAPS into further rows like the close record; the mockup only
       ever carried 7 */
    flex-wrap: wrap;
    gap: 8px clamp(26px, 2.2vw, 40px);
    width: var(--kw-card-w);
    max-width: 94vw;
    margin: -11px auto 0;
    padding: 0 6px 14px;
    min-height: 64px;
}
.kw-tstep {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    flex: none;
    position: relative;
    transition: opacity 0.45s var(--ease-brush);
}
/* a stone is a flat-topped garden stone catching quiet top light — a hint of
   body, never a polished pearl */
.kw-tstone {
    width: clamp(22px, 1.7vw, 32px);
    height: clamp(22px, 1.7vw, 32px);
    border-radius: 48% 52% 50% 50% / 52% 48% 52% 48%;
    border: 1px solid rgba(120, 112, 96, 0.26);
    position: relative;
    background: linear-gradient(168deg, #efece5, #e6e2d8 70%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 2px rgba(var(--sh), 0.10);
    transition: all 0.45s var(--ease-brush);
    transform: translateY(var(--sway, 0px));   /* garden path, not progress bar */
}
.kw-tstone::before { /* contact shadow — the stone meets its ground */
    content: "";
    position: absolute;
    left: 50%;
    bottom: -3px;
    width: 72%;
    height: 4px;
    transform: translateX(-50%);
    border-radius: 50%;
    background: radial-gradient(ellipse, rgba(var(--sh), 0.12), transparent 72%);
}
.kw-tstep.done .kw-tstone {
    background: linear-gradient(168deg, #e2ddd2, #d8d2c5 70%);
    border-color: rgba(110, 100, 82, 0.32);
}
.kw-tstep.now .kw-tstone {
    border-color: var(--color-stone);
    background: linear-gradient(168deg, #eae6dc, #e2ddd2 70%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3),
        0 0 0 3.5px rgba(87, 83, 78, 0.10), 0 2px 7px rgba(var(--sh), 0.12);
}
.kw-tstep.ahead { opacity: 0.55; }
.kw-tstep.kw-fade { opacity: 0.26; }
/* a long night closes ranks — the stones shrink and tighten so ONE line
   holds up to ~20; the crossing must never read as two floating clumps */
/* density tiers ride ONE data attribute set by renderTrail (12/17/26
   thresholds live there) — tiers are cumulative, hence the selector lists */
.kw-trail[data-density="1"], .kw-trail[data-density="2"], .kw-trail[data-density="3"] { gap: 8px clamp(10px, 1vw, 18px); }
.kw-trail[data-density="1"] .kw-tstone, .kw-trail[data-density="2"] .kw-tstone,
.kw-trail[data-density="3"] .kw-tstone { width: clamp(17px, 1.25vw, 24px); height: clamp(17px, 1.25vw, 24px); }
/* deeper ranks (round D): 17+ takes more floor and retires the stamp
   romaji (the close record keeps it); 26+ tightens the pitch — one line
   holds ~30, and past that the wrap keeps an even row gap by design */
.kw-trail[data-density="2"], .kw-trail[data-density="3"] { width: min(94vw, 1240px); gap: 8px clamp(8px, 0.8vw, 14px); }
.kw-trail[data-density="2"] .kw-tstamp, .kw-trail[data-density="3"] .kw-tstamp { max-width: 60px; }
.kw-trail[data-density="2"] .kw-tstamp .r, .kw-trail[data-density="3"] .kw-tstamp .r { display: none; }
.kw-trail[data-density="3"] { gap: 6px clamp(4px, 0.5vw, 8px); }
.kw-trail[data-density="3"] .kw-tstone { width: clamp(14px, 1.05vw, 20px); height: clamp(14px, 1.05vw, 20px); }
.kw-trail[data-density="3"] .kw-tstamp { max-width: 46px; font-size: clamp(9.5px, 0.68vw, 11px); }
/* the threshold preview — tonight's path laid across the floor, evenly present */
.kw-trail.kw-preview { cursor: pointer; }
.kw-trail.kw-preview .kw-tstep { opacity: 0.85; }
.kw-trail.kw-preview .kw-lantern .kw-tstone { animation: kwLanternWake 1.6s var(--ease-brush) 0.9s both; }
@keyframes kwLanternWake { /* a quiet tonal lift of promise — honey belongs to
    the MEETING (discovery warmth only), so the preview merely stirs */
    0% { background: #e9e2d4; }
    45% { background: #f3edde; }
    100% { background: #e9e2d4; }
}
/* the stamped word appears only once its stone is cleared */
.kw-tstamp {
    font-family: var(--font-jp);
    font-size: clamp(11px, 0.85vw, 13.5px);
    line-height: 1.1;
    color: var(--color-ink);
    max-width: 72px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-height: 13px;
    text-align: center;
}
.kw-tstamp .r { display: block; font: italic 8.5px var(--font-ui); color: var(--color-faint-warm); }
/* sumi settles onto the stone you just cleared — once, on that stone only */
.kw-tstep.kw-just-stamped .kw-tstamp { animation: kwStampInk 0.52s var(--ease-brush) both; }
@keyframes kwStampInk {
    from { opacity: 0; transform: translateY(-3px); filter: blur(1.2px); }
    to { opacity: 1; transform: none; filter: none; }
}
/* discovery slot = a small lantern; lit only after the meeting */
.kw-tstep.kw-lantern .kw-tstone {
    border-radius: 5px 5px 2px 2px;
    width: clamp(17px, 1.25vw, 23px);
    height: clamp(25px, 1.9vw, 35px);
    background: #e9e2d4;
}
.kw-tstep.kw-lantern .kw-tstone::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: var(--color-divider);
}
/* the lit lantern RECORDS the meeting with its warm fill + bright wick — the
   honey HALO is the exhale: one breath when it first lights, then rest */
.kw-tstep.kw-lantern.kw-lit .kw-tstone { background: #f5ead0; animation: kwLanternLit 2.4s var(--ease-brush); }
.kw-tstep.kw-lantern.kw-lit .kw-tstone::after {
    background: radial-gradient(circle, #f9ecc2, rgba(232, 178, 108, 1));
    box-shadow: 0 0 3px rgba(232, 178, 108, 0.6);
}
@keyframes kwLanternLit {
    0% { box-shadow: none; }
    30% { box-shadow: 0 0 12px rgba(232, 178, 108, 0.5); }
    100% { box-shadow: none; }
}
/* a miss cracks the stone in sumi; the gold seam belongs to the comeback (S3).
   Every stone carries its crack path; only .kw-cracked shows it — DRAWN on. */
.kw-crack { position: absolute; inset: 0; pointer-events: none; display: none; }
.kw-tstep.kw-cracked .kw-crack, .kw-tstep.kw-mended .kw-crack { display: block; }
.kw-crack path { stroke: #8a8175; stroke-width: 1.3; fill: none; opacity: 0.85; }
.kw-tstep.kw-cracked .kw-crack path {
    stroke-dasharray: 60;
    stroke-dashoffset: 60;
    animation: kwSeam 0.55s var(--ease-brush) forwards;
}
.kw-tstep.kw-mended .kw-crack path {
    stroke: var(--color-gold);
    stroke-width: 1.6;
    opacity: 1;
    filter: drop-shadow(0 0 2px rgba(212, 184, 124, 0.7));
    stroke-dasharray: 60;
    stroke-dashoffset: 60;
    animation: kwSeam 1s var(--ease-brush) forwards;
}
@keyframes kwSeam { to { stroke-dashoffset: 0; } }

/* ═══ THE CARD — grid-card DNA on a stage, content-height ═════════════════ */
.kw-card { width: var(--kw-card-w); max-width: 94vw; position: relative; }
.kw-card-inner { position: relative; }
.kw-face { display: flex; flex-direction: column; }
.kw-face-ask { position: relative; }
.kw-face-reveal { display: none; }
/* the stone's pile stamp — quiet tracked caps on the card's top corner
   (the beam's stamp voice in faint-warm for AA at 10.5px). Ask face only:
   it retires with the ask (one utterance per element); the reveal and the
   sheet/static cards stay clean. Inert — no seal, no dot. */
.kw-pile-stamp {
    position: absolute;
    top: 13px;
    right: 16px;
    font: 500 10.5px var(--font-ui);
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--color-faint-warm);
    pointer-events: none;
}
.kw-card.kw-settled .kw-pile-stamp,
.kw-card.kw-turning .kw-pile-stamp,
.kw-card.kw-static .kw-pile-stamp { display: none; }
/* ── the TURN (owner bug, 2026-07-08): the old 3D flip flashed a tilted,
   overflowing answer mid-rotation. Now the ask face BOWS OUT (a 240ms breath)
   and only then does the answer enter the flow and settle through the develop
   cascade — there is no visible in-between state, and the card grows to its
   content so the exit can never fall below a clipped fold. ────────────────── */
.kw-card.kw-turning .kw-face-ask { animation: kwAskOut 0.24s var(--ease-page) both; pointer-events: none; }
@keyframes kwAskOut { to { opacity: 0; transform: translateY(-9px) scale(0.985); } }
.kw-card.kw-settled .kw-face-ask { display: none; }
.kw-card.kw-settled .kw-face-reveal { display: flex; }
/* born-open (the discovery) — a single resting face */
.kw-card.kw-static .kw-face-reveal { display: flex; }
.kw-card.kw-static .kw-face-ask { display: none; }

/* ask face = a pinned paper sheet (the WARM paper token — the bright grid
   token read as a lightbox panel on the stone body; elevation round A) */
.kw-face-ask {
    background: var(--color-card);
    border: 1px solid rgba(44, 44, 44, 0.05);
    border-top-color: rgba(255, 255, 255, 0.7);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 3px rgba(var(--sh), 0.05), 0 5px 14px -6px rgba(var(--sh), 0.08),
        inset 0 0 70px rgba(120, 100, 70, 0.035);
    padding: clamp(30px, 2.6vw, 44px) clamp(26px, 2.2vw, 38px) clamp(24px, 2vw, 34px);
    min-height: clamp(400px, 42vh, 540px);
    justify-content: center;
    align-items: center;
    text-align: center;
}
/* faint washi grain on the paper (the card carries the texture, not the body
   — the ONE textured surface, house budget) */
.kw-face-ask::before,
.kw-flipcard .kw-face-reveal::before,
.kw-cxcard .kw-face-reveal::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius-lg);
    pointer-events: none;
    opacity: 0.68;
    background-image: radial-gradient(circle at 20% 30%, rgba(120, 110, 90, 0.05) 0 1px, transparent 1px),
        radial-gradient(circle at 70% 65%, rgba(120, 110, 90, 0.042) 0 1px, transparent 1px);
    background-size: 7px 7px, 11px 11px;
    mix-blend-mode: multiply;
}
.kw-flipcard .kw-face-ask { cursor: pointer; }
.kw-cxcard .kw-face-ask { cursor: pointer; }   /* K2 — the readctx recall-flip */
.kw-ask-jp {
    font-family: var(--font-jp);
    font-weight: 600;
    color: #332F2B;
    line-height: 1.1;
    font-size: clamp(2.5rem, calc(21rem / var(--ja-chars, 5)), 5.4rem);
    font-feature-settings: 'palt' 1;
    text-shadow: 0 0 0.5px rgba(44, 44, 44, 0.12);
}
.kw-ask-jp.kw-compact { font-size: clamp(2rem, calc(16.5rem / var(--ja-chars, 5)), 3.7rem); }
/* the reading is romaji everywhere in this app: italic, amber — one species */
.kw-ask-ro {
    font: italic 500 clamp(1.05rem, 1.05vw, 1.3rem) var(--font-ui);
    letter-spacing: 0.03em;
    color: var(--color-amber-deep);
    margin-top: clamp(6px, 0.55vw, 10px);
}
.kw-ask-q {
    font: 500 clamp(13px, 0.95vw, 16px) var(--font-ui);
    letter-spacing: 0.02em;
    color: var(--color-stone);
    margin-top: clamp(14px, 1.3vw, 22px);
}
.kw-ask-hint {
    font: 400 clamp(12px, 0.85vw, 14px) var(--font-ui);
    color: var(--color-faint-warm);
    margin-top: clamp(18px, 1.9vw, 28px);
}
.kw-ask-hint .jp { font-family: var(--font-jp); margin-left: 7px; }
.kw-ask-hint i { font-style: italic; margin-left: 5px; }
.kw-ask-hint kbd {
    font: 500 10px var(--font-ui);
    color: var(--color-faint-warm);
    border: 1px solid var(--color-divider);
    border-bottom-width: 2px;
    border-radius: 4px;
    padding: 0 5px;
    margin: 0 2px;
    background: rgba(255, 255, 255, 0.5);
}

/* choice tiles — pressable paper */
.kw-choices {
    display: flex;
    flex-direction: column;
    gap: clamp(11px, 1vw, 15px);
    margin-top: clamp(18px, 1.6vw, 26px);
    width: 100%;
    max-width: clamp(340px, 27vw, 470px);
    align-items: stretch;
}
.kw-choices--images {
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    max-width: none;
    width: 100%;
    gap: clamp(12px, 1.2vw, 18px);
}
.kw-choice {
    appearance: none;
    cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.13);
    border-radius: 10px;
    color: var(--color-ink);
    font-family: var(--font-ui);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 3px 8px -6px rgba(var(--sh), 0.14);
    transition: border-color 0.18s var(--ease-settle), box-shadow 0.18s, transform 0.18s,
        opacity 0.18s, background 0.22s var(--ease-settle);
}
.kw-choice:hover {
    border-color: var(--color-accent);
    box-shadow: 0 5px 13px -6px rgba(var(--sh), 0.22);
    transform: translateY(-1px);
}
/* the commit tap PRESSES (round B) — paper gives under the finger; a
   hover that only lifts reads as glass */
.kw-choices:not(.kw-locked) .kw-choice:active {
    transform: translateY(0.5px) scale(0.995);
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05);
    transition-duration: 0.06s;
}
/* the numeral is the 1/2/3 keyboard map — faint-warm holds AA at this size */
.kw-choice .num { font: 400 10px var(--font-ui); color: var(--color-faint-warm); width: 12px; flex: none; font-variant-numeric: tabular-nums; }
.kw-choice--gloss { padding: clamp(12px, 1vw, 15px) 18px; font-size: clamp(15px, 1.05vw, 17.5px); font-weight: 500; line-height: 1.35; }
/* three paintings share ONE row at gallery size — they split the see-card's
   inner width between them (the old 300px cap left them small on a wide
   wall); a painting is framed by an inset hairline, never a gray keyline —
   and the numeral lives on a small placard strip OFF the art (never ON a
   painting) */
.kw-choice--image {
    flex: 1 1 0;
    min-width: 0;
    max-width: 390px;
    padding: 0;
    overflow: hidden;
    position: relative;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    border: none;
    box-shadow: inset 0 0 0 1px rgba(var(--sh), 0.10), 0 3px 9px -5px rgba(var(--sh), 0.26);
}
.kw-choice--image:hover { box-shadow: inset 0 0 0 1.5px var(--color-accent), 0 7px 16px -7px rgba(var(--sh), 0.30); }
.kw-choice--image img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; }
.kw-choice--image .num { width: 100%; padding: 3px 0 4px; text-align: center; color: var(--color-faint-warm); font-variant-numeric: tabular-nums; }
/* a painting the CDN failed to serve — the word stands in on paper; the
   tile never collapses to a blank frame (round A) */
.kw-choice--image .kw-img-fb { display: none; }
.kw-choice--image.kw-img-lost .kw-img-fb {
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 3 / 2;
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(1.3rem, 1.6vw, 1.8rem);
    color: var(--color-stone);
    background: var(--color-card);
}
/* verdict rings on the tiles — moss = the answer, amber = a wrong pick;
   never a ✓/✗, never a mark on the painting itself */
.kw-choice.is-answer {
    box-shadow: inset 0 0 0 2px rgba(107, 127, 92, 0.42);
    background: color-mix(in srgb, var(--color-moss) 6%, transparent);
}
.kw-choice--image.is-answer { box-shadow: inset 0 0 0 2px rgba(107, 127, 92, 0.55), 0 3px 9px -5px rgba(var(--sh), 0.26); }
/* the pick ring wears DRY SEPIA (round B): amber is the sound voice, and
   the mark moment now carries a real amber sound disc — two ambers on one
   face would say two things in one color. The 惜 seal keeps the verdict. */
.kw-choice.is-chosen:not(.is-answer) {
    box-shadow: inset 0 0 0 2px rgba(138, 118, 98, 0.5);
    background: color-mix(in srgb, #8a7662 7%, transparent);
}
.kw-choice--image.is-chosen:not(.is-answer) { box-shadow: inset 0 0 0 2px rgba(138, 118, 98, 0.6), 0 3px 9px -5px rgba(var(--sh), 0.26); }
.kw-choices.kw-locked .kw-choice { cursor: default; pointer-events: none; }
/* every pill teaches once graded (r4) — 0.45 dimmed them past reading */
.kw-choices.kw-locked .kw-choice:not(.is-answer):not(.is-chosen) { opacity: 0.7; }
/* after the mark a marked pill becomes a DOOR (S3.9c) — silent at rest,
   the interactive indigo on hover: the word-door law, tile-shaped */
.kw-choices.kw-locked .kw-choice.kw-door { cursor: pointer; pointer-events: auto; }
.kw-choices.kw-locked .kw-choice.kw-door:hover {
    border-color: var(--color-accent);
    transform: none;
    box-shadow: 0 5px 13px -6px rgba(var(--sh), 0.22);
}
.kw-choices.kw-locked .kw-choice.is-answer.kw-door:hover {
    box-shadow: inset 0 0 0 2px rgba(107, 127, 92, 0.42), 0 5px 13px -6px rgba(var(--sh), 0.22);
}
.kw-choices.kw-locked .kw-choice.is-chosen:not(.is-answer).kw-door:hover {
    box-shadow: inset 0 0 0 2px rgba(138, 118, 98, 0.5), 0 5px 13px -6px rgba(var(--sh), 0.22);
}
/* an image door hovers in ITS OWN voice: a neutral painting speaks the
   interactive indigo (never the answer's moss — a green frame on a wrong
   tile would lie), the ringed tiles keep their verdict tint */
.kw-choices.kw-locked .kw-choice--image.kw-door:hover {
    box-shadow: inset 0 0 0 1.5px var(--color-accent), 0 7px 16px -7px rgba(var(--sh), 0.30);
}
.kw-choices.kw-locked .kw-choice--image.is-answer.kw-door:hover {
    box-shadow: inset 0 0 0 2px rgba(107, 127, 92, 0.55), 0 7px 16px -7px rgba(var(--sh), 0.30);
}
.kw-choices.kw-locked .kw-choice--image.is-chosen:not(.is-answer).kw-door:hover {
    box-shadow: inset 0 0 0 2px rgba(138, 118, 98, 0.6), 0 7px 16px -7px rgba(var(--sh), 0.30);
}
/* a coat that slipped past goes HOLLOW — moss ring, transparent body, ○ in
   the numeral's seat (chamTest's got/missed truth lives on the chips now) */
.kw-choices .kw-choice.is-answer.kw-missed { background: transparent; }
.kw-choice--coat.kw-missed .num { color: var(--amber-aa); font-weight: 600; font-size: 12px; }
/* the replay disc seated on the moss form tile — the answer keeps its
   sound. Scoped to out-rank .kw-form-audio's forms-ladder margin-left:auto
   (the same leak that once pushed the ident disc to the card's far edge) */
.kw-choice .kw-tile-disc { margin-left: 4px; }

/* the listen surface — sound is the signature, no image, no word */
.kw-listen-wrap { display: flex; justify-content: center; margin-bottom: 4px; }
.kw-listen-disc {
    width: clamp(96px, 7vw, 120px);
    height: clamp(96px, 7vw, 120px);
    border-radius: 50%;
    position: relative;
    cursor: pointer;
    border: 1px solid var(--color-divider);
    background: radial-gradient(circle at 50% 45%, #FDFCF9, var(--color-card));
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.2s;
}
.kw-listen-disc:hover { transform: scale(1.03); }
.kw-tri {
    width: 0;
    height: 0;
    border-left: 16px solid var(--color-accent);
    border-top: 11px solid transparent;
    border-bottom: 11px solid transparent;
    margin-left: 5px;
}
/* amber = sound (locked semantics); base opacity 0 = no stuck ring under RM */
.kw-ripple {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1.5px solid rgba(160, 120, 80, 0.5);
    opacity: 0;
}
.kw-listen-disc.playing .kw-ripple { animation: kwRipple 1.2s var(--ease-brush) 1; }
.kw-listen-disc.playing .kw-ripple.r2 { animation-delay: 0.18s; }
.kw-listen-disc.playing .kw-ripple.r3 { animation-delay: 0.36s; }
@keyframes kwRipple {
    0% { transform: scale(0.7); opacity: 0.55; }
    100% { transform: scale(2.1); opacity: 0; }
}

/* ── reveal face — painting on stone, placard below. Content-height, exit
   ALWAYS in view: the fold bug cannot exist here. ─────────────────────────── */
.kw-face-reveal { padding: 0; }
.kw-reveal-img { /* the app's grid-card print shadow, warmed — sumi cast */
    width: 100%;
    aspect-ratio: 3 / 2;
    border-radius: 6px;
    overflow: hidden;
    position: relative;
    isolation: isolate;
    box-shadow: 0 0 0 1px var(--kw-ring, rgba(83, 62, 30, 0.15)),
        0 6px 16px -7px rgba(var(--sh), 0.5), 0 2px 6px -2px rgba(var(--sh), 0.14);
}
.kw-reveal-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* the painting's ring IS the verdict on the art (house law: no marks on a
   watercolor) */
.kw-face-reveal.kw-known .kw-reveal-img { --kw-ring: rgba(107, 127, 92, 0.45); }
.kw-face-reveal.kw-learning .kw-reveal-img { --kw-ring: rgba(160, 120, 80, 0.42); }
/* the reveal settles like a print developing — never a lazy-load fade */
.kw-card.kw-just-revealed .kw-face-reveal > * { animation: kwSettleUp 0.42s var(--ease-brush) both; }
.kw-card.kw-just-revealed .kw-face-reveal > *:nth-child(2) { animation-delay: 0.1s; }
.kw-card.kw-just-revealed .kw-face-reveal > *:nth-child(3) { animation-delay: 0.16s; }
.kw-card.kw-just-revealed .kw-face-reveal > *:nth-child(4) { animation-delay: 0.22s; }
.kw-card.kw-just-revealed .kw-face-reveal > *:nth-child(n+5) { animation-delay: 0.27s; }
@keyframes kwSettleUp { from { opacity: 0.4; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.kw-card.kw-just-revealed .kw-reveal-img img { animation: kwDevelop 0.9s var(--ease-brush) 0.15s both; }
@keyframes kwDevelop {
    from { filter: brightness(1.22) contrast(0.9) saturate(0.82); transform: scale(1.03); }
    to { filter: none; transform: none; }
}

/* 音 + 間 ride the painting's corner — opaque paper tokens with a lit crown,
   resting ON the print rather than dissolving into it */
.kw-corner-disc {
    position: absolute;
    top: 14px;
    z-index: 5;
    width: clamp(33px, 2.4vw, 40px);
    height: clamp(33px, 2.4vw, 40px);
    border: none;
    border-radius: 50%;
    background: rgba(251, 250, 247, 0.94);
    cursor: pointer;
    padding: 0;
    box-shadow: 0 1px 3px rgba(var(--sh), 0.20), 0 3px 8px -3px rgba(var(--sh), 0.14),
        inset 0 0 0 0.5px rgba(44, 44, 44, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.65);
    display: grid;
    place-items: center;
    transition: background 0.2s, box-shadow 0.2s, transform 0.12s;
}
.kw-corner-disc:hover {
    background: rgba(253, 252, 250, 0.98);
    box-shadow: 0 2px 6px rgba(var(--sh), 0.22), 0 4px 10px -3px rgba(var(--sh), 0.16),
        inset 0 0 0 0.5px rgba(44, 44, 44, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.65);
}
.kw-corner-disc:active { transform: scale(0.92); }
/* the sound leaves one amber ripple per tap (amber = sound, locked semantics);
   base opacity 0 = no stuck ring under reduced motion */
.kw-corner-disc.playing::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    pointer-events: none;
    opacity: 0;
    border: 1.5px solid rgba(160, 120, 80, 0.5);
    animation: kwSonar 0.55s var(--ease-brush) forwards;
}
@keyframes kwSonar { from { opacity: 0.7; transform: scale(1); } to { opacity: 0; transform: scale(1.75); } }
.kw-corner-audio { right: 14px; color: var(--color-ink); }
.kw-corner-audio svg { width: clamp(17px, 1.25vw, 21px); height: clamp(17px, 1.25vw, 21px); display: block; }
/* the placard under the painting — the identity trio (furi/headword/romaji)
   reads as one locked block; the switch to meaning gets the air.
   The furigana wears FADED INK, not a hue: terracotta belongs to on'yomi
   alone in this room (fleet 2026-07-09) */
.kw-plq { display: flex; flex-direction: column; padding: clamp(12px, 1.1vw, 18px) 6px 0; text-align: left; }
.kw-plq-furi {
    font-family: var(--font-jp);
    font-size: clamp(12px, 0.9vw, 15px);
    color: rgba(44, 44, 44, 0.55);
    letter-spacing: 0.14em;
    margin-bottom: -1px;
}
.kw-plq-jp {
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(1.6rem, calc(14rem / var(--ja-chars, 5)), 2.5rem);
    color: var(--color-ink);
    line-height: 1.1;
    font-feature-settings: 'palt' 1;
}
/* the discovery's name-beat lands VISIBLY — the headword inks amber for a
   breath while its sound plays (amber = sound, locked semantics) */
.kw-plq-jp.kw-heard { animation: kwHeard 0.6s var(--ease-brush); }
@keyframes kwHeard { 30% { color: var(--color-amber-deep); } }
.kw-plq-ro {
    font: italic clamp(0.85rem, 0.8vw, 1.05rem) var(--font-ui);
    letter-spacing: 0.035em;
    color: var(--color-amber-deep);
    margin-top: 3px;
}
.kw-plq-row { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.kw-plq-en {
    font: 400 clamp(0.95rem, 0.92vw, 1.2rem) var(--font-ui);
    color: rgba(44, 44, 44, 0.72);
    line-height: 1.4;
    flex: 1;
    min-width: 0;
}
.kw-statusline {
    display: flex;
    align-items: center;
    gap: 6px;
    font: 600 clamp(9.5px, 0.72vw, 11.5px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    white-space: nowrap;
}
.kw-statusline .kw-dot { width: 6px; height: 6px; border-radius: 50%; }
.kw-statusline.kw-state-saved { color: var(--amber-aa); }
.kw-statusline.kw-state-saved .kw-dot { background: var(--color-amber); }
.kw-statusline.kw-state-known { color: var(--moss-aa); }
.kw-statusline.kw-state-known .kw-dot { background: var(--color-moss); }
.kw-statusline.kw-state-comeback { color: var(--moss-aa); }
.kw-statusline.kw-state-comeback .kw-dot { background: var(--color-moss-bright); }

/* ── the miss SPLIT (owner 2026-07-09): answer and pick side by side, images
   and text mirrored in anatomy but NOT in weight — the answer wins the frame
   in moss; the pick stands beside it smaller, drained, in amber. ──────────── */
.kw-split { display: flex; gap: clamp(12px, 1.1vw, 17px); align-items: flex-start; }
/* attention drives the SIZE: the viewed card holds the big frame, the other
   steps back — the swap animates; the moss/amber verdict rings never move */
.kw-split-ans, .kw-split-pick { flex: 1 1 0; min-width: 0; transition: flex-grow 0.45s var(--ease-settle); cursor: pointer; }
.kw-split > .kw-viewing { flex-grow: 1.72; }
.kw-split-tag {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin: 0 2px 7px;
    font: 600 clamp(9.5px, 0.72vw, 11px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
}
.kw-split-ans .kw-split-tag { color: var(--moss-aa); }
.kw-split-pick .kw-split-tag { color: var(--amber-aa); }
.kw-split-tag .jp { font-family: var(--font-jp); text-transform: none; letter-spacing: 0; font-size: clamp(11.5px, 0.88vw, 14px); }
.kw-split-tag i { font-style: italic; text-transform: none; letter-spacing: 0.02em; font-weight: 400; }
/* the miss NAMES the confusion — one quiet bridge line under the split when
   the pick is a typed neighbour of the answer */
.kw-relbridge {
    display: flex;
    align-items: baseline;
    gap: 8px;
    justify-content: center;
    margin-top: 10px;
    font: 400 clamp(12px, 0.92vw, 14px) var(--font-ui);
    color: var(--color-stone);
}
.kw-relbridge .ink { flex: none; font-family: var(--font-jp); font-size: clamp(11px, 0.85vw, 13px); color: var(--color-faint-warm); }
.kw-relbridge .jp { font-family: var(--font-jp); color: var(--color-jp-text); }
.kw-relbridge i { font-style: italic; color: var(--color-amber-deep); }

/* ── S3w1: the relation stones ─────────────────────────────────────────────
   WORD tiles — the antonym/related asks deal WORDS: writing + romaji, never
   a gloss (the gloss would hand the answer — the demo's locked law) */
.kw-choice--word { padding: clamp(11px, 0.95vw, 14px) 18px; gap: 10px; }
.kw-choice--word .wj {
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(1.15rem, 1.35vw, 1.45rem);
    line-height: 1.15;
    color: var(--color-jp-text);
}
.kw-choice--word .wr {
    font-style: italic;
    font-size: clamp(0.82rem, 0.85vw, 0.95rem);
    letter-spacing: 0.02em;
    color: var(--color-amber-deep);
}
/* CP-A extended to the rack (owner 2026-07-21): in 'earned' mode the tile
   romaji WAITS on the ask face — it returns on the reveal (settle removes
   kw-ro-wait) or via the romaji chip. Direct child only: the reveal's
   .kw-pill-id identities keep their own .wr untouched. */
.kw-choices.kw-ro-wait .kw-choice > .wr { display: none; }
/* the completed pill (S3.9c — the pills complete themselves): once graded,
   the reading rides as ruby and the first-sense gloss joins the line — the
   tile says everything the retired explanation lines used to */
.kw-choice--word .wj rt { font-size: 0.5em; font-weight: 400; color: var(--color-stone); letter-spacing: 0; }
.kw-choices.kw-locked .kw-choice--word { flex-wrap: wrap; row-gap: 2px; }
.kw-choices.kw-locked .kw-choice--word .wj { line-height: 1.35; }
.kw-choice--word .wg { font: 400 clamp(12.5px, 0.95vw, 15px) var(--font-ui); color: rgba(44, 44, 44, 0.72); }
.kw-choice--word .wg::before { content: '· '; color: var(--color-faint-warm); }
/* the listen / soundalike GLOSS pill completes the other way — its word's
   writing and romaji join the gloss (the heard word's identity returns) */
.kw-choices.kw-locked .kw-choice--gloss { flex-wrap: wrap; row-gap: 2px; }
.kw-pill-id { display: inline-flex; align-items: baseline; gap: 7px; }
.kw-pill-id::before { content: '·'; color: var(--color-faint-warm); font-weight: 400; }
.kw-pill-id .wj {
    font-family: var(--font-jp); font-weight: 600; line-height: 1.35;
    font-size: clamp(1.05rem, 1.1vw, 1.25rem); color: var(--color-jp-text);
}
.kw-pill-id .wj rt { font-size: 0.5em; font-weight: 400; color: var(--color-stone); letter-spacing: 0; }
.kw-pill-id .wr {
    font-style: italic; font-size: clamp(0.8rem, 0.82vw, 0.92rem);
    letter-spacing: 0.02em; color: var(--color-amber-deep);
}
/* SELF-CONTAINED reveal (owner round 4): a marked distractor painting names
   its word on a caption strip UNDER the art (off the painting, house law);
   the keyword tiles wrap when a distractor's glyph joins its keyword */
.kw-choice--image .kw-img-id {
    display: flex; align-items: baseline; justify-content: center; gap: 7px;
    width: 100%; padding: 1px 8px 7px;
}
.kw-choice--image .kw-img-id .wj {
    font-family: var(--font-jp); font-weight: 600; line-height: 1.4;
    font-size: clamp(0.95rem, 1vw, 1.1rem); color: var(--color-jp-text);
}
.kw-choice--image .kw-img-id .wj rt { font-size: 0.5em; font-weight: 400; color: var(--color-stone); letter-spacing: 0; }
.kw-choice--image .kw-img-id .wr {
    font-style: italic; font-size: clamp(0.78rem, 0.8vw, 0.88rem);
    letter-spacing: 0.02em; color: var(--color-amber-deep);
}
.kw-choices.kw-locked .kw-choice--kw { flex-wrap: wrap; row-gap: 2px; }
/* a conjugation tile's form name rides the word-tile gloss seat */
.kw-choices--forms .kw-choice--word .wg { white-space: nowrap; }
/* the PAIR LINE — a relation reveal confirms both ends: the answer holds the
   placard, this line names the other end (ink glyph = the app's one relation
   legend). As --lead it re-states the question above a miss split. */
.kw-pairline {
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: 9px;
    margin-top: clamp(10px, 0.9vw, 14px);
    font: 400 clamp(13px, 0.98vw, 15.5px) var(--font-ui);
    color: var(--color-stone);
}
.kw-pairline .ink { flex: none; font-family: var(--font-jp); font-size: clamp(11px, 0.85vw, 13px); color: var(--color-faint-warm); }
.kw-pairline .jp { font-family: var(--font-jp); font-weight: 600; font-size: 1.12em; color: var(--color-jp-text); }
.kw-pairline .ro { font-style: italic; color: var(--color-amber-deep); }
.kw-pairline .en { color: var(--color-ink); }
.kw-pairline .en::before { content: '· '; color: var(--color-faint-warm); }
.kw-pairline .note { color: var(--color-faint-warm); font-size: 0.92em; }
.kw-pairline .kw-statusline { margin-left: 4px; align-self: center; }
.kw-pairline--lead { margin-top: 0; margin-bottom: clamp(8px, 0.8vw, 12px); }
.kw-face-reveal.kw-learning .kw-split-ans .kw-reveal-img { --kw-ring: rgba(107, 127, 92, 0.5); }
.kw-face-reveal.kw-learning .kw-split-pick .kw-reveal-img { --kw-ring: rgba(160, 120, 80, 0.42); }
.kw-split-pick .kw-reveal-img img { filter: saturate(0.72) brightness(0.98); transition: filter 0.45s var(--ease-settle); }
.kw-split-pick.kw-viewing .kw-reveal-img img { filter: none; }   /* full colour while examined */
/* the smaller (unviewed) card compacts its text; full sizes return with focus */
.kw-split > :not(.kw-viewing) .kw-plq { padding: clamp(9px, 0.85vw, 13px) 2px 0; }
.kw-split > :not(.kw-viewing) .kw-plq-jp { font-size: clamp(1.15rem, calc(9rem / var(--ja-chars, 5)), 1.6rem); }
.kw-split > :not(.kw-viewing) .kw-plq-ro { font-size: clamp(0.78rem, 0.72vw, 0.95rem); }
.kw-split > :not(.kw-viewing) .kw-plq-en { font-size: clamp(0.85rem, 0.8vw, 1.02rem); }

/* ── the verdict-in-place INK LINE (S3.9c — 朱, the owner's pick): the mini
   seal — moss 正 = correct · amber 惜 = so close — plus the scheduling
   truth, landing in the hint's seat on the marked ask face. The glyph
   stands unglossed; nothing else rides the line. ── */
.kw-inkline {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px 14px;
    margin-top: clamp(16px, 1.6vw, 24px);
    font: 500 clamp(12.5px, 0.95vw, 15px) var(--font-ui);
    animation: kwInkRise 0.42s var(--ease-brush) both;
}
.kw-vmini {
    width: clamp(24px, 1.8vw, 30px);
    height: clamp(24px, 1.8vw, 30px);
    flex: none;
    display: grid;
    place-items: center;
    position: relative;
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(13px, 1vw, 17px);
    line-height: 1;
    color: #FBF8F2;
    border-radius: 28% 34% 30% 33% / 33% 28% 34% 30%;   /* carved by hand, not die-cut */
    transform: rotate(-4deg);
}
.kw-inkline.kw-right .kw-vmini { background: var(--moss-aa); }
.kw-inkline.kw-wrong .kw-vmini { background: var(--amber-aa); }
.kw-vmini::after { /* stamped ink is never flat — a breath of unevenness */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: radial-gradient(120% 120% at 30% 24%, rgba(255, 255, 255, 0.18), transparent 55%),
        radial-gradient(95% 95% at 74% 82%, rgba(0, 0, 0, 0.14), transparent 62%);
}
/* the seal PRESSES once as the mark lands */
.kw-card.kw-just-marked .kw-inkline .kw-vmini { animation: kwSealPress 0.5s var(--ease-brush) 0.12s both; }
@keyframes kwSealPress {
    0% { opacity: 0; transform: rotate(-4deg) scale(1.3); }
    55% { opacity: 1; transform: rotate(-4deg) scale(0.95); }
    100% { opacity: 1; transform: rotate(-4deg) scale(1); }
}
/* the comparison's cleaned row reuses the line, left-set under the scene */
.kw-inkline--cmp { justify-content: flex-start; margin: clamp(12px, 1vw, 16px) 6px 0; }
/* ── the settle CASCADE (round B): on the mark the rings land at once,
   each pill's identity inks in sequence, the ink line presses, the exits
   rise — a hand finishing the page. Reduced motion collapses it all. ── */
.kw-choices.kw-locked .kw-choice .kw-lifted {
    animation: kwPillInk 0.38s var(--ease-brush) both;
    animation-delay: calc(0.1s + var(--i, 0) * 0.05s);
}
@keyframes kwPillInk {
    from { opacity: 0; transform: translateY(2px); filter: blur(0.6px); }
    to { opacity: 1; transform: none; filter: none; }
}
.kw-card.kw-just-marked .kw-inkline { animation-delay: 0.22s; }
.kw-card.kw-just-marked .kw-inkline .kw-vmini { animation-delay: 0.32s; }
.kw-card.kw-just-marked .kw-face-ask > .kw-exit-row { animation-delay: 0.34s; }
/* the ink line's replay disc — the answer's own voice, one tap away
   (the sound sits WITH the verdict; margin-left:auto declared away —
   the forms-ladder leak must not push it to the card's edge) */
.kw-inkline .kw-ink-disc { margin-left: 2px; position: relative; }
.kw-inkline .kw-ink-disc.playing::after {
    content: "";
    position: absolute;
    inset: -3px;
    border-radius: 50%;
    pointer-events: none;
    opacity: 0;
    border: 1.5px solid rgba(160, 120, 80, 0.5);
    animation: kwSonar 0.55s var(--ease-brush) forwards;
}

/* ── the exit — 次へ or the grade pair — pressable paper, not a ghost ─────── */
.kw-exit-row { display: flex; gap: 8px; align-items: stretch; margin: 12px 6px 2px; }
/* on the marked ask face (S3.9c) the exit row hangs at the choices' width */
.kw-face-ask > .kw-exit-row {
    width: 100%;
    max-width: clamp(340px, 27vw, 470px);
    margin: clamp(14px, 1.3vw, 20px) auto 0;
    animation: kwInkRise 0.42s var(--ease-brush) 0.08s both;
}
.kw-card--see .kw-face-ask > .kw-exit-row { max-width: clamp(420px, 34vw, 560px); }
.kw-next, .kw-grade-btn {
    appearance: none;
    cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.14);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: clamp(9px, 0.85vw, 13px) 6px;
    flex: 1;
    font: 600 clamp(11px, 0.82vw, 13px) var(--font-ui);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-stone);
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 3px 8px -5px rgba(var(--sh), 0.10);
    transition: border-color 0.18s, color 0.18s, background 0.18s, box-shadow 0.18s, transform 0.18s;
}
.kw-next:hover, .kw-grade-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(var(--sh), 0.06), 0 5px 12px -5px rgba(var(--sh), 0.15);
}
/* the press — the room's most consequential taps physically GIVE (a hover
   that lifts but never presses reads as glass, not paper) */
.kw-next:active, .kw-grade-btn:active {
    transform: translateY(0.5px);
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05);
    transition-duration: 0.06s;
}
.kw-next .jp, .kw-next [lang="ja"], .kw-grade-btn .jp {
    font-family: var(--font-jp);
    font-size: clamp(14px, 1.1vw, 17px);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0.02em;
    line-height: 1;
}
.kw-next rt { font-size: 8.5px; color: var(--color-faint-warm); }
/* the session's first mark carries the ask's own key chip — once (round D) */
.kw-next kbd {
    font: 500 10px var(--font-ui);
    color: var(--color-faint-warm);
    border: 1px solid var(--color-divider);
    border-bottom-width: 2px;
    border-radius: 4px;
    padding: 0 5px;
    margin-left: 4px;
    background: rgba(255, 255, 255, 0.5);
    text-transform: none;
    letter-spacing: 0;
}
.kw-next i, .kw-grade-btn i { font: italic clamp(11px, 0.8vw, 13px) var(--font-ui); text-transform: none; font-weight: 400; color: var(--color-faint-warm); }
.kw-next:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 7%, transparent);
}
.kw-grade-btn .kw-gdot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: 0.45; }
.kw-grade-btn.kw-grade-learning:hover {
    border-color: var(--color-amber);
    color: var(--amber-aa);
    background: color-mix(in srgb, var(--color-amber) 10%, transparent);
}
.kw-grade-btn.kw-grade-known:hover {
    border-color: var(--color-moss);
    color: var(--moss-aa);
    background: color-mix(in srgb, var(--color-moss) 8%, transparent);
}
/* the optional keep-in-review beside 次へ — secondary width; once kept it
   settles into a quiet pressed state (advance stays the learner's move) */
.kw-exit-row .kw-keep { flex: 0 0 clamp(150px, 14vw, 210px); }
/* もう一度 mirrors 次へ — two equal halves, one calm row */
.kw-exit-row .kw-again { flex: 1 1 0; }
.kw-exit-row .kw-again .jp, .kw-exit-row .kw-again i { white-space: nowrap; }
.kw-exit-row .kw-again.kw-kept,
.kw-exit-row .kw-keep.kw-kept {
    cursor: default;
    border-color: var(--color-amber);
    color: var(--amber-aa);
    background: color-mix(in srgb, var(--color-amber) 10%, transparent);
    transform: none;
    box-shadow: none;
}
.kw-exit-row .kw-keep.kw-kept .kw-gdot { opacity: 1; }

/* (the drift auto-advance current is RETIRED — owner 2026-07-08: advance is
   always the learner's move, right or wrong; 次へ / → is the only exit) */
.kw-card.kw-leaving { animation: kwFly 0.32s var(--ease-brush) forwards; }
@keyframes kwFly { to { opacity: 0; transform: translateY(-26px) scale(0.97); } }

/* ═══ THE DISCOVERY MINI-SCENE (the night's event, learner-paced) ══════════ */
/* the word arrives dim; each tap develops the meeting one beat further */
.kw-card.kw-disc .kw-face-reveal { cursor: pointer; }
.kw-disc-img {
    filter: brightness(1.35) contrast(0.82) saturate(0.55);
    transform: scale(1.02);
    transition: filter 0.9s var(--ease-brush), transform 0.9s var(--ease-brush);
}
.kw-card[data-beat="1"] .kw-disc-img { filter: brightness(1.18) contrast(0.9) saturate(0.75); }
.kw-card.kw-disc:not([data-beat="0"]):not([data-beat="1"]) .kw-disc-img { filter: none; transform: none; }
.kw-disc-gloss { opacity: 0; transition: opacity 0.5s var(--ease-brush); }
.kw-card.kw-disc:not([data-beat="0"]):not([data-beat="1"]) .kw-disc-gloss { opacity: 1; }
/* the identity colophon develops WITH the meaning beat — the pre-gloss
   placard stays a name and a sound. Visibility rides along so the veiled
   pills can't leak tooltips or screen-reader text before their beat. */
.kw-card.kw-disc .kw-ident {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.5s var(--ease-brush), visibility 0s 0.5s;
}
.kw-card.kw-disc:not([data-beat="0"]):not([data-beat="1"]) .kw-ident {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.5s var(--ease-brush);
}
/* the beat cue: dots + a quiet 続き, riding the FOOTER row beside the trail
   (owner 2026-07-09: one line of chrome, never two stacked rows). The trail
   keeps its own centered geometry; the cue floats just right of it, so its
   coming and going never re-centers the stones mid-walk. */
.kw-footrow { position: relative; }
.kw-footcue,
.kw-footcue:hover {
    /* a quiet line, not a control — the global button chrome (components.css
       white bg / 12px radius / floating shadow / hover lift) declared away */
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    transform: none;
    padding: 0;
    position: absolute;
    left: calc(50% + var(--kw-card-w) / 2 + 28px);
    top: -3px;
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 32px;
    white-space: nowrap;
    font: 400 clamp(12px, 0.92vw, 14.5px) var(--font-ui);
    color: var(--color-faint-warm);
}
.kw-footcue[hidden] { display: none; }
#keikoWalk.kw-closing .kw-footcue { display: none; }
.kw-beatdots { display: flex; gap: 6px; }
.kw-beatdots .bd { width: 6px; height: 6px; border-radius: 50%; background: #cfc8ba; transition: background 0.3s; }
.kw-beatdots .bd.on { background: var(--color-stone); }
.kw-beatcue {
    display: flex;
    align-items: center;
    gap: 7px;
}
.kw-beatcue .jp { font-family: var(--font-jp); font-size: clamp(13px, 1vw, 15.5px); color: var(--color-stone); }
.kw-beatcue i { font-style: italic; font-size: clamp(11px, 0.82vw, 13px); }
/* a new-word meeting warms once at its close — honey, never gold. Base
   opacity is 0 so a no-animation (reduced-motion) render shows NO glow —
   the exhale may be skipped, the warmth must never get stuck on. */
.kw-card.kw-disc.kw-met .kw-face-reveal::after {
    content: "";
    position: absolute;
    inset: -30px;
    border-radius: 26px;
    pointer-events: none;
    z-index: -1;
    opacity: 0;
    background: radial-gradient(58% 46% at 50% 40%, rgba(232, 178, 108, 0.22), transparent 70%);
    animation: kwBreath 2.2s var(--ease-brush) both;
}
@keyframes kwBreath { 0% { opacity: 0; } 35% { opacity: 1; } 100% { opacity: 0; } }   /* one breath — it exhales */
.kw-card.kw-disc .kw-face-reveal { position: relative; }

/* ═══ THE SLIPS — loose washi notes on the card's shoulders ════════════════ */
.kw-slipcol {
    position: absolute;
    top: 0;
    z-index: 3;
    width: clamp(300px, 20vw, 396px);
    display: flex;
    flex-direction: column;
    gap: clamp(18px, 1.6vw, 26px);
}
/* fukinsei stagger — right starts high, left lower */
.kw-slipcol--r { left: calc(50% + var(--kw-card-w) / 2 + 40px); padding-top: 38px; }
.kw-slipcol--l { right: calc(50% + var(--kw-card-w) / 2 + 40px); padding-top: 48px; }
/* (the ≤1279px fold lives with the narrow block further down — the notes
   step under the card there; the ≥1280 shoulder law holds above) */
.kw-slip {
    width: 100%;
    background: var(--color-card-bright);
    border: 1px solid var(--color-divider);
    border-top-color: rgba(255, 255, 255, 0.85);
    border-left-color: rgba(232, 228, 220, 0.9);
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 8px 18px -12px rgba(var(--sh), 0.09);
    padding: clamp(15px, 1.3vw, 21px) clamp(17px, 1.5vw, 23px) clamp(14px, 1.2vw, 19px);
    transform: rotate(var(--kw-tilt, 0deg));
    animation: kwSlipIn 0.55s var(--ease-brush) both;
    animation-delay: var(--wait, 0.65s);
}
/* one restrained lean per shoulder — a hand pinned each column the same way */
.kw-slipcol--r .kw-slip { --kw-tilt: -0.6deg; }
.kw-slipcol--l .kw-slip { --kw-tilt: 0.6deg; }
/* paper lands: it enters flatter and rotates into its lean as it settles */
@keyframes kwSlipIn {
    0% { opacity: 0; transform: rotate(calc(var(--kw-tilt, 0deg) * 0.35)) translateY(20px); }
    55% { opacity: 1; }
    100% { opacity: 1; transform: rotate(var(--kw-tilt, 0deg)) translateY(0); }
}
/* the notes depart WITH the card — never a hard wipe */
.kw-slip.kw-slip-out { animation: kwSlipOut 0.26s var(--ease-brush) both; }
@keyframes kwSlipOut { to { opacity: 0; transform: rotate(var(--kw-tilt, 0deg)) translateY(-12px); } }

/* a reference block: one section of the word's deeper material */
.kw-refsec { text-align: left; }
.kw-refsec + .kw-refsec { margin-top: 18px; }
.kw-refsec-h { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.kw-refsec-h .ink { /* a stamped ink chip — pressed into the paper, not pasted on */
    width: clamp(22px, 1.6vw, 27px);
    height: clamp(22px, 1.6vw, 27px);
    border-radius: 5px;
    display: grid;
    place-items: center;
    flex: none;
    font-family: var(--font-jp);
    font-size: clamp(12.5px, 0.95vw, 15px);
    color: #FBF7F1;
    background: linear-gradient(150deg, #514c45, #5c574f);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.13), inset 0 -1px 2px rgba(44, 44, 44, 0.18),
        0 1px 2px rgba(var(--sh), 0.18);
}
.kw-refsec-h .lbl {
    font: 600 clamp(10px, 0.75vw, 12px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--color-faint-warm);
}
/* each panel's own voice — one muted ink per panel kind, worn ONLY by the
   chip (owner 2026-07-09: a voice per panel; restraint keeps it washi, not
   carnival). Sound wears the app's amber (locked: amber = sound). */
.kw-refsec[data-voice] .kw-refsec-h .ink {
    background: linear-gradient(150deg, color-mix(in srgb, var(--kw-voice) 86%, var(--color-ink) 14%), var(--kw-voice));
}
.kw-refsec[data-voice='sent'] { --kw-voice: #57524A; }      /* warm sumi — the plain voice */
.kw-refsec[data-voice='story'] { --kw-voice: #7A6355; }     /* sepia — the telling voice */
.kw-refsec[data-voice='watch'] { --kw-voice: var(--kw-clay); }  /* burnt clay — caution */
.kw-refsec[data-voice='kanji'] { --kw-voice: #3E4A59; }     /* scholar slate */
.kw-refsec[data-voice='antonym'] { --kw-voice: #8A5058; }   /* iron plum — tension */
.kw-refsec[data-voice='synonym'] { --kw-voice: #6C7D60; }   /* sage — kinship */
.kw-refsec[data-voice='homophone'] { --kw-voice: #A67C2E; } /* amber — sound */
.kw-refsec[data-voice='homograph'] { --kw-voice: #52616F; } /* slate blue — the written face */
.kw-refsec[data-voice='related'] { --kw-voice: #7D7468; }   /* warm stone — same topic */
.kw-refsec[data-voice='register'] { --kw-voice: #6E5E75; }  /* wisteria — courtesy */

/* 礼 the politeness ladder — one meaning at different heights */
.kw-reg-meaning { font: italic clamp(11.5px, 0.88vw, 13.5px) var(--font-ui); color: var(--color-stone); margin-bottom: 7px; }
/* rows may wrap their trailing tag; the JP word itself never breaks mid-word
   (round A — いらっしゃる once fragmented across lines) */
.kw-reg-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 9px; padding: 4px 0; min-width: 0; }
.kw-reg-row + .kw-reg-row { border-top: 1px dashed rgba(var(--sh), 0.07); }
.kw-reg-lv { flex: none; width: 38%; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.kw-reg-lv .jp { font-family: var(--font-jp); font-size: clamp(11.5px, 0.9vw, 14px); color: var(--color-stone); }
.kw-reg-lv i { font: italic clamp(9px, 0.7vw, 10.5px) var(--font-ui); color: var(--color-faint-warm); }
.kw-reg-jp { font-family: var(--font-jp); font-size: clamp(13.5px, 1.05vw, 16.5px); color: var(--color-ink); white-space: nowrap; }
.kw-reg-ro { font: italic clamp(10.5px, 0.82vw, 12.5px) var(--font-ui); color: var(--color-amber-deep); }
.kw-reg-row--here .kw-reg-jp { font-weight: 600; }
.kw-refsec-jp {
    font-family: var(--font-jp);
    font-size: clamp(17.5px, 1.3vw, 22px);
    line-height: 1.65;
    color: var(--color-ink);
    font-feature-settings: 'palt' 1;
}
.kw-refsec-jp .hit { border-bottom: 2px solid rgba(160, 120, 80, 0.4); }
/* per-run ruby from the bundle's own furigana — the JP line finally reads
   for a beginner; the line breathes to hold the small readings */
.kw-refsec-jp--ruby { line-height: 2.1; }
.kw-refsec-jp--ruby rt {
    font-size: 0.48em;
    color: var(--color-stone);
    letter-spacing: 0;
    font-weight: 400;
}
.kw-refsec-jp--ruby .hit ruby { border-bottom: none; }   /* the wrapping span carries the one underline */
/* romaji hugs the JP it romanizes; the switch to English gets the air */
.kw-refsec-ro { font: italic clamp(12px, 0.95vw, 14.5px) var(--font-ui); color: var(--color-amber-deep); margin-top: 1px; line-height: 1.5; }
.kw-refsec-en { font: 400 clamp(12.5px, 1vw, 15px) var(--font-ui); color: var(--color-stone); margin-top: 7px; line-height: 1.55; }
.kw-refsec-body { font: 400 clamp(12.5px, 1vw, 15px) var(--font-ui); color: var(--color-stone); line-height: 1.62; }
.kw-refsec-body .kw-jp { font-family: var(--font-jp); color: var(--color-jp-text); }
/* the culture note rides INSIDE the story glance — one slip, never two */
.kw-refsec-cult { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--color-divider); }
.cult-lead {
    display: block;
    font: 600 clamp(9.5px, 0.72vw, 11px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--color-faint-warm);
    margin-bottom: 3px;
}
.cult-lead i { font-style: italic; text-transform: none; letter-spacing: 0.02em; margin-right: 2px; }

/* ── the identity colophon — POS · topic, then politeness / band / rank as
   quiet chips (owner 2026-07-09: the word's tags are study material too).
   The pills are the app's SHARED .freq-tier / .register-chip, sized down to
   the placard's whisper voice. ────────────────────────────────────────────── */
.kw-ident {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: clamp(9px, 0.8vw, 13px);
    padding-top: clamp(8px, 0.7vw, 11px);
    border-top: 1px dashed var(--color-divider);
}
.kw-id-left {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    min-width: 0;
    font: 500 clamp(10px, 0.78vw, 12px) var(--font-ui);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-faint-warm);
}
.kw-id-pos { color: var(--color-stone); }
.kw-id-pos .jp { font-family: var(--font-jp); margin-left: 5px; letter-spacing: 0; }
.kw-id-chips { display: flex; align-items: center; gap: 9px; flex: none; }
/* the shared pills default to absolute (they decorate card corners elsewhere)
   — HERE they sit in the colophon's own flow, never on the art */
.kw-id-chips .freq-tier, .kw-id-chips .register-chip {
    position: static;
    pointer-events: auto;
    font-size: 10px;
}
.kw-id-rank {
    font: 600 clamp(10px, 0.78vw, 12px) var(--font-ui);
    letter-spacing: 0.03em;
    color: var(--color-faint-warm);
    font-variant-numeric: tabular-nums;
}

/* ── the kanji GLANCE — glyph · keyword · kun/on rows (law-8 colors) · the
   shape sumi-e + its one-line story. A pinned item, not the kanji page. ───── */
.kw-kglance-row { display: flex; gap: 16px; align-items: center; }
.kw-kglance-glyph { font-family: var(--font-jp); font-weight: 400; font-size: clamp(46px, 3.5vw, 62px); line-height: 1; color: var(--color-ink); }
.kw-kglance-meta { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.kw-kglance-kw { font: 600 clamp(13px, 1vw, 15.5px) var(--font-ui); color: var(--color-ink); }
/* ── 読み方 the readings fold — the kanji page's structure at slip scale:
   訓読み / 音読み / まるごと sections, each reading with its words, the kanji
   lit in its family colour (kun = indigo, on = terracotta) ─────────────────── */
.kw-yomi-fam { margin-top: 4px; }
.kw-yomi-fam + .kw-yomi-fam { margin-top: 13px; padding-top: 11px; border-top: 1px dashed var(--color-divider); }
.kw-kfam-h { display: flex; align-items: baseline; gap: 7px; margin-bottom: 5px; min-width: 0; }
.kw-kfam-h .ktag {
    font-family: var(--font-jp);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.1em;
    border-radius: 4px;
    padding: 1.5px 6px;
    flex: none;
}
.kw-kfam-h .ktag i { font: italic 8.5px var(--font-ui); margin-left: 3px; letter-spacing: 0.02em; }
.kw-kfam-h .ktag--neu {
    /* まるごと・その他 are JAPANESE tags — they keep the house brush (Klee),
       never the gothic UI face (fleet 2026-07-09) */
    font-family: var(--font-jp);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.07em;
    color: var(--color-stone);
    background: rgba(var(--sh), 0.06);
}
.kw-kfam-h .ktag--neu i { font: italic 8.5px var(--font-ui); letter-spacing: 0.02em; }
.kw-kfam-h .def { font: italic clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-faint-warm); }
.kw-yomi-fam--kun .ktag { color: var(--kw-kun); background: rgba(61, 90, 128, 0.09); }
.kw-yomi-fam--on .ktag { color: var(--kw-on); background: rgba(158, 94, 67, 0.10); }
/* the reading line — a small headline over its words */
.kw-yomi-read { display: flex; align-items: baseline; gap: 7px; margin: 7px 0 2px; }
.kw-yomi-read .jp { font-family: var(--font-jp); font-size: clamp(14px, 1.08vw, 17px); line-height: 1.3; }
.kw-yomi-fam--kun .kw-yomi-read .jp { color: var(--kw-kun); }
.kw-yomi-fam--on .kw-yomi-read .jp { color: var(--kw-on); }
.kw-yomi-read i { font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-amber-deep); }
/* a word behind the reading — the kanji lit in its family colour */
.kw-yomi-row { display: flex; align-items: baseline; gap: 8px; padding: 3px 0 3px 10px; min-width: 0; }
.kw-yomi-row .jp { font-family: var(--font-jp); font-size: clamp(13px, 1vw, 15.5px); color: var(--color-ink); flex: none; }
.kw-yomi-fam--kun .kw-yomi-row .hl { color: var(--kw-kun); }
.kw-yomi-fam--on .kw-yomi-row .hl { color: var(--kw-on); }
.kw-yomi-row i { font: italic clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-amber-deep); flex: none; }
.kw-yomi-row .en {
    font: 400 clamp(11px, 0.86vw, 13px) var(--font-ui);
    color: var(--color-stone);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.kw-yomi-kana { font-family: var(--font-jp); font-size: clamp(11.5px, 0.88vw, 13.5px); color: var(--color-stone); flex: none; }
.kw-yomi-row--later .jp { color: var(--color-stone); }   /* not a card yet — quieter ink */
.kw-yomi-row .kw-rel-rank { margin-left: auto; align-self: center; }
/* the honest tail indents WITH the rows it truncates */
.kw-yomi-fam .kw-fam-more { padding-left: 10px; }
.kw-khere {
    font: 600 9px var(--font-ui);
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--color-stone);
    background: rgba(var(--sh), 0.06);
    border-radius: 4px;
    padding: 2px 6px;
    align-self: center;
}
.kw-kvoiced { font: italic clamp(10px, 0.78vw, 12px) var(--font-ui); color: var(--color-faint-warm); }
.kw-kvoiced [lang="ja"] { font-family: var(--font-jp); font-style: normal; }
/* the kanji's own trap — one quiet 注 line under the readings */
.kw-kwatch { display: flex; gap: 8px; margin-top: 9px; align-items: baseline; }
/* 注 speaks in ONE ink everywhere — the watch-voice clay, never the romaji
   amber (locked: italic amber = romaji only) */
.kw-kwatch .ink { flex: none; font-family: var(--font-jp); font-size: clamp(11px, 0.85vw, 13px); color: var(--kw-clay); }
.kw-kwatch .txt { font: italic clamp(11px, 0.86vw, 13.5px) var(--font-ui); color: var(--color-stone); line-height: 1.5; }
.kw-kwatch .txt .kw-jp { font-family: var(--font-jp); font-style: normal; color: var(--color-jp-text); }
.kw-kglance-img { margin-top: 11px; border-radius: 6px; overflow: hidden; background: #F6F3EC; border: 1px solid rgba(44, 44, 44, 0.06); }
.kw-kglance-img img { width: 100%; height: clamp(110px, 9vw, 150px); object-fit: contain; display: block; }
.kw-kglance-story { margin-top: 9px; font: italic clamp(11.5px, 0.9vw, 14px) var(--font-ui); color: var(--color-stone); line-height: 1.55; }
.kw-kglance-story b, .kw-kglance-story .kw-jp { font-family: var(--font-jp); font-style: normal; color: var(--color-jp-text); font-weight: 400; }

/* the relation glance IS a pinned word — the header already named the
   relation; the body is just the word(s): name, reading, meaning, painting.
   Complete within its type: one row per relation word (父 shows BOTH
   opposites), separated by quiet air. */
.kw-relnote { display: flex; flex-direction: row; align-items: center; gap: 12px; }
/* the SAME-WRITING slip carries the how-to-tell rule where the twins meet */
.kw-relrule {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 10px;
    padding-top: 9px;
    border-top: 1px dashed var(--color-divider);
    font: italic clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--color-stone);
    line-height: 1.55;
}
.kw-relrule .ink { flex: none; font-family: var(--font-jp); font-style: normal; font-size: clamp(11px, 0.85vw, 13px); color: var(--kw-clay); }
.kw-relrule .txt .kw-jp, .kw-relrule .txt b { font-family: var(--font-jp); font-style: normal; color: var(--color-jp-text); font-weight: 400; }
.kw-relnote + .kw-relnote { margin-top: 14px; }
/* more than three neighbours SCROLL inside the panel — every neighbour
   reachable, the room's height held; the fourth row peeking past the edge
   is the honest cue (owner 2026-07-10) */
.kw-rel-scroll {
    max-height: clamp(300px, 24vw, 360px);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(87, 83, 78, 0.22) transparent;
    padding-right: 6px;
    margin-right: -6px;
    overscroll-behavior: contain;
}
.kw-relnote-text { display: flex; flex-direction: column; gap: 1px; align-items: flex-start; min-width: 0; flex: 1; }
.rel-jp { font-family: var(--font-jp); font-weight: 600; font-size: clamp(1.15rem, 1vw, 1.35rem); line-height: 1.2; color: var(--color-ink); font-feature-settings: 'palt' 1; }
.rel-ro { font: italic clamp(0.78rem, 0.72vw, 0.92rem) var(--font-ui); letter-spacing: 0.035em; color: var(--color-amber-deep); }
.rel-en { font: 400 clamp(0.82rem, 0.78vw, 0.95rem) var(--font-ui); color: var(--color-stone); margin-top: 4px; line-height: 1.4; }
.kw-relnote-thumb {
    flex: none;
    width: clamp(76px, 6vw, 100px);
    aspect-ratio: 3 / 2;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 0 0 1px rgba(44, 44, 44, 0.07);
}
.kw-relnote-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* a meet-later FRAME row: no painting yet — the empty tile-space is the
   signal; a quiet rank chip keeps the scale honest */
.kw-rel-rank {
    flex: none;
    align-self: center;
    font: 600 clamp(9.5px, 0.72vw, 11px) var(--font-ui);
    letter-spacing: 0.03em;
    color: var(--color-faint-warm);
    font-variant-numeric: tabular-nums;
}


/* ── the 字 panel SWITCHER — one panel per word; glyph tabs in the slip
   header + the headword's own kanji steer it (2+-kanji words) ─────────────── */
.kw-ktabs { margin-left: auto; display: inline-flex; gap: 4px; }
.kw-ktab,
.kw-ktab:hover {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    box-shadow: none;
    transform: none;
    padding: 1px 7px;
    font-family: var(--font-jp);
    font-size: clamp(13px, 1vw, 15.5px);
    line-height: 1.4;
    color: var(--color-faint-warm);
    transition: color 0.18s, background 0.18s;
}
.kw-ktab:hover { color: var(--color-ink); background: rgba(var(--sh), 0.05); }
.kw-ktab.on { color: var(--color-ink); background: rgba(var(--sh), 0.07); border-color: rgba(var(--sh), 0.12); }
/* the headword's kanji as quiet switch handles — the active one speaks in
   the app's interactive indigo INK, no floating underline (owner 2026-07-09:
   the tick read as clutter; colour carries the state elegantly) */
.kw-kt { cursor: pointer; transition: color 0.22s var(--ease-brush); }
.kw-kt:hover { color: #5C7699; }
.kw-kt.kw-active { color: var(--color-accent); }

/* every gated kanji in the room is a quiet handle — hovering peeks its
   calling card (owner 2026-07-10); interactive-indigo on hover only, the
   resting text stays pure ink (no decoration at rest — Muji) */
.kw-kx { cursor: pointer; transition: color 0.2s var(--ease-brush); }
.kw-kx:hover { color: #5C7699; }
.hl .kw-kx { color: inherit; }               /* the family colour outranks the handle */
.hl .kw-kx:hover { color: #5C7699; }
.kw-kxpeek {
    position: fixed;
    /* above the word sheet (8800) — the peek serves the sheet's own kanji
       handles now that the 字 material lives there (S3.9) */
    z-index: 8900;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    /* chrome unified DOWN to the global card's whisper (owner 2026-07-16):
       the quiet two-part shadow ring, washi noise, 300px — one paper for
       both hover cards; the readings row inside is the shared .kpk-*
       (css/entity-peek.css), rendered by KanjiPage.readingsRowHTML */
    max-width: 300px;
    padding: 9px 13px 10px;
    background: var(--color-card, #FAFAF7);
    background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.02'/%3E%3C/svg%3E");
    border-radius: 10px;
    box-shadow: 0 3px 14px rgba(var(--sh), 0.09), 0 0 0 1px rgba(var(--sh), 0.05);
    pointer-events: none;
    animation: kwSettleUp 0.22s var(--ease-brush) both;
}
.kw-kxpeek[hidden] { display: none; }
.kw-kxpeek .glyph { font-family: var(--font-jp); font-size: 34px; line-height: 1.15; color: var(--color-ink); }
.kw-kxpeek .meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding-top: 2px; }
.kw-kxpeek .kwd { font: 600 12.5px var(--font-ui); color: var(--color-ink); }

/* (the 縁 min-row fold retired 2026-07-16 — the neighbour slip rests OPEN
   like the typed relations; its rows wear the shared .kw-relnote dress) */

/* the honest "… and N more" tail every capped list wears */
.kw-fam-more { font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-faint-warm); margin-top: 2px; }

/* the kanji panel RESTS half-expanded (owner 2026-07-11) — the sumi-e and
   the shape story are the glance; the shoji is retired. The image keeps its
   framed-print treatment at full width. */

/* ── 活用 forms ladder + 数え方 counting table — folded reference rows
   (word-page parity; 音 disc only where the form has audio) ───────────────── */
.kw-forms { display: flex; flex-direction: column; }
.kw-form-row { display: flex; align-items: baseline; gap: 10px; padding: 4.5px 0; min-width: 0; }
.kw-form-row + .kw-form-row { border-top: 1px dashed rgba(var(--sh), 0.07); }
.kw-form-lbl { flex: none; width: 34%; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.kw-form-lbl .jp { font-family: var(--font-jp); font-size: clamp(11.5px, 0.9vw, 14px); color: var(--color-stone); white-space: nowrap; }
.kw-form-lbl .en {
    font: 500 clamp(9px, 0.7vw, 10.5px) var(--font-ui);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-faint-warm);
}
.kw-form-kana { font-family: var(--font-jp); font-size: clamp(13.5px, 1.05vw, 16.5px); color: var(--color-ink); }
.kw-form-ro { font: italic clamp(10.5px, 0.82vw, 12.5px) var(--font-ui); color: var(--color-amber-deep); }
.kw-form-audio,
.kw-form-audio:hover {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: none;
    border-radius: 50%;
    box-shadow: none;
    transform: none;
    padding: 2px;
    margin-left: auto;
    flex: none;
    align-self: center;
    color: var(--color-faint-warm);
    display: grid;
    place-items: center;
    transition: color 0.18s;
}
.kw-form-audio:hover { color: var(--color-ink); }
.kw-form-audio svg { width: 14px; height: 14px; display: block; }
.kw-cnt-usage { font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-stone); margin-bottom: 5px; }
/* the counter row's kana READING sits in the JP voice (upright, jp font) —
   the italic amber slot is for romaji only (locked inline semantics) */
.kw-cnt-kana { font-family: var(--font-jp); font-size: clamp(11.5px, 0.9vw, 14px); color: var(--color-stone); }
.kw-cnt-n {
    flex: none;
    width: 20px;
    font: 600 clamp(10.5px, 0.8vw, 12px) var(--font-ui);
    color: var(--color-faint-warm);
    font-variant-numeric: tabular-nums;
}
/* the counting table COLUMN-aligns like the word page's grid — the romaji
   column sits flush instead of riding each row's kana width. FIXED columns:
   each row is its own grid, so auto-sizing would go ragged again. */
.kw-cnt-row {
    display: grid;
    grid-template-columns: 20px 4em 6.5em 1fr auto;
    column-gap: 10px;
    align-items: baseline;
}
.kw-cnt-row .kw-form-audio { justify-self: end; align-self: center; }

/* ── depth folds — a slip may carry more, revealed only on tap (owner
   2026-07-09: everything stays within the room; no door out) ─────────────── */
.kw-slip-fold { margin-top: 11px; border-top: 1px dashed var(--color-divider); padding-top: 8px; }
/* a QUIET text line, not a control: the app's global button chrome
   (components.css — white bg, 12px radius, floating shadow, hover lift)
   must not reach it; every leaked property is declared away, rest AND hover */
.kw-slip-more,
.kw-slip-more:hover {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    transform: none;
    padding: 2px 0;
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    color: var(--color-faint-warm);
    transition: color 0.18s;
}
.kw-slip-more:hover { color: var(--color-accent); }
.kw-slip-more .jp { font-family: var(--font-jp); font-size: clamp(12.5px, 0.95vw, 15px); color: var(--color-stone); }
.kw-slip-more i { font-style: italic; }
/* the chevron turns with the fold — open points down, closed points on */
.kw-slip-more .chev { font-size: 12px; display: inline-block; transition: transform 0.25s var(--ease-brush); }
.kw-slip-more.kw-open .chev { transform: rotate(90deg); }
.kw-slip-deep { margin-top: 2px; display: flex; flex-direction: column; gap: 12px; }
.kw-slip-deep[hidden] { display: none; }   /* folded until the tap — display:flex must not defeat [hidden] */
.kw-slip-deep.kw-deep-in { animation: kwSettleUp 0.4s var(--ease-brush) both; }
.kw-slip-deep .kw-deep-item { padding-top: 2px; }
.kw-deep-note { font: 400 clamp(12px, 0.92vw, 14px) var(--font-ui); color: var(--color-stone); line-height: 1.6; }
.kw-deep-note + .kw-deep-note { margin-top: 8px; }
.kw-deep-note .kw-jp, .kw-deep-note b { font-family: var(--font-jp); color: var(--color-jp-text); font-weight: 400; }

/* ═══ THRESHOLD (session open) — tonight's path already lies on the floor ══ */
.kw-threshold { width: min(640px, 94vw); text-align: center; margin: auto; }
.kw-threshold.kw-exiting { animation: kwThExit 0.28s var(--ease-page) both; }
@keyframes kwThExit { to { opacity: 0; transform: translateY(-8px); } }
.kw-th-mark { font-family: var(--font-jp); font-size: clamp(56px, 4.2vw, 82px); color: var(--color-ink); line-height: 1.15; }
.kw-th-mark .ro {
    display: block;
    font: 400 clamp(12px, 0.85vw, 14px) var(--font-ui);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-faint-warm);
    margin-top: 10px;
}
.kw-th-shape { margin-top: 28px; font: 400 clamp(15px, 1.15vw, 19px) var(--font-ui); color: var(--color-stone); line-height: 1.7; }
.kw-th-shape b { color: var(--color-ink); font-weight: 600; }
/* the thread — one quiet line when the deck leans one way (round D) */
.kw-th-thread {
    margin-top: 7px;
    font: 400 clamp(12.5px, 0.95vw, 15px) var(--font-ui);
    color: var(--color-faint-warm);
}
.kw-th-thread .jp { font-family: var(--font-jp); color: var(--color-stone); }
.kw-begin {
    margin-top: 36px;
    appearance: none;
    cursor: pointer;
    background: var(--color-accent);
    color: #fff;
    border: none;
    border-radius: var(--radius-full);
    padding: clamp(12px, 1vw, 15px) clamp(34px, 2.8vw, 46px);
    font: 500 clamp(14.5px, 1.1vw, 17px) var(--font-ui);
    letter-spacing: 0.03em;
    box-shadow: 0 2px 8px -3px rgba(31, 45, 66, 0.35);
    transition: filter 0.18s, transform 0.18s, box-shadow 0.18s;
}
.kw-begin:hover { filter: brightness(1.07); transform: translateY(-1px); box-shadow: 0 4px 12px -4px rgba(31, 45, 66, 0.4); }
.kw-begin .jp { font-family: var(--font-jp); margin-left: 8px; }
.kw-begin i { font: italic clamp(11px, 0.8vw, 12.5px) var(--font-ui); opacity: 0.7; margin-left: 6px; }
/* 昨夜の一文 — last night's payoff line returns for a cold re-read, faded
   like a note left on the threshold */
.kw-lastline {
    margin: 26px auto 0;
    max-width: 460px;
    padding-top: 14px;
    border-top: 1px dashed var(--color-divider);
    opacity: 0.82;
}
.kw-lastline .lead {
    display: block;
    font-family: var(--font-jp);
    font-size: clamp(10.5px, 0.8vw, 12.5px);
    color: var(--color-faint-warm);
    margin-bottom: 6px;
}
.kw-lastline .lead i { font: italic clamp(9.5px, 0.72vw, 11px) var(--font-ui); margin-left: 6px; }
.kw-lastline .jp { font-family: var(--font-jp); font-size: clamp(15px, 1.15vw, 19px); line-height: 1.7; color: var(--color-ink); }
.kw-lastline .ro { display: block; font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-amber-deep); margin-top: 2px; }
.kw-lastline .en { font: 400 clamp(11.5px, 0.88vw, 13.5px) var(--font-ui); color: var(--color-stone); margin-top: 4px; }

/* ═══ THE CLOSE — the far bank; the record finally spreads ═════════════════ */
.kw-close { width: min(900px, 94vw); text-align: center; margin: 0 auto; }
/* a clean crossing earns the brushstroke ensō — drawn once, opening showing;
   the loaded entry + drifting double body keep it a stroke, not a circle */
.kw-enso { width: clamp(88px, 7vw, 118px); margin: 0 auto 10px; }
.kw-enso svg { display: block; width: 100%; height: auto; }
.kw-enso path {
    fill: none;
    stroke: var(--color-ink);
    stroke-linecap: round;
    stroke-dasharray: 100 100;
    stroke-dashoffset: 100;
    animation: kwEnsoDraw 1.15s var(--ease-brush) 0.25s forwards;
}
.kw-enso path.b { stroke-width: 2.3; opacity: 0.4; animation-delay: 0.32s; }
.kw-enso path.entry { stroke-width: 6.2; opacity: 0.3; animation-duration: 0.5s; }
@keyframes kwEnsoDraw { to { stroke-dashoffset: 0; } }
/* the caught-up day's one quiet line (nothing walked, nothing due) */
.kw-close-note {
    margin: 18px auto 0;
    font: 400 clamp(13.5px, 1.05vw, 16.5px) var(--font-ui);
    color: var(--color-stone);
    line-height: 1.6;
    max-width: 560px;
}
/* ── the PRODUCTIVE SUMMARY (owner 2026-07-15) — every walked word named,
   grouped by outcome in quiet ledger rows; the stone record retired from
   the close (the crossing lives in the walk itself). Left key carries the
   honest count; the words are DOORS into the WordPanel glance. ─────────── */
.kw-summary { margin: 56px auto 0; max-width: 680px; text-align: left; }
.kw-sum-row {
    display: flex;
    align-items: baseline;
    gap: 18px;
    border-top: 1px solid var(--color-divider);
    padding: 13px 8px;
}
.kw-sum-row:first-child { border-top: none; }
/* the key column wears the BEAM's stamp dress (tracked caps + the bold
   tabular count) — the close reads as the beam's ladder laid on its side,
   one status grammar in both rooms (nav rethink, owner-approved 2026-07-16) */
.kw-sum-key {
    flex: none;
    width: 118px;
    font: 500 10.5px var(--font-ui);
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--color-stone);
    padding-top: 5px;
}
.kw-sum-key .n {
    font: 600 13px var(--font-ui);
    letter-spacing: normal;
    color: var(--color-ink);
    margin-left: 6px;
    font-variant-numeric: tabular-nums;
}
.kw-sum-body { flex: 1; line-height: 2; min-width: 0; }
/* a word is a real door — quiet at rest, awake on hover/focus */
.kw-sum-word, .kw-sum-word:hover {
    appearance: none;
    cursor: pointer;
    border: none;
    background: transparent;
    padding: 2px 5px;
    margin: 0 6px 0 0;
    font: 400 clamp(12px, 0.9vw, 13px) var(--font-ui);
    color: var(--color-stone);
    box-shadow: none;
    transform: none;
    border-radius: 4px;
    text-align: left;
    transition: background-color 0.15s;
}
.kw-sum-word:hover { background: rgba(var(--sh), 0.05); }
.kw-sum-word .jp { font-family: var(--font-jp); font-size: clamp(14px, 1.05vw, 15.5px); color: var(--color-ink); margin-right: 6px; }
.kw-sum-word .r { font: italic clamp(10px, 0.78vw, 11px) var(--font-ui); color: var(--amber-aa); }
.kw-sum-word .en { color: var(--color-stone); margin-left: 6px; }
/* the covered list names a word WITHOUT its gloss — hover whispers it
   (the "remind me" tier); the panel waits for the click, never the hover */
.kw-sum-word .en.kw-sum-whisper { display: none; margin-left: 4px; font-size: 0.92em; }
.kw-sum-word:hover .en.kw-sum-whisper,
.kw-sum-word:focus-visible .en.kw-sum-whisper { display: inline; }
/* outcome marks — the walk's own vocabulary at ledger scale */
.kw-sum-mark { display: inline-block; width: 11px; height: 11px; vertical-align: -1px; margin-right: 7px; }
.kw-sum-mark svg { display: block; width: 100%; height: 100%; }
.kw-sum-mark.crack path { stroke: #8a8175; stroke-width: 3.2; fill: none; }
.kw-sum-mark.gold path { stroke: var(--color-gold); stroke-width: 3.4; fill: none; filter: drop-shadow(0 0 2px rgba(212, 184, 124, 0.7)); }
.kw-sum-mark.lantern {
    width: 8px;
    height: 12px;
    border-radius: 2.5px 2.5px 1px 1px;
    background: #f5ead0;
    border: 1px solid rgba(232, 178, 108, 0.8);
    position: relative;
}
.kw-sum-mark.lantern::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: rgba(232, 178, 108, 1);
}
/* the reassurance rides INSIDE the missed row — one italic tail */
.kw-sum-rest { display: block; font: italic 400 clamp(11px, 0.85vw, 12.5px) var(--font-ui); color: var(--color-faint-warm); margin-top: 2px; }
/* the payoff, UNBOXED (owner 2026-07-15): the sentence is the room's one
   hero — ink on the ground, no card; the cap whispers once in lowercase */
.kw-payoff {
    margin: 10px auto 0;
    max-width: clamp(560px, 46vw, 720px);
}
.kw-payoff-cap {
    font: italic 400 clamp(11.5px, 0.85vw, 12.5px) var(--font-ui);
    color: var(--moss-aa);
    margin-bottom: 13px;
}
.kw-payoff-jp {
    font-family: var(--font-jp);
    font-size: clamp(26px, 2.2vw, 36px);
    color: var(--color-ink);
    line-height: 1.55;
    font-feature-settings: 'palt' 1;
}
.kw-veils { display: flex; flex-wrap: wrap; gap: 8px 14px; justify-content: center; margin-top: 11px; }
.kw-veil { min-height: 24px; display: flex; align-items: center; }
.kw-veil-body { animation: kwInkRise 0.42s var(--ease-brush) both; }
@keyframes kwInkRise { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
.kw-veil-chip {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-full);
    padding: 4px 14px;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    letter-spacing: 0.04em;
    color: var(--color-stone);
    transition: border-color 0.18s, color 0.18s;
}
.kw-veil-chip:hover { border-color: var(--color-faint); color: var(--color-ink); }
.kw-veil-body { font: italic clamp(13.5px, 1.05vw, 16px) var(--font-ui); color: var(--amber-aa); }
.kw-veil-body.en { font-style: normal; color: var(--color-stone); }
/* the metacognition half-line — one quiet clause beside the schedule
   truth (the inkline's own flex gap spaces it; a margin would double it) */
.kw-inkline .kw-metacog {
    font: italic 400 clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--color-faint-warm);
    white-space: nowrap;
}

/* ── the pitch contour — the word's H/L mora line, sound's own amber.
   Bars step high/low per mora; the drop tick falls off the accent mora. ── */
.kw-pitch {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: 14px 16px 8px;
}
.kw-pitch.kw-reveal-ladder { flex-wrap: wrap; }
.kw-pitch--bare { padding: 5px 0 0; }
.kw-pitch-m {
    position: relative;
    font: italic 400 clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--amber-aa);
    padding: 11px 7px 1px;
}
.kw-pitch--bare .kw-pitch-m { font-size: clamp(9.5px, 0.72vw, 11px); padding: 9px 5px 0; }
.kw-pitch-m::before {
    content: '';
    position: absolute;
    left: 2px;
    right: 2px;
    border-top: 1.6px solid var(--amber-aa);
}
.kw-pitch-m.h::before { top: 2px; }
.kw-pitch-m.l::before { top: 8px; opacity: 0.45; }
.kw-pitch-m.drop::after {
    content: '';
    position: absolute;
    right: 0;
    top: 2px;
    height: 6px;
    border-right: 1.6px solid var(--amber-aa);
}


/* one more stone — real, or absent */
.kw-onemore-btn { margin-top: 0; }
.kw-onemore { margin-top: 28px; }
.kw-stonebtn {
    width: clamp(46px, 3.2vw, 56px);
    height: clamp(46px, 3.2vw, 56px);
    border-radius: 48% 52% 50% 50% / 52% 48% 52% 48%;
    border: 1.5px dashed var(--color-divider);
    background: #eceae4;
    cursor: pointer;
    margin: 0 auto;
    display: block;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.kw-stonebtn:hover { border-color: var(--color-faint); box-shadow: 0 0 0 4px rgba(87, 83, 78, 0.10); }
.kw-onemore-lbl { margin-top: 9px; font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui); color: var(--color-faint-warm); }
.kw-leave {
    margin-top: 24px;
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-full);
    padding: 9px 20px;
    font: 400 clamp(12.5px, 0.95vw, 14.5px) var(--font-ui);
    color: var(--color-stone);
    transition: border-color 0.18s, color 0.18s;
}
.kw-leave:hover { border-color: var(--color-faint); color: var(--color-ink); }
/* 戻る leads here too — one JP-led leaving voice with the lintel chip */
.kw-leave .jp { font-family: var(--font-jp); margin-right: 7px; }
/* the sign-off closes the far bank (brand §7 — component in brand.css;
   only its seat is the walk's) */
.kw-close .kotoba-signoff { margin-top: 46px; }

/* ── neutralize the app's global button chrome (components.css: white bg +
   floating shadow + 12px radius + hover translateY lift) on every walk
   control that dresses itself as quiet paper or bare material. The raised
   paper buttons (次へ / grade pair / choices / Begin) declare their own
   shadows and hover lifts and stand on their own. ─────────────────────────── */
.kw-veil-chip, .kw-veil-chip:hover,
.kw-leave, .kw-leave:hover,
.kw-lintel-leave, .kw-lintel-leave:hover {
    box-shadow: none;
    transform: none;
}
.kw-stonebtn { box-shadow: none; }
.kw-stonebtn:hover { transform: none; }              /* a stone sits in its ground */
.kw-listen-disc, .kw-listen-disc:hover { box-shadow: none; }
.kw-corner-disc:hover { transform: none; }           /* discs rest ON the print; :active keeps its press */

/* one shared keyboard focus ring across the walk's interactive elements */
#keikoWalk :where(button, [role="button"], [tabindex]):focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
/* the programmatic focus anchors never draw a ring of their own */
#keikoWalk .kw-card:focus, #keikoWalk .kw-close:focus { outline: none; }

/* short desktop viewports (≤820px tall): tighten the reveal stack so the
   verdict and the whole exit clear the first screenful */
@media (max-height: 820px) {
    .kw-verdict { padding-top: 9px; }
    .kw-exit-row { margin-top: 9px; }
    .kw-stage { min-height: clamp(380px, 48vh, 560px); }
    .kw-face-ask { min-height: clamp(340px, 38vh, 470px); }
}

/* narrow (≤1279px): the notes fold under the card instead of the shoulders */
@media (max-width: 1279px) {
    .kw-stage { flex-direction: column; align-items: center; justify-content: flex-start; }
    .kw-slipcol {
        position: static;
        width: 100%;
        max-width: var(--kw-card-w);
        margin: 14px auto 0;
        padding: 0 !important;
        gap: 14px;
    }
    .kw-slip { --kw-tilt: 0deg; }
    .kw-kglance-img { width: fit-content; margin-left: auto; margin-right: auto; }
    .kw-kglance-img img { width: auto; max-width: 100%; }
    /* the footer cue compresses to dots + 続き and pins to the edge — never
       off-screen, never over the stones */
    .kw-footcue { left: auto; right: 14px; }
    .kw-footcue .cue-txt { display: none; }
}

/* the walk is desktop-first; on true mobile the journey flow owns study */
@media (max-width: 768px) {
    #keikoWalk { --kw-card-w: min(460px, 92vw); }
}

/* ── reduced motion: instant states, honest strokes ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
    #keikoWalk *, #keikoWalk *::before, #keikoWalk *::after {
        animation: none !important;
        transition: none !important;
    }
    /* drawn-on strokes must still EXIST without their draw — honesty over motion */
    #keikoWalk .kw-tstep.kw-cracked .kw-crack path,
    #keikoWalk .kw-tstep.kw-mended .kw-crack path,
    #keikoWalk .kw-enso path { stroke-dashoffset: 0 !important; }
}

/* ── S3 WAVE 2 — the family PEAK + the chameleon pair ─────────────────────────
   family ask: the gathered members with the shared glyph LIT (light by
   CONTRAST — the tails recede to a quieter ink, the family glyph stays full
   sumi; no new hue, the locked inline semantics hold), the glyph itself
   large, kanji-KEYWORD tiles. Reveal: the kanji calling card. */
.kw-fam-gather {
    display: flex;
    flex-direction: column;
    gap: clamp(7px, 0.65vw, 11px);
    align-items: center;
    margin-bottom: clamp(14px, 1.3vw, 22px);
}
.kw-fam-member { display: flex; align-items: baseline; gap: 12px; }
.kw-fam-member .wj {
    font-family: var(--font-jp);
    font-size: clamp(21px, 1.7vw, 28px);
    line-height: 1.25;
    color: rgba(44, 44, 44, 0.55);
}
.kw-fam-member .wr { font: italic clamp(12px, 0.92vw, 14.5px) var(--font-ui); color: var(--color-amber-deep); }
.kw-fam-hl { color: var(--color-ink); font-weight: 600; }
.kw-fam-glyph {
    font-family: var(--font-jp);
    font-size: clamp(46px, 3.8vw, 64px);
    line-height: 1.15;
    color: var(--color-ink);
    text-align: center;
}
.kw-choice--kw {
    padding: clamp(12px, 1vw, 15px) 18px;
    font-size: clamp(15px, 1.05vw, 17.5px);
    font-weight: 500;
    line-height: 1.35;
}

/* the kanji calling card — the reveal anchor (sumi-e on paper, the glyph as
   the headword, honest kun/on inked in the reading family colours) */
.kw-fam-img { background: #F6F3EC; }
.kw-fam-img img { object-fit: contain; }
.kw-plq-jp.kw-fam-glyphbig { font-size: clamp(54px, 4.2vw, 76px); line-height: 1.12; }
.kw-fam-reads { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 6px; }
.kw-fam-read { display: inline-flex; align-items: baseline; gap: 7px; font-size: clamp(13.5px, 1vw, 16px); }
.kw-fam-read b {
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(10.5px, 0.8vw, 12.5px);
    padding: 1px 6px 2px;
    border-radius: 4px;
}
.kw-fam-read--kun b { color: var(--kw-kun); background: rgba(61, 90, 128, 0.09); }
.kw-fam-read--on b { color: var(--kw-on); background: rgba(158, 94, 67, 0.10); }
.kw-fam-read span[lang="ja"] { font-family: var(--font-jp); }
.kw-fam-read--kun span[lang="ja"] { color: var(--kw-kun); }
.kw-fam-read--on span[lang="ja"] { color: var(--kw-on); }
.kw-fam-read i { font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-amber-deep); }

/* the family, named — the pair line's kanji cousin */
.kw-fam-line { flex-wrap: wrap; row-gap: 4px; }
.kw-fam-mem { display: inline-flex; align-items: baseline; gap: 6px; }
.kw-fam-mem .jp .kw-fam-hl { font-weight: 600; }
.kw-fam-sep { color: var(--color-faint-warm); }

/* the kanji-shaped miss split — halves are reference, not doors. The art
   frame follows the sumi-e's own height here (the 3:2 painting aspect
   would letterbox dead paper around a squarish kanji image) */
.kw-split--kanji .kw-split-ans,
.kw-split--kanji .kw-split-pick { cursor: default; }
.kw-split--kanji .kw-fam-img { aspect-ratio: auto; }
.kw-split--kanji .kw-fam-img img { height: clamp(96px, 8vw, 140px); width: 100%; }
.kw-split--kanji .kw-plq-jp.kw-fam-glyphbig { font-size: clamp(40px, 3.2vw, 58px); }

/* ── the chameleon coats ──────────────────────────────────────────────────────
   the placard's sense STACK (every coat, verbatim); the chamTest reveal
   marks each coat got ✓ / missed ○, and names a worn trap below */
.kw-plq-en.kw-coats { display: flex; flex-direction: column; gap: 4px; }
.kw-coat { display: block; position: relative; }
.kw-coat + .kw-coat { margin-top: 1px; }
.kw-coat-mark { display: inline-block; width: 1.15em; font-weight: 600; }
.kw-coat--got .kw-coat-mark { color: var(--moss-aa); }
.kw-coat--missed { color: var(--color-ink); }
.kw-coat--missed .kw-coat-mark { color: var(--amber-aa); }
.kw-coat--missed .kw-coat-note {
    display: block;
    font: italic clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--amber-aa);
    margin-left: 1.15em;
}
.kw-cham-trap {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: clamp(8px, 0.7vw, 12px);
    font-size: clamp(13px, 0.95vw, 15.5px);
    color: var(--color-ink);
}
.kw-cham-trap .ink { flex: none; font-weight: 600; color: var(--amber-aa); }

/* chamTest ask — toggle chips + the one deliberate door (the only MCQ where
   the tap is not yet the attempt; the commit is) */
.kw-choice--coat {
    padding: clamp(11px, 0.9vw, 14px) 18px;
    font-size: clamp(14.5px, 1vw, 17px);
    font-weight: 500;
    line-height: 1.35;
    justify-content: flex-start;
    text-align: left;
}
.kw-choice--coat.is-picked {
    border-color: var(--color-accent);
    background: rgba(61, 90, 128, 0.06);
    box-shadow: inset 0 0 0 1px rgba(61, 90, 128, 0.35), 0 1px 2px rgba(var(--sh), 0.05);
}
.kw-choices.kw-locked .kw-choice--coat.is-picked { opacity: 1; }
.kw-cham-commitrow { margin-top: clamp(12px, 1.1vw, 18px); display: flex; justify-content: center; }
.kw-cham-commit {
    appearance: none;
    cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.16);
    border-radius: 10px;
    padding: clamp(9px, 0.8vw, 12px) clamp(20px, 1.8vw, 30px);
    font-family: var(--font-ui);
    font-size: clamp(13.5px, 1vw, 16px);
    color: var(--color-ink);
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 3px 8px -6px rgba(var(--sh), 0.14);
    transition: border-color 0.18s var(--ease-settle), box-shadow 0.18s, opacity 0.18s, transform 0.18s;
}
.kw-cham-commit .jp { font-family: var(--font-jp); font-weight: 600; }
.kw-cham-commit i { font-style: italic; font-size: 0.88em; color: var(--color-faint-warm); }
.kw-cham-commit:hover:not([disabled]) {
    border-color: var(--color-accent);
    box-shadow: 0 5px 13px -6px rgba(var(--sh), 0.22);
    transform: translateY(-1px);
}
.kw-cham-commit[disabled] { cursor: default; opacity: 0.45; box-shadow: none; transform: none; }

/* ── S3w3: the production + sentence stones ────────────────────────────────
   REGISTER — the ladder ask: the family's shared MEANING is the cue, in
   plain English (the one ask without a Japanese head — any rung shown
   would be a choice answering itself) */
.kw-reg-cue {
    font: 500 clamp(1.5rem, 1.9vw, 2.3rem) var(--font-ui);
    letter-spacing: 0.01em;
    line-height: 1.25;
    color: var(--color-ink);
    max-width: 24ch;
    text-wrap: balance;
}
/* COUNTER — the count in plain English under the written compound (the
   compound keeps kanji in every display mode: its kana IS the answer) */
.kw-cnt-cue {
    font: 400 clamp(0.95rem, 0.95vw, 1.15rem) var(--font-ui);
    color: var(--color-stone);
    margin-top: clamp(6px, 0.55vw, 10px);
}
/* CLOZE — the word's own sentence with the word gone. ONE fixed-width
   blank for every answer: a lemma-length blank would measure the fill
   (the format-tell law). Ruby rides at sentence scale when the cut is
   clean; the romaji line returns blanked or not at all. */
.kw-cloze-sent {
    font-family: var(--font-jp);
    font-weight: 500;
    font-size: clamp(1.3rem, 1.65vw, 2rem);
    line-height: 1.95;
    color: #332F2B;
    max-width: 24ch;
    text-wrap: balance;
    font-feature-settings: 'palt' 1;
}
.kw-cloze-sent rt { font-size: 0.42em; letter-spacing: 0; color: var(--color-stone); }
/* the filled word inks like every surface (S3.9c — the blank made whole) */
.kw-cloze-sent .hit {
    border-bottom: 2px solid rgba(160, 120, 80, 0.4);
    animation: kwInkRise 0.42s var(--ease-brush) both;
}
.kw-cloze-sent .hit ruby { border-bottom: none; }
.kw-cloze-blank {
    display: inline-block;
    width: 2.6em;
    height: 0.95em;
    margin: 0 0.12em;
    border-bottom: 2px solid rgba(var(--sh), 0.42);
    border-radius: 1px;
}
.kw-cloze-ro {
    font: italic 500 clamp(0.95rem, 0.95vw, 1.15rem) var(--font-ui);
    letter-spacing: 0.03em;
    color: var(--color-amber-deep);
    margin-top: clamp(8px, 0.7vw, 12px);
    max-width: 44ch;
}
.kw-cloze-roblank {
    display: inline-block;
    width: 3em;
    height: 0.72em;
    margin: 0 0.15em;
    border-bottom: 1.5px solid rgba(var(--sh), 0.28);
}
/* the reveal: the sentence made whole — the slips' own sentence anatomy a
   notch up in scale, the filled word inked via .hit like every surface */
/* the veils lift on the mark (S3.9c) — whatever returns settles like ink */
.kw-lifted { animation: kwFuriIn 0.45s var(--ease-settle); }
/* form-pick reveals: the pair line carries a small sound disc — seat it on
   the text line, never floating (the slip rows' own alignment) */
.kw-formline .kw-form-audio { align-self: center; }

/* ── ふりがな on demand (owner 2026-07-10) — a kanji-rendered ask carries
   its ruby HIDDEN; the quiet reading chip reveals it in place. A help tap,
   never a grade signal: CP-A untouched (romaji stays earned), and the chip
   never boards a face whose ANSWER is the reading (the counter compound
   builds its own head; a future readctx stone must keep doing the same). */
.kw-furi-wrap { display: flex; flex-direction: column; align-items: center; }
.kw-furi-off rt { display: none; }               /* ruby collapses to plain text */
.kw-furi-on .kw-ask-jp,
.kw-furi-on .kw-payoff-jp,
.kw-furi-on .kw-cloze-sent { line-height: 1.6; } /* room for the revealed ruby */
.kw-furi-on rt {
    opacity: 1 !important;                       /* wakes past any mastery fade */
    animation: kwFuriIn 0.35s var(--ease-settle);
}
.kw-ask-jp rt,
.kw-payoff-jp rt { font-size: 0.32em; letter-spacing: 0; color: var(--color-stone); font-weight: 400; }
@keyframes kwFuriIn { from { opacity: 0; } }
/* the reading chip speaks the veil-chip voice — ONE reveal-door idiom
   app-wide (owner 2026-07-10: the dashed pill read as a placeholder,
   not a control this app would own) */
.kw-furi-chip,
.kw-ro-chip,
.kw-en-chip {
    appearance: none;
    cursor: pointer;
    margin-top: clamp(7px, 0.6vw, 10px);
    padding: 4px 14px;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    letter-spacing: 0.04em;
    color: var(--color-stone);
    background: transparent;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-full);
    box-shadow: none;
    transform: none;
    transition: color 0.18s, border-color 0.18s;
}
.kw-furi-chip:hover,
.kw-ro-chip:hover,
.kw-en-chip:hover {
    color: var(--color-ink);
    border-color: var(--color-faint);
    background: none;
    box-shadow: none;
    transform: none;                             /* the global button chrome never leaks in */
}
/* the chip's second rung settles in like the ruby it follows */
.kw-furi-wrap .kw-ask-ro { animation: kwFuriIn 0.35s var(--ease-settle); }
/* 禁則 kinsoku — a wrapped line never opens with 、。; the blank and its
   following punctuation travel together */
.kw-nobr { white-space: nowrap; }
.kw-cloze-sent, .kw-payoff-jp { line-break: strict; }
/* the cloze doors — reading and meaning side by side, tapped separately */
.kw-cloze-doors {
    display: flex;
    gap: 10px;
    justify-content: center;
    margin-top: clamp(7px, 0.6vw, 10px);
}
.kw-cloze-doors .kw-furi-chip,
.kw-cloze-doors .kw-ro-chip,
.kw-cloze-doors .kw-en-chip { margin-top: 0; }
.kw-cloze-en {
    font: 400 clamp(13px, 1vw, 15.5px) var(--font-ui);
    color: var(--color-stone);
    margin-top: clamp(8px, 0.7vw, 12px);
    animation: kwFuriIn 0.35s var(--ease-settle);
}
.kw-cloze-ro { animation: kwFuriIn 0.35s var(--ease-settle); }
@media (prefers-reduced-motion: reduce) {
    .kw-furi-on rt, .kw-furi-wrap .kw-ask-ro, .kw-cloze-en, .kw-cloze-ro,
    .kw-lifted { animation: none; }
}


/* ── owner round 2026-07-10 — calm + recall-first ──────────────────────────
   RECALL-FIRST: the question stands alone; the choices arrive on the
   learner's tap (reverses the demo-era instant-choices ruling, on record).
   The wait line speaks the flip's own hint voice — a door label, not a
   caption. */
.kw-ask-holding .kw-choices,
.kw-ask-holding .kw-ask-hint,
.kw-ask-holding .kw-cx-built,
.kw-ask-holding .kw-cx-commitrow,
.kw-ask-holding .kw-cham-commitrow { display: none; }
.kw-ask-holding .kw-face-ask { cursor: pointer; }
.kw-ask-wait {
    font: 400 clamp(12px, 0.85vw, 14px) var(--font-ui);
    color: var(--color-faint-warm);
    margin-top: clamp(18px, 1.9vw, 28px);
}
.kw-ask-wait .jp { font-family: var(--font-jp); margin-left: 7px; }
.kw-ask-wait i { font-style: italic; margin-left: 5px; }
.kw-ask-wait kbd {
    font: 500 10px var(--font-ui);
    color: var(--color-faint-warm);
    border: 1px solid var(--color-divider);
    border-bottom-width: 2px;
    border-radius: 4px;
    padding: 0 5px;
    margin-left: 7px;
    background: rgba(255, 255, 255, 0.5);
}
.kw-ask-open .kw-choices { animation: kwChoicesIn 0.38s var(--ease-settle) backwards; }
@keyframes kwChoicesIn { from { opacity: 0; transform: translateY(7px); } }
@media (prefers-reduced-motion: reduce) { .kw-ask-open .kw-choices { animation: none; } }

/* the see-ask widens — the paintings ARE the question (owner: the thumbs
   read small beside the ask and the reveal); the settle returns the card
   to placard width for the reveal — EXCEPT the see reveal itself, whose
   answer is the painting large (S3.9, turnCard keeps the class).
   Gallery-size round (owner 2026-07-16): the tiles now FILL this width
   (flex row, no fixed cap) and hang the full sheet, so the card's reach
   is the paintings' reach — dead paper on the shoulders would lie. */
.kw-card { transition: width 0.3s var(--ease-settle); }
.kw-card--see { width: clamp(700px, 62vw, 1240px); }

/* ══ S3.9c RESPONSE ANATOMY — what survives of the response cards serves
   the flip's turn (respMeaning) and the comparison scenes (respForm, the
   coat stack). The identity pieces reuse the placard's own type
   (.kw-plq-*) so the room keeps one voice. */
.kw-resp { text-align: left; }
.kw-resp .kw-plq { padding-top: clamp(8px, 0.8vw, 14px); }

/* the door — the word stays a SILENT link (owner 2026-07-11: the dotted
   line read as decoration): nothing at rest, the interactive indigo on
   hover/focus. The SPOKEN door is the word-card chip below. */
.kw-word-door, .kw-kanji-door {
    cursor: pointer;
    border-bottom: 1px dotted transparent;
    transition: color 0.18s ease, border-color 0.18s ease;
}
.kw-word-door:hover, .kw-word-door:focus-visible,
.kw-kanji-door:hover, .kw-kanji-door:focus-visible {
    color: var(--color-accent);
    border-bottom-color: currentColor;
    outline: none;
}

/* (the spoken 'word card' chip retired everywhere — S3.9c owner round 2:
   the word is the silent door, nothing speaks for it) */

/* the identity's own sound — a quiet disc BESIDE the romaji (flex keeps it
   on the line; kw-form-audio's forms-ladder margin-left:auto must not
   push it to the card's far edge here) */
.kw-resp .kw-plq-ro, .kw-form-hero .kw-plq-ro {
    display: flex; align-items: center; gap: 8px;
}
.kw-resp-audio { vertical-align: middle; margin-left: 0; }

/* one compact word row — the form comparison's base-word door */
.kw-wrow {
    display: flex; align-items: baseline; gap: 10px; min-width: 0;
    flex-wrap: wrap;
    margin: clamp(5px, 0.5vw, 9px) 6px 0;
}
.kw-wrow .jp {
    font-family: var(--font-jp); font-weight: 600;
    font-size: clamp(17px, 1.35vw, 22px); color: var(--color-jp-text);
}
.kw-wrow .ro { font-style: italic; color: var(--color-amber-deep); font-size: clamp(12px, 0.95vw, 15px); }
.kw-wrow .en { color: var(--color-ink); font-size: clamp(12.5px, 1vw, 15.5px); }
.kw-wrow .en::before { content: '· '; color: var(--color-faint-warm); }
.kw-wrow .kw-statusline { margin-left: 4px; }

/* conjugation / counter — the asked form leads with its sound */
.kw-form-hero { padding: clamp(8px, 0.8vw, 14px) 6px 0; }
.kw-form-hero-lv {
    font: 600 clamp(10px, 0.78vw, 12px) var(--font-ui);
    letter-spacing: var(--track-eyebrow); text-transform: uppercase;
    color: var(--color-stone); margin-bottom: 4px;
}
.kw-form-hero-jp {
    font-family: var(--font-jp); font-weight: 600; line-height: 1.25;
    font-size: clamp(1.7rem, 3vw, 2.6rem); color: var(--color-jp-text);
}
.kw-form-hero-kana {
    font-family: var(--font-jp); line-height: 1.3;
    font-size: clamp(1.2rem, 1.9vw, 1.7rem); color: var(--color-jp-text);
}
.kw-form-base {
    margin-top: clamp(10px, 1vw, 16px); padding-top: clamp(8px, 0.8vw, 12px);
    border-top: 1px dashed rgba(var(--sh), 0.1);
}

/* chamTest — the marked coat stack is the star */
.kw-coat-head { display: flex; align-items: baseline; gap: 10px; margin: 6px 6px 4px; }
.kw-coat-head .jp { font-family: var(--font-jp); font-weight: 600; font-size: clamp(20px, 1.7vw, 27px); color: var(--color-jp-text); }
.kw-coat-head .ro { font-style: italic; color: var(--color-amber-deep); }
.kw-resp--coats .kw-coats { margin: 2px 6px 0; font-size: 1.04em; }

/* ══ the word SHEET — the full presentation IN THE ROOM ══════════════════
   (owner 2026-07-11: a modal read as forced — "the room breathes"): the
   reveal steps aside into a hidden holder; the presentation card takes
   the stage the way a first meeting looks, the washi material settling
   on the shoulders around it. 戻る / Escape hand the reveal back. */
.kw-sheet-card .kw-sheet-hero { text-align: left; }
/* the COMPARISON detour rides the sheet vehicle at the reveal card's own
   width; only the see-miss wants the gallery room (the two paintings) —
   capped so its width can never collide with the shoulder slips (round C) */
.kw-cmp-card.kw-cmp--see { width: min(clamp(700px, 56vw, 1080px), calc(60vw - 80px)); }

/* ══ round C — the rooms ══════════════════════════════════════════════ */
/* the flip's answer keeps the PAPER: the turn must not strip the sheet —
   the flip reveal was the one bare room in the walk (K2's readctx is the
   same recall-flip class and keeps the same sheet) */
.kw-flipcard .kw-face-reveal,
.kw-cxcard .kw-face-reveal {
    position: relative;
    background: var(--color-card);
    border: 1px solid rgba(44, 44, 44, 0.05);
    border-top-color: rgba(255, 255, 255, 0.7);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 3px rgba(var(--sh), 0.05), 0 5px 14px -6px rgba(var(--sh), 0.08),
        inset 0 0 70px rgba(120, 100, 70, 0.035);
    padding: clamp(26px, 2.2vw, 38px) clamp(26px, 2.2vw, 38px) clamp(22px, 1.8vw, 32px);
    min-height: clamp(320px, 34vh, 440px);
    justify-content: center;
}
/* an imageless comparison keeps the room's footprint — the form anatomy
   sits mid-sheet, never a strip stranded over a void */
.kw-cmp-card .kw-face-reveal { min-height: clamp(360px, 38vh, 500px); justify-content: center; }
/* the answer half rests on a quiet placard ground */
.kw-cmp-card .kw-split-ans .kw-plq {
    border-bottom: 1px solid rgba(var(--sh), 0.10);
    padding-bottom: clamp(8px, 0.8vw, 12px);
}
/* the cloze's tested sentence, made whole, leads the scene */
.kw-cloze-lead { margin: 0 6px clamp(10px, 1vw, 15px); text-align: left; }
.kw-cloze-lead .kw-refsec-jp .hit { border-bottom-color: rgba(107, 127, 92, 0.55); }
.kw-cloze-lead-ro {
    display: block;
    font: italic clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--color-amber-deep);
    margin-top: 3px;
}
/* the 活 ladder's ASKED rung lights (the register --here idiom) */
.kw-form-row--here .kw-form-kana { font-weight: 700; }
.kw-form-row--here .kw-form-lbl .jp { color: var(--color-ink); }
/* 戻る — the paper exit, in the exit row's own seat */
.kw-sheet-back {
    appearance: none;
    cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.14);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: clamp(9px, 0.85vw, 13px) 6px;
    flex: 1;
    font: 600 clamp(11px, 0.82vw, 13px) var(--font-ui);
    letter-spacing: 0.06em;
    color: var(--color-stone);
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 3px 8px -5px rgba(var(--sh), 0.10);
    transform: none;
    transition: border-color 0.18s, color 0.18s, background 0.18s, box-shadow 0.18s, transform 0.18s;
}
.kw-sheet-back:hover {
    transform: translateY(-1px);
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 7%, transparent);
    box-shadow: 0 2px 4px rgba(var(--sh), 0.06), 0 5px 12px -5px rgba(var(--sh), 0.15);
}
.kw-sheet-back:active { transform: translateY(0.5px); transition-duration: 0.06s; }
.kw-sheet-back .jp {
    font-family: var(--font-jp);
    font-size: clamp(14px, 1.1vw, 17px);
    font-weight: 400;
    letter-spacing: 0.02em;
    line-height: 1;
}
.kw-sheet-back i { font: italic clamp(11px, 0.8vw, 13px) var(--font-ui); font-weight: 400; color: var(--color-faint-warm); }
@media (prefers-reduced-motion: reduce) {
    .kw-word-door, .kw-kanji-door { transition: none; }
}

/* ═══ ROUND E — the sound cluster: the reveal's own reference block ══════════
   E1 the register ladder (E2 counter ladder · E3 twin contrast ride the same
   seat). Mounts between the marked tiles and the ink line; enters on the
   settle cascade after the pills ink, before the ink line presses. */
.kw-reveal-ladder {
    width: 100%;
    max-width: clamp(340px, 27vw, 470px);
    margin-top: clamp(12px, 1.1vw, 18px);
    text-align: left;
}
.kw-card.kw-just-marked .kw-reveal-ladder {
    animation: kwFuriIn 0.45s var(--ease-settle) 0.26s backwards;
}
/* E1 rungs borrow the 礼 slip's row anatomy wholesale; only the disc's ink
   (amber — the sound seat) and the asked rung's quiet wash are its own.
   The wash stays a paper tone: moss marks verdicts, gold is scarcer still —
   "the rung in question" is emphasis, not a grade. */
.kw-reg-ladder .kw-reg-row { padding: 5px 8px; }
.kw-reg-ladder .kw-form-audio { color: var(--color-amber-deep); }
.kw-reg-ladder .kw-form-audio:hover { color: var(--color-ink); }
.kw-reg-ladder .kw-reg-row--here {
    background: rgba(var(--sh), 0.05);
    border-radius: 6px;
}
.kw-reg-ladder .kw-reg-row--here + .kw-reg-row,
.kw-reg-ladder .kw-reg-row + .kw-reg-row--here { border-top-color: transparent; }
/* E2 the counter's 1-10 strip — compact cells (numeral / kana / romaji /
   disc), five to a row; the ASKED cell wears the same quiet wash as the
   register ladder's lit rung. Wider than the tiles: ten kana readings
   need the room, and the strip reads as ONE series, not ten buttons. */
.kw-cnt-ladder {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 4px 6px;
    max-width: clamp(380px, 32vw, 560px);
}
.kw-cnt-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    padding: 6px 4px 4px;
    border-radius: 8px;
    min-width: 0;
}
.kw-cnt-cell .n {
    font: 600 10px var(--font-ui);
    color: var(--color-faint-warm);
    font-variant-numeric: tabular-nums;
}
.kw-cnt-cell .k {
    font-family: var(--font-jp);
    font-size: clamp(12.5px, 0.95vw, 15px);
    color: var(--color-ink);
    white-space: nowrap;
}
.kw-cnt-cell .r {
    font: italic clamp(9.5px, 0.72vw, 11px) var(--font-ui);
    color: var(--color-amber-deep);
    white-space: nowrap;
}
/* the forms-ladder disc idiom, centered in its cell (margin-left:auto is
   the flex-row seat — it must not shove the disc off a column cell) */
.kw-cnt-cell .kw-form-audio { margin-left: 0; margin-top: 1px; color: var(--color-amber-deep); }
.kw-cnt-cell .kw-form-audio:hover { color: var(--color-ink); }
.kw-cnt-cell--here { background: rgba(var(--sh), 0.05); }
.kw-cnt-cell--here .k { font-weight: 700; }
.kw-cnt-cell--here .n { color: var(--color-ink); }
/* the counter NAMED (owner 2026-07-12): the base word's identity leads the
   ladder — the writing is the room's silent word-door, the gloss says what
   the counter itself means (the compound head can't) */
.kw-cnt-name {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 2px 7px;
    padding-bottom: 3px;
}
.kw-cnt-name .jp {
    font-family: var(--font-jp); font-weight: 600; line-height: 1.4;
    font-size: clamp(1rem, 1.05vw, 1.2rem); color: var(--color-jp-text);
}
.kw-cnt-name .wr {
    font-style: italic; font-size: clamp(0.78rem, 0.8vw, 0.88rem);
    letter-spacing: 0.02em; color: var(--color-amber-deep);
}
.kw-cnt-name .wg { font-size: clamp(0.8rem, 0.82vw, 0.9rem); color: var(--color-ink); }
.kw-cnt-name .wg::before { content: '· '; color: var(--color-faint-warm); }
/* E3 the soundalike twin contrast — both paintings side by side (the
   see-tile frame: inset hairline, 3:2 cover, caption strip UNDER the
   art), answer first; one control plays the pair in sequence. Paintings
   are reference, not tiles — no hover lift, no rings, never a mark. */
.kw-twin-contrast { max-width: clamp(380px, 32vw, 560px); }
.kw-twin-figs {
    display: flex;
    gap: clamp(10px, 0.9vw, 14px);
    justify-content: center;
}
.kw-twin-fig {
    flex: 1 1 0;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    border-radius: 10px;
    background: var(--color-card-bright);
    box-shadow: inset 0 0 0 1px rgba(var(--sh), 0.10), 0 3px 9px -5px rgba(var(--sh), 0.22);
}
.kw-twin-fig img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; }
.kw-twin-fig .kw-img-fb { display: none; }
.kw-twin-fig.kw-img-lost .kw-img-fb {
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 3 / 2;
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(1.2rem, 1.4vw, 1.6rem);
    color: var(--color-stone);
    background: var(--color-card);
}
/* the caption strip borrows the see-tile kw-img-id recipe, grown one seat:
   the short GLOSS joins writing + romaji (owner 2026-07-12 — each figure
   self-contained; the twins sound the same, the caption does the telling) */
.kw-twin-fig .kw-img-id {
    display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
    gap: 2px 7px; width: 100%; padding: 4px 8px 8px;
}
.kw-twin-fig .kw-img-id .wj {
    font-family: var(--font-jp); font-weight: 600; line-height: 1.4;
    font-size: clamp(0.95rem, 1vw, 1.1rem); color: var(--color-jp-text);
}
.kw-twin-fig .kw-img-id .wj rt { font-size: 0.5em; font-weight: 400; color: var(--color-stone); letter-spacing: 0; }
.kw-twin-fig .kw-img-id .wr {
    font-style: italic; font-size: clamp(0.78rem, 0.8vw, 0.88rem);
    letter-spacing: 0.02em; color: var(--color-amber-deep);
}
.kw-twin-fig .kw-img-id .wg {
    font-size: clamp(0.8rem, 0.82vw, 0.9rem);
    color: var(--color-ink);
}
.kw-twin-fig .kw-img-id .wg::before { content: '· '; color: var(--color-faint-warm); }
@media (prefers-reduced-motion: reduce) {
    .kw-card.kw-just-marked .kw-reveal-ladder { animation: none; }
}

/* ══ round E2 — the connection round (陽だまり payoffs + rung doors) ═══ */
/* the kanji sheet's family cluster: relatives as small nodes — met kanji
   lit on paper, unmet as ghosts (no paper, dashed hairline, faint ink —
   the room's unlit-shadow idiom at node scale). Captions stay legible on
   ghosts: a ghost that can't be read teaches nothing. */
.kw-famclu {
    max-width: clamp(340px, 30vw, 520px);
    /* left edge sits on the placard column (its 6px text inset), never a
       floating centered band (fleet E2 composition) */
    margin: clamp(14px, 1.4vw, 22px) 0 0;
    padding: 0 6px;
    text-align: left;
}
.kw-famclu + .kw-famclu { margin-top: 10px; }
.kw-famclu-eb {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font: 500 clamp(10.5px, 0.8vw, 12.5px) var(--font-ui);
    color: var(--color-faint-warm);
    letter-spacing: 0.04em;
}
.kw-famclu-eb .jp {
    font-family: var(--font-jp);
    font-size: clamp(14px, 1.05vw, 17px);
    color: var(--color-ink);
}
.kw-famclu-eb i { font-style: normal; }
.kw-famclu-row {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 6px;
    margin-top: 7px;
}
.kw-famclu-node {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 2px;
    padding: 7px 9px 5px;
    min-width: 56px;
    border-radius: 8px;
    background: var(--color-card);
    border: 1px solid rgba(var(--sh), 0.10);
}
.kw-famclu-k {
    font-family: var(--font-jp);
    font-size: clamp(22px, 1.7vw, 27px);
    line-height: 1.15;
    color: var(--color-ink);
}
.kw-famclu-cap {
    font: 400 clamp(9.5px, 0.74vw, 11.5px) var(--font-ui);
    color: var(--color-faint-warm);
    max-width: 92px;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* the member's voice, decoupled from its meaning (owner 2026-07-16): the
   reading sits ABOVE the glyph in the romaji voice — italic amber, the
   inline color law — never fused into the grey cap. The slot renders
   strip-wide when any member has a voice, so the glyph line stays level. */
.kw-famclu-ro {
    display: block;
    min-height: 1.35em;
    font: italic 400 clamp(9.5px, 0.74vw, 11.5px) var(--font-ui);
    color: var(--color-amber-deep);
    text-align: center;
    line-height: 1.35;
}
.kw-famclu-ghost {
    background: transparent;
    border-style: dashed;
    border-color: rgba(var(--sh), 0.15);
}
.kw-famclu-ghost .kw-famclu-k { color: rgba(var(--sh), 0.55); }   /* ≥3:1 on the paper — a ghost still reads */
.kw-famclu-here { border-color: rgba(var(--sh), 0.30); }
.kw-famclu-worn .kw-famclu-k { opacity: 0.78; }   /* the meaning link wore thin — the caption says 'worn' */
/* a node door is a TILE, not an inline word — the shared door recipe's
   dotted underline steps aside; the ring carries the interactive indigo.
   Both states claimed here (equal-specificity hover lesson on record). */
.kw-famclu-node.kw-kanji-door {
    border-bottom: 1px solid rgba(var(--sh), 0.10);
    transition: border-color 0.18s ease, transform 0.18s ease;
}
.kw-famclu-node.kw-famclu-ghost.kw-kanji-door { border-bottom: 1px dashed rgba(var(--sh), 0.15); }
.kw-famclu-node.kw-kanji-door:hover,
.kw-famclu-node.kw-kanji-door:focus-visible {
    color: inherit;
    border-color: var(--color-accent);
    border-bottom-color: var(--color-accent);
    transform: translateY(-1px);
    outline: none;
}
.kw-famclu-more {
    align-self: center;
    font: 400 10.5px var(--font-ui);
    color: var(--color-faint-warm);
    padding: 0 4px;
    white-space: nowrap;
}

/* the word sheet's 陽だまり crest — the word page's crest recipe at walk
   scale: one warm sunlit strip, the door into the graph room. */
.kw-sheet-crest {
    appearance: none;
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    max-width: clamp(300px, 24vw, 420px);
    margin: clamp(12px, 1.2vw, 18px) 6px 0;   /* on the placard column, like the strips */
    padding: 9px 12px;
    background: linear-gradient(174deg, rgba(255, 253, 246, 0.85), rgba(250, 244, 230, 0.75));
    border: 1px solid rgba(126, 100, 58, 0.16);
    border-radius: 3px;
    cursor: pointer;
    font-family: inherit;
    text-align: left;
    transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.kw-sheet-crest:hover,
.kw-sheet-crest:focus-visible {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(96, 72, 36, 0.08), 0 10px 24px rgba(96, 72, 36, 0.10);
    outline: none;
}
.kw-crest-sun {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: radial-gradient(closest-side, #FFEEBC 0%, rgba(255, 238, 188, 0.45) 62%, rgba(255, 238, 188, 0) 100%);
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: 15px;
    color: #8A6E35;
}
.kw-crest-tx { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.kw-crest-tx .jp {
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: 13.5px;
    color: var(--color-ink);
}
.kw-crest-tx i {
    font-style: normal;
    font: 400 11px var(--font-ui);
    color: var(--color-faint-warm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kw-crest-go { flex: 0 0 auto; color: var(--color-faint-warm); font-size: 13px; }
@media (prefers-reduced-motion: reduce) {
    .kw-famclu-node.kw-kanji-door,
    .kw-sheet-crest { transition: none; }
    .kw-famclu-node.kw-kanji-door:hover,
    .kw-famclu-node.kw-kanji-door:focus-visible,
    .kw-sheet-crest:hover,
    .kw-sheet-crest:focus-visible { transform: none; }
}

/* ═══ OWNER ROUND (2026-07-12) — the head completes at the mark ═════════════
   Items 5+6: once graded, a word-headed ask's English joins the lifted
   reading and romaji — the reveal is self-contained. The line speaks the
   placard's own English voice (plain UI face, secondary ink), never the
   romaji's amber: one species per meaning. */
.kw-ask-en {
    font: 400 clamp(0.95rem, 0.95vw, 1.15rem) var(--font-ui);
    /* the placard's own English ink (.kw-plq-en) — a shade warmer than the
       question line beneath, so meaning and chrome never share one grey */
    color: rgba(44, 44, 44, 0.72);
    margin-top: clamp(4px, 0.4vw, 7px);
    max-width: 36em;
}

/* Item 7 — the word, built (reshaped owner round 2026-07-16, pick A1 of
   design-mockups/kanji-inside-word): the row IS the word written large —
   the caption header and the + joiners are gone, 間 air alone separates.
   Each glyph wears decoupled species: in-word reading ABOVE in the romaji
   voice, meaning BELOW in plain ink — the head's own placement grammar
   (ruby above, English below) at kanji grain. */
.kw-comp-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: 4px 18px;
    margin-top: 4px;
}
/* the reading line: italic amber = the romaji voice (inline color law).
   Rendered row-wide when any node has a voice — the empty slot keeps the
   glyph line level where a block read silences one part. */
.kw-comp-ro {
    display: block;
    min-height: 1.35em;
    font: italic 400 clamp(10px, 0.78vw, 12px) var(--font-ui);
    color: var(--color-amber-deep);
    text-align: center;
    line-height: 1.35;
}
/* the meaning line WRAPS — a one-line ellipsis would clip a present
   keyword mid-word ('counter for small th…'), quietly falsifying the
   lesson (fleet). */
.kw-comp-mean {
    font: 400 clamp(10px, 0.78vw, 12px) var(--font-ui);
    color: var(--color-faint-warm);
    max-width: 118px;
    text-align: center;
    line-height: 1.35;
    margin-top: 3px;
}
/* bare ink (S3.5-C): on the REVEAL the built-word tiles lose their paper —
   ink strength alone says met/ghost (the unlit-shadow idiom already carries
   it). The hand's rest is the WARM WASH (the kanji-room brush idiom), never
   a drawn ring — owner round 3: the indigo box read alien on the washi. The
   sheet's own family cluster keeps its tiles — the desk is owner-ruled. */
.kw-comp-row .kw-famclu-node,
.kw-comp-row .kw-famclu-node.kw-kanji-door,
.kw-comp-row .kw-famclu-node.kw-famclu-ghost {
    background: none;
    border-color: transparent;
    border-style: solid;
    padding: 5px 8px 3px;
    min-width: 54px;
}
.kw-comp-row .kw-famclu-node.kw-kanji-door:hover,
.kw-comp-row .kw-famclu-node.kw-kanji-door:focus-visible {
    border-color: transparent;
    background: rgba(67, 50, 30, 0.045);
}
.kw-comp-row .kw-famclu-k {
    font-size: clamp(30px, 2.4vw, 38px);
}
/* a ghost's voice dims with its ink — but stays legible (a ghost that
   can't be read teaches nothing) */
.kw-famclu-ghost .kw-comp-ro,
.kw-famclu-ghost .kw-famclu-ro { opacity: 0.7; }
/* the comparison's headword handles: the active tick is a quiet underline,
   never a recoloured character — a word being absorbed side-by-side must
   not read as fragmented (fleet; the sheet placard keeps its own tick) */
.kw-split .kw-kt.kw-active {
    color: inherit;
    box-shadow: inset 0 -2px 0 rgba(61, 90, 128, 0.4);
}

/* ═══ S3.5 K1 — the kanji spine: the PLANT and the RIDE ═══════════════════
   The character's biography threads the walk (rulings R1–R7, 2026-07-13):
   the plant names one fresh piece on a discovery; the ride settles a due
   character on a correct reveal. BARE INK since S3.5-C (owner pick,
   2026-07-16, design-mockups/kanji-own-voice; seams dropped same day —
   owner: a dotted rule reads unpolished): the chips lose their boxes AND
   their rules — the glyph stands larger in brush ink and 間 (deliberate
   air) alone does the separating, ONE shared anatomy across every kanji
   moment. Never louder than the word they ride. */
.kw-plant {
    display: flex; align-items: center; gap: 12px;
    margin: clamp(18px, 1.7vw, 28px) auto 0;
    padding: 2px; max-width: clamp(340px, 27vw, 470px);
    text-align: left;
}
.kw-plant-glyph {
    appearance: none; cursor: pointer; background: transparent; border: none;
    padding: 2px 6px; margin: -2px -4px; flex: none; border-radius: 8px;
    font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(32px, 2.5vw, 42px); line-height: 1; color: var(--color-ink);
    transition: background 0.18s;
}
.kw-plant-glyph:hover, .kw-plant-glyph:focus-visible { background: rgba(67, 50, 30, 0.045); outline: none; }
.kw-plant-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.kw-plant-kw { font: 500 clamp(12.5px, 0.95vw, 15px) var(--font-ui); color: var(--color-ink); }
.kw-plant-line { font: italic 400 clamp(11px, 0.84vw, 13px) var(--font-ui); color: var(--color-faint-warm); }
.kw-plant .kw-plant-yurai { margin-left: auto; flex: none; }
.kw-plant-yline {
    display: flex; gap: 8px; align-items: baseline; text-align: left;
    margin: 8px auto 0; max-width: clamp(320px, 26vw, 460px);
    font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui); color: var(--color-stone);
    line-height: 1.55; animation: kwInkRise 0.4s var(--ease-brush) both;
}
.kw-plant-yline .ink { flex: none; font-family: var(--font-jp); font-size: clamp(11px, 0.85vw, 13px); color: var(--kw-clay); }

.kw-kride {
    width: 100%; max-width: clamp(340px, 27vw, 470px);
    margin: clamp(16px, 1.5vw, 24px) auto 0;
    animation: kwInkRise 0.5s var(--ease-brush) 0.5s both;
}
.kw-kride-ask {
    appearance: none; cursor: pointer; width: 100%;
    display: flex; align-items: center; gap: 12px; padding: 2px;
    background: transparent; border: none;
    font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui); color: var(--color-stone);
    text-align: left; transition: color 0.18s;
}
.kw-kride-ask:hover { color: var(--color-ink); background: rgba(67, 50, 30, 0.035); border-radius: 8px; }
.kw-kride-ask .g, .kw-kride-open .g, .kw-kride-done .g {
    flex: none; font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(28px, 2.2vw, 36px); line-height: 1; color: var(--color-ink);
    transition: color 0.18s;
}
.kw-kride-ask .t { min-width: 0; }
.kw-kride-ask i { font-style: italic; color: var(--color-faint-warm); margin-left: auto; flex: none; }
.kw-kride-open {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px;
    padding: 2px; text-align: left;
    animation: kwInkRise 0.35s var(--ease-brush) both;
}
/* the keyword may NOT be crushed to zero — a long keyword wraps the grades
   to their own row instead of painting under them (S3.5-C floor fix) */
.kw-kride-open .kwl { font: 500 clamp(12.5px, 0.95vw, 15px) var(--font-ui); color: var(--color-ink); flex: 1 1 140px; min-width: 0; }
.kw-kride-grades { display: flex; gap: 6px; margin-left: auto; flex: none; }
.kw-kride-grades .kw-grade-btn { flex: none; padding: 7px 12px; font-size: clamp(9.5px, 0.74vw, 11px); gap: 7px; }
/* the grades speak the room's brush voice at chip scale (the audit's HIGH:
   these once fell to 10px Inter with the romaji outsizing the Japanese) */
.kw-kride-grades .kw-grade-btn .jp { font-size: clamp(13px, 1vw, 16px); white-space: nowrap; }
.kw-kride-grades .kw-grade-btn i { font-size: clamp(10px, 0.76vw, 12px); }
.kw-kride-done {
    display: flex; align-items: center; gap: 12px; justify-content: center;
    padding: 2px 4px;
    animation: kwInkRise 0.35s var(--ease-brush) both;
}
/* the kana-mode settings control tells the truth — the switch cannot act */
#kanjiStudyControl.is-disabled { opacity: 0.45; }
#kanjiStudyControl .st-opt[disabled] { cursor: default; }

/* the plant follows the word it belongs to — it fades in with the meaning
   beat, never leading the reveal (fleet K1; mirrors the .kw-ident gate).
   The hats chip rides the SAME seat and takes the same gate (S3.5-C floor:
   it used to stand alone under an empty meaning area on the early beats) */
.kw-card.kw-disc .kw-plant,
.kw-card.kw-disc .kw-hats {
    opacity: 0; visibility: hidden;
    transition: opacity 0.5s var(--ease-brush), visibility 0s 0.5s;
}
.kw-card.kw-disc:not([data-beat="0"]):not([data-beat="1"]) .kw-plant,
.kw-card.kw-disc:not([data-beat="0"]):not([data-beat="1"]) .kw-hats {
    opacity: 1; visibility: visible;
    transition: opacity 0.5s var(--ease-brush);
}

/* ── S3.5 K2 · the READCTX stone — the reading channel's full-ladder face ────
   Ask: the bare written form at glyph scale, or (needsContext only) the
   anchor's real sentence with the probed run wearing the ○○ maru blank —
   every other run keeps its furigana (context is support, the veiled run is
   the whole question). Nothing on the ask may print the answer: no reading
   chip, no romaji, no gloss. Reveal: the reading arrives inked in ITS OWN
   family colour — kun indigo #3D5A80 / on terracotta #9E5E43, the
   kw-fam-read voice — with the app's sound amber as the honest fallback
   where the family data can't back a claim. */
.kw-cx-cap {
    font: 500 clamp(11px, 0.85vw, 13px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--color-faint-warm);
}
.kw-cx-sent {
    font-family: var(--font-jp);
    font-size: clamp(19px, 1.75vw, 27px);
    line-height: 2.15;                    /* ruby needs headroom */
    color: var(--color-ink);
    text-align: center;
    max-width: min(94%, 680px);
}
.kw-cx-sent rt {
    font-size: 0.42em;
    letter-spacing: 0.02em;
    color: var(--color-stone);
}
/* the probed run: amber dotted floor under the base — "the sound is the
   question here" — and the ○○ maru blank riding where the kana would */
.kw-cx-probe { border-bottom: 2px dotted rgba(160, 120, 80, 0.55); }
.kw-cx-slot::before {
    content: '○○';
    letter-spacing: 2px;
    color: var(--color-amber-deep);
    opacity: 0.8;
}
/* the reveal: the withheld kana lands exactly where the blank asked, bold,
   in the answer's own family ink (amber when the family can't be claimed) */
.kw-cx-probe--shown rt { font-weight: 700; color: var(--color-amber-deep); }
.kw-cx-probe--kun rt { color: var(--kw-kun); }
.kw-cx-probe--on rt { color: var(--kw-on); }
/* word-mode ask — the anchor word alone IS the question, so it holds the
   face at glyph scale (kw-ask-jp brings the family type + --ja-chars fit) */
.kw-cx-wordq { overflow-wrap: anywhere; }

/* the reveal — sentence resolved (sentence variant), then the word; the
   walk's reveal grammar (left placard), not the deck's centered card */
.kw-resp--readctx .kw-cx-sent {
    font-size: clamp(15px, 1.3vw, 20px);
    line-height: 2;
    text-align: left;
    max-width: 100%;
}
.kw-cx-ro {
    font: italic 400 clamp(11px, 0.85vw, 13px) var(--font-ui);
    letter-spacing: 0.04em;
    color: var(--color-stone);
}
.kw-cx-en {
    font: 400 clamp(12px, 0.95vw, 14px) var(--font-ui);
    color: var(--color-stone);
    line-height: 1.5;
}
/* the asked glyph, lit inside its word — the light IS the sheet door */
.kw-cx-hl { color: var(--color-accent); cursor: pointer; }
.kw-cx-hl:hover, .kw-cx-hl:focus-visible { text-decoration: underline 1.5px; text-underline-offset: 6px; }
/* the kana line — the answer in the word's own habitat, the probed span
   inked in its family colour */
.kw-cx-kana {
    font-family: var(--font-jp);
    font-size: clamp(21px, 1.9vw, 28px);
    line-height: 1.45;
    color: var(--color-ink);
}
.kw-cx-kana .kw-cx-read { font-weight: 700; color: var(--color-amber-deep); }
.kw-cx-kana .kw-cx-read--kun { color: var(--kw-kun); }
.kw-cx-kana .kw-cx-read--on { color: var(--kw-on); }
.kw-resp--readctx .kw-plq { gap: 6px; }
/* the look-alike door sits with the identity block it belongs to — the
   readctx reveal reads left, so its tell does too (S3.5-C floor fix) */
.kw-resp--readctx .kw-tell { text-align: left; margin-left: 6px; }

/* ── S3 (Kanji Builder) — the TILE MOUTH: build the reading ───────────────
   The readctx ask as production: a built row of seats fills from a rack
   of kana tiles. The verdict marks the SEATS sound-by-sound — moss for a
   right sound, amber for a voicing-only near (the §3 fairness law made
   visible), vermilion-warm for a wrong one. Tap targets hold ≥44px (the
   iPad is a primary device). */
.kw-cx-built {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: clamp(6px, 0.6vw, 9px);
    margin: clamp(10px, 1vw, 16px) 0 clamp(4px, 0.4vw, 8px);
    flex-wrap: wrap;
}
.kw-cx-seat {
    min-width: clamp(44px, 3.4vw, 52px);
    min-height: clamp(48px, 3.6vw, 56px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-jp);
    font-size: clamp(20px, 1.7vw, 26px);
    color: var(--color-ink);
    border-bottom: 2px solid rgba(var(--sh), 0.22);
    background: transparent;
    transition: background 0.18s var(--ease-settle), border-color 0.18s;
}
.kw-cx-seat.kw-filled {
    cursor: pointer;
    background: var(--color-card-bright);
    border-bottom-color: var(--color-accent);
    border-radius: 8px 8px 0 0;
}
/* the marked row — the verdict lands sound-by-sound */
.kw-cx-seat.kw-cx-good { border-bottom-color: var(--moss-aa); color: var(--moss-aa); cursor: default; }
.kw-cx-seat.kw-cx-near { border-bottom-color: var(--amber-aa); color: var(--amber-aa); cursor: default; }
.kw-cx-seat.kw-cx-bad {
    border-bottom-color: rgba(158, 94, 67, 0.75);
    color: #9E5E43;
    cursor: default;
    text-decoration: line-through 1.5px rgba(158, 94, 67, 0.45);
}
.kw-choices--cxtiles {
    flex-direction: row;          /* the base .kw-choices stacks — a rack rows */
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(7px, 0.7vw, 10px);
    max-width: 560px;
    margin: clamp(14px, 1.3vw, 20px) auto 0;
}
.kw-cxtile {
    flex: 0 0 auto;
    flex-direction: column;
    gap: 1px;
    min-width: clamp(46px, 3.6vw, 56px);
    min-height: clamp(48px, 3.8vw, 58px);
    padding: clamp(5px, 0.5vw, 8px) clamp(8px, 0.7vw, 11px);
}
.kw-cxtile .tk { font-family: var(--font-jp); font-size: clamp(19px, 1.6vw, 24px); line-height: 1.15; }
.kw-cxtile .tr { font-style: italic; font-size: clamp(10.5px, 0.8vw, 12px); color: var(--color-faint-warm); }
/* a used tile rests on the rack — its sound is on a seat now */
.kw-cxtile.kw-used {
    opacity: 0.32;
    cursor: default;
    transform: none;
    box-shadow: none;
    border-color: rgba(var(--sh), 0.09);
}
.kw-cxtile.kw-used:hover { border-color: rgba(var(--sh), 0.09); transform: none; }
.kw-cx-commitrow { margin-top: clamp(12px, 1.1vw, 18px); display: flex; justify-content: center; }
.kw-cx-commit {
    appearance: none;
    cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.16);
    border-radius: 10px;
    padding: clamp(9px, 0.8vw, 12px) clamp(20px, 1.8vw, 30px);
    font-family: var(--font-ui);
    font-size: clamp(13.5px, 1vw, 16px);
    color: var(--color-ink);
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    box-shadow: 0 1px 2px rgba(var(--sh), 0.05), 0 3px 8px -6px rgba(var(--sh), 0.14);
    transition: border-color 0.18s var(--ease-settle), box-shadow 0.18s, opacity 0.18s, transform 0.18s;
}
.kw-cx-commit .jp { font-family: var(--font-jp); font-weight: 600; }
.kw-cx-commit i { font-style: italic; font-size: 0.88em; color: var(--color-faint-warm); }
.kw-cx-commit:hover:not([disabled]) {
    border-color: var(--color-accent);
    box-shadow: 0 5px 13px -6px rgba(var(--sh), 0.22);
    transform: translateY(-1px);
}
.kw-cx-commit[disabled] { cursor: default; opacity: 0.45; box-shadow: none; transform: none; }
/* the fairness line on the ink line — the rule named, one utterance */
.kw-cx-teach { font-style: normal; }
.kw-cx-teach b { font-family: var(--font-jp); font-weight: 600; }
.kw-cx-teach i { font-style: italic; color: var(--color-faint-warm); }
/* the marked identity block mounts under the row — left voice, as the
   readctx reveal always read */
.kw-cx-marked { text-align: left; margin-top: clamp(12px, 1.1vw, 18px); }

/* ── 書 the write stone — kanji tiles on the cx rack ─────────────────────
   the glyph IS the choice: no romaji line (a printed reading would sort
   the same-reading traps and hand back the crutch produce's romaji is),
   a larger hand, and seats sized for a kanji instead of a mora */
.kw-kbtile { min-width: clamp(52px, 4vw, 62px); }
.kw-kbtile .tk { font-size: clamp(24px, 2vw, 30px); line-height: 1.25; }
.kw-kbbuild .kw-cx-seat {
    min-width: clamp(50px, 3.9vw, 60px);
    font-size: clamp(24px, 2vw, 30px);
}
/* sound on demand — the ear sits under the cue, up through the hold */
.kw-kb-ear { display: flex; justify-content: center; margin: clamp(6px, 0.6vw, 10px) 0 0; }

/* ═══ S3.5 K3 — THE ARC: crutch falls · two hats · the tell door ═══════════
   The channel's payoff beats (rulings R7 + the K3 kickoff), each in the
   room's own voice — quiet paper chips, the locked family colours (kun
   indigo #3D5A80 / on terracotta #9E5E43), amber only for sound. */

/* 卒 CRUTCH FALLS — the reading crutch lifts away, once ever: the woken
   ruby on a marked head, or the whole kana line on a placard / readctx
   reveal. The line and the held identity rise in the ink voice (the
   approved mock's own stage directions: lift 0.9s, line at 0.75s). */
.kw-crutch-lifting rt,
.kw-plq-furi.kw-crutch-lifting,
.kw-cx-kana.kw-crutch-lifting { animation: kwCrutchLift 0.9s var(--ease-brush) both; }
@keyframes kwCrutchLift {
    from { opacity: 1; transform: none; filter: none; }
    to { opacity: 0; transform: translateY(-9px); filter: blur(1.5px); }
}
.kw-crutch { text-align: center; }
.kw-crutch-line {
    margin-top: clamp(12px, 1.1vw, 18px);
    font: 400 clamp(13.5px, 1vw, 16px) var(--font-ui);
    color: var(--color-ink);
    animation: kwInkRise 0.5s var(--ease-brush) 0.75s both;
}
.kw-crutch-line .jp { font-family: var(--font-jp); font-weight: 600; margin-right: 7px; }
.kw-crutch-line i { font-style: italic; color: var(--color-amber-deep); }
.kw-crutch-held {
    margin-top: clamp(5px, 0.5vw, 9px);
    font: italic 400 clamp(12px, 0.9vw, 14px) var(--font-ui);
    color: var(--color-amber-deep);
    animation: kwInkRise 0.5s var(--ease-brush) 0.9s both;
}
.kw-crutch-held .en { font-style: normal; color: var(--color-stone); }
.kw-crutch-held .kw-form-audio { vertical-align: middle; }

/* 開 S3.5 K5a — THE UNLOCK ECHO: the words a graduation just opened
   ("you can now read 電車 densha · train"). Bare ink: the moss lives in
   the cap and the words, not a box or a rule; the crossed character leads
   (S3.5-C — the learner finally sees WHO did the unlocking) and the named
   words ink in one by one. Riding a crutch ceremony it draws close and
   joins on air alone: one moment. */
.kw-unlock {
    width: 100%; max-width: clamp(340px, 27vw, 470px);
    margin: clamp(16px, 1.5vw, 24px) auto 0;
    padding: 2px;
    display: flex; gap: 12px; align-items: flex-start;
    text-align: left;
    animation: kwInkRise 0.5s var(--ease-brush) both;
}
.kw-unlock-g {
    appearance: none; cursor: pointer; background: transparent; border: none;
    padding: 2px 6px; margin: -2px -4px; flex: none; border-radius: 8px;
    font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(28px, 2.2vw, 36px); line-height: 1; color: var(--color-ink);
    transition: background 0.18s;
}
.kw-unlock-g:hover, .kw-unlock-g:focus-visible { background: rgba(67, 50, 30, 0.045); outline: none; }
.kw-unlock-body { min-width: 0; flex: 1; }
.kw-unlock-cap {
    display: block; margin-bottom: 6px;
    font: 600 10px var(--font-ui); letter-spacing: var(--track-eyebrow);
    text-transform: uppercase; color: var(--moss-aa, #5E7050);
}
.kw-unlock-words {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
}
.kw-unlock-w { white-space: nowrap; opacity: 0; animation: kwUnlockInk 0.45s ease-out both; }
.kw-unlock-w:nth-child(1) { animation-delay: 0.25s; }
.kw-unlock-w:nth-child(3) { animation-delay: 0.4s; }
.kw-unlock-w:nth-child(5) { animation-delay: 0.55s; }
@keyframes kwUnlockInk { from { opacity: 0; filter: blur(1px); } to { opacity: 1; filter: none; } }
.kw-unlock-w .jp {
    font-family: var(--font-jp); font-weight: 600;
    font-size: clamp(17px, 1.3vw, 21px); color: var(--color-jp-text, #523E1E);
}
/* italic carries ONLY the romaji (the inline color law); the gloss rides
   beside it in its own plain span (owner 2026-07-16, kanji-inside decouple) */
.kw-unlock-w i {
    font: italic clamp(11px, 0.8vw, 13px) var(--font-ui);
    color: var(--color-faint-warm); margin-left: 5px;
}
.kw-unlock-en {
    font: 400 clamp(11px, 0.8vw, 13px) var(--font-ui);
    color: var(--color-faint-warm); margin-left: 5px;
}
/* S2+A — the close-tease: the echo's quiet promise that the words wait as
   asks at tonight's close (renders only when the bank truly holds them) */
.kw-unlock-later {
    display: block; width: 100%;
    font: italic 400 clamp(10px, 0.75vw, 12px) var(--font-ui);
    color: var(--color-amber-deep);
    margin-top: 5px;
}
.kw-unlock-dot { color: var(--color-faint); font-size: 13px; }
/* joined ceremony: the crutch leads, the doors follow close — one breath */
.kw-crutch + .kw-unlock {
    justify-content: center;
    padding: 8px 0 0; margin-top: 8px;
    text-align: center;
}
.kw-crutch + .kw-unlock .kw-unlock-body { flex: 0 1 auto; }
.kw-crutch + .kw-unlock .kw-unlock-words { justify-content: center; }

/* 文 THE SCHOLAR LETTER — the 由来 note delivered once, on the second
   meeting. Sumi and stone ONLY (no red — #645 stands; no gold — kintsugi
   stays earned; no amber — that voice is sound's): the letter's weight is
   its rarity, not a colour. A quiet centered line in the crutch's seat,
   dressed in the fold-cue grammar (jp glyph · romaji · plain words ·
   chevron) because it IS a door — to the sheet's 由来 fold. Buttons in
   this room REST: no paper chip, no lift. */
.kw-letter {
    appearance: none; cursor: pointer;
    background: transparent; border: none; border-radius: 0;
    box-shadow: none; transform: none;
    display: block; margin: clamp(12px, 1.1vw, 18px) auto 0;
    padding: 2px 0;
    font: 400 clamp(13.5px, 1vw, 16px) var(--font-ui);
    color: var(--color-ink); text-align: center;
    transition: color 0.18s;
    animation: kwInkRise 0.5s var(--ease-brush) 0.25s both;
}
.kw-letter .jp {
    font-family: var(--font-jp); font-weight: 600;
    margin-right: 7px; color: var(--color-stone);
}
.kw-letter i { font-style: italic; color: var(--color-faint-warm); margin-right: 7px; }
.kw-letter .txt b { font-family: var(--font-jp); font-weight: 600; }
.kw-letter .chev {
    display: inline-block; margin-left: 6px; font-size: 12px;
    color: var(--color-faint-warm);
    transition: transform 0.25s var(--ease-brush);
}
.kw-letter:hover { color: var(--color-accent); }
.kw-letter:hover .chev { transform: translateX(2px); }
/* 文 §12-C — Sensei's READING letter offers itself at the close wearing the
   very same line (one 文 idiom, two letters); only the breathing room
   differs, because here it stands between the doors and the way out. */
.kw-close .kw-fumi { margin: clamp(22px, 2vw, 34px) auto clamp(2px, 0.4vw, 6px); }

/* ── the letter SHEET, where the letter now lives: at the session's own
   edges (the start it greets, the close that earned it). The 文箱's dress
   verbatim — serif hand, ◎ in the teacher's red, the kept block's indigo
   rule — because there is one letter idiom in this app, not two.
   ⛔ And on 2026-07-29 that stopped being true of intent only. The 文箱 was
   re-set (S12 dress, owner picks B and C) and this copy had drifted a dozen
   half-pixels away from it — a 15px signature against 16, a 12px P.S. label
   against 13, a body at 14.5 against 14.5 but a shadow still in the (44,42,40)
   sumi the portal had already corrected. Every value the block declares now
   mirrors its original, and its Japanese joins the same serif. What stays
   local is what the SEAT owns: the clamped padding this letter needs standing
   between the doors and the way out, and its own --fumi-hand/--fumi-shu. */
.kw-fumi-th {
    /* The CJK tail is load-bearing: this letter's Japanese rides INSIDE the
       hand's paragraphs (kw-jp runs with no face of their own), so the stack
       itself must land it on the picked serif — Latin resolves earlier and
       never reaches it. Without the tail, kana fell through to the system's
       generic CJK serif, one face short of the portal's letter. */
    --fumi-hand: 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Noto Serif JP', 'Hiragino Mincho ProN', serif;
    --fumi-shu: #A8402C;                /* the red ink — ◎, at most once */
    width: min(680px, 94vw); margin: auto; text-align: center;
}
.kw-fumi-mark {
    font-family: var(--font-jp); font-size: clamp(40px, 3vw, 58px);
    color: var(--color-ink); line-height: 1.15;
}
.kw-fumi-mark .ro {
    display: block;
    font: 400 clamp(11px, 0.8vw, 13px) var(--font-ui);
    letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--color-faint-warm); margin-top: 9px;
}
.kw-fumi-sheet {
    text-align: left; margin: clamp(20px, 2vw, 30px) auto 0; max-width: 620px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 130px),
        var(--color-card-bright);
    border: 1px solid rgba(44, 44, 44, 0.07); border-radius: 3px;
    box-shadow: 0 1px 2px rgba(44, 44, 44, 0.04), 0 14px 40px -28px rgba(44, 44, 44, 0.18);
    padding: clamp(28px, 3vw, 44px) clamp(24px, 3.4vw, 52px) clamp(26px, 2.6vw, 38px);
}
.kw-fumi-dateline {
    display: flex; justify-content: space-between; align-items: baseline;
    font: 400 12px var(--font-ui); color: var(--color-stone); margin-bottom: 26px;
}
.kw-fumi-tag { font-family: var(--fumi-hand); font-style: italic; font-size: 12px; }
.kw-fumi-body p {
    font-family: var(--fumi-hand); font-size: 15.5px; line-height: 1.85;
    color: var(--color-ink); opacity: 0.92; margin: 0 0 15px; max-width: 58ch;
}
.kw-fumi-kept {
    display: flex; gap: 10px; margin: 4px 0 18px 26px; padding-left: 16px;
    border-left: 2px solid rgba(61, 90, 128, 0.26);
}
.kw-fumi-maru { color: var(--fumi-shu); font-size: 15.5px; padding-top: 4px; opacity: 0.9; }
.kw-fumi-kept-jp {
    font-family: 'Noto Serif JP', 'Hiragino Mincho ProN', serif;
    font-size: 20px; line-height: 1.7; color: var(--color-jp-text);
}
.kw-fumi-kept-sub {
    font-family: var(--fumi-hand); font-style: italic; font-size: 13px;
    color: var(--color-stone); margin-top: 4px;
}
.kw-fumi-sig {
    font-family: var(--fumi-hand); font-size: 15.5px; color: var(--color-ink);
    text-align: right; margin-top: 22px;
}
.kw-fumi-sig .jp {
    font-family: 'Noto Serif JP', 'Hiragino Mincho ProN', serif;
    font-size: 12px; color: var(--color-stone); margin-left: 6px;
}
/* the raw hairline is --vp-line's value; that token is the portal's own scope */
.kw-fumi-ps { margin-top: 26px; padding-top: 18px; border-top: 1px solid rgba(44, 44, 44, 0.07); }
.kw-fumi-ps-lbl {
    font-family: var(--fumi-hand); font-style: italic; font-size: 13px;
    color: var(--color-stone); margin-bottom: 6px;
}
.kw-fumi-ps p {
    font-family: var(--fumi-hand); font-size: 15.5px; line-height: 1.85;
    color: var(--color-ink); opacity: 0.88; margin: 0; max-width: 58ch;
}
.kw-fumi-th .kw-begin { margin-top: clamp(20px, 2vw, 30px); }

/* 似 THE LOOKALIKE DUEL (§4.7) — two near-twins side by side, six rapid
   rounds. The word gives itself away (reading + meaning shown); the two
   glyphs are the only answers, and the curated tell does the teaching
   after every pick. Verdict tints stay the walk's own: moss = the true
   glyph, amber = the reached-for twin — never a red X. */
.kw-duel .kw-face-ask { padding: clamp(18px, 2vw, 30px) clamp(14px, 2vw, 28px); }
.kw-duel-head {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui);
    letter-spacing: 0.08em; color: var(--color-stone);
}
.kw-duel-head .ink {
    font-family: var(--font-jp); font-size: clamp(17px, 1.3vw, 21px);
    color: var(--color-faint-warm);
}
.kw-duel-dots {
    display: flex; justify-content: center; gap: 7px;
    margin: clamp(10px, 1vw, 16px) 0 clamp(4px, 0.5vw, 8px);
}
.kw-duel-dots .dd {
    width: 6px; height: 6px; border-radius: 50%;
    background: rgba(44, 44, 44, 0.14);
    transition: background 0.25s;
}
.kw-duel-dots .dd.on { background: var(--color-accent); }
.kw-duel .kw-ask-q {
    text-align: center; margin-top: clamp(8px, 0.9vw, 14px);
    font: 400 clamp(13.5px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
}
.kw-duel-word {
    display: flex; align-items: baseline; justify-content: center; gap: 2px;
    margin-top: clamp(12px, 1.2vw, 20px);
    font-family: var(--font-jp);
    font-size: clamp(40px, 3.4vw, 58px); line-height: 1.2; color: var(--color-ink);
}
.kw-duel-hole {
    display: inline-block; width: 1.06em; height: 1.06em;
    align-self: center; border-radius: 6px;
    border: 2px dashed rgba(44, 44, 44, 0.22);
    transition: border-color 0.25s;
}
.kw-duel-hole.kw-dl-filled {
    border-color: transparent;
    width: auto; height: auto; align-self: baseline;
    animation: kwInkRise 0.4s var(--ease-brush) both;
}
.kw-duel-sub {
    display: flex; align-items: baseline; justify-content: center; gap: 12px;
    margin-top: clamp(8px, 0.8vw, 13px);
    font: 400 clamp(13px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
}
.kw-duel-sub .jp { font-family: var(--font-jp); color: var(--color-jp-text); }
.kw-duel-sub i { font-style: italic; color: var(--color-faint-warm); }
.kw-duel-picks {
    display: flex; justify-content: center; gap: clamp(14px, 1.6vw, 26px);
    margin-top: clamp(16px, 1.6vw, 26px);
}
.kw-duel-pick {
    appearance: none; cursor: pointer;
    width: clamp(86px, 7vw, 118px); height: clamp(86px, 7vw, 118px);
    display: grid; place-items: center;
    background: var(--color-card); border: 1px solid rgba(44, 44, 44, 0.1);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(44, 44, 40, 0.05);
    font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(46px, 3.8vw, 64px); line-height: 1; color: var(--color-ink);
    transition: transform 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.kw-duel-pick:hover:not(:disabled) {
    transform: translateY(-1px); border-color: rgba(44, 44, 44, 0.2);
}
.kw-duel-pick:disabled { cursor: default; }
.kw-duel-pick.kw-dl-ans { border-color: var(--moss-aa); box-shadow: 0 0 0 2px var(--moss-aa) inset; }
.kw-duel-pick.kw-dl-pick { border-color: var(--amber-aa); box-shadow: 0 0 0 2px var(--amber-aa) inset; opacity: 0.85; }
.kw-duel-verdict { margin-top: clamp(12px, 1.2vw, 18px); }
.kw-duel-verdict .kw-pair-tell { margin-left: auto; margin-right: auto; max-width: clamp(360px, 30vw, 520px); }
.kw-duel-on {
    appearance: none; cursor: pointer; display: block;
    margin: clamp(12px, 1.1vw, 18px) auto 0;
    background: transparent; border: none; padding: 4px 10px;
    font: 400 clamp(13px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
    transition: color 0.18s;
}
.kw-duel-on:hover { color: var(--color-accent); }
.kw-duel-on .jp { font-family: var(--font-jp); margin-left: 7px; color: var(--color-faint-warm); }
.kw-duel-done { text-align: center; margin-top: clamp(14px, 1.4vw, 24px); }
.kw-duel-pair {
    font-family: var(--font-jp); font-size: clamp(34px, 2.6vw, 46px);
    color: var(--color-ink);
}
.kw-duel-pair .vs { margin: 0 10px; color: var(--color-faint-warm); }
.kw-ink--duel { flex-wrap: wrap; }
.kw-duel-score { font-weight: 600; }
.kw-duel-when { color: var(--color-stone); margin-left: 10px; }

/* 鍛 THE FORGE — two mastered glyphs write a word never studied; the
   meaning is guessed for nothing, the reveal pays the composition.
   Verdict tints stay the walk's own: moss = the true meaning, amber =
   the reached-for foil — never a red X. */
.kw-forge .kw-face-ask { padding: clamp(18px, 2vw, 30px) clamp(14px, 2vw, 28px); }
.kw-forge-head {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui);
    letter-spacing: 0.08em; color: var(--color-stone);
}
.kw-forge-head .ink {
    font-family: var(--font-jp); font-size: clamp(17px, 1.3vw, 21px);
    color: var(--color-faint-warm);
}
.kw-forge-glyphs {
    display: flex; align-items: center; justify-content: center;
    gap: clamp(14px, 1.5vw, 24px);
    margin-top: clamp(14px, 1.4vw, 24px);
    font-family: var(--font-jp);
    font-size: clamp(46px, 3.8vw, 66px); line-height: 1.15; color: var(--color-ink);
}
.kw-forge-glyphs .plus {
    font-family: var(--font-ui);
    font-size: 0.42em; color: var(--color-faint-warm);
}
.kw-forge .kw-ask-q {
    text-align: center; margin-top: clamp(10px, 1vw, 16px);
    font: 400 clamp(13.5px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
}
.kw-forge-picks {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(10px, 1vw, 16px);
    margin: clamp(16px, 1.6vw, 26px) auto 0;
    max-width: clamp(360px, 32vw, 560px);
}
.kw-forge-pick {
    appearance: none; cursor: pointer;
    min-height: 52px; padding: 12px 14px;
    background: var(--color-card); border: 1px solid rgba(44, 44, 44, 0.1);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(44, 44, 40, 0.05);
    font: 400 clamp(14px, 1.05vw, 16.5px) var(--font-ui);
    line-height: 1.35; color: var(--color-ink); text-align: center;
    transition: transform 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.kw-forge-pick:hover:not(:disabled) {
    transform: translateY(-1px); border-color: rgba(44, 44, 44, 0.2);
}
.kw-forge-pick:disabled { cursor: default; }
.kw-forge-pick.kw-fg-ans { border-color: var(--moss-aa); box-shadow: 0 0 0 2px var(--moss-aa) inset; }
.kw-forge-pick.kw-fg-pick { border-color: var(--amber-aa); box-shadow: 0 0 0 2px var(--amber-aa) inset; opacity: 0.85; }
.kw-forge-verdict { margin-top: clamp(12px, 1.2vw, 18px); }
.kw-forge-word {
    text-align: center; margin-top: clamp(10px, 1vw, 16px);
    animation: kwInkRise 0.4s var(--ease-brush) both;
}
.kw-forge-word ruby {
    font-family: var(--font-jp);
    font-size: clamp(34px, 2.8vw, 48px); line-height: 1.4; color: var(--color-ink);
}
.kw-forge-word rt {
    font-size: 0.32em; color: var(--color-stone); letter-spacing: 0.12em;
}
.kw-forge-sub {
    display: flex; align-items: baseline; justify-content: center; gap: 12px;
    margin-top: clamp(4px, 0.5vw, 8px);
    font: 400 clamp(13px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
}
.kw-forge-sub i { font-style: italic; color: var(--color-faint-warm); }
.kw-forge-eq {
    display: flex; align-items: baseline; justify-content: center;
    gap: clamp(12px, 1.2vw, 20px);
    margin-top: clamp(10px, 1vw, 16px);
    font: 400 clamp(13px, 1vw, 16px) var(--font-ui); color: var(--color-stone);
}
.kw-forge-eq .p b {
    font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(19px, 1.5vw, 25px); color: var(--color-ink);
    margin-right: 7px;
}
.kw-forge-eq .p i { font-style: italic; }
.kw-forge-eq .plus { color: var(--color-faint-warm); }
.kw-ink--forge { flex-wrap: wrap; justify-content: center; }
.kw-forge-line { text-align: center; }

/* 二役 TWO HATS — the known kanji arrives wearing a new sound; rides the
   discovery in the plant's own seat (R7: two-hats wins the collision).
   Bare ink like its sibling — the lesson is the line, not a box. */
.kw-hats {
    display: flex; align-items: center; gap: 12px;
    margin: clamp(18px, 1.7vw, 28px) auto 0;
    padding: 2px; max-width: clamp(340px, 27vw, 470px);
    text-align: left;
}
.kw-hats-glyph {
    appearance: none; cursor: pointer; background: transparent; border: none;
    padding: 2px 6px; margin: -2px -4px; flex: none; border-radius: 8px;
    font-family: var(--font-jp); font-weight: 400;
    font-size: clamp(32px, 2.5vw, 42px); line-height: 1; color: var(--color-ink);
    transition: background 0.18s;
}
.kw-hats-glyph:hover, .kw-hats-glyph:focus-visible { background: rgba(67, 50, 30, 0.045); outline: none; }
.kw-hats-t {
    min-width: 0;
    font: 400 clamp(12.5px, 0.94vw, 15px) var(--font-ui);
    color: var(--color-stone); line-height: 1.6;
}
.kw-hats-t .jp { font-family: var(--font-jp); }
.kw-hats-t i { font-style: italic; color: var(--color-amber-deep); }
.kw-hats-r--kun { color: var(--kw-kun); font-weight: 600; }
.kw-hats-r--on { color: var(--kw-on); font-weight: 600; }

/* 似 THE TELL DOOR — a quiet look-alike door on the reveal (the reveal-door
   chip voice); open = the curated per-side tells, each glyph a kanji-sheet
   door. The same block dresses the family comparison's 似 line. */
.kw-tell { margin-top: clamp(10px, 0.9vw, 14px); text-align: center; }
.kw-tell-door {
    appearance: none; cursor: pointer;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 4px 14px;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    letter-spacing: 0.04em; color: var(--color-stone);
    background: transparent; border: 1px solid var(--color-divider);
    border-radius: var(--radius-full);
    transition: color 0.18s, border-color 0.18s;
}
.kw-tell-door:hover { color: var(--color-ink); border-color: var(--color-faint); }
.kw-tell-door .ink { font-family: var(--font-jp); color: var(--kw-clay); }
.kw-tell-door .jp { font-family: var(--font-jp); font-weight: 600; font-size: 1.15em; color: var(--color-ink); }
.kw-pair-tell {
    display: flex; gap: 10px; align-items: flex-start; text-align: left;
    margin: clamp(10px, 0.9vw, 14px) auto 0; max-width: clamp(340px, 30vw, 540px);
    animation: kwInkRise 0.4s var(--ease-brush) both;
}
.kw-pair-tell > .ink {
    flex: none; font-family: var(--font-jp);
    font-size: clamp(12px, 0.9vw, 14px); color: var(--kw-clay); padding-top: 2px;
}
.kw-tell-sides { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.kw-tell-side { display: flex; gap: 9px; align-items: baseline; }
.kw-tell-side .g {
    flex: none; font-family: var(--font-jp); font-weight: 600;
    font-size: clamp(17px, 1.3vw, 22px); line-height: 1.2; color: var(--color-ink);
}
.kw-tell-side .txt {
    min-width: 0; font: 400 clamp(12px, 0.9vw, 14px) var(--font-ui);
    color: var(--color-stone); line-height: 1.55;
}
.kw-tell-side .txt i { font-style: italic; }
.kw-tell-side .txt b { font-family: var(--font-jp); font-weight: 600; color: var(--color-ink); }

@media (prefers-reduced-motion: reduce) {
    /* the lift resolves at once — the crutch's disappearance must never
       depend on an animation reaching opacity 0 (the room's RM law) */
    .kw-crutch-lifting rt,
    .kw-plq-furi.kw-crutch-lifting,
    .kw-cx-kana.kw-crutch-lifting { animation: none; opacity: 0; }
    .kw-crutch-line, .kw-crutch-held, .kw-pair-tell,
    .kw-unlock, .kw-unlock-w {
        animation-duration: 0.01s; animation-delay: 0s;
    }
    .kw-hats-glyph, .kw-plant-glyph, .kw-tell-door,
    .kw-kride-ask, .kw-kride-open .g, .kw-kride-done .g,
    .kw-unlock-g { transition: none; }
}

/* ══ DESIGN WALK RULINGS 2026-07-14 — the winners, hardened ═══════════════
   auto-bloom (JS-only), the 砂利 pebble trail at scale, the merged 族
   panel. The losing forms (線 line / 帯 band / the fold-kill) and the
   preview switcher were removed with the rulings. ─────────────────────────── */

/* ── the trail AT SCALE — the stones survive as a strip of pebbles ───────
   One quiet line past ~30 stones; the word rides a hover tip, never a
   stamped wall. The trail's seat and click-to-begin contracts hold. */
.kw-trail.kw-scale {
    position: relative;
    flex-wrap: nowrap;
    width: min(94vw, 1240px);
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 8px 6px 18px;
}
/* the hover label — one floating word.
   ⚠️ display:flex here beats the UA [hidden] rule — the reset must claim
   the hidden state or the tip never leaves (the footcue trap) */
.kw-scaletip[hidden] { display: none; }
.kw-scaletip {
    position: absolute;
    bottom: calc(100% - 6px);
    transform: translateX(-50%);
    background: var(--color-card);
    border: 1px solid rgba(120, 112, 96, 0.28);
    border-radius: 7px;
    box-shadow: 0 2px 9px rgba(var(--sh), 0.14);
    padding: 4px 10px;
    display: flex;
    align-items: baseline;
    gap: 7px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 3;
}
.kw-scaletip .jp { font-family: var(--font-jp); font-size: 14px; color: var(--color-ink); }
.kw-scaletip i { font: italic 11px var(--font-ui); color: var(--color-amber-deep); }
.kw-peb {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 48% 52% 50% 50% / 52% 48% 52% 48%;
    border: 1px solid rgba(120, 112, 96, 0.26);
    background: linear-gradient(168deg, #efece5, #e6e2d8 70%);
    transition: all 0.45s var(--ease-brush);
}
.kw-peb.done { background: linear-gradient(168deg, #d9d3c6, #cfc8b8 70%);
    border-color: rgba(110, 100, 82, 0.4); }
.kw-peb.ahead { opacity: 0.55; }
.kw-peb.now {
    width: 15px;
    height: 15px;
    border-color: var(--color-stone);
    box-shadow: 0 0 0 3px rgba(87, 83, 78, 0.10);
}
/* every 10th pebble sits a touch deeper — the milestone */
.kw-peb.kw-mile { box-shadow: 0 3px 0 -1px rgba(120, 112, 96, 0.5); }
.kw-peb.now.kw-mile { box-shadow: 0 0 0 3px rgba(87, 83, 78, 0.10), 0 4px 0 -1px rgba(120, 112, 96, 0.5); }
.kw-peb.kw-lantern { background: #e9dfc8; border-color: rgba(160, 140, 96, 0.55); }
.kw-peb.kw-lantern.kw-lit { background: #f5ead0; box-shadow: 0 0 5px rgba(212, 184, 124, 0.55); }
/* the mended pebble — the comeback's gold, scarce by law */
.kw-peb.kw-mended {
    background: linear-gradient(168deg, #e8d9ae, var(--color-gold) 78%);
    box-shadow: 0 0 4px rgba(212, 184, 124, 0.55);
}
.kw-peb.kw-cracked { background: linear-gradient(168deg, #e3cfa8, #d9c294 70%);
    border-color: rgba(176, 129, 47, 0.55); }
/* the threshold preview — the strip lies evenly present, step-on begins */
.kw-trail.kw-preview .kw-peb { opacity: 0.85; }

/* (the merged 族 panel CSS retired with famYomiHTML — S3.5-KR1) */

@media (prefers-reduced-motion: reduce) {
    .kw-peb { transition: none; }
}

/* ═══ S3.5-KR — THE KANJI ROOM: the study sheet as a tutor's desk ═════════
   (owner-ruled off design-mockups/kanji-room, 2026-07-14/15). Whisper law:
   lessons rest on hover; the record is one wordless moss dot; frequency
   speaks the grid's band words; no counts, no empty frames, no school-facts.
   All reference — nothing here writes. ═══════════════════════════════════ */

/* the hover whisper — a lesson resting behind its element; paper card on
   hover/focus, never inline chrome */
.kw-tip {
    position: absolute; left: -4px; top: calc(100% + 8px); z-index: 40;
    width: 232px;
    background: var(--color-card-bright); border: 1px solid var(--color-divider);
    border-radius: 9px; box-shadow: 0 10px 26px -12px rgba(67, 50, 30, 0.35);
    padding: 9px 12px;
    font: italic 400 11.5px/1.55 var(--font-ui); color: var(--color-stone);
    text-align: left; text-transform: none; letter-spacing: 0.01em;
    white-space: normal; opacity: 0; visibility: hidden;
    transition: opacity 0.18s; pointer-events: none;
}
.kw-tip b { font-style: normal; font-weight: 600; color: var(--color-ink); }
.kw-tip .jp, .kw-tip [lang="ja"] { font-family: var(--font-jp); font-style: normal; color: var(--color-jp-text); }
.kw-kfam-h .ktag { position: relative; }
.kw-tiphost { position: relative; }
.kw-readmark { position: relative; }
/* hover only where hover is REAL — on touch, iOS sticky-hover would show
   the tip via :hover on the first tap and desync the tap toggle's class
   state; touch relies solely on .kw-tip-on below */
@media (hover: hover) and (pointer: fine) {
    .kw-kfam-h .ktag:hover > .kw-tip,
    .kw-tiphost:hover > .kw-tip,
    .kw-readmark:hover > .kw-tip {
        opacity: 1; visibility: visible;
    }
}
.kw-kfam-h .ktag:focus-visible > .kw-tip,
.kw-tiphost:focus-visible > .kw-tip,
.kw-readmark:focus-visible > .kw-tip {
    opacity: 1; visibility: visible;
}
/* touch (iPad): the same whispers open on TAP — .kw-tip-on is set only by
   the walk's touch tap handler, so mouse keeps pure hover */
.kw-kfam-h .ktag.kw-tip-on > .kw-tip,
.kw-tiphost.kw-tip-on > .kw-tip,
.kw-readmark.kw-tip-on > .kw-tip {
    opacity: 1; visibility: visible;
}
/* the record dot's whisper hangs from the RIGHT edge (it sits at row end) */
.kw-readmark > .kw-tip { left: auto; right: -4px; width: 196px; }

/* the record — ONE wordless moss dot: this reading is yours (one voice with
   the status dots); absence says not-yet */
.kw-readmark { margin-left: auto; flex: none; display: inline-flex; align-items: center; }
.kw-readmark::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--color-moss); }
.kw-readmark::after { content: ""; position: absolute; inset: -10px; }

/* frequency speaks the grid's own band words — quiet, lowercase, no badge */
.kw-band { flex: none; margin-left: auto; font: italic 500 10px var(--font-ui); letter-spacing: 0.06em; color: var(--color-faint); }

/* ledger rows: a studied word leads with its painting; meet-later rows are
   text alone (no empty frame) */
.kw-yomi-row { align-items: center; }
.kw-yomi-thumb { flex: none; width: 44px; height: 32px; border-radius: 5px; overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(67, 50, 30, 0.1); }
.kw-yomi-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kw-yomi-tx { display: flex; align-items: baseline; gap: 8px; flex: 1 1 auto; min-width: 0; flex-wrap: wrap; }
.kw-yomi-tx .en { flex: 0 1 auto; }

/* "… and N more" — a quiet tap; the rows ink in place, the line retires */
button.kw-yomi-morebtn {
    appearance: none; cursor: pointer; background: none; border: none;
    display: block; padding: 2px 0 2px 10px; margin-top: 2px; text-align: left;
    font: italic clamp(11px, 0.85vw, 13px) var(--font-ui); color: var(--color-faint-warm);
    transition: color 0.15s;
}
button.kw-yomi-morebtn:hover { color: var(--color-accent); }

/* the shape, honestly built — part chips + type caption (KR1) */
.kw-kparts { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.kw-kpart { display: inline-flex; align-items: baseline; gap: 7px;
    border: 1px solid rgba(67, 50, 30, 0.14); border-radius: 9px; padding: 4px 10px;
    background: var(--color-card); }
.kw-kpart .g { font-family: var(--font-jp); font-weight: 600; font-size: clamp(15px, 1.15vw, 19px);
    line-height: 1; color: var(--color-ink); }
.kw-kpart .n { font: 400 clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-stone); }
.kw-kpart--sound { border-color: rgba(158, 94, 67, 0.38); }
.kw-kpart--sound .says { font: italic 400 clamp(10px, 0.76vw, 12px) var(--font-ui); color: var(--kw-on); }
.kw-kpart.kw-kanji-door { cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s; }
.kw-kpart.kw-kanji-door:hover { border-color: var(--color-accent); box-shadow: 0 1px 4px rgba(61, 90, 128, 0.14); }
.kw-kplus { font: 400 13px var(--font-ui); color: var(--color-faint); }
.kw-ksum { font-family: var(--font-jp); font-weight: 600; font-size: clamp(19px, 1.5vw, 25px);
    line-height: 1; color: var(--color-ink); }
.kw-ktypecap { margin-top: 7px; font: 400 clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-faint-warm); }
.kw-ktypecap .jp { font-family: var(--font-jp); color: var(--color-stone); }

/* the dressed 由来 — the older-form impression + the 説 honesty mark (KR3) */
.kw-kimpress { display: flex; align-items: center; gap: 14px; margin: 8px 0 4px;
    padding: 9px 13px; border: 1px solid rgba(67, 50, 30, 0.09); border-radius: 10px;
    background: var(--color-card); }
.kw-kimpress .g { font-family: var(--font-jp); font-size: clamp(34px, 2.6vw, 44px); line-height: 1;
    color: rgba(44, 44, 44, 0.5); }
.kw-kimpress .cap { font: italic 400 clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-faint-warm); }
.kw-kimpress .cap [lang="ja"] { font-family: var(--font-jp); font-style: normal; color: var(--color-stone); }
.kw-kcert { display: flex; align-items: baseline; gap: 8px; margin-top: 8px;
    font: italic 400 clamp(10.5px, 0.8vw, 12.5px) var(--font-ui); color: var(--color-faint); }
.kw-kcert .g { font-family: var(--font-jp); font-style: normal; font-size: 13.5px; color: rgba(44, 44, 44, 0.35); }

/* the 字 panel's tab dots — the kanji's own state at a glance (KR4) */
.kw-ktab .kw-kdot { display: inline-block; width: 6px; height: 6px; border-radius: 50%;
    margin-right: 5px; vertical-align: 2px; }
.kw-kdot--known { background: var(--color-moss); }
.kw-kdot--comeback { background: var(--color-moss-bright); }
.kw-kdot--saved { background: var(--color-amber); }
.kw-kdot--new { background: transparent; border: 1.2px solid var(--color-faint); box-sizing: border-box; }

/* the borrowed writing block (KR2) — the kanji page's own player, walk-sized.
   The page's .hint dress is #kanjiPage-scoped, so the host dresses its own. */
.kw-brush-host { position: relative; display: inline-flex; flex-direction: column;
    align-items: center; gap: 1px; }
.kw-brush-host .glyph-stage { width: clamp(96px, 7.6vw, 132px); height: clamp(96px, 7.6vw, 132px);
    border-radius: 10px; }
.kw-brush-host .glyph-rest { font-size: clamp(74px, 5.9vw, 102px); }
.kw-brush-host .hint { display: flex; align-items: baseline; justify-content: center;
    gap: 8px; min-height: 17px;
    font: 400 clamp(10px, 0.78vw, 12px) var(--font-ui); color: var(--color-faint-warm); }
.kw-brush-host .hint .rest { display: inline-flex; align-items: baseline; gap: 5px;
    opacity: 0.55; transition: opacity 0.2s; }
.kw-brush-host:hover .hint .rest { opacity: 1; }
.kw-brush-host .hint .rest .brush { display: none; }
.kw-brush-host .hint .rest [lang="ja"] { font-family: var(--font-jp); color: var(--color-stone); }
/* In the walk the glyph IS the whole control — tap: watch it written ·
   tap: rest · tap: write again. The page's after-bench (write again /
   stroke by stroke / the stroke counter) is a kanji-page tool; the page's
   unscoped is-writing rules would force it on here, so the host suppresses
   it outright (the elements stay in the DOM — the player derefs them). */
.kw-brush-host .hint .after,
.kw-brush-host .glyph-stage.is-writing ~ .hint .after { display: none; }
/* panel scale — the 字 panel's glance glyph, compact */
.kw-brush-host--panel .glyph-stage { width: 74px; height: 74px; border-radius: 8px; }
.kw-brush-host--panel .glyph-rest { font-size: 56px; }
.kw-brush-host--panel .hint { min-height: 15px; font-size: 9.5px; }
/* the sheet hero centers its brush inside the big-glyph seat */
.kw-fam-glyphbig .kw-brush-host { vertical-align: top; }

/* the first-meeting dress (KR1) — the painting leads, the line whispers */
.kw-meet-art { margin-bottom: clamp(10px, 0.9vw, 14px); }
.kw-meet-line { font: italic 400 clamp(12px, 0.92vw, 14.5px) var(--font-ui);
    color: var(--color-faint-warm); text-align: center; margin-bottom: clamp(6px, 0.5vw, 9px); }
.kw-plq--meet { align-items: center; text-align: center; }
.kw-plq--meet .kw-plq-row { justify-content: center; }
.kw-plq--meet .kw-plq-en { flex: none; }

/* a tell wrapped in its refsec slip keeps ONE 似 — the header's */
.kw-refsec .kw-pair-tell > .ink { display: none; }
.kw-refsec .kw-pair-tell { margin-top: 2px; }

/* a fold standing alone as a slip's whole content needs no rule above it */
.kw-slip > .kw-slip-fold:first-child { margin-top: 0; border-top: none; padding-top: 0; }

/* a slip whose whisper is up rises above its later siblings — every slip is
   its own stacking context (the washi tilt), so the hovered one takes the
   higher seat and its hanging tip is never occluded (fleet) */
.kw-slip:hover, .kw-slip:focus-within { z-index: 6; }

/* ═══ THE BOOK NIGHT (story spine SS3a) ════════════════════════════════════ */
/* the threshold's recap — the story picks up where it left off: one quiet
   authored line ("Previously: …") above tonight's shape, spoken only on a
   book session with an episode still ahead */
.kw-recap {
    margin: 22px auto 0;
    max-width: 460px;
    font: 400 clamp(13px, 1vw, 16px) var(--font-ui);
    color: var(--color-stone);
    line-height: 1.65;
}
.kw-recap-next {
    display: block;
    margin-top: 6px;
    font-size: clamp(11px, 0.85vw, 13px);
    color: var(--color-faint-warm);
}
/* the walk's closing READ — tonight's episode as the far bank: the same
   resting card the deck close serves, seated on the walk stage */
.kw-read {
    width: min(640px, 94vw);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.kw-read .grid-read-card--walk { width: min(560px, 100%); }
/* the productive summary lands BELOW the answered episode (the R2a-ii law:
   answering lands the close; the read was the payoff) */
.kw-read + .kw-close { margin-top: 30px; }

/* ── S2 — the UNLOCK HARVEST (Builder close): the echo's newly-readable
   words as read-them-now asks. The dress is the readctx card's voice at
   close scale — paper card, the same grade pair, the unlock's moss cap.
   Builder nights only (harvestHTML gates by profile). ───────────────── */
.kw-harvest {
    width: 100%; max-width: clamp(340px, 27vw, 470px);
    margin: clamp(16px, 1.5vw, 24px) auto 0;
    text-align: left;
    animation: kwInkRise 0.5s var(--ease-brush) both;
}
.kw-harvest-cap { display: block; margin-bottom: 10px; }
.kw-harvest-cap .kw-unlock-cap { margin-bottom: 0; display: inline-flex; align-items: baseline; gap: 7px; }
.kw-harvest-cap .jp { font-family: var(--font-jp); font-weight: 400; font-size: 13px; text-transform: none; letter-spacing: 0; }
.kw-harvest-cap i { font: italic 400 10px var(--font-ui); letter-spacing: 0.04em; color: var(--color-faint-warm); text-transform: none; }
.kw-hv-card {
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.12);
    border-radius: 10px;
    padding: clamp(12px, 1vw, 16px);
    margin-bottom: 10px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);
}
.kw-hv-ask {
    appearance: none; cursor: pointer; background: transparent; border: none;
    width: 100%; padding: 2px;
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    text-align: center;
}
/* the turn folds the ask away — display:flex above beats the UA [hidden] rule,
   so the reset must claim it here (same law as .kw-hv-reveal below). Without
   it wireHarvest's ask.setAttribute('hidden') is inert: the question button
   stays painted OVER the answer it just revealed, and stays clickable. */
.kw-hv-ask[hidden] { display: none; }
.kw-hv-jp {
    font-family: var(--font-jp); font-weight: 400; color: var(--color-ink);
    font-size: clamp(24px, 1.9vw, 32px); line-height: 1.4;
    overflow-wrap: anywhere;
}
.kw-hv-jp--ruby rt { font-size: 0.42em; color: var(--color-faint-warm); }
.kw-hv-q {
    font: 600 clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--color-secondary);
}
.kw-hv-ask .kw-ask-hint { margin-top: 2px; }
.kw-hv-reveal { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
.kw-hv-reveal[hidden] { display: none; }
.kw-hv-en { font: 400 clamp(12px, 0.95vw, 14px) var(--font-ui); color: var(--color-secondary); }
.kw-hv-card .kw-grade-pair { margin-top: 10px; width: 100%; }
.kw-hv-verdict {
    margin-top: 10px;
    font: italic 400 clamp(11px, 0.85vw, 13px) var(--font-ui);
    color: var(--color-faint-warm);
    animation: kwInkRise 0.35s var(--ease-brush) both;
}
.kw-harvest--done { text-align: center; }
/* S3b — the COLD READ probe: the harvest card wears the tile mouth. The
   rack reuses the readctx tile classes verbatim; only the housing is
   card-scale. */
.kw-hv-card--tiles { display: flex; flex-direction: column; align-items: center; text-align: center; }
.kw-hv-card--tiles .kw-cx-built { margin: clamp(8px, 0.8vw, 12px) 0 2px; }
.kw-hv-card--tiles .kw-cx-seat {
    min-width: clamp(38px, 3vw, 46px);
    min-height: clamp(42px, 3.2vw, 50px);
    font-size: clamp(18px, 1.5vw, 23px);
}
.kw-hv-card--tiles .kw-choices--cxtiles { margin-top: clamp(10px, 1vw, 14px); }
.kw-hv-card--tiles .kw-cxtile { min-width: clamp(46px, 3.6vw, 54px); min-height: 44px; }
.kw-hv-card--tiles .kw-cx-commitrow { margin-top: clamp(10px, 1vw, 14px); }
.kw-hv-hint { margin-top: 4px; }
.kw-hv-teach {
    margin-top: 8px;
    font: 400 clamp(11.5px, 0.9vw, 13px) var(--font-ui);
    color: var(--color-secondary);
}
.kw-hv-teach b { font-family: var(--font-jp); font-weight: 600; }
.kw-hv-teach i { font-style: italic; color: var(--color-faint-warm); }
.kw-hv-meaning {
    margin-top: clamp(10px, 1vw, 14px);
    display: flex; flex-direction: column; align-items: center; gap: 7px;
    animation: kwInkRise 0.35s var(--ease-brush) both;
}
.kw-hv-mq { font: italic 400 11px var(--font-ui); letter-spacing: 0.04em; color: var(--color-faint-warm); }
.kw-hv-mrow { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.kw-hv-mchoice {
    appearance: none; cursor: pointer;
    background: var(--color-card-bright);
    border: 1px solid rgba(var(--sh), 0.16);
    border-radius: 9px;
    padding: 9px 14px;
    min-height: 44px;
    font: 400 clamp(12px, 0.95vw, 14px) var(--font-ui);
    color: var(--color-ink);
    transition: border-color 0.16s, transform 0.16s var(--ease-settle);
}
.kw-hv-mchoice:hover:not([disabled]) { border-color: rgba(var(--sh), 0.3); transform: translateY(-1px); }
.kw-hv-mchoice[disabled] { cursor: default; }
.kw-hv-mchoice.kw-hv-m--good { border-color: var(--moss-aa); color: var(--moss-aa); }
.kw-hv-mchoice.kw-hv-m--bad {
    border-color: rgba(158, 94, 67, 0.75); color: #9E5E43;
    text-decoration: line-through 1.5px rgba(158, 94, 67, 0.45);
}
.kw-hv-mchoice.kw-hv-m--truth { border-color: var(--moss-aa); color: var(--moss-aa); border-style: dashed; }

/* ── S12-A — the register in its smallest honest form (owner pick, sketch A):
      the crossing's receipt line + the ledger's wild line. Rung 4 joins the
      RECORD as plain text — no new glyph beside the moss dot's idiom; the
      lines exist only when true (absence = not yet). ──────────────────────── */
#keikoWalk .kw-unlock-kept {
    display: block; margin-top: 2px;
    font: 400 clamp(10px, 0.75vw, 11.5px) var(--font-ui);
    color: var(--color-faint-warm);
}
#keikoWalk .kw-yomi-wild {
    margin-top: 13px; padding-top: 11px;
    border-top: 1px dashed var(--color-divider);
    font: italic 400 clamp(11px, 0.85vw, 12.5px) var(--font-ui);
    color: var(--moss-aa); line-height: 1.55;
}
#keikoWalk .kw-yomi-wild .jp {
    font-family: var(--font-jp); font-style: normal;
    font-size: 1.15em; color: var(--color-jp-text);
}
#keikoWalk .kw-yomi-wild i { color: var(--amber-aa); margin-left: 4px; }
#keikoWalk .kw-wild-when { color: var(--color-faint); }
