/* =============================================================================
   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,
/* the journey TITLE WALL (道 board inside .grid-container) is wall chrome —
   during the session the lintel names the journey; its "to see today" number
   speaks the pre-walk queue math, not tonight's dealt deck */
body.keiko-walk-active #journeyTitleWall { display: none !important; }

#keikoWalk {
    /* the room's light + hands */
    --sh: 67, 50, 30;
    --moss-aa: #5E7050;
    --amber-aa: #7A6230;
    --track-eyebrow: 0.12em;
    /* 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 voice: one centered quiet line directly under the
   beam (mirror of .browse-subrow / #referenceBoard — the scope mark leads,
   count cells follow as number + uppercase stamp label, the shared beam
   treatment). It mounts inside #navExpandZone, so it rides the nav. ───────── */
.kw-lintel {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 18px;
    padding: 2px 8px 9px;
}
.kw-lintel-mark { display: inline-flex; align-items: baseline; gap: 6px; }
.kw-lintel-mark .jp { font-family: var(--font-jp); font-size: 13.5px; color: var(--color-ink); }
.kw-lintel-mark i { font: italic 10.5px var(--font-ui); color: var(--color-faint); letter-spacing: 0.02em; }
.kw-lintel-mark .tx { font: 500 12.5px var(--font-ui); color: var(--color-ink); letter-spacing: 0.01em; }
/* a count cell = number + stamp label (the beam's shared treatment:
   dayline-date / deck-label — 10px, 500, .13em caps, tertiary) */
.kw-lintel-cell { display: inline-flex; align-items: center; gap: 5px; }
.kw-lintel-cell .n,
.kw-lintel-pos .n { font: 600 13px var(--font-ui); color: var(--color-ink); font-variant-numeric: tabular-nums; }
.kw-lintel-cell .lbl,
.kw-lintel-pos .lbl {
    font: 500 10px var(--font-ui);
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--color-faint);
}
.kw-lintel-pos { display: inline-flex; align-items: center; gap: 5px; }
.kw-lintel-pos .jp { font-family: var(--font-jp); font-size: 13.5px; color: var(--color-ink); }
.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); }
.kw-lintel-leave .jp { font-family: var(--font-jp); margin-left: 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(20px, 3.5vh, 44px) 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 carries its own ground under the record — hide the stray horizon
   AND the walk trail (hidden, not wiped: its inked stamps survive the way back) */
#keikoWalk.kw-closing .kw-ground { display: none; }
#keikoWalk.kw-closing .kw-trail { display: none; }

/* 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 */
.kw-trail.kw-dense { gap: 8px clamp(10px, 1vw, 18px); }
.kw-trail.kw-dense .kw-tstone { width: clamp(17px, 1.25vw, 24px); height: clamp(17px, 1.25vw, 24px); }
/* 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 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 */
.kw-face-ask {
    background: var(--color-card-bright);
    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 {
    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.026) 0 1px, transparent 1px),
        radial-gradient(circle at 70% 65%, rgba(120, 110, 90, 0.022) 0 1px, transparent 1px);
    background-size: 7px 7px, 11px 11px;
    mix-blend-mode: multiply;
}
.kw-flipcard .kw-face-ask { cursor: pointer; }
.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: 400 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: wrap; justify-content: center; max-width: none; }
.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 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 thumbs sit in ONE row inside the card's inner width; 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 {
    width: clamp(148px, 9.9vw, 198px);
    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; }
/* 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); }
.kw-choice.is-chosen:not(.is-answer) {
    box-shadow: inset 0 0 0 2px rgba(160, 120, 80, 0.42);
    background: color-mix(in srgb, var(--color-amber) 7%, transparent);
}
.kw-choice--image.is-chosen:not(.is-answer) { box-shadow: inset 0 0 0 2px rgba(160, 120, 80, 0.55), 0 3px 9px -5px rgba(var(--sh), 0.26); }
.kw-choices.kw-locked .kw-choice { cursor: default; pointer-events: none; }
.kw-choices.kw-locked .kw-choice:not(.is-answer):not(.is-chosen) { opacity: 0.45; }

/* 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%, #fff, 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); }
.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); }

/* ── verdict — the kanji deck's words beside a carved SEAL (owner 2026-07-09,
   amending the #645 seal retirement: OFF the art, marks the VERDICT, not the
   grade). Moss 正 = correct · amber 惜 = so close — hue AND glyph carry it. ── */
