/* =========================================================================
   REOL — the entry gate and the shopkeeper's parlour
   -------------------------------------------------------------------------
   Loaded only by the two pages that use it: the home page while the gate is
   still being offered, and /shopkeeper.

   Everything here is scoped under .gate or .parlour-page. That matters: these
   are the only dark surfaces in the site, and they are dark because they are a
   *place* — a shop after hours, lit for one customer — not because there is a
   dark theme. Nothing in this file may leak into the storefront.

   Values come from tokens.css, including the night palette and the four door
   accents. There are no literals below except geometry.
   ========================================================================= */

/* =========================================================================
   1. The gate — two ways in, over the home page
   ========================================================================= */

.gate {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: grid;
    place-items: center;
    padding: var(--gutter);
    overflow-y: auto;
    background:
        radial-gradient(120% 90% at 50% -10%, var(--night-soft), transparent 60%),
        var(--night);
    animation: gate-in var(--slow) var(--ease-out) both;
}

@keyframes gate-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.gate__inner {
    width: min(1040px, 100%);
    text-align: center;
    color: var(--night-text);
}

.gate__mark {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--gold-400);
}

.gate__title {
    margin-top: var(--space-4);
    font-family: var(--font-display);
    font-size: clamp(var(--text-3xl), 7vw, var(--text-5xl));
    font-weight: 300;
    line-height: var(--leading-tight);
}

.gate__sub {
    margin-top: var(--space-3);
    color: var(--night-muted);
    font-size: var(--text-md);
}

.gate__choices {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);
    margin-top: var(--space-7);
    text-align: left;
}

.gate__choice { display: flex; }

.gate__button {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-6);
    border: 1px solid var(--night-line);
    border-radius: var(--radius-lg);
    background: linear-gradient(160deg, var(--night-raised), var(--night));
    color: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--normal) var(--ease),
                transform var(--normal) var(--ease-out),
                box-shadow var(--normal) var(--ease);
}

.gate__button:hover,
.gate__button:focus-visible {
    border-color: var(--gold);
    transform: translateY(-3px);
    box-shadow: var(--shadow-lg);
}

.gate__icon {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border: 1px solid var(--night-line);
    border-radius: var(--radius-full);
    color: var(--gold-400);
}

.gate__label {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    line-height: var(--leading-snug);
}

.gate__note {
    color: var(--night-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

.gate__go {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: auto;
    padding-top: var(--space-3);
    color: var(--gold-400);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
}

.gate__choice--feature .gate__button {
    border-color: var(--gold-800);
    background:
        radial-gradient(90% 120% at 100% 0%, rgba(201, 169, 97, 0.16), transparent 62%),
        linear-gradient(160deg, var(--night-raised), var(--night));
}

.gate__foot {
    margin-top: var(--space-6);
    color: var(--night-muted);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
}

@media (max-width: 780px) {
    .gate__choices { grid-template-columns: 1fr; }
    .gate__button  { padding: var(--space-5); }
}

/* =========================================================================
   2. The parlour — page shell
   ========================================================================= */

.parlour-page {
    position: relative;
    isolation: isolate;
    /* The room is the whole window: no header above it, no footer under it,
       and enough height that the shopkeeper is never the top half of
       something else. */
    min-height: 100vh;
    min-height: 100dvh;
    display: grid;
    align-items: center;
    padding: calc(var(--space-6) + 2.5rem) var(--gutter) var(--space-6);
    /* The ground the room is painted on. It lives here rather than in the
       ambience layer because that layer now sits *above* the room: an opaque
       base up there would have hidden the arcade completely. */
    background: linear-gradient(180deg, var(--night-raised), var(--night) 45%);
    color: var(--night-text);
}

/* The only two links in the room: the way out, and the way on. */
.parlour-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-5) var(--gutter);
}

.parlour-bar__mark {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    letter-spacing: var(--tracking-label);
    color: var(--night-text);
    opacity: 0.75;
    transition: opacity var(--fast) var(--ease);
}

.parlour-bar__mark span {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--night-muted);
}

.parlour-bar__mark:hover { opacity: 1; }

.parlour-bar__bag {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--night-line);
    border-radius: var(--radius-full);
    color: var(--night-muted);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}

.parlour-bar__bag:hover { border-color: var(--gold); color: var(--gold-400); }

