/* Chum Flap — self-contained mini-game styling. Palette + fonts come from
   quest.css (:root vars, @font-face) and retro.css (cc-crt, neon-* utilities,
   the shared chrome: .cc-window / .cc-panel / .cc-back / .cc-hud / .px-*).
   Readability block: antialias reading copy; leave Press Start 2P headings crisp.

   The page is an arcade cabinet (Batch 3): marquee header, a royal-window
   BEZEL around the screen glass, two .cc-panel WINGS (quest card, standings)
   from 900px, and a control-panel footer strip. */

.flap-body {
    background: radial-gradient(circle at 50% 12%, #0a0a3a 0%, var(--void) 62%);
    color: var(--ink);
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
.flap-body, .ov-p, .flap-hint, .flap-wing-p, .flap-standing {
    font-family: 'DotGothic16', 'Courier New', monospace;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* the house pixel dash as a single straight rule (8 on / 6 off, 3px, dim):
   the marquee's bottom edge and the control panel's top edge */
.flap-head, .flap-foot {
    --flap-rule: repeating-linear-gradient(90deg, var(--win-line) 0 8px, transparent 8px 14px);
}

/* ---- header: arcade marquee ----
   Phones: a wrapping chrome row like .cc-topbar (the back links left, the
   HUD strip pushed right) over a centred title. Anonymous, the strip (BEST +
   LOG IN) shares the row with the links, so the header is two rows; signed
   in, the strip is wider than the room beside the links and drops to its
   own full-width row, where its pills wrap again if they must. Under 480px
   the home link reads HOME so the two links and the anonymous strip fit a
   360px row. The links never stack (nowrap): a stacked nav was the
   three-row header the Batch 2 review caught. From 900px up it is one grid
   row with the title truly centred: at that width each side cell is 314px,
   room for the widest pill (a 14-character Demolitionist's name pill is
   300px); at 640px the cells were 184px and a signed-in admin's strip ran
   off the screen (measured 819px of header at a 700px viewport). */
.flap-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 8px 14px 12px;
    background: var(--flap-rule) left bottom / 100% 3px no-repeat;
    /* a flex item's z-index makes a stacking context: keep the header (and
       the HUD's login dropdown hanging out of it) above the playfield's
       overlay (z 4), under the CRT layer (60) and modals (90) */
    z-index: 5;
}
.flap-nav { display: flex; flex-wrap: nowrap; align-items: center; gap: 0 10px; }
.flap-title {
    flex: 1 0 100%;
    text-align: center;
    font-size: clamp(var(--px-2, 16px), 4vw, var(--px-3, 24px));
    letter-spacing: 1px;
    color: var(--gold);
}
/* the HUD strip (BEST pill + session pills, retro.css .cc-hud--inline):
   right-aligned on its row and never wider than the header, so a long name
   pill wraps the strip instead of running off a phone screen */
#cc-hud { margin-left: auto; max-width: 100%; }
@media (max-width: 479px) {
    .flap-long { display: none; }
}
@media (min-width: 900px) {
    .flap-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
        grid-template-areas: "nav title best";
        padding: 10px 14px 13px;
    }
    .flap-nav { grid-area: nav; gap: 0 14px; }
    .flap-title { grid-area: title; flex: none; }
    #cc-hud { grid-area: best; justify-self: end; margin-left: 0; }
}

/* quest-mode banner (phones) + score-submit feedback. The banner is a 44px
   touch row (the project's floor for a primary target): the quest name in
   it is the only route to the quest page before a run on a phone, and at
   the old 28px strip the link was a 20px target. */
.flap-quest {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0 6px;
    min-height: 44px;
    padding: 0 12px;
    text-align: center;
    font-family: 'Press Start 2P', monospace;
    font-size: var(--px-1, 8px);
    letter-spacing: 1px;
    line-height: 1.6;
    color: var(--gold);
    background: rgba(248, 204, 80, 0.09);
    border-bottom: 1px solid var(--win-line);
    -webkit-font-smoothing: none;
}
.flap-quest[hidden] { display: none; }
.flap-quest-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 8px;
    color: var(--gold);
    text-decoration: underline;
    text-decoration-color: var(--gold-deep);
    text-underline-offset: 3px;
}
.flap-quest-link:hover, .flap-quest-link:focus-visible { color: var(--glint); text-decoration-color: var(--glint); outline: none; }
.ov-submit { font-size: 14px; color: var(--glint); min-height: 1.2em; }
/* the route back to the quest: the shared backlink face (.cc-back draws the
   glyph), centred in the panel; the hit area stays 44px */
