/* ============================================================================
   The AWOW Jukebox launch page.

   READ THIS BEFORE EDITING.
   Two compositions live in this file, not one page and a set of tweaks:

     - THE DESKTOP VIEW (>= 768px): the OUTRUN world behind a centred column,
       the picker as a 23-row listbox, the HUD along the bottom.
     - THE PHONE CUT   (<= 767px): its own design. The visualizer is pinned to
       the bottom edge as a live band inside .dock (the cabinet gives the
       visualizer the bottom half of its screen; a phone is the only place a web
       page can keep that promise). Above it: two widths only -- the 16px column
       for copy, full bleed for every picture. The picker becomes a thumb
       carousel. Denise becomes a tap-through. Both tables become stacked rows.

   Everything the cabinet itself draws comes from the kit (kit/jukebox.css and
   kit/*.js): the backdrop, the groove, the visualizer, the bars, the EQ, the
   23-mode picker and the sprites. This stylesheet is the WEB PAGE around them.
   Prefix aw- so nothing here collides with the kit's classes.

   Three rules that are load-bearing. Break one and something measurable breaks:
     1. .px wraps (kit). Only .px--quote may be `white-space: pre`, and only the
        EQ band-label row uses it. `pre` on every .px is what made a 390px
        window carry a 760px document.
     2. `img, video { height: auto }` below. Without it any <img> with width and
        height attributes is squashed to its attribute height.
     3. Nothing is `display:none` on a phone that carries copy. Hiding a claim
        from half the audience is a change to the claim.
   ========================================================================== */

/* Cross-document View Transitions: the second half of the site morph. Browsers
   without support fall back to the overlay the theme snippet paints. */
@view-transition { navigation: auto; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { padding-bottom: calc(var(--jb-hud-h) + 24px); }
/* height:auto is not optional: without it every <img> carrying width/height
   attributes keeps its attribute height while the width is clamped, which is
   what squashed both setup-page PNGs by 52% on desktop as well as on a phone. */
img, video { max-width: 100%; height: auto; }
a { color: var(--jb-neon); text-decoration: none; }
a:hover { color: var(--jb-hot); }
a:focus-visible, button:focus-visible, summary:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--jb-gold); outline-offset: 2px; }

/* The kit sets box-sizing per component rather than globally, so the page's own
   controls have to opt in: without it a 44 px min-height plus 8 px of padding is
   a 60 px button, and the nav was 81 px tall for no reason. */
.aw-order-pill, .aw-cta, .aw-step-btn, .hud__motion, .aw-store span, .aw-faq summary,
.aw-badge, .aw-mark, .aw-nav__home, .aw-nav__links a, .aw-wrap, .aw-footer, .aw-nav,
.aw-phone-frame, .aw-card, .aw-order, .aw-wave2, .aw-narrate, .aw-crew__fig,
.jb-rail, .jb-deck__cards, .aw-frames, .dock, .dock__row, .aw-nav__scroll, .aw-tablewrap,
.eq__pane, .aw-steps li, .aw-hero, .aw-hero__band, .jb-rail__card { box-sizing: border-box; }
/* A full-bleed row is 100vw INCLUDING its gutters. Without border-box the kit's
   16 px of scroll padding is added on top, the document reports itself 41 px
   wider than the window, and the phone browser zooms the whole page out to fit
   -- which is what made 16 px body copy read as 8 px. */

/* the drifting invaders cross the whole width, so their section clips them --
   otherwise the document reports itself wider than the window. They used to
   cross #second-wave; that band is retired, so they cross the origin story. */
#about { overflow: hidden; }

/* the HUD ships with a rail-width gutter; there is no rail on this page */
.hud { padding-left: 16px; }

/* The CRT scanroll is 6% alpha and there are 27 frames on this page. It runs
   only where it can be seen; off-screen it is 27 running animations for nothing.
   The same goes for every 2.5 Hz blink the kit ships: a blinking LED nobody can
   see is a running animation nobody asked for. The budget is one primary mover,
   two accents and the room, per viewport -- and it is only kept if the accents
   outside the viewport stand still. */
.screen::before, .screen > .led, .aw-hudstrip .cursor, #eq .eq__cap, .coin { animation-play-state: paused; }
.is-near .screen::before, .screen.is-near::before,
.is-near .screen > .led,
.aw-footer.is-near .cursor,
#sound.is-near .eq__cap,
#top.is-near .coin, .dock .coin { animation-play-state: running; }

/* ---------- the backdrop ---------- */
/* jukebox-backdrop.js paints the OUTRUN sun, grid and drifting invaders on
   fixed canvases (three on desktop, one merged canvas at DPR 1 on a phone). If
   the modules do not load (file://, no JS) this CSS layer stands in so the page
   is never a flat black rectangle. */
