/* FLX Trail — retro pixel aesthetic */

@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap');

:root {
    --bg: #2a1f1a;
    --bg-light: #3d2f26;
    --fg: #f0e6d0;
    --fg-dim: #c9b896;
    --accent: #e87a3c;    /* Scout orange — title, active waypoint, Scout sprite */
    --accent-2: #6fa865;  /* finger lakes green */
    --btn: #2a8a94;       /* teal — buttons only, distinct from title */
    --btn-hover: #3ba7b0;
    --border: #8b6e4e;
    --shadow: rgba(0, 0, 0, 0.45);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
    height: 100%;
    font-family: 'VT323', 'Courier New', monospace;
    background: var(--bg);
    color: var(--fg);
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
}

body {
    display: flex;
    align-items: safe center;
    justify-content: center;
    min-height: 100vh;
    /* `safe center` falls back to flex-start when content is taller than the
       viewport, so the top doesn't get cropped off into the unscrollable
       overflow zone. The title screen + leaderboard card can exceed a 13"
       laptop viewport. No overflow:hidden on body — short viewports (mobile
       virtual keyboard on the finish form) need to be able to scroll. */
}

#app {
    width: 100%;
    max-width: 800px;
    padding: 1rem;
}

.screen {
    text-align: center;
    padding: 2rem 1rem;
    animation: fadeIn 0.4s ease;
}

.screen.hidden { display: none; }

/* Finish screen is tighter so the Save button fits above the fold on a
   13" MacBook (~700px of vertical viewport after browser chrome). */
#finish-screen { padding: 1rem 1rem 1.25rem; }
#finish-screen .title { font-size: 1.75rem; margin-bottom: 0.25rem; }
#finish-screen .blurb { font-size: 1.1rem; line-height: 1.35; margin-bottom: 0.75rem; }
#finish-screen .footnote { margin-top: 0.75rem; }

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
}

.title {
    font-family: 'Press Start 2P', 'Courier New', monospace;
    font-size: 2.25rem;
    color: var(--accent);
    letter-spacing: 2px;
    text-shadow: 3px 3px 0 var(--shadow);
    margin-bottom: 0.5rem;
}

.subtitle {
    font-size: 1.75rem;
    color: var(--fg-dim);
    margin-bottom: 2rem;
    letter-spacing: 1px;
}

.blurb {
    font-size: 1.375rem;
    line-height: 1.5;
    margin-bottom: 2rem;
    color: var(--fg-dim);
}

.pixel-btn {
    font-family: 'Press Start 2P', monospace;
    font-size: 0.875rem;
    padding: 0.9rem 1.5rem;
    background: var(--btn);
    color: var(--fg);
    border: none;
    border-radius: 0;
    cursor: pointer;
    letter-spacing: 1px;
    box-shadow: 4px 4px 0 var(--shadow);
    transition: transform 80ms, box-shadow 80ms, background 120ms;
}

.pixel-btn:hover {
    background: var(--btn-hover);
    transform: translate(-2px, -2px);
    box-shadow: 6px 6px 0 var(--shadow);
}

.pixel-btn:active {
    transform: translate(2px, 2px);
    box-shadow: 0 0 0 var(--shadow);
}

.footnote {
    font-size: 1rem;
    color: var(--border);
    margin-top: 3rem;
    letter-spacing: 1px;
}

