/* Project Pumper — the design framework.
 * ============================================================================
 * This file is the whole of how pumper is built visually. It is short on
 * purpose; the rules below are not suggestions, they are what makes a page
 * here reviewable and what keeps a phone as first-class as a desktop.
 *
 * 1. NO INLINE STYLES. ANYWHERE. Not in a template, not in a Java element
 *    tree, and not concatenated by a script. A `style="…"` attribute is a rule
 *    nobody can find, override, theme or review — and one written from
 *    JavaScript is all of that in a language that does not know it is emitting
 *    CSS. If a value must be computed at run time it is handed to CSS as data:
 *    a `data-` attribute for a STATE (`data-mood="pr"`, `data-on="true"`) or a
 *    custom property for a NUMBER (`--fill: 68%`). The script says WHAT is
 *    true; this file says what that LOOKS like.
 *
 * 2. NO MARKUP IN STRINGS. Structure comes from the template pipeline —
 *    `.mustache` files and degeneration-x element trees — never from string
 *    concatenation. A script that needs to build rows clones a `<template>`
 *    the generator wrote (see cabinettemplates.mustache) and fills it with
 *    textContent. The ban is on assembling HTML, in any language.
 *
 * 3. FLEXBOX, NOT COORDINATES. Layout is flex containers and flex children:
 *    `display:flex` with `flex-wrap`, `gap`, and `flex: <grow> <shrink>
 *    <basis>`. ***There is no `position: absolute` or `position: fixed` in this
 *    design, and no exception that permits one.*** Positioning content at
 *    computed percentages is the legacy divitis this framework exists to keep
 *    out. Decoration that seemed to need it does not:
 *      - A TEXTURE over a surface is a background LAYER on that surface, not an
 *        element over it (`background: var(--scanline), <the real background>`).
 *        That deleted six empty divs and every z-index that went with them.
 *      - Things that must OVERLAP — a crossfade, a sweeping VHS bar — are a
 *        one-cell grid: `display:grid; grid-template-areas:"stack"` on the
 *        parent, `grid-area:stack` on each child. They share the cell, the cell
 *        is sized by its content, and `align-self` says where in it they sit.
 *    Both are declarative and reflow; neither names a coordinate.
 *
 * 4. EVERY FLEX CHILD GETS min-width: 0. A flex item's default minimum is its
 *    content, so one long word or one wide input silently pushes a row past
 *    the viewport — which is how a page ends up scrolling sideways on a phone
 *    while looking fine on a laptop. Inputs additionally take `width: 100%`
 *    and `box-sizing: border-box`: a date input is as wide as the browser's
 *    own picker chrome wants to be, and that is wider than a phone.
 *
 * 5. em, NOT px. `.screen` sets the root size with `clamp()` and everything
 *    within scales from it, so the whole design breathes with the viewport
 *    rather than stepping between breakpoints. A media query is for a layout
 *    that must CHANGE (a two-column grid becoming one), never for resizing
 *    text that em already handles.
 *
 * 6. SEMANTIC BEM-ish NAMES. `.campaign__pick`, not `.btn-green-small`. A
 *    class says what a thing IS; this file decides what that means.
 *
 * Colours are literal rather than tokenized. Moving the arcade palette into
 * custom properties is a safe follow-up and would make rule 1's data-attribute
 * states themeable too.
 * ============================================================================
 */

