/* ═══════════════════════════════════════════════════════════════════════════
   玄関 · home-hall.css — the desktop entrance hall (journey-gallery PR 2).
   Production port of design-mockups/desktop-home-genkan/home.css: ADDITIVE
   GLUE over the real design system. Everything structural on the wall
   (painting frame, placard, feature) resolves from tokens.css + grid-mode.css
   — the hall's wall carries the real .grid-cards / .grid-card-back-* classes.
   This file:
     (1) the hall OVERLAY — a level above the gallery; the room below stays
         mounted and untouched (body.home-hall gates it),
     (2) the BARE genkan beam (tokens only — deliberately not ink-wash-tabs'
         beam, which belongs to the gallery level),
     (3) journey hangings (nails, montage, hairline track, verb, ledger),
     (4) the 常設 doors — a deliberately DIFFERENT shape from journeys,
     (5) hall-only chrome the mockup lacked: the ⋯ manage popover and the
         道 journey-scope pill (which lives on the GALLERY beam).
   NO token/color redefinition — every value pulls from tokens.css.
   Desktop-gated by the <link media="(min-width: 769px)"> in index.html.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ THE OVERLAY — one opaque level above every room page overlay
   (word page 9000 / kanji sheet 9100 + drawer aside 9200 / 陽だまり room
   9050). The voice tutor sits at 5000 (chat-mode.css) — BELOW the hall — so
   the Practice door must always hide() before enterChatMode(), which it does;
   never show the hall over a live Sensei session. ═══ */