/* Zero in the bag is not worth a badge. */
.parlour-bar__bag [data-count="0"] { display: none; }

/* -- the room behind everything ---------------------------------------
   A backdrop, and priced like one: it sits under the ambience layer so the
   vignette still closes over it, and it is dim enough that the counter and
   the stage remain the only things with real contrast. */

.parlour-room {
    position: absolute;
    inset: 0;
    z-index: -2;
    /* -2 is under the ambience (-1) and over .parlour-page's own ground. */
    width: 100%;
    height: 100%;
    pointer-events: none;
    /*It is the room, not the subject. Anything brighter and the arcade's
       arches argue with the doors' arches instead of standing behind them. */
    opacity: 0.28;
}

.pr-arch          { fill: none; stroke: var(--gold); stroke-width: 2.4; opacity: .55; }
.pr-screen        { opacity: .3; }
.pr-lattice       { fill: none; stroke: var(--gold); stroke-width: 1.1; }
.pr-lattice-dot   { fill: var(--gold); }
.pr-stone         { fill: var(--gold); opacity: .55; }

.pr-floor         { stroke: var(--gold); stroke-width: 2; fill: none; opacity: .45; }
.pr-floor-faint   { stroke-width: 1; opacity: .5; }
.pr-plinth        { fill: var(--night-raised); opacity: .55; }
.pr-plinth-joint  { fill: none; stroke: var(--gold); stroke-width: 1; opacity: .22; }

.pr-lamp          { opacity: .8; }
.pr-chain         { stroke: var(--gold); stroke-width: 2; fill: none; }
.pr-shade         { fill: var(--night-soft); stroke: var(--gold-400); stroke-width: 2; }
.pr-shade-band    { stroke: var(--gold-400); stroke-width: 1.4; opacity: .8; fill: none; }
.pr-flame         { fill: var(--gold-400); }
.pr-glow-in       { stop-color: var(--gold-400); stop-opacity: .5; }
.pr-glow-out      { stop-color: var(--gold-400); stop-opacity: 0; }

.pr-stacks        { opacity: .5; }
.pr-bolt-a        { fill: var(--wine); }
.pr-bolt-b        { fill: var(--wine-600); }
.pr-bolt-c        { fill: var(--door-modern); }

/* The lamp over the counter, the shaft of light it throws, and the vignette
   that puts everything else in shadow. Purely atmospheric — hidden from
   assistive technology, and gradients rather than images, because the whole
   project ships without an asset pipeline. */
.parlour-page__ambience {
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        radial-gradient(60% 45% at 22% 0%, var(--lamp-gold), transparent 70%),
        radial-gradient(70% 60% at 85% 20%, var(--lamp-wine), transparent 72%),
        /* the vignette: darkness closing in at the edges of the room */
        radial-gradient(120% 90% at 50% 30%, transparent 45%, var(--night) 100%);
}

/* Light falling from somewhere off to the left, and the dust that drifts
   through it. Two elements, no images, no JavaScript. */
.parlour-page__ambience::before,
.parlour-page__ambience::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.parlour-page__ambience::before {
    background: linear-gradient(103deg, transparent 12%, var(--lamp-shaft) 20%,
                                transparent 30%, transparent 62%,
                                var(--lamp-shaft) 68%, transparent 78%);
    animation: shaft-drift 26s var(--ease) infinite alternate;
}

/* Motes: one radial gradient per speck, tiled and drifting upward. */
.parlour-page__ambience::after {
    background-image:
        radial-gradient(1.5px 1.5px at 18% 30%, var(--mote), transparent),
        radial-gradient(1px 1px at 42% 72%, var(--mote), transparent),
        radial-gradient(1.5px 1.5px at 67% 21%, var(--mote), transparent),
        radial-gradient(1px 1px at 81% 58%, var(--mote), transparent),
        radial-gradient(1px 1px at 32% 88%, var(--mote), transparent),
        radial-gradient(1.5px 1.5px at 92% 84%, var(--mote), transparent);
    background-size: 42rem 34rem;
    animation: motes-rise 38s linear infinite;
}

@keyframes shaft-drift {
    from { transform: translateX(-2%) skewX(0deg); opacity: 0.7; }
    to   { transform: translateX(2%) skewX(-1.5deg); opacity: 1; }
}

@keyframes motes-rise {
    from { background-position: 0 0; }
    to   { background-position: 3rem -34rem; }
}