.kw-verdict {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 13px 6px 0;
    font: 500 clamp(12.5px, 0.95vw, 15px) var(--font-ui);
}
.kw-vseal {
    width: clamp(31px, 2.3vw, 39px);
    height: clamp(31px, 2.3vw, 39px);
    flex: none;
    display: grid;
    place-items: center;
    position: relative;
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(17px, 1.3vw, 22px);
    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-verdict.kw-right .kw-vseal { background: var(--moss-aa); }
.kw-verdict.kw-wrong .kw-vseal { background: var(--amber-aa); }
.kw-vseal::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%);
}
.kw-verdict .jp { font-family: var(--font-jp); font-size: clamp(15px, 1.2vw, 19px); }
.kw-verdict.kw-right .jp { color: var(--moss-aa); font-weight: 600; }
.kw-verdict.kw-wrong .jp { color: var(--amber-aa); font-weight: 600; }
.kw-verdict i.kw-vro { font: italic clamp(11px, 0.8vw, 13px) var(--font-ui); color: var(--color-faint-warm); }
/* the scheduling truth shares the verdict's line — one row, no extra chrome */
.kw-verdict .kw-statusline { margin-left: auto; }
/* Undo — a quiet ink line at the verdict's far edge (S2, owner 2026-07-10).
   Same law as .kw-slip-more: the global button chrome (components.css white
   bg / radius / shadow / hover lift) is declared away, rest AND hover. */
.kw-verdict .kw-undo,
.kw-verdict .kw-undo:hover {
    appearance: none;
    cursor: pointer;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    transform: none;
    margin-left: auto;
    padding: 2px 0;
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    font: 400 clamp(11px, 0.82vw, 13px) var(--font-ui);
    color: var(--color-faint-warm);
    transition: color 0.18s;
}
.kw-verdict .kw-undo:hover { color: var(--color-accent); }
/* the undo's jp keeps the quiet voice — never the verdict's moss/amber ink */
.kw-verdict .kw-undo .jp {
    font-family: var(--font-jp);
    font-size: clamp(12px, 0.9vw, 14px);
    font-weight: 400;
    color: var(--color-stone);
}
.kw-verdict .kw-undo i { font-style: italic; }
/* when the statusline already claims the right edge, undo just follows it */
.kw-verdict .kw-statusline + .kw-undo {
    margin-left: 14px;
    padding-left: 12px;
    border-left: 1px solid var(--color-divider);
}
/* the seal PRESSES once — confident for right, softer for a miss */
.kw-card.kw-just-revealed .kw-verdict.kw-right .kw-vseal { animation: kwSealPress 0.5s var(--ease-brush) 0.3s 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); }
}
.kw-card.kw-just-revealed .kw-verdict.kw-wrong .kw-vseal { animation: kwSealSoft 0.45s var(--ease-settle) 0.3s both; }
@keyframes kwSealSoft {
    0% { opacity: 0; transform: rotate(-4deg) scale(1.15); }
    100% { opacity: 1; transform: rotate(-4deg) scale(1); }
}

/* ── 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; }
.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); }
.kw-next 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); }
.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: 56px; }
.kw-slipcol--l { right: calc(50% + var(--kw-card-w) / 2 + 40px); padding-top: 120px; }
.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 12px 30px -14px rgba(var(--sh), 0.13);
    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(0, 0, 0, 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%, #2C2C2C 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: #A05C3B; }     /* 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; }
.kw-reg-row { display: flex; align-items: baseline; gap: 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); }
.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: #3D5A80; background: rgba(61, 90, 128, 0.09); }
.kw-yomi-fam--on .ktag { color: #9E5E43; 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: #3D5A80; }
.kw-yomi-fam--on .kw-yomi-read .jp { color: #9E5E43; }
.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: #3D5A80; }
.kw-yomi-fam--on .kw-yomi-row .hl { color: #9E5E43; }
.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: #A05C3B; }
.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: #A05C3B; }
.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: 12px; padding-top: 12px; border-top: 1px dashed var(--color-divider); }
/* 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-relnote--frame .rel-jp { color: var(--color-stone); }
.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: #3D5A80; }

/* 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;
    z-index: 240;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 340px;
    padding: 10px 14px;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.08);
    border-radius: 9px;
    box-shadow: 0 3px 9px rgba(var(--sh), 0.10), 0 10px 26px -12px rgba(var(--sh), 0.22);
    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; color: var(--color-ink); }
.kw-kxpeek .meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.kw-kxpeek .kwd { font: 600 12.5px var(--font-ui); color: var(--color-ink); }
.kw-kxpeek .reads { display: flex; flex-wrap: wrap; gap: 2px 10px; font: 400 11px var(--font-ui); color: var(--color-stone); }
.kw-kxpeek .reads b { font-family: var(--font-jp); font-weight: 400; color: var(--color-faint-warm); margin-right: 2px; }
.kw-kxpeek .reads [lang="ja"] { font-family: var(--font-jp); }
.kw-kxpeek .reads i { font-style: italic; color: var(--color-amber-deep); }

/* 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's shoji — RESTING it is a calling card (glyph ·
   keyword), the sumi-e peeking through a slim band; the band is the open
   button, and hovering widens the slit a breath (owner 2026-07-09) ───────── */