.home-hall-root {
    position: fixed;
    inset: 0;
    z-index: 9500;
    /* the genkan's one light source: a barely-there daylight wash from the
       high window, top-left (≤3% shift — felt as morning light on the upper
       wall, never read as "a gradient") */
    background-color: var(--color-paper, #F0EDE8);
    background-image: linear-gradient(165deg,
        color-mix(in srgb, var(--color-paper, #F0EDE8) 97%, #FFF6E3) 0%,
        var(--color-paper, #F0EDE8) 38%);
    overflow-y: auto;
    overscroll-behavior: contain;
}
.home-hall-root[hidden] { display: none; }
/* arriving/leaving — one gesture each way; interaction never waits (the
   leave fences pointers and only the paint lingers 200ms) */
.home-hall-root.hall-arrive {
    animation: hallArrive 0.24s var(--ease-brush, cubic-bezier(0.16, 1, 0.3, 1)) backwards;
}
@keyframes hallArrive { from { opacity: 0; } }
.home-hall-root.hall-leaving {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
}
.home-hall-root.hall-leaving * { pointer-events: none; }

/* ── ONE WALL WIDTH (fold recomposition 2026-07-05): the hall commits to a
   1460px wall — content 1380, exactly the hero's cap — so the beam, hero and
   shelf rows share BOTH edges and the wall centers as one composed column.
   Wide monitors gain symmetric ma instead of a bare right gutter (the old
   1800px wall left a full-height empty strip beside the hero at 1920).
   Painting scale is untouched: hero/shelf caps match the gallery level. ── */
.hall-scroll {
    width: 100%;
    max-width: 1460px;
    margin: 0 auto;
    padding: 12px 40px 40px;
    box-sizing: border-box;
}
@media (min-width: 769px) and (max-width: 1440px) {
    .hall-scroll { padding-left: 24px; padding-right: 24px; }
}

/* ═══ REGION 1 · THE GENKAN BEAM ═══
   The gallery lintel's wood — floating washi panel — with almost nothing on
   it. Hierarchy by absence: brand, the collection search, the date. */
.genkan-beam {
    position: sticky;
    top: 0;
    z-index: 100;
    padding: 0 24px;
    pointer-events: none;
}
.gb-inner {
    max-width: 1460px;   /* the lintel sits on the same wall (one width) */
    margin: 12px auto 0;
    height: 56px;
    padding: 0 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    pointer-events: auto;
    background: var(--color-card, #FAFAF7);
    /* Washi grain — the one surface that claims texture actually has it
       (0.012 sat below perceptual threshold; 0.028 is felt, not seen) */
    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.028'/%3E%3C/svg%3E");
    border-radius: 12px;
    /* a lintel has an edge you can feel: warm sumi hairline + contact shadow */
    border-bottom: 1px solid rgba(74, 58, 42, 0.10);
    box-shadow: 0 1px 2px rgba(44, 44, 44, 0.05), 0 0 1px rgba(44, 44, 44, 0.03);
}
.gb-left { display: flex; align-items: center; gap: 14px; }
.gb-right { display: flex; align-items: center; gap: 12px; }

/* Brand — the wordmark is the canonical .kotoba-wordmark--nav (css/brand.css
   §8) carried in the markup, so hall and gallery beams cannot drift apart.
   Not a button: this IS home. */
.gb-brand { display: flex; align-items: center; gap: 10px; user-select: none; }
.gb-logo {
    width: 34px; height: 34px;
    display: block;
    border-radius: 50%;      /* the hanko seal is ROUND, as on the gallery beam */
    object-fit: cover;
}

/* the HALL beam's 今日 date stamp retired with owner pick B (2026-07-16) —
   the hero's eyebrow is the one place that says today, and carries the
   date. The recipe stays: the composer bench's beam still wears gb-date
   (its room has no hero to speak for the day). */
.gb-date {
    display: flex;
    align-items: baseline;
    gap: 7px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    color: var(--text-tertiary, #8C8578);
    font-variant-numeric: tabular-nums;
}
.gb-date [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--color-stone, #57534e);
}

/* M3 · the lifetime line — the ONE number the hall keeps for the learner:
   "N learned" (learned = resting + coming back; the same word every card
   speaks). Quiet chrome recipe, the number in stone. On the hundredth-word
   day it wears 百 hyaku once — Japanese appears here only on that one
   earned day (scarcity gives meaning); every other day plain Inter. */
.gb-yours {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-tertiary, #8C8578);
}
/* below one learned word the line goes away entirely — display:inline-flex
   above out-ranks the UA [hidden] rule, so the reset must claim it here (same
   law as .gb-signin / .gb-account / .hall-toast). Without it updateYoursLine's
   el.hidden = true is inert and the beam keeps speaking the PREVIOUS count
   after a progress reset. */
.gb-yours[hidden] { display: none; }
.gb-yours b { font-weight: 600; color: var(--color-stone, #57534e); }
.gb-yours [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--color-amber-deep, #8A6E35);
}
.gb-yours i {
    font-style: italic;
    text-transform: none;
    letter-spacing: 0.02em;
    color: var(--color-amber-deep, #8A6E35);
}
.gb-yours .gy-dot { color: var(--text-tertiary, #8C8578); }

/* Sign in — the beam's one account affordance, shown only while signed OUT
   (the sync payoff needs a door at home); once signed in the hall goes bare
   again and account state lives in the rooms. Ghost voice, never a pill. */
.gb-signin {
    appearance: none;
    border: 1px solid rgba(44, 44, 44, 0.14);
    border-radius: 8px;
    background: transparent;
    box-shadow: none;
    padding: 6px 12px;
    font-family: 'Inter', sans-serif;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--color-stone, #57534e);
    cursor: pointer;
    transition: color 0.25s ease, border-color 0.25s ease;
}
.gb-signin:hover { color: var(--color-ink, #2C2C2C); border-color: rgba(44, 44, 44, 0.28); transform: none; box-shadow: none; }
.gb-signin:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }
.gb-signin[hidden] { display: none; }

/* Tutor — the practice hall's beam affordance (§A1d): the gallery beam's
   quiet destination voice, in the genkan's ghost dress. Localhost-gated in
   JS, so production never shows a dead door. */
.gb-tutor {
    appearance: none;
    box-shadow: none;
    border: 1px solid rgba(44, 44, 44, 0.14);
    border-radius: 8px;
    background: transparent;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    font-family: 'Inter', sans-serif;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--color-stone, #57534e);
    cursor: pointer;
    transition: color 0.25s ease, border-color 0.25s ease;
}
.gb-tutor svg { flex: none; display: block; }
.gb-tutor:hover, .gb-tutor:active { color: var(--color-ink, #2C2C2C); border-color: rgba(44, 44, 44, 0.28); }
.gb-tutor:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }

/* settings — the same quiet ⋮ every room header carries (T2 item 4) */
.gb-settings {
    appearance: none;
    box-shadow: none;
    border: none;
    background: transparent;
    padding: 0;
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 8px;
    font-size: 17px;
    line-height: 1;
    color: var(--color-stone, #57534e);
    cursor: pointer;
    transition: color 0.25s ease, background 0.25s ease;
}
.gb-settings:hover { color: var(--color-ink, #2C2C2C); background: rgba(44, 44, 44, 0.05); }
.gb-settings:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }

/* the settings rail must rise over the hall (root z 9500) when opened from
   it. Two locks: the rail's own z, AND main#app (its ancestor) must stop
   being a stacking context for the rail's lifetime — #app{z:10} otherwise
   caps every descendant at layer 10, under the hall, whatever z the rail
   claims. Scoped to exactly the rail-open-over-hall state; the app's own
   children keep their internal order (none competes above 300). */
body.home-hall .settings-sidebar { z-index: 9600; }
body.home-hall.settings-sidebar-open main#app { z-index: auto; }

/* The account mark (§A1c) — one quiet circle with the signed-in initial;
   the tooltip carries the sync state. Ghost voice, never a pill. */
.gb-account {
    appearance: none;
    box-shadow: none;
    border: none;
    background: transparent;
    padding: 0;              /* components.css button{padding:9px 18px} would crush the 34px mark to an oval */
    width: 34px; height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    cursor: pointer;
}
.gb-account[hidden] { display: none; }
.gb-account .gb-account-circle {
    width: 28px; height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--color-accent, #3D5A80) 9%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-accent, #3D5A80) 26%, transparent);
    font-family: 'Inter', sans-serif;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-accent, #3D5A80);
    transition: border-color 0.25s ease, background 0.25s ease;
}
.gb-account:hover .gb-account-circle,
.gb-account[aria-expanded="true"] .gb-account-circle {
    background: color-mix(in srgb, var(--color-accent, #3D5A80) 14%, transparent);
    border-color: color-mix(in srgb, var(--color-accent, #3D5A80) 42%, transparent);
}
.gb-account:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }

/* the account popover's extra lines (rides the .hall-pop panel) */
.hall-pop .hp-headsub {
    display: block;
    font-size: 11px;
    font-weight: 400;
    color: var(--color-faint-warm, #6E6860);   /* 11px on the bright face needs the AA faint */
    margin-top: 2px;
}
.hall-pop .hp-syncline {
    display: flex;
    align-items: center;
    gap: 7px;
    font-family: 'Inter', sans-serif;
    font-size: 11.5px;
    color: var(--color-stone, #57534e);
    padding: 0 6px 10px;
}
.hall-pop .hp-syncdot {
    flex: none;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--text-tertiary, #8C8578);
}
.hall-pop .hp-syncdot-synced { background: var(--color-moss, #6B7F5C); }
.hall-pop .hp-syncdot-syncing { background: var(--color-amber-deep, #8A6E35); }
.hall-pop .hp-syncdot-stuck { background: var(--color-terracotta, #A35A4A); }

.hall-pop {
    animation: hallPopIn 0.18s var(--ease-brush, cubic-bezier(0.16, 1, 0.3, 1)) backwards;
}
@keyframes hallPopIn {
    from { opacity: 0; transform: translateY(5px); }
}

/* ── The hero at HOME spans the full row — ONE cap (1380 = the wall's own
   content width) shared with every section below it, both edges aligned.
   height:auto lets the 3:2 painting set the row (the gallery's fixed
   --wall-card-h once cropped it ~80px at 1512 — "a fit, never a crop"). ── */
.home-hall-root .grid-feature {
    grid-column: 1 / -1;
    width: 100%;
    max-width: 1380px;
    height: auto;
    margin: 8px 0 0;
    gap: 44px;
}
.home-hall-root .gf-art { flex: 0 0 56%; }
/* grid-mode.css removes the REAL wall's feature below 1280px (word cards flow
   beside it there and the two-column frame starves). The hall's hero has the
   whole row to itself at every desktop width — re-assert it, or the most-due
   journey vanishes from home on half-screen laptops. */
@media (min-width: 769px) and (max-width: 1279px) {
    .home-hall-root .grid-feature { display: flex; }
}

/* ── The hero PLACARD is a resting card (2026-07-05): the gallery's naked
   placard floated on the same bare paper as the wall around it, so the hero
   had no right edge and the fold's emptiness ran straight through it. A
   paper body + hairline gives the composition its terminus — the same
   surface the first-run door and every shelf door already rest on. ── */
.home-hall-root .grid-feature .gf-placard {
    justify-content: flex-start;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);
    padding: 32px 36px 28px;
    box-sizing: border-box;
}

/* ── 今日のことば — today's NEW words on the placard, real word ink (Klee JP
   + amber romaji + gloss — the fold's one piece of CONTENT Japanese; the
   new slice of the Begin deck only, never the revisits). Degradation order
   for long phrases: the JP ink stays whole, romaji may shrink + ellipsize,
   and the gloss keeps a floor — wrapping to its own line before it ever
   crushes to nothing (a phrase with no meaning teaches nothing). ── */
.gf-meet {
    display: flex;
    flex-direction: column;
    gap: 13px;
    margin-top: 22px;
    min-width: 0;
}
.gf-meet-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 12px;
    min-width: 0;
}
.gf-meet-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 22px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.02em;
    font-feature-settings: 'palt' 1;
    line-height: 1.2;
    white-space: nowrap;
    flex: none;
    max-width: 100%;             /* whole ink; ellipsis only at pathological length */
    overflow: hidden;
    text-overflow: ellipsis;
}
.gf-meet-kanji .gf-meet-jp { font-size: 26px; }
.gf-meet-rom {
    font-family: 'Inter', sans-serif;
    font-style: italic;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--color-amber-deep, #8A6E35);
    white-space: nowrap;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gf-meet-en {
    font-family: 'Inter', sans-serif;
    font-size: 13.5px;
    color: rgba(44, 44, 44, 0.62);
    flex: 1 1 auto;
    min-width: 90px;             /* the floor: wrap to a fresh line, never 0px */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── The hero's STANDING block — the honest sentence speaks TODAY; beneath
   it the standing trace and the page's ONE real button into the session. ── */
.gf-meta {
    display: flex;
    flex-direction: column;
    gap: 10px;             /* standing + action read as ONE unit… */
    margin-top: auto;      /* …seated at the placard's foot (padding-top guards the gap) */
    padding-top: 18px;
    max-width: 460px;
}
.home-hall-root .grid-feature .jhang-verb { font-size: 11px; }
.home-hall-root .grid-feature .jhang-verb [lang="ja"] { font-size: 13px; }
.home-hall-root .grid-feature .jhang-verb .jhang-frac { font-size: 13px; }
.home-hall-root .grid-feature .jhang-verb.is-revisit .jhang-dot { width: 6px; height: 6px; }

/* one supporting line under the title — romaji (amber = pronunciation) and
   gloss share a baseline instead of stacking two tiers */
.home-hall-root .gf-sub {
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-family: 'Inter', sans-serif;
    font-size: 15px;
    margin-bottom: 2px;
    min-width: 0;
}
.home-hall-root .gf-sub .gf-sub-rom {
    font-style: italic;
    letter-spacing: 0.04em;
    color: var(--color-amber-deep, #8A6E35);
    font-size: 14px;
}
.home-hall-root .gf-sub .gf-sub-gloss {
    font-weight: 500;
    color: rgba(44, 44, 44, 0.82);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* the standing trace — one quiet tabular line at legible size; the met
   total splits into learned · saved (M3 walk), numbers set in stone the
   way the Continue ledger sets its own */
.home-hall-root .gf-standing {
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    color: var(--color-faint-warm, #6E6860);
    font-variant-numeric: tabular-nums;
}
.home-hall-root .gf-standing b {
    font-weight: 600;
    color: var(--color-stone, #57534e);
}

/* M3 · the last-crossing echo — yesterday's payoff line resting under the
   today card until today's own close re-stamps kwLastClose and the echo
   yields on its own. gf-standing's quiet voice; the sentence speaks Klee.
   One line, no door (owner-taste prototype). */
.hall-echo {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    padding: 0 6px;
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    color: var(--color-faint-warm, #6E6860);
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
.hall-echo .he-label {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-tertiary, #8C8578);
}
.hall-echo .he-label [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--color-stone, #57534e);
}
.hall-echo .he-label i {
    font-style: italic;
    text-transform: none;
    letter-spacing: 0.02em;
}
.hall-echo .he-line {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 14px;
    color: var(--color-stone, #57534e);
}
.hall-echo .he-rom {
    font-style: italic;
    font-size: 12px;
    color: var(--color-amber-deep, #8A6E35);
}
.hall-echo .he-en { font-size: 12px; }

/* ── the BEGIN button — the landing's one solid affordance (a page needs
   exactly one primary action; everything else stays ghost/ink). Solid
   accent, no gradient, no lift — hp-primary's voice at hero scale. ── */
.gf-actions { display: flex; align-items: center; gap: 14px; margin-top: 2px; }
.gf-begin {
    appearance: none;
    border: none;
    cursor: pointer;
    background: var(--color-accent, #3D5A80);
    color: var(--color-card, #FAFAF7);
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 10px 18px;
    border-radius: 8px;
    box-shadow: none;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    transition: background 0.25s ease;
}
.gf-begin:hover, .gf-begin:active {
    background: color-mix(in srgb, var(--color-accent, #3D5A80) 88%, #000);
    transform: none;
    box-shadow: none;
}
.gf-begin:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }
.gf-begin.gf-begin-ghost {
    background: transparent;
    border: 1px solid rgba(44, 44, 44, 0.16);
    color: var(--color-stone, #57534e);
    padding: 9px 17px;   /* the hairline keeps the solid's outer size */
}
.gf-begin.gf-begin-ghost:hover, .gf-begin.gf-begin-ghost:active {
    background: transparent;
    border-color: rgba(44, 44, 44, 0.32);
    color: var(--color-ink, #2C2C2C);
}
.gf-begin .gf-begin-arrow {
    display: inline-block;
    transition: transform 0.3s var(--ease-out-expo, cubic-bezier(0.19, 1, 0.22, 1));
}
.gf-begin:hover .gf-begin-arrow { transform: translateX(3px); }

/* (the hero's arrival track-fill retired with the hero track itself,
   2026-07-05 — a 1%-full hairline at eye level said "nothing here yet" to a
   learner who had practiced; today's actual words carry the placard now.
   The hung cards keep their tracks: at ledger scale the split earns it.) */

/* romaji beside the eyebrow's JP (beginner-romaji rule) — italic, lowercase,
   in the pronunciation layer's amber */
/* A user-composed journey may carry a Latin name — Klee sets Latin poorly.
   Same display scale as the JP cap, optically adjusted (Inter runs larger):
   the resume title must command the placard, not caption it. */
.home-hall-root .gf-jp.hall-title-latin {
    font-family: 'Inter', sans-serif;
    font-size: clamp(30px, 2.9vw, 44px);
    font-weight: 600;
    letter-spacing: -0.01em;
}
/* the one honest sentence holds the mid-column — body scale, real contrast
   (at 0.92rem/0.66 it visually dropped out and the placard read as 3 items) */
.home-hall-root .grid-feature .gf-story {
    font-size: 15.5px;
    color: rgba(44, 44, 44, 0.80);
}

/* ═══ A HUNG JOURNEY PIECE ═══ (byte-identical to a resting word painting:
   reuses .grid-card-back-image + the .grid-card-back-* placard classes; the
   wrapper gives it the wall height and stacks the placard beneath). */
.jhang {
    height: var(--wall-card-h, 480px);
    display: flex;
    flex-direction: column;
    padding: 0 var(--wall-pad, 8px);
    box-sizing: border-box;
    cursor: pointer;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
/* Cards REST — no lift/scale on the box; only the MAIN painting breathes
   (in a montage the two small pieces stay still: one living print per frame). */
.jhang:hover .grid-card-back-image > img,
.jhang:hover .jh-main img { transform: scale(1.035); }
.jhang .grid-card-back-image { flex: 0 0 auto; background-size: cover; background-position: center; }
.jhang .grid-card-back-header { padding-right: 40px; position: relative; }

/* ── WIDE HANGING (1-2 journeys) — the wall composes to what hangs on it:
   a lone card in a three-track grid left two tracks of bare wall (the
   fold's disease, one shelf down). Few pieces hang across the full row —
   montage left, resting paper placard right (the hero's anatomy, one
   voice quieter: shorter painting, card-scale type). ── */
.jhang.jhang-wide {
    grid-column: 1 / -1;
    width: 100%;
    max-width: 1380px;
    height: auto;
    flex-direction: row;
    align-items: stretch;
    gap: 44px;
}
.jhang-wide .jh-cover {
    flex: 0 0 40%;
    min-width: 0;
    height: 232px;
    align-self: center;
    border-radius: 5px;
    overflow: hidden;
}
.jhang-wide .jh-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);
    padding: 24px 30px 22px;
    box-sizing: border-box;
    transition: border-color 0.25s ease;
}
.jhang-wide:hover .jh-body { border-color: rgba(44, 44, 44, 0.16); }
/* the meta seats at the placard's foot — same anatomy as the hero card */
.jhang-wide .jhang-meta { margin-top: auto; padding-top: 14px; }
.jhang-wide .jh-gloss { margin-top: 4px; }

/* ── THE MONTAGE COVER — a journey is a SET of paintings, and its cover says
   so: one main piece + two smaller, mounted with 2px seams that read as the
   mat between prints (seam color = the frame's own tone wash). ── */
.jh-cover.jh-montage {
    display: flex;
    align-items: stretch;
    justify-content: flex-start;
    gap: 2px;
}
.jh-montage figure { margin: 0; position: relative; overflow: hidden; }
.jh-montage .jh-main { flex: 1 1 auto; min-width: 0; height: 100%; }
.jh-montage .jh-side {
    flex: 0 0 31%;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.jh-montage .jh-piece { flex: 1 1 50%; min-height: 0; }
.jh-montage figure img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}

/* A user-named journey may carry a Latin name — Inter at a matched size. */
.jhang .grid-card-back-japanese.jh-title-latin {
    font-family: 'Inter', sans-serif;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── THE JOURNEY SUBTITLE — descriptive wall text, its own species (the word
   card's English is the flashcard ANSWER; a journey's gloss only describes,
   so it steps back: smaller, stone, two lines then ellipsis). ── */
.jh-gloss {
    flex: 0 0 auto;
    margin-top: 3px;
    padding: 0 4px;
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    font-weight: 400;
    color: var(--color-stone, #57534e);
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The four corner-dot "nails" — the hung signal. Warm sumi-brown, never gold. */
.jhang-nail,
.gf-art .jhang-nail {
    position: absolute;
    width: 3px; height: 3px;
    border-radius: 50%;
    background: rgba(74, 58, 42, 0.55);
    z-index: 4;
    pointer-events: none;
}
.jhang-nail.n-tl { top: 4px; left: 4px; }
.jhang-nail.n-tr { top: 4px; right: 4px; }
.jhang-nail.n-bl { bottom: 4px; left: 4px; }
.jhang-nail.n-br { bottom: 4px; right: 4px; }

/* Slim journey meta: 1px progress hairline (learned=moss, saved=sumi — never
   gold) + verb + honest ledger, pinned to the placard's foot. */
.jhang-meta {
    margin-top: auto;
    padding: 8px 4px 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.jhang-track-row {
    display: flex;
    align-items: center;
    gap: 10px;
}
.jhang-track {
    position: relative;
    height: 3px; flex: 1;
    background: rgba(44, 44, 44, 0.10);
    border-radius: 3px;
    overflow: hidden;
}
.jhang-fill-learned {
    position: absolute; left: 0; top: 0; bottom: 0;
    background: var(--color-moss, #6B7F5C);   /* full moss — a thin line needs its pigment */
}
.jhang-fill-saved {
    position: absolute; top: 0; bottom: 0;
    background: rgba(44, 44, 44, 0.38);
}
/* the track's number (owner pick B) — "72% learned", moss so the word names
   the moss segment; the saved fill stays a texture the ledger spells out */
.jhang-pct {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--color-moss, #6B7F5C);
    white-space: nowrap;
    flex: none;
}
.jhang-pct i {
    font-style: normal;
    font-weight: 600;
    font-size: 8px;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    margin-left: 3px;
}
/* On the hero the same row scales up a step. */
.home-hall-root .grid-feature .jhang-pct { font-size: 12px; }
.home-hall-root .grid-feature .jhang-pct i { font-size: 9px; }

/* THE ACTION VERB — one unambiguous word per hung piece.
   START (new) · CONTINUE n/m (in progress) · TO REVISIT n (review debt). */
.jhang-verb {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--color-ink, #2C2C2C);
}
.jhang-verb [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 12px;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0.04em;
}
.jhang-verb .jhang-frac { font-size: 12px; letter-spacing: 0; }
.jhang-verb .jhang-slash { color: var(--text-tertiary, #8C8578); margin: 0 1px; }
.jhang-verb.is-new { color: var(--text-tertiary, #8C8578); font-weight: 500; }
.jhang-verb.is-new [lang="ja"] { color: var(--text-tertiary, #8C8578); }
.jhang-verb.is-progress .jhang-frac { color: var(--color-ink, #2C2C2C); }
.jhang-verb.is-revisit { color: var(--color-accent, #3D5A80); }
.jhang-verb.is-revisit [lang="ja"] { color: var(--color-accent, #3D5A80); }
.jhang-verb.is-revisit .jhang-dot {
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--color-accent, #3D5A80);
    align-self: center;
    flex: none;
}

/* THE HONEST LEDGER — where a beginner actually stands, as one readable
   fraction ("973 of 1,356 learned · 379 saved"). Sentence-case on purpose
   (owner pick B): a full phrase reads better than shouted caps. faint-warm,
   not tertiary — the app's most trust-bearing line holds AA. */
.jhang-ledger {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.06em;
    color: var(--color-faint-warm, #6E6860);
}
.jhang-ledger b { font-weight: 700; color: var(--color-stone, #57534e); }

/* numbers set like a jeweller: tabular figures on every counting surface */
.jhang-frac, .jhang-ledger, .jhang-pct, .gdoor-ledger, .th-ledger, .tt-count,
.gf-standing, .hs-count,
.gb-yours, .sc-started, .hall-echo {
    font-variant-numeric: tabular-nums;
}

/* Components.css dresses EVERY bare <button> as a raised white pill
   (background:white, 9×18 padding, drop shadow, hover translateY lift).
   The hall's controls are quiet ghost utilities — re-assert flat here, or
   the ⋯ renders as an empty lozenge (the 18px side padding leaves a 30px
   border-box button zero content width, collapsing the svg to 0). */
.jh-manage, .journey-scope-pill .jsp-clear, .hall-pop .hp-row, .hall-pop .hp-btn {
    padding: 0;
    box-shadow: none;
}
/* The new §A buttons (.hall-kura/.gb-tutor/.gb-account) neutralize
   the components.css pill INSIDE their own blocks — .gb-tutor/.gb-signin set
   their own padding, .gb-account resets to 0 (it once forgot: the mark shipped
   as a crushed oval). Listing them here would zero the padding some just set
   (same specificity, later rule wins), so only the shared hover/active
   flattening rides this list. */
.jh-manage:hover, .journey-scope-pill .jsp-clear:hover,
.hall-pop .hp-row:hover, .hall-pop .hp-btn:hover,
.jh-manage:active, .journey-scope-pill .jsp-clear:active,
.hall-pop .hp-row:active, .hall-pop .hp-btn:active,
.hall-kura:hover, .hall-kura:active,
.gb-tutor:hover, .gb-tutor:active, .gb-account:hover, .gb-account:active {
    transform: none;
    box-shadow: none;
}

/* ── the ⋯ manage handle — the placard's quiet corner utility (ghost wash,
   wakes on hover; sits in the header's cleared right column). ── */
.jh-manage {
    appearance: none;
    background: transparent;
    border: none;
    border-radius: 8px;
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-tertiary, #8C8578);
    opacity: 0.55;
    cursor: pointer;
    transition: opacity 0.25s ease, background 0.25s ease, color 0.25s ease;
}
.jh-manage svg { width: 15px; height: 15px; flex: none; display: block; }
.jhang .jh-manage { position: absolute; right: 0; top: 12px; }
.gf-eyebrow .jh-manage { margin-left: auto; align-self: center; }
/* the eyebrow's reading — 今日 kyō (the beginner-romaji rule; same voice
   as the 百 hyaku and 前回 zenkai seals, which always carried theirs) */
.home-hall-root .gf-eyebrow .gf-eyebrow-rom {
    font-style: italic;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--color-gold-deep, #8a6e35);
}
.jhang:hover .jh-manage, .grid-feature:hover .jh-manage { opacity: 1; }
.jh-manage:hover { background: rgba(140, 133, 120, 0.10); color: var(--color-stone, #57534e); }
.jh-manage:focus-visible { opacity: 1; outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; }

/* ── the manage POPOVER — a structured washi menu: a labelled header zone,
   row groups split by the wall's fading rule, destructive rows below their
   own hairline, actions behind a footer seam. Bright card face so it reads
   as a layer OVER the resting placard; shadow is warm ink, never black.
   The account panel rides the same classes. ── */
.hall-pop {
    position: absolute;
    z-index: 300;
    width: 296px;
    background: var(--color-card-bright, #FEFDFB);   /* crisper figure/ground vs the #FAFAF7 placard behind */
    border: 1px solid rgba(44, 44, 44, 0.10);
    border-radius: 10px;                             /* the placard's own radius — same hand */
    box-shadow: 0 1px 2px rgba(44, 44, 44, 0.05),
                0 10px 30px rgba(44, 44, 44, 0.09),
                0 30px 70px -28px rgba(44, 44, 44, 0.18);
    padding: 8px;
    box-sizing: border-box;
    max-height: calc(100vh - 120px);                 /* many scope groups scroll, never grow past the fold */
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;                                        /* quiet scroll — an OS scrollbar would
                                                                     shout on washi; 0.35 keeps the thumb
                                                                     perceivable (the only overflow cue) */
    scrollbar-color: rgba(44, 44, 44, 0.35) transparent;
}
/* text selection in the house indigo, not browser blue */
.hall-pop ::selection { background: rgba(61, 90, 128, 0.18); }

/* header zone: a whisper-caps kicker names the panel's job, the name leads
   (confirm views reuse .hp-head alone as their question line) */
.hall-pop .hp-kicker {
    display: block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* 10px caps needs the AA faint */
    margin-bottom: 3px;
}
.hall-pop .hp-head {
    font-family: 'Inter', sans-serif;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    padding: 9px 10px 7px;
    line-height: 1.4;
}

/* the wall's fading rule scaled to the panel — groups earn structure
   without boxes; the second one isolates the destructive rows */
.hall-pop .hp-sep {
    height: 1px;
    margin: 5px 10px;
    background: linear-gradient(90deg, rgba(44, 44, 44, 0.10) 0%, rgba(44, 44, 44, 0.07) 55%, transparent 96%);
}

/* rows: quiet ghost buttons, warm sumi wash on hover (never a gray chip).
   .hall-pop prefix keeps padding ahead of the pill-neutralizer's padding:0. */
.hall-pop .hp-row {
    appearance: none; background: none; border: none;
    display: block; width: 100%; text-align: left;
    padding: 8px 10px 9px;
    border-radius: 7px;
    cursor: pointer;
    font-family: 'Inter', sans-serif;
    transition: background-color 0.15s ease;
}
.hall-pop .hp-row b { display: block; font-size: 13px; font-weight: 500; color: var(--color-ink, #2C2C2C); line-height: 1.35; }
.hall-pop .hp-row span { display: block; font-size: 11px; color: var(--color-faint-warm, #6E6860); margin-top: 2px; line-height: 1.4; }
.hall-pop .hp-row:hover { background: rgba(44, 44, 44, 0.045); }
.hall-pop .hp-row:active { background: rgba(44, 44, 44, 0.06); }
.hall-pop .hp-row:focus { outline: none; }               /* mouse focus quiet; keyboard keeps the ring below */
.hall-pop .hp-row:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: -2px; }
/* danger speaks terracotta AND sits below its own hairline + a weight step —
   never color alone (mobile's Remove row wears the same token) */
.hall-pop .hp-row.hp-danger b { color: var(--color-terracotta, #A35A4A); font-weight: 600; }
.hall-pop .hp-row.hp-danger:hover { background: var(--color-terracotta-bg, rgba(163, 90, 74, 0.07)); }
.hall-pop .hp-row.hp-danger:active { background: rgba(163, 90, 74, 0.08); }   /* 0.10 dipped the label under AA */

.hall-pop .hp-note {
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--color-stone, #57534e);
    padding: 2px 10px 10px;
}
.hall-pop .hp-input {
    width: calc(100% - 20px);
    box-sizing: border-box;
    height: 34px;
    margin: 2px 10px 12px;
    padding: 0 1px;
    border: none;
    border-bottom: 1px solid rgba(44, 44, 44, 0.16);
    border-radius: 0;
    background: transparent;
    font-family: 'Inter', sans-serif;
    font-size: 13.5px;
    color: var(--color-ink, #2C2C2C);
    caret-color: var(--color-accent, #3D5A80);
    outline: none;
}
.hall-pop .hp-input:focus,
.hall-pop .hp-input:focus-visible {
    outline: none;                                   /* the underline IS the ring — a box outline fights the borderless input */
    border-bottom-color: var(--color-accent, #3D5A80);   /* opaque indigo: 6.8:1, clears the 3:1 non-text minimum */
    box-shadow: 0 1px 0 var(--color-accent, #3D5A80);    /* thickens to 2px without a layout shift */
}

/* footer seam: actions sit behind their own fading rule; the scope view's
   count keeps the left column — a full phrase with jeweller's numerals,
   never shouted caps */
.hall-pop .hp-actions {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    margin: 6px 2px 0;
    padding: 9px 6px 4px;
}
.hall-pop .hp-actions::before {
    content: "";
    position: absolute;
    top: 0; left: 8px; right: 8px;
    height: 1px;
    background: linear-gradient(90deg, rgba(44, 44, 44, 0.10) 0%, rgba(44, 44, 44, 0.07) 55%, transparent 96%);
}
.hall-pop .hp-btn {
    appearance: none; cursor: pointer;
    display: inline-flex; align-items: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 7px;
    padding: 6px 13px;
    min-height: 30px;
    box-sizing: border-box;
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--color-stone, #57534e);
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
.hall-pop .hp-btn:hover { background: rgba(44, 44, 44, 0.05); }
.hall-pop .hp-btn:focus { outline: none; }
.hall-pop .hp-btn:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 1px; }
.hall-pop .hp-btn.hp-primary { background: var(--color-accent, #3D5A80); color: var(--color-card, #FAFAF7); }
.hall-pop .hp-btn.hp-primary:hover { background: color-mix(in srgb, var(--color-accent, #3D5A80) 88%, #000); }
/* the destructive confirm carries real affordance — a hairline terracotta
   ghost, never a solid alarm (there is no red) */
.hall-pop .hp-btn.hp-danger-btn { color: var(--color-terracotta, #A35A4A); border-color: rgba(163, 90, 74, 0.35); }
.hall-pop .hp-btn.hp-danger-btn:hover { background: rgba(163, 90, 74, 0.08); border-color: rgba(163, 90, 74, 0.5); }

/* scope view: caps label + rows per group; the JP names speak Klee —
   content is the panel's Japanese voice, the chrome stays Inter */
.hall-pop .hp-sgrp { padding: 5px 10px 7px; }
.hall-pop .hp-slabel {
    font-family: 'Inter', sans-serif;
    font-size: 10px; font-weight: 600;
    letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* 10px caps needs the AA faint */
    margin-bottom: 4px;
}
.hall-pop .hp-srow {
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    color: var(--color-ink, #2C2C2C);
    line-height: 1.6;
}
.hall-pop .hp-srow [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13.5px; font-weight: 500;
    letter-spacing: 0; font-feature-settings: 'palt' 1;
}
.hall-pop .hp-srow i {
    font-style: normal;
    color: var(--color-faint-warm, #6E6860);   /* 11.5px detail needs the AA faint */
    margin-left: 7px;
    font-size: 11.5px;
    font-variant-numeric: tabular-nums;
}
.hall-pop .hp-foot {
    margin-right: auto;                     /* the footer seam's left column */
    font-family: 'Inter', sans-serif;
    font-size: 11.5px;
    font-weight: 500;
    color: var(--color-faint-warm, #6E6860);
    font-variant-numeric: tabular-nums;
}

/* account extras (hp-headsub/hp-syncline, defined near :279) ride the same
   grid: panel 8px + 10px = one 18px text edge */
.hall-pop .hp-syncline { padding: 0 10px 10px; }

/* ── A SOFT IN-WALL SECTION LABEL — the wall's own typographic voice: Klee
   ink JP, italic amber romaji, whisper caps, a hairline fading rightward.
   Margins rebalance the wall's 52px row-gap: a little above, negative below
   (a label belongs to what it names — and the shelf must break the fold,
   so the hero→shelf band stays a seam, never a moat). ── */
.wall-section {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: 14px;
    margin: 18px var(--wall-pad, 8px) -22px;
    animation: cardEntrance 0.6s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
.wall-section .ws-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 20px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.02em;   /* palt does the fitting — Western tracking gaps kana */
    font-feature-settings: 'palt' 1;
    line-height: 1;
}
.wall-section .ws-rom {
    font-family: 'Inter', sans-serif;
    font-style: italic;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--text-tertiary, #8C8578);
}
.wall-section .ws-en {
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-tertiary, #8C8578);
}
.wall-section .ws-rule {
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg,
        rgba(44, 44, 44, 0.10) 0%,
        rgba(44, 44, 44, 0.07) 55%,
        transparent 96%);
    align-self: center;
    margin-left: 10px;
}

/* ═══ FIRST-RUN — an empty wall leads with the question; the 道の棚 doors
   below are the answer. The question OWNS the page (display scale — on a
   wall with no paintings yet, the headline is the only object that can
   compose the width), then plain English, then the one honest promise. ═══ */
.hall-firstrun {
    grid-column: 1 / -1;
    padding: 40px var(--wall-pad, 8px) 6px;
    max-width: 900px;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
}
.hall-firstrun .hf-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: clamp(32px, 3vw, 44px);
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.04em;
    font-feature-settings: 'palt' 1;
    line-height: 1.3;
}
.hall-firstrun .hf-en {
    margin-top: 12px;
    font-family: 'Inter', sans-serif;
    font-size: 19px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
}
.hall-firstrun .hf-sub {
    margin: 10px 0 0;
    font-family: 'Inter', sans-serif;
    font-size: 14px;
    line-height: 1.6;
    color: var(--color-stone, #57534e);
    max-width: 62ch;
}

/* ═══ START HERE (first-run only) — the first lesson, not a catalogue: ONE
   recommended door that answers the question and begins today's session.
   HERO ANATOMY (fold recomposition 2026-07-05): the same 56% painting +
   resting placard the return hero hangs, so a brand-new user's first screen
   composes the same full row a lived-in wall gets — never a business card
   floating in the left half. ═══ */
.hall-start {
    grid-column: 1 / -1;
    display: flex;
    align-items: stretch;
    width: 100%;
    max-width: 1380px;
    margin: 22px 0 0;
    padding: 0 var(--wall-pad, 8px);
    box-sizing: border-box;
    gap: 44px;
    cursor: pointer;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
.hall-start .hs-art {
    flex: 0 0 56%;
    min-width: 0;
    align-self: center;
    aspect-ratio: 3 / 2;
    position: relative;
    overflow: hidden;
    border-radius: 5px;
    /* the hero painting's own frame (gf-art's voice) */
    box-shadow:
        0 0 0 1px rgba(44, 44, 44, 0.08),
        0 10px 24px -10px rgba(44, 44, 44, 0.5),
        0 2px 8px -2px rgba(44, 44, 44, 0.12);
}
.hall-start .hs-art .hs-img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 1.8s cubic-bezier(0.19, 1, 0.22, 1);
}
.hall-start:hover .hs-art .hs-img { transform: scale(1.03); }
.hall-start .hs-art .scard-cover { height: 100%; min-height: 0; border-radius: 0; }
.hall-start .hs-body {
    flex: 1;
    min-width: 0;
    padding: 32px 36px 28px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);
    box-sizing: border-box;
    transition: border-color 0.25s ease;
}
.hall-start:hover .hs-body { border-color: rgba(44, 44, 44, 0.16); }
.hall-start .hs-eyebrow {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-amber-deep, #8A6E35);
}
.hall-start .hs-eyebrow [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: none;
}
.hall-start .hs-eyebrow i { font-style: italic; font-weight: 400; letter-spacing: 0.04em; text-transform: none; }
.hall-start .hs-name {
    font-family: 'Inter', sans-serif;
    font-size: clamp(26px, 2.4vw, 36px);   /* a recommendation speaks one size
                                              under the resident hero's title */
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--color-ink, #2C2C2C);
}
.hall-start .hs-sub {
    margin: 6px 0 0;
    font-family: 'Inter', sans-serif;
    font-size: 14px;
    line-height: 1.6;
    color: var(--color-stone, #57534e);
    max-width: 46ch;
}
.hall-start .hs-actions {
    margin-top: auto;
    padding-top: 18px;
    display: flex;
    align-items: center;
    gap: 14px;
}
.hall-start .hs-count {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);
}
.hall-start .hs-count b { font-weight: 700; color: var(--color-stone, #57534e); }

/* "or choose your own path" — a whisper between the one door and the shelf */
.hall-or {
    grid-column: 1 / -1;
    margin: 20px var(--wall-pad, 8px) -26px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}

/* ═══ 道の棚 · THE SHELF DOORS — the gdoor species with its own class (five
   doors onto ready-made journeys; the 常設 walk below keeps counting ITS
   three). Shape, glimpse and verb re-state the door recipe verbatim. ═══ */
.tdoor {
    display: flex;
    align-items: stretch;
    min-height: 150px;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);   /* warm sumi, never cold black */
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.tdoor:hover {
    border-color: rgba(44, 44, 44, 0.16);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(44, 44, 44, 0.06);
}
.tdoor:focus-visible {
    outline: 2px solid rgba(61, 90, 128, 0.55);
    outline-offset: 3px;
}
.tdoor:hover .gdoor-art { flex-basis: 148px; }
.tdoor:hover .gdoor-verb { color: var(--color-accent, #3D5A80); }
.tdoor:hover .gdoor-verb .gdoor-arrow { transform: translateX(3px); }
.tdoor:hover .gk-hero { opacity: 0.92; }

/* one painting through the door */
.tdoor-art-pic { height: 100%; }
.tdoor-art-pic img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.6s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1));
}
.tdoor:hover .tdoor-art-pic img { transform: scale(1.05); }

/* the topic door's 2×2 world mosaic (onboarding's rmosaic, door-scaled) */
.tdoor-art-mosaic {
    height: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 1px;
}
.tdoor-art-mosaic img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    min-height: 0;
}

/* おすすめ — a quiet amber recommendation, not a gold ceremony */
.tdoor-seal {
    display: flex;
    align-items: baseline;
    gap: 5px;
    font-family: 'Inter', sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-amber-deep, #8A6E35);
    margin-bottom: 1px;
}
.tdoor-seal [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 11.5px;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: none;
}
.tdoor-seal i { font-style: italic; font-weight: 400; letter-spacing: 0.04em; text-transform: none; }

/* ═══ 道の棚 · THE STOCKED ROWS (§A1) — each axis shows its spines: a small
   header, 3-4 live entry cards (the shelf room's .scard species, scaled to
   row density per the one-component rule), and a "see all N →" tail. ═══ */
.tana-rows {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: 34px;
    margin: 0 var(--wall-pad, 8px) 8px;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}

/* the axis header — the wall-section voice, one size quieter */
.tana-head {
    display: flex;
    align-items: baseline;
    gap: 11px;
    margin-bottom: 12px;
}
.tana-head .th-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 15px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.02em;   /* palt-fitted, same as every Klee label */
    font-feature-settings: 'palt' 1;
    line-height: 1;
}
/* the head's reading — the beginner-romaji rule (same voice as ws-rom
   on つづき above and sc-rom on the spines below) */
.tana-head .th-rom {
    font-family: 'Inter', sans-serif;
    font-style: italic;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--text-tertiary, #8C8578);
}
.tana-head .th-en {
    font-family: 'Inter', sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* AA at 9.5px caps */
}
.tana-head .th-rule {
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg,
        rgba(44, 44, 44, 0.09) 0%,
        rgba(44, 44, 44, 0.06) 55%,
        transparent 96%);
    align-self: center;
    margin-left: 8px;
}
/* the kanji row's honest SRS ledger (PR 4 — "622 kanji · 12 learned · 3 to
   revisit"), a whisper after the axis words */
.tana-head .th-ledger {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    color: var(--color-faint-warm, #6E6860);
    white-space: nowrap;
}
.tana-head .th-ledger b { font-weight: 600; color: var(--color-ink, #2C2C2C); }

/* a kanji journey's cover glyph — the path's first kanji on a small paper
   tag (the wall twin of the shelf room's .sck-glyph) */
.jh-kglyph {
    position: absolute;
    right: 12px;
    bottom: 8px;
    z-index: 2;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-weight: 600;
    font-size: 34px;
    line-height: 1.2;
    /* brushed straight on the painting — no white chip (the boxed tag read
       as a UI button; the story paintings are washi-pale, ink holds) */
    color: var(--color-ink, #2C2C2C);
    opacity: 0.82;
    /* a breath of paper behind the ink — separation over dark strokes
       without bringing the chip back */
    text-shadow: 0 0 6px rgba(240, 237, 232, 0.95), 0 0 2px rgba(240, 237, 232, 0.95);
    pointer-events: none;
}

/* the strip — ONE scrolling row per axis, never a wrapping wall (the hall
   must stay scannable); EVERY entry rides it since the shelf room retired —
   fixed spine width, sideways scroll, a part-visible card as the honest
   "there's more" cue (no tail door, no second level) */
.tana-strip {
    display: flex;
    align-items: stretch;
    gap: 16px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding: 2px 2px 10px;           /* room for focus rings + a quiet scrollbar */
    scrollbar-width: thin;
    scrollbar-color: rgba(44, 44, 44, 0.18) transparent;
}
.tana-strip::-webkit-scrollbar { height: 6px; }
.tana-strip::-webkit-scrollbar-thumb { background: rgba(44, 44, 44, 0.14); border-radius: 3px; }
.tana-strip::-webkit-scrollbar-track { background: transparent; }

/* quiet paging (T2 item 5) — hover chevrons + an edge fade, present only
   when there IS more shelf that way. Ghost circles, sumi ink; they fade in
   on row hover and vanish at the strip's edges. */
.tana-row { position: relative; }
.tana-chev {
    appearance: none;
    position: absolute;
    top: 55%;
    transform: translateY(-50%);
    width: 34px; height: 34px;
    padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid rgba(44, 44, 44, 0.12);
    border-radius: 50%;
    background: rgba(250, 250, 247, 0.94);
    color: var(--color-stone, #57534e);
    box-shadow: 0 1px 4px rgba(44, 44, 44, 0.06);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, color 0.2s ease, border-color 0.2s ease;
    z-index: 3;
}
/* a strip with nothing more to show retires its chevron for EVERY input, not
   just the mouse. display:flex above out-ranks the UA [hidden] rule, so sync()'s
   prev.hidden / next.hidden left the button rendered — and a rendered <button>
   keeps its tab stop no matter the attribute. Keyboard readers were landing on
   two dead ghost controls per shelf row, which :focus-visible below then lit up
   (that rule carries no :not([hidden]) guard, unlike the hover pair). */
.tana-chev[hidden] { display: none; }
.tana-chev svg { width: 16px; height: 16px; display: block; }
.tana-chev-l { left: -8px; }
.tana-chev-r { right: -8px; }
.tana-row:hover .tana-chev:not([hidden]),
.tana-row:focus-within .tana-chev:not([hidden]) { opacity: 1; pointer-events: auto; }
.tana-chev:hover { color: var(--color-ink, #2C2C2C); border-color: rgba(44, 44, 44, 0.26); }
.tana-chev:focus-visible { outline: 2px solid var(--color-accent, #3D5A80); outline-offset: 2px; opacity: 1; pointer-events: auto; }
/* the edge fade — the paper swallowing the clipped card, felt not read */
.tana-row::before, .tana-row::after {
    content: '';
    position: absolute;
    top: 36px; bottom: 10px;
    width: 56px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.25s ease;
    z-index: 2;
}
.tana-row::before { left: -2px;  background: linear-gradient(90deg, var(--color-paper, #F0EDE8) 10%, rgba(240, 237, 232, 0)); }
.tana-row::after  { right: -2px; background: linear-gradient(270deg, var(--color-paper, #F0EDE8) 10%, rgba(240, 237, 232, 0)); }
.tana-row.tana-more-l::before { opacity: 1; }
.tana-row.tana-more-r::after  { opacity: 1; }
.tana-strip .scard-spine {
    flex: 0 0 236px;
    min-width: 0;
}
/* compact spine density (base .scard rules ported below from the retired
   shelf room — journey-shelves.css is orphaned) */
.tana-strip .scard-spine .scard-cover { height: 104px; }
.tana-strip .scard-spine .scard-body { padding: 11px 13px 10px; gap: 2px; }
.tana-strip .scard-spine .sc-name { font-size: 13px; }
.tana-strip .scard-spine .sc-jp { font-size: 12px; }
.tana-strip .scard-spine .sc-foot { padding-top: 6px; }

/* ═══ collection SPINE CARDS — ported verbatim from the retired shelf room
   (css/journey-shelves.css .scard family) so the strips stand alone ═══ */
.scard {
    display: flex;
    flex-direction: column;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);   /* warm sumi, cards REST */
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
    animation: cardEntrance 0.6s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc(var(--card-i, 0) * 0.03s);
}
.scard:hover {
    border-color: rgba(44, 44, 44, 0.16);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(44, 44, 44, 0.06);
}
.scard:focus-visible {
    outline: 2px solid rgba(61, 90, 128, 0.55);   /* full ring — watercolor camouflages a faint one */
    outline-offset: 3px;
}
.scard-cover {
    position: relative;
    height: 128px;
    overflow: hidden;
    background: color-mix(in srgb, var(--color-paper, #F0EDE8) 94%, var(--color-ink, #2C2C2C));
}
.scard-cover img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.6s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1));
}
.scard:hover .scard-cover img { transform: scale(1.035); }
.scard-cover.scard-montage { display: flex; gap: 2px; }
.scard-montage figure { margin: 0; position: relative; overflow: hidden; }
.scard-montage .sm-main { flex: 1 1 auto; min-width: 0; height: 100%; }
.scard-montage .sm-side {
    flex: 0 0 31%;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.scard-montage .sm-side figure { flex: 1 1 50%; min-height: 0; }
/* only the MAIN painting breathes — one living print per frame */
.scard:hover .scard-montage .sm-side img { transform: none; }
.scard-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 13px 15px 12px;
}
.sc-seal {
    display: flex;
    align-items: baseline;
    gap: 5px;
    font-family: 'Inter', sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-amber-deep, #8A6E35);
    margin-bottom: 2px;
}
.sc-seal [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 11.5px;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: none;
}
.sc-seal i { font-style: italic; font-weight: 400; letter-spacing: 0.04em; text-transform: none; }
.sc-name {
    font-family: 'Inter', sans-serif;
    font-size: 14.5px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    line-height: 1.35;
}
.sc-jp {
    display: flex;
    align-items: baseline;
    gap: 7px;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    color: var(--color-stone, #57534e);
}
.sc-jp .sc-rom {
    font-family: 'Inter', sans-serif;
    font-style: italic;
    font-size: 11px;
    color: var(--text-tertiary, #8C8578);
}
.sc-foot {
    font-variant-numeric: tabular-nums;
    margin-top: auto;
    padding-top: 8px;
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* AA at 10px */
}
.sc-foot b { font-weight: 700; color: var(--color-stone, #57534e); }

/* M3 · the memory mark — a spine you have BEGUN says so, in the ledger's
   own small voice ("started · N met"). One line, faint-warm (AA at 10px),
   the number in stone. An untouched spine carries nothing: the marker
   earns its place or stays away. */
.sc-started {
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);
}
.sc-started b { font-weight: 700; color: var(--color-stone, #57534e); }
.scard-cover-kanji {
    /* warm washi under the ink paintings — never a cold gray hole (a 404'd
       side painting shows paper, not slate) */
    background: color-mix(in srgb, var(--color-paper, #F0EDE8) 96%, var(--color-amber-deep, #8A6E35));
}
.scard-cover-kanji figure {
    background: color-mix(in srgb, var(--color-paper, #F0EDE8) 96%, var(--color-amber-deep, #8A6E35));
}
.sck-glyph {
    position: absolute;
    right: 10px;
    bottom: 6px;
    z-index: 1;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-weight: 600;
    font-size: 30px;
    line-height: 1.2;
    /* brushed straight on the painting — the boxed white tag read as a UI
       chip (and 一 in it as a minus button); bare ink on washi holds */
    color: var(--color-ink, #2C2C2C);
    opacity: 0.82;
    text-shadow: 0 0 6px rgba(240, 237, 232, 0.95), 0 0 2px rgba(240, 237, 232, 0.95);
}

/* ═══ per-shelf voice (owner ask 2026-07-17) — each row speaks as what it
   IS: the spoken row a LADDER (rungs that nest), the textbook row a
   BOOKSHELF (series clusters behind washi tags), the topic row a GALLERY
   (four equal corners per world); the kanji row keeps its ink and gets its
   two authored axes back as tags. Voice through composition and honest
   information — no theming, no new color. ═══ */

/* the bookshelf's series tag — a slim washi divider opening each cluster
   (Genki · Ippo · Minna; the kanji wing's 学年 | よく見る順). The kana runs
   VERTICAL like a real spine label — a long series name never breaks
   mid-mora (みんなのにほ/んご was the horizontal failure) — while its
   reading sits horizontal at the foot, where beginner eyes land. */
.tana-sect {
    flex: 0 0 auto;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 10px;
    max-width: 106px;
    padding: 6px 4px 16px 14px;
    border-left: 1px solid rgba(44, 44, 44, 0.10);
}
.tana-sect:first-child { border-left: none; padding-left: 2px; }
.tana-sect .ts-jp {
    writing-mode: vertical-rl;
    align-self: flex-start;
    flex-shrink: 0;           /* a tight card never squeezes the column into a wrap */
    max-height: 160px;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-stone, #57534e);
    letter-spacing: 0.14em;   /* vertical air between kana */
    line-height: 1.3;
}
.tana-sect .ts-foot { display: flex; flex-direction: column; gap: 3px; }
.tana-sect .ts-rom {
    font-family: 'Inter', sans-serif;
    font-style: italic;
    font-size: 10px;
    letter-spacing: 0.04em;
    color: var(--text-tertiary, #8C8578);
}
.tana-sect .ts-en {
    font-family: 'Inter', sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* AA at 9px caps on paper */
    line-height: 1.5;
}

/* the ladder's nesting line — the one fact a learner can't derive from
   the wall: each spoken rung HOLDS the rung before it (progress carries;
   choosing "further" never abandons the road walked). Plain roman — the
   italic register belongs to romaji alone. */
.sc-nest {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    color: var(--color-faint-warm, #6E6860);
}

/* the gallery's four corners — a topic is a world with no single hero, so
   its panes hang EQUAL (2×2), a touch taller than the hero-montage rows:
   the row earns its own silhouette. No pane breathes on hover — with no
   hero there is no one living print to single out. */
.scard-cover.scard-mosaic {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 2px;
}
/* the height rides the ROW, not the mosaic class — a young topic's
   montage FALLBACK stands as tall as its mosaic siblings (critique:
   a 104px cover next to 132px ones would break the row's silhouette) */
.tana-row-topic .tana-strip .scard-spine .scard-cover { height: 132px; }
.scard-mosaic figure { margin: 0; position: relative; overflow: hidden; min-width: 0; min-height: 0; }
.scard:hover .scard-mosaic img { transform: none; }

/* ＋ make your own — the bench's home door: quiet ghost line in the
   hall-kura voice, never a boxed CTA */
.hall-make {
    grid-column: 1 / -1;
    margin: 6px var(--wall-pad, 8px) 0;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
.hall-make-btn {
    appearance: none;
    box-shadow: none;
    background: transparent;
    border: 1px dashed rgba(44, 44, 44, 0.18);
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 11px 18px;
    cursor: pointer;
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 500;
    color: var(--color-stone, #57534e);
    transition: border-color 0.25s ease, color 0.25s ease, background 0.25s ease;
}
.hall-make-btn:hover, .hall-make-btn:active {
    border-color: rgba(44, 44, 44, 0.34);
    color: var(--color-ink, #2C2C2C);
    background: rgba(140, 133, 120, 0.05);
}
.hall-make-btn:focus-visible {
    outline: 2px solid rgba(61, 90, 128, 0.55);
    outline-offset: 3px;
}
.hall-make-btn .hm-plus {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 15px;
    line-height: 1;
    color: var(--color-amber-deep, #8A6E35);
}

/* ═══ THE WALL'S FOOT (§A1d) — the signed threshold at the room's exit:
   one fading rule (the wall's own line language), then the two 蔵 doors on
   a shared baseline with honest air above. ═══ */
.hall-foot {
    grid-column: 1 / -1;
    margin: 44px var(--wall-pad, 8px) 72px;
    padding-top: 26px;
    position: relative;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
    /* two reference doors since the gallery toggle retired: words + kanji */
    display: flex;
    align-items: baseline;
    gap: 34px;
    flex-wrap: wrap;
}
.hall-foot::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg,
        rgba(44, 44, 44, 0.10) 0%,
        rgba(44, 44, 44, 0.07) 55%,
        transparent 96%);
}
.hall-kura {
    appearance: none;
    box-shadow: none;
    background: transparent;
    border: none;
    display: inline-flex;
    align-items: baseline;
    gap: 9px;
    padding: 8px 10px;
    margin-left: -10px;      /* the text aligns with the wall's own edge */
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.25s ease;
}
.hall-kura:hover, .hall-kura:active { background: rgba(140, 133, 120, 0.08); }
.hall-kura:focus-visible { outline: 2px solid rgba(61, 90, 128, 0.55); outline-offset: 2px; }
.hall-kura [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 15px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.02em;
    font-feature-settings: 'palt' 1;
}
.hall-kura .hk-en {
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    color: var(--color-stone, #57534e);
}
.hall-kura .hk-arrow {
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    color: var(--color-stone, #57534e);
    transition: transform 0.3s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)), color 0.2s ease;
    display: inline-block;
}
.hall-kura:hover .hk-en { color: var(--color-ink, #2C2C2C); }
.hall-kura:hover .hk-arrow { transform: translateX(3px); color: var(--color-accent, #3D5A80); }

/* ═══ the shelf colophon on a hanging — "from the shelf · Genki 1" ═══ */
.jhang-prov {
    font-family: 'Inter', sans-serif;
    font-size: 10.5px;
    font-style: italic;
    letter-spacing: 0.02em;
    color: var(--color-faint-warm, #6E6860);   /* small-text faint that holds AA */
}
.home-hall-root .gf-placard .jhang-prov { margin-top: 10px; }

/* ═══ 常設 · THE PERMANENT ROOMS — doors, not journeys ═══
   Wide and horizontal where journeys are tall; no nails, no progress
   hairline; ENTER/BROWSE/PRACTICE verbs. A door shows a glimpse of its room. */
.genkan-doors {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 20px;
    margin: 0 var(--wall-pad, 8px) 72px;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
}
.gdoor {
    display: flex;
    align-items: stretch;
    min-height: 150px;
    background: var(--color-card, #FAFAF7);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);   /* warm sumi, never cold black */
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.gdoor:hover {
    border-color: rgba(44, 44, 44, 0.16);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(44, 44, 44, 0.06);
}

/* The glimpse through the door; the inset shadow along the right edge is the
   wall's thickness — the depth cue that makes a panel read as an OPENING.
   On hover the window widens a crack — the shared threshold gesture. */
.gdoor-art {
    flex: 0 0 134px;
    position: relative;
    overflow: hidden;
    background: color-mix(in srgb, var(--color-paper, #F0EDE8) 94%, var(--color-ink, #2C2C2C));
    border-right: 1px solid rgba(44, 44, 44, 0.06);
    box-shadow: inset -5px 0 6px -6px rgba(44, 44, 44, 0.14);
    transition: flex-basis 0.45s var(--ease-settle, cubic-bezier(0.22, 1, 0.36, 1));
}
.gdoor:hover .gdoor-art { flex-basis: 148px; }

/* Collection — a sliver of the real wall: two stacked thumbnails drifting
   one after the other (60ms apart), a wall passing behind a doorway. */
.gdoor-art-thumbs { display: flex; flex-direction: column; height: 100%; }
.gdoor-art-thumbs img {
    flex: 1 1 50%;
    width: 100%;
    min-height: 0;
    object-fit: cover;
    display: block;
    transition: transform 0.6s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1));
}
.gdoor-art-thumbs img + img { transition-delay: 60ms; }
.gdoor:hover .gdoor-art-thumbs img { transform: scale(1.05); }

/* Kanji wing — ONE standing ink form, whole and unhurried; an echo behind. */
.gdoor-art-ink { position: relative; height: 100%; }
.gdoor-art-ink .gk-hero {
    position: absolute;
    right: 14px;
    bottom: 16px;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 72px;
    font-weight: 600;
    line-height: 1;
    color: var(--color-ink, #2C2C2C);
    opacity: 0.8;
    transition: opacity 0.35s ease;
    pointer-events: none;
}
.gdoor-art-ink .gk-echo {
    position: absolute;
    top: 12px;
    left: 14px;
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 20px;
    line-height: 1;
    color: var(--color-ink, #2C2C2C);
    opacity: 0.26;
    transition: opacity 0.35s ease;
    pointer-events: none;
}
.gdoor:hover .gk-hero { opacity: 0.92; }
.gdoor:hover .gk-echo { opacity: 0.4; }

/* Practice hall — the tutor's resting orb: one quiet breathing circle with a
   soft outer halo. Hover wakes it a shade. */
.gdoor-art-orb { height: 100%; display: flex; align-items: center; justify-content: center; }
.gdoor-art-orb i {
    position: relative;
    width: 60px; height: 60px;
    border-radius: 50%;
    background: radial-gradient(circle at 38% 34%,
        color-mix(in srgb, var(--color-accent, #3D5A80) 38%, var(--color-paper, #F0EDE8)),
        color-mix(in srgb, var(--color-accent, #3D5A80) 14%, var(--color-paper, #F0EDE8)) 72%);
    border: 1px solid color-mix(in srgb, var(--color-accent, #3D5A80) 34%, transparent);
    animation: gdoorBreathe 5.5s ease-in-out infinite;
    transition: border-color 0.35s ease, filter 0.35s ease;
}
.gdoor-art-orb i::after {
    content: '';
    position: absolute;
    inset: -9px;
    border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--color-accent, #3D5A80) 14%, transparent);
    transition: inset 0.35s ease, border-color 0.35s ease;
}
.gdoor:hover .gdoor-art-orb i {
    border-color: color-mix(in srgb, var(--color-accent, #3D5A80) 50%, transparent);
    filter: saturate(1.15);
}
.gdoor:hover .gdoor-art-orb i::after {
    inset: -12px;
    border-color: color-mix(in srgb, var(--color-accent, #3D5A80) 22%, transparent);
}
@keyframes gdoorBreathe {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.07); }
}

.gdoor-body {
    flex: 1;
    min-width: 0;
    padding: 18px 20px 16px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.gdoor-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 20px;
    font-weight: 600;
    color: var(--color-ink, #2C2C2C);
    letter-spacing: 0.02em;
    line-height: 1.25;
}
.gdoor-romaji {
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    font-style: italic;
    color: var(--color-amber-deep, #8A6E35);
}
.gdoor-en {
    margin-top: 3px;
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--color-stone, #57534e);
}
.gdoor-ledger {
    margin-top: auto;
    padding-top: 8px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-faint-warm, #6E6860);   /* 10px caps holds AA */
}
.gdoor-ledger b { font-weight: 700; color: var(--color-stone, #57534e); }
.gdoor-ledger span { white-space: nowrap; }   /* wrap between segments, never inside one */
.gdoor-verb {
    margin-top: 5px;
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--color-ink, #2C2C2C);
    transition: color 0.2s ease;
}
.gdoor-verb [lang="ja"] {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 12px;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0.04em;
}
.gdoor-verb .gdoor-arrow {
    font-family: 'Inter', sans-serif;
    transition: transform 0.3s var(--ease-out-expo, cubic-bezier(0.19,1,0.22,1));
    display: inline-block;
}
.gdoor:hover .gdoor-verb { color: var(--color-accent, #3D5A80); }
.gdoor:hover .gdoor-verb .gdoor-arrow { transform: translateX(3px); }

/* ── the hall's quiet toast (grade-echo voice) ── */
.hall-toast {
    position: fixed;
    left: 50%;
    bottom: 34px;
    transform: translateX(-50%);
    background: var(--color-ink, #2C2C2C);
    color: var(--color-card, #FAFAF7);
    font-family: 'Inter', sans-serif;
    font-size: 12.5px;
    padding: 9px 18px;
    border-radius: 4px;
    box-shadow: 0 2px 10px rgba(44, 44, 44, 0.14);
    z-index: 9600;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
}
.hall-toast.show { opacity: 0.94; }
.hall-toast[hidden] { display: none; }

/* ═══ THE JOURNEY IS A PLACE (owner ruling 2026-07-04) — its name never
   wears filter grammar. The beam speaks two rows (owner refinement):
   ROW 1 = actions — centre holds Browse|Study alone, no hairline.
   ROW 2 = the room's CONTEXT line (#browseSubrow): the name-board
   (#journeyScopePill) LEADS it, always visible at any scroll depth; the
   counts follow. (#journeyTitleWall retired, nav rethink 2026-07-16 — the
   pill is the room's one announcement.) Leaving is place language, never
   an ✕. Old id/classes kept so the kanji-wing exemptions and walk suites
   stay anchored. ═══ */
.journey-scope-pill {
    appearance: none;
    border: none;
    background: transparent;
    box-shadow: none;
    padding: 0;
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    max-width: min(340px, 24vw);
    font-family: 'Inter', sans-serif;
    white-space: nowrap;
    cursor: pointer;
    /* set apart from the counts that follow — a little extra air, no ink */
    margin-right: 10px;
}
.journey-scope-pill:hover { transform: none; box-shadow: none; background: transparent; }
/* A book scope carries its place phrase — wider room, and the phrase itself
   truncates before it ever pushes the deck counts (one line, always). */
.journey-scope-pill--book { max-width: min(560px, 40vw); }
.journey-scope-pill .jsp-place {
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--color-text-secondary, #57534e);
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 300px;
}
.journey-scope-pill:focus-visible { outline: 1.5px solid rgba(61, 90, 128, 0.45); outline-offset: 3px; border-radius: 4px; }
.journey-scope-pill .jsp-jp {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 12px;
    color: var(--color-amber-deep, #8A6E35);
    line-height: 1;
}
.journey-scope-pill .jsp-romaji {
    font-size: 9.5px;
    font-style: italic;
    color: var(--color-amber-deep, #8A6E35);
    margin-left: -3px;
}
.journey-scope-pill .jsp-name {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.1px;
    color: var(--color-ink, #2C2C2C);
    overflow: hidden;
    text-overflow: ellipsis;
}
/* ("← every word" retired 2026-07-04 — leaving a room is level 0's job;
   the brand leads home, the hall's 蔵 doors hold every sideways move.) */

/* (The title wall — 道 seal + 27px name + counts before .grid-cards — is
   RETIRED, nav rethink owner-approved 2026-07-16: the beam pill names the
   room at every scroll depth; the wall opens on 今日の一枚.) */

/* (The Words|Kanji toggle retired 2026-07-04 — level 0 owns the library
   choice; no journey-scoped hiding left to do on row 1.) */
/* Inside a KANJI journey the popularity facet steps out of the +Filter panel:
   the journey IS the popularity slice, and the browse chip's "Top 100" means
   something else (kanji from the top-100 WORDS ≈ 19) than the journey's
   "Top 100 kanji" (the first 100 of the path) — two contradictory numbers
   under one label. Grade and structure-type facets stay: they still answer
   real questions within the journey. (kanji-path-active ∧ journey-scoped can
   only be a kanji journey — a word scope never coexists with the kanji wall.) */
body.journey-scoped.kanji-path-active #sidebarKFreq { display: none !important; }
/* Defense-in-depth from PR 2, sharpened for PR 4: the scope's name-board
   only shows on the wall it actually narrows. A WORD scope means nothing on
   the kanji wall; a KANJI scope (--kanji, the kanji journey's own wing)
   means nothing on the word wall. (The title wall left this pair when it
   was retired, nav rethink 2026-07-16.) */
body.kanji-path-active .journey-scope-pill:not(.journey-scope-pill--kanji):not(.reference-board) { display: none; }
body:not(.kanji-path-active) .journey-scope-pill--kanji { display: none; }

/* ═══ KEYBOARD — every walkable piece answers focus. Image-backed pieces
   get the FULL ring (2px/0.55): a 1.5px 45% line camouflages against
   watercolor; the offset gap onto the paper wall is the halo. ═══ */
.jhang:focus-visible {
    outline: 2px solid rgba(61, 90, 128, 0.55);
    outline-offset: 4px;
    border-radius: 6px;
}
.gdoor:focus-visible, .hall-start:focus-visible {
    outline: 2px solid rgba(61, 90, 128, 0.55);
    outline-offset: 3px;
}

/* Honor reduced motion: no entrance stagger, no breathing, doors stay still. */
@media (prefers-reduced-motion: reduce) {
    .jhang, .wall-section, .genkan-doors, .hall-firstrun,
    .tana-rows, .hall-foot, .hall-start, .hall-or, .hall-make,
    .scard { animation: none; }
    .scard:hover { transform: none; }
    .scard:hover .scard-cover img { transform: none; }
    .scard-cover img { transition: none; }
    .home-hall-root.hall-arrive { animation: none; }
    .home-hall-root.hall-leaving { transition: none; }
    .hall-pop { animation: none; }
    .gf-begin .gf-begin-arrow { transition: none; }
    .gf-begin:hover .gf-begin-arrow { transform: none; }
    .hall-start:hover { transform: none; }
    .jhang:hover .grid-card-back-image img,
    .home-hall-root .grid-feature:hover .gf-art img,
    .hall-start:hover .hs-art .hs-img,
    .gdoor:hover .gdoor-art-thumbs img,
    .tdoor:hover .tdoor-art-pic img { transform: none; }
    .gdoor-art { transition: none; }
    .gdoor:hover .gdoor-art, .tdoor:hover .gdoor-art { flex-basis: 134px; }
    .gdoor-art-thumbs img, .tdoor-art-pic img { transition: none; }
    .gdoor-art-orb i { animation: none; transition: none; }
    .gdoor-verb .gdoor-arrow { transition: none; }
    .hall-kura:hover .hk-arrow { transform: none; }
    .hall-kura .hk-arrow { transition: none; }
    .hall-books { animation: none; }
}

/* ── 本棚 the bookshelf — one serial book, one quiet card (story spine SS2).
   A paper card with a book-spine left edge; the spine warms to gold only
   while the book is OPEN (scarcity gives the accent meaning). ─────────── */
.hall-books {
    position: relative;
    background: var(--color-card);
    border: 1px solid rgba(44, 44, 44, 0.07);
    border-left: 3px solid rgba(44, 44, 44, 0.14);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(44, 44, 44, 0.04);
    padding: 22px 26px 20px;
    cursor: pointer;
    animation: cardEntrance 0.7s var(--ease-out-expo, cubic-bezier(0.19, 1, 0.22, 1)) backwards;
    animation-delay: calc((var(--card-i, 0) + 1) * 0.05s);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.hall-books:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(44, 44, 44, 0.06);
}
.hall-books:focus-visible {
    outline: 2px solid var(--color-accent, #3D5A80);
    outline-offset: 2px;
}
.hall-books--open {
    border-left-color: var(--color-gold, #C9A96E);
}
.hb-eyebrow {
    font-size: 10.5px;
    letter-spacing: 0.14em;
    color: var(--color-faint-warm, #6E6860);
    margin-bottom: 10px;
}
.hb-eyebrow [lang="ja"] { letter-spacing: 0.2em; }
.hb-title {
    font-family: 'Klee One', 'Noto Sans JP', sans-serif;
    font-size: 30px;
    line-height: 1.25;
    color: var(--color-ink, #2C2C2C);
}
.hb-sub {
    font-size: 12.5px;
    color: var(--color-stone, #57534e);
    margin: 3px 0 14px;
}
.hb-state {
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--color-ink, #2C2C2C);
}
.hb-tease {
    font-size: 12.5px;
    color: var(--color-stone, #57534e);
    font-style: italic;
    margin-top: 3px;
}
.hb-action {
    margin-top: 14px;
    display: flex;
    align-items: center;
    gap: 14px;
}
.hb-cta {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-accent, #3D5A80);
}
.hb-open-mark {
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-amber-deep, #8A6E35);
}
.hb-putback {
    font: inherit;
    font-size: 12px;
    color: var(--color-faint-warm, #6E6860);
    background: none;
    border: none;
    padding: 2px 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.hb-putback:hover { color: var(--color-ink, #2C2C2C); }