.parlour {
    display: grid;
    grid-template-columns: minmax(0, 23rem) minmax(0, 1fr);
    gap: var(--space-7);
    align-items: center;
    width: 100%;
    max-width: var(--container-wide);
    margin-inline: auto;
}

.parlour__counter {
    position: relative;
    /* The room is one screen, so the counter scrolls inside itself rather
       than pushing the doors off the bottom of it. */
    max-height: calc(100dvh - 9rem);
    overflow-y: auto;
    scrollbar-width: thin;
    padding: var(--space-5);
    border: 1px solid var(--night-line);
    border-radius: var(--radius-lg);
    background: linear-gradient(180deg, var(--night-raised), var(--night));
}

/* The same gold brackets the piece frame uses, so the counter and what is set
   down on it are recognisably parts of one room rather than two components
   that happen to be next to each other. Drawn on the scroll container's
   padding box, which is why they ride with the content and not the viewport —
   the alternative is brackets that detach the moment the transcript is long
   enough to scroll. */
.parlour__counter::before,
.parlour__counter::after {
    content: '';
    position: absolute;
    width: 1.6rem;
    height: 1.6rem;
    border: 1px solid var(--gold-800);
    opacity: .55;
    pointer-events: none;
}

.parlour__counter::before {
    top: var(--space-3); left: var(--space-3);
    border-right: 0;
    border-bottom: 0;
}

.parlour__counter::after {
    right: var(--space-3); bottom: var(--space-3);
    border-left: 0;
    border-top: 0;
}

.parlour__room { min-width: 0; }

/* =========================================================================
   3. The shopkeeper himself
   ========================================================================= */

.keeper {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--night-line);
}

/* He is the largest thing on his side of the room, lit from above, breathing
   very slightly so the counter never looks like a screenshot. */
.keeper__figure {
    display: block;
    width: 100%;
    color: var(--gold-400);
    animation: keeper-breathe 7s var(--ease) infinite;
}

.keeper__art {
    display: block;
    width: 100%;
    max-width: 15rem;
    margin-inline: auto;
    /* The lamp is above and slightly left, so the drawing carries its own
       warm cast rather than sitting flat on the panel. */
    filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.5));
}

/* Stacked, not side by side: the drawing is a portrait now, not an avatar. */
.keeper {
    display: block;
    text-align: center;
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--night-line);
}

.keeper__id {
    display: flex;
    flex-direction: column;
    margin-top: var(--space-3);
}

/* -- the miniature's palette ------------------------------------------
   The portrait's SVG carries shape only; every fill it uses is named here so
   the pigments live with the rest of the palette rather than inside a
   template. Flat colour throughout — a miniature has no modelling, and the
   moment one of these becomes a gradient the whole thing looks like a logo. */

.mk-mount      { fill: var(--night-raised); stroke: var(--gold-800); stroke-width: 2; }
.mk-rule       { fill: none; stroke: var(--gold); stroke-width: 1; opacity: .65; }

.mk-niche      { fill: var(--night-soft); }
.mk-niche-edge { fill: none; stroke: var(--gold); stroke-width: 2.5; }
.mk-jaali      { fill: none; stroke: var(--gold); stroke-width: 1; opacity: .45; }
.mk-jaali-dot  { fill: var(--gold); opacity: .3; }
.mk-lamp-in    { stop-color: var(--gold-400); stop-opacity: .26; }
.mk-lamp-out   { stop-color: var(--gold-400); stop-opacity: 0; }

.mk-nimbus      { fill: var(--gold-400); opacity: .17; }
.mk-nimbus-edge { fill: none; stroke: var(--gold-400); stroke-width: 1.1; opacity: .55; }

.mk-jama   { fill: var(--wine); }
.mk-seam   { fill: none; stroke: var(--wine-900); stroke-width: 2; }
.mk-piping { fill: none; stroke: var(--gold-400); stroke-width: 1.2; opacity: .45; }
.mk-buti   { fill: var(--gold-400); opacity: .5; }

/* The sleeve is a stroke rather than a shape, so the buti has to be stroked
   over it in a second pass with the same geometry. */