.kw-kopen,
.kw-kopen:hover {
    appearance: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    margin-top: 11px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    transform: none;
    text-align: left;
}
/* the WHOLE sumi-e, small — a framed print, never a blind letterbox crop
   (fleet 2026-07-09: a middle-strip crop turned 自 into a blob) */
.kw-kopen-peek {
    display: block;
    position: relative;
    flex: none;
    width: clamp(84px, 6.4vw, 108px);
    height: clamp(46px, 3.4vw, 60px);
    border-radius: 6px;
    overflow: hidden;
    background: #F6F3EC;
    border: 1px solid rgba(44, 44, 44, 0.06);
}
.kw-kopen-peek img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    opacity: 0.92;
    transition: transform 0.3s var(--ease-brush), opacity 0.3s;
}
/* the invitation breathes INSIDE its frame — the column below never moves;
   keyboard focus earns the same breath as the pointer */
.kw-kopen:hover .kw-kopen-peek img,
.kw-kopen:focus-visible .kw-kopen-peek img { transform: scale(1.05); opacity: 1; }
.kw-kopen-line {
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    padding: 2px 0;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    color: var(--color-faint-warm);
    transition: color 0.18s;
}
.kw-kopen:hover .kw-kopen-line,
.kw-kopen:focus-visible .kw-kopen-line { color: var(--color-accent); }
/* the shoji closes too (owner 2026-07-10) — OPEN, the thumb steps aside
   (the full art is right below) and the line reads 閉じる */
.kw-kopen-line.kw-ko-open { display: none; }
.kw-kbody--open .kw-kopen-line.kw-ko-closed { display: none; }
.kw-kbody--open .kw-kopen-line.kw-ko-open { display: inline-flex; }
.kw-kbody--open .kw-kopen-peek { display: none; }
.kw-kbody--open .kw-kopen { margin-top: 8px; }
.kw-kopen-line .jp { font-family: var(--font-jp); font-size: clamp(12.5px, 0.95vw, 15px); color: var(--color-stone); }
.kw-kopen-line i { font-style: italic; }
.kw-kopen-line .chev { font-size: 12px; }
.kw-kfull[hidden] { display: none; }
.kw-kfull.kw-deep-in { animation: kwSettleUp 0.4s var(--ease-brush) both; }

