* { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Body uses a friendly humanist sans for legibility; the "chunky" font
   stack below is reserved for the kid-facing UI (title, buttons, hint,
   panel labels) where the playful Comic-Sans-ish feel does the most. */
:root {
    --font-body:   'Trebuchet MS', 'Verdana', system-ui, sans-serif;
    --font-chunky: 'Comic Sans MS', 'Marker Felt', 'Chalkboard SE',
                   'Bradley Hand', 'Trebuchet MS', cursive, sans-serif;
    /* Caveat is loaded via Google Fonts in index.html. The fallback chain
       degrades to the chunky stack so the title still feels playful if
       the network call is blocked / hasn't finished. */
    --font-cursive: 'Caveat', 'Marker Felt', 'Bradley Hand', cursive,
                    var(--font-chunky);
}

html, body {
    margin: 0;
    padding: 0;
    font-family: var(--font-body);
    background:
        radial-gradient(ellipse at top, #3b1f6b 0%, transparent 60%),
        radial-gradient(ellipse at bottom right, #ff6ec7 0%, transparent 50%),
        linear-gradient(180deg, #1a0f33 0%, #2b1454 100%);
    background-attachment: fixed;
    color: #fff;
    /* 100vh on mobile Safari/Chrome includes the area behind the URL bar,
       so the page is taller than the visible viewport on first paint and
       can jump when the bar collapses. 100dvh is the dynamic viewport
       height that accounts for retracting toolbars. The vh line is the
       fallback for browsers without dvh support. */
    min-height: 100vh;
    min-height: 100dvh;
    overflow-x: hidden;
    -webkit-tap-highlight-color: transparent;
}

/* ============ TOP-EDGE OVERLAYS ============

   Back link, title, and currency pill float over the full-viewport
   stage as fixed elements. Nothing in the document flow reserves space
   for them. */

.back-floating {
    position: fixed;
    top: 12px;
    left: 12px;
    font-size: 18px;
    font-weight: bold;
    letter-spacing: 1px;
    text-decoration: none;
    color: #d6bdff;
    background: rgba(26, 15, 51, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.18);
    padding: 6px 10px;
    border-radius: 10px;
    line-height: 1;
    transition: background 0.15s;
    z-index: 110;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
@media (hover: hover) {
    .back-floating:hover { background: rgba(0, 255, 204, 0.22); }
}

.title-overlay {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    z-index: 105;
    /* Sized so it sits cleanly between the back link (left, ~46px wide
       at top: 12px) and the currency pill (right, ~80-110px wide).
       max-width is conservative on phones so the title never grows
       into the back/currency rectangles. */
    max-width: calc(100vw - 200px);
    padding: 2px 14px 6px;
    border-radius: 0 0 16px 16px;
    background:
        radial-gradient(ellipse 100% 100% at 50% 0%, rgba(255, 110, 199, 0.22) 0%, transparent 70%),
        rgba(26, 15, 51, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-top: none;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    pointer-events: none;
    text-align: center;
}
.title-overlay h1 {
    margin: 0;
    font-family: var(--font-cursive);
    font-size: 30px;
    letter-spacing: 0;
    color: #00ffcc;
    line-height: 1;
    text-shadow:
        0 0 14px rgba(0, 255, 204, 0.45),
        0 2px 0 #1a0f33;
    transform: rotate(-1.5deg);
    display: inline-block;
}
.title-overlay h1 .neon-pink {
    color: #ff6ec7;
    text-shadow:
        0 0 14px rgba(255, 110, 199, 0.55),
        0 2px 0 #1a0f33;
    display: inline-block;
    transform: rotate(3deg);
}
.title-overlay .tagline {
    margin: 2px 0 0;
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #d6bdff;
    line-height: 1.1;
    white-space: nowrap;
    /* Hidden on phones — the 38-char tagline can't share a top-row
       with the back link + currency pill on a 375-wide viewport.
       Tablet+ has the breathing room. */
    display: none;
}
@media (min-width: 480px) {
    .title-overlay { padding: 4px 18px 8px; max-width: calc(100vw - 240px); }
    .title-overlay h1 { font-size: 38px; }
}
@media (min-width: 720px) {
    .title-overlay { padding: 6px 24px 10px; }
    .title-overlay h1 { font-size: 48px; }
    .title-overlay .tagline { display: block; font-size: 11px; letter-spacing: 1.4px; }
}

/* Hide title during dance so the figure has the whole frame to itself. */
body.dancing .title-overlay { opacity: 0; transition: opacity 0.3s; }

/* Currency pill — top-right fixed overlay. Yellow accent because
   Doodles are a value/score. Label collapses on small phones so the
   pill stays compact. Hidden during dance to clear visual noise. */
.currency-pill {
    position: fixed;
    top: 12px;
    right: 12px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 20px;
    background: rgba(26, 15, 51, 0.55);
    border: 1px solid rgba(255, 210, 63, 0.5);
    color: #ffd23f;
    font-size: 13px;
    font-weight: bold;
    letter-spacing: 0.5px;
    z-index: 110;
    box-shadow:
        0 2px 8px rgba(0, 0, 0, 0.4),
        inset 0 0 8px rgba(255, 210, 63, 0.08);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
body.dancing .currency-pill { opacity: 0; transition: opacity 0.3s; }
.currency-icon { font-size: 16px; line-height: 1; }
.currency-value { font-variant-numeric: tabular-nums; }

/* Face-zoom toggle — big round tap target on the right edge, mid-
   height: clear of the home link (top-left), title (top-centre),
   currency pill (top-right) and the tool dock (bottom). Same glassy
   language as the currency pill. Hidden during dance (can't draw-zoom
   while grooving, and starting a dance exits zoom anyway). */
.face-zoom-btn {
    position: fixed;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    z-index: 106;
    width: 52px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    line-height: 1;
    border-radius: 50%;
    background: rgba(26, 15, 51, 0.55);
    border: 1px solid rgba(0, 255, 204, 0.55);
    color: #fff;
    cursor: pointer;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}
.face-zoom-btn:hover {
    background: rgba(26, 15, 51, 0.72);
    border-color: rgba(0, 255, 204, 0.9);
}
.face-zoom-btn.active {
    background: rgba(255, 110, 199, 0.32);
    border-color: #ff6ec7;
    box-shadow: 0 0 14px rgba(255, 110, 199, 0.6);
}
body.dancing .face-zoom-btn { display: none; }
.currency-label {
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    opacity: 0.85;
}
@media (max-width: 480px) {
    /* Just "🪙 45" on phones — keeps the pill out of the title's way. */
    .currency-label { display: none; }
}

/* Brief scale pulse when the value changes. Triggered via JS by adding
   .bump to the pill — animation removes itself with animationend. */
.currency-pill.bump {
    animation: currencyBump 0.45s ease-out;
}
@keyframes currencyBump {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.18); }
    100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .currency-pill.bump { animation: none; }
}

/* ============ BACKGROUND PICKER ============

   Lives inside the Stage drawer. Just a flex-wrap grid of thumbnail
   buttons — the wrapping drawer-section provides the panel chrome. */

.bg-picker {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}

/* ============ POSE PICKER ============

   Sits in the Stage drawer above the background picker. Buttons are
   generated by buildPosePicker() from the POSES dictionary in
   game.js, so adding a new pose grows the UI automatically. */

.pose-picker {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}

.pose-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 72px;
    min-height: 60px;
    padding: 8px 4px;
    background: rgba(0, 0, 0, 0.3);
    border: 2px solid rgba(0, 255, 204, 0.4);
    border-radius: 12px;
    color: #fff;
    font-family: var(--font-chunky);
    font-size: 10px;
    letter-spacing: 0.5px;
    font-weight: bold;
    text-transform: uppercase;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
.pose-btn .pose-icon { font-size: 22px; line-height: 1; }
.pose-btn .pose-name { line-height: 1; }
.pose-btn:active { transform: scale(0.96); }
.pose-btn.active {
    border-color: #ff6ec7;
    background:
        radial-gradient(ellipse 100% 60% at 50% 0%, rgba(255, 110, 199, 0.22) 0%, transparent 70%),
        rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 12px rgba(255, 110, 199, 0.35);
}
@media (hover: hover) {
    .pose-btn:hover {
        border-color: #00ffcc;
        background: rgba(0, 255, 204, 0.18);
    }
}

.bg-thumb {
    width: 50px;
    height: 50px;
    border-radius: 10px;
    border: 2px solid rgba(255, 255, 255, 0.2);
    background: transparent;
    cursor: pointer;
    padding: 3px;
    transition: transform 0.1s, border-color 0.1s;
    overflow: hidden;
}

@media (hover: hover) {
    .bg-thumb:hover { transform: scale(1.05); }
}

.bg-thumb.active {
    border-color: #00ffcc;
    box-shadow: 0 0 10px rgba(0, 255, 204, 0.5);
}

.bg-preview {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 6px;
}

/* ============ STAGE & CREATURE ============

   Stage fills the entire viewport — no scroll to compete between the
   canvas and tools. The figure inside (.creature) keeps its native
   400x600 logical box via the SVG layers' preserveAspectRatio="meet";
   on viewports that don't match 2:3 (most phones), the background
   color shows around the figure in the letterbox region. */

.stage {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
    z-index: 1;
}

/* Override of the .creature rule defined below — fits the figure into
   the largest 2:3 box that fills the viewport without distorting. The
   left/right/top/bottom: 0 with margin: auto centers an explicitly
   sized element on both axes. min() picks whichever dimension is the
   limit (height on portrait phones, width on landscape / desktop). */
.stage > .creature {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    margin: auto;
    /* 0.85 of the largest fitting 2:3 box leaves ~7.5% slack top+bottom.
       The figure's head art starts only ~5.7% down its own viewBox, so
       headroom is tight: the dance jump's upward components (translateY
       AND the hop scale-stretch about the near-feet origin) are trimmed
       in applyMove() so even the wildest PARTY peak clears the viewport
       top on viewports down to ~500px tall (.stage is overflow:hidden).
       The pattern layer uses the IDENTICAL formula so the static-pattern
       window stays pixel-aligned with the body. */
    width: calc(min(100vw, 100dvh * 2 / 3) * 0.85);
    height: calc(min(100dvh, 100vw * 3 / 2) * 0.85);
    z-index: 2;
}

/* Stage floor is positioned via percentages relative to .creature, so
   it follows the figure's centered 2:3 box. */

.bg-layer {
    position: absolute;
    inset: 0;
    z-index: 0;
    transition: background 0.3s;
}

/* ----- background variants (also reused for thumbnails) ----- */

.bg-studio {
    /* Studio = clean white-to-cool-gray with the pink floor glow.
       Replaced the prior cream / peach gradient since cream clashes with
       the onioncore dark / teal / pink palette used across the rest of
       Madderverse. The faint lavender tint at the bottom edge picks up
       the page background's purple so the canvas frames into the page
       rather than sitting on it as a bright slab. */
    background:
        radial-gradient(ellipse 70% 28% at 50% 92%, rgba(255, 110, 199, 0.22) 0%, transparent 70%),
        linear-gradient(180deg, #ffffff 0%, #fafafa 60%, #ececf4 100%);
}

.bg-disco {
    background:
        radial-gradient(circle at 20% 20%, rgba(255, 220, 100, 0.5) 0%, transparent 30%),
        radial-gradient(circle at 80% 30%, rgba(255, 110, 199, 0.55) 0%, transparent 30%),
        radial-gradient(circle at 50% 80%, rgba(0, 200, 255, 0.4) 0%, transparent 35%),
        linear-gradient(180deg, #2a0a4a 0%, #4d1c8a 100%);
}

.bg-outdoors {
    background:
        radial-gradient(circle at 80% 25%, #fff8c0 0%, transparent 12%),
        linear-gradient(180deg, #87ceeb 0%, #b6e0f5 60%, #6fbf52 60%, #4a9b34 100%);
}

.bg-night {
    background:
        radial-gradient(circle at 20% 25%, #fff 0%, transparent 0.5%),
        radial-gradient(circle at 78% 18%, #fff 0%, transparent 0.4%),
        radial-gradient(circle at 35% 60%, #fff 0%, transparent 0.4%),
        radial-gradient(circle at 65% 75%, #fff 0%, transparent 0.5%),
        radial-gradient(circle at 88% 55%, #fff 0%, transparent 0.4%),
        radial-gradient(circle at 50% 30%, rgba(255, 255, 200, 0.9) 0%, transparent 4%),
        linear-gradient(180deg, #0a1838 0%, #1a2c5a 100%);
}

.bg-sunset {
    /* Warm horizon-to-zenith gradient with a sun glow at the bottom-right.
       Pink → orange → gold horizon. */
    background:
        radial-gradient(circle at 78% 78%, #ffd23f 0%, rgba(255, 210, 63, 0.4) 6%, transparent 14%),
        linear-gradient(180deg, #2b1454 0%, #7209b7 22%, #ff6ec7 55%, #ff9966 78%, #ffd23f 100%);
}

.bg-underwater {
    /* Deep blue with bubbles + a few highlight orbs near the surface. */
    background:
        radial-gradient(circle at 22% 18%, rgba(255, 255, 255, 0.55) 0%, transparent 3%),
        radial-gradient(circle at 62% 30%, rgba(255, 255, 255, 0.45) 0%, transparent 2.5%),
        radial-gradient(circle at 78% 60%, rgba(135, 206, 235, 0.55) 0%, transparent 3%),
        radial-gradient(circle at 38% 75%, rgba(255, 255, 255, 0.4) 0%, transparent 2%),
        radial-gradient(circle at 18% 50%, rgba(0, 255, 204, 0.3) 0%, transparent 2.5%),
        radial-gradient(ellipse 80% 30% at 50% 0%, rgba(135, 206, 235, 0.4) 0%, transparent 70%),
        linear-gradient(180deg, #1f5f9c 0%, #143560 60%, #0a1f3a 100%);
}

.bg-stadium {
    /* Dark concert venue with crossing spotlight beams of neon pink,
       teal, and gold sweeping in from the corners. */
    background:
        linear-gradient(125deg, rgba(255, 110, 199, 0.4) 0%, transparent 38%),
        linear-gradient(55deg,  rgba(0, 255, 204, 0.38) 0%, transparent 40%),
        linear-gradient(95deg,  rgba(255, 210, 63, 0.22) 0%, transparent 50%),
        radial-gradient(ellipse 60% 18% at 50% 88%, rgba(255, 110, 199, 0.28) 0%, transparent 70%),
        linear-gradient(180deg, #0a0518 0%, #2b1454 100%);
}

.bg-candy {
    /* Bright purple-to-pink base with a sprinkle of neon dots in the
       brand colors (teal, pink, gold, purple). */
    background:
        radial-gradient(circle at 15% 22%, #ff6ec7 0%, rgba(255, 110, 199, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 78% 14%, #00ffcc 0%, rgba(0, 255, 204, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 50% 55%, #ffd23f 0%, rgba(255, 210, 63, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 28% 78%, #7209b7 0%, rgba(114, 9, 183, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 84% 65%, #ff6ec7 0%, rgba(255, 110, 199, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 62% 88%, #00ffcc 0%, rgba(0, 255, 204, 0.6) 1.5%, transparent 3%),
        radial-gradient(circle at 12% 60%, #ffd23f 0%, rgba(255, 210, 63, 0.55) 1.5%, transparent 3%),
        linear-gradient(165deg, #7209b7 0%, #ff6ec7 100%);
}

.creature {
    position: absolute;
    inset: 0;
    z-index: 2;
    transform-origin: 50% 92%;
    /* No CSS transition on transform — applyMove() writes a new value
       every RAF tick, and a 40 ms transition on top of 16 ms writes
       was muddling visible motion on the larger full-viewport figure.
       will-change keeps the compositor layer warm. */
    will-change: transform;
}

/* Three stacked layers inside .creature:
     z 1  .silhouette-fill-layer       — pale interior wash, "coloring paper"
     z 2  .draw-canvas                 — the kid's strokes (clipped to body)
     z 3  .silhouette-outline-layer    — dark stroke on the same shapes; sits
                                          ABOVE the canvas so colors stop
                                          visually at the boundary instead
                                          of being clipped 5 px before it. */
.silhouette-fill-layer,
.silhouette-outline-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
.silhouette-fill-layer    { z-index: 1; }
.silhouette-outline-layer { z-index: 3; }

/* Hat layer sits above the outline so hats land on top of the head
   ring rather than being trimmed by it. Same absolute fill + no
   pointer events as the silhouette layers; the SVG inherits the
   creature's transform so hats dance with the figure. */
.hat-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 4;
}

/* Accessory layer sits above hats (z-index 5) so glasses can ride
   on top of a hat brim and a cape can wrap around the figure. Like
   the hat layer, it's unclipped — accessories can extend past the
   silhouette (capes, wings) and inherit the creature's dance
   transform. */
.accessory-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 5;
}

/* Face-parts layer: above the outline ring, below hats. Click-through
   (pointer-events:none) so freehand drawing passes straight through;
   only placed parts re-enable events so they can be dragged. Sits
   after .silhouette-outline-layer in the DOM so it paints above it at
   the shared z-index 3, while the hat layer (z4) still covers hair. */
.face-parts-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 3;
}
.face-parts-layer .face-part { pointer-events: auto; cursor: grab; }
.face-parts-layer .face-part:active { cursor: grabbing; }
/* Transparent (not none) so the grab box is hit-testable. */
.face-parts-layer .fp-hit { fill: transparent; }

/* Face-parts bank — one row per category in the Brush drawer. */
.face-bank { display: flex; flex-direction: column; gap: 10px; }
.face-row { display: flex; align-items: center; gap: 8px; }
.face-row-label {
    flex: 0 0 46px;
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #d6bdff;
}
.face-opts {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
}
.face-opt {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 10px;
    border: 2px solid rgba(255, 255, 255, 0.18);
    background: rgba(255, 255, 255, 0.92);
    cursor: pointer;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
}
.face-opt svg { display: block; width: 100%; height: 100%; }
.face-opt:active { transform: scale(0.92); }
.face-opt.active {
    border-color: #00ffcc;
    box-shadow: 0 0 8px rgba(0, 255, 204, 0.5);
}
.face-none {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.3);
    color: #d6bdff;
    font-size: 20px;
    line-height: 1;
}
@media (hover: hover) {
    .face-opt:hover { border-color: rgba(0, 255, 204, 0.6); }
}
.face-bank-hint {
    margin: 2px 0 0;
    font-size: 11px;
    color: rgba(214, 189, 255, 0.75);
    line-height: 1.3;
}

/* Static fill-pattern layer. Stage-level (NOT inside .creature) so
   the pattern field never inherits the dance transform — it stays
   locked to the stage. z-index 1: above the bg, below .creature, so
   the kid's strokes paint over it. #patternWinPath is the moving
   window: it gets the SAME CSS transform string as .creature each
   dance frame, and transform-box:view-box + a JS-synced
   transform-origin make that transform resolve identically to the
   body's, so the pattern reads as seen-through-a-dancing-body. */
/* MUST occupy the exact same centred 2:3 box as .creature (NOT the
   full viewport) — otherwise the SVG viewBox maps to a different
   rect than the body and the pattern lands off the figure. Same
   sizing formula as `.stage > .creature` (kept in lockstep with the
   shared 0.85 jump-headroom scale below). */
.stage > .pattern-layer {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    margin: auto;
    width: calc(min(100vw, 100dvh * 2 / 3) * 0.85);
    height: calc(min(100dvh, 100vw * 3 / 2) * 0.85);
    pointer-events: none;
    z-index: 1;
}
#patternWinPath {
    transform-box: view-box;
    transform-origin: 50% 92%;
}

/* Pale wash inside the silhouette so the kid sees the body shape even
   before any strokes — this is the "coloring page" surface. Slight cool
   tint (vs pure white) so the figure still reads as a distinct shape on
   the studio background (which is now off-white rather than cream); on
   the dark backgrounds — disco / outdoors / night — it still appears
   essentially white because the tint is so subtle. */
.silhouette-fill > * {
    fill: rgba(232, 232, 244, 0.94);
}

/* When a pattern is active the pale wash would hide it (the wash is
   inside .creature, z above the pattern layer). Make it transparent
   so the static pattern shows through as the body's backdrop; the
   kid still draws on top normally. */
body.has-pattern .silhouette-fill > * {
    fill: transparent;
}

/* Pattern picker — swatch row in the Brush drawer. Each swatch is a
   mini SVG tiled with that pattern; "None" (∅) clears it. */
.pattern-picker {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}
.pattern-swatch {
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 10px;
    border: 2px solid rgba(255, 255, 255, 0.18);
    background: rgba(0, 0, 0, 0.3);
    cursor: pointer;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
    transition: border-color 0.12s, transform 0.08s;
}
.pattern-swatch svg { display: block; width: 100%; height: 100%; }
.pattern-swatch:active { transform: scale(0.92); }
.pattern-swatch.active {
    border-color: #00ffcc;
    box-shadow: 0 0 8px rgba(0, 255, 204, 0.5);
}
.pattern-none {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #d6bdff;
    font-size: 20px;
    line-height: 1;
}
@media (hover: hover) {
    .pattern-swatch:hover { border-color: rgba(0, 255, 204, 0.6); }
}

/* Outline shapes provide the SourceAlpha that the
   #innerOutlineFilter operates on — the fill color is irrelevant
   because the filter only reads the alpha channel. We give them a
   visible fill anyway as a fallback in case the filter is unsupported
   (very old browser); in that case the kid sees a solid body, not
   an empty rectangle. */
.silhouette-outline > * {
    fill: #1a0f33;
}

.draw-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
    /* The canvas IS the page now (.stage fills the entire viewport),
       so the previous pan-y / drawing dance-of-heuristics is gone.
       touch-action: none means every touch becomes a draw event with
       no scroll competition. There's nothing below the canvas in the
       viewport that needs scrolling to reach — tools live as
       fixed-position dock overlays. */
    touch-action: none;
    cursor: crosshair;
    /* Drawing is clipped to the silhouette inside game.js via ctx.clip()
       on a Path2D built from BODY_SHAPES — see buildBodyPath() / buildCanvas.
       That clip is the single source of truth for "the drawable area";
       a CSS clip-path here would just duplicate the same mask. */
}

/* Dance mode no longer disables drawing — the draw canvas remains
   interactive so kids can keep editing while the creature grooves.
   The pointer-events: none rule that used to live here was deliberately
   removed; isPlaying checks inside the pointer handlers no-op strokes
   during dance instead, so we keep the cursor / hit-testing alive for
   the always-editable experience. */

.stage-floor {
    position: absolute;
    bottom: 2.5%;
    left: 50%;
    transform: translateX(-50%);
    width: 65%;
    height: 4%;
    background: radial-gradient(ellipse, rgba(0, 0, 0, 0.45) 0%, transparent 75%);
    border-radius: 50%;
    transform-origin: center center;
    pointer-events: none;
    transition: opacity 0.05s linear;
    z-index: 1;
}

/* Beat bubble pulses on each kick. */
.beat-bubble {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #ff6ec7;
    opacity: 0;
    pointer-events: none;
    box-shadow: 0 0 12px #ff6ec7;
    transition: opacity 0.06s linear, transform 0.06s linear;
    z-index: 5;
}

/* ============ MODAL ============

   Full-viewport overlay with a backdrop + sheet that slides up from
   the bottom on mobile and centers on larger screens. Used by the
   achievements board and (in the next commit) the hat shop. The whole
   element is [hidden] until openModal adds .open; the .open class
   triggers the slide-up + backdrop fade transitions. */

.modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    pointer-events: auto;
}

.modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 5, 25, 0.7);
    opacity: 0;
    transition: opacity 0.25s ease-out;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.modal.open .modal-backdrop { opacity: 1; }

.modal-sheet {
    position: relative;
    width: 100%;
    max-width: 600px;
    margin: 0 auto;
    background:
        radial-gradient(ellipse 80% 30% at 50% 0%, rgba(255, 110, 199, 0.22) 0%, transparent 70%),
        linear-gradient(170deg, #3b1f6b 0%, #1a0f33 100%);
    border: 3px solid rgba(0, 255, 204, 0.5);
    border-bottom: none;
    border-radius: 22px 22px 0 0;
    padding: 18px 16px 24px;
    max-height: 88vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Hide the native scrollbar — kept scroll behavior, dropped the
       chrome. The kid-friendly visual stays unbroken by a system
       scrollbar gutter. */
    scrollbar-width: none;        /* Firefox */
    -ms-overflow-style: none;     /* legacy IE / Edge */
    transform: translateY(100%);
    transition: transform 0.32s cubic-bezier(0.2, 0.9, 0.3, 1);
    box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.5);
}
.modal-sheet::-webkit-scrollbar { display: none; }  /* WebKit (Chrome / Safari) */
.modal.open .modal-sheet { transform: translateY(0); }

@media (min-width: 720px) {
    /* On desktop / tablet land, center the sheet vertically and round
       all four corners so it reads as a card rather than a bottom-sheet. */
    .modal { justify-content: center; padding: 24px; }
    .modal-sheet { border-radius: 22px; border-bottom: 3px solid rgba(0, 255, 204, 0.5); max-height: 80vh; }
}

@media (prefers-reduced-motion: reduce) {
    .modal-backdrop, .modal-sheet { transition: none; }
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 2px dashed rgba(0, 255, 204, 0.25);
}
.modal-header h2 {
    margin: 0;
    font-family: var(--font-cursive);
    /* Match drawer-head h2 (26px) so achievements/hat-shop reads as a
       big sibling to the drawers rather than a different component. */
    font-size: 26px;
    color: #ff6ec7;
    line-height: 1;
    text-shadow: 0 2px 0 #1a0f33;
}

.modal-close {
    appearance: none;
    background: rgba(255, 255, 255, 0.08);
    border: 2px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    font-size: 14px;
    cursor: pointer;
    line-height: 1;
    -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
    .modal-close:hover { background: rgba(255, 255, 255, 0.18); }
}

.modal-stats {
    text-align: center;
    font-size: 12px;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: #d6bdff;
    margin-bottom: 14px;
}

.modal-body { display: flex; flex-direction: column; gap: 10px; }

/* ============ WARDROBE TABS ============

   Pill-shaped tab bar between the balance line and the body grid in
   the Wardrobe modal. Each tab toggles its hat-grid / accessory-grid
   body panel via the [hidden] attribute (see attachWardrobeTabs in
   game.js). */

.wardrobe-tabs {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin-bottom: 14px;
}

.wardrobe-tab {
    flex: 0 1 auto;
    padding: 8px 18px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(255, 255, 255, 0.15);
    color: #d6bdff;
    font-family: inherit;
    font-size: 13px;
    font-weight: bold;
    letter-spacing: 0.6px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    min-height: 40px;
    transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.08s;
}
.wardrobe-tab:active { transform: scale(0.97); }
@media (hover: hover) {
    .wardrobe-tab:hover {
        background: rgba(0, 255, 204, 0.12);
        border-color: rgba(0, 255, 204, 0.4);
    }
}
.wardrobe-tab.active {
    background: linear-gradient(135deg, #ff6ec7 0%, #00ffcc 100%);
    border-color: rgba(255, 255, 255, 0.5);
    color: #1a0f33;
    box-shadow: 0 3px 10px rgba(255, 110, 199, 0.35);
}

/* Lock body scroll while a modal is open so swipes inside the modal
   don't accidentally scroll the page behind it. JS toggles this on
   <html> when openModal/closeModal run. */
.modal-open, .modal-open body {
    overflow: hidden;
    overscroll-behavior: contain;
}

/* ============ HAT SHOP ============ */

.hat-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}
@media (min-width: 480px) {
    .hat-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 720px) {
    .hat-grid { grid-template-columns: repeat(4, 1fr); }
}

.hat-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    transition: border-color 0.2s, background 0.2s, transform 0.1s;
}
.hat-card.owned {
    border-color: rgba(0, 255, 204, 0.5);
}
.hat-card.equipped {
    border-color: #ff6ec7;
    background:
        radial-gradient(ellipse 100% 60% at 50% 0%, rgba(255, 110, 199, 0.18) 0%, transparent 70%),
        rgba(0, 0, 0, 0.35);
    box-shadow: 0 0 14px rgba(255, 110, 199, 0.25);
}
.hat-card.locked { opacity: 0.65; }

.hat-preview {
    width: 100%;
    aspect-ratio: 1 / 1;
    background:
        radial-gradient(ellipse 80% 50% at 50% 90%, rgba(0, 0, 0, 0.25) 0%, transparent 70%),
        linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.02) 100%);
    border-radius: 10px;
    display: block;
}
/* The preview's silhouette head reuses the same wash tone as the
   in-stage figure so it reads as a mini-Groodle. */

.hat-name {
    font-size: 12px;
    font-weight: bold;
    text-align: center;
    line-height: 1.2;
    min-height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.hat-card.locked .hat-name { color: rgba(255, 255, 255, 0.55); }

.hat-action {
    width: 100%;
    padding: 7px 8px;
    border-radius: 10px;
    font-size: 11px;
    letter-spacing: 0.8px;
    font-weight: bold;
    text-transform: uppercase;
    border: 2px solid #1a0f33;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    min-height: 36px;
}
.hat-action.buy {
    background: linear-gradient(135deg, #ff6ec7 0%, #00ffcc 100%);
    color: #1a0f33;
    box-shadow: 0 3px 0 #1a0f33;
}
.hat-action.buy:active { transform: translateY(2px); box-shadow: 0 1px 0 #1a0f33; }
.hat-action.own {
    background: rgba(0, 255, 204, 0.18);
    border-color: #00ffcc;
    color: #fff;
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.35);
}
.hat-action.own:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35); }
.hat-action.equipped-tag {
    background: #ff6ec7;
    color: #1a0f33;
    border-color: #1a0f33;
    cursor: default;
}
.hat-action.locked-tag {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.55);
    cursor: not-allowed;
}
@media (hover: hover) {
    .hat-action.buy:hover { filter: brightness(1.06); }
    .hat-action.own:hover { background: rgba(0, 255, 204, 0.28); }
}

/* ============ ACHIEVEMENT CARDS ============ */

.ach-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    transition: border-color 0.2s, background 0.2s;
}
.ach-card.unlocked {
    border-color: rgba(0, 255, 204, 0.6);
    background:
        radial-gradient(ellipse 100% 100% at 100% 50%, rgba(0, 255, 204, 0.08) 0%, transparent 70%),
        rgba(0, 0, 0, 0.35);
}
.ach-icon {
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.06);
    border: 2px solid rgba(255, 255, 255, 0.15);
}
.ach-card.unlocked .ach-icon {
    background: linear-gradient(135deg, rgba(255, 110, 199, 0.35) 0%, rgba(0, 255, 204, 0.35) 100%);
    border-color: #00ffcc;
}
.ach-card.locked .ach-icon {
    filter: grayscale(1) brightness(0.6);
    opacity: 0.55;
}
.ach-body { flex: 1 1 auto; min-width: 0; }
.ach-title { font-weight: bold; font-size: 15px; color: #fff; line-height: 1.2; }
.ach-card.locked .ach-title { color: rgba(255, 255, 255, 0.5); }
.ach-desc { font-size: 12px; color: #d6bdff; margin-top: 2px; line-height: 1.3; }
.ach-card.locked .ach-desc { color: rgba(214, 189, 255, 0.5); }
.ach-reward {
    flex: 0 0 auto;
    font-size: 12px;
    font-weight: bold;
    color: #ffd23f;
    background: rgba(255, 210, 63, 0.12);
    border: 1px solid rgba(255, 210, 63, 0.45);
    border-radius: 14px;
    padding: 4px 10px;
    white-space: nowrap;
}
.ach-card.unlocked .ach-reward {
    background: rgba(255, 210, 63, 0.22);
    color: #1a0f33;
    background: #ffd23f;
}

/* ============ TOAST ============

   Slides down from the top, fixed position, stacks if multiple unlock
   in quick succession. Auto-dismisses; the JS queue drains one toast
   at a time so they don't pile on top of each other. */

.toast-container {
    position: fixed;
    top: 14px;
    left: 0;
    right: 0;
    z-index: 300;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

.achievement-toast {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px 10px 12px;
    background: linear-gradient(135deg, #ff6ec7 0%, #ffd23f 50%, #00ffcc 100%);
    color: #1a0f33;
    border: 3px solid #1a0f33;
    border-radius: 18px;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.5), 0 0 22px rgba(255, 110, 199, 0.35);
    max-width: min(94vw, 360px);
    transform: translateY(-140%);
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.2, 0.9, 0.3, 1), opacity 0.25s;
    pointer-events: auto;
}
.achievement-toast.show { transform: translateY(0); opacity: 1; }
.achievement-toast.hide { transform: translateY(-140%); opacity: 0; }

.toast-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    background: rgba(26, 15, 51, 0.18);
    border-radius: 50%;
    flex: 0 0 auto;
}
.toast-body { flex: 1 1 auto; min-width: 0; }
.toast-meta {
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 2px;
    text-transform: uppercase;
    opacity: 0.7;
    line-height: 1.2;
}
.toast-title { font-weight: bold; font-size: 14px; line-height: 1.2; }
.toast-reward { font-size: 12px; font-weight: bold; line-height: 1.2; margin-top: 2px; }

@media (prefers-reduced-motion: reduce) {
    .achievement-toast { transition: opacity 0.2s; transform: none; }
    .achievement-toast.show { transform: none; }
    .achievement-toast.hide { transform: none; }
}

/* ============ DRAWER CONTROLS ============

   Generic styles for the inputs that live inside drawers (palette,
   sizes, eraser, action buttons). The drawer chrome itself is below
   under DRAWER. */

.palette {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}

.swatch {
    /* 44px to meet the iOS / WCAG minimum tap target on phones; kid
       fingers especially aren't precise. */
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.3);
    cursor: pointer;
    padding: 0;
    transition: transform 0.1s, box-shadow 0.1s;
    flex: 0 0 auto;
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
}
@media (hover: hover) {
    .swatch:hover { transform: scale(1.1); }
}
.swatch.active {
    border-color: #00ffcc;
    box-shadow: 0 0 14px #00ffcc, inset 0 0 0 2px #1a0f33, 0 3px 0 rgba(0, 0, 0, 0.3);
    transform: scale(1.18);
}
.swatch[data-color="#ffffff"] { border-color: #999; }

.sizes {
    display: flex;
    gap: 6px;
}

.size-btn {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    border: 2px solid rgba(255, 255, 255, 0.2);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.1s, border-color 0.1s;
}
.size-btn.active {
    border-color: #00ffcc;
    background: rgba(0, 255, 204, 0.18);
}
.size-btn .dot {
    background: #fff;
    border-radius: 50%;
    display: block;
}

/* "sizes-row" wraps the row of three size-btns plus the inline ERASER
   button inside the Brush drawer. */
.sizes-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
}

/* Generic "actions" row of buttons inside a drawer (used by the New
   drawer: Surprise + Clear side by side). */
.actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
}

/* ============ BUTTONS ============ */

.btn {
    padding: 12px 18px;
    border-radius: 16px;
    border: 3px solid rgba(255, 255, 255, 0.32);
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    font-family: var(--font-chunky);
    font-size: 15px;
    font-weight: bold;
    letter-spacing: 1px;
    cursor: pointer;
    text-transform: uppercase;
    min-height: 48px;
    box-shadow: 0 4px 0 rgba(0, 0, 0, 0.35);
    transition: background 0.12s, border-color 0.12s, transform 0.05s, box-shadow 0.05s;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
    .btn:hover { background: rgba(255, 255, 255, 0.16); }
}
.btn:active {
    transform: translateY(2px);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
}
/* min-height keeps the small variant above the 44px touch floor even
   though it visually reads smaller (less padding, smaller font). */
.btn.small { padding: 8px 12px; font-size: 12px; min-height: 44px; }
.btn.active {
    background: rgba(255, 110, 199, 0.28);
    border-color: #ff6ec7;
    color: #fff;
}
.btn.primary {
    background: linear-gradient(135deg, #ff6ec7 0%, #00ffcc 100%);
    color: #1a0f33;
    border: 2px solid rgba(255, 255, 255, 0.4);
    box-shadow: 0 4px 14px rgba(255, 110, 199, 0.35);
}
@media (hover: hover) {
    .btn.primary:hover {
        filter: brightness(1.08);
        background: linear-gradient(135deg, #ff6ec7 0%, #00ffcc 100%);
    }
}

/* ============ BEAT DRAWER (now-playing) ============ */

.now-playing {
    display: flex;
    flex-direction: column;
    gap: 12px;
    font-size: 13px;
    letter-spacing: 1px;
    color: #fff;
    text-transform: uppercase;
}
.now-playing .np-row {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(0, 0, 0, 0.3);
    border: 2px solid rgba(0, 255, 204, 0.25);
    border-radius: 12px;
    padding: 10px 14px;
}
.now-playing .np-label {
    flex: 0 0 48px;
    font-size: 11px;
    color: #d6bdff;
    letter-spacing: 1.5px;
}
.now-playing strong {
    flex: 1 1 auto;
    color: #00ffcc;
    font-size: 16px;
    font-family: var(--font-cursive);
    letter-spacing: 0;
    text-transform: none;
}

/* ============ FOOTER ============ */
/* Footer styles live in /assets/css/site-footer.css (.site-footer)
   so the look is uniform across the Madderverse. The footer sits
   below the fullscreen stage in document flow; scrolling past the
   stage (which the canvas now blocks via touch-action: none) is only
   possible by swiping the tool-dock area, so the footer is
   effectively a "scroll-to-discover" element for parents. */

/* ============ TOOL DOCK + DRAWERS ============

   The big mobile UX shift: instead of a tool tray below the canvas,
   tools live as fixed-position floating icons along the bottom edge.
   Tapping an icon opens a corresponding slide-up drawer. Only one
   drawer is open at a time; openDrawer() in game.js manages the
   switch. Dance mode hides the draw dock and reveals .dance-dock. */

.tool-dock,
.dance-dock {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    display: flex;
    justify-content: space-around;
    align-items: stretch;
    padding: 8px 6px calc(8px + env(safe-area-inset-bottom)) 6px;
    gap: 4px;
    background:
        linear-gradient(180deg, transparent 0%, rgba(10, 5, 25, 0.55) 35%, rgba(10, 5, 25, 0.85) 100%);
    pointer-events: auto;
}

body.dancing .tool-dock { display: none; }
body:not(.dancing) .dance-dock { display: none; }

.dock-btn {
    flex: 1 1 0;
    min-width: 0;
    min-height: 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 6px 2px;
    border-radius: 14px;
    background: rgba(26, 15, 51, 0.7);
    border: 2px solid rgba(0, 255, 204, 0.4);
    color: #fff;
    font-family: var(--font-chunky);
    font-size: 10px;
    letter-spacing: 0.6px;
    font-weight: bold;
    text-transform: uppercase;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
/* Dock buttons are now icon-only. The icon is a custom inline SVG
   sized here (not an emoji font-size). position: relative anchors
   the .dock-label tooltip. */
.dock-btn { position: relative; }
.dock-btn .dock-icon {
    display: flex;
    align-items: center;
    justify-content: center;
}
.dock-btn .dock-icon svg {
    width: 26px;
    height: 26px;
    display: block;
}

/* Neon-glow icons. The SVGs paint with currentColor, so tinting is
   just `color` + a layered drop-shadow glow (teal core, faint pink
   halo) — no per-icon edits, fully themeable. Scoped to exclude the
   primary (Dance) + stop buttons, which sit on bright gradients and
   keep their dark/white glyphs for contrast. */
.dock-btn:not(.primary):not(.stop) .dock-icon svg {
    color: #00ffcc;
    filter:
        drop-shadow(0 0 3px rgba(0, 255, 204, 0.55))
        drop-shadow(0 0 7px rgba(255, 110, 199, 0.22));
    transition: color 0.15s, filter 0.15s;
}
/* Open-drawer / selected state: glyph flips to neon pink. */
.dock-btn.active:not(.primary):not(.stop) .dock-icon svg {
    color: #ff6ec7;
    filter: drop-shadow(0 0 5px rgba(255, 110, 199, 0.7));
}
@media (hover: hover) {
    .dock-btn:not(.primary):not(.stop):hover .dock-icon svg {
        filter:
            drop-shadow(0 0 5px rgba(0, 255, 204, 0.85))
            drop-shadow(0 0 11px rgba(255, 110, 199, 0.35));
    }
}
/* Dance icon: subtle white edge so the dark glyph stays crisp on the
   bright pink→gold→teal gradient. */
.dock-btn.primary .dock-icon svg {
    filter: drop-shadow(0 1px 1px rgba(255, 255, 255, 0.55));
}
@media (prefers-reduced-motion: reduce) {
    .dock-btn .dock-icon svg { transition: none; }
}

/* .dock-label is no longer an inline caption — it floats above the
   button as a tooltip pill. Hidden by default; revealed on hover
   (desktop) or a long-press (.show-tip added by attachDockTooltips
   in game.js for touch). aria-label on the button keeps screen
   readers covered regardless. */
.dock-btn .dock-label {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(26, 15, 51, 0.97);
    border: 1.5px solid rgba(0, 255, 204, 0.55);
    color: #fff;
    font-family: var(--font-chunky);
    font-size: 11px;
    font-weight: bold;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    line-height: 1;
    padding: 5px 10px;
    border-radius: 9px;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease, transform 0.12s ease;
    z-index: 200;
}
.dock-btn .dock-label::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: rgba(0, 255, 204, 0.55);
}
@media (hover: hover) {
    .dock-btn:hover .dock-label {
        opacity: 1;
        visibility: visible;
        transform: translateX(-50%) translateY(0);
    }
}
.dock-btn.show-tip .dock-label {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion: reduce) {
    .dock-btn .dock-label { transition: opacity 0.12s ease; }
}
.dock-btn:active { transform: scale(0.94); }
.dock-btn.active {
    border-color: #ff6ec7;
    background: rgba(255, 110, 199, 0.22);
}
@media (hover: hover) {
    .dock-btn:hover {
        border-color: #00ffcc;
        background: rgba(0, 255, 204, 0.18);
    }
}

/* Primary dock button (DANCE) — pink → yellow → teal gradient,
   visually distinct from the regular dock buttons. */
.dock-btn.primary {
    background: linear-gradient(135deg, #ff6ec7 0%, #ffd23f 50%, #00ffcc 100%);
    color: #1a0f33;
    border-color: rgba(26, 15, 51, 0.5);
}
.dock-btn.primary:hover { filter: brightness(1.06); background: linear-gradient(135deg, #ff6ec7 0%, #ffd23f 50%, #00ffcc 100%); }

/* Stop button (during dance) — solid red-ish to read as an exit. */
.dock-btn.stop {
    background: linear-gradient(135deg, #e63946 0%, #ff6ec7 100%);
    color: #fff;
    border-color: rgba(26, 15, 51, 0.5);
}

@media (min-width: 720px) {
    /* On wider screens give the dock more breathing room and don't
       let buttons stretch ridiculously wide. */
    .tool-dock, .dance-dock {
        justify-content: center;
        gap: 10px;
    }
    .dock-btn {
        flex: 0 0 auto;
        min-width: 72px;
        min-height: 64px;
    }
    .dock-btn .dock-icon svg { width: 30px; height: 30px; }
}

/* ---- Drawer host: fixed full-viewport overlay that's hidden when
   no drawer is open. Backdrop dims the canvas without hiding it. ---- */

.drawer-host {
    position: fixed;
    inset: 0;
    z-index: 150;
    pointer-events: none;
}
.drawer-host.open { pointer-events: auto; }

.drawer-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 5, 25, 0.55);
    opacity: 0;
    transition: opacity 0.2s ease-out;
    pointer-events: none;
}
.drawer-host.open .drawer-backdrop {
    opacity: 1;
    pointer-events: auto;
}

.drawer {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 14px 16px calc(18px + env(safe-area-inset-bottom));
    max-height: 50dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background:
        radial-gradient(ellipse 80% 50% at 50% 0%, rgba(255, 110, 199, 0.22) 0%, transparent 70%),
        linear-gradient(170deg, #3b1f6b 0%, #1a0f33 100%);
    border: 3px solid rgba(0, 255, 204, 0.5);
    border-bottom: none;
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.5);
    transform: translateY(100%);
    transition: transform 0.28s cubic-bezier(0.2, 0.9, 0.3, 1);
    /* Hidden scrollbar — kept scroll behavior, dropped the chrome. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.drawer::-webkit-scrollbar { display: none; }
.drawer.open { transform: translateY(0); }

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

@media (min-width: 720px) {
    /* On wider screens, the drawer becomes a centered card rather
       than a full-width sheet so the canvas isn't entirely covered. */
    .drawer {
        left: auto;
        right: 24px;
        bottom: 100px;
        max-width: 380px;
        border: 3px solid rgba(0, 255, 204, 0.5);
        border-radius: 22px;
    }
}

.drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 2px dashed rgba(0, 255, 204, 0.25);
}
.drawer-head h2 {
    margin: 0;
    font-family: var(--font-cursive);
    font-size: 26px;
    color: #ff6ec7;
    line-height: 1;
    text-shadow: 0 2px 0 #1a0f33;
}

.drawer-close {
    appearance: none;
    background: rgba(255, 255, 255, 0.08);
    border: 2px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    font-size: 14px;
    cursor: pointer;
    line-height: 1;
    -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
    .drawer-close:hover { background: rgba(255, 255, 255, 0.18); }
}

.drawer-body { display: flex; flex-direction: column; gap: 14px; }

.drawer-section { display: flex; flex-direction: column; gap: 8px; }
.drawer-section-label {
    margin: 0;
    font-size: 11px;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: #d6bdff;
    font-weight: bold;
}

.drawer-text {
    margin: 0;
    font-size: 13px;
    text-align: center;
    color: #d6bdff;
    line-height: 1.4;
}

/* Lock body scroll while a drawer / modal is open. */
.drawer-open, .drawer-open body {
    overflow: hidden;
    overscroll-behavior: contain;
}

/* ============ COLORING-BOOK PAGES MODAL ============

   Same responsive grid as the hat shop. Each card is a button so a kid
   can tap anywhere on it to pick the page; the "Color it" / "✓ Done"
   pill at the bottom is a visual label, not a separate hit target. */

.page-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}
@media (min-width: 480px) {
    .page-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 720px) {
    .page-grid { grid-template-columns: repeat(4, 1fr); }
}

.page-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 8px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    color: #fff;
    cursor: pointer;
    font-family: inherit;
    text-align: center;
    transition: border-color 0.2s, background 0.2s, transform 0.1s;
    -webkit-tap-highlight-color: transparent;
}
.page-card:active { transform: scale(0.97); }

/* "Colour it for me" corner button on each character card. Tapping
   it loads the pre-coloured version; tapping anywhere else on the
   card loads the colour-it-yourself outline. Sized to clear the 44px
   touch-target floor. */
.char-fill-btn {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    line-height: 1;
    border-radius: 9px;
    border: 1.5px solid rgba(255, 110, 199, 0.55);
    background: rgba(26, 15, 51, 0.9);
    cursor: pointer;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, transform 0.08s;
}
.char-fill-btn:active { transform: scale(0.9); }
@media (hover: hover) {
    .char-fill-btn:hover { background: rgba(255, 110, 199, 0.35); }
}
.page-card.done {
    border-color: rgba(0, 255, 204, 0.6);
    background:
        radial-gradient(ellipse 100% 60% at 50% 0%, rgba(0, 255, 204, 0.14) 0%, transparent 70%),
        rgba(0, 0, 0, 0.35);
}
.page-card-blank {
    border-color: rgba(255, 110, 199, 0.5);
    background:
        radial-gradient(ellipse 100% 60% at 50% 0%, rgba(255, 110, 199, 0.16) 0%, transparent 70%),
        rgba(0, 0, 0, 0.35);
}
@media (hover: hover) {
    .page-card:hover { border-color: rgba(0, 255, 204, 0.55); }
}

.page-emoji {
    font-size: 38px;
    line-height: 1.05;
}
.page-name {
    font-weight: bold;
    font-size: 14px;
    letter-spacing: 0.4px;
}
.page-action {
    font-size: 11px;
    font-weight: bold;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    padding: 4px 8px;
    border-radius: 10px;
    background: rgba(0, 255, 204, 0.16);
    color: #d6bdff;
    border: 1px solid rgba(0, 255, 204, 0.35);
    align-self: center;
}
.page-card.done .page-action {
    background: #00ffcc;
    color: #1a0f33;
    border-color: #00ffcc;
}
.page-card-blank .page-action {
    background: rgba(255, 110, 199, 0.2);
    border-color: rgba(255, 110, 199, 0.5);
    color: #fff;
}

/* ============ STARTER GRID (Default Groodles in the New drawer) ============

   3-up grid that fits comfortably inside the drawer body without making
   the kid scroll. Same card visual idiom as .page-card but a touch
   denser since there are 6 of them. */

.starter-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
@media (min-width: 480px) {
    .starter-grid { grid-template-columns: repeat(6, 1fr); }
}

.starter-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 6px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(0, 255, 204, 0.35);
    border-radius: 14px;
    color: #fff;
    cursor: pointer;
    font-family: inherit;
    text-align: center;
    transition: border-color 0.15s, background 0.15s, transform 0.08s;
    -webkit-tap-highlight-color: transparent;
}
.starter-card:active { transform: scale(0.96); }
@media (hover: hover) {
    .starter-card:hover {
        border-color: #ff6ec7;
        background: rgba(255, 110, 199, 0.12);
    }
}

.starter-emoji {
    font-size: 30px;
    line-height: 1;
}
.starter-name {
    font-weight: bold;
    font-size: 11px;
    line-height: 1.15;
    letter-spacing: 0.3px;
    min-height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.starter-action {
    font-size: 9px;
    font-weight: bold;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    padding: 2px 6px;
    border-radius: 8px;
    background: rgba(0, 255, 204, 0.18);
    color: #d6bdff;
    border: 1px solid rgba(0, 255, 204, 0.35);
}

/* ============ SAVE DIALOG ============

   Narrower than the achievement / hat / pages modals (single-column
   form). The sheet is centered; the body holds the name field, status
   line, primary submit button, and a one-line safety hint. */

.save-sheet { max-width: 380px; }

.save-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 4px 2px;
}

.save-label {
    font-size: 12px;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #d6bdff;
    font-weight: bold;
}

.save-input {
    width: 100%;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.4);
    border: 2px solid rgba(0, 255, 204, 0.5);
    color: #fff;
    font-size: 16px;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
}
.save-input:focus {
    outline: none;
    border-color: #ff6ec7;
    box-shadow: 0 0 0 3px rgba(255, 110, 199, 0.25);
}

.save-status {
    font-size: 13px;
    color: #d6bdff;
    min-height: 18px;
    text-align: center;
}

.save-submit { align-self: stretch; }

.save-hint {
    margin: 4px 0 0;
    font-size: 11px;
    line-height: 1.4;
    text-align: center;
    color: rgba(255, 255, 255, 0.55);
}

/* ============ GALLERY GRID ============ */

.gallery-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}
@media (min-width: 480px) {
    .gallery-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 720px) {
    .gallery-grid { grid-template-columns: repeat(4, 1fr); }
}

.gallery-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px;
    background: rgba(0, 0, 0, 0.35);
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
}

.gallery-img {
    width: 100%;
    aspect-ratio: 2 / 3;
    object-fit: contain;
    background:
        radial-gradient(ellipse 80% 50% at 50% 90%, rgba(0, 0, 0, 0.25) 0%, transparent 70%),
        linear-gradient(180deg, rgba(255, 255, 255, 0.92) 0%, rgba(236, 236, 244, 0.92) 100%);
    border-radius: 10px;
}

.gallery-name {
    font-size: 13px;
    font-weight: bold;
    text-align: center;
    color: #fff;
    word-break: break-word;
}

/* Local-gallery delete: corner trash button with a two-tap confirm.
   .gallery-card is flex; relative positioning lets the button overlay
   the thumbnail. Harmless to web (Supabase) cards — they have no
   .gallery-del child. */
.gallery-card { position: relative; }
.gallery-del {
    position: absolute;
    top: 10px;
    right: 10px;
    min-width: 38px;
    height: 38px;
    padding: 0 10px;
    border: none;
    border-radius: 19px;
    background: rgba(26, 15, 51, 0.78);
    color: #fff;
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}
.gallery-del.confirm {
    background: #e63946;
    font-size: 13px;
    font-weight: bold;
}

/* One-tap-save confirmation toast (app mode has no public name dialog). */
.groodle-toast {
    position: fixed;
    left: 50%;
    bottom: 96px;
    transform: translate(-50%, 12px);
    z-index: 130;
    max-width: 80vw;
    padding: 10px 18px;
    border-radius: 22px;
    background: rgba(26, 15, 51, 0.92);
    border: 1px solid rgba(0, 255, 204, 0.5);
    color: #fff;
    font-size: 14px;
    font-weight: bold;
    text-align: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s, transform 0.2s;
}
.groodle-toast.show { opacity: 1; transform: translate(-50%, 0); }

.gallery-empty {
    grid-column: 1 / -1;
    padding: 32px 16px;
    text-align: center;
    color: #d6bdff;
    font-size: 14px;
    line-height: 1.5;
}
.gallery-empty code {
    background: rgba(0, 0, 0, 0.35);
    padding: 2px 6px;
    border-radius: 6px;
    font-size: 12px;
}

/* iOS: kill double-tap-to-zoom (Safari ignores user-scalable=no). Keeps taps/scroll/pinch; canvas touch-action:none wins on specificity. */
* { touch-action: manipulation; }