.mk-sleeve      { fill: none; stroke: var(--wine); stroke-width: 17; stroke-linecap: round; }
.mk-sleeve-buti { fill: none; stroke: url(#buti); stroke-width: 17; stroke-linecap: round; }

.mk-skin    { fill: var(--mk-skin); }
.mk-shade   { fill: var(--mk-skin-shade); opacity: .4; }
.mk-fingers { fill: none; stroke: var(--mk-skin-shade); stroke-width: .9; opacity: .5; }
.mk-ear     { fill: none; stroke: var(--mk-skin-shade); stroke-width: 2.2; stroke-linecap: round; }
.mk-collar  { fill: none; stroke: var(--ivory-warm); stroke-width: 4; }

.mk-hair      { fill: var(--mk-hair); }
.mk-brow      { fill: none; stroke: var(--mk-hair); stroke-width: 2.4; stroke-linecap: round; }
.mk-eye-white { fill: var(--ivory-warm); }
.mk-pupil     { fill: var(--ink); }
.mk-lash      { fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round; }

.mk-turban      { fill: var(--ivory-warm); }
.mk-wrap        { fill: none; stroke: var(--gold); stroke-width: 1.5; opacity: .9; }
.mk-jewel       { fill: var(--gold-400); }
.mk-jewel-stone { fill: var(--wine); }
.mk-turra       { fill: var(--wine-600); }
.mk-turra-edge  { fill: none; stroke: var(--gold-400); stroke-width: 1.2; }

.mk-counter-top  { fill: var(--gold-400); }
.mk-counter      { fill: var(--wine-800); }
.mk-counter-line { fill: none; stroke: var(--gold-800); stroke-width: 1; opacity: .8; }
.mk-bolt-a       { fill: var(--wine-600); }
.mk-bolt-b       { fill: var(--door-modern); }
.mk-bolt-fold    { fill: none; stroke: var(--gold-400); stroke-width: 1; opacity: .6; }
.mk-bolt-fold-b  { fill: none; stroke: var(--gold-100); stroke-width: .9; opacity: .5; }

@keyframes keeper-breathe {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}

/* A carved band — a rosette between two tendrils. See ornament-band.php for
   why this is drawn rather than ruled. */
.ornament {
    display: block;
    width: 100%;
    height: 1.5rem;
    margin-top: var(--space-5);
    overflow: visible;
}

.or-rule    { fill: none; stroke: var(--gilt); stroke-width: 1; }
.or-vine    { fill: none; stroke: var(--gold-800); stroke-width: 1.1; stroke-linecap: round; }
.or-rosette { fill: none; stroke: var(--gold); stroke-width: 1.1; opacity: .85; }
.or-eye     { fill: var(--gold-400); }

.keeper__id { display: flex; flex-direction: column; }

.keeper__name {
    font-family: var(--font-display);
    font-size: var(--text-lg);
}

.keeper__where {
    font-size: var(--text-xs);
    /* Wide, not the full label tracking — "At the front of the shop" has to
       stay on one line beside the figure. */
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--gold-400);
}

.keeper__speech {
    position: relative;
    margin-top: var(--space-5);
    padding-left: var(--space-5);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-style: italic;
    line-height: var(--leading-snug);
    color: var(--night-text);
    transition: opacity var(--normal) var(--ease),
                transform var(--normal) var(--ease-out);
}

/* An opening quotation mark, set in the display face and hung in the margin —
   it marks the line as speech without a comic-book bubble around it. */
.keeper__speech::before {
    content: '\201C';
    position: absolute;
    top: -0.5rem;
    left: -0.1rem;
    font-size: var(--text-3xl);
    line-height: 1;
    color: var(--gold-800);
}

/* Set while a turn is in flight, so he visibly pauses before answering
   instead of the sentence swapping under the cursor. */
.keeper__speech.is-changing {
    opacity: 0;
    transform: translateY(6px);
}

/* -- what he is working to -------------------------------------------- */

.brief-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-4);
    list-style: none;
}

.brief-chip {
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--gold-800);
    border-radius: var(--radius-full);
    color: var(--gold-400);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
}

/* -- transcript -------------------------------------------------------- */

.transcript {
    max-height: 15rem;
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--night-line);
    overflow-y: auto;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    /* Fades the overflow instead of guillotining a sentence — the scroll is
       then obviously a scroll rather than a rendering fault. */
    /* currentColor rather than a literal — a mask reads the alpha only. */
    mask-image: linear-gradient(180deg, transparent, currentColor 1.5rem);
    scrollbar-width: thin;
}