/* ── 活用 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; }
.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; }
.kw-th-hint { margin-top: 15px; font: 400 clamp(12px, 0.85vw, 14px) var(--font-ui); color: var(--color-faint-warm); }
/* 昨夜の一文 — 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: #2C2C2C;
    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; } }
.kw-close-h { font-family: var(--font-jp); font-size: clamp(32px, 2.7vw, 44px); color: var(--color-ink); }
.kw-close-ro {
    display: block;
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-faint-warm);
    margin-top: 9px;
}
.kw-tally { display: flex; justify-content: center; gap: clamp(28px, 2.6vw, 44px); margin: 24px 0 4px; flex-wrap: wrap; }
/* the settling words by NAME — a last look before they rest */
.kw-settling {
    margin-top: 10px;
    text-align: center;
    font: 400 clamp(11.5px, 0.88vw, 13.5px) var(--font-ui);
    color: var(--color-stone);
    line-height: 1.7;
}
.kw-settling .jp { font-family: var(--font-jp); color: var(--color-jp-text); }
.kw-settling i { font-style: italic; color: var(--color-amber-deep); }
.kw-settling .sep { color: var(--color-faint-warm); padding: 0 7px; }
.kw-tally-item { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.kw-tally-num { font-family: var(--font-jp); font-size: clamp(28px, 2.3vw, 37px); color: var(--color-ink); font-variant-numeric: tabular-nums; }
.kw-tally-lbl {
    font: 400 clamp(11px, 0.82vw, 13px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--color-faint-warm);
}
.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 record — tonight's stones at full size, cracks finally legible */
.kw-record {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    flex-wrap: wrap;
    gap: clamp(30px, 3vw, 48px);
    margin: 30px auto 0;
    padding: 22px 26px 16px;
    position: relative;
}
/* the ground follows EVERY row of a wrapped crossing (one absolute line
   once left row two floating) — each stone carries its own reach of earth,
   and neighbouring reaches meet into one soft line */
.kw-record .kw-tstep::before {
    content: "";
    position: absolute;
    left: calc(50% - clamp(42px, 3.4vw, 58px));
    width: calc(2 * clamp(42px, 3.4vw, 58px));
    top: clamp(21px, 1.5vw, 27px);
    height: 1px;
    background: rgba(var(--sh), 0.13);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
}
.kw-record .kw-tstep { gap: 9px; }
.kw-record .kw-tstone { width: clamp(42px, 3vw, 54px); height: clamp(42px, 3vw, 54px); }
.kw-record .kw-tstep.kw-lantern .kw-tstone {
    width: clamp(29px, 2.1vw, 38px);
    height: clamp(44px, 3.2vw, 57px);
    border-radius: 6px 6px 3px 3px;
}
.kw-record .kw-tstamp { font-size: clamp(13px, 1vw, 16px); max-width: 84px; min-height: 28px; }
.kw-record .kw-tstamp .r { font-size: clamp(8.5px, 0.68vw, 10.5px); }
/* at record scale the crack is finally legible — thicken accordingly */
.kw-record .kw-crack path { stroke-width: 2; }
.kw-record .kw-tstep.kw-mended .kw-crack path { stroke-width: 2.4; filter: drop-shadow(0 0 3px rgba(212, 184, 124, 0.85)); }
.kw-torii { width: 34px; height: 32px; position: relative; margin-top: 4px; }
.kw-torii::before {
    content: "";
    position: absolute;
    top: 0;
    left: -2px;
    right: -2px;
    height: 5px;
    background: var(--rel-opposite);
    border-radius: 2px;
    opacity: 0.7;
}
.kw-torii::after {
    content: "";
    position: absolute;
    top: 7px;
    left: 2px;
    right: 2px;
    height: 3px;
    background: var(--rel-opposite);
    border-radius: 2px;
    opacity: 0.55;
}
.kw-torii .legs::before, .kw-torii .legs::after {
    content: "";
    position: absolute;
    top: 5px;
    bottom: 0;
    width: 3px;
    background: var(--rel-opposite);
    opacity: 0.6;
}
.kw-torii .legs::before { left: 6px; }
.kw-torii .legs::after { right: 6px; }
/* the 間 door at the far bank — a walked stone with a real room carries the
   real seal (real-or-absent, the app-wide contract); wandering starts here */
.kw-record-seal,
.kw-record-seal:hover {
    appearance: none;
    cursor: pointer;
    display: block;
    margin: 7px auto 0;
    width: clamp(26px, 1.9vw, 32px);
    height: clamp(26px, 1.9vw, 32px);
    border: none;
    border-radius: 50%;
    background: rgba(251, 250, 247, 0.94);
    font-family: var(--font-jp);
    font-weight: 600;
    font-size: clamp(12.5px, 0.95vw, 15px);
    color: #6F5524;
    box-shadow: 0 1px 3px rgba(var(--sh), 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.65);
    transform: none;
    transition: box-shadow 0.2s;
    padding: 0;
}
.kw-record-seal:hover { box-shadow: 0 0 0 3px rgba(201, 169, 110, 0.18), 0 2px 6px rgba(var(--sh), 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.65); }
.kw-payoff {
    margin: 26px auto 0;
    max-width: clamp(520px, 42vw, 680px);
    background: var(--color-card-bright);
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-lg);
    padding: clamp(20px, 1.7vw, 28px) clamp(22px, 1.9vw, 30px);
    box-shadow: 0 1px 2px rgba(var(--sh), 0.045), 0 10px 30px -14px rgba(var(--sh), 0.10);
}
.kw-payoff-cap {
    font: 400 clamp(11.5px, 0.85vw, 13.5px) var(--font-ui);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--moss-aa);
    margin-bottom: 12px;
}
.kw-payoff-cap [lang="ja"] { font-family: var(--font-jp); letter-spacing: 0; text-transform: none; }
.kw-payoff-jp {
    font-family: var(--font-jp);
    font-size: clamp(24px, 1.9vw, 32px);
    color: var(--color-ink);
    line-height: 1.5;
    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); }
/* one more stone — real, or absent */
.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); }

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