.flap-back-quest { padding: 10px 8px; margin-top: -2px; }
/* .cc-back's inline-flex is an author rule and would beat the UA [hidden] */
.flap-back-quest[hidden] { display: none; }

/* ---- the cabinet ----
   A size query container that fills the room between header and footer:
   wings | bezel | wings in one row. The bezel's CSS size (its width from
   the cabinet's HEIGHT, cqh, at the field's 2:3 ratio; narrower rooms
   shrink it, flex-shrink + min-width 0) is the room on OFFER: game.js
   resize() measures the integer step that offer allows and then snaps the
   bezel to the canvas plus the 8px ring, so the glass hugs the picture and
   the cabinet centres whatever is left. Margin, not padding, is the
   breathing room: cqh is the cabinet's own box either way, so the offer can
   never outgrow the room. Size containment also means nothing resize()
   writes inside can change the cabinet's size and feed back. */
.flap-cabinet {
    container-type: size;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin: 8px 8px 10px;
}
@media (min-width: 900px) {
    .flap-cabinet { gap: 16px; margin: 10px 16px 14px; }
}

/* ---- the bezel: the royal window around the glass ----
   .cc-window gives the recipe (royal gradient, 3px --frame, 3px --win-line
   inset, hard 6px drop, cyan corner brackets). --bz is the frame's full
   depth (3px border + the padding), the one number the sizing maths uses.
   Phones get the slim bezel (8px: the 3px line and 5px of royal surface)
   with the brackets off, the --bare rule: a 13px bracket cannot live in a
   5px strip and a half-drawn frame is worse than none. From 900px the
   padding opens to 22px and the brackets return, sitting in the surface
   (6..21px) clear of the glass at 22. box-sizing is content-box on purpose:
   the content box IS the glass. The CSS size below (2:3 of the room's
   height) is only the OFFER: game.js resize() measures the step the room
   allows at this depth, then snaps the bezel's inline width/height down to
   the integer-scaled canvas plus the 8px ring, so the glass hugs the
   picture and the slack of the integer step lands outside the frame (the
   cabinet centres it). When the slim frame buys a whole extra step (a
   1440x900 desktop: 1.96 deep, 2.03 slim) the renderer sets .flap-bezel--slim
   and the brackets go with it. */
.flap-bezel {
    --bz: 11px;
    box-sizing: content-box;
    flex: 0 1 auto;
    min-width: 0;
    min-height: 0;
    width: calc((100cqh - 2 * var(--bz)) * 2 / 3);
    aspect-ratio: 2 / 3;
    display: flex;
    padding: calc(var(--bz) - 3px);
    border-radius: 10px;
}
.flap-bezel::before, .flap-bezel::after { display: none; }
@media (min-width: 900px) {
    .flap-bezel { --bz: 25px; }
    .flap-bezel::before, .flap-bezel::after { display: block; }
}
/* the renderer's call: the slim frame at any width when it buys a step */
.flap-bezel.flap-bezel--slim { --bz: 11px; }
.flap-bezel.flap-bezel--slim::before, .flap-bezel.flap-bezel--slim::after { display: none; }
/* no container units: the bezel takes the room's height and the glass may
   carry a little slack above and below the field (the Batch 2 look) */
@supports not (width: 1cqh) {
    .flap-cabinet { align-items: stretch; }
    .flap-bezel { width: auto; height: calc(100% - 2 * var(--bz)); max-width: calc(100% - 2 * var(--bz)); }
    .flap-wing { align-self: center; margin-top: 0; max-height: 100%; }
}
/* no aspect-ratio at all (old engines): the bezel fills the row */
@supports not (aspect-ratio: 2 / 3) {
    .flap-cabinet { align-items: stretch; }
    .flap-bezel { width: auto; flex: 1 1 auto; max-width: none; }
}

