/* ============================================================
   Medieval Solutions — Interactive example
   Palette and fonts from theme.css; avatars, banner, score bar, cards,
   bubbles and choices from components.css. This file is only the
   example's own layout: the group-chat story stage and its chrome.
   Each councillor's colours come from data/example-stories.json
   as --bub / --acc.
   ============================================================ */

:root { --av: 40px; }

* { box-sizing: border-box; }

body {
    font-family: var(--font-ui);
    background-color: var(--paper);
    color: var(--ink);
    margin: 0;
    padding: 0 16px 96px;
    overflow-x: hidden;
}

/* ---------- Top bar: one slim row; proofreading tools fold out under ⚙ ---------- */

.xd-bar {
    position: fixed; top: 0; left: 0; right: 0; z-index: 200;
    background: var(--paper);
    border-bottom: 2px solid var(--tan);
}
.xd-bar-row, .xd-tools {
    display: flex; gap: 8px; align-items: center;
    max-width: 552px; margin: 0 auto; padding: 6px 16px;
}
.xd-tools { padding-top: 0; flex-wrap: wrap; }
.xd-tools[hidden] { display: none; }
.xd-bar select, .xd-bar button, .xd-toggle {
    font-family: var(--font-ui); font-size: 0.85rem; color: var(--ink);
    background: #fff; border: 2px solid var(--tan); border-radius: 8px;
    padding: 3px 8px; cursor: pointer;
}
#xd-story {
    flex: 1; min-width: 0;
    font-family: var(--font-pixel); font-size: 0.95rem; color: var(--red);
    background: transparent; border-color: transparent; text-align: center; text-align-last: center;
}
.xd-icon {
    flex-shrink: 0; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
    font-size: 1.05rem; color: var(--ink); text-decoration: none;
    background: #fff; border: 2px solid var(--tan) !important; border-radius: 50% !important; padding: 0 !important;
}
.xd-toggle { display: inline-flex; align-items: center; gap: 4px; }
.xd-toggle input { margin: 0; }

.xd-progress {
    position: fixed; top: 0; left: 0; height: 3px; width: 0%;
    background: var(--red); z-index: 210; transition: width .3s ease;
}

/* ---------- Sticky header: town banner + score bar ---------- */
/* --bar-h is measured by example.js (the tools row changes the bar's height). */

.xd-head {
    position: sticky; top: var(--bar-h, 46px); z-index: 100;
    max-width: 520px; margin: calc(var(--bar-h, 46px) + 6px) auto 0;
    padding: 6px 0 4px;
    background: var(--paper);
}
.xd-head::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -16px; height: 16px;
    background: linear-gradient(var(--paper), rgba(243, 239, 237, 0)); pointer-events: none;
}

/* ---------- Stage ---------- */

.xd-stage { max-width: 520px; margin: 12px auto 0; }
/* On phones the feed leaves room for "The table" tab on the left edge. */
@media (max-width: 600px) { .xd-stage, .xd-head { padding-left: 22px; } }

.beat { margin: 8px 0; animation: rise .4s ease both; }
.instant .beat, .instant .beat * { animation: none !important; transition: none !important; }

/* Chapter */
.beat-chapter { text-align: center; margin: 40px 0 18px; }
.beat-chapter:first-child { margin-top: 12px; }
.beat-chapter h2 {
    font-family: var(--font-pixel); font-weight: normal; font-size: 1.8rem;
    margin: 0; color: var(--red);
}
.beat-chapter .sub { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 0.9rem; color: var(--ink2); }
.beat-chapter .sub .av { --av: 26px; }

/* Narration: the Town Crier (the roster's preacher), reading the scene off a scroll.
   He strikes up (two notes) once at the start of each run of lines. */