/* ---- base (was each page's <style> head block) ---- */
body { margin: 0; background: #0d0517; color: #efe9ff }
a { color: #25e8e0; text-decoration: none }
a:hover { color: #ff2fa0 }
a:focus-visible, button:focus-visible { outline: 0.2em solid #ffd23e; outline-offset: 0.15em }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important } }
img, video { max-width: 100% }

@keyframes blink { 0%,55% { opacity: 1 } 56%,100% { opacity: 0 } }
@keyframes bob { 0%,100% { transform: translateY(0) } 50% { transform: translateY(-8%) } }
@keyframes tracking {
  0%,92% { transform: translateY(0); opacity: 0 }
  93% { opacity: .6 }
  96% { transform: translateY(30vh); opacity: .5 }
  100% { transform: translateY(60vh); opacity: 0 }
}
@keyframes neonpulse {
  0%,100% { text-shadow: 0 0 0.5em #ff2fa0, 0 0 1.5em #ff2fa088 }
  50% { text-shadow: 0 0 0.9em #ff2fa0, 0 0 2.75em #ff2fa0aa }
}

/* ---- the page root: em-based scaling ---- */
.screen { font-family: 'Oswald','Archivo',system-ui,sans-serif; font-size: clamp(0.7rem,1.05vw,1.15rem) }

/* ---- fonts / small helpers ---- */
.pixel { font-family: 'Press Start 2P',monospace }
.brush { font-family: 'Shojumaru',system-ui,cursive }

/* ---- nav (shared chrome) ---- */
.nav { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
       gap: 1em; padding: 1em clamp(0.8em,4vw,2.5em); background: #080312;
       border-bottom: 0.15em solid #ff2fa0; min-width: 0 }
.nav__brand { font-family: 'Press Start 2P',monospace; font-size: 1em; color: #fff; flex: none }
.nav__cursor { color: #39ff5a; animation: blink 1.2s steps(1) infinite }
.nav__links { display: flex; flex-wrap: wrap; gap: clamp(0.8em,2.5vw,1.6em); align-items: center;
              font-family: 'Press Start 2P',monospace; font-size: 0.625em; min-width: 0 }
.nav__link { color: #cfc4e6 }
.nav__link--active { color: #25e8e0; border-bottom: 0.3em solid #25e8e0; padding-bottom: 0.4em }
.nav__links a[aria-current="page"] { color: #ff2fa0; border-bottom: 0.3em solid #ff2fa0; padding-bottom: 0.4em }
.nav__link--analyzer { color: #25e8e0; display: inline-flex; align-items: baseline; gap: 0.4em }
.nav__link--arrow { font-size: 0.8em }
.nav__beta { background: #c2187c; color: #fff; padding: 0.9em 1.4em; box-shadow: 0.3em 0.3em 0 #7a0e4c }

/* ---- buttons (shared) ---- */
.btn { font-family: 'Press Start 2P',monospace; font-size: 0.7em; padding: 1.25em 1.8em }
.btn--pink { background: #c2187c; color: #fff; box-shadow: 0.36em 0.36em 0 #7a0e4c }
.btn--cyan { background: #25e8e0; color: #08131a; box-shadow: 0.36em 0.36em 0 #0e5a56 }

/* ---- scanline (shared) ----
 * NOT an element. A CRT scanline is a TEXTURE, so it is a background layer on
 * whatever it textures — which needed no positioning, deleted five empty divs
 * from the markup, and cannot be clicked, focused or read aloud by a screen
 * reader because it is not in the document at all. Compose it in front of the
 * surface's own background: the first layer listed is the topmost. */
:root { --scanline: repeating-linear-gradient(0deg,rgba(255,255,255,.03) 0 0.0625em,transparent 0.0625em 0.25em) }

/* ---- exercise-library shell ---- */
.lib-header { text-align: center; padding: 2.75em clamp(0.8em,4vw,2.5em) 2.5em;
              background: var(--scanline), linear-gradient(180deg,#0d0517 0%,#0e2230 100%);
              overflow: hidden; border-bottom: 0.15em solid #25e8e0 }
.lib-header__world { font-family: 'Press Start 2P',monospace; font-size: 0.7em; color: #8d7fae }
.lib-header__title { margin: 0.3em 0 0; font-family: 'Archivo Black',sans-serif; font-style: italic;
  font-weight: 900; font-size: min(4.75em,11vw); line-height: .95; transform: skewX(-8deg);
  background: linear-gradient(180deg,#eaf6ff 0%,#9fd8ff 40%,#1e5f8a 50%,#fff 54%,#25e8e0 70%,#0e5a56 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0.05em 0 #001a20) }
.lib-header__tag { font-family: 'Press Start 2P',monospace; font-size: 0.75em; color: #ffd23e; margin: 1.85em 0 0 }
.accent-cyan { color: #25e8e0 }
.accent-green { color: #39ff5a }
.accent-yellow { color: #ffd23e }
.accent-pink { color: #ff2fa0 }
.accent-muted { color: #8d7fae }

.banner { background: #140a26; color: #39ff5a; text-align: center; padding: 1em clamp(0.8em,4vw,2.5em);
          font-family: 'Press Start 2P',monospace; font-size: 0.625em; line-height: 2;
          border-bottom: 0.15em solid #39ff5a }
.lib-sections { padding: 2.5em clamp(0.8em,4vw,2.5em) 3.4em; background: #0d0517;
                display: flex; flex-direction: column; gap: 2.5em }
.lib-footer { text-align: center; padding: 2.25em clamp(0.8em,4vw,2.5em) 2.75em; background: #080312;
              border-top: 0.15em solid #ff2fa0 }
.lib-footer__title { font-family: 'Press Start 2P',monospace; font-size: 0.8em; color: #39ff5a }
.lib-footer__cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.1em; margin-top: 1.25em }
.lib-footer__legal { font-family: ui-monospace,monospace; font-size: 0.7em; color: #5c4f78; margin-top: 2.2em }

/* ---- region section ---- */
/* each world is a pure-CSS accordion (<details>/<summary>), closed by default */
.region { max-width: 78em; margin: 0 auto; width: 100%; min-width: 0 }
.region__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 1em;
                border-bottom: 0.15em solid #2c1a4a; padding-bottom: 0.75em;
                cursor: pointer; list-style: none }
.region__head::-webkit-details-marker { display: none }
.region__head::before { content: "\25B8"; align-self: center; color: #39ff5a;
                        font-family: 'Press Start 2P',monospace; font-size: 0.7em;
                        transition: transform .15s ease }
.region[open] > .region__head::before { transform: rotate(90deg) }
.region__head:hover .region__world { color: #25e8e0 }
.region__world { font-family: 'Press Start 2P',monospace; font-size: 0.8em; color: #39ff5a }
.region__count { font-family: 'Press Start 2P',monospace; font-size: 0.55em; color: #8d7fae }
.region__grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(min(100%,17.5em),1fr));
                gap: 1.25em; margin-top: 1.25em }

/* ---- exercise card ---- */
.card { display: flex; flex-direction: column; gap: 0.65em; background: #140a26;
        border: 0.19em solid #25e8e0; padding: 1em; box-shadow: 0 0 1em #25e8e022; color: inherit }
.card__head { display: flex; justify-content: space-between; align-items: center; gap: 0.5em; flex-wrap: wrap }
.card__name { font-family: 'Press Start 2P',monospace; font-size: 0.75em; color: #25e8e0 }
.card__stars { font-family: 'Press Start 2P',monospace; font-size: 0.56em; color: #ffd23e }
.card__pills { display: flex; gap: 0.4em; flex-wrap: wrap }
.card__copy { font-family: 'Shojumaru',system-ui,cursive; font-size: 0.78em; line-height: 1.8;
              color: #ffd23e; text-shadow: 0 0 0.8em #ffd23e33 }
.card__stats { font-family: 'Press Start 2P',monospace; font-size: 0.55em; color: #8d7fae;
               margin-top: auto; line-height: 1.8 }
.card__variants { color: #25e8e0; white-space: nowrap }

/* ---- card art box (photo | sprite gap-filler | dashed placeholder) ---- */
.art { aspect-ratio: 10/3.4; border: 0.13em solid #3f6d75; background: #0a0414 }
.art--photo { overflow: hidden }
.art--photo img { width: 100%; height: 100%; object-fit: cover }
.art--sprite { display: flex; align-items: center; justify-content: center; padding: 0.3em 0 }
.art--sprite img { height: 100%; aspect-ratio: 26/16 }
.art--placeholder { aspect-ratio: 10/3.4; border: 0.13em dashed #3f6d75;
  background: repeating-linear-gradient(45deg,#0e1a22 0 0.5em,#12222c 0.5em 1em);
  display: flex; align-items: center; justify-content: center;
  font-family: ui-monospace,monospace; font-size: 0.625em; color: #6fa7b0; text-align: center; padding: 0.5em }

/* ---- pills (fixed palette -> color modifier classes) ---- */
.pill { font-family: ui-monospace,monospace; font-weight: 700; font-size: 0.625em;
        border: 0.18em solid currentColor; padding: 0.3em 0.8em }
.pill.c-cyan   { color: #25e8e0 }
.pill.c-pink   { color: #ff2fa0 }
.pill.c-yellow { color: #ffd23e }
.pill.c-orange { color: #ff8c25 }
.pill.c-lilac  { color: #cfc4e6 }
.pill.c-green  { color: #39ff5a }
.pill.c-blue   { color: #9fd8ff }
.pill.c-purple { color: #c084fc }
.pill.c-rose   { color: #f472b6 }
.pill.c-white  { color: #fff }

/* ---- detail page ---- */
.detail-hero { background: var(--scanline), linear-gradient(180deg,#0d0517 0%,#1c0836 100%);
               border-bottom: 0.15em solid #25e8e0; overflow: hidden }
.detail-hero__inner { display: flex; flex-wrap: wrap; gap: 2em; align-items: center;
                      max-width: 78em; margin: 0 auto; padding: 2.5em clamp(0.8em,4vw,2.5em) }
.detail-hero__main { flex: 1.4 1 22em; min-width: 0; display: flex; flex-direction: column; gap: 1em }
.detail-hero__crumb { font-family: 'Press Start 2P',monospace; font-size: 0.625em; color: #8d7fae; line-height: 2 }
.detail-hero__crumb a { color: #8d7fae }
.detail-hero__title { margin: 0; font-family: 'Archivo Black',sans-serif; font-style: italic; font-weight: 900;
  font-size: min(4.5em,12vw); line-height: .95; transform: skewX(-8deg);
  background: linear-gradient(180deg,#eaf6ff 0%,#9fd8ff 40%,#1e5f8a 50%,#fff 54%,#ffd23e 70%,#b3541e 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0.05em 0 #2c003a) }
.detail-hero__pills { display: flex; gap: 0.4em; flex-wrap: wrap }
.detail-hero__lineage { font-family: 'Press Start 2P',monospace; font-size: 0.56em;
                        letter-spacing: 0.06em; line-height: 2.2 }
.detail-hero__copy { font-family: 'Shojumaru',system-ui,cursive; font-size: 0.9em; line-height: 1.8;
                     color: #ffd23e; text-shadow: 0 0 0.8em #ffd23e44 }
.detail-hero__stats { font-family: 'Press Start 2P',monospace; font-size: 0.6em; color: #8d7fae; line-height: 2 }
.lineage-node { color: #cfc4e6 }
.lineage-self { color: #fff }
.lineage-sep { color: #ff2fa0 }

.detail-body { padding: 2.5em clamp(0.8em,4vw,2.5em) 3em; background: #0d0517 }
.detail-body__inner { max-width: 78em; margin: 0 auto; display: flex; flex-direction: column; gap: 1.5em }
.detail-body__movelist { font-family: 'Press Start 2P',monospace; font-size: 0.7em; color: #39ff5a; line-height: 2; margin: 0; font-weight: normal }
.detail-body__back { align-self: center }
.detail-footer { text-align: center; padding: 1.8em; background: #080312; border-top: 0.15em solid #ff2fa0 }
.detail-footer__legal { font-family: ui-monospace,monospace; font-size: 0.7em; color: #5c4f78 }

/* ---- variant position groups: the worlds accordion, closed by default ---- */
.vgroup { max-width: 100%; min-width: 0 }
.vgroup__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 1em;
                border-bottom: 0.15em solid #2c1a4a; padding: 0.9em 0 0.6em;
                cursor: pointer; list-style: none }
.vgroup__head::-webkit-details-marker { display: none }
.vgroup__head::before { content: "\25B8"; align-self: center; color: #39ff5a;
                        font-family: 'Press Start 2P',monospace; font-size: 0.7em;
                        transition: transform .15s ease }
.vgroup[open] > .vgroup__head::before { transform: rotate(90deg) }
.vgroup__title { font-family: 'Press Start 2P',monospace; font-size: 0.8em;
                 color: #39ff5a; margin: 0; display: inline }
.vgroup__head:hover .vgroup__title { color: #25e8e0 }
.vgroup__count { font-family: 'Press Start 2P',monospace; font-size: 0.55em; color: #8d7fae }
.vgroup__list { display: flex; flex-direction: column; gap: 1.5em; margin-top: 1.25em }

/* ---- attract panel (animated sprite frames) + photo reference poster ---- */
.attract { flex: 1 1 16em; min-width: 0; max-width: 24em }
.attract__frame { border: 0.19em solid #25e8e0;
                  background: repeating-linear-gradient(0deg,rgba(255,255,255,.05) 0 0.0625em,transparent 0.0625em 0.25em), #0a0414;
                  box-shadow: 0 0 1.4em #25e8e044; overflow: hidden }
.attract__bar { display: flex; justify-content: space-between; padding: 0.6em 0.8em;
                font-family: 'Press Start 2P',monospace; font-size: 0.55em }
.attract__bar--single { padding: 0.6em 0.8em; font-family: 'Press Start 2P',monospace; font-size: 0.55em }
.attract__label { color: #39ff5a }
.attract__demo { color: #ff2fa0; animation: blink 1.1s steps(1) infinite }
/* Two frames CROSSFADE, so they must occupy the same box at once. That is a
 * STACK, and a one-cell grid says so: every child is placed in the same cell,
 * in source order, sized by the cell. No coordinates, no `position`. */
.attract__stage { display: grid; grid-template-areas: "stack"; aspect-ratio: 24/20; margin: 0 8% }
.attract__frame-img { grid-area: stack; width: 100%; height: 100%; object-fit: contain }
/* The crossfade is a two-frame flipbook, so it is two keyframes — not a setInterval
 * assigning style.opacity. `steps(1)` gives the hard cut a sprite wants, and the
 * reduced-motion rule at the top of this file already stops it for anyone who asked. */
@keyframes attract-a { 0%,49.99% { opacity: 1 } 50%,100% { opacity: 0 } }
@keyframes attract-b { 0%,49.99% { opacity: 0 } 50%,100% { opacity: 1 } }
.attract__frame-img--a { animation: attract-a 1.4s steps(1) infinite }
.attract__frame-img--b { animation: attract-b 1.4s steps(1) infinite }
.attract__divider { height: 0.4em; background: linear-gradient(90deg,#33104f,#4a1d7a,#33104f) }
.attract__tagline { text-align: center; font-family: 'Press Start 2P',monospace; font-size: 0.5em;
                    color: #8d7fae; padding: 0.8em; line-height: 1.8 }
.attract__photo { display: block; width: 100%; aspect-ratio: 24/20; object-fit: cover }

/* ---- variant card ---- */
.variant { border: 0.19em solid #ff2fa0; background: #140a26; box-shadow: 0 0 1em #ff2fa022;
           padding: 1.2em; display: flex; flex-direction: column; gap: 0.9em; min-width: 0 }
.variant__head { display: flex; flex-wrap: wrap; gap: 0.4em; align-items: center }
.variant__num { margin-left: auto; font-family: 'Press Start 2P',monospace; font-size: 0.6em; color: #8d7fae }
.variant__aka { font-family: 'Shojumaru',system-ui,cursive; font-size: 0.78em; letter-spacing: 0.04em;
                color: #ffd23e; text-shadow: 0 0 0.7em #ffd23e44 }
.variant__body { display: flex; flex-wrap: wrap; gap: 1.2em; align-items: flex-start; min-width: 0 }
.variant__instr { flex: 1.6 1 24em; min-width: 0; display: flex; flex-direction: column; gap: 0.8em }
.variant__instr p { margin: 0; font-size: 1em; letter-spacing: 0.02em; line-height: 1.7; color: #d7cfe8 }

/* ---- variant media / equipment-icon panel ---- */
.media-panel { flex: 1 1 16em; min-width: 0; max-width: 22em; display: flex; flex-wrap: wrap;
               gap: 0.8em; align-content: flex-start }
.media-cell { flex: 1 1 8em; min-width: 0; border: 0.13em solid #3f6d75; background: #0a0414; padding: 0.5em }
.media-cell--video { flex: 1 1 12em }
.media-cell img { display: block; width: 100%; object-fit: contain }
.media-cell video { display: block; width: 100% }
.icon-panel { flex: 0 1 12em; min-width: 0; border: 0.13em solid #3f6d75; background: #0a0414;
              padding: 0.8em; display: flex; flex-direction: column; gap: 0.6em; align-items: center }
.icon-panel img { display: block; width: 70%; aspect-ratio: 18/10 }
.icon-panel__cap { text-align: center; font-family: 'Press Start 2P',monospace; font-size: 0.5em;
                   color: #8d7fae; line-height: 1.8 }
