/* screens/select.css · the Setlist (SPEC 3.5 stall content, 3.6 Select).
   One system for the whole screen:
     spacing  --s1 .25 · --s2 .5 · --s3 .75 · --s4 1 · --s5 1.5rem (4 px grid at a 16 px rem)
     radius   --r-s chips, caps, jacket · --r-m cards, tickets · --r-l Play
     stroke   --ow-s chips, caps, medallions · --ow cards, bars, jacket · --ow-l the panel (components.css)
     depth    --drop-s everything at rest · a heat-coloured lift for the chosen card · the cobalt plate only on the panel
   Layout inside the stall body (standard, container >= 50rem):
     [ setlist  ] [ jacket + record | title bar                        ]
     [ tickets  ] [                 | artist · tempo · length · best   ]
     [          ] [ DIFFICULTY ←→ - - - - - - - - - - - - - - No Fail ]
     [          ] [ easy · medium · hard · expert (medallion cards)    ]
     [          ] [ Tap · Strum (key caps)                 |   PLAY    ]
   Compact (< 50rem): a strip of mini tickets on top, then head, heat cards, controls.
   Rules kept: transform / opacity only in motion; no filter or backdrop-filter; text >= .875rem; ids and roles
   untouched; nothing reaches left of the stall frame (so nothing reaches Aisu). */

/* ============================================================================ section tokens */
#select {
  --heat: var(--dif-medium); --tk-r: max(2px, .16rem);
  --head-h: 6.9rem; --bar-h: 3.1rem; --chip-h: 3.1rem; --card-h: 4.85rem; --ctl-h: 4.8rem; --dif-label-h: 1.45rem;
}
#select[data-heat="easy"]   { --heat: var(--dif-easy); }
#select[data-heat="hard"]   { --heat: var(--dif-hard); }
#select[data-heat="expert"] { --heat: var(--dif-expert); }

/* ============================================================================ the sign: the Setlist sticker + live count */
/* the logo hangs over the beam like a shop sign; the live count is pinned under it, on the valance */
#select .stall__sign {
  --logo-w: 13.6rem;
  bottom: calc(100vh - var(--stall-body-t) - .75rem);
  flex-direction: column; justify-content: flex-end; align-items: center; gap: 0;
  width: var(--logo-w); height: calc(var(--logo-w) / 2.4645 + 1.35rem); padding: 0;
  border: 0; border-radius: 0; box-shadow: none; rotate: -2.5deg; transform-origin: 30% 70%;
  background: url(../../img/brand/setlist-logo@900.webp) 50% 0 / 100% auto no-repeat;
}
#select .stall__sign .stall-title {                   /* the logo says it; the heading stays for screen readers */
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
#select .setlist-count {
  gap: .45rem; min-height: 1.75rem; padding: 0 .8rem 0 .62rem; rotate: 3deg; translate: .55rem 0;
  border: var(--ow-s) solid var(--ink); background: var(--night-2); color: var(--ivory); letter-spacing: .08em;
  box-shadow: 0 0 0 .2rem var(--paper), 0 0 0 calc(.2rem + var(--ow-s)) var(--ink), .15rem .3rem 0 calc(.2rem + var(--ow-s)) rgb(44 15 21 / .45);
}
#select .setlist-count::before {                      /* the "live" lamp: a red bulb with a hot core */
  content: ''; flex: none; width: .62rem; height: .62rem; border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #FFE3D0 0 18%, var(--red-hi) 40%, var(--red-deep) 100%);
  box-shadow: 0 0 0 .1rem var(--ink), 0 0 .45rem .1rem rgb(255 70 80 / .75);
}

/* ============================================================================ body grid (standard) */
#select .stall__body {
  container-name: stall; scrollbar-width: thin; scrollbar-color: var(--ink-2) transparent;
  padding-top: calc(1.55rem + var(--ow-l)); scrollbar-gutter: auto;
}
.select-body {
  --list-w: clamp(13.25rem, 100cqi - 40.5rem, 16rem); /* 13.25rem at 16:10, roomier at 16:9 */
  grid-template-columns: var(--list-w) minmax(0, 1fr);
  grid-template-rows: var(--head-h) calc(var(--dif-label-h) + var(--sp-2) + var(--card-h)) var(--ctl-h);
  column-gap: 1.15rem; row-gap: 1.1rem;
  overflow: clip; overflow-clip-margin: 1.2rem;      /* drops, tips and lifts paint out, never scroll the stall */
  min-height: 100%; align-content: center;             /* tall narrow windows: the block sits in the middle */
}

/* ============================================================================ setlist: gig tickets */
.select-body > #song-list {
  grid-row: 1 / span 3; display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-2); padding: 0;
}