.aw-backdrop { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.aw-backdrop::before {
  content: ''; position: absolute; left: 50%; top: var(--jb-horizon); width: 62vw; height: 62vw;
  max-width: 720px; max-height: 720px; transform: translate(-50%, -50%);
  background: radial-gradient(circle at 50% 50%, rgba(242,227,16,.30), rgba(232,32,138,.22) 55%, transparent 70%);
}
.aw-backdrop::after {
  content: ''; position: absolute; left: 0; right: 0; top: var(--jb-horizon); bottom: 0;
  background:
    repeating-linear-gradient(180deg, rgba(64,200,236,.16) 0 2px, transparent 2px 34px),
    linear-gradient(180deg, transparent, rgba(64,200,236,.07));
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 40%);
  mask-image: linear-gradient(180deg, transparent, #000 40%);
}
.aw-backdrop.is-replaced { display: none; }

/* ---------- the readability veil ----------
   The world's strength is a per-section attribute, not a constant. Every
   section carries data-presence p; the frame loop interpolates it between the
   sections straddling the viewport and sets veil = 0.78 - 0.50p. The hero and
   the order panel are p 1.0 (veil 0.28); body copy sits at p 0.3-0.6.
   With no JS it rests at the mid value, which is the one the copy needs. */
.aw-veil {
  position: fixed; inset: 0; z-index: 5; pointer-events: none;
  background: radial-gradient(130% 90% at 50% 38%, rgba(10,10,15,.62) 0%, rgba(10,10,15,.84) 60%, rgba(10,10,15,.93) 100%);
  opacity: var(--aw-veil, .60);
}
@media (prefers-reduced-motion: no-preference) { .aw-veil { transition: opacity 220ms linear; } }
.aw-content { position: relative; z-index: 7; }

/* ---------- sticky nav ----------
   The page's own navigation, never a rail of cabinet items: a visitor always
   knows they are on a website. One set of links serves both views -- inline on
   desktop, a snap strip on row 2 on a phone. */
.aw-nav {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 20px;
  padding: 10px 40px;
  background: rgba(10,10,15,.78);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
  border-bottom: 1px solid rgba(255,255,255,.07);
  view-transition-name: aw-nav;
}
.aw-mark { font-family: var(--jb-font-head); font-size: 14px; line-height: 1; flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px; }
.aw-mark .a { color: var(--jb-neon); } .aw-mark .w { color: var(--jb-hot); }
.aw-mark .j { font-size: 9px; color: var(--jb-secondary); letter-spacing: 2px; margin-left: 12px; }
.aw-nav__scroll { display: flex; align-items: center; gap: 22px; flex: 1 1 auto; min-width: 0; }
.aw-nav__links { position: relative; display: flex; align-items: center; gap: 22px; font-size: 14px; letter-spacing: .4px; min-width: 0; }
.aw-nav__links a { color: var(--jb-body); display: inline-flex; align-items: center; min-height: 44px; padding: 0 2px; position: relative; white-space: nowrap; }
.aw-nav__links a:hover, .aw-nav__links a[aria-current="true"] { color: var(--jb-neon); }
/* the gold > rides the hovered link; the 6x6 LED slides to the active one */
.aw-nav__links a::before { content: '>'; position: absolute; left: -11px; color: var(--jb-gold); font-family: var(--jb-font-px); opacity: 0; transition: opacity 140ms; }
.aw-nav__links a:hover::before { opacity: 1; }
.aw-nav__led {
  position: absolute; bottom: 4px; left: 0; width: 6px; height: 6px; background: var(--jb-neon);
  box-shadow: 0 0 8px rgba(64,200,236,.9); opacity: 0;
  transform: translate3d(var(--x, 0px), 0, 0);
  transition: transform 180ms var(--spring-snappy), opacity 180ms linear;
}
.aw-nav__led.is-on { opacity: 1; }
.aw-nav__home { color: var(--jb-dim-aa) !important; font-size: 13px; flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px; }
.aw-nav__home:hover { color: var(--jb-neon) !important; }
.aw-order-pill {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--jb-neon); color: #0a0a0f !important;
  font-family: var(--jb-font-head); font-size: 10px; letter-spacing: 1px; line-height: 1.4;
  min-height: 44px; padding: 8px 18px; border-radius: var(--jb-r-btn); text-align: center; white-space: nowrap;
  box-shadow: 0 0 20px rgba(64,200,236,.35);
  transition: box-shadow 180ms var(--spring-snappy), transform 120ms var(--spring-snappy);
}
.aw-order-pill:hover { box-shadow: 0 0 32px rgba(64,200,236,.6); color: #0a0a0f !important; }
.aw-order-pill:active { transform: translateY(1px); }
.aw-nav__order { flex: 0 0 auto; }

/* ---------- hero ----------
   No photograph under the headline. The one live thing that could sit behind
   the H1 is the world itself, and a 1280x720 capture of the cabinet screen was
   sitting on top of it -- putting the cabinet's own rail, its own HUD line and
   the cabinet's own station list on the most prominent surface of the site, and
   rendering the cabinet's
   8px type at 2.4px on a phone. It survives as a framed still in #visualizer. */
.aw-hero {
  position: relative; view-transition-name: aw-hero;
  min-height: min(88vh, 760px);
  display: flex; align-items: center; justify-content: center;
  padding: 56px 24px 24px;
}
.aw-hero__stack { position: relative; display: flex; flex-direction: column; align-items: center; gap: 20px; text-align: center; max-width: 940px; }
/* a soft plate under the hero copy: depth, not a box */
.aw-hero__stack::before {
  content: ''; position: absolute; inset: -40px -16px -28px; z-index: -1; pointer-events: none;
  background: radial-gradient(115% 100% at 50% 55%, rgba(10,10,15,.72) 0%, rgba(10,10,15,.42) 50%, rgba(10,10,15,0) 78%);
}
.aw-badge { background: var(--jb-gold); color: #0a0a0f; font-family: var(--jb-font-head); font-size: 11px; line-height: 1.6; padding: 8px 12px; letter-spacing: 2px; }
.aw-h1 { margin: 0; font-family: var(--jb-font-head); font-size: 30px; line-height: 1.4; color: var(--jb-neon); letter-spacing: 3px; max-width: 940px; text-shadow: 0 0 28px rgba(64,200,236,.45); text-wrap: pretty; }
/* the headline arrives 40ms per word; the words are wrapped by script so the
   markup stays one readable sentence and no-JS gets it whole */
.aw-h1 .aw-word { display: inline-block; }
/* An ANIMATION, not a transition: an animation with `both` always runs to its
   end once it starts, so a throttled frame loop or a missed class can never
   leave the headline invisible. With no animation at all the words are simply
   already there. */
@keyframes aw-wordin { from { opacity: .001; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  .aw-h1.is-split .aw-word { animation: aw-wordin 420ms var(--spring-standard) both; animation-delay: calc(var(--i, 0) * 40ms); }
}
.aw-strap { font-size: 16px; line-height: 1.7; color: var(--jb-body); max-width: 720px; margin: 0; }
.aw-strap b { color: var(--jb-hot); font-weight: 600; }
.aw-hero__cta { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; align-items: center; }
.aw-coin-status { margin: 0; font-size: 13px; color: var(--jb-dim-aa); min-height: 1.25em; }
.aw-coin-status.is-blocked { color: var(--jb-gold); }

/* the live band under the hero: the page's own visualizer, not footage.
   The frame is transparent so the sun and grid move visibly through the bars. */
.aw-hero__band { position: relative; max-width: 1100px; margin: -8px auto 0; padding: 0 32px; z-index: 8; }
.aw-hero__band .screen { background: transparent; }
.aw-hero__band canvas { display: block; width: 100%; height: 100%; }
.aw-band__head { position: absolute; left: 10px; right: 10px; top: 8px; z-index: 2; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; font-size: 13px; color: var(--jb-dim-aa); }
.aw-band-note { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 10px 0 0; color: var(--jb-dim-aa); font-size: 15px; }
/* the hero runs the world at full strength, so the copy that sits in it carries
   its own shadow rather than asking the veil to be darker everywhere */
.aw-strap, .aw-band-note, .aw-coin-status { text-shadow: 0 1px 8px rgba(10,10,15,.92), 0 0 2px rgba(10,10,15,.8); }
.aw-band-note .px { color: var(--jb-neon); font-size: 13px; }

/* ---------- section furniture ----------
   --aw-navh and --aw-dockh are written by ResizeObservers, so an anchor jump
   lands under the nav and above the dock whatever height they end up. A
   hard-coded 84px against a 122px nav put every jump 38px under the nav. */
.aw-section { scroll-margin-top: calc(var(--aw-navh, 64px) + 12px); scroll-margin-bottom: calc(var(--aw-dockh, 0px) + 16px); position: relative; }
.aw-wrap { max-width: 1100px; margin: 0 auto; padding: 96px 32px 0; }
.aw-wrap--narrow { max-width: 880px; }
.aw-eyebrow { font-family: var(--jb-font-head); font-size: 11px; color: var(--jb-gold); letter-spacing: 3px; margin: 0; line-height: 1.6; }
.aw-h2 { margin: 18px 0 0; font-family: var(--jb-font-head); font-size: 19px; line-height: 1.6; color: var(--jb-neon); letter-spacing: 2px; text-wrap: pretty; }
.aw-h2--c { text-align: center; }
.aw-h3 { margin: 0 0 10px; font-family: var(--jb-font-head); font-size: 12px; line-height: 1.7; color: var(--jb-neon); letter-spacing: 1px; }
.aw-h3 .aw-cursor { color: var(--jb-gold); }
.aw-lead { margin-top: 14px; font-size: 17px; line-height: 1.7; color: var(--jb-body); }
.aw-body { margin-top: 28px; display: flex; flex-direction: column; gap: 18px; font-size: 17px; line-height: 1.7; color: var(--jb-body); }
.aw-body p { margin: 0; }
.aw-body .aw-quiet { color: var(--jb-secondary); }
.aw-p { font-size: 15px; line-height: 1.65; color: var(--jb-secondary); margin: 0 0 10px; }
.aw-p:last-child { margin-bottom: 0; }
/* a [CONFIRM] is a note to us, not a headline: a dim outline chip, never gold
   inline text the eye catches before the sentence it sits in */
.aw-confirm {
  display: inline-block; border: 1px solid rgba(242,227,16,.32); color: var(--jb-dim-aa);
  font-family: ui-monospace, Menlo, monospace; font-size: 12px; line-height: 1.5;
  padding: 1px 6px; border-radius: 4px; white-space: normal;
}
.aw-note { font-size: 14px; line-height: 1.6; color: var(--jb-dim-aa); }

/* pixel captions that quote the cabinet screen. These carry the per-screen
   honesty lines, so they are the copy most worth reading on the page. */
.aw-cap { margin-top: 10px; font-family: var(--jb-font-px); font-size: 15px; line-height: 1.35; color: var(--jb-dim-aa); text-transform: uppercase; letter-spacing: 0; }
/* captions and notes sit directly on the world in places; they carry their own
   ground rather than asking the veil to be darker for the whole page */
.aw-cap, .aw-note, .aw-scrollnote { text-shadow: 0 1px 8px rgba(10,10,15,.92); }
.aw-cap .c-gold { color: var(--jb-gold); }

/* ---------- cards ---------- */
.aw-cards { margin-top: 32px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; }
.aw-card {
  background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.09); border-radius: var(--jb-r-card);
  padding: 26px; display: flex; flex-direction: column; gap: 14px;
  transition: transform 220ms var(--spring-bouncy), border-color 220ms var(--spring-standard), box-shadow 220ms var(--spring-standard);
}
.aw-card:hover { transform: scale(1.02); border-color: rgba(64,200,236,.4); }
.aw-card img.aw-icon { width: 44px; height: auto; image-rendering: pixelated; }
.aw-card__t { font-family: var(--jb-font-head); font-size: 12px; line-height: 1.7; color: var(--jb-neon); letter-spacing: 1px; overflow-wrap: anywhere; }
.aw-card__b { font-size: 15px; line-height: 1.6; color: var(--jb-secondary); }
.aw-card--hot { border-color: rgba(232,32,138,.35); }
.aw-card--hot:hover { border-color: rgba(232,32,138,.6); }
.aw-card--hot .aw-card__t { color: var(--jb-hot); }
.aw-card--gold { border-color: rgba(242,227,16,.3); }
.aw-card--gold:hover { border-color: rgba(242,227,16,.55); }
.aw-card--gold .aw-card__t { color: var(--jb-gold); }
/* the visualizer card breathes on the beat, off the shared beat bus */
.aw-card--kick { transition: border-color 160ms var(--spring-snappy), box-shadow 160ms var(--spring-snappy), transform 220ms var(--spring-bouncy); }
.is-kick .aw-card--kick { border-color: rgba(232,32,138,.7); box-shadow: 0 0 26px rgba(232,32,138,.22); }

/* ---------- feature rows: a screen beside its explanation ---------- */
.aw-rows { margin-top: 36px; display: flex; flex-direction: column; gap: 56px; }
.aw-row { display: grid; grid-template-columns: 1.15fr 1fr; gap: 36px; align-items: center; }
.aw-row--rev .aw-row__media { order: 2; }
.aw-row__body, .aw-row__media { min-width: 0; }  /* a grid item that scrolls inside
   itself must never size its own track: the EQ's 464 px rack was making #sound's
   1fr track 794 px and the whole document 810 px wide inside a 390 px window. */
.aw-row__body .aw-p { font-size: 16px; color: var(--jb-body); }
.aw-row__body .aw-p + .aw-p { color: var(--jb-secondary); }
/* ...and the same when the run after the first paragraph is folded into a
   disclosure. `+` cannot reach across the <details> boundary, so the first
   paragraph inside one lost the secondary colour it had on the page before.
   Only #sound puts a fold inside a row body; the rule is written generally so
   the next one that does cannot inherit the bug. */
.aw-row__body > .aw-more:not(.aw-fold) .aw-p { color: var(--jb-secondary); }
/* `.aw-p:last-child` drops the trailing 10 px so a run of paragraphs does not
   push a gap onto whatever follows. A fold makes its last paragraph a
   :last-child that is NOT the last thing in the body, and #sound lost exactly
   those 10 px on the desktop because of it. Give them back -- but only when
   something really does follow the fold, so a fold that IS last keeps the 0. */
.aw-fold:not(:last-child) > .aw-p:last-child { margin-bottom: 10px; }
figure { margin: 0; }

/* .aw-frames holds every frame belonging to one block. On desktop it is a
   stack; on a phone it is the kit's full-bleed snap rail, so nine stacked
   screenshots become four carousels you thumb through. One container, two
   compositions, and the copy never moves. */
.aw-frames { display: grid; gap: 16px; }
@media (min-width: 768px) {
  .aw-frames.jb-rail { display: grid; overflow: visible; padding: 0; scroll-snap-type: none; }
  .aw-frames.jb-rail > .jb-rail__card { width: auto; }
  .aw-frames.jb-fade-x { -webkit-mask-image: none; mask-image: none; }
  .aw-frames--two { grid-template-columns: 1fr 1fr; }
}
.aw-frames > figure { min-width: 0; }

/* a section's own tab strip: real anchors to its blocks, the cabinet's tab
   names where the cabinet has them. Works with no JavaScript. */
.aw-tabs { margin-top: 22px; }
.aw-tabs .tab { text-decoration: none; }

/* ---------- the picker's lead frame ---------- */
.aw-lead-frame { margin-top: 28px; }

/* ---------- Denise's stage ---------- */
.aw-stage { margin-top: 32px; }
.aw-stage .screen { position: relative; }
#denise-stage { display: block; width: 100%; height: 100%; }
.aw-stepper__frames { position: absolute; inset: 0; }
.aw-stepper__frames img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 320ms var(--spring-standard); }
.aw-stepper__frames img.is-on { opacity: 1; }
.aw-stepper__ctl { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; align-items: center; }
.aw-step-btn { font-family: var(--jb-font-px); font-size: 15px; background: transparent; border: 1px solid var(--jb-hairline); color: var(--jb-dim-aa); min-height: 44px; padding: 0 14px; cursor: pointer; text-transform: uppercase; }
.aw-step-btn[aria-current="true"] { border-color: var(--jb-neon); color: var(--jb-ink); }
.aw-step-btn:hover { color: var(--jb-ink); }
.aw-push { display: none; }   /* the phone's one big PUSH IT; see the phone cut */

/* ---------- crew sprites ---------- */
.aw-crew { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; margin-top: 32px; }
.aw-crew__fig { display: flex; gap: 20px; align-items: flex-start; }
.aw-crew__fig img { image-rendering: pixelated; flex: 0 0 auto; }
.aw-crew__fig .rick { flex: 0 0 68px; }
/* Rick's ZZZ sits outside his 68 px box by design; the card keeps it in */
.aw-crew__fig { overflow: hidden; }
/* Denise idles on a two-frame swap, the cabinet's own steps() cadence, and only
   while her section is near. Rick is the kit's Rick: asleep with ZZZ until the
   coin, then one head-bob per kick -- on the music, not on a wall clock. */
.aw-denise { position: relative; width: 66px; height: 84px; flex: 0 0 auto; }
.aw-denise img { position: absolute; inset: 0; width: 66px; height: 84px; }
.aw-denise img + img { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .is-near .aw-denise img + img { animation: aw-denise-idle 1.34s steps(1) infinite; }
}
@keyframes aw-denise-idle { 0%, 49.9% { opacity: 0; } 50%, 100% { opacity: 1; } }

/* ---------- the update narration ----------
   The cabinet's six strings, in turn, on a 900ms cadence under a progress bar
   with the moving highlight. The cheapest good motion on the page: CSS plus one
   interval that only runs while the section is near. */
.aw-narrate { margin-top: 28px; border: 1px solid var(--jb-hairline); border-radius: var(--jb-r-card); background: rgba(6,7,15,.6); padding: 18px; }
.aw-narrate__bar { position: relative; height: 6px; background: var(--jb-track); overflow: hidden; }
.aw-narrate__bar i { position: absolute; top: 0; bottom: 0; left: 0; width: 38%; background: linear-gradient(90deg, transparent, var(--jb-neon), transparent); animation: aw-sweep 1.2s linear infinite; animation-play-state: paused; }
.is-near .aw-narrate__bar i { animation-play-state: running; }
@keyframes aw-sweep { from { transform: translateX(-100%); } to { transform: translateX(300%); } }
.aw-narrate ol { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 7px; }
.aw-narrate li { font-family: var(--jb-font-px); font-size: 15px; line-height: 1.3; text-transform: uppercase; color: var(--jb-dim-aa); opacity: .35; transition: opacity 300ms linear, color 300ms linear; }
.aw-narrate li.is-on { opacity: 1; color: var(--jb-ink); }
.aw-narrate li.is-done { opacity: .7; }
.aw-narrate li:last-child.is-on { color: var(--jb-led); }

/* ---------- a phone screenshot gets a phone's shape ----------
   9:19.5, and the long one scrolls inside itself: 4,538px of squashed PNG
   becomes a frame you can flick through, and its length becomes the point
   instead of the problem. */
.aw-phone-frame {
  aspect-ratio: 9 / 19.5; max-width: 320px; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch; border: 1px solid rgba(64,200,236,.25); border-radius: 6px;
  background: #000; scrollbar-width: thin;
}
.aw-phone-frame img { display: block; width: 100%; height: auto; }
.aw-scrollnote { margin: 8px 0 0; font-family: var(--jb-font-px); font-size: 13px; color: var(--jb-dim-aa); text-transform: uppercase; }

/* ---------- tables ---------- */
.aw-tablewrap { margin-top: 28px; overflow-x: auto; overscroll-behavior-x: contain; border: 1px solid var(--jb-hairline); border-radius: var(--jb-r-card); }
table.aw-table { border-collapse: collapse; width: 100%; min-width: 720px; font-size: 15px; }
table.aw-table caption { text-align: left; padding: 16px 18px 0; color: var(--jb-secondary); font-size: 14px; }
.aw-table th, .aw-table td { text-align: left; padding: 12px 18px; border-bottom: 1px solid var(--jb-hairline); vertical-align: top; }
.aw-table thead th { font-family: var(--jb-font-head); font-size: 9px; letter-spacing: 2px; color: var(--jb-gold); text-transform: uppercase; }
.aw-table tbody th { font-family: var(--jb-font-px); font-size: 15px; color: var(--jb-ink); font-weight: normal; white-space: nowrap; }
.aw-table td { color: var(--jb-secondary); }
.aw-table .yes { color: var(--jb-led); }
.aw-table .no { color: var(--jb-dim-aa); }
.aw-table .soon { color: var(--jb-gold); }
.aw-table tr:last-child th, .aw-table tr:last-child td { border-bottom: 0; }
/* the tick list lights in sequence when the table arrives */
.aw-table--led tbody th::before {
  content: ''; display: inline-block; width: 8px; height: 8px; margin-right: 10px; vertical-align: 1px;
  background: var(--jb-led); opacity: 0; transition: opacity 200ms linear;
}
.aw-table--led.is-in tbody th::before { opacity: 1; transition-delay: calc(var(--i, 0) * 60ms); }
.aw-table--led tbody tr { --i: 0; }

/* ---------- the app block ---------- */
.aw-wave2 { border: 1px solid rgba(242,227,16,.28); border-radius: var(--jb-r-panel); padding: 32px; background: rgba(242,227,16,.02); }
.aw-wave2__badge { display: inline-block; background: var(--jb-gold); color: #0a0a0f; font-family: var(--jb-font-head); font-size: 10px; line-height: 1.6; letter-spacing: 2px; padding: 8px 12px; }
.aw-rolling { display: inline-block; border: 1px solid rgba(242,227,16,.5); color: var(--jb-gold); font-family: var(--jb-font-head); font-size: 9px; letter-spacing: 2px; padding: 5px 8px; white-space: nowrap; }
.aw-phone { position: relative; border: 8px solid #1a1c24; border-radius: 34px; background: #000; box-shadow: 0 0 0 2px #33363f, 0 24px 60px rgba(0,0,0,.6); overflow: hidden; }
.aw-phone::before { content: ''; position: absolute; left: 50%; top: 8px; transform: translateX(-50%); width: 34%; height: 16px; border-radius: 12px; background: #000; z-index: 2; }
.aw-phone img { display: block; width: 100%; height: auto; border-radius: 26px; }
.aw-phonecap { margin-top: 10px; font-size: 14px; line-height: 1.5; color: var(--jb-dim-aa); text-align: center; }
.aw-store { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 24px; }
.aw-store span {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px;
  border: 1px dashed rgba(255,255,255,.18); border-radius: 8px; color: var(--jb-dim-aa);
  font-family: var(--jb-font-head); font-size: 9px; letter-spacing: 1.5px;
}
.aw-androidcard { margin-top: 28px; }

/* ---------- how it arrives: a four-step rail that fills on scroll ---------- */
.aw-steps { counter-reset: awstep; list-style: none; margin: 28px 0 0; padding: 0; position: relative; }
.aw-steps__track { position: absolute; left: 13px; top: 8px; bottom: 8px; width: 2px; background: var(--jb-track); }
.aw-steps__track i { position: absolute; left: 0; right: 0; top: 0; height: calc(var(--p, 0) * 100%); background: var(--jb-neon); box-shadow: 0 0 10px rgba(64,200,236,.6); }
.aw-steps li { counter-increment: awstep; position: relative; padding: 12px 0 12px 46px; font-family: var(--jb-font-px); font-size: 15px; line-height: 1.4; text-transform: uppercase; color: var(--jb-body); }
.aw-steps li::before {
  content: counter(awstep); position: absolute; left: 0; top: 10px;
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  background: var(--jb-bg); border: 1px solid var(--jb-neon); color: var(--jb-neon); font-size: 13px;
}

/* ---------- FAQ ---------- */
.aw-faq { margin-top: 28px; border: 1px solid var(--jb-hairline); border-radius: var(--jb-r-card); overflow: hidden; }
.aw-faq details { border-bottom: 1px solid var(--jb-hairline); background: rgba(6,7,15,.5); }
.aw-faq details:last-child { border-bottom: 0; }
.aw-faq summary { list-style: none; cursor: pointer; padding: 16px 20px; min-height: 44px; box-sizing: border-box; font-family: var(--jb-font-head); font-size: 11px; line-height: 1.7; letter-spacing: 1px; color: var(--jb-ink); display: flex; gap: 12px; align-items: center; }
.aw-faq summary::-webkit-details-marker { display: none; }
.aw-faq summary::before { content: '>'; color: var(--jb-gold); font-family: var(--jb-font-px); transition: transform 120ms var(--spring-snappy); flex: 0 0 auto; }
.aw-faq details[open] summary { color: var(--jb-neon); }
.aw-faq details[open] summary::before { transform: rotate(90deg); }
.aw-faq .aw-a { padding: 0 20px 20px 44px; font-size: 16px; line-height: 1.7; color: var(--jb-body); margin: 0; }

/* ---------- order ---------- */
.aw-order {
  background: var(--jb-glass);
  -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3);
  border: 1px solid rgba(255,255,255,.12); border-radius: 18px;
  padding: 56px 48px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 24px;
}
.aw-price { font-family: var(--jb-font-head); font-size: 34px; line-height: 1.4; color: var(--jb-neon); letter-spacing: 2px; text-shadow: 0 0 24px rgba(64,200,236,.4); }
.aw-terms { max-width: 620px; font-size: 16px; line-height: 1.7; color: var(--jb-secondary); }
.aw-cta {
  display: inline-flex; align-items: center; justify-content: center; min-height: 56px;
  background: var(--jb-neon); color: #0a0a0f !important;
  font-family: var(--jb-font-head); font-size: 15px; line-height: 1.5; letter-spacing: 2px; padding: 18px 40px;
  border: 2px solid var(--jb-hot); border-radius: var(--jb-r-btn);
  box-shadow: 0 0 24px rgba(232,32,138,.55), 0 0 64px rgba(232,32,138,.28);
  transition: box-shadow 200ms var(--spring-snappy);
}
.aw-cta:hover { box-shadow: 0 0 36px rgba(232,32,138,.8), 0 0 90px rgba(232,32,138,.4); color: #0a0a0f !important; }
.aw-cta:active { transform: translateY(1px); }
.aw-cta.is-flicker { animation: jb-coinflicker 180ms steps(1) 1; }

/* ---------- the buy block ----------
   The order in the shape it will really have: the two fields Shopify's product form carries
   as line-item properties, and the button. Where Shopify will draw its own express-checkout
   button there is a dashed strip that SAYS so, in words. The strip is deliberately not a
   button and borrows no payment brand's mark, colour or shape: Shopify renders the real ones
   itself, on the live form only, and a drawn imitation is a fake payment button on a page that
   gets forwarded. Every selector here is new, so nothing already on the page can move. */
.aw-buy { box-sizing: border-box; width: 100%; max-width: 480px; margin: 0; text-align: left; }
.aw-field { display: block; margin: 0 0 18px; }
.aw-field__label { display: block; font-family: var(--jb-font-head); font-size: 11px; line-height: 1.6; letter-spacing: 1px; text-transform: uppercase; color: var(--jb-ink); }
.aw-field__hint { display: block; margin-top: 2px; font-size: 14px; line-height: 1.5; color: var(--jb-secondary); }
.aw-field input {
  box-sizing: border-box; display: block; width: 100%; min-height: 48px; margin: 8px 0 0; padding: 12px 14px;
  border: 1px solid rgba(255,255,255,.2); border-radius: var(--jb-r-btn); background: rgba(5,6,11,.78);
  color: var(--jb-ink); font: 16px/1.4 var(--jb-font-body);   /* 16 px: iOS zooms the page into anything smaller */
}
.aw-field input:focus-visible { outline: 2px solid var(--jb-gold); outline-offset: 2px; border-color: var(--jb-neon); }
.aw-buy .aw-cta { box-sizing: border-box; width: 100%; margin-top: 6px; padding-left: 20px; padding-right: 20px; text-align: center; cursor: pointer; }
.aw-buy__msg { margin: 14px 0 0; padding: 12px 14px; border: 1px solid rgba(64,200,236,.4); border-radius: var(--jb-r-btn); background: rgba(5,6,11,.78); color: var(--jb-ink); font-size: 15px; line-height: 1.6; }
/* empty, it stays in the accessibility tree (so the live region is heard when it speaks) and
   draws nothing; display:none would take it out of the tree */
.aw-buy__msg:empty { margin: 0; padding: 0; border: 0; }
.aw-express { margin: 14px 0 0; padding: 12px 14px; border: 1px dashed rgba(255,255,255,.2); border-radius: var(--jb-r-btn); background: rgba(5,6,11,.66); color: var(--jb-body); font-size: 14px; line-height: 1.6; text-align: center; }
.aw-express__label { display: block; margin-bottom: 4px; font-family: var(--jb-font-head); font-size: 11px; line-height: 1.6; letter-spacing: 1px; color: var(--jb-secondary); }

/* ---------- footer ---------- */
.aw-footer { margin-top: 112px; border-top: 1px solid rgba(255,255,255,.07); padding: 40px 32px; text-align: center; font-size: 14px; line-height: 1.8; color: var(--jb-dim-aa); }
.aw-footer a { color: var(--jb-secondary); display: inline-flex; align-items: center; min-height: 44px; }
.aw-footer__mark { font-family: var(--jb-font-head); font-size: 11px; padding-bottom: 10px; }
.aw-hudstrip { display: flex; gap: 10px; justify-content: center; align-items: center; flex-wrap: wrap; margin: 16px 0 6px; font-family: var(--jb-font-px); font-size: 13px; text-transform: uppercase; color: var(--jb-dim-aa); }
.aw-hudstrip .cursor { display: inline-block; color: var(--jb-gold); }

/* ---------- the phone dock ----------
   Declared here, shown only in the phone cut. Kit .dock supplies the chassis;
   this is the page telling it what its three controls are. */
.dock__row .aw-order-pill {
  border-radius: 0; box-shadow: none; font-size: 11px; white-space: nowrap; padding: 8px 4px;
  /* ORDER . £99 at 11 px with 1 px of tracking measured 132 px inside a 128 px
     plate: two pixels of the price were clipped, which is the same defect
     Jordan photographed at the bottom of the screen. Half a pixel of tracking
     and a 44 px MOTION chip buy it 12 px of headroom without dropping below
     the 11 px type floor. */
  letter-spacing: .5px;
}
/* MOTION IS NO LONGER IN THIS ROW. It used to be a 44 px chip here, then an
   absolutely-positioned chip on the band above it; the band has gone, and three
   plates measure 376 px of glyphs and gaps inside a 366 px row at 390. It is in
   the hero and the footer now (.aw-motion-phone), where it has room to be a
   whole word. The row is two plates with air. */
.dock__row .coin { flex: 1.15 1 0; font-size: 13px; padding-left: 8px; padding-right: 8px; }
/* INSERT COIN needs 141 px of glyphs and ORDER . £99 needs 127: at 12 px of
   side padding and a 1.25 share the price plate had no breathing room left
   and read as clipped. This gives the price 16 px of air and the coin 6. */

/* ---------- reveal on arrival ---------- */
.jb-reveal { transition-delay: calc(var(--i, 0) * 60ms); }

/* ============================================================================
   NARROW DESKTOP (768-1099px). Not a third layout: the desktop composition at
   a tighter gutter. Anything smaller is the phone cut below.
   ========================================================================== */
@media (max-width: 1099px) {
  .aw-nav { padding: 10px 20px; gap: 14px; }
  .aw-nav__links { gap: 16px; font-size: 13px; overflow-x: auto; scrollbar-width: none; }
  .aw-nav__links::-webkit-scrollbar { display: none; }
  .aw-wrap { padding: 72px 20px 0; }
  .aw-row { grid-template-columns: 1fr; gap: 20px; }
  .aw-row--rev .aw-row__media { order: 0; }
  .aw-hero__band { padding: 0 20px; }
  .aw-h1 { font-size: 26px; }
}

/* ============================================================================
   THE PHONE CUT (<= 767px). Its own composition, not the page narrowed.

   The thesis in one line: the cabinet gives the visualizer the bottom half of
   its screen on every source, and a phone is the only screen whose bottom edge
   is under the reader's thumb. So the live band comes off the back of the page
   -- where it composited to 0.03 alpha and nobody ever saw it -- and is pinned
   to the bottom edge at full brightness, on every screen, inside .dock. The
   dock also carries INSERT COIN and ORDER, and it carries NO TEXT in the band
   row, which is why nothing there can ever be clipped.

   Two widths only above it: the 16px column for copy, full bleed for pictures.
   Nothing in between -- a 358px picture with 16px of ground either side is the
   narrow-laptop look this view exists to avoid.
   ========================================================================== */
@media (max-width: 767px) {

  /* -- the chassis ------------------------------------------------------- */
  body { padding-bottom: calc(var(--aw-dockh, 104px) + 16px); }
  .aw-wrap { padding: 44px calc(16px + env(safe-area-inset-left, 0px)) 0 calc(16px + env(safe-area-inset-right, 0px)); }
  .aw-wrap--narrow { max-width: none; }
  #hud { display: none; }                        /* the dock replaces it entirely */

  /* the nav: 95px, two rows, and complete. Every one of the six sections is
     reachable by thumbing the strip, with an edge fade that says so. */
  .aw-nav {
    display: grid; grid-template-columns: auto 1fr; grid-template-areas: "mark pill" "strip strip";
    padding: 0; gap: 0; align-items: center;
    /* 0.78 is a desktop number: on a phone the nav sits 95 px over full-width
       display type and the headings read straight through the mark and the
       chips. The blur stays; the ground stops being a window. */
    background: rgba(10, 10, 15, .94);
  }
  .aw-mark { grid-area: mark; min-height: 44px; padding-left: calc(12px + env(safe-area-inset-left, 0px)); font-size: 13px; }
  .aw-mark .j { font-size: 8px; margin-left: 8px; }
  .aw-nav__order { grid-area: pill; justify-self: end; min-height: 44px; margin: 3px calc(12px + env(safe-area-inset-right, 0px)) 3px 0; padding: 8px 14px; font-size: 10px; }
  /* THE STRIP IS A SCROLLER AND IT HAS TO LOOK LIKE ONE. Six section labels are 508 px of
     glyphs at the 11 px floor: 375 px cannot hold them and dropping the type is not on the
     table. What was wrong was the RIGHT EDGE -- "Visualizer  You" and then a guillotine, which
     reads as a page that overflows rather than a row that scrolls. The labels now dissolve into
     the nav's own ground over 46 px, the last chip has room to clear that fade, and a caret sits
     in it saying which way the rest is. The caret goes out at the end of the scroll (data-more),
     so it never points at nothing. */
  /* STICKY, not relative. This line only ever existed to give the caret below something to be
     absolute inside -- but `position` is a single property, and `relative` here silently
     cancelled the `position: sticky` the base rule sets, so on a phone the nav scrolled away
     and never came back. Every `.aw-section` carries
     `scroll-margin-top: calc(var(--aw-navh) + 12px)`, so a nav link was also landing its
     section 107 px down an otherwise empty screen -- a gap held open for a bar that was no
     longer there. `sticky` is a positioned value too: the caret's containing block, the
     `top: 0` and the `z-index: 20` all come from the base rule and are unchanged. */
  .aw-nav { position: sticky; }
  .aw-nav__scroll {
    grid-area: strip; height: 44px; gap: 10px; overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x proximity; overscroll-behavior-x: contain; scrollbar-width: none;
    padding: 0 calc(58px + env(safe-area-inset-right, 0px)) 0 calc(12px + env(safe-area-inset-left, 0px));
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 60px), transparent calc(100% - 14px));
    mask-image: linear-gradient(90deg, #000 calc(100% - 60px), transparent calc(100% - 14px));
  }
  .aw-nav::after {
    content: '\203A';
    position: absolute; bottom: 0; right: 0;
    width: calc(46px + env(safe-area-inset-right, 0px)); height: 44px;
    display: flex; align-items: center; justify-content: center;
    padding-right: env(safe-area-inset-right, 0px);
    font-family: var(--jb-font-head); font-size: 18px; line-height: 1; color: var(--jb-gold);
    background: linear-gradient(90deg, rgba(10, 10, 15, 0) 0, rgba(10, 10, 15, .96) 10px);
    pointer-events: none; opacity: .9; transition: opacity 220ms linear;
  }
  .aw-nav[data-more="0"]::after { opacity: 0; }
  .aw-nav__scroll::-webkit-scrollbar { display: none; }
  /* the handshake link leaves the section group: it was styled as their peer
     and coloured so it could not be read. Its own chip, ahead of them. */
  /* the sections lead the strip; the handshake link is discreet, at the end */
  .aw-nav__home { order: 2; font-size: 12px; min-height: 44px; border-left: 1px solid var(--jb-hairline); padding-left: 14px; flex: 0 0 auto; }
  .aw-nav__links { order: 1; gap: 10px; flex: 0 0 auto; }
  .aw-nav__links a { font-family: var(--jb-font-head); font-size: 11px; letter-spacing: 1px; min-height: 44px; min-width: 44px; justify-content: center; scroll-snap-align: center; }
  .aw-nav__links a::before { display: none; }
  .aw-nav__led { bottom: 2px; }

  /* -- the type scale: 11px floor, and nothing carrying information under 13 -- */
  .aw-h1 { font-size: 22px; line-height: 1.35; letter-spacing: 2px; }
  .aw-h2 { font-size: 18px; line-height: 1.35; letter-spacing: 1px; margin-top: 14px; }
  .aw-h3 { font-size: 14px; line-height: 1.5; }
  .aw-eyebrow { font-size: 11px; }
  .aw-lead, .aw-body, .aw-strap { font-size: 16px; line-height: 1.65; }
  .aw-p, .aw-card__b, .aw-terms, .aw-faq .aw-a { font-size: 16px; line-height: 1.6; }
  /* the world runs full strength behind the reading column on a phone and the
     sun crosses several sections of prose. The hero's strap already carries
     this shadow for exactly that reason; every run of body copy needs it. */
  .aw-p, .aw-lead, .aw-cap, .aw-note, .aw-h2, .aw-h3, .aw-eyebrow, .aw-terms,
  .aw-deflist dt, .aw-deflist dd, .aw-phonecap {
    text-shadow: 0 1px 8px rgba(10, 10, 15, .92), 0 0 2px rgba(10, 10, 15, .8);
  }
  .aw-cap { font-size: 15px; }
  .aw-note, .aw-phonecap { font-size: 14px; }
  .px { font-size: 13px; }
  .aw-card__t { font-size: 14px; }
  .aw-faq summary { font-size: 13px; min-height: 56px; }
  /* the 11 px floor, kept: nothing on the phone is smaller than this, and
     anything carrying a fact is 13 or more */
  .aw-rolling, .aw-store span, .aw-mark .j { font-size: 11px; }
  .aw-order-pill, .aw-wave2__badge { font-size: 11px; }
  .aw-nav__home, .aw-confirm { font-size: 13px; }
  /* a dt is the feature name of a stacked comparison row -- it carries the fact,
     so it obeys the 13 px rule the comment above states */
  .aw-deflist dt { font-size: 13px; }

  /* -- full bleed: every picture, every carousel, the dock band ------------ */
  /* Every rail is full bleed on a phone, the picker's included: a carousel with
     16 px of ground either side is the narrow-laptop look this view avoids.
     The bleed is the column's own gutter negated, not `50% - 50vw`: vw counts
     a scrollbar and disagrees with the layout width inside device emulators,
     and either one puts the page a few pixels wider than the window. */
  .jb-rail, .aw-bleed,
  .picker--swipe .picker__rail {   /* the kit's own margin shorthand outranks .jb-rail */
    width: auto;
    margin-left: calc(-16px - env(safe-area-inset-left, 0px));
    margin-right: calc(-16px - env(safe-area-inset-right, 0px));
  }
  .picker--swipe .picker__rail { margin-bottom: 8px; }
  /* the app's rail sits inside the WAVE2 panel, so it has 14 px more to negate */
  #app .jb-deck__cards { margin-left: calc(-31px - env(safe-area-inset-left, 0px)); margin-right: calc(-31px - env(safe-area-inset-right, 0px)); }
  .jb-rail__dots { padding: 0 16px; }
  /* the kit's 32 px section title is the cabinet's; the page already has an H2 */
  .picker__head .title { font-size: 16px; }
  .picker__head { padding: 0; gap: 10px; }
  .picker__caption, .picker__row--pinned { font-size: 13px; }
  /* THE LIVE CARD. jukebox-screens.js's LiveBand is ONE canvas that travels to whichever card is
     under the thumb and draws that card's own mode on the page's music. It lies OVER the still,
     never after it: in normal flow it lands under the picture and the card's overflow clips it
     away -- which is exactly where the old #viz-layer and <video> went on this cut, measured in
     WebKit at top 152 px of a 151 px card, unseen while the caption said LIVE. It is the card's
     own 2:1 and it fades up only once its first frame has painted. The caption is held at two
     lines because RECORDED FROM THE JUKEBOX wraps at 390 and LIVE ON THIS PAGE does not: without
     the floor everything below the picker jumped 17 px each time a card went live or came back. */
  .picker--swipe .picker__caption { min-height: 2.5em; }
  .viz-card__shot > .jb-band {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; transition: opacity 200ms linear; pointer-events: none;
  }
  .viz-card__shot.is-live > .jb-band { opacity: 1; }
  .jb-motion-off .viz-card__shot > .jb-band { display: none !important; }
  @media (prefers-reduced-motion: reduce) { .viz-card__shot > .jb-band { display: none !important; } }
  .screen { border-radius: 0; border-left: 0; border-right: 0; }
  .jb-rail__card .screen { border-radius: var(--jb-r-btn); border-left: 1px solid var(--jb-img-border); border-right: 1px solid var(--jb-img-border); }
  /* THE CAROUSELS THAT NEVER WERE. `.aw-frames { display: grid }` above is a single class, and
     it is declared AFTER kit/jukebox.css, so it beat the kit's own `.jb-rail { display: flex }`
     at every width -- which is why the `@media (min-width: 768px)` block has to say
     `display: grid` again to turn the rail off, and why turning it off changed nothing. The
     rail's other half all arrived (overflow-x, the snap type, the padding, the bleed, the edge
     fade); only the axis was missing, so a phone got the nine stacked pictures this cut was
     written to replace -- and in the radio block that is three cabinet frames one under the
     other with the same BARS band running in each. Two classes outrank one, and this is inside
     the phone cut, so nothing at 768 px and up can see it. */
  .aw-frames.jb-rail { display: flex; gap: 12px; }
  .aw-frames.jb-rail > figure { width: calc(100vw - 40px); }
  .aw-frames.jb-rail .aw-cap { padding: 0 2px; }

  /* -- the hero: world, headline, act, then explain ------------------------
     The act comes before the explanation: on a phone the visitor is one thumb
     and four seconds, and INSERT COIN is the only thing they can do that
     changes anything. Measured at 390x844 the coin's bottom lands under 400px. */
  .aw-hero { min-height: 0; padding: 20px 16px 8px; }
  .aw-hero__stack { display: flex; flex-direction: column; gap: 12px; width: 100%; }
  .aw-badge { order: 1; font-size: 11px; align-self: stretch; padding: 7px 10px; }
  .aw-h1 { order: 2; }
  .aw-hero__cta { order: 3; flex-direction: column; align-items: stretch; gap: 10px; width: 100%; }
  /* PRESS INSERT COIN FOR SOUND  SCROLL FOR THE REST is two statements with the cabinet's own
     double space between them. At 375 px the line broke after FOR, so the reader met "FOR /
     SOUND  SCROLL FOR THE REST" and it read as one run-on sentence. Not a word of it changes:
     the module gives each half of the double space its own line box. */
  .aw-coin-status { order: 4; font-size: 13px; text-align: left; }
  .aw-coin-status .seg { display: block; white-space: normal; }
  .aw-coin-status .seg + .seg { margin-top: 2px; }
  /* PRESS INSERT COIN FOR SOUND is 27 glyphs, which is 351 px at the 13 px this line has to keep
     (it carries CREDIT 01 and LIVE  124 BPM, and those are facts). The column is 343. The line is
     therefore allowed 14 px of the hero's own right-hand gutter -- the LEFT edge does not move, so
     it stays flush with every other line in the column, and the box has no ground and no border,
     so a reader cannot tell where it ends. Dropping the type instead would have been the wrong
     eight pixels to save. */
  .aw-coin-status { margin-right: -14px; }
  /* and if a future line is longer than that, it breaks in two even halves rather than orphaning
     one word: a belt to the fourteen pixels' braces */
  .aw-coin-status .seg { text-wrap: balance; }
  .aw-strap { order: 5; text-align: left; }
  .aw-hero__cta .coin--big, .aw-hero__cta .aw-order-pill { width: 100%; min-height: 56px; font-size: 14px; }
  /* THE ATTRACT FLICKER, DEEPER. The plate has always pulsed -- measured on this build at 375 px
     it goes 1 -> 0.55 at 2.5 Hz, and it did before this pass too. But 0.55 on a saturated gold
     plate the width of the screen is a shimmer you have to be looking for, and on a phone the
     coin is the only thing a reader can do. 0.34 is the same 400/400 square wave with enough
     depth to be seen out of the corner of an eye. This is the ONE documented exception to
     "motion means real audio": it is an invitation to press, not a claim about sound. */
  .coin { --jb-blink-low: .34; }
  .aw-hero__stack::before { inset: -20px -16px -12px; }
  /* THE HERO GETS ITS BAND BACK. It was cut as "a duplicate that costs a canvas and a screen of
     height", and both halves of that were wrong on the page as it reads: the dock's strip is 48 px
     at the very bottom edge, under the thumb rather than in the eye, and the note directly below
     this promises "the visualizer on this page is running in your browser" with nothing beside it
     to be running. A 4:1 strip at full bleed is 94 px, not a screen; the canvas is 640x160, which
     is a quarter of the desktop's buffer.

     The head keeps the desktop's composition -- pills floating at the top of the band, which is
     where the cabinet's own HUD line is and where the Bars renderer has nothing but ground, since
     its forty bars stand up from the floor. It is simply smaller: 11 px pills in a 96 px strip
     rather than 13 px ones in a 259 px strip. ON AIR needs somewhere a reader can see it. */
  .aw-hero__band { padding: 0; margin-top: 18px; }
  .aw-hero__band .screen--band { border-radius: 0; border-left: 0; border-right: 0; }
  .aw-band__head { left: 10px; right: 10px; top: 6px; gap: 6px; font-size: 11px; }
  /* the phone cut puts .px at 13; inside a 96 px band the head has to be the 11 px floor or the
     three pills wrap to a second row and take a third of the strip */
  .aw-band__head .px, .aw-band__head .pill { font-size: 11px; }
  .aw-band-note { flex-direction: column; gap: 6px; font-size: 15px; padding: 0 16px; }

  /* -- the claims grid: two columns, so every one is scannable at once ----- */
  #features .aw-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 22px;
    /* a card that opens must not stretch the one beside it into a tall empty
       bordered box: each tile keeps its own height */
    align-items: start; }
  #features .aw-card { padding: 14px; gap: 8px; }
  /* the world is at full strength behind these on a phone and the card ground is
     3 % white: 15 px secondary body copy was landing straight on the sun. The EQ
     already takes this treatment; the cards need it more, because they are the
     claims list and every one of them has to be readable. */
  .aw-card { background: rgba(6, 7, 15, .72); }
  /* A tap leaves :hover stuck on iOS. That was cosmetic while a card was just a
     card; now that the nine cards ARE the controls, the 1.02 scale dragged the
     card 3-4 px up the screen at the exact moment the reader opened it. The
     colour still answers the touch; the geometry does not move. */
  .aw-card:hover { transform: none; }
  #features .aw-card img.aw-icon { width: 32px; }
  #app .aw-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  #app .aw-card { padding: 14px; gap: 8px; }

  /* -- rows stack, media first -------------------------------------------- */
  .aw-row { grid-template-columns: 1fr; gap: 12px; }
  .aw-row--rev .aw-row__media { order: 0; }
  .aw-rows { gap: 28px; }

  /* -- Denise is a toy: one 56px button, five stops, nothing painting between - */
  .aw-stage { margin-top: 22px; }
  .aw-push { display: inline-flex; align-items: center; justify-content: center; width: 100%; min-height: 56px; font-size: 15px; }
  .aw-stepper__ctl { gap: 8px; }
  .aw-stepper__ctl .aw-step-btn { flex: 1 1 40%; justify-content: center; font-size: 13px; padding: 0 6px; }

  /* -- the app: no bezel. The visitor's own phone is the bezel. ------------ */
  .aw-wave2 { padding: 18px 14px; border-radius: var(--jb-r-card); }
  .aw-phone { border: 0; border-radius: 0; box-shadow: none; aspect-ratio: 9 / 16; overflow: hidden; }
  .aw-phone::before { display: none; }
  .aw-phone img { border-radius: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; }
  .aw-phonecap { text-align: left; }

  /* -- both tables become stacked rows (built by script from the same markup,
        so the copy has one source). With no script they stay tables inside a
        strip that says, with an edge fade and a note, that it scrolls. ------ */
  .aw-tablewrap.jb-fade-x { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); }
  .aw-deflist { margin-top: 20px; }
  .aw-deflist dd { font-size: 16px; line-height: 1.55; }
  /* a table of Yes/No reads as one line per row, not three */
  .aw-deflist.is-tight dd { display: inline-block; margin: 4px 16px 0 0; font-size: 15px; }
  .aw-deflist dd b { color: var(--jb-gold); font-weight: 400; font-family: var(--jb-font-px); font-size: 13px; text-transform: uppercase; }
  /* inline links inside running prose are exempt from the 44 px width, not from
     being tappable: 6 px of block padding is the plan's own floor for them */
  .aw-deflist dd a, .aw-p a, .aw-a a, .aw-lead a, .aw-note a, .aw-terms a, .aw-card__b a { padding-block: 6px; }

  /* -- phone screenshots keep a phone's shape, centred ---------------------- */
  .aw-phone-frame { max-width: 240px; margin: 0 auto; }

  /* -- the dock: two plates, and nothing else -----------------------------
     THE BAND CAME OFF (Jordan: "it just looks like a bug"). What the band was for -- a live
     visualizer under the reader's thumb -- is kept by the hero's own cabinet frame, which is
     back, at full bleed, with the note that promises it directly underneath. The dock is now
     the two controls that must not scroll away.

     THE FIRST VIEWPORT STOPS SAYING EVERYTHING TWICE. The dock exists because the hero's own
     coin and ORDER scroll away; while they are still on screen it is duplicating them, and at
     375 px that put two INSERT COINs and three ORDERs in one screenful. With no band left to
     keep on screen, the whole dock simply stands aside there, the way it already does for the
     real ORDER panel -- one rule, two reasons. */
  .dock.is-lean { transform: translateY(calc(100% + 2px)); }

  /* MOTION, which used to be pinned to the band, and its two new homes. It is the page's own
     off switch for every animation, so it may not be twenty screens away: one under INSERT
     COIN, where the motion is started, and one in the footer. Both are the real control --
     same [data-motion] handler, same aria-pressed, kept in step by the existing code. */
  .aw-motion-phone { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; order: 4; font-size: 11px; padding: 0 12px; }
  .aw-footmotion { display: block; margin-top: 16px; }

  /* -- crew, order, footer ------------------------------------------------- */
  .aw-crew { gap: 14px; margin-top: 22px; }
  .aw-crew__fig { gap: 14px; padding: 16px; }
  .aw-order { padding: 28px 18px; gap: 18px; }
  .aw-price { font-size: 30px; }
  .aw-cta { width: 100%; font-size: 12px; padding: 16px 18px; }
  /* ORDER THE JUKEBOX . £99 is 23 glyphs. At the phone's 12 px with 2 px of tracking that is
     322 px of text in a 305-320 px button, and it broke onto two lines (a 72 px plate). 11 px
     with 1 px of tracking is 276 px: one line at 375 and 390, and still on the type floor. */
  .aw-buy .aw-cta { font-size: 11px; letter-spacing: 1px; padding-left: 12px; padding-right: 12px; }
  .aw-footer { margin-top: 72px; padding: 32px 16px calc(16px + env(safe-area-inset-bottom, 0px)); }
  .aw-rows { margin-top: 24px; }
  .aw-tabs { margin-top: 16px; }
}

/* ---------- reduced motion: a resting state, not a blank page ---------- */
@media (prefers-reduced-motion: reduce) {
  .aw-card, .aw-order-pill, .aw-cta, .aw-stepper__frames img, .aw-veil, .jb-reveal, .aw-nav__led,
  .aw-faq summary::before, .aw-table--led tbody th::before { transition: none !important; }
  .aw-narrate__bar i, .aw-denise img + img, .aw-cta.is-flicker { animation: none !important; }
  .aw-narrate li { opacity: 1; color: var(--jb-ink); }   /* the narration is simply already read */
  .aw-h1 .aw-word { opacity: 1 !important; transform: none !important; }
  .aw-steps__track i { height: 100%; }
}
.jb-motion-off .aw-narrate__bar i, .jb-motion-off .aw-denise img + img, .jb-motion-off .aw-cta.is-flicker { animation: none !important; }
.jb-motion-off .aw-narrate li { opacity: 1; color: var(--jb-ink); }
.jb-motion-off .aw-h1 .aw-word { opacity: 1 !important; transform: none !important; animation: none !important; }
/* the !important above already parks the words where they belong, but the
   keyframe kept running underneath it and MOTION-off is measured with
   getAnimations(): a switch that says it stops every animation must. */
.jb-motion-off .aw-veil, .jb-motion-off .aw-nav__led, .jb-motion-off .jb-reveal, .jb-motion-off .aw-card { transition: none !important; }
.jb-motion-off .aw-steps__track i { height: 100%; }
.jb-motion-off .screen::before { animation-play-state: paused !important; }

/* The EQ rack is 680 px of faders. In a 1.15fr column of a 1100 px wrap it does
   not fit, and with nothing scrolling it pushed the whole document 66 px wider
   than the window. The instrument gets the full width, and the pane scrolls
   inside itself as a backstop at every size. */
#sound .aw-row { grid-template-columns: 1fr; }
#sound .aw-row__body { max-width: 820px; }
.eq__pane { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
/* same law one level down: the pane and the preset row both scroll inside
   themselves, so neither may set the width of .eq--wide's column. */
.eq--wide > * { min-width: 0; }
.eq__presets .jb-row { min-width: 0; }

/* ---------- the picker's no-JavaScript fallback ----------
   Deliberately real markup and not a <template>: with modules blocked, all 23
   modes, their taglines and a real frame of each must still be on the page.
   kit/jukebox-picker.js replaces it wholesale when it loads. */
.aw-picker-fallback { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; margin-top: 20px; }
.aw-picker-fallback figure { border: 1px solid rgba(64,200,236,.25); border-radius: var(--jb-r-btn); overflow: hidden; background: var(--jb-bg); }
.aw-picker-fallback img { display: block; width: 100%; height: auto; }
.aw-picker-fallback figcaption { padding: 8px 10px; font-family: var(--jb-font-px); font-size: 13px; color: var(--jb-ink); }
.aw-picker-fallback figcaption span { display: block; color: var(--jb-dim-aa); margin-top: 4px; }

/* ---------- the EQ's no-JavaScript fallback ---------- */
.aw-eq-fallback { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
.aw-eqband { margin-top: 18px; background: transparent; }
.aw-eqband canvas { display: block; width: 100%; height: 100%; }

/* a block inside a section is an anchor target too */
.aw-row[id] { scroll-margin-top: calc(var(--aw-navh, 64px) + 12px); scroll-margin-bottom: calc(var(--aw-dockh, 0px) + 16px); }

/* the MOTION switch is a real control, not a 22 px word */
.hud__motion {
  font-family: var(--jb-font-px); font-size: 13px; text-transform: uppercase;
  background: transparent; border: 1px solid var(--jb-hairline); color: var(--jb-dim-aa);
  min-height: 44px; min-width: 44px; padding: 0 10px; cursor: pointer;
}
.hud__motion:hover { color: var(--jb-ink); }
.hud__motion[aria-pressed="true"] { border-color: var(--jb-gold); color: var(--jb-gold); }

/* a status LED inside a frame, not on the rail it was written for */
.screen > .led { position: absolute; right: 10px; top: 10px; left: auto; width: 8px; height: 8px; z-index: 2; }

/* the drifting invaders cross the SECTION, not 12% of their own 24 px */
@keyframes aw-drift { from { transform: translate3d(-48px, 0, 0); } to { transform: translate3d(calc(100vw + 48px), 0, 0); } }
.jb-drift { left: 0; animation-name: aw-drift; }

/* the ABOUT stamp types itself in when it arrives, one glyph at a time */
#about-stamp .stamp__mark, #about-stamp .stamp__crew { clip-path: inset(0 100% 0 0); }
#about-stamp.is-in .stamp__mark { animation: jb-typein 900ms steps(24, end) both; }
#about-stamp.is-in .stamp__crew { animation: jb-typein 900ms steps(24, end) 260ms both; }
@media (prefers-reduced-motion: reduce) {
  #about-stamp .stamp__mark, #about-stamp .stamp__crew { clip-path: none; animation: none !important; }
}
.jb-motion-off #about-stamp .stamp__mark, .jb-motion-off #about-stamp .stamp__crew { clip-path: none; animation: none !important; }

/* the swipe affordance under a table is only true where the table overflows */
@media (min-width: 1100px) { [data-deflist-note] { display: none; } }

@media (max-width: 767px) {
  /* THE AMBIENCE LAYER STAYS OFF HERE. It used to be the picker's live surface on this cut, moved
     into the snapped card; the card now has a LiveBand of its own (jukebox-screens.js) that draws
     all 23 modes, so #viz-layer is nobody's surface on a phone and simply stays out of the way.
     What the wash was there to do -- a world alive behind the reading -- is done on this cut by
     the backdrop instead, and that is where the work went: a horizon at 0.58 instead of 0.66, an
     invader field instead of none, and a backing store at the device's own scale instead of 1x. */
  #viz-wrap { display: none; }
  /* the six app screenshots become a full-bleed deck of 9:16 top crops */
  .jb-deck__cards { width: auto; margin-top: 22px; }
  /* the EQ band labels are the page's ONE fixed grid of glyphs; they scroll
     inside themselves rather than widening the document */
  .px--quote { max-width: 100%; }
  /* ...and a line that scrolls has to look like one. Measured at 390: the ten band labels are
     463 px inside a 358 px column, so 4K5 and 8K2 were simply gone, cut off square against the
     margin with nothing to say they were still there. This is the same 24 px dissolve the nav
     strip, the EQ pane and every carousel on this cut already use. Where the row fits -- SUB
     BASS MID HIGH AIR is 358 -- the fade lands on empty ground and nothing changes. */
  .px--quote { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); }

  /* ---- the EQ is the one instrument on the page and the phone gets all of it.
     The presets come first, as a thumbed snap row; the ten faders scroll under
     them at a 44 px column pitch, because a ten-band EQ IS a wide instrument. */
  #eq { background: rgba(6, 7, 15, .55); border: 1px solid var(--jb-hairline); border-radius: 12px; padding: 12px; }
  .eq__presets { order: -1; margin-bottom: 12px; }
  /* the kit renders this row with an inline flex-direction for the desktop
     column, so the phone's row direction has to shout */
  .eq__presets .jb-row { flex-direction: row !important; gap: 8px !important; padding-bottom: 4px; }
  .eq__preset { min-height: 52px; line-height: 52px; padding: 0 14px; }
  /* three glyphs in a 44 px column must not wrap; this is a grid of labels, not prose */
  .eq__label, .eq__zone, .eq__read, .eq__gutter span { white-space: nowrap; }
}
/* ============================================================================
   THE SOURCE RAIL (#sources), AND THE DISCLOSURE THAT COMPACTS THE PHONE.

   Two rules govern everything below, and they are the same rule twice:

   1. NOTHING IS HIDDEN FROM ANYBODY. Every sentence, number, [CONFIRM] and
      picture is in the document at every width. On a phone some of it is one
      tap away instead of one scroll away -- a <details> that is `open` in the
      markup, so with JavaScript off (or stripped, or blocked) the phone gets
      exactly the page it got before: everything, laid out, nothing shut.
   2. THE DESKTOP DOES NOT MOVE. Every phone behaviour here lives inside
      `@media (max-width: 767px)`, and the disclosures' own summaries are
      display:none above it -- so at 768 px and up a <details open> renders as
      the plain block of content it wraps, which is what was there before.
   ========================================================================== */

/* ---------- the rail's chips ----------
   Real anchors on both cuts. On desktop they jump to a panel that is already
   laid out; on a phone script turns them into a tablist and shows one panel at
   a time, which is what the cabinet's own rail does when the stick moves. */
.aw-srctabs { margin-top: 26px; }
/* On a desktop every panel is already laid out, so these are jump links, not a
   switch -- and directly above them the lead names the same rail in running
   prose. Two rows of the same grey pixel words read as the page saying it
   twice, so up here they take a chip's outline and stop looking like copy.
   On a phone the kit's own `.tab[aria-selected]` plate takes over and they
   read as what they then are: the cabinet's rail with one item lit. */
.aw-srctabs .tab {
  text-decoration: none; height: 30px; line-height: 28px; padding: 0 11px;
  border: 1px solid var(--jb-hairline); border-radius: var(--jb-r-btn);
  transition: border-color 140ms var(--spring-standard), color 140ms linear;
}
.aw-srctabs .tab:hover { border-color: rgba(64,200,236,.55); }
.aw-srctabs .tab[aria-selected="true"] { color: var(--jb-bg); }

/* ---------- the panels ----------
   On desktop this is the section as it was: a column of blocks in the page's
   own two-column row language, one under the other, all of them on screen. */
.aw-srcpanels { margin-top: 34px; display: flex; flex-direction: column; gap: 72px; }
.aw-srcpanel { scroll-margin-top: calc(var(--aw-navh, 64px) + 12px); scroll-margin-bottom: calc(var(--aw-dockh, 0px) + 16px); }
.aw-srcpanel__head { margin-bottom: 26px; }
.aw-srcpanel__head .aw-h2 { margin-top: 12px; }
/* the retired #second-wave band's sentence, on the first section it introduced */
.aw-wavefold { margin: 0 0 20px; }
.aw-wavefold .px { color: var(--jb-gold); margin-right: 10px; }

/* ---------- the disclosure ----------
   Desktop: no control, and the content simply stands there. */
.aw-more { display: block; }
.aw-more > summary { display: none; }

/* The folds THIS cut adds -- and the nine card folds -- generate NO BOX AT ALL
   on a desktop. `display: contents` drops their children straight back into the
   parent's own box tree, so the desktop keeps the boxes, the margins, the grid
   tracks and the sibling combinators it already had; it is not a reconstruction
   of the layout, it is the same layout. The phone cut below turns them back
   into real <details>. They are `open` in the markup, so a desktop with no
   script -- or a phone with no script -- gets every word, laid out, unfolded. */
.aw-fold, .aw-cardmore { display: contents; }
.aw-cardmore > summary { display: contents; list-style: none; }
.aw-cardmore > summary::-webkit-details-marker { display: none; }
/* a <span> title behaves as the <div> title it replaced */
.aw-card__t { display: block; }

/* the MOTION switch's two phone homes are declared here and shown in the cut */
.aw-motion-phone, .aw-footmotion { display: none; }

@media (max-width: 767px) {

  /* -- the chips become the rail: full bleed, snapped, and it scrolls -------
     Same bleed arithmetic as every other rail on this cut (the column's own
     gutter negated, never 50% - 50vw), and the same 24 px dissolve at the end
     that the nav strip, the EQ pane and the carousels use to say so. */
  .aw-srctabs {
    display: flex; flex-wrap: nowrap; gap: 8px;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
    scroll-snap-type: x proximity; overscroll-behavior-x: contain;
    width: auto;
    margin: 18px calc(-16px - env(safe-area-inset-right, 0px)) 0 calc(-16px - env(safe-area-inset-left, 0px));
    padding: 0 calc(16px + env(safe-area-inset-right, 0px)) 0 calc(16px + env(safe-area-inset-left, 0px));
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent calc(100% - 8px));
    mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent calc(100% - 8px));
  }
  .aw-srctabs::-webkit-scrollbar { display: none; }
  /* the outline goes: on this cut the strip IS the rail, and the kit's own
     selected plate is the cabinet's own way of saying which item is lit */
  .aw-srctabs .tab {
    flex: 0 0 auto; scroll-snap-align: center; min-width: 44px; text-align: center;
    font-size: 15px; height: 44px; line-height: 44px; padding: 0 12px;
    border: 0; border-radius: 0;
  }

  /* -- one panel at a time. `hidden` is set by script; with no script every
        panel is simply on the page, stacked, exactly as it was. ------------- */
  .aw-srcpanels { gap: 0; margin-top: 18px; }
  .aw-srcpanel[hidden] { display: none !important; }
  .aw-srcpanel__head { margin-bottom: 16px; }
  .aw-srcpanel__head .aw-h2 { margin-top: 8px; }
  .aw-wavefold { margin-bottom: 16px; }

  /* -- the disclosure gets its control back -------------------------------
     A 44 px plate that says what is inside it, with the FAQ's own caret. */
  .aw-more > summary {
    display: flex; align-items: center; gap: 10px;
    box-sizing: border-box; min-height: 44px; margin-top: 18px; padding: 10px 14px;
    border: 1px solid var(--jb-hairline); border-radius: var(--jb-r-btn);
    background: rgba(6, 7, 15, .72);
    font-family: var(--jb-font-head); font-size: 11px; line-height: 1.6; letter-spacing: 1px;
    color: var(--jb-neon); cursor: pointer; list-style: none;
  }
  .aw-more > summary::-webkit-details-marker { display: none; }
  .aw-more > summary::before {
    content: '>'; flex: 0 0 auto; color: var(--jb-gold); font-family: var(--jb-font-px);
    transition: transform 120ms var(--spring-snappy);
  }
  .aw-more[open] > summary::before { transform: rotate(90deg); }
  .aw-more > summary:hover { color: var(--jb-ink); }
  .aw-fold { display: block; }

  /* -- the nine cards fold behind their own titles -----------------------
     The title IS the control. No second row of chrome, no "READ MORE": all
     nine headline claims stay on the page at a glance, in the grid they were
     always in, and the sentence under each one is one tap away. Same gold
     caret as every other disclosure on this page, parked on the right where
     it cannot eat a 174 px column. 44 px, keyboard operable, announced. */
  #features .aw-card { position: relative; }
  #features .aw-cardmore { display: block; }
  #features .aw-cardmore > summary {
    display: flex; align-items: center;
    box-sizing: border-box; min-height: 44px; cursor: pointer;
  }
  /* The caret is taken OUT of the flow and parked in the card's own top right
     corner, level with the icon. In the flex row it was eating 21 px of a
     146 px column and BLUETOOTH and VISUALIZER were breaking mid-word --
     BLUETOOT / H. Out of flow the title keeps the full column: the longest
     single word on the grid, VISUALIZER, measures 129 px against 146. */
  #features .aw-cardmore > summary::after {
    content: '>'; position: absolute; top: 16px; right: 14px;
    font-family: var(--jb-font-px); font-size: 11px; line-height: 1; color: var(--jb-gold);
    transition: transform 120ms var(--spring-snappy);
  }
  #features .aw-cardmore[open] > summary::after { transform: rotate(90deg); }
  /* and with the caret out of the way the title never breaks inside a word */
  #features .aw-cardmore > summary .aw-card__t { overflow-wrap: break-word; }
  #features .aw-cardmore > .aw-card__b { margin-top: 8px; }

  /* -- MOTION's two phone homes ------------------------------------------- */
  .aw-motion-phone { display: inline-flex; }
  .aw-footmotion { display: block; }
}