.beat-mav { display: flex; gap: 8px; align-items: flex-start; padding: 6px 0; color: #3a2414; }
.beat-mav.cont { padding-top: 0; margin-top: -2px; }
.beat-mav .crier { --av: var(--av-chat, 40px); --bub: var(--parch); --acc: var(--ink3); margin-top: 16px; }
.beat-mav.cont .crier { margin-top: 0; }
.beat-mav .col { min-width: 0; max-width: 440px; }
.beat-mav .who { font-family: var(--font-pixel); font-size: .8rem; color: var(--ink3); margin: 0 0 2px 6px; }
.beat-mav .scroll {
    position: relative; margin: 0; padding: 9px 14px; font-style: italic; line-height: 1.45;
    background: var(--parch); border: 2px solid var(--parch-brd); border-radius: 4px;
    box-shadow: 0 2px 0 var(--tan);
}
/* The rolled ends of the scroll */
.beat-mav .scroll::before, .beat-mav .scroll::after {
    content: ''; position: absolute; left: -5px; right: -5px; height: 7px; border-radius: 4px;
    background: var(--tan-lt); border: 2px solid var(--parch-brd);
}
.beat-mav .scroll::before { top: -6px; }
.beat-mav .scroll::after { bottom: -6px; }
.beat-mav.cont .scroll::before { display: none; }
/* The toot: two notes puff up as he starts (he faces right, towards the scroll). */
.crier .toot { position: absolute; right: -10px; top: -6px; font-style: normal; font-size: .8rem; color: var(--red); line-height: 1; opacity: 0; pointer-events: none; }
.crier .toot b { position: absolute; left: 9px; top: -7px; font-weight: normal; }
.beat-mav:not(.cont) .crier .toot { animation: toot 1.1s .25s ease-out both; }
@keyframes toot { 0% { opacity: 0; translate: 0 4px; } 25% { opacity: 1; } 100% { opacity: 0; translate: 6px -12px; } }
@media (prefers-reduced-motion: reduce) { .crier .toot { display: none; } }

/* Speech — avatar on the first line of a run; later lines tuck under it. */
.row { display: flex; gap: 8px; align-items: flex-start; }
.row.right { flex-direction: row-reverse; }
.row .av { --av: var(--av-chat, 40px); }
.beat-say.cont { margin-top: 3px; }
.col { display: flex; flex-direction: column; align-items: flex-start; max-width: calc(100% - var(--av) - 24px); }
.right .col { align-items: flex-end; }
.who { font-size: 0.75rem; color: var(--acc); margin: 0 4px 2px; font-weight: bold; }
.left .bubble { border-top-left-radius: 4px; }
.right .bubble { border-top-right-radius: 4px; }
.cont .left .bubble, .cont .right .bubble { border-radius: 18px; }

/* Heckle — cuts across the middle of the table */
.beat-heckle { display: flex; justify-content: center; }
.heckle {
    display: inline-flex; align-items: center; gap: 6px; max-width: 86%;
    font-size: 15px; padding: 5px 12px 5px 5px;
    background: #fff; border: 2px dashed var(--acc); border-radius: 22px;
    transform: rotate(var(--tilt, -2deg)); animation: heckle .4s cubic-bezier(.3, 1.6, .5, 1) both;
}
.heckle .av { --av: 26px; }
.heckle b { color: var(--acc); }

.beat-stage { text-align: center; font-style: italic; font-size: 0.88rem; color: var(--ink2); }

/* Pitch divider */
.beat-pitch { margin-top: 30px; text-align: center; }
.beat-pitch .line { display: flex; align-items: center; gap: 8px; }
.beat-pitch .line::before, .beat-pitch .line::after { content: ''; flex: 1; border-top: 2px dotted var(--tan); }
.beat-pitch .name { font-family: var(--font-pixel); font-size: 1.15rem; color: var(--acc); }
.beat-pitch .av { --av: 28px; }
.beat-pitch .note { font-size: 0.82rem; font-style: italic; color: var(--ink2); margin-top: 2px; }

/* The trouble */
.beat-trouble { text-align: center; padding: 6px 0 4px; }
.beat-trouble .label { font-family: var(--font-pixel); color: var(--red); font-size: 1.3rem; }
.trouble-slot { width: min(170px, 40vw, 22vh); margin: 6px auto 0; }

/* Flipped cards sit under the speaker's bubble column, slightly askew like a real table. */
.beat-flip { display: flex; }
.beat-flip.left { justify-content: flex-start; padding-left: calc(var(--av) + 8px); }
.beat-flip.right { justify-content: flex-end; padding-right: calc(var(--av) + 8px); }

/* Award */
.beat-award { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 14px 0 6px; }
.award-card { width: 64px; }
.award-who { display: flex; align-items: center; gap: 8px; }
.award-who .av { --av: 44px; animation: pop .7s .7s ease both; }
.award-text { font-size: 0.95rem; line-height: 1.3; }
.award-text b { font-family: var(--font-pixel); font-weight: normal; font-size: 1.15rem; color: var(--acc); }

/* Choice */
.beat-choice { text-align: center; padding-top: 18px; }
.beat-choice .prompt { font-family: var(--font-pixel); font-size: 1.1rem; color: var(--red); margin-bottom: 12px; }
.options { display: grid; gap: 10px; }
.ending-head { margin: 26px 0 0; text-align: center; font-size: 0.82rem; color: var(--ink2); border-top: 2px dotted var(--tan); padding-top: 6px; }

/* Interlude — the "keep going?" break after round one */
.beat-interlude {
    margin: 30px 0 10px; padding: 18px 16px 16px; text-align: center;
    background: var(--parch); border: 3px double var(--parch-brd); border-radius: 10px;
    box-shadow: 0 4px 0 var(--tan);
}
.beat-interlude h3 { font-family: var(--font-pixel); font-weight: normal; font-size: 1.35rem; color: var(--red); margin: 0 0 8px; }
.beat-interlude p { margin: 0 0 10px; }
.beat-interlude .teaser { font-style: italic; font-size: 1.05rem; }
.beat-interlude .keep {
    display: inline-block; margin-top: 4px; padding: 10px 22px;
    font-family: var(--font-pixel); font-size: 1.05rem; color: #fff;
    background: var(--red); border: 2px solid #000; border-radius: 12px; cursor: pointer;
    animation: beckon 1.8s ease-in-out infinite;
}
.beat-interlude .keep:disabled { animation: none; opacity: .5; cursor: default; }
.beat-interlude .exits { display: flex; justify-content: center; gap: 16px; margin-top: 12px; font-size: 0.88rem; }
.beat-interlude .exits a { color: var(--ink2); }

/* Tap prompt — fades away once the reader has the idea, returns if they stall. */
.xd-tap {
    position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
    background: rgba(30, 14, 6, .75); color: var(--paper); padding: 4px 14px; border-radius: 20px;
    font-size: 0.8rem; z-index: 150; pointer-events: none;
    transition: opacity .6s ease; animation: bob 1.6s ease-in-out infinite;
}
.xd-tap.faded { opacity: 0; }
.xd-tap.hidden { display: none; }
/* Above the hand when it's tucked at the bottom (demo). */
body.hf-tucked .xd-tap { bottom: 146px; }

.xd-end { text-align: center; padding: 24px 0 40px; max-width: 520px; margin: 0 auto; }
.xd-end a, .xd-end button {
    display: inline-block; margin: 6px; padding: 8px 18px;
    font-family: var(--font-ui); font-size: 1rem; cursor: pointer;
    border: 2px solid #000; border-radius: 10px; background: var(--btn-tan); color: #412d0a; text-decoration: none;
}
.xd-end #xd-next-story { display: block; margin: 0 auto 8px; background: var(--red); font-family: var(--font-pixel); color: #fff; }

.xd-error { max-width: 520px; margin: 20px auto; padding: 10px; border: 2px solid var(--red); color: var(--red); background: #fff; border-radius: 8px; }

@keyframes heckle { from { opacity: 0; transform: scale(.4) rotate(8deg); } }

@media (max-width: 400px) {
    :root { --av: 34px; }
    .row .av { --av: 34px; }
    .bubble { font-size: 15.5px; }
    .flip-card { width: 84px; }
    .ms-scorebar { gap: 8px 12px; }
}

/* ---------- Demo game ---------- */
.xd-title { flex: 1; text-align: center; font-family: var(--font-pixel); font-size: 1rem; color: var(--red); }
html[data-mode="demo"] .xd-toggle { display: none; }
.xd-end-lead { font-family: var(--font-pixel); color: var(--red); font-size: 1.25rem; line-height: 1.3; margin: 0 16px 14px; text-wrap: balance; }

/* Pick cards (demo): the prompt, and the hand rising from the bottom (css/hand-fan.css) */
.beat-pick { text-align: center; padding-top: 18px; }
/* Picking a face happens over the council table: a wash of the page behind the picker
   fades the table and the guests out, so the prompt and the faces read on their own. */
.beat-face { position: relative; isolation: isolate; }
.beat-face::before {
    content: ''; position: absolute; inset: -36px -16px -12px; z-index: -1; pointer-events: none;
    background: linear-gradient(to bottom, transparent, var(--paper) 44px, var(--paper) calc(100% - 20px), transparent);
}
.beat-pick .prompt { font-family: var(--font-pixel); font-size: 1.1rem; color: var(--red); margin-bottom: 12px; text-wrap: balance; }
.pick-open { margin: 0 auto; }
.pick-down { display: flex; justify-content: center; gap: 8px; }
.pick-down:empty { display: none; }
.down-card { width: 56px; rotate: -4deg; animation: pickIn .4s cubic-bezier(.3, 1.4, .5, 1) backwards; }
.down-card + .down-card { rotate: 5deg; animation-delay: .08s; }
.down-card .card-back { width: 100%; display: block; border-radius: 6px; box-shadow: 0 3px 0 var(--tan); }
@keyframes pickIn { from { opacity: 0; translate: 0 18px; } }
@media (prefers-reduced-motion: reduce) { .down-card { animation: none; } }
.xd-end-note { margin: 0 16px 14px; font-size: .88rem; color: var(--ink3); }

/* Pick a face (demo): five goblins in a row */
.face-row { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; }
.face { padding: 4px; border: 0; background: none; border-radius: 50%; cursor: pointer; transition: translate .15s;
    animation: pickIn .4s cubic-bezier(.3, 1.4, .5, 1) backwards; animation-delay: calc(var(--i) * 70ms); }
.face .av { --av: 58px; }
.face:not(:disabled):hover { translate: 0 -4px; }
.face.sel { translate: 0 -6px; box-shadow: 0 0 0 3px var(--red), 0 0 16px rgba(236, 188, 52, .9); }
.face:disabled:not(.sel) { opacity: .4; }
.face:disabled { cursor: default; }
@media (prefers-reduced-motion: reduce) { .face { animation: none; } }

/* An answered choice stays on screen; a tap on it should still turn the story on. */
.option:disabled, .face:disabled, .keep:disabled { pointer-events: none; }

/* ---------- The council table (example.js renderCouncil) ----------
   The title screen's table (same 25×16 sprite, same view-transition name, so it glides
   over from the title), with the story's cast round it while the scene is set. When the
   first round starts it rises towards the score bar and fades, the same councillors
   appear there, and the chat below stays clear. */
.xd-council {
    /* Centred by margins, not translate: the world swipe moves top-level elements with translate. */
    position: fixed; left: 50%; z-index: 0;
    /* Centred at 52%, but its top (--council-rise above the centre) never under the story's lines so far (--council-min);
       both set by example.js. And never so low the button leaves the screen. */
    top: min(max(52%, calc(var(--council-min, 0px) + var(--council-rise, 112px) + 10px)), calc(100% - 190px)); width: 320px; height: 200px;
    margin: -100px 0 0 -160px; pointer-events: none;
    /* Leaving: the table drifts up towards the top bar and fades, about as long as the councillors take. */
    transition: top 1.5s cubic-bezier(.45, 0, .2, 1), scale 1.5s cubic-bezier(.45, 0, .2, 1), opacity 1.3s .2s ease-in;
}
.xd-council:not(.gathering) { top: calc(var(--bar-h, 46px) + 60px); scale: .5; opacity: 0; }
/* Short phones (an iPhone SE, 568 px): no room for the whole table between the story and the screen's foot,
   so it gathers at four fifths of its size, a little lower, and "I want to join in" stays clear of the scroll. */
@media (max-height: 600px) {
    .xd-council.gathering { scale: .8; top: min(max(52%, calc(var(--council-min, 0px) + var(--council-rise, 112px) * .8 + 8px)), calc(100% - 156px)); }
}
/* Hidden until the story's first line, then it fades up just after that line lands
   (backwards fill only, so it never holds the opacity). */
.xd-council:not(.arrive) { opacity: 0; transition: none; }
.xd-council.gathering.arrive:not(.instant) { animation: council-in .9s .45s cubic-bezier(.2, .8, .3, 1) backwards; }
@keyframes council-in { from { opacity: 0; scale: .94; } }
.xd-stage { position: relative; z-index: 1; }
.xc-table {
    position: absolute; left: 50%; bottom: 0; translate: -50% 0; width: 225px; height: 144px;
    image-rendering: pixelated; z-index: 2; view-transition-name: council-table;
}
.xc-seat { position: absolute; animation: bob 2.6s ease-in-out infinite; }
.xc-seat:nth-child(odd) { animation-delay: -1.3s; }
.xc-seat .av { --av: 46px; }
.xc-seat.fl { left: 2px; bottom: 18px; z-index: 3; }
.xc-seat.bl { left: 62px; bottom: 128px; z-index: 1; }
.xc-seat.bc { left: calc(50% - 23px); bottom: 138px; z-index: 1; }
.xc-seat.br { right: 62px; bottom: 128px; z-index: 1; }
.xc-seat.fr { right: 2px; bottom: 18px; z-index: 3; }
/* On a 320 px phone the council fills the screen: the front seats step in so their goblins
   (wider than the circle) stay on it. */
@media (max-width: 340px) {
    .xc-seat.fl { left: 18px; }
    .xc-seat.fr { right: 18px; }
}

/* While the scene is set the councillors are at the table, so the score bar waits.
   Leaving, each one drifts up to their seat (example.js driftToSeats), which shows as they land. */
.xd-head .ms-scorebar { transition: opacity .3s; }
.xd-council:not(.gathering) .xc-seat { visibility: hidden; }
.xd-drift { position: fixed; z-index: 250; margin: 0; pointer-events: none; }
.ms-seat.landing { opacity: 0; }
.ms-seat { transition: opacity .25s; }
html:not(.xd-seated) .xd-head .ms-scorebar { opacity: 0; pointer-events: none; }

/* The seat nobody has taken (example only): pressing it goes to the demo. */
.xd-empty { --bub: var(--paper); --acc: var(--tan); border-style: dashed; color: var(--red); font-size: 1.4rem; line-height: 1; }
.xc-free { pointer-events: auto; text-decoration: none; display: flex; flex-direction: column; align-items: center; z-index: 4; }
.xc-free .av { --av: 46px; animation: join-pulse 1.6s ease-in-out infinite; }
.xc-free:hover .av, .xc-free:focus-visible .av { --acc: var(--red); background: #fff; }
.xc-free-label {
    position: absolute; bottom: calc(100% + 6px); white-space: nowrap;
    font-family: var(--font-pixel); font-size: .78rem; color: var(--red);
    background: var(--parch); border: 2px solid var(--parch-brd); border-radius: 10px; padding: 2px 8px;
}
.xc-free, .xc-watch { transition: opacity .4s; }
.xd-council:not(.at-door) .xc-free, .xd-council:not(.at-door) .xc-watch { opacity: 0; pointer-events: none; }
/* Watch from the sidelines: the way into the story, under the table. */
.xc-watch {
    position: absolute; left: 50%; top: calc(100% + 18px); translate: -50% 0; white-space: nowrap;
    pointer-events: auto; padding: 10px 20px; font-size: 1rem; box-shadow: 0 3px 0 rgba(0, 0, 0, .2);
}
@keyframes join-pulse { 50% { box-shadow: 0 0 0 4px rgba(236, 188, 52, .45); } }
@media (prefers-reduced-motion: reduce) {
    .xd-council, .xd-head .ms-scorebar { transition: none; }
    .xd-council.gathering.arrive { animation: none; }
    .xc-free .av { animation: none; }
    .xc-seat { animation: none; }
}