.song-thumb.ticket {
  --n: .42rem;                                         /* side notch radius */
  display: block; flex: 0 1 3.7rem; width: 100%; height: auto; min-height: 2.9rem; padding: 0; margin: 0;
  border: 0; border-radius: var(--r-m); background: none; box-shadow: none; overflow: visible; rotate: 0deg;
  color: var(--ink); text-align: left; font: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--t-base) var(--spring-pop);
}
.song-thumb.ticket::after { translate: 0 .2rem; }    /* the ink drop = --drop-s */
.song-thumb .ticket__in {
  height: calc(100% - 2 * var(--ow)); display: grid; grid-template-columns: 2.45rem minmax(0, 1fr);
  align-items: center; gap: 0; padding: 0;
}
.song-thumb .ticket__stub {                           /* the number on the left stub, a dashed perforation after it */
  width: auto; height: 100%; margin: 0; padding: 0 0 0 .15rem; border: 0;
  border-right: .14rem dashed rgb(44 15 21 / .35);
  background: var(--ivory-2); color: var(--red);
  font: 700 1.2rem/1 var(--font-num); font-stretch: 85%; letter-spacing: .02em; text-transform: none;
  -webkit-text-stroke: 0;
}
.song-thumb .ticket__body { display: grid; gap: .15rem; min-width: 0; padding: 0 .55rem 0 .6rem; }
.song-thumb .ticket__row { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.song-thumb .ticket__title {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 700 1.1rem/1.1 var(--font-display); font-stretch: 80%; letter-spacing: .01em;
}
.song-thumb .ticket__meta {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 900 var(--fs-small)/1.15 var(--font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2);
}
/* "now playing" bars: only on the selected ticket (select-view mirrors the preview levels into them) */
.song-thumb .ticket__now { display: none; flex: none; align-items: flex-end; gap: .13rem; height: .95rem; margin-left: auto; }
.song-thumb .ticket__now i {
  width: .24rem; height: 100%; border-radius: .12rem; background: var(--red);
  box-shadow: 0 0 0 .07rem var(--ink); transform-origin: 50% 100%;
}
.song-thumb .ticket__now i:nth-child(1) { transform: scaleY(.55); }
.song-thumb .ticket__now i:nth-child(2) { transform: scaleY(1); background: var(--f3); }
.song-thumb .ticket__now i:nth-child(3) { transform: scaleY(.7); }
.song-thumb .ticket__now i:nth-child(4) { transform: scaleY(.38); background: var(--f3); }

@media (hover: hover) {
  .song-thumb.ticket:not(.locked, .sel):hover { transform: translateY(-.14rem); }
  .song-thumb.ticket:not(.locked, .sel):hover .ticket__stub { background: var(--f1); }
}
.song-thumb.ticket:not(.locked):is(:active, .is-pressed) { transform: translateY(.14rem) scale(.99); transition-duration: var(--t-instant); }

/* selected: warm paper, red seigaiha stub, an orange plate under it and a soft heat glow */
.song-thumb.ticket.sel { transform: translateX(.2rem); z-index: 1; box-shadow: 0 .3rem 1.4rem rgb(255 120 30 / .32); }
.song-thumb.ticket.sel::after { background: var(--f3); translate: .28rem .3rem; }
.song-thumb.ticket.sel::before { background: var(--ink); }
.song-thumb.sel .ticket__in {
  background:
    radial-gradient(120% 140% at 100% 0, rgb(255 210 58 / .32), transparent 55%),
    url(../../img/svg/paper-grain.webp) 0 0 / 16rem, linear-gradient(180deg, var(--paper), #FBE7C4);
}
.song-thumb.sel .ticket__stub {
  background: #D11A2A url(../../img/svg/pat-seigaiha-red.svg) 0 0 / 1.8rem .9rem; color: var(--ivory);
  border-right-color: var(--ink);
  -webkit-text-stroke: max(1.5px, .13em) var(--ink); paint-order: stroke fill;
}
.song-thumb.sel .ticket__title { color: var(--ink); }
.song-thumb.sel .ticket__meta { color: var(--red-deep); }
.song-thumb.sel .ticket__now { display: flex; }
.song-thumb.sel .ticket__in::after {                  /* one gleam across the selected ticket when the setlist shows */
  content: ''; position: absolute; inset: -20% 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 38%, rgb(255 255 255 / .8) 50%, transparent 62%);
  transform: translateX(-120%) skewX(-20deg);
  --anim: ff-shine 1.3s var(--ease-inout) 380ms 1 both; animation: var(--anim);
}

/* locked: an unlit ticket printed flat on the paper (soft rim, no drop), the number faded, "Coming soon" in quiet caps
   and a charcoal bichito asleep at the right end: not lit yet */
.song-thumb.ticket.locked { cursor: default; }
.song-thumb.locked::before { background: rgb(44 15 21 / .26); }
.song-thumb.locked::after { background: transparent; }
.song-thumb.locked .ticket__in {
  background: url(../../img/svg/paper-grain.webp) 0 0 / 16rem, linear-gradient(180deg, #EFE6D3, #E7DBC2);
  color: var(--ink-2);
}
.song-thumb.locked .ticket__stub {                 /* the number gives way to the charcoal bichito, peeking up */
  position: relative; overflow: hidden; color: transparent; border-right-color: rgb(44 15 21 / .18);
  background: url(../../img/brand/bichito-carbon@384.webp) 50% calc(100% + .55rem) / 2.7rem auto no-repeat, rgb(44 15 21 / .05);
}
.song-thumb.locked:nth-child(even) .ticket__stub { background-position: 40% calc(100% + .62rem), 0 0; }
.song-thumb.locked .ticket__title { color: rgb(44 15 21 / .72); font-size: 1rem; font-stretch: 75%; }
.song-thumb.locked .ticket__meta { color: rgb(91 58 64 / .7); letter-spacing: .1em; }
.song-thumb .ticket__lock { display: none; }
.song-thumb .ticket__tip { position: absolute; inset: 0; z-index: 2; border-radius: var(--r-m); }
.song-thumb.locked:hover { z-index: 5; }               /* its tooltip opens over the song head */
.song-thumb .ticket__tip::after { white-space: nowrap; }

/* ============================================================================ song head: jacket + record, title bar, chips */
.song-head { grid-template-columns: var(--head-h) minmax(0, 1fr); column-gap: calc(var(--sp-5) + 1.35rem); align-items: stretch; }

/* the jacket: straight, ink rim, a hard drop; the record behind it peeks out on the right and turns while it plays */
.cover-wrap {
  isolation: isolate; width: var(--head-h); height: var(--head-h); rotate: 0deg;
  border: var(--ow) solid var(--ink); border-radius: var(--r-s);
  background: var(--night); box-shadow: var(--drop-s);
}
.cover-wrap .vinyl, .cover-wrap::after {
  position: absolute; z-index: -1; top: 50%; right: -1.85rem; width: calc(var(--head-h) - .7rem); aspect-ratio: 1;
  translate: 0 -50%; border-radius: 50%; pointer-events: none;
}
.cover-wrap .vinyl {
  display: block; background: url(../../img/stall/vinyl.svg) 50% 50% / contain no-repeat;
  box-shadow: .2rem .25rem 0 rgb(44 15 21 / .55);
  --loop: ffs-spin 5.4s linear infinite; animation: var(--loop);
}
.cover-wrap::after { content: ''; background: url(../../img/stall/vinyl-shine.svg) 50% 50% / contain no-repeat; }
@keyframes ffs-spin { to { transform: rotate(1turn); } }
#sd-cover { position: relative; border-radius: calc(var(--r-s) - var(--ow)); object-position: 0 50%; background: var(--night-3); }
.cover-wrap.is-jacket #sd-cover { object-position: 50% 50%; }

/* preview meter: 5 bars on a night pill over the jacket's bottom-left (ui.eq writes scaleY) */
.eq {
  z-index: 1; left: .3rem; bottom: .3rem; height: 1.45rem; gap: .14rem; padding: .22rem .3rem;
  background: rgb(13 11 22 / .82); border-radius: var(--r-xs); box-shadow: 0 0 0 .1rem var(--ink);
}
.eq i { width: .24rem; border-radius: .12rem; background: linear-gradient(0deg, var(--red) 0%, var(--f3) 55%, var(--f2) 100%); box-shadow: none; }
.eq i:nth-child(1) { transform: scaleY(.55); }
.eq i:nth-child(2) { transform: scaleY(.9); }
.eq i:nth-child(3) { transform: scaleY(.42); }
.eq i:nth-child(4) { transform: scaleY(.75); }
.eq i:nth-child(5) { transform: scaleY(.3); }

/* info: the night title bar (a heat stripe on its left edge), then the stat chips and the best card on one baseline */
.song-info {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: var(--bar-h) var(--chip-h);
  column-gap: var(--sp-2); row-gap: 0; align-content: space-between;
}
.song-info::before {
  content: ''; grid-row: 1; grid-column: 1 / -1; z-index: 0;
  border: var(--ow) solid var(--ink); border-radius: var(--r-s);
  background:
    linear-gradient(90deg, var(--heat) 0 .4rem, var(--ink) .4rem calc(.4rem + var(--ow-s)), transparent 0),
    linear-gradient(180deg, rgb(255 255 255 / .08), transparent 45%, rgb(0 0 0 / .2)),
    #14102A url(../../img/svg/pat-seigaiha-night.svg) 0 0 / 2.2rem 1.1rem;
  box-shadow: var(--drop-s);
}
.song-info::after { content: none; }
#sd-title {
  grid-row: 1; grid-column: 1 / -1; z-index: 1; align-self: center; justify-self: start; max-width: 100%;
  margin: 0; padding-left: 1rem; padding-right: var(--sp-3); overflow: hidden; text-overflow: clip;
  font-size: 1.95rem; line-height: 1.2;
  --tk-fill: var(--f2); --tk-shadow: var(--red); --tk-drop: .08em; --tk-halo: var(--ivory);
  --tk-gradient: linear-gradient(180deg, #FFF8C4 8%, #FFD23A 40%, #FF8A1C 72%, #FF5A1F 96%);
}
#sd-title::before { text-shadow: .05em .08em 0 var(--red); }

/* stat chips: paper tags, ink rim, the small drop */
.stats { grid-row: 2; grid-column: 1; display: flex; flex-wrap: nowrap; gap: var(--sp-2); margin: 0; min-width: 0; }
.stats .stat {
  display: grid; align-content: center; gap: .14rem; min-width: 0; height: var(--chip-h); padding: 0 .7rem;
  border: var(--ow-s) solid var(--ink); border-radius: var(--r-s); box-shadow: var(--drop-s);
  background: url(../../img/svg/paper-grain.webp) 0 0 / 16rem, linear-gradient(180deg, var(--paper), var(--ivory));
}
.stats dt { font: 900 var(--fs-small)/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.stats dd {
  margin: 0; max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 700 1.25rem/1 var(--font-display); font-stretch: 85%; color: var(--ink);
}

/* the best card (#sd-best): gold foil when there is a record, a dashed slot with a line-drawn bichito when empty, ash
   with a meh face offline */
#sd-best {
  container: best / inline-size;
  grid-row: 2; grid-column: 2; position: relative; display: grid; align-content: center; gap: .12rem;
  min-width: 0; height: var(--chip-h); min-height: 0; margin: 0; padding: 0 .8rem;
  border-radius: var(--r-s); font: 800 var(--fs-small)/1.2 var(--font-body); color: var(--ink-2);
}
#sd-best.is-loading { border: var(--ow-s) dashed rgb(91 58 64 / .3); background: rgb(234 223 201 / .35); }
#sd-best.is-empty, #sd-best.is-offline {
  grid-template-columns: auto minmax(0, 1fr); column-gap: .65rem; align-items: center; padding-left: .6rem;
  border: var(--ow-s) dashed rgb(91 58 64 / .45); background: rgb(234 223 201 / .45);
}
#sd-best.is-empty::before {                            /* a bichito stamp, waiting for your first score */
  content: ''; width: 1.9rem; height: 2rem; background: var(--ink-2); opacity: .45;
  -webkit-mask: url(../../img/brand/bichito-silueta-mira@384.webp) 50% 50% / contain no-repeat;
          mask: url(../../img/brand/bichito-silueta-mira@384.webp) 50% 50% / contain no-repeat;
}
#sd-best.is-offline {
  grid-template-columns: minmax(0, 1fr); padding-left: 1.35rem;
  border-style: solid; border-color: rgb(91 58 64 / .4); background: rgb(205 187 156 / .3);
}
#sd-best.is-offline::before {                           /* the meh face, stuck over the card's corner like a sticker */
  content: ''; position: absolute; left: -.5rem; top: -.6rem; width: 1.75rem; height: 1.75rem; border-radius: 50%; rotate: -10deg;
  background: url(../../img/mascot/face-meh.svg) 50% 60% / 74% auto no-repeat, var(--ember);
  box-shadow: 0 0 0 var(--ow-s) var(--ink), inset 0 .22rem 0 rgb(255 255 255 / .25), .1rem .14rem 0 var(--ink);
}
#sd-best .best__msg { min-width: 0; font-weight: 800; line-height: 1.2; text-wrap: balance; }
#sd-best.has-best {
  overflow: hidden; border: var(--ow-s) solid var(--ink); color: var(--ink);
  background: radial-gradient(90% 120% at 0 0, rgb(255 255 255 / .45), transparent 55%), var(--grad-gold);
  box-shadow: inset 0 .14rem 0 rgb(255 255 255 / .6), inset 0 -.16rem 0 rgb(176 122 18 / .35), var(--drop-s);
}
#sd-best.has-best::after {                             /* one shine sweep when the record lands (not a loop) */
  --anim: ff-shine 1.5s var(--ease-inout) 250ms 1 both; animation: var(--anim);
}
#sd-best .best__head { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
#sd-best .best__k { font: 900 var(--fs-small)/1 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); }
#sd-best .rank {
  margin-left: auto; padding: .12rem .5rem .14rem; border-radius: var(--r-pill); background: var(--ink); color: var(--f2);
  font: 900 var(--fs-small)/1 var(--font-body); letter-spacing: .02em; white-space: nowrap;
}
#sd-best .best__line { display: flex; align-items: baseline; gap: .55rem; min-width: 0; white-space: nowrap; }
#sd-best .best__score { font: 700 1.3rem/1 var(--font-num); font-stretch: 85%; color: var(--ink); letter-spacing: .01em; }
#sd-best .st { font: 700 1rem/1 var(--font-display); letter-spacing: 0; color: var(--red); -webkit-text-stroke: max(1px, .06em) var(--ink); paint-order: stroke fill; }
#sd-best .st.gold { color: var(--paper); }
#sd-best .best__acc { font: 900 1rem/1 var(--font-body); color: var(--ink-2); }