/* The card caret's own rule is written with #features in it, so these two have
   to carry the same weight or the still stays in motion. */
@media (prefers-reduced-motion: reduce) {
  .aw-more > summary::before,
  #features .aw-cardmore > summary::after { transition: none; }
}
.jb-motion-off .aw-more > summary::before,
.jb-motion-off #features .aw-cardmore > summary::after { transition: none; }

/* ============================================================================
   2026-10 WEB CUT (arcadewow.app/jukebox/). Everything below is new for the
   multi-file page: real pictures and clips of the current product, a hero
   with a framed screen beside the headline, karaoke, looks and the app.
   ========================================================================== */
.aw-h1 { text-transform: uppercase; }
.aw-h2 { text-transform: uppercase; }
.aw-hero { min-height: 0; padding: 48px 32px 16px; }
.aw-hero__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 40px; align-items: center; max-width: 1240px; margin: 0 auto; }
.aw-hero__grid .aw-hero__stack { align-items: flex-start; text-align: left; }
.aw-hero__grid .aw-hero__cta { justify-content: flex-start; }
.aw-hero__media { min-width: 0; }
.aw-btn {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 8px 18px;
  border: 1px solid rgba(64,200,236,.55); border-radius: var(--jb-r-btn); color: var(--jb-neon) !important;
  font-family: var(--jb-font-head); font-size: 10px; letter-spacing: 1px; line-height: 1.4; white-space: nowrap;
  background: rgba(6,7,15,.55);
}
.aw-btn:hover { border-color: var(--jb-hot); color: var(--jb-ink) !important; }
.aw-btn--hot { border-color: rgba(232,32,138,.7); color: var(--jb-hot) !important; }