.transcript__line { margin-bottom: var(--space-2); }

.transcript__line--him {
    color: var(--night-muted);
}

.transcript__line--you {
    padding-left: var(--space-3);
    border-left: 2px solid var(--wine-400);
    color: var(--night-text);
}

/* -- the shortlist on the counter -------------------------------------- */

.counter-rail {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--night-line);
}

.counter-rail__head {
    display: flex;
    justify-content: space-between;
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--gold-400);
}

.counter-rail__list {
    margin-top: var(--space-3);
    list-style: none;
}

/* Shortlisted pieces hang off the rail like paper tags: a hairline "string"
   down the left, and a punched hole at each stop. */
.counter-rail__list {
    position: relative;
    padding-left: var(--space-4);
}

.counter-rail__list::before {
    content: '';
    position: absolute;
    top: 0.4rem;
    bottom: 1.2rem;
    left: 0.28rem;
    width: 1px;
    background: var(--gold-800);
}

.counter-rail__list a {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    color: inherit;
    position: relative;
}

.counter-rail__list a::before {
    content: '';
    position: absolute;
    top: 50%;
    left: calc(var(--space-4) * -1 + 0.13rem);
    width: 0.32rem;
    height: 0.32rem;
    margin-top: -0.16rem;
    border-radius: var(--radius-full);
    background: var(--gold-400);
}

.counter-rail__list img {
    width: 2.75rem;
    height: 3.5rem;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

.counter-rail__list span {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.counter-rail__list strong {
    font-weight: 400;
    font-size: var(--text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.counter-rail__list em {
    font-style: normal;
    font-size: var(--text-xs);
    color: var(--gold-400);
}

.counter-rail__list a:hover strong { color: var(--gold-400); }

/* -- exits -------------------------------------------------------------- */

.parlour__exits {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    align-items: flex-start;
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--night-line);
}

.parlour-page .link-quiet,
.gate .link-quiet {
    background: none;
    border: 0;
    padding: 0;
    color: var(--night-muted);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    cursor: pointer;
    transition: color var(--fast) var(--ease);
}

.parlour-page .link-quiet:hover { color: var(--gold-400); }

/* =========================================================================
   4. The stage — shared furniture
   ========================================================================= */

/* Each new stage is uncovered rather than faded in — the cloth comes off. */
.stage { animation: stage-reveal var(--slow) var(--ease-out) both; }

@keyframes stage-reveal {
    from {
        opacity: 0;
        clip-path: inset(0 0 100% 0);
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        clip-path: inset(0 0 0 0);
        transform: none;
    }
}

.stage__eyebrow {
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--gold-400);
}

.stage__title {
    margin-top: var(--space-3);
    font-family: var(--font-display);
    font-size: clamp(var(--text-2xl), 4.5vw, var(--text-4xl));
    font-weight: 300;
    line-height: var(--leading-tight);
}

.stage__note {
    max-width: 46ch;
    margin-top: var(--space-4);
    color: var(--night-muted);
    line-height: var(--leading-normal);
}

.stage__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-6);
}

/* =========================================================================
   5. The four doors
   ========================================================================= */

.doors {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-4);
    margin-top: var(--space-6);
    /* Room under the doors for the floor they stand on. */
    padding-bottom: var(--space-6);
    perspective: 1400px;
}

/* The threshold. Without it the panels faded into the page at their feet and
   read as cut off rather than as standing in a room. */
.doors::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--space-4);
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--gilt) 10%, var(--gilt) 90%, transparent);
}

/* The door frame: a second arch, drawn behind the panel and slightly proud of
   it, so the doorway has a reveal rather than being one flat shape. */
.door {
    display: flex;
    position: relative;
    padding: 0.5rem 0.5rem 0;
    border-radius: 12.5rem 12.5rem var(--radius) var(--radius);
    background:
        linear-gradient(180deg, var(--gilt), transparent 55%),
        var(--night-soft);
}

/* The accent is set inline on the .door form from config, and read back with a
   fallback rather than being re-declared here — a local declaration on the
   button would beat the inherited value and every door would look the same. */