/* ============================================================================ difficulty: label row (+ No Fail) and heat cards */
.dif-field { grid-template-rows: var(--dif-label-h) var(--card-h); row-gap: var(--sp-2); }
.dif-head { display: flex; align-items: center; gap: var(--sp-4); min-width: 0; }
.dif-field .label {
  flex: 1 1 auto; min-width: 0; height: var(--dif-label-h); margin: 0; gap: .45rem; color: var(--ink); font: 900 var(--fs-small)/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase;
}
.dif-field .label::after {                            /* the dashed rule that runs to No Fail */
  content: ''; flex: 1; min-width: 1rem; margin-left: .35rem; height: 0; border-top: .14rem dashed rgb(44 15 21 / .25);
}
.dif-field .hint-keys { display: inline-flex; gap: .15rem; }
.dif-field .hint-keys kbd { height: 1.3rem; min-width: 1.4rem; padding: 0 .3rem; margin: 0; box-shadow: 0 .14rem 0 var(--ink); }

/* No Fail: a compact switch at the end of the rule */
.dif-head > .switch {
  flex: none; gap: var(--sp-2); min-height: 0; color: var(--ink);
  font: 900 var(--fs-small)/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
}
.dif-head > .switch .track { width: 2.4rem; height: 1.35rem; }
.dif-head > .switch .track::after { width: 1rem; height: 1rem; }
.dif-head > .switch input { width: 2.4rem; height: 1.35rem; }
.dif-head > .switch input:checked + .track::after { transform: translateX(1.05rem); }
.dif-head > .switch:has(input:checked) > span:not(.track) { color: var(--red-deep); }
.dif-head > .switch .switch__key { height: 1.3rem; min-width: 1.4rem; padding: 0 .3rem; margin: 0 0 0 -.1rem; box-shadow: 0 .14rem 0 var(--ink); letter-spacing: 0; }
.dif-head > .switch:has(input:disabled) { opacity: .55; }