/* ---- the stage: the screen glass ----
   Guard: quest.css carries `#stage { position: fixed; inset: 0; z-index: 1;
   cursor: pointer }` for the saga player. Our stage is #flap-stage, and these
   explicit resets keep the field in flow even if an id collision ever recurs.
   The padding is 8px because game.js resize() sizes the canvas from this
   box's rect minus 16: change one, change the other. No border here (it
   would eat into that rect); the lip is an inset shadow. Overlays are
   inset 0 inside this box, so they can never reach the bezel or the wings. */
.flap-stage {
    position: relative;
    inset: auto;
    z-index: auto;
    cursor: default;
    /* the glass is a size container (named, so the overlay queries at the
       end of this file read the GLASS's height, never the viewport's: a
       360x740 phone at 3x has a 578px cabinet and a 376px glass). Size
       containment is safe here: the stage is sized by the bezel through
       flex, never by its content. */
    container: glass / size;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    overflow: hidden;
    background: #03031a;
    border-radius: 4px;
    box-shadow:
        inset 0 0 0 2px #020212,
        inset 0 0 0 3px rgba(128, 232, 255, 0.09),
        inset 0 0 36px rgba(0, 0, 8, 0.85);
}
/* a faint glass sheen across the top-left corner: a flat gradient laid over
   the hard pixel grid, never a blur of it; under the HUD score (2) and the
   overlays (4) */
.flap-stage::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(160deg, rgba(128, 232, 255, 0.05), transparent 38%);
}
/* the field wraps the canvas so the HUD score is anchored to the playfield,
   not to the stage (which has slack above/below the canvas on tall phones) */
.flap-field { position: relative; flex: 0 0 auto; line-height: 0; }
/* edge to edge art: the bezel is the frame now. The hairline and glow are
   shadows, so they never change the canvas box game.js measures. */
#game {
    display: block;
    background: #060626;
    box-shadow: 0 0 0 1px rgba(128, 232, 255, 0.16), 0 0 26px rgba(128, 232, 255, 0.12);
    image-rendering: pixelated;
    touch-action: none;
}

/* the in-field score: a 32px gold HUD numeral with a one-FONT-pixel dark
   outline. At 32px a Press Start 2P pixel is 4 CSS px, so the outline is
   eight hard offsets at 4px (axes and diagonals, no blur): a pixel-art
   outline on a pixel glyph, not a hairline vector stroke around it. The
   dead panel's final score (.ov-score b) uses the same recipe. */
.flap-score, .ov-score b {
    --hud-ink: #04041c;
    text-shadow:
        -4px 0 0 var(--hud-ink), 4px 0 0 var(--hud-ink), 0 -4px 0 var(--hud-ink), 0 4px 0 var(--hud-ink),
        -4px -4px 0 var(--hud-ink), 4px -4px 0 var(--hud-ink), -4px 4px 0 var(--hud-ink), 4px 4px 0 var(--hud-ink);
}
.flap-score {
    position: absolute;
    top: 18px;
    left: 50%;
    transform: translateX(-50%);
    font-size: var(--px-4, 32px);
    line-height: 1;
    letter-spacing: 0;
    color: var(--gold);
    -webkit-font-smoothing: none;
    pointer-events: none;
    z-index: 2;
}

/* ---- wings (from 900px): the quest card and the standings ----
   Two .cc-panel columns flanking the bezel, cards beside the screen: each
   hugs its content and hangs from the bezel's top edge (the bezel is
   centred in the cabinet, so its top is half the slack down: margin-top =
   (100cqh - --flap-screen-h) / 2, --flap-screen-h set by game.js resize()
   from the snapped bezel). They were stretched to the bezel's height and
   read as two tall panels of empty glass with 100px of copy at the top.
   Never taller than the bezel: a long standings list scrolls inside its
   wing. Hidden under 900px (the #quest-banner strip and the dead overlay's
   inline standings carry the same facts there) and while [hidden] (quest
   mode, data not yet arrived). Each wing holds two blocks; game.js shows
   the quest pair or the practice pair. */