.footnote-link {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.footnote-link:hover, .footnote-link:focus-visible {
    color: var(--accent);
    outline: none;
}

/* Attribution under the title (replaces the old bottom footnote per Adam's
   2026-05-09 Loom — wants the FLE link prominent, not buried at the bottom). */
.attribution {
    font-size: 1.05rem;
    color: var(--fg-dim);
    margin: -0.25rem 0 1.5rem;
    letter-spacing: 1px;
}

.attribution-link {
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.attribution-link:hover {
    color: var(--accent-2, var(--accent));
}

.attribution-link:focus-visible {
    color: var(--accent-2, var(--accent));
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Top-3 leaderboard preview — sits below the Start button, hidden by default
   and revealed by JS only when the API returns >=1 entry. Stays out of the
   way of the conversion path (Start button) above the fold.

   Boxed treatment per Adam's 2026-05-09 follow-up — a simple outlined card
   so the section reads as its own surface instead of floating text. Lighter
   touch than leaderboard.html's heavy 3px border + drop shadow (would
   compete with the Start button's chunky shadow). */
.title-leaderboard {
    margin: 2.5rem auto 0;
    width: 100%;
    max-width: 320px;
    text-align: center;
    background: var(--bg-light);
    border: 1px solid rgba(0, 0, 0, 0.5);
    padding: 1rem 1.25rem;
}

.title-leaderboard.hidden { display: none; }

/* Divider HR removed — the box outline does the section break now. Keep
   the rule as a no-op so any cached CSS that targets it doesn't 404. */
.title-leaderboard-divider { display: none; }

.title-leaderboard-heading {
    font-family: 'Press Start 2P', monospace;
    font-size: 0.7rem;
    letter-spacing: 1px;
    color: var(--fg-dim);
    text-transform: uppercase;
    margin: 0 0 0.75rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.35);
}

.title-leaderboard-list {
    list-style: none;
    padding: 0;
    margin: 0 0 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0;
}

.title-leaderboard-list li {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.75rem;
    align-items: baseline;
    font-size: 1.125rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}

.title-leaderboard-list li:last-child {
    border-bottom: none;
}

.tlb-rank {
    font-family: 'Press Start 2P', monospace;
    font-size: 0.75rem;
    color: var(--accent);
    min-width: 1.5em;
    text-align: left;
}

.tlb-name {
    color: var(--fg);
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tlb-score {
    font-family: 'Press Start 2P', monospace;
    font-size: 0.8rem;
    color: var(--fg);
}

.title-leaderboard-link {
    display: inline-block;
    font-size: 1rem;
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
    letter-spacing: 1px;
}

.title-leaderboard-link:hover {
    color: var(--btn);
}

.title-leaderboard-link:focus-visible {
    color: var(--btn);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

@media (max-width: 520px) {
    .attribution { font-size: 0.9rem; margin-bottom: 1.25rem; }
    .title-leaderboard { margin-top: 2rem; max-width: 280px; padding: 0.85rem 1rem; }
    .title-leaderboard-heading { font-size: 0.6rem; }
    .title-leaderboard-list li { font-size: 1rem; padding: 0.35rem 0; }
    .tlb-rank { font-size: 0.65rem; }
    .tlb-score { font-size: 0.7rem; }
}

/* Scout hero sprite — 128x128 source. Exact 1:1 display keeps features crisp
   (non-integer scale erases small features like eyes/snout). object-fit
   contain is a safety net against any future size mismatch. */
.scout-hero {
    display: block;
    width: 128px;
    height: 128px;
    margin: 0.5rem auto 1.25rem;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    object-fit: contain;
}

/* Title-screen hero is the painted FLX trail-sign artwork. PNG ships with a
   transparent background (edge flood-fill in the asset pipeline), so it sits
   directly on --bg with no beige rectangle behind it. Width-only sizing lets
   the natural aspect of the cropped artwork drive the height. */
.scout-hero-title {
    width: min(380px, 80vw);
    height: auto;
    margin: 0.75rem auto 1.5rem;
}

/* Sparkle overlay wrapper — positions sparkles absolutely over the lake
   region of the hero image. The wrap takes over the hero's outer margins
   so the sparkles inherit the image's flowed position. */
.title-hero-wrap {
    position: relative;
    display: block;
    width: min(380px, 80vw);
    margin: 0.75rem auto 1.5rem;
}

.title-hero-wrap .scout-hero-title {
    width: 100%;
    margin: 0;
    display: block;
}

/* Water-sparkle dots — Adam's 2026-05-01 ask: "if the water in the Pixel
   image was sparkling, not fast, just kind of slow, but just adding that
   little bit of animation." Five dots positioned over the lake, slow
   staggered twinkle, no movement (static position, just opacity+scale). */
.sparkle {
    position: absolute;
    width: 4px;
    height: 4px;
    background: #ffffff;
    border-radius: 50%;
    opacity: 0;
    box-shadow: 0 0 4px #ffffff, 0 0 8px rgba(255, 255, 255, 0.6);
    animation: water-sparkle 3.6s ease-in-out infinite;
    pointer-events: none;
}

.sparkle.s1 { top: 30%; left: 42%; animation-delay: 0s; }
.sparkle.s2 { top: 28%; left: 56%; animation-delay: 1.2s; }
.sparkle.s3 { top: 32%; left: 62%; animation-delay: 2.4s; }
.sparkle.s4 { top: 38%; left: 48%; animation-delay: 0.6s; }
.sparkle.s5 { top: 36%; left: 60%; animation-delay: 1.8s; }

@keyframes water-sparkle {
    0%, 100% { opacity: 0; transform: scale(0.5); }
    50% { opacity: 0.95; transform: scale(1.3); }
}

@media (prefers-reduced-motion: reduce) {
    .sparkle { animation: none; opacity: 0; }
}

.scout-hero-finish {
    width: 96px;
    height: 96px;
    margin: 0.25rem auto 0.5rem;
}

/* Finish-screen duo: chosen player avatar + Scout side-by-side. Adam's
   2026-05-01 video review wanted the player sprite to also appear here,
   not just Scout, so the climax shows the duo. The player sprite source
   is set in main.js showFinish() based on state.character. */
.finish-duo {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: 0.75rem;
    margin: 0.75rem auto 1rem;
}

.finish-duo-sprite {
    width: 96px;
    height: 96px;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    object-fit: contain;
}

/* Character selection — sits between title and game.
   Two cards side by side, keyboard-navigable, tap-friendly for mobile. */
.select-heading {
    font-family: 'Press Start 2P', monospace;
    font-size: 1.1rem;
    color: var(--accent);
    letter-spacing: 1px;
    margin-bottom: 2rem;
}

.select-row {
    display: flex;
    justify-content: center;
    gap: 1.75rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.select-card {
    background: var(--bg-light);
    border: 3px solid var(--border);
    padding: 1rem 1rem 0.75rem;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    box-shadow: 4px 4px 0 var(--shadow);
    transition: transform 120ms, border-color 120ms, box-shadow 120ms;
    font-family: 'VT323', monospace;
    color: var(--fg);
}

.select-card:hover,
.select-card:focus-visible {
    border-color: var(--accent);
    transform: translate(-2px, -2px);
    box-shadow: 6px 6px 0 var(--shadow);
    outline: none;
}

.select-card img {
    display: block;
    width: 128px;
    height: 128px;
    margin: 0 auto;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    object-fit: contain;
}

.select-label {
    font-size: 1.5rem;
    letter-spacing: 1px;
}

.select-hint {
    font-size: 1.1rem;
    color: var(--fg-dim);
    font-style: italic;
}

/* Narrow viewports — 2 columns, smaller sprites, tighter padding so all 5
   cards fit without scrolling on a Pixel-class phone (~360-400px wide). */
@media (max-width: 520px) {
    .select-heading { margin-bottom: 1rem; font-size: 0.95rem; }
    .select-row { gap: 0.75rem; }
    .select-card {
        flex: 0 0 calc(50% - 0.5rem);
        max-width: calc(50% - 0.5rem);
        padding: 0.5rem 0.5rem 0.4rem;
        gap: 0.25rem;
    }
    .select-card img { width: 88px; height: 88px; }
    .select-label { font-size: 1.25rem; }
}

/* Prologue screen — Friday-morning weekend planning beat that sits between
   character select and the game world. Visual language parallels .select-card
   so the player reads "this is a choice" the same way. The background image
   is a scene illustration above the choices (not a full-screen backdrop) to
   keep heading + prompt + cards readable on every viewport. */
.prologue-bg-wrap {
    display: flex;
    justify-content: center;
    margin-bottom: 1.25rem;
}

.prologue-bg {
    display: block;
    max-width: 100%;
    width: auto;
    max-height: 240px;
    border: 3px solid var(--border);
    box-shadow: 4px 4px 0 var(--shadow);
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    object-fit: contain;
}

.prologue-heading {
    font-family: 'Press Start 2P', monospace;
    font-size: 1.1rem;
    color: var(--accent);
    letter-spacing: 1px;
    margin-bottom: 0.75rem;
}

.prologue-prompt {
    font-size: 1.375rem;
    line-height: 1.4;
    color: var(--fg-dim);
    margin-bottom: 1.5rem;
}

.prologue-choices {
    display: flex;
    justify-content: center;
    gap: 1.25rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.prologue-card {
    background: var(--bg-light);
    border: 3px solid var(--border);
    padding: 1rem 1rem 0.75rem;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    box-shadow: 4px 4px 0 var(--shadow);
    transition: transform 120ms, border-color 120ms, box-shadow 120ms, opacity 120ms;
    font-family: 'VT323', monospace;
    color: var(--fg);
    width: 180px;
}

.prologue-card:hover:not(:disabled),
.prologue-card:focus-visible:not(:disabled) {
    border-color: var(--accent);
    transform: translate(-2px, -2px);
    box-shadow: 6px 6px 0 var(--shadow);
    outline: none;
}

.prologue-card:disabled {
    cursor: default;
}

.prologue-card img {
    width: 96px;
    height: 96px;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    object-fit: contain;
}

.prologue-label {
    font-size: 1.25rem;
    letter-spacing: 1px;
    line-height: 1.2;
    text-align: center;
}

.prologue-card-faded {
    opacity: 0.45;
}

.prologue-result {
    max-width: 560px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

.prologue-result.hidden { display: none; }

.prologue-result p {
    font-size: 1.25rem;
    line-height: 1.5;
    color: var(--fg);
    background: var(--bg-light);
    border: 2px solid var(--border);
    padding: 1rem 1.25rem;
    text-align: left;
}

/* Narrow viewports — 2 cards side-by-side, 3rd centered below. Sized so the
   prologue prompt + cards + result button fit without scrolling. */
@media (max-width: 520px) {
    .prologue-heading { margin-bottom: 0.5rem; font-size: 0.95rem; }
    .prologue-prompt { margin-bottom: 0.75rem; font-size: 1.2rem; }
    .prologue-bg { max-height: 140px; }
    .prologue-bg-wrap { margin-bottom: 0.75rem; }
    .prologue-choices {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.6rem;
        max-width: 360px;
        margin-left: auto;
        margin-right: auto;
        margin-bottom: 1rem;
    }
    .prologue-card {
        width: 100%;
        padding: 0.5rem 0.5rem 0.4rem;
        gap: 0.25rem;
    }
    .prologue-card:nth-child(3) {
        grid-column: 1 / -1;
        justify-self: center;
        max-width: calc(50% - 0.3rem);
    }
    .prologue-card img { width: 64px; height: 64px; }
    .prologue-label { font-size: 1.05rem; }
}

/* Celebration overlay — confetti falling + balloons rising on finish screen.
   Full-viewport fixed, non-interactive. Elements are DOM-injected by
   spawnCelebration() in main.js and animate via these keyframes. */
.celebration {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 100;
}

.confetti {
    position: absolute;
    top: -24px;
    width: 10px;
    height: 14px;
    opacity: 0;
    animation: confetti-fall linear forwards;
}

@keyframes confetti-fall {
    0%   { transform: translate3d(0, -24px, 0) rotate(0deg); opacity: 1; }
    85%  { opacity: 1; }
    100% { transform: translate3d(var(--drift, 0), 110vh, 0) rotate(var(--spin, 720deg)); opacity: 0; }
}

.balloon {
    position: absolute;
    bottom: -80px;
    width: 34px;
    height: 42px;
    border-radius: 50% 50% 48% 48%;
    opacity: 0;
    box-shadow: inset -5px -6px 0 rgba(0, 0, 0, 0.18),
                inset 4px 4px 0 rgba(255, 255, 255, 0.22);
    animation: balloon-rise ease-out forwards;
}

/* Tiny triangular "tie" under the balloon body. Border longhand needed
   because `border-top: 5px solid inherit` is invalid shorthand (the CSS-wide
   `inherit` keyword can't share a shorthand with other values), so the whole
   declaration gets discarded and the tie disappears. */
.balloon::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 100%;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top-width: 5px;
    border-top-style: solid;
    border-top-color: currentColor;
    transform: translateX(-50%);
    opacity: 0.8;
}

/* Balloon string */
.balloon::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    width: 1px;
    height: 48px;
    background: rgba(255, 255, 255, 0.35);
    transform: translateX(-50%);
    margin-top: 3px;
}

@keyframes balloon-rise {
    0%   { transform: translate3d(0, 0, 0); opacity: 0; }
    10%  { opacity: 1; }
    90%  { opacity: 1; }
    100% { transform: translate3d(var(--drift, 0), -120vh, 0); opacity: 0; }
}

/* Wilderness-flair trees — fires when the player hits the bottom-right
   easter egg. Replaced the original creepy wood-elf sprite (2026-05-01)
   with a friendly deciduous tree per Adam's "maple/oak slightly waving in
   the wind" direction. Internal class name kept as .wood-elf to avoid
   churn; the sprite + animation are re-themed but the trigger is the same. */
.wood-elf {
    position: absolute;
    top: -72px;
    width: 64px;
    height: 64px;
    background-image: url("assets/sprites/tree_deciduous.png");
    background-size: contain;
    background-repeat: no-repeat;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    opacity: 0;
    transform-origin: 50% 95%;  /* sway from the trunk base, not the canopy */
    animation: wood-elf-drift ease-in-out forwards;
}

/* Trees drift across the viewport with a gentle wind-rustle sway. Lower
   rotation amplitude than the original wobble to read as "blowing in the
   wind" rather than "cartoon wobble," matching the lighthearted-but-
   ambient framing Adam wanted. */
@keyframes wood-elf-drift {
    0%   { transform: translate3d(0, 0, 0) rotate(-3deg); opacity: 0; }
    10%  { opacity: 1; }
    25%  { transform: translate3d(calc(var(--drift, 50vw) * 0.25), 6vh, 0) rotate(3deg); }
    50%  { transform: translate3d(calc(var(--drift, 50vw) * 0.5), 12vh, 0) rotate(-2deg); }
    75%  { transform: translate3d(calc(var(--drift, 50vw) * 0.75), 6vh, 0) rotate(2deg); }
    90%  { opacity: 1; }
    100% { transform: translate3d(var(--drift, 100vw), 0, 0) rotate(0deg); opacity: 0; }
}

/* Respect reduced-motion users — skip the bouncy celebration. */
@media (prefers-reduced-motion: reduce) {
    .confetti, .balloon, .wood-elf { display: none; }
}

/* Game canvas */
#game-container:not(.hidden) {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.canvas-wrap {
    position: relative;
    display: inline-block;
    max-width: 100%;
    line-height: 0;  /* kill inline-block whitespace below canvas */
}

#game {
    border: 3px solid var(--border);
    box-shadow: 6px 6px 0 var(--shadow);
    max-width: 100%;
    image-rendering: pixelated;
}

/* Map establishing-shot fade overlay. Sits over the canvas during the
   1.5s "show the whole Finger Lakes for context" beat at startGame, then
   fades while the camera switches to a 1.5x follow-cam on the player. */
.map-fade {
    position: absolute;
    inset: 0;
    background: var(--bg);
    opacity: 0;
    pointer-events: none;
    z-index: 4;
    transition: opacity 220ms ease;
}

.map-fade.fade-on { opacity: 1; }

/* Mute button — sits over the canvas, top-right. Always visible. */
.mute-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 5;
    font-family: 'Press Start 2P', monospace;
    font-size: 0.55rem;
    letter-spacing: 1px;
    padding: 0.45rem 0.65rem;
    background: rgba(42, 31, 26, 0.85);
    color: var(--fg);
    border: 2px solid var(--border);
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    line-height: 1;
}

.mute-btn:hover { background: var(--btn); }
.mute-btn[aria-pressed="true"] { color: var(--fg-dim); }

/* Touch d-pad — hidden by default, shown on coarse-pointer / no-hover devices.
   Positioning lives in the base rule so the media query only toggles display. */
.touch-controls {
    display: none;
    position: absolute;
    bottom: 14px;
    left: 14px;
    grid-template-columns: repeat(3, 48px);
    grid-template-rows: repeat(3, 48px);
    gap: 4px;
    z-index: 5;
    touch-action: none;
}

@media (pointer: coarse), (hover: none) {
    .touch-controls { display: grid; }
}

.dpad-btn {
    background: rgba(42, 31, 26, 0.78);
    color: var(--fg);
    border: 2px solid var(--border);
    font-size: 1.1rem;
    cursor: pointer;
    user-select: none;
    touch-action: none;
    -webkit-tap-highlight-color: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'VT323', monospace;
    line-height: 1;
    padding: 0;
}

.dpad-btn:active,
.dpad-btn.pressed { background: var(--btn); }

.dpad-up    { grid-column: 2; grid-row: 1; }
.dpad-left  { grid-column: 1; grid-row: 2; }
.dpad-right { grid-column: 3; grid-row: 2; }
.dpad-down  { grid-column: 2; grid-row: 3; }

#hud {
    display: flex;
    gap: 1.5rem;
    margin-top: 0.75rem;
    font-family: 'Press Start 2P', monospace;
    font-size: 0.75rem;
    color: var(--fg-dim);
}

.hud-item { letter-spacing: 1px; }

/* Dialogue overlay */
#dialogue-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 1rem;
    z-index: 10;
}