#difficulty { --med: 2.45rem; gap: .5rem; padding-top: 0; }
#difficulty [data-dif="easy"]   { --dif-icon: url(../../img/svg/dif-easy.svg); }
#difficulty [data-dif="medium"] { --dif-icon: url(../../img/svg/dif-medium.svg); }
#difficulty [data-dif="hard"]   { --dif-icon: url(../../img/svg/dif-hard.svg); }
#difficulty [data-dif="expert"] { --dif-icon: url(../../img/svg/dif-expert.svg); }
#difficulty [role="radio"] {
  height: var(--card-h); grid-template-columns: var(--med) minmax(0, 1fr); row-gap: .08rem; column-gap: .45rem;
  padding: .4rem .5rem .45rem .45rem;
  box-shadow: inset 0 .28rem 0 color-mix(in oklab, var(--dif-color) 80%, transparent), var(--drop-s);
}
#difficulty [role="radio"]::before {                  /* the medallion: same size and ring for every heat */
  width: var(--med); height: var(--med); border-radius: 50%;
  background: var(--dif-icon) 50% 62% / 80% auto no-repeat,
              radial-gradient(circle at 50% 32%, #FFFDF6 0 30%, color-mix(in oklab, var(--dif-color) 22%, var(--paper)) 100%);
  box-shadow: 0 0 0 var(--ow-s) var(--ink), inset 0 -.2rem 0 color-mix(in oklab, var(--dif-color) 35%, transparent);
}
#difficulty [role="radio"] { row-gap: .14rem; }
#difficulty [role="radio"] b { font-size: 1.28rem; line-height: 1.05; }
#difficulty [role="radio"] small { font-size: .94rem; line-height: 1.15; }
#difficulty .pips { height: 1.05rem; }
#difficulty [role="radio"][aria-checked="true"] {
  transform: translateY(-.25rem);
  background:
    radial-gradient(rgb(255 255 255 / .18) 22%, transparent 25%) 0 0 / .5rem .5rem,
    radial-gradient(120% 90% at 30% 0, rgb(255 255 255 / .3), transparent 60%),
    linear-gradient(180deg, color-mix(in oklab, var(--dif-color) 66%, #fff), var(--dif-color) 52%, color-mix(in oklab, var(--dif-color) 70%, #000));
  box-shadow: inset 0 .16rem 0 rgb(255 255 255 / .35), inset 0 -.22rem 0 rgb(0 0 0 / .14), 0 .45rem 0 var(--ink),
              0 .7rem 1.5rem color-mix(in srgb, var(--dif-color) 50%, transparent);
}
#difficulty [role="radio"][aria-checked="true"]::before {
  background: var(--dif-icon) 50% 62% / 80% auto no-repeat, radial-gradient(circle at 50% 32%, #FFFDF6 0 40%, var(--ivory-2) 100%);
  box-shadow: 0 0 0 var(--ow-s) var(--ink), 0 0 0 calc(var(--ow-s) + .16rem) rgb(255 250 240 / .55);
}
#difficulty [role="radio"][aria-checked="true"]::after { content: none; }   /* no flame tips: nothing leaves the card */
#difficulty [role="radio"][aria-checked="true"] .pips i.on { background-image: url(../../img/svg/flame-gold-rim.svg); }
#difficulty [role="radio"][aria-checked="true"] .pips i:not(.on) { opacity: .62; }
/* picking a heat: its lit flames ignite one after another (starts when aria-checked turns true) */
#difficulty [role="radio"][aria-checked="true"] .pips i.on {
  --anim: ff-pop 260ms var(--spring-pop) var(--at, 0ms) backwards; animation: var(--anim); transform-origin: 50% 100%;
}
#difficulty [role="radio"][aria-checked="true"] .pips i.on:nth-child(2) { --at: 45ms; }
#difficulty [role="radio"][aria-checked="true"] .pips i.on:nth-child(3) { --at: 90ms; }
#difficulty [role="radio"][aria-checked="true"] .pips i.on:nth-child(4) { --at: 135ms; }
#difficulty [role="radio"][aria-checked="true"] .pips i.on:nth-child(5) { --at: 180ms; }
#difficulty [role="radio"][aria-checked="true"]:not(:focus-visible) { outline-offset: -.38rem; }