.flap-wing {
    --wing-w: clamp(180px, 22vw, 260px);
    display: none;
    flex: 0 0 var(--wing-w);
    width: var(--wing-w);
    max-width: 260px;
    max-height: var(--flap-screen-h, 100cqh);
    min-width: 0;
    min-height: 0;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    align-self: flex-start;
    margin-top: calc((100cqh - var(--flap-screen-h, 100cqh)) / 2);
}
.flap-wing[hidden] { display: none; }
.flap-wing-block { display: flex; flex-direction: column; gap: 10px; flex: 0 1 auto; min-height: 0; }
.flap-wing-block[hidden] { display: none; }
/* the wing's backlink: the shared face, pulled in so the row stays tight */
.flap-wing-back { margin: -4px 0 -6px; }
.flap-wing-back[hidden] { display: none; }
.flap-wing-k, .flap-wing-h {
    font-family: 'Press Start 2P', monospace;
    font-size: var(--px-1, 8px);
    letter-spacing: 1px;
    line-height: 1.7;
    font-weight: normal;
    -webkit-font-smoothing: none;
}
.flap-wing-k { color: var(--dim); margin-bottom: -6px; }
.flap-wing-h { color: var(--gold); overflow-wrap: anywhere; }
.flap-wing-p { font-size: 14px; line-height: 1.6; color: var(--dim); letter-spacing: 0.03em; }
.flap-wing-p:empty { display: none; }
.flap-wing-p b { color: var(--gold); font-weight: normal; }

/* standings rows: the quest page's .qv-standings look (rank in the pixel
   face, the leader's gold with a glow; name with ellipsis; gold best; the
   viewer's row tinted). Shared by the wing and the dead overlay. */