/* a shot: one picture of the real product, with an optional clip laid over it */
.aw-shot { position: relative; margin: 0; }
.aw-shot__frame { position: relative; display: block; border-radius: 10px; overflow: hidden; background: #05060b;
  border: 1px solid rgba(64,200,236,.22); box-shadow: 0 18px 48px rgba(0,0,0,.55); aspect-ratio: 16 / 9; }
.aw-shot__frame img, .aw-shot__frame video { display: block; width: 100%; height: 100%; object-fit: cover; }
.aw-shot__frame video { position: absolute; inset: 0; opacity: 0; transition: opacity 240ms linear; }
.aw-shot__frame video.is-playing { opacity: 1; }
.aw-shot--phone .aw-shot__frame { aspect-ratio: auto; max-width: 300px; border-radius: 28px; border: 6px solid #1a1c24; box-shadow: 0 0 0 2px #33363f, 0 20px 50px rgba(0,0,0,.6); }
.aw-shot--phone { display: flex; flex-direction: column; align-items: center; }
.aw-shot figcaption { margin-top: 10px; }
.jb-motion-off .aw-shot__frame video { display: none; }
@media (prefers-reduced-motion: reduce) { .aw-shot__frame video { display: none; } }

.aw-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 22px; margin-top: 30px; }
.aw-gallery--3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.aw-sub { margin-top: 64px; }
.aw-sub:first-of-type { margin-top: 40px; }
.aw-ticks { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.aw-ticks li { position: relative; padding-left: 22px; font-size: 16px; line-height: 1.6; color: var(--jb-body); }
.aw-ticks li::before { content: '>'; position: absolute; left: 0; color: var(--jb-gold); font-family: var(--jb-font-px); }
.aw-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.aw-chips .px { border: 1px solid var(--jb-hairline); padding: 4px 8px; border-radius: 4px; color: var(--jb-ink); background: rgba(6,7,15,.6); }

/* the radio card: typeset, not a screenshot (the current radio screens carry real
   station names, so the genre list is drawn here from the shipped station list) */
.aw-radio { border: 1px solid rgba(64,200,236,.3); border-radius: 10px; background: rgba(5,6,11,.86); padding: 22px 24px; font-family: var(--jb-font-px); text-transform: uppercase; }
.aw-radio__head { display: flex; justify-content: space-between; gap: 12px; color: var(--jb-gold); font-size: 15px; margin-bottom: 14px; }
.aw-radio__list { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 32px; }
.aw-radio__list li { display: flex; justify-content: space-between; gap: 10px; font-size: 16px; line-height: 1.5; color: var(--jb-ink); break-inside: avoid; }
.aw-radio__list li span { color: var(--jb-dim-aa); }
.aw-radio__list li.is-on { color: var(--jb-neon); }

/* the machines block: our own cabinet sprite beside the call to action */
.aw-machines { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 36px; align-items: center; }
.aw-machines img { width: 174px; height: auto; filter: drop-shadow(0 0 24px rgba(232,32,138,.35)); }
.aw-machines .aw-hero__cta { justify-content: flex-start; margin-top: 22px; }

.aw-applist { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-top: 26px; }
.aw-soon { display: inline-block; border: 1px solid rgba(242,227,16,.5); color: var(--jb-gold); font-family: var(--jb-font-head); font-size: 10px; letter-spacing: 1.5px; padding: 8px 12px; line-height: 1.6; }

@media (max-width: 1099px) {
  .aw-hero__grid { grid-template-columns: 1fr; gap: 26px; }
}
@media (max-width: 767px) {
  .aw-hero { padding: 20px 16px 8px; }
  .aw-hero__grid .aw-hero__stack { align-items: stretch; }
  .aw-hero__media { margin: 0 -16px; }
  .aw-hero__media .aw-shot__frame { border-radius: 0; border-left: 0; border-right: 0; }
  .aw-gallery, .aw-gallery--3 { grid-template-columns: 1fr; gap: 18px; }
  .aw-radio__list { columns: 1; }
  .aw-radio { padding: 16px; }
  .aw-machines { grid-template-columns: 1fr; justify-items: center; text-align: left; }
  .aw-machines img { width: 130px; }
  .aw-btn { width: 100%; min-height: 52px; font-size: 12px; }
  .aw-sub { margin-top: 44px; }
  .dock__row .aw-order-pill { font-size: 11px; }
}
.aw-centre { text-align: center; }
.aw-lead--c { max-width: 760px; margin-left: auto; margin-right: auto; }
.aw-mt { margin-top: 22px; }
.aw-picker { margin-top: 36px; }
#visualisers .aw-shot { margin-top: 30px; }
#looks > .aw-wrap > .aw-shot { margin-top: 30px; }
.aw-footer__mark .a { color: var(--jb-neon); } .aw-footer__mark .w { color: var(--jb-hot); }
.aw-btn, .aw-soon, .aw-radio, .aw-shot__frame { box-sizing: border-box; }
#app .aw-row__media.aw-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 0; }
#app .aw-shot--phone .aw-shot__frame { max-width: 100%; border-width: 4px; border-radius: 22px; }
@media (max-width: 767px) { #app .aw-row__media.aw-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } }
.aw-shot__frame--1610 { aspect-ratio: 16 / 10; }
.aw-shot__frame--1610 video { opacity: 1; position: static; }
.jb-motion-off .aw-shot__frame--1610 video { display: block; }
@media (prefers-reduced-motion: reduce) { .aw-shot__frame--1610 video { display: block; } }

/* ---- review fixes 2026-10-06 ---- */
.aw-short { display: none; }
@media (max-width: 767px) {
  /* one full SEE THE MACHINES on the phone's first screen: the header keeps a compact plate */
  .aw-nav__order .aw-long { display: none; }
  .aw-nav__order .aw-short { display: inline; }
  .aw-nav__order { padding: 8px 12px; }
  .aw-h1 { font-size: 18px; line-height: 1.4; letter-spacing: 1px; }
}
/* PHONE ORDER: under 900 px the product comes straight after the headline, before the buttons */
@media (max-width: 899px) {
  .aw-hero__grid { display: flex; flex-direction: column; gap: 14px; }
  .aw-hero__grid .aw-hero__stack { display: contents; }
  .aw-hero__grid .aw-badge { order: 1; align-self: stretch; }
  .aw-hero__grid .aw-h1 { order: 2; }
  .aw-hero__grid .aw-hero__media { order: 3; }
  .aw-hero__grid .aw-hero__cta { order: 4; }
  .aw-hero__grid .aw-coin-status { order: 5; }
  .aw-hero__grid .aw-motion-phone { order: 6; }
  .aw-hero__grid .aw-strap { order: 7; text-align: left; }
}
@media (max-width: 767px) {
  #eq { max-width: 100%; box-sizing: border-box; min-width: 0; }
  .eq__presets { max-width: 100%; min-width: 0; }
  .eq__presets .jb-row { overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
}
/* the stack is display:contents under 900 px, so its soft plate would hang off the hero itself
   (16 px past the right edge); the hero copy carries its own text shadow there instead */
@media (max-width: 899px) { .aw-hero__grid .aw-hero__stack::before { display: none; } }
@media (max-width: 767px) { .aw-hero__media figcaption { padding: 0 16px; font-size: 13px; } }
/* the WOWLITZER is an option, shown once and small */
.aw-wowopt .aw-shot { max-width: 320px; }
@media (max-width: 767px) { .aw-wowopt .aw-shot { max-width: 80%; margin: 0 auto; } }

/* ---------- arcadewow.app family (Jordan 10-07): the hub's own header + footer pieces ----------
   The AW mark is the same pill as the hub's and goes HOME (/); SHOP is the hub's gold arcade button;
   a neon hairline closes the header and opens the footer so the top and bottom of the page rhyme
   with the hub's grid horizon; the footer ends on PICK YOUR CAB, the way back to arcadewow.app and the
   80s Arcade Classics sign, like the hub. */
.aw-nav { border-bottom: 0; }
.aw-nav::before, .aw-footer::before {
  content: ''; position: absolute; left: 0; right: 0; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(232,32,138,.85) 18%, #f2e310 50%, rgba(64,200,236,.85) 82%, transparent);
  box-shadow: 0 0 12px rgba(232,32,138,.55);
}
.aw-nav::before { bottom: -1px; }
.aw-footer { position: relative; border-top: 0; }
.aw-footer::before { top: 0; }
.aw-mark { padding: 7px 14px; border-radius: 999px; background: rgba(5,6,11,.55); border: 1px solid rgba(231,240,255,.16); min-height: 38px; }
.aw-mark:hover { border-color: rgba(64,200,236,.55); }
.aw-shop {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--jb-font-head); font-size: 11px; letter-spacing: .04em; line-height: 1; white-space: nowrap;
  color: #1a0726 !important; text-decoration: none; padding: 11px 14px 10px; border-radius: 10px; overflow: hidden;
  background: linear-gradient(180deg, #fff6a8 0%, #f2e310 36%, #f9a21a 72%, #ff6a3d 100%);
  border: 3px solid #2a0b3a;
  box-shadow: 0 4px 0 #b3127a, 0 4px 0 3px #2a0b3a, 0 10px 24px -10px rgba(232,32,138,.8);
  transition: transform .08s ease, box-shadow .08s ease; -webkit-tap-highlight-color: transparent;
}
.aw-shop::after { content: ''; position: absolute; inset: -20% auto -20% -40%; width: 28%; background: linear-gradient(90deg, transparent, rgba(255,255,255,.85), transparent); transform: skewX(-20deg); animation: aw-glint 3.4s ease-in-out infinite; }
.aw-shop .go-arrow { display: inline-block; animation: aw-nudge 1s steps(2) infinite; }
.aw-shop:hover { color: #1a0726 !important; }
.aw-shop:active { transform: translateY(3px); box-shadow: 0 1px 0 #b3127a, 0 1px 0 3px #2a0b3a, 0 6px 16px -10px rgba(232,32,138,.7); }
.aw-shop:focus-visible, .aw-ghost:focus-visible { outline: 3px solid var(--jb-neon); outline-offset: 5px; }
@keyframes aw-glint { 0%, 55% { left: -40%; } 85%, 100% { left: 130%; } }
@keyframes aw-nudge { 50% { transform: translateX(4px); } }
.aw-nav__order.aw-shop { flex: 0 0 auto; min-height: 0; }
.aw-foothome { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin: 22px 0 6px; }
.aw-shop--big { font-size: 14px; padding: 16px 22px 14px; border-radius: 12px; box-shadow: 0 6px 0 #b3127a, 0 6px 0 3px #2a0b3a, 0 20px 40px -14px rgba(232,32,138,.75); }
.aw-ghost { display: inline-flex; align-items: center; justify-content: center; min-height: 52px; padding: 0 20px; border-radius: 12px; font-family: var(--jb-font-head); font-size: 11px; letter-spacing: .06em; color: var(--jb-neon) !important; border: 2px solid rgba(64,200,236,.5); background: rgba(64,200,236,.06); }
.aw-ghost:hover { background: rgba(64,200,236,.14); }
.aw-classics { display: block !important; width: 150px; margin: 18px auto 0; opacity: .82; transition: opacity .2s ease; min-height: 0 !important; }
.aw-classics:hover { opacity: 1; }
.aw-classics img { display: block; width: 100%; height: auto; }
@media (max-width: 760px) {
  .aw-mark { padding: 6px 12px; margin-left: calc(10px + env(safe-area-inset-left, 0px)); }
  .aw-nav__order.aw-shop { margin: 6px calc(12px + env(safe-area-inset-right, 0px)) 6px 0; padding: 9px 12px 8px; font-size: 10px; }
  .aw-foothome { flex-direction: column; align-items: stretch; max-width: 22rem; margin-left: auto; margin-right: auto; }
}
@media (prefers-reduced-motion: reduce) { .aw-shop::after, .aw-shop .go-arrow { animation: none; } }
.jb-motion-off .aw-shop::after, .jb-motion-off .aw-shop .go-arrow { animation: none !important; }

/* the hero film is transparent (Jordan 10-07): no frame, the cab and the phone stand on the page */
.aw-shot--hero .aw-shot__frame { background: none; border: 0; box-shadow: none; border-radius: 0; overflow: visible; }
.aw-shot--hero .aw-shot__frame video { object-fit: contain; }
/* every screen you own (10-07): wide device shots stack in one column; the Duo clip is transparent like the hero */
#app .aw-row__media.aw-gallery.aw-gallery--wide { grid-template-columns: 1fr; gap: 18px; }
@media (max-width: 767px) { #app .aw-row__media.aw-gallery.aw-gallery--wide { grid-template-columns: 1fr; } }
.aw-shot--duo .aw-shot__frame--duo { aspect-ratio: 720 / 732; max-width: 420px; margin: 0 auto; background: none; border: 0; box-shadow: none; border-radius: 0; overflow: visible; }
.aw-shot--duo .aw-shot__frame--duo video { object-fit: contain; }
.aw-shot--duo figcaption { text-align: center; }
/* the Apple Watch tile (10-07): the phone frame, rounded into a watch face, a little smaller */
.aw-watch { display: flex; align-items: center; justify-content: center; }
.aw-watch .aw-shot--phone .aw-shot__frame { max-width: 210px; border-radius: 44px; border-width: 8px; }