#dialogue-overlay.hidden { display: none; }

/* On portrait mobile, centering distributes the empty space evenly above
   and below the dialogue card. flex-end (default) sticks it at the bottom
   and leaves a black band on top — felt asymmetric on the Pixel 10 review. */
@media (max-width: 520px) {
    #dialogue-overlay { align-items: center; }
}

.dialogue-box {
    width: 100%;
    max-width: 640px;
    background: var(--bg-light);
    border: 3px solid var(--border);
    box-shadow: 6px 6px 0 var(--shadow);
    padding: 1.5rem;
    font-size: 1.375rem;
    line-height: 1.5;
}

/* Per-waypoint scene art — 3:2 banner pixel-art illustration that fills the
   dialogue width edge-to-edge above the prompt text. Hidden until openEvent()
   sets a src; the .hidden class display-overrides keep it from reserving
   vertical space when a dialogue (e.g. easter egg) has no scene of its own.

   Sizing notes: the image needs to scale to BOTH dialogue width and viewport
   height. Pure width:100%+aspect-ratio overflowed shorter desktop viewports
   (laptops with browser chrome left ~750px tall; the 426px-tall image plus
   text and buttons pushed the top of the dialogue off-screen — confirmed via
   2026-05-09 Loom). max-height:45vh + width:auto + aspect-ratio + max-width:100%
   lets the browser pick the binding constraint and scale the whole image
   instead of cropping. */