.door__panel {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: 100%;
    min-height: 23rem;
    padding: var(--space-5) var(--space-4) var(--space-4);
    border: 1px solid var(--night-line);
    /* An arch, cut in CSS: the top corners take a full half-width radius so
       the panel reads as a doorway rather than a card. */
    border-radius: 12rem 12rem var(--radius) var(--radius);
    /* A lit bottom edge, so the door ends somewhere the eye can find. */
    border-bottom-color: var(--gilt);
    background:
        radial-gradient(90% 50% at 50% 0%, color-mix(in srgb, var(--door-accent, var(--gold)) 26%, transparent), transparent 65%),
        linear-gradient(180deg, var(--night-raised) 0%, var(--night) 62%, var(--night-raised) 100%);
    color: inherit;
    text-align: left;
    cursor: pointer;
    transform-origin: left center;
    transition: transform var(--slow) var(--ease-out),
                border-color var(--normal) var(--ease),
                box-shadow var(--normal) var(--ease);
}

/* Light under the door — the tell that there is a lit room on the other side.
   Widens and brightens as the door opens. */
.door__panel::before {
    content: '';
    position: absolute;
    left: 12%;
    right: 12%;
    bottom: 0;
    height: 2px;
    background: var(--door-accent, var(--gold));
    filter: blur(1.5px);
    opacity: 0.4;
    transition: opacity var(--normal) var(--ease),
                left var(--slow) var(--ease-out),
                right var(--slow) var(--ease-out),
                box-shadow var(--normal) var(--ease);
}

/* A sheen travelling across the panel on hover — light catching varnish.
   It carries the panel's own radius rather than being clipped by an
   `overflow: hidden` on the panel: that would make the panel a scroll
   container, zeroing its automatic minimum height and clipping the plate. */
.door__panel::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(105deg, transparent 42%, var(--lamp-shaft) 50%, transparent 58%);
    background-size: 300% 100%;
    background-position: 100% 0;
    opacity: 0;
    transition: opacity var(--fast) var(--ease);
}

/* Opening: the panel swings on its hinge, the light under it spills wider,
   and the sheen sweeps across. */
.door__panel:hover,
.door__panel:focus-visible {
    transform: rotateY(-13deg) translateZ(18px);
    border-color: var(--door-accent, var(--gold));
    box-shadow: 30px 0 60px rgba(0, 0, 0, 0.45);
}

.door__panel:hover::before,
.door__panel:focus-visible::before {
    left: 4%;
    right: 4%;
    opacity: 1;
    box-shadow: 0 0 18px 3px var(--door-accent, var(--gold));
}

.door__panel:hover::after,
.door__panel:focus-visible::after {
    opacity: 1;
    animation: door-sheen var(--slow) var(--ease-out) forwards;
}

/* The gradient slides *within* the pseudo-element rather than the element
   moving across the panel — so the highlight stays inside the door. */
@keyframes door-sheen {
    from { background-position: 100% 0; }
    to   { background-position: -100% 0; }
}

/* The arch and its numeral share one box, the numeral centred over the
   tympanum the way a cut date sits in a keystone. */
.door__head {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 6.5rem;
}

.door__arch {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* It is carving, not furniture: present, and never louder than the plate. */
    opacity: .75;
}

.da-lattice     { fill: none; stroke: var(--door-accent, var(--gold)); stroke-width: .9; opacity: .22; }
.da-arch-outer  { fill: none; stroke: var(--door-accent, var(--gold)); stroke-width: 2; opacity: .55; }
.da-arch-inner  { fill: none; stroke: var(--gilt); stroke-width: 1; }
.da-cusp        { fill: none; stroke: var(--door-accent, var(--gold)); stroke-width: 1.4; opacity: .7;
                  stroke-linecap: round; stroke-linejoin: round; }
.da-finial      { fill: var(--door-accent, var(--gold)); opacity: .8; }

/* Engraved: the numeral is filled with a gold gradient and given a hairline
   of shadow above, the way a cut letter catches light from one side. */
.door__numeral {
    position: relative;
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 400;
    text-align: center;
    letter-spacing: var(--tracking-wide);
    /* Solid, not a clipped gradient. Over a lattice the gradient's pale end
       disappeared and II, III and IV stopped being readable at all. */
    color: var(--door-accent, var(--gold));
    /* A cut letter is dark where the chisel went in, before it catches light
       on the other side of the stroke. */
    text-shadow: 0 1px 0 var(--night), 0 0 14px var(--night);
}