/* ============================================================================ controls: modes (key caps) and PLAY */
.controls-row { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--sp-4); align-items: stretch; position: relative; }
#modes { height: var(--ctl-h); gap: .6rem; }
#modes [role="radio"] {
  grid-template-columns: 1.6rem minmax(0, 1fr); grid-template-rows: auto auto; column-gap: var(--sp-2); row-gap: .4rem;
  align-content: center; padding: .4rem .5rem .5rem .5rem; box-shadow: var(--drop-s);
}
#modes [role="radio"] b { grid-column: 2; grid-row: 1; align-self: center; font-size: 1.36rem; }
#modes [role="radio"] small {
  grid-column: 1 / -1; grid-row: 2; display: flex; align-items: center; gap: .2rem; min-width: 0;
  overflow: hidden; white-space: nowrap; line-height: 1;
}
#modes .cap {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; height: 1.42rem; min-width: 1.5rem; margin: 0; padding: 0 .28rem; border-radius: var(--r-xs);
  font: 900 .94rem/1 var(--font-body); letter-spacing: .04em; word-spacing: -.1em; box-shadow: 0 .14rem 0 var(--ink);
}
#modes .cap--lanes { flex: 0 1 auto; display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; line-height: 1.42rem; letter-spacing: .06em; word-spacing: -.25em; }
#modes .cap--star::before { content: '★'; margin-right: .18em; color: var(--f3); -webkit-text-stroke: .6px var(--ink); }
#modes .mode__icon {
  grid-column: 1; grid-row: 1; align-self: center; width: 1.6rem; height: 1.6rem;
  border: var(--ow-s) solid var(--ink); border-radius: var(--r-xs); box-shadow: 0 .12rem 0 var(--ink);
}
#modes [data-preset="tap"] .mode__icon {             /* a fret button: yellow cap, ink ring, red core */
  background:
    radial-gradient(circle, var(--red) 0 .19rem, var(--ink) .21rem .29rem, var(--f2) .31rem .44rem, var(--ink) .46rem .54rem, transparent .56rem),
    linear-gradient(180deg, #FFE27A, var(--f2) 55%, var(--f3));
}
#modes [data-preset="clone"] .mode__icon {           /* the strum bar: red and paper stripes */
  background: repeating-linear-gradient(135deg, var(--red) 0 .22rem, var(--paper) .22rem .42rem);
}
#modes [role="radio"][aria-checked="true"] { box-shadow: inset 0 0 0 .14rem rgb(246 240 228 / .2), var(--drop-s); }
#modes [role="radio"][aria-checked="true"] .cap { background: var(--night-3); color: var(--ivory); border-color: var(--ivory-3); }
#modes [role="radio"][aria-checked="true"] .mode__icon { box-shadow: 0 .14rem 0 #000, 0 0 0 .14rem rgb(246 240 228 / .5); }
#modes [role="radio"][aria-checked="true"]:not(:focus-visible) { outline-offset: -.36rem; }
#modes [role="radio"][aria-checked="true"]::before { right: -.5rem; top: -.6rem; width: 1.45rem; height: 1.45rem; }