.dialogue-scene {
    display: block;
    max-width: 100%;
    max-height: 45vh;
    width: auto;
    height: auto;
    aspect-ratio: 3 / 2;
    margin: 0 auto 1rem;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
}

.dialogue-scene.hidden { display: none; }

#dialogue-text {
    margin-bottom: 1rem;
    min-height: 3rem;
    white-space: pre-line;  /* preserve the \n\n between event text and clue */
}

#dialogue-choices {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.choice-btn {
    font-family: 'VT323', monospace;
    font-size: 1.25rem;
    padding: 0.5rem 0.75rem;
    background: transparent;
    color: var(--fg);
    border: 2px solid var(--border);
    cursor: pointer;
    text-align: left;
    transition: background 120ms, color 120ms;
}

.choice-btn:hover:not(:disabled) {
    background: var(--accent);
    color: var(--bg);
}

.choice-btn:disabled,
.choice-btn-wrong {
    opacity: 0.35;
    cursor: not-allowed;
    text-decoration: line-through;
}

/* Finish screen */
.final-score {
    font-family: 'Press Start 2P', monospace;
    font-size: 1.1rem;
    color: var(--accent);
    margin-bottom: 0.35rem;
    letter-spacing: 1px;
}

.bonus-note {
    font-size: 1rem;
    color: var(--accent-2);
    margin-bottom: 0.5rem;
    font-style: italic;
}

