/* ==========================================================================
   MASV UI LAB v2, liquid glass + aurora skin
   Loaded after styles.css, additive overrides only. The one bold move: the
   app glows with its own poster (bg-aurora.jpg, the 2026 flyer processed in
   Photoshop). Everything above it is disciplined glass: hairline borders,
   specular top edges, deep blur, one red.
   ========================================================================== */

:root {
  --lab-r: 18px;
  --lab-hair: rgba(255, 255, 255, 0.11);
  --lab-hair-soft: rgba(255, 255, 255, 0.055);
  --lab-glassbg: rgba(12, 14, 27, 0.58);
  --lab-glass: blur(26px) saturate(1.75);
  --lab-red: #ff2e2e;
  --lab-ember: #ff5f3d;
  --lab-ink-grad: linear-gradient(180deg, #ffffff 0%, #d4d7f2 78%);
  --lab-spring: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------- aurora field (the signature) ---------- */
.amb { z-index: 0; }
.amb .aurora {
  position: absolute; inset: -7%;
  width: 114%; height: 114%;
  object-fit: cover;
  opacity: 0.58;
  filter: saturate(1.15) brightness(1.03);
  animation: labAurora 80s var(--lab-spring) infinite alternate;
  will-change: transform;
}
@keyframes labAurora {
  0%   { transform: translate3d(-1.5%, -1%, 0) scale(1.02) rotate(0.001deg); }
  50%  { transform: translate3d(1.2%, 1.6%, 0) scale(1.07); }
  100% { transform: translate3d(-0.8%, 0.8%, 0) scale(1.03); }
}
/* vignette keeps edges dark so glass and type always sit on depth */
.amb::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 8%, transparent 40%, rgba(3, 4, 10, 0.62) 100%),
    linear-gradient(180deg, rgba(3, 4, 10, 0.25), transparent 30%, transparent 62%, rgba(3, 4, 10, 0.66));
  pointer-events: none;
}
/* existing orbs become gentle accents above the aurora */
.amb i { opacity: 0.55; }

/* film grain above everything, barely there */
.lab-grain {
  position: fixed; inset: 0; z-index: 9998; pointer-events: none;
  opacity: 0.028; mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.82'%20numOctaves='2'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='saturate'%20values='0'/%3E%3C/filter%3E%3Crect%20width='180'%20height='180'%20filter='url(%23n)'%20opacity='0.55'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* ---------- shared glass recipe ---------- */
.auth-card, .tix, .acard, .set, .stage-card, .sched-cta, .map-cta,
.beta-note, .lock-note, .install, .sheet, .search,
.gps-readout, .stage-blurb, .info-meta, .linklist a, .ib-btn, .acc-item {
  border-color: var(--lab-hair);
  background-color: var(--lab-glassbg);
  -webkit-backdrop-filter: var(--lab-glass);
  backdrop-filter: var(--lab-glass);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.13),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.03),
    0 24px 60px -30px rgba(0, 0, 0, 0.9);
}
.tix, .acard, .set, .stage-card, .sched-cta, .map-cta, .auth-card,
.beta-note, .lock-note, .install, .info-meta {
  border-radius: var(--lab-r);
}
/* soft top light so every card reads as lit glass, no layout impact */
.tix, .stage-card, .sched-cta, .map-cta, .auth-card, .info-meta {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0) 42%);
}

/* specular sheen sweep on the two hero surfaces */
.auth-card { position: relative; overflow: hidden; }
.auth-card::before {
  content: ""; position: absolute; top: 0; left: -60%;
  width: 55%; height: 100%; pointer-events: none;
  background: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.075) 45%, transparent 90%);
  transform: skewX(-14deg);
  animation: labSheen 9s var(--lab-spring) infinite;
}
@keyframes labSheen {
  0%, 62% { left: -60%; }
  100% { left: 130%; }
}