/* A brass plate screwed to the door: a lit top edge, a shadowed bottom one. */
.door__plate {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-2);
    border-top: 1px solid var(--gilt);
    border-bottom: 1px solid rgba(0, 0, 0, 0.35);
    background: linear-gradient(180deg, var(--lamp-shaft), transparent);
}

.door__name {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
}

.door__blurb {
    color: var(--night-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

.door__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: auto;
}

.door__count {
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--night-muted);
}

.door__knob {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: var(--radius-full);
    background: var(--door-accent, var(--gold));
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--door-accent, var(--gold)) 22%, transparent);
}

.door.is-bare .door__panel { opacity: 0.55; }

/* =========================================================================
   6. Specific, or shall I bring things out?
   ========================================================================= */

.choice-pair {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.choice {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    height: 100%;
    padding: var(--space-6);
    border: 1px solid var(--night-line);
    border-radius: var(--radius-lg);
    background: linear-gradient(160deg, var(--night-raised), var(--night));
    color: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--normal) var(--ease), transform var(--normal) var(--ease-out);
}

.choice:hover,
.choice:focus-visible {
    border-color: var(--gold);
    transform: translateY(-2px);
}

.choice__icon { color: var(--gold-400); }

.choice__label {
    font-family: var(--font-display);
    font-size: var(--text-xl);
}

.choice__note {
    color: var(--night-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

/* =========================================================================
   7. The brief
   ========================================================================= */

.brief-form { margin-top: var(--space-6); }

.brief-form__input {
    width: 100%;
    padding: var(--space-4);
    border: 1px solid var(--night-line);
    border-radius: var(--radius);
    background: var(--night-raised);
    color: var(--night-text);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    line-height: var(--leading-snug);
    resize: vertical;
}

.brief-form__input::placeholder { color: var(--night-muted); opacity: 0.7; }

.brief-form__input:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}

.brief-form__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    margin-top: var(--space-4);
}

.brief-form__hint {
    max-width: 34ch;
    color: var(--night-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
}

.brief-form__or {
    margin-top: var(--space-6);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--gold-400);
}

.prompt-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.prompt-chip {
    padding: 0.55rem 1rem;
    border: 1px dashed var(--night-line);
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--night-muted);
    font-size: var(--text-sm);
    cursor: pointer;
    transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}

.prompt-chip:hover {
    color: var(--night-text);
    border-color: var(--gold);
}

/* =========================================================================
   8. A piece, brought out
   ========================================================================= */

.piece {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
}

.piece__media { animation: piece-lift var(--slow) var(--ease-out) both; }

.piece__frame {
    position: relative;
    padding: var(--space-3);
}

/* Gold corner brackets, the way a piece is presented on a display board.
   Two elements, four corners: each draws two of them. */
.piece__frame::before,
.piece__frame::after {
    content: '';
    position: absolute;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--gold-800);
    pointer-events: none;
}

.piece__frame::before {
    top: 0; left: 0;
    border-right: 0;
    border-bottom: 0;
}

.piece__frame::after {
    right: 0; bottom: 0;
    border-left: 0;
    border-top: 0;
}

/* Brought out and set down on the counter. */
@keyframes piece-lift {
    from { opacity: 0; transform: translateY(18px) scale(0.985); }
    to   { opacity: 1; transform: none; }
}

.piece__img {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 4;
    /* Capped against the window, not just the column: the room is one screen,
       and a portrait crop on a wide monitor would push the buttons under the
       fold. */
    max-height: 60dvh;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--night-soft);
    box-shadow: var(--shadow-lg);
    /* Set by the pointer-parallax in shopkeeper.js; 0 until it runs, so the
       no-JS and reduced-motion paths render flat and correct. */
    transform: perspective(900px)
               rotateX(calc(var(--tilt-y, 0) * -3deg))
               rotateY(calc(var(--tilt-x, 0) * 3deg));
    transition: transform var(--normal) var(--ease-out);
}

.piece__flag {
    position: absolute;
    top: var(--space-4);
    left: var(--space-4);
    padding: 0.35rem 0.7rem;
    border-radius: var(--radius-sm);
    background: var(--gold);
    color: var(--wine-900);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
}

.piece__thumbs {
    display: flex;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.piece__thumb {
    width: 4rem;
    padding: 0;
    border: 1px solid var(--night-line);
    border-radius: var(--radius-sm);
    background: none;
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--fast) var(--ease);
}