.flap-standings {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    border-top: 2px solid var(--win-line);
    scrollbar-width: thin;
    scrollbar-color: var(--win-line) transparent;
}
.flap-standings:empty { display: none; }
.flap-standing {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 4px;
    border-bottom: 2px solid var(--win-line);
    font-size: 15px;
    line-height: 1.5;
    letter-spacing: 0.03em;
    color: var(--ink);
    text-align: left;
}
.flap-standing.mine { color: var(--gold); background: rgba(248, 204, 80, 0.07); }
.flap-standing .rank, .flap-standing .best {
    flex: 0 0 auto;
    font-family: 'Press Start 2P', monospace;
    font-size: var(--px-1, 8px);
    letter-spacing: 1px;
    line-height: 1.5;
    -webkit-font-smoothing: none;
}
.flap-standing .rank { width: 24px; color: var(--dim); }
.flap-standing:first-child .rank, .flap-standing.lead .rank { color: var(--gold); text-shadow: 0 0 8px rgba(248, 204, 80, 0.5); }
.flap-standing .who { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the (you) tag: the quest page's .qv-who small, dim and 12px */
.flap-standing .who small { color: var(--dim); font-size: 12px; }
.flap-standing .best { color: var(--gold); }
/* the dead overlay's copy on phones: compact, the top few rows */
.flap-standings--inline { width: 100%; max-width: 280px; margin: 0 auto; overflow: visible; }
.flap-standings--inline .flap-standing { padding: 5px 4px; gap: 6px; font-size: 14px; }

@media (min-width: 900px) {
    .flap-wing { display: flex; }
    .flap-quest { display: none; }
    .flap-standings--inline { display: none; }
    /* the left wing carries the route back from here */
    .flap-back-quest { display: none; }
}

/* ---- overlays ----
   A hard scrim over the glass (no blur: the pixel grid stays a pixel grid)
   with a .cc-panel in the middle. The scrim scrolls if the panel is taller
   than the glass (a short phone with five standings rows): the panel's
   auto margins centre it when it fits and keep its top reachable when it
   does not. Inside the stage, so an overlay never covers bezel or wings. */
.flap-overlay {
    position: absolute;
    inset: 0;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding: 8px;
    overflow-y: auto;
    background: rgba(4, 4, 22, 0.6);
    z-index: 4;
}
.flap-overlay.on { display: flex; }
.flap-ov-panel {
    margin: auto;
    width: min(100%, 320px);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
    padding: 18px 16px 16px;
    box-shadow: 0 6px 0 rgba(0, 0, 0, 0.35);
}
.ov-h { font-size: var(--px-2, 16px); line-height: 1.5; letter-spacing: 0; -webkit-font-smoothing: none; }
.ov-p { font-size: 15px; line-height: 1.6; color: var(--dim); max-width: 30ch; }
.ov-p b { color: var(--ink); }
.ov-score { font-size: 16px; color: var(--dim); }
.ov-score b { font-family: 'Press Start 2P', monospace; font-size: var(--px-4, 32px); line-height: 1.3; letter-spacing: 0; color: var(--gold); display: block; margin-top: 4px; -webkit-font-smoothing: none; }
.ov-pb { display: block; margin-top: 8px; color: var(--glint); font-size: 13px; }
/* display:block would beat the UA [hidden] rule and show NEW BEST on every run */
.ov-pb[hidden] { display: none; }

.flap-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

.flap-btn {
    font-family: 'Press Start 2P', monospace;
    font-size: var(--px-1, 8px);
    letter-spacing: 1px;
    line-height: 1.4;
    color: var(--ink);
    background: rgba(8, 8, 40, 0.9);
    border: 2px solid var(--glint);
    border-radius: 6px;
    padding: 14px 18px;
    min-height: 44px;
    cursor: pointer;
    transition: transform 0.06s ease, background 0.15s ease;
    -webkit-font-smoothing: none;
}
.flap-btn.gold { border-color: var(--gold); color: var(--gold); }
.flap-btn:hover, .flap-btn:focus-visible { background: rgba(24, 24, 72, 0.95); }
.flap-btn:active { transform: translateY(1px); }
.flap-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* replay badge sits top-center, non-blocking; no panel, no scrim */
.flap-replay-badge {
    inset: 0 0 auto 0;
    background: transparent;
    overflow: visible;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    pointer-events: none;
}
.flap-replay-badge.on { display: flex; }
.flap-replay-badge .ov-h { font-size: var(--px-1, 8px); letter-spacing: 1px; }
.flap-replay-badge .flap-btn { pointer-events: auto; padding: 10px 14px; }

/* ---- footer: the control-panel strip ---- */
.flap-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 4px 18px;
    padding: 11px 14px 9px;
    background: var(--flap-rule) left top / 100% 3px no-repeat;
    text-align: center;
}
.flap-marquee { color: var(--dim); letter-spacing: 2px; }
/* DotGothic16 at 14px: 12px was below the face's grid and smeared */
.flap-hint { font-size: 14px; color: var(--dim); }

@media (max-width: 430px) {
    .flap-hint { display: none; }
}

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

/* ---- overlay layout by the size of the glass (container: glass) ----
   Tall glass (a desktop, a 1366x768 laptop's 540px field): the ready panel
   sits in the lower half so the idle shard, resting at 42% of the field
   with its halo, shows above it: the player sees the thing they are before
   the first tap. Short glass (an iPhone SE / 8 at 2x, a 360-wide Android
   at 3x: 376px): the dead panel tightens so SCORE, the actions, the message
   and the route back fit the first screen, RETRY and WATCH REPLAY sit side
   by side (at 14px 18px padding they stacked and cost a 54px row; still
   44px tall), and the inline standings stop at three rows (the panel
   scrolls for the rest). These sit after .flap-btn so they win the cascade. */
@container glass (min-height: 520px) {
    #ov-ready .flap-ov-panel { margin: auto 0 16px; }
}
@container glass (max-height: 430px) {
    .flap-ov-panel { gap: 8px; padding: 14px 12px 12px; }
    .ov-submit { line-height: 1.5; }
    .flap-actions { gap: 8px; }
    .flap-btn { padding: 12px 11px; }
    .flap-standings--inline .flap-standing:nth-child(n+4) { display: none; }
}