/* ---------- type ---------- */
.vhead h1 {
  font-size: clamp(31px, 8.4vw, 42px);
  letter-spacing: 0.005em;
  background: var(--lab-ink-grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.vhead .sub {
  font-style: italic;
  letter-spacing: 0.12em; text-transform: uppercase;
  font-size: 11px; opacity: 0.92;
}
.sect-label {
  display: flex; align-items: center; gap: 10px;
  letter-spacing: 0.17em;
}
.sect-label::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.16), transparent 82%);
}

/* countdown: jumbo tabular digits with a hot core */
.count-row .cd b {
  font-variant-numeric: tabular-nums;
  background: linear-gradient(180deg, #ffffff, #ffb3a6 62%, var(--lab-red));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: none;
  filter: drop-shadow(0 0 18px rgba(255, 46, 46, 0.38));
}

/* ---------- app chrome ---------- */
.appbar {
  -webkit-backdrop-filter: var(--lab-glass);
  backdrop-filter: var(--lab-glass);
  background-color: rgba(8, 9, 19, 0.66);
  border-bottom: 1px solid var(--lab-hair-soft);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 18px 40px -26px rgba(0, 0, 0, 0.9);
}
.nav {
  border-color: var(--lab-hair);
  background-color: rgba(10, 12, 24, 0.62);
  -webkit-backdrop-filter: blur(30px) saturate(1.9);
  backdrop-filter: blur(30px) saturate(1.9);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 26px 60px -22px rgba(0, 0, 0, 0.95),
    0 6px 24px -12px rgba(255, 46, 46, 0.12);
}
.nav button { transition: color 0.25s ease, transform 0.35s var(--lab-spring); }
.nav button:active { transform: scale(0.94); }
/* NO text-shadow here: like the icon drop-shadow, it rasterized into a rectangular
   texture over the nav's backdrop blur and re-surfaced as a chopped box on device once
   the idle pause rebuilt layers. The warm label color stays; the radial ::before halo
   behind the icon carries the glow. */
.nav button.active:not(.center) { color: #ffd9d3; }
.nav .ring {
  background:
    radial-gradient(120% 120% at 50% 18%, rgba(255, 255, 255, 0.22), transparent 42%),
    linear-gradient(180deg, #ff5340, #e01f1f);
  border: 1px solid rgba(255, 130, 110, 0.65);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 8px 26px -6px rgba(255, 46, 46, 0.6),
    0 0 0 5px rgba(255, 46, 46, 0.08);
  animation: labPulse 6s ease-in-out infinite;
}
@keyframes labPulse {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 8px 26px -6px rgba(255,46,46,.6), 0 0 0 5px rgba(255,46,46,.08); }
  50% { box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 8px 30px -6px rgba(255,46,46,.78), 0 0 0 9px rgba(255,46,46,.05); }
}

/* ---------- controls ---------- */
.auth-btn, .sc-btn, .tix-cta {
  background: linear-gradient(180deg, var(--lab-ember) 0%, #ff2626 100%);
  border: 1px solid rgba(255, 150, 128, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.38),
    inset 0 -10px 18px rgba(150, 0, 0, 0.28),
    0 14px 34px -12px rgba(255, 46, 46, 0.6);
  text-shadow: 0 1px 2px rgba(90, 0, 0, 0.4);
  transition: transform 0.3s var(--lab-spring), box-shadow 0.3s ease, filter 0.3s ease;
}
.auth-btn:active, .sc-btn:active, .tix-cta:active { transform: scale(0.97); filter: brightness(1.06); }

.daytab, .chip, .map-tab, .auth-tab {
  border-color: var(--lab-hair-soft);
  transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease, transform 0.3s var(--lab-spring);
}
.daytab:active, .chip:active, .map-tab:active { transform: scale(0.95); }
.daytab.active, .chip.on, .map-tab.on, .auth-tab.on {
  background-color: rgba(255, 46, 46, 0.13);
  border-color: rgba(255, 46, 46, 0.55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 6px 18px -8px rgba(255, 46, 46, 0.5);
}

.field input, .search {
  border-radius: 14px;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, background-color 0.25s ease;
}
.field input:focus, .search:focus {
  border-color: rgba(255, 46, 46, 0.6);
  box-shadow: 0 0 0 3px rgba(255, 46, 46, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.1);
  outline: none;
}
:focus-visible { outline: 2px solid rgba(255, 92, 74, 0.7); outline-offset: 2px; }

/* ---------- cards and media ---------- */
.acard { overflow: hidden; transition: transform 0.35s var(--lab-spring), box-shadow 0.35s ease; }
.acard:active { transform: scale(0.965); }
.acard .ph { transition: transform 0.6s var(--lab-spring); }
.acard:hover .ph { transform: scale(1.045); }

.home-hero { border-radius: var(--lab-r); overflow: hidden; border: 1px solid var(--lab-hair); box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.1); }
.poster { border-radius: var(--lab-r); overflow: hidden; border: 1px solid var(--lab-hair); box-shadow: 0 26px 60px -28px rgba(0, 0, 0, 0.92); }

.mapframe {
  border-radius: var(--lab-r);
  border-color: var(--lab-hair);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09), 0 26px 60px -26px rgba(0, 0, 0, 0.95);
}
.map-zoom button, .map-locate {
  border-color: var(--lab-hair);
  background-color: rgba(10, 12, 24, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 8px 20px -10px rgba(0, 0, 0, 0.8);
}

/* modal sheet: grabber + heavier glass */
.sheet {
  border-top-left-radius: 22px; border-top-right-radius: 22px;
  border-color: var(--lab-hair);
  background-color: rgba(11, 13, 26, 0.78);
  -webkit-backdrop-filter: blur(34px) saturate(1.8);
  backdrop-filter: blur(34px) saturate(1.8);
}
.modal .scrim { background: rgba(2, 3, 8, 0.6); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }

/* ---------- view entrance ---------- */
.view.active { animation: labViewIn 0.5s var(--lab-spring) both; }
@keyframes labViewIn {
  from { opacity: 0; transform: translateY(12px) scale(0.995); }
  to   { opacity: 1; transform: none; }
}

/* ---------- auth gate polish ---------- */
.auth-logo .auth-logo-masv { filter: drop-shadow(0 4px 18px rgba(0, 0, 0, 0.6)); }
.auth-logo .auth-logo-img { filter: drop-shadow(0 8px 30px rgba(210, 59, 255, 0.28)); }
.auth-logo .sub { font-style: italic; letter-spacing: 0.34em; }
.auth-card { border-radius: 22px; }
.auth-guest { transition: color 0.25s ease; }

/* ---------- quiet details ---------- */
::selection { background: rgba(255, 46, 46, 0.35); color: #fff; }
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 100px; }
::-webkit-scrollbar-track { background: transparent; }

@media (prefers-reduced-motion: reduce) {
  .amb .aurora, .auth-card::before, .nav .ring { animation: none; }
  .view.active { animation: none; }
}

/* screenshot mode: hide the install toast */
.labshot .install { display: none !important; }

/* ==========================================================================
   UI LAB v2.1, choreography + interaction states (paired with ui-lab.js)
   ========================================================================== */

/* scroll-in reveals: ui-lab.js adds .lab-io pre-paint, .lab-in on entry */
.lab-io { opacity: 0; transform: translateY(14px) scale(0.992);
  transition: opacity 0.65s var(--lab-spring), transform 0.65s var(--lab-spring); }
.lab-io.lab-in { opacity: 1; transform: none; }

/* heart pop + magenta burst ring */
.lab-pop { position: relative; animation: labHeartPop 0.5s var(--lab-spring); }
@keyframes labHeartPop {
  0% { transform: scale(1); }
  35% { transform: scale(1.32) rotate(-4deg); }
  65% { transform: scale(0.92); }
  100% { transform: scale(1); }
}
/* burst ring: spawned on <body> by ui2.js so overflow:hidden cards and row
   stacking can never mask it - always renders above the button */
.lab-burst { position: fixed; z-index: 9999; border-radius: 50%;
  border: 2px solid rgba(255, 43, 214, 0.75); pointer-events: none;
  animation: labBurst 0.5s ease-out both; }
@keyframes labBurst {
  0% { opacity: 0.9; transform: scale(0.6); }
  100% { opacity: 0; transform: scale(1.5); }
}

/* Staggered list entrance on tab switch.
   Was 45ms per item up to 540ms, with everything past the 12th pinned at 300ms - so
   item 13 landed BEFORE item 12 and the tail arrived out of order. Now 25ms per item
   and the tail matches the last explicit step, so it is monotonic and the whole run
   finishes in 300ms instead of 540ms. The lineup grid overrides these with a
   row-aware delay of its own (see renderLineup); this ladder drives the schedule. */
.view.active .acard, .view.active .set { animation: labItemIn 0.5s var(--lab-spring) both; }
.view.active .acard:nth-child(n+13), .view.active .set:nth-child(n+13) { animation-delay: 300ms; }
.view.active .acard:nth-child(1), .view.active .set:nth-child(1) { animation-delay: 25ms; }
.view.active .acard:nth-child(2), .view.active .set:nth-child(2) { animation-delay: 50ms; }
.view.active .acard:nth-child(3), .view.active .set:nth-child(3) { animation-delay: 75ms; }
.view.active .acard:nth-child(4), .view.active .set:nth-child(4) { animation-delay: 100ms; }
.view.active .acard:nth-child(5), .view.active .set:nth-child(5) { animation-delay: 125ms; }
.view.active .acard:nth-child(6), .view.active .set:nth-child(6) { animation-delay: 150ms; }
.view.active .acard:nth-child(7), .view.active .set:nth-child(7) { animation-delay: 175ms; }
.view.active .acard:nth-child(8), .view.active .set:nth-child(8) { animation-delay: 200ms; }
.view.active .acard:nth-child(9), .view.active .set:nth-child(9) { animation-delay: 225ms; }
.view.active .acard:nth-child(10), .view.active .set:nth-child(10) { animation-delay: 250ms; }
.view.active .acard:nth-child(11), .view.active .set:nth-child(11) { animation-delay: 275ms; }
.view.active .acard:nth-child(12), .view.active .set:nth-child(12) { animation-delay: 300ms; }

@keyframes labItemIn {
  from { opacity: 0; transform: translateY(16px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* nav: icon lift on active, springy center press */
.nav button svg { transition: transform 0.35s var(--lab-spring), filter 0.25s ease; } /* keep the filter fade - the shorthand here was silently overriding styles.css's */
.nav button.active:not(.center) svg { transform: translateY(-2px); }
.nav .center:active .ring { transform: scale(0.88); }
.nav .ring { transition: transform 0.3s var(--lab-spring); }

/* artist sheet springs up, scrim fades */
.modal.open .sheet { animation: labSheetUp 0.5s var(--lab-spring); }
@keyframes labSheetUp {
  from { transform: translateY(46px); opacity: 0.4; }
  to { transform: none; opacity: 1; }
}
.modal.open .scrim { animation: labFade 0.35s ease both; }
@keyframes labFade { from { opacity: 0; } to { opacity: 1; } }

/* splash logo breathes while loading */
#splash .splash-logo { animation: labBreathe 2.2s ease-in-out infinite; }
@keyframes labBreathe {
  0%, 100% { transform: scale(1); filter: drop-shadow(0 6px 22px rgba(0,0,0,0.6)); }
  50% { transform: scale(1.035); filter: drop-shadow(0 10px 34px rgba(255,46,46,0.28)); }
}

/* day tabs and chips pop when they become active */
.daytab.active, .chip.on, .map-tab.on { animation: labChipPop 0.32s var(--lab-spring); }
@keyframes labChipPop { 0% { transform: scale(0.94); } 60% { transform: scale(1.04); } 100% { transform: scale(1); } }

/* pressable rows */
.tix:active, .set:active, .stage-card:active, .stage-row:active { transform: scale(0.978); }
.tix, .set, .stage-card, .stage-row { transition: transform 0.3s var(--lab-spring), box-shadow 0.3s ease; }

@media (prefers-reduced-motion: reduce) {
  .lab-io, .lab-io.lab-in { opacity: 1; transform: none; transition: none; }
  .lab-pop, .lab-pop::after, .view.active .acard, .view.active .set,
  .modal.open .sheet, .modal.open .scrim, #splash .splash-logo,
  .daytab.active, .chip.on, .map-tab.on { animation: none; }
}

/* ==========================================================================
   UI LAB v2.2, user feedback round: cards, key tiles, stage gate, vector map
   ========================================================================== */

/* stage cards: roomier, rounder, circular number badges */
.stage-grid { gap: 12px; }
/* Sized for the two-up grid. The old values were set when each stage was a full-width
   bar with room to spare; at half width they pushed every name onto two lines. */
.stage-card { padding: 14px 13px; border-radius: 18px; gap: 11px; }
.stage-card .sc-num { width: 34px; height: 34px; border-radius: 50%; font-size: 15px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 6px 16px -6px rgba(0, 0, 0, 0.6); }
.stage-card .sc-name { font-size: 14.5px; line-height: 1.25; }
.stage-card .sc-blurb { font-size: 12px; margin-top: 1px; }
.stage-card .sc-n { font-size: 11.5px; }

/* key tiles: solid fill, generous radius, no backdrop pass (kills the square
   filter artifact some Chrome builds paint behind rounded corners) */
.key-item { border-radius: 14px; padding: 13px 14px;
  background: rgba(15, 17, 32, 0.92);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0) 46%);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border-color: var(--lab-hair-soft);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  isolation: isolate; overflow: hidden; }

/* stage list stays hidden until set times are live (dev toggle overrides) */
/* Stages stay visible on the map while set times are embargoed: the cards only
   pulse the map marker now, they don't reveal any times. */
body.stages-locked #mapStages { display: block; }

/* hybrid vector map: crisp SVG icon chips sit on the printed icons full-time */
.map-hotspots.viz .mk-hot { opacity: 1; transform: translate(-50%, -50%) scale(0.34); }
.map-hotspots.viz .mk-hot .mk-dot { border-width: 3px;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.6); }
.map-hotspots.viz .mk-hot.sel { opacity: 1; transform: translate(-50%, -50%) scale(0.72); }
/* The .mk-stage block that lived here made stage hotspots transparent, then gave them a
   white ring when lit, on the theory that the badge painted into the art was enough. In
   practice a stage read as nothing happening next to Boomba's bright chip, so stages no
   longer carry the class at all and fall through to the rules every numbered pin uses. */
.map-hotspots.viz .mk-hot.hl { opacity: 1; transform: translate(-50%, -50%) scale(0.72); }
@keyframes mkPulse { 0%, 100% { transform: translate(-50%, -50%) scale(0.72); } 50% { transform: translate(-50%, -50%) scale(0.8); } }

/* aerial entry-guide overlay: animated queue routes + pins + tags */
.entry-ov { position: absolute; inset: 0; pointer-events: none; }
.entry-ov svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.entry-ov .rt { fill: none; stroke-width: 2.6px; stroke-linecap: round;
  stroke-dasharray: 2.4 2; animation: labDash 1.5s linear infinite;
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.9)); }
.entry-ov .rt.ga { stroke: #ff4632; }
.entry-ov .rt.wb { stroke: #2ae8ff; }
.entry-ov .ah.ga { fill: #ff4632; }
.entry-ov .ah.wb { fill: #2ae8ff; }
@keyframes labDash { to { stroke-dashoffset: -8.8; } }
.entry-ov .ov-pin { position: absolute; width: 13px; height: 13px; border-radius: 50%;
  transform: translate(-50%, -50%); border: 2.5px solid #fff; background: #ff2e2e;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.5), 0 0 14px rgba(255, 46, 46, 0.9); }
.entry-ov .ov-pin.arch { animation: labPinPulse 1.8s ease-in-out infinite; }
.entry-ov .ov-pin.ride { background: #8b5cf6; box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.5), 0 0 12px rgba(139, 92, 246, 0.9); }
@keyframes labPinPulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(0,0,0,.5), 0 0 14px rgba(255,46,46,.9), 0 0 0 0 rgba(255,46,46,.5); }
  50% { box-shadow: 0 0 0 2px rgba(0,0,0,.5), 0 0 18px rgba(255,46,46,1), 0 0 0 9px rgba(255,46,46,0); }
}
.entry-ov .ov-chip { position: absolute; transform: translate(-50%, -50%);
  font-family: "Chakra Petch", sans-serif; font-weight: 700; font-size: 10.5px;
  letter-spacing: 0.06em; text-transform: uppercase; color: #fff; white-space: nowrap;
  padding: 6px 10px; border-radius: 100px; background: rgba(8, 10, 20, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.14); }
.entry-ov .ov-chip.ga { border-color: rgba(255, 70, 50, 0.65); }
.entry-ov .ov-chip.wb { border-color: rgba(42, 232, 255, 0.55); }

@media (prefers-reduced-motion: reduce) {
  .entry-ov .rt, .entry-ov .ov-pin.arch { animation: none; }
}

/* ==========================================================================
   UI LAB v2.3, liquid glass light pass: silky aurora + moving caustic sheen
   ========================================================================== */
.amb::before {
  content: ""; position: absolute; inset: -22%;
  background:
    linear-gradient(112deg, transparent 32%, rgba(255, 255, 255, 0.055) 44%, rgba(150, 175, 255, 0.045) 50%, transparent 64%),
    radial-gradient(58% 42% at 82% 108%, rgba(255, 43, 214, 0.09), transparent 70%),
    radial-gradient(46% 34% at 12% -6%, rgba(255, 95, 61, 0.10), transparent 72%);
  mix-blend-mode: screen; pointer-events: none;
  animation: labCaustic 30s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes labCaustic {
  from { transform: translate3d(-5%, -1.5%, 0); }
  to { transform: translate3d(5%, 2.5%, 0); }
}
@media (prefers-reduced-motion: reduce) { .amb::before { animation: none; } }

/* ==========================================================================
   UI LAB v2.4, feedback round 2: sheet anchor, marker glow, countdown, fonts
   ========================================================================== */

/* countdown belongs in the center of the appbar */
.count-row { justify-content: center; text-align: center; }

/* highlighted map markers fill with their color so they read instantly */
.map-hotspots .mk-hot.hl .mk-dot, .map-hotspots .mk-hot.sel .mk-dot {
  background: currentColor;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.55), 0 0 18px currentColor, 0 3px 10px rgba(0, 0, 0, 0.6);
}
.map-hotspots .mk-hot.hl .mk-dot svg, .map-hotspots .mk-hot.sel .mk-dot svg { color: #05060d; }

/* the active key tile lights up in its own color too */
.key-item.on { background: rgba(255, 255, 255, 0.10); border-color: currentColor;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 0 18px -6px currentColor; }
/* jump back to the day tabs from the foot of a ~30-set day */
.back-to-days {
  display: block; width: 100%; margin: 16px 0 6px; padding: 13px 16px;
  border-radius: 14px; border: 1px solid var(--hair, rgba(255,255,255,0.12));
  background: rgba(255, 255, 255, 0.05); color: var(--dim);
  font-family: inherit; font-size: 13px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; cursor: pointer;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.back-to-days:active { transform: scale(0.978); }

/* selected stage matches the key chips, with the number badge lighting up like an icon */
.stage-card.on { background: rgba(255, 255, 255, 0.10); border-color: var(--de-cyan, var(--cyan));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 0 18px -6px var(--de-cyan, var(--cyan)); }
.stage-card.on .sc-num { background: var(--de-cyan, var(--cyan)); color: #05060d; border-color: transparent; }



/* vector icons, print-style: filled color chip, white glyph, white ring */
.map-hotspots.viz .mk-hot .mk-dot {
  background: currentColor;
  border: 2px solid rgba(255, 255, 255, 0.94);
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.5), 0 2px 7px rgba(0, 0, 0, 0.55);
}
.map-hotspots.viz .mk-hot .mk-dot svg { color: #fff; }
.map-hotspots.viz .mk-hot .mk-dot .mk-n {
  color: #fff; font-family: var(--disp); font-weight: 800; font-size: 17px; line-height: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
/* highlight = same fill, bigger + glow (glyph stays white) */
.map-hotspots .mk-hot.hl .mk-dot svg, .map-hotspots .mk-hot.sel .mk-dot svg { color: #fff; }

/* GPS accuracy halo: capped and quiet, the dot is the message */
.you-here .yh-acc { max-width: 96px; max-height: 96px; opacity: 0.55; }

/* GPS teleport tester (reveal mode only) */
#labGpsPill { position: fixed; left: 14px; bottom: calc(env(safe-area-inset-bottom) + 108px); z-index: 70;
  padding: 9px 13px; border-radius: 100px; border: 1px solid rgba(42, 232, 255, 0.5);
  background: rgba(8, 10, 20, 0.82); color: #2ae8ff; font-family: "Chakra Petch", sans-serif;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; cursor: pointer;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 8px 22px -8px rgba(0, 0, 0, 0.8); }
#labGpsPill:active { transform: scale(0.95); }
#labGpsPanel { position: fixed; left: 14px; bottom: calc(env(safe-area-inset-bottom) + 152px); z-index: 70;
  display: none; width: min(320px, calc(100vw - 28px)); max-height: 46vh; overflow-y: auto;
  padding: 13px; border-radius: 18px; border: 1px solid var(--lab-hair);
  background: rgba(9, 11, 22, 0.9); -webkit-backdrop-filter: blur(24px) saturate(1.6); backdrop-filter: blur(24px) saturate(1.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 26px 60px -20px rgba(0, 0, 0, 0.95); }
#labGpsPanel.open { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
#labGpsPanel b { grid-column: 1 / -1; font-family: "Chakra Petch", sans-serif; font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase; color: #2ae8ff; margin-bottom: 2px; }
#labGpsPanel button { padding: 9px 8px; border-radius: 11px; border: 1px solid var(--lab-hair-soft);
  background: rgba(18, 20, 38, 0.85); color: var(--text); font-size: 11.5px; line-height: 1.25;
  text-align: left; cursor: pointer; }
#labGpsPanel button.on { border-color: rgba(42, 232, 255, 0.65); background: rgba(42, 232, 255, 0.12); }
#labGpsPanel button.real { grid-column: 1 / -1; text-align: center; color: #ffd9d3; border-color: rgba(255, 46, 46, 0.4); }

/* embargo: set times blur EVERYWHERE they render while locked, including sheets */
body.sched-locked .sheet .stime, body.times-locked .sheet .stime {
  filter: blur(7px); opacity: 0.75; user-select: none; pointer-events: none;
}

/* entry + aerial tabs: no specular ring, the lighter imagery made it read as a white border */
.mapframe.alt-map { box-shadow: none; border-color: rgba(255, 255, 255, 0.05); }

/* ===== 2026 site map (inline vector) ===== */
#mapContent svg.fmap{width:100%;height:auto;display:block;-webkit-user-select:none;user-select:none;pointer-events:none}
.map-ribbon26{position:absolute;left:50%;top:10px;transform:translateX(-50%);background:rgba(20,16,4,.85);border:1px solid rgba(232,200,74,.5);color:#ffe9a8;font:700 11px/1 "Saira Condensed",sans-serif;letter-spacing:.08em;text-transform:uppercase;padding:7px 12px;border-radius:999px;z-index:5;white-space:nowrap}

/* The festival key chips already read as a group, so the outer glass panel drew a
   box around a grid of boxes. Kill the frame, keep the chips. */
#mapKey {
  background: transparent !important;
  border: 0 !important;
  padding: 0 !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}

/* Guest link stays deliberately quiet: sign-up is the funnel, this is the 5.1.1(v) door. */
#authGuest.auth-guest {
  font-size: 13px;
  margin-top: 15px;
  padding: 9px 10px;           /* bigger tap target: the 5.1.1(v) escape hatch */
  color: var(--dim);
  letter-spacing: .04em;
  opacity: .95;
}
/* comfier tap target on the login/signup swap link */
.auth-alt { font-size: 13px; }
.auth-alt a { padding: 6px 4px; display: inline-block; }

/* ---------- SMS opt-in (ships unchecked, TCPA) ---------- */
.field label .opt { font-weight: 400; opacity: .5; text-transform: none; letter-spacing: 0; margin-left: 5px; }

/* Field labels and placeholders were tuned for a bright room; they read as unlabelled
   on a phone at a night festival. Lift both well clear of the card background. */
.field label { color: #c3c2e2 !important; font-size: 10.5px !important; font-weight: 600; }
.field input::placeholder { color: #8f8fb4; opacity: 1; }
.field input { color: #ffffff; }

/* hCaptcha mounts an iframe with its own light chrome. Centre it, round the corners,
   and collapse the row entirely when the widget is not rendered. */
.ts-box { display: flex; justify-content: center; margin: 2px 0; }
.ts-box:empty { display: none; margin: 0; }
.ts-box iframe { border-radius: 12px; overflow: hidden; }
.optin { display: flex; gap: 10px; align-items: flex-start; margin: 2px 0 4px; cursor: pointer; }
.optin input[type="checkbox"] { flex: none; width: 17px; height: 17px; margin-top: 2px; accent-color: #ff2e2e; cursor: pointer; }
.optin-t { font-size: 12px; line-height: 1.45; color: var(--dim); }
.optin-t b { display: block; color: var(--text); font-weight: 600; margin-bottom: 3px; }
.optin-fine { display: block; font-size: 10px; line-height: 1.45; color: var(--mute); }

/* Lineup entrance. Two problems, one fix.
   The grid is held invisible until its photos have decoded (see waitForArt), so no card
   is ever on screen holding a gradient placeholder that fills in a moment later.
   And the whole grid tiles down as ONE block rather than card by card: any per-card or
   per-row cascade means the alphabetically-first tiles (1991, Benda) are on screen before
   the rest, which reads as the page loading one artist and stalling. Moving the grid as a
   unit keeps the motion without ever letting one card precede another. */
#lineupGrid.art-wait { opacity: 0; }
#lineupGrid.art-wait .acard { animation: none; }
#lineupGrid.art-in { animation: labTileDown 0.38s var(--lab-spring) both; }
#lineupGrid.art-in .acard { animation: none; }
@keyframes labTileDown {
  from { opacity: 0; transform: translateY(-16px); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   AMBIENT REST, perf: the moving aurora + caustic sit underneath 30+
   backdrop-blur glass surfaces, so while they animate the compositor has to
   re-filter the whole screen every frame even when nobody is touching the
   phone - that is what was running phones warm. ui2.js flips html.amb-rest
   after 15s without input; paused-in-place animations resume exactly where
   they stopped, so waking never visibly jumps.
   ========================================================================== */
html.amb-rest .amb .aurora,
html.amb-rest .amb::before,
html.amb-rest .auth-card::before,
html.amb-rest .nav .ring,
/* map pulses were never in this list, so they kept the GPU warm for anyone standing
   still READING the map - the one place people genuinely idle. Same paused-in-place
   rule: the dot and highlighted pins stay visible, they just stop breathing. */
html.amb-rest .you-here .yh-dot,
html.amb-rest .map-hotspots .mk-hot.hl,
html.amb-rest .map-hotspots .mk-hot.hl .mk-glow,
html.amb-rest .entry-ov .ov-pin.arch,
html.amb-rest .mpoi.hl circle,
html.amb-rest .mpoi.hl rect { animation-play-state: paused; }

/* Festival Info tile: keep the glass but stop the text hugging its edges (user, 8/4) */
.info-meta { padding: 15px 17px !important; }