#save-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem 0.75rem;
    max-width: 520px;
    margin: 0 auto 0.5rem;
}

#save-form input {
    font-family: 'VT323', monospace;
    font-size: 1.125rem;
    padding: 0.5rem 0.65rem;
    background: var(--bg-light);
    color: var(--fg);
    border: 2px solid var(--border);
}

#save-form button {
    grid-column: 1 / -1;
    justify-self: center;
}

/* Narrow viewports (mobile) — stack inputs full-width. */
@media (max-width: 520px) {
    #save-form { grid-template-columns: 1fr; max-width: 360px; }
}

#save-form input:focus {
    outline: none;
    border-color: var(--accent);
}

.save-status {
    font-size: 1.125rem;
    color: var(--fg-dim);
    margin-top: 1rem;
}

/* Quiet note under Save My Score: only the player's highest score is kept
   on the leaderboard, so replays don't count as separate entries. Adam's
   2026-05-01 phone review wanted this surfaced so replayers don't expect
   each run to add a new row. */
.save-disclaimer {
    font-size: 0.95rem;
    color: var(--fg-dim);
    opacity: 0.7;
    margin-top: 0.5rem;
    font-style: italic;
}

.save-status.success { color: var(--accent-2); }
.save-status.error { color: #e25c5c; }

/* Leaderboard link — default <a> blue is illegible on the dark brown bg. */
.lb-back {
    color: var(--fg);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.lb-back:hover {
    color: var(--accent);
}

/* Reciprocal link to FLX Match. Trail's contest is over and Match is the live
   daily, so this points forward rather than competing for the same click. A
   proper game shelf at / is Stage 2; this closes the one-way gap until then. */
.cross-game {
    margin-top: 14px;
    font-size: 1.05rem;
    color: var(--fg-dim);
}
.cross-game a { color: var(--btn); }