/* Strum is the small, quiet option (made for guitars; it asks before switching, select-view askStrum): a dashed
   paper tab next to the big Tap card. Unchosen it says who it is for; chosen it turns night with the flame check and
   shows its strum keys. Tap stays the main card. */
#modes { grid-template-columns: minmax(0, 1fr) auto; }
#modes .mode--alt {
  grid-template-columns: auto; row-gap: .3rem; align-self: center; height: auto; min-height: 3.3rem;
  padding: .35rem .6rem .4rem; border-style: dashed; border-width: var(--ow-s); background: rgb(246 240 228 / .55); box-shadow: none;
}
#modes .mode--alt b { grid-column: 1; font-size: 1.02rem; }
#modes .mode--alt small { font: 800 var(--fs-small)/1.1 var(--font-body); color: var(--ink-2); }
#modes .mode--alt .mode__icon { display: none; }      /* at this size the stripes read as a "no" sign */
#modes .mode--alt[aria-checked="true"] {
  border-style: solid; border-width: var(--ow); background: url(../../img/svg/paper-grain.webp) 0 0 / 16rem, var(--grad-night);
  box-shadow: inset 0 0 0 .14rem rgb(246 240 228 / .2), var(--drop-s);
}
#modes .mode--alt[aria-checked="true"] small { color: var(--ivory-3); }
#modes .mode--alt .cap { height: 1.25rem; font-size: var(--fs-small); }
#modes .mode--alt[aria-checked="true"]::before { right: -.55rem; top: -.7rem; width: 1.3rem; height: 1.3rem; }

/* the Strum question: a sticker centred on the stall body (the body, hint bar and chip go inert meanwhile) */
#select > .strum-ask {
  left: var(--stall-l); right: var(--stall-r); top: var(--stall-body-t); bottom: var(--stall-b); z-index: 2;
  place-items: center; padding: 1rem; pointer-events: none;
}
#select > .strum-ask:not([hidden]) { display: grid; }
.strum-ask__paper {
  width: min(28rem, 100%); padding: 0 0 1.1rem; gap: .75rem; pointer-events: auto;
  --anim: ff-pop 260ms var(--spring-pop) backwards; animation: var(--anim);
}
.strum-ask__paper > :not(.band) { margin-inline: 1.25rem; }
.strum-ask__paper .band { margin-bottom: .4rem; border-radius: calc(var(--r-l) - var(--ow-l)) calc(var(--r-l) - var(--ow-l)) 0 0; }
.strum-ask__paper .band h2 { margin: 0; font-size: var(--fs-h3); }
.strum-ask__paper .body { margin-block: 0; font-size: var(--fs-body); line-height: 1.4; }
.strum-ask__keys { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin-block: 0; }
.strum-ask__keys .cap {
  display: inline-flex; align-items: center; height: 1.42rem; padding: 0 .3rem; border: var(--ow-s) solid var(--ink); border-radius: var(--r-xs);
  background: var(--paper); font: 900 .94rem/1 var(--font-body); letter-spacing: .06em; box-shadow: 0 .14rem 0 var(--ink);
}
.strum-ask__keys .cap--star::before { content: '★'; margin-right: .18em; color: var(--f3); -webkit-text-stroke: .6px var(--ink); }
.strum-ask__paper .row { justify-content: flex-end; }