.piece__thumb img {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
}

.piece__thumb.is-active,
.piece__thumb:hover { border-color: var(--gold); }

.piece__title {
    margin-top: var(--space-3);
    font-family: var(--font-display);
    font-size: clamp(var(--text-2xl), 3.4vw, var(--text-3xl));
    font-weight: 300;
    line-height: var(--leading-tight);
}

.piece__meta {
    margin-top: var(--space-2);
    color: var(--night-muted);
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-wide);
}

.piece__price {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--gilt);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
}

.piece__price del { color: var(--night-muted); font-size: var(--text-md); }

.piece__detail {
    margin-top: var(--space-4);
    max-width: 52ch;
    color: var(--night-muted);
    line-height: var(--leading-normal);
}

.piece__buy {
    margin-top: var(--space-5);
    padding-top: var(--space-5);
    border-top: 1px solid var(--night-line);
}

.piece__cut {
    color: var(--night-muted);
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-wide);
}

.piece__scarce { color: var(--gold-400); }

.piece__bag { margin-top: var(--space-4); }

.piece__soldout {
    margin-top: var(--space-5);
    padding-top: var(--space-5);
    border-top: 1px solid var(--night-line);
    color: var(--night-muted);
    font-size: var(--text-sm);
}

.piece__reactions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-5);
}

.parlour-page .btn--ghost {
    --btn-fg: var(--night-text);
    --btn-border: var(--night-line);
}

.parlour-page .btn--ghost:hover {
    --btn-bg: var(--night-soft);
    --btn-fg: var(--gold-400);
    --btn-border: var(--gold-800);
}

.piece__reactions .link-quiet { text-transform: none; letter-spacing: normal; }

/* =========================================================================
   9. Send him back for something else
   ========================================================================= */

.moves {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--night-line);
}

.moves__head {
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--gold-400);
}

.moves__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.move {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    width: 100%;
    padding: var(--space-3);
    border: 1px solid var(--night-line);
    border-radius: var(--radius);
    background: var(--night-raised);
    color: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--fast) var(--ease),
                background var(--fast) var(--ease),
                transform var(--fast) var(--ease);
}

.move:hover,
.move:focus-visible {
    border-color: var(--gold);
    background: var(--night-soft);
    transform: translateY(-1px);
}

.move__label { font-size: var(--text-sm); }

.move__hint {
    color: var(--night-muted);
    font-size: var(--text-xs);
}

/* =========================================================================
   10. Narrower rooms
   ========================================================================= */

@media (max-width: 1080px) {
    .parlour { grid-template-columns: 1fr; }

    .parlour__counter { position: static; }

    .transcript { max-height: 11rem; }

    .doors { grid-template-columns: repeat(2, 1fr); }

    .door__panel { min-height: 20rem; border-radius: 8rem 8rem var(--radius) var(--radius); }

    /* The swing needs room the narrow layout does not have. */
    .door__panel:hover,
    .door__panel:focus-visible { transform: translateY(-3px); }
}

@media (max-width: 780px) {
    /* The bar's two-line wordmark is taller here — leave room under it. */
    .parlour-page { padding-block: calc(var(--space-6) + 3.5rem) var(--space-8); }

    .piece { grid-template-columns: 1fr; }

    .choice-pair { grid-template-columns: 1fr; }

    .doors { grid-template-columns: 1fr; }

    .door__panel { min-height: auto; border-radius: 6rem 6rem var(--radius) var(--radius); }

    .piece__reactions .btn { flex: 1 1 auto; }
}

/* =========================================================================
   11. Motion
   ========================================================================= */

/* tokens.css already zeroes the durations for anyone who has asked for reduced
   motion; the entrance animations have to be switched off outright, since a
   0ms animation still runs its first keyframe. */
@media (prefers-reduced-motion: reduce) {
    .gate,
    .stage,
    .piece__media,
    .keeper__figure,
    .parlour-page__ambience::before,
    .parlour-page__ambience::after { animation: none; }

    /* The dust and the light shaft are motion, not decoration — with the
       animation off they are just haze, so take them out entirely. */
    .parlour-page__ambience::before,
    .parlour-page__ambience::after { display: none; }

    .door__panel:hover,
    .door__panel:focus-visible { transform: none; }

    .door__panel:hover::after,
    .door__panel:focus-visible::after { animation: none; opacity: 0; }
}