.controls-row > #modes { grid-column: 1; grid-row: 1; }
.controls-row > #btn-play { grid-column: 2; grid-row: 1; }

#btn-play {
  min-width: 11rem; min-height: var(--ctl-h); height: var(--ctl-h); padding: .1rem .95rem .3rem 1.3rem; gap: .6rem;
  justify-content: space-between; border-radius: var(--r-l);
  box-shadow: inset 0 .22rem 0 rgb(255 255 255 / .32), inset 0 -.3rem 0 rgb(80 0 10 / .32),
              0 var(--btn-drop) 0 var(--ink), 0 .6rem 1.8rem rgb(255 90 31 / .42);
}
#btn-play .tk { font-size: 2.65rem; line-height: 1; letter-spacing: .02em; --tk-shadow: var(--red-deep); }
#btn-play::before { right: 1.1rem; top: -1rem; width: 2rem; height: 1.35rem; background-size: auto 1.35rem, auto .95rem; }

/* No Fail on: an ember pill stuck on Play's top-left corner (same grid cell as Play). It stays inside Play's box, so
   the focus cursor's ring (outside the box) never crosses its text. */
.nofail-pill {
  grid-column: 2; grid-row: 1; justify-self: start; align-self: start; z-index: 3; pointer-events: none;
  display: none; align-items: center; min-height: 1.4rem; padding: 0 .55rem; translate: .55rem -.18rem; rotate: -5deg;
  border: var(--ow-s) solid var(--ink); border-radius: var(--r-pill);
  background: linear-gradient(180deg, #FF8A55, var(--ember) 60%, #D9441C);
  box-shadow: inset 0 .12rem 0 rgb(255 255 255 / .35), 0 .14rem 0 var(--ink); color: var(--ink);
  font: 900 var(--fs-small)/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}
.nofail-pill::before {                                  /* a little shield: you can't fail */
  content: ''; width: .78rem; height: .9rem; margin-right: .3rem; flex: none;
  background: var(--ink); clip-path: polygon(50% 0, 100% 18%, 92% 62%, 50% 100%, 8% 62%, 0 18%);
}
#select:has(#opt-nofail:checked) .nofail-pill {
  display: inline-flex;
  --anim: ff-pop var(--t-base) var(--spring-pop) backwards; animation: var(--anim);
}
#select:has(#opt-nofail:checked) #btn-play { padding-top: 1rem; }
#select:has(#opt-nofail:checked) #btn-play .tk { translate: 0 -.12rem; }

/* ============================================================================ hint bar: roomy groups, Play at the far end */
#select > .hintbar { gap: 1.1rem; padding-inline: .2rem; letter-spacing: .04em; }
#select > .hintbar .hint { gap: .25rem; }
#select > .hintbar .hint--go { margin-left: auto; }
@container (max-width: 60rem) { #select > .hintbar .hint--full { display: none; } }   /* F sits on the Full song switch */
body:not([data-input="pad"]) #select > .hintbar .hint--pad { display: none; }          /* Y asks for Strum; keys don't */

/* reduced motion and reduced graphics: the record stands still */
@media (prefers-reduced-motion: reduce) { .cover-wrap .vinyl { animation: none; } }
body.lowfx .cover-wrap .vinyl { animation: none; }

/* ============================================================================ entrances (SPEC 3.5, 4.4)
   Base styles are the final state; these only add `from` keyframes (fill backwards).
   select-view sets #select[data-enter] on aisu:screen: "swap" (from board / settings / calibrate, or any cut) or
   "move" (a camera move). It never changes while body[data-move] goes away, so nothing restarts mid-way. */
#select[data-enter="swap"] .stall__sign { --anim: ff-drop-in 320ms var(--spring-soft) backwards; animation: var(--anim); }
#select[data-enter="swap"] :is(.menu-top, .hintbar) { --anim: ff-rise-in var(--t-base) var(--ease-out) 60ms backwards; animation: var(--anim); }
#select[data-enter="swap"] .song-thumb { --anim: ff-rise-in 200ms var(--ease-out) var(--at, 0ms) backwards; animation: var(--anim); }
#select[data-enter="swap"] .song-thumb:nth-child(2) { --at: 25ms; }
#select[data-enter="swap"] .song-thumb:nth-child(3) { --at: 50ms; }
#select[data-enter="swap"] .song-thumb:nth-child(4) { --at: 75ms; }
#select[data-enter="swap"] .song-thumb:nth-child(n+5) { --at: 100ms; }
#select[data-enter="swap"] :is(.song-head, .dif-field, .controls-row) { --anim: ff-rise-in 200ms var(--ease-out) var(--at, 0ms) backwards; animation: var(--anim); }
#select[data-enter="swap"] .song-head { --at: 25ms; }
#select[data-enter="swap"] .dif-field { --at: 60ms; }
#select[data-enter="swap"] .controls-row { --at: 95ms; }

/* camera move (title / results / pause -> select): the sign and the body ride in with the frame, on its curve
   (components.css --stall-dx / --stall-in-ms / --ease-stall), 60ms behind it, so they never pass its left edge (and
   the frame clears Aisu + halo). They land with the frame, before body[data-move] goes. The logo and the hint bar
   keep the G0 wait (--move-at). Without linear() the section keeps the G0 fade. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timing-function: linear(0, 1)) {
    body:is([data-move="title-menu"], [data-move="play-menu"]) #select { animation: none; }
    body:is([data-move="title-menu"], [data-move="play-menu"]) #select > :is(.stall__sign, .stall__body) {
      animation: ffc-stall-in calc(var(--stall-in-ms) - 60ms) var(--ease-stall) calc(var(--stall-at, 0ms) + 60ms) backwards;
    }
    body:is([data-move="title-menu"], [data-move="play-menu"]) #select > .menu-top {
      animation: ff-rise-in var(--t-base) var(--ease-out) var(--move-at, 0ms) backwards;
    }
    body:is([data-move="title-menu"], [data-move="play-menu"]) #select > .hintbar {
      animation: ff-rise-in var(--t-base) var(--ease-out) calc(var(--move-at, 0ms) + 120ms) backwards;
    }
  }
}

/* ============================================================================ compact (stall body < 50rem)
   Tickets become a strip of mini tickets on top; head 6.2rem, heat cards 4.5rem, controls 4.8rem. */
@container stall (max-width: 50rem) {
  .select-body {
    --head-h: 6.2rem; --bar-h: 2.8rem; --chip-h: 2.85rem; --card-h: 4.5rem;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 2.7rem var(--head-h) calc(1.35rem + var(--sp-2) + var(--card-h)) var(--ctl-h); row-gap: .9rem;
  }
  .select-body > #song-list { grid-row: auto; flex-direction: row; justify-content: flex-start; gap: var(--sp-2); }
  .song-thumb.ticket { --n: .36rem; flex: 0 0 3.6rem; height: 2.6rem; min-height: 0; }
  .song-thumb.ticket[data-id] { flex: 1 1 0; min-width: 0; }
  .song-thumb.ticket.sel { transform: none; }
  .song-thumb .ticket__in { grid-template-columns: 2.15rem minmax(0, 1fr); }
  .song-thumb .ticket__stub { font-size: 1rem; }
  .song-thumb .ticket__body { padding: 0 .5rem 0 .55rem; }
  .song-thumb .ticket__row { display: none; }
  .song-thumb.locked .ticket__in { grid-template-columns: minmax(0, 1fr); }
  .song-thumb.locked .ticket__body { display: none; }
  .song-thumb.locked .ticket__stub,
  .song-thumb.locked:nth-child(even) .ticket__stub { border-right: 0; background-position: 50% calc(100% + .5rem), 0 0; background-size: 2.1rem auto, auto; }

  .song-head { column-gap: calc(var(--sp-5) + 1.1rem); }
  .cover-wrap .vinyl, .cover-wrap::after { right: -1.55rem; }
  .stats .stat { padding: 0 .55rem; }
  .stats dd { font-size: 1.05rem; }
  .stats .stat--artist { display: none; }
  #sd-best .best__score { font-size: 1.1rem; }

  #difficulty { gap: var(--sp-2); }
  #difficulty [role="radio"] { grid-template-columns: 2.2rem minmax(0, 1fr); column-gap: .45rem; padding: .3rem .5rem .35rem .4rem; }
  #difficulty [role="radio"]::before { width: 2.2rem; height: 2.2rem; }
  #difficulty [role="radio"] small { font-size: var(--fs-small); }

  #btn-play { min-width: 10.5rem; padding-inline: 1.3rem .9rem; }
}

/* a snug standard stall (16:10 laptops, where the stall starts 1.5rem right of the menu safe line): tighter gaps so the
   note counts and the key caps never clip */
@container stall (min-width: 50rem) and (max-width: 53.5rem) {
  .select-body { column-gap: .6rem; }
  #difficulty { gap: .25rem; }
  #difficulty [role="radio"] { column-gap: .3rem; padding-inline: .5rem .45rem; }
  .controls-row { column-gap: var(--sp-2); }
  #modes { gap: .4rem; }
  #modes [role="radio"] { padding-inline: .4rem; }
  #modes [role="radio"] small { gap: .15rem; }
}

/* a roomy stall (16:9): bigger medallions and ticket type */
@container stall (min-width: 58rem) {
  .song-thumb .ticket__in { grid-template-columns: 2.7rem minmax(0, 1fr); }
  .song-thumb .ticket__body { padding: 0 .7rem 0 .75rem; }
  .song-thumb .ticket__title { font-size: 1.22rem; }
  .song-thumb.locked .ticket__title { font-size: 1.12rem; }
  #btn-play { min-width: 12.5rem; }
  #difficulty { --med: 2.75rem; gap: var(--sp-3); }
  #difficulty [role="radio"] { column-gap: .6rem; padding: .4rem .7rem .45rem .5rem; }
  #difficulty [role="radio"] b { font-size: 1.22rem; }
}

/* a roomy best card (16:9): bigger numbers */
@container best (min-width: 18rem) {
  #sd-best.has-best .best__score { font-size: 1.5rem; }
  #sd-best.has-best .st { font-size: 1.12rem; }
  #sd-best.has-best .best__acc { font-size: 1.1rem; }
  #sd-best.has-best .best__line { gap: .7rem; }
}
