/* ═══ DOTD public site — shell ═════════════════════════════════════════════════
   Layout, navigation, views and skeletons. Colour/type/motion tokens come from
   tokens.css; the scene comes from atmos.css. Nothing here reaches off-box.
   ------------------------------------------------------------------------- */

html, body { height: 100%; }
body { overflow: hidden; }

/* keyboard users land here first */
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 100;
  background: #061A30; color: var(--text-hi); border: 1px solid var(--plasma);
  border-radius: 8px; padding: 10px 18px; font-family: var(--f-display);
  font-size: 13px; letter-spacing: .2em; text-transform: uppercase; text-decoration: none;
  transition: top .18s var(--ease-wipe);
}
.skip:focus { top: 8px; outline: 2px solid var(--plasma-core); outline-offset: 2px; }

.app { position: relative; height: 100vh; min-height: 620px; display: flex; overflow: hidden; }
.atmos { position: fixed; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--plasma-core); outline-offset: 2px; border-radius: 4px;
}

/* ── rail ──────────────────────────────────────────────────────────────────── */
.rail {
  position: relative; z-index: 4; width: 78px; flex: 0 0 78px;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, rgba(4,16,32,.88), rgba(3,10,22,.93));
  border-right: 1px solid var(--line); backdrop-filter: blur(4px);
  transition: width .32s var(--ease-wipe), flex-basis .32s var(--ease-wipe);
}
.rail.is-open { width: 252px; flex-basis: 252px; }
.rail::after {
  content: ""; position: absolute; top: 0; right: -1px; width: 1px; height: 34%;
  background: linear-gradient(180deg, transparent, var(--plasma), transparent);
  opacity: .5; animation: railSpine 6.5s var(--ease-breathe) infinite;
}
@keyframes railSpine {
  0% { transform: translateY(-40%); opacity: 0 } 14% { opacity: .6 }
  70% { opacity: .6 } 100% { transform: translateY(320%); opacity: 0 }
}

/* Right padding is not decoration: without it the label runs to the rail edge and
   there is nowhere for a slightly wider fallback font to go. */
.rail-brand {
  display: flex; align-items: center; gap: 12px; padding: 17px 16px 17px 19px;
  min-height: 92px; border-bottom: 1px solid var(--line); text-decoration: none;
}
/* The artwork is a real alpha cutout, so the glow is a drop-shadow that follows
   the disc — not a CSS ring, which would double the rim the art already has. */
.rail-brand .mark { position: relative; width: 40px; flex: 0 0 40px; aspect-ratio: 794 / 846; }
.rail-brand img {
  width: 100%; display: block;
  animation: markBreatheSm var(--t-breathe) var(--ease-breathe) infinite;
}
@keyframes markBreatheSm {
  0%, 100% { filter: drop-shadow(0 0 4px rgba(12,60,174,.55)) }
  50% { filter: drop-shadow(0 0 11px rgba(12,60,174,.95)) }
}
/* Set two-up, exactly as the wordmark itself is set. One line needs 195px in the
   fallback font against 169px of rail — it clipped. Two lines need 136px, so it
   fits with room to spare whichever font wins, and it echoes the logo lockup
   instead of looking squeezed. */
.rail-brand .txt { overflow: hidden; min-width: 0; }
.rail-brand b {
  display: block; font-family: var(--f-display); font-size: 14px; letter-spacing: .14em;
  line-height: 1.08; color: var(--text-hi); text-transform: uppercase; white-space: nowrap;
}
.rail-brand b .l2 { display: block; }
.rail-brand > .txt > span {
  display: block; font-family: var(--f-mono); font-size: 9.5px; color: var(--text-dim);
  white-space: nowrap; margin-top: 4px;
}

.rail-nav { position: relative; padding: 14px 0; flex: 1; }
/* one bar that slides — not four borders switching on and off */
.rail-ind {
  position: absolute; left: 0; top: 14px; width: 2px; height: 46px;
  background: var(--plasma); border-radius: 0 2px 2px 0;
  box-shadow: 0 0 10px var(--plasma), 0 0 26px rgba(4,148,252,.5);
  transition: transform .38s var(--ease-wipe);
}
.rail-item {
  position: relative; display: flex; align-items: center; height: 46px;
  padding-left: 19px; padding-right: 16px;
  color: var(--text-dim); text-decoration: none; font-family: var(--f-display);
  font-size: 13.5px; letter-spacing: .2em; text-transform: uppercase;
  transition: color .22s, background .22s;
}
.rail-item:hover, .rail-item:focus-visible {
  color: var(--text-hi);
  background: linear-gradient(90deg, rgba(4,148,252,.14), transparent 78%);
}
.rail-item[aria-current="page"] { color: var(--paper); }
.rail-item .ic { width: 40px; flex: 0 0 40px; display: grid; place-items: center; }
.rail-item svg {
  width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round; transition: filter .25s;
}
.rail-item[aria-current="page"] svg, .rail-item:hover svg {
  filter: drop-shadow(0 0 6px rgba(4,185,252,.85));
}
/* labels are uncovered by a plasma edge, staggered — they never fade */
.rail-item .lb {
  overflow: hidden; white-space: nowrap; clip-path: inset(0 100% 0 0); opacity: 0;
  transition: clip-path .34s var(--ease-wipe), opacity .2s;
}
.rail.is-open .rail-item .lb { clip-path: inset(0 0 0 0); opacity: 1; }
.rail.is-open .rail-item:nth-of-type(2) .lb { transition-delay: .04s }
.rail.is-open .rail-item:nth-of-type(3) .lb { transition-delay: .08s }
.rail.is-open .rail-item:nth-of-type(4) .lb { transition-delay: .12s }

.rail-pin {
  position: absolute; top: 36px; right: -11px; width: 22px; height: 22px; border-radius: 50%;
  background: #061A30; border: 1px solid var(--line-hi); color: var(--text-dim);
  cursor: pointer; display: grid; place-items: center; font-size: 11px; z-index: 5;
  transition: .2s;
}
.rail-pin:hover { color: var(--plasma-hot); border-color: var(--plasma); box-shadow: var(--glow-plasma); }

.rail-foot {
  border-top: 1px solid var(--line); padding: 13px 16px 15px 19px;
  display: flex; align-items: center; gap: 12px;
}
.rail-foot .txt {
  overflow: hidden; min-width: 0; white-space: nowrap; clip-path: inset(0 100% 0 0);
  transition: clip-path .34s var(--ease-wipe) .08s;
}
.rail.is-open .rail-foot .txt { clip-path: inset(0 0 0 0); }
.rail-foot b { font-family: var(--f-mono); font-size: 10.5px; display: block; color: var(--text); }
.rail-foot span { color: var(--text-dim); font-family: var(--f-mono); font-size: 9.5px; }

/* ── views ─────────────────────────────────────────────────────────────────── */
.main { position: relative; z-index: 2; flex: 1; overflow: hidden; }
.main:focus { outline: none; }
.view { position: absolute; inset: 0; overflow-y: auto; overflow-x: hidden; }
/* the map is a frame, not a document: it must not scroll or it drags the stage taller */
#view-map { overflow: hidden; }
.view[hidden] { display: none; }
.col { max-width: 1000px; margin: 0 auto; padding: 0 40px 64px; }

/* every direct child of a revealing block is uncovered, never faded */
.reveal > * { clip-path: inset(0 100% 0 0); animation: plasmaWipe .44s var(--ease-wipe) forwards; }
.reveal > *:nth-child(1) { animation-delay: .04s } .reveal > *:nth-child(2) { animation-delay: .16s }
.reveal > *:nth-child(3) { animation-delay: .28s } .reveal > *:nth-child(4) { animation-delay: .40s }
.reveal > *:nth-child(5) { animation-delay: .52s } .reveal > *:nth-child(6) { animation-delay: .64s }
@keyframes plasmaWipe { to { clip-path: inset(0 0 0 0) } }

.hero {
  min-height: 100vh; display: grid; grid-template-columns: minmax(280px, 400px) 1fr;
  gap: 52px; align-items: center; padding: 56px 0 40px;
}
/* ── hero badge · ignition ──────────────────────────────────────────────────
   The animation is the icon's own plasma, played from sprite strips and driven
   from JS (see app.js) so the reveals stay locked to the energy. CSS owns only
   the idle breathing that takes over once it has finished. */
.hero-badge { position: relative; width: 100%; max-width: 396px; aspect-ratio: 794 / 846; margin: 0 auto; }
.hero-badge img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; z-index: 2;
}
/* hidden before ignition — a mask stop below 0% leaves nothing visible */
.hero-badge .mark {
  -webkit-mask-image: linear-gradient(to bottom, #000 -11%, transparent 0%);
          mask-image: linear-gradient(to bottom, #000 -11%, transparent 0%);
}
.hero-badge .word {
  -webkit-mask-image: linear-gradient(to right, #000 -11%, transparent 0%);
          mask-image: linear-gradient(to right, #000 -11%, transparent 0%);
}
.hero-badge.is-idle .mark, .hero-badge.is-idle .word {
  -webkit-mask-image: none; mask-image: none;
}
.hero-badge .fx {
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none;
}
.hero-badge .halo {
  position: absolute; left: 0; top: 0; width: 100%; aspect-ratio: 1;
  border-radius: 50%; z-index: 0; opacity: 0;
  box-shadow: 0 0 14px rgba(12,60,174,.7), 0 0 46px rgba(4,28,140,.4);
}
.hero-badge.is-idle .halo {
  opacity: 1; animation: haloBreathe var(--t-breathe) var(--ease-breathe) infinite;
}
@keyframes haloBreathe {
  0%, 100% { opacity: .75; box-shadow: 0 0 12px rgba(12,60,174,.55), 0 0 34px rgba(4,28,140,.28) }
  50% { opacity: 1; box-shadow: 0 0 24px rgba(12,60,174,.95), 0 0 66px rgba(4,28,140,.55) }
}

h1 { font-size: clamp(32px, 4.2vw, 52px); line-height: 1.02; letter-spacing: .02em; }
h1 .eyebrow {
  display: block; color: var(--text-dim); font-size: .40em; letter-spacing: .3em; margin-bottom: 12px;
}
.lede { font-size: 15px; color: var(--text); max-width: 56ch; margin: 18px 0 0; line-height: 1.7; }
.lede b { color: var(--text-hi); }
.tags { display: flex; gap: 9px; flex-wrap: wrap; margin-top: 18px; }
/* the compact roster on Home. Same lesson as .pl below: these rules existed only
   in the self-contained design preview, so the live chips rendered as bare text. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--line); border-radius: 99px; padding: 4px 12px 4px 5px;
  font-size: 11.5px; color: var(--text); background: rgba(4,40,72,.26);
}
.chip i {
  width: 19px; height: 19px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--f-display); font-size: 9px; font-style: normal;
  color: #B9E4FF; background: rgba(4,60,110,.6);
}
.more { color: var(--text-dim); font-family: var(--f-mono); font-size: 10.5px; }
.tag {
  font-family: var(--f-mono); font-size: 11px; color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 99px; padding: 5px 13px; background: rgba(4,20,40,.4);
}
.tag b { color: var(--plasma-hot); font-weight: 400; }
.disclaimer {
  margin-top: 22px; font-size: 12px; color: var(--text-dim); line-height: 1.6;
  max-width: 58ch; padding-left: 13px; border-left: 1px solid var(--line-hi);
}
.disclaimer em { font-style: normal; color: var(--text); }

.section { margin-top: 56px; }
.section-head { display: flex; align-items: baseline; gap: 14px; margin-bottom: 14px; }
.section-head h2 { font-size: 17px; letter-spacing: .2em; }
.section-head .meta { font-family: var(--f-mono); font-size: 10.5px; color: var(--text-dim); margin-left: auto; }

/* ── status ────────────────────────────────────────────────────────────────── */
.status {
  position: relative; display: grid; grid-template-columns: auto 1fr auto; gap: 24px;
  align-items: center; border: 1px solid var(--line); border-radius: 14px;
  padding: 20px 24px; overflow: hidden;
  background: linear-gradient(180deg, rgba(4,26,46,.66), rgba(4,12,26,.7));
}
.status::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--steel); transition: background .4s, box-shadow .4s;
}
.status[data-state="up"]::before { background: var(--live); box-shadow: var(--glow-live); }
.status[data-state="down"]::before { background: var(--down); box-shadow: var(--glow-down); }
.status[data-state="checking"]::before { background: var(--plasma); box-shadow: var(--glow-plasma); }
.status[data-state="stale"]::before { background: #C9A227; box-shadow: 0 0 8px rgba(201,162,39,.8); }

.lamp { position: relative; width: 52px; height: 52px; display: grid; place-items: center; }
.lamp .glass { width: 20px; height: 20px; border-radius: 50%; background: var(--steel); transition: .35s; }
.lamp .halo { position: absolute; inset: 6px; border-radius: 50%; border: 1.5px solid transparent; }
.lamp .arc { position: absolute; inset: 2px; opacity: 0; }
.lamp .arc circle {
  fill: none; stroke: var(--plasma); stroke-width: 2.5; stroke-linecap: round;
  stroke-dasharray: 150; stroke-dashoffset: 150; filter: drop-shadow(0 0 5px rgba(4,148,252,.9));
}
.status[data-state="checking"] .glass { background: #0A2440; transform: scale(.62); }
.status[data-state="checking"] .arc { opacity: 1; }
.status[data-state="checking"] .arc circle { animation: ringClose 1.4s var(--ease-wipe) infinite; }
@keyframes ringClose { 0% { stroke-dashoffset: 150 } 70%, 100% { stroke-dashoffset: 0 } }
.status[data-state="up"] .glass { background: var(--live); box-shadow: var(--glow-live); }
.status[data-state="up"] .halo { border-color: rgba(52,224,138,.34); animation: haloRing 2.4s var(--ease-breathe) infinite; }
@keyframes haloRing { 0% { transform: scale(.72); opacity: .9 } 100% { transform: scale(1.5); opacity: 0 } }

.status .label {
  font-family: var(--f-display); font-size: 20px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--text-hi);
}
.status[data-state="up"] .label { color: #8DF0BE; }
.status[data-state="down"] .label { color: #FF8A98; }
.status .sub { font-size: 12px; color: var(--text-dim); margin-top: 3px; }
.status .sub .mono { color: var(--text); }
.count { text-align: right; min-width: 140px; }
.count .n { font-family: var(--f-mono); font-size: 28px; color: var(--text-hi); line-height: 1; }
.count .n i { font-style: normal; color: var(--text-dim); font-size: 16px; }
.count .cap {
  font-family: var(--f-display); font-size: 10px; letter-spacing: .26em;
  color: var(--text-dim); text-transform: uppercase; margin-top: 5px;
}
.bar { height: 3px; border-radius: 2px; background: rgba(20,76,116,.4); margin-top: 8px; overflow: hidden; }
.bar i {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--plasma-deep), var(--plasma-hot));
  box-shadow: 0 0 8px rgba(4,148,252,.7); transition: width .8s var(--ease-wipe);
}

/* ── skeletons ─────────────────────────────────────────────────────────────
   A skeleton is a PENDING state, not an empty one. It says what it is waiting
   for, in words, and it uses the closing-ring language rather than a shimmer. */
.skeleton { position: relative; overflow: hidden; border-radius: 6px; background: rgba(20,76,116,.22); }
.skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(4,148,252,.16), transparent);
  animation: skelSweep 1.9s var(--ease-wipe) infinite;
}
@keyframes skelSweep { to { transform: translateX(100%) } }
.skel-chip { height: 26px; width: 92px; border-radius: 99px; }
.skel-row { height: 34px; margin-bottom: 8px; }
.pending-note { font-family: var(--f-mono); font-size: 11px; color: var(--text-dim); margin-top: 10px; }

/* ── gates ─────────────────────────────────────────────────────────────────── */
.gates { display: grid; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); gap: 13px; }
.gate {
  position: relative; display: grid; grid-template-columns: 44px 1fr auto; gap: 15px;
  align-items: center; border: 1px solid var(--line-hi); border-radius: 12px; padding: 17px 19px;
  overflow: hidden; text-decoration: none; color: var(--text);
  background: linear-gradient(180deg, rgba(4,28,52,.58), rgba(4,12,26,.68));
  transition: border-color .25s, transform .25s var(--ease-wipe), box-shadow .25s;
}
.gate:hover, .gate:focus-visible {
  border-color: var(--plasma); transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(2,8,20,.6), var(--glow-plasma);
}
.gate::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -30%; width: 26%; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(4,185,252,.22), rgba(210,244,255,.4), transparent);
  filter: blur(6px); opacity: 0;
}
.gate:hover::after, .gate:focus-visible::after { opacity: 1; animation: gateWipe .62s var(--ease-wipe); }
@keyframes gateWipe { from { left: -30% } to { left: 110% } }
.gate .ic {
  width: 44px; height: 44px; border-radius: 11px; display: grid; place-items: center;
  border: 1px solid var(--line-hi); background: rgba(4,44,80,.4); transition: .25s;
}
.gate:hover .ic { border-color: var(--plasma); background: rgba(4,148,252,.18); box-shadow: var(--glow-plasma); }
.gate svg {
  width: 21px; height: 21px; stroke: var(--plasma-hot); fill: none; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.gate b {
  display: block; font-family: var(--f-display); font-size: 15px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-hi);
}
.gate .desc { display: block; font-size: 11.5px; color: var(--text-dim); margin-top: 3px; line-height: 1.45; }
.gate .arw { color: var(--text-dim); font-size: 17px; transition: transform .25s var(--ease-wipe), color .25s; }
.gate:hover .arw { color: var(--plasma-hot); transform: translateX(4px); }

.site-foot {
  margin-top: 60px; padding-top: 20px; border-top: 1px solid var(--line);
  font-size: 11.5px; color: var(--text-dim); line-height: 1.7;
  display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-start;
}
.site-foot a { color: var(--plasma-hot); text-decoration: none; }
.site-foot a:hover { text-decoration: underline; }
.site-foot .fl { flex: 1; min-width: 300px; max-width: 70ch; }
.site-foot b { color: var(--text); }

/* ── partner (affiliate) ────────────────────────────────────────────────────
   Last item in the footer row, pushed to the trailing edge by margin-left:auto so
   it reads as a credit rather than competing with the legal text.

   ⚠ The banner is loud by our standards — neon green on its own dark plate, in a
   page whose brightest accent is a muted plasma blue. Two things keep it subtle:
   it is SMALL (210px against a 6.9:1 lockup), and it rests at 60% opacity, coming
   to full only on hover/focus. That is the same "dim at rest, light on intent"
   language the gates and rail items already use. It carries its own border, so it
   gets none of ours. */
.site-foot .foot-links { white-space: nowrap; }
.partner {
  margin-left: auto; flex: 0 0 auto;
  display: block; text-decoration: none !important;
}
.partner-label {
  display: block; margin-bottom: 5px;
  font-family: var(--f-display); font-size: 9px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--text-dim);
}
.partner img {
  display: block; width: 210px; max-width: 100%; height: auto; border-radius: 2px;
  opacity: .6; transition: opacity var(--t-portal, 320ms) var(--ease-wipe, ease);
}
.partner:hover img, .partner:focus-visible img { opacity: 1; }
/* wrapped onto its own line, "pushed right" is just stranded — line it up with
   everything else instead */
@media (max-width: 900px) { .partner { margin-left: 0; } }
@media (prefers-reduced-motion: reduce) { .partner img { transition: none; } }

/* ── map view ──────────────────────────────────────────────────────────────── */
.map-frame {
  position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 296px;
  /* min-height:0 is not optional here: without it a grid child takes its content
     height as its minimum and the stage grows past the frame, which pushes the map
     down and leaves a band of empty above it. */
  min-height: 0; overflow: hidden;
}
.map-stage { position: relative; overflow: hidden; min-height: 0; min-width: 0; }
.map-stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.map-title { position: absolute; left: 22px; top: 18px; z-index: 3; }
.map-title h2 { font-size: 24px; letter-spacing: .16em; }
.map-title .row { display: flex; gap: 8px; margin-top: 9px; }
.map-title .tag {
  font-family: var(--f-display); font-size: 10.5px; letter-spacing: .24em;
  text-transform: uppercase; background: rgba(3,10,22,.6);
}
.map-side {
  background: linear-gradient(180deg, rgba(4,14,28,.9), rgba(3,10,22,.94));
  border-left: 1px solid var(--line); backdrop-filter: blur(4px);
  display: flex; flex-direction: column; min-height: 0;
}
.map-side .top { padding: 20px 20px 14px; border-bottom: 1px solid var(--line); }
.map-side h3 { font-size: 15px; letter-spacing: .2em; }
.map-side .cnt { font-family: var(--f-mono); font-size: 10.5px; color: var(--text-dim); margin-top: 5px; }
.map-side .list { flex: 1; overflow: auto; padding: 6px 0; min-height: 0; }
/* Shown only under 560px — see § MOBILE at the end of this file. */
.map-desktop-note { display: none; }

/* ── roster row ─────────────────────────────────────────────────────────────
   These live here and not only in the design preview. The previews are
   self-contained by design, so a rule that exists only there does nothing on the
   real site — which is exactly how this row shipped as unstyled inline spans,
   rendering "HA" and "Hando" as "HAHando". */
.pl {
  display: grid; grid-template-columns: 26px 1fr auto; gap: 11px; align-items: center;
  width: 100%; padding: 9px 20px; background: none; border: 0; color: var(--text);
  cursor: pointer; text-align: left; font: inherit;
  border-left: 2px solid transparent;
  transition: background .2s, border-color .2s;
}
.pl:hover, .pl:focus-visible {
  background: linear-gradient(90deg, rgba(4,148,252,.13), transparent);
  border-left-color: var(--plasma); outline: none;
}
.pl .av {
  width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;
  font-family: var(--f-display); font-size: 10.5px; letter-spacing: .04em;
  color: #B9E4FF; background: rgba(4,60,110,.5); border: 1px solid var(--line-hi);
}
.pl b { display: block; font-size: 12.5px; color: var(--text-hi); font-weight: 500; }
.pl .z {
  display: block; font-family: var(--f-mono); font-size: 10px;
  color: var(--text-dim); margin-top: 1px;
}
.map-side .foot {
  border-top: 1px solid var(--line); padding: 13px 20px 15px;
  font-size: 11px; color: var(--text-dim); line-height: 1.55;
}
.map-side .foot b { color: var(--text); }
/* TIS Terms §2.2: using their assets requires this credit, prominently. */
.map-side .credit {
  display: block; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  font-size: 10px; line-height: 1.5; color: var(--text-dim);
}
.map-side .list .pl[aria-current="true"] {
  background: linear-gradient(90deg, rgba(4,148,252,.2), transparent);
  border-left-color: var(--plasma);
}


/* ── overlay panels ────────────────────────────────────────────────────────── */
.scrim {
  position: fixed; inset: 0; z-index: 20; background: rgba(2,6,14,.62);
  backdrop-filter: blur(6px) saturate(.8); display: grid; place-items: center; padding: 32px;
  opacity: 0; pointer-events: none; transition: opacity .28s;
}
.scrim.is-open { opacity: 1; pointer-events: auto; }
.panel {
  position: relative; width: min(660px, 100%); max-height: 88vh; overflow: auto; border-radius: 16px;
  border: 1px solid var(--line-hi);
  background: linear-gradient(180deg, rgba(6,26,48,.97), rgba(4,12,26,.98));
  box-shadow: 0 30px 90px rgba(1,4,10,.8), 0 0 0 1px rgba(4,148,252,.12);
  transform: translateY(14px) scale(.985); opacity: 0;
  transition: transform .34s var(--ease-wipe), opacity .24s;
}
.scrim.is-open .panel { transform: none; opacity: 1; }
.panel::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px; border-radius: 16px 16px 0 0;
  background: linear-gradient(90deg, transparent, var(--plasma-core), var(--plasma), transparent);
  opacity: .6;
}
.panel-head {
  display: flex; align-items: flex-start; gap: 16px; padding: 24px 26px 18px;
  border-bottom: 1px solid var(--line);
}
.panel-head .ic {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: 12px; display: grid; place-items: center;
  border: 1px solid var(--line-hi); background: rgba(4,44,80,.42);
}
.panel-head svg {
  width: 22px; height: 22px; stroke: var(--plasma-hot); fill: none; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.panel-head h2 { font-size: 20px; letter-spacing: .14em; }
.panel-head p { margin: 5px 0 0; font-size: 12.5px; color: var(--text-dim); }
.panel-close {
  margin-left: auto; width: 32px; height: 32px; flex: 0 0 32px; border-radius: 8px;
  background: none; cursor: pointer; border: 1px solid var(--line); color: var(--text-dim);
  font-size: 15px; line-height: 1; transition: .2s;
}
.panel-close:hover { color: var(--text-hi); border-color: var(--plasma); box-shadow: var(--glow-plasma); }
.panel-body { padding: 22px 26px 8px; }
.panel-body p { font-size: 13.5px; color: var(--text); margin: 0 0 14px; line-height: 1.65; }
.panel-body p b { color: var(--text-hi); }
.panel-body h3 {
  font-family: var(--f-display); font-size: 15px; letter-spacing: .2em; color: var(--text-hi);
  text-transform: uppercase; margin: 24px 0 9px; padding-top: 16px; border-top: 1px solid var(--line);
}
.panel-body h3:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.panel-body h3 .num {
  font-family: var(--f-mono); font-size: 11px; color: var(--plasma); letter-spacing: .06em; margin-right: 11px;
}
.bullets { list-style: none; padding: 0; margin: 0 0 18px; }
.bullets li {
  position: relative; padding-left: 24px; font-size: 13px; color: var(--text);
  margin-bottom: 9px; line-height: 1.55;
}
.bullets li::before {
  content: ""; position: absolute; left: 6px; top: 8px; width: 6px; height: 6px; border-radius: 50%;
  background: var(--plasma); box-shadow: 0 0 7px rgba(4,148,252,.85);
}
.invite {
  display: flex; align-items: center; gap: 14px; border: 1px solid var(--line-hi);
  border-radius: 11px; padding: 14px 16px; background: rgba(4,40,74,.34); margin-bottom: 16px;
  flex-wrap: wrap;
}
.invite .u { font-family: var(--f-mono); font-size: 14px; color: var(--plasma-hot); flex: 1; }
.invite a {
  font-family: var(--f-display); font-size: 12px; letter-spacing: .2em; text-transform: uppercase;
  text-decoration: none; color: #EAF6FF; border: 1px solid #1077DE; border-radius: 8px;
  padding: 9px 18px; background: linear-gradient(180deg, #0B63C8, #063C86); box-shadow: var(--glow-plasma);
}
.panel-foot {
  padding: 14px 26px 22px; border-top: 1px solid var(--line);
  font-size: 11.5px; color: var(--text-dim); line-height: 1.6;
}
.panel-foot b { color: var(--text); }
.legal-dl {
  margin: 0 0 14px; display: grid; grid-template-columns: 160px 1fr; gap: 7px 18px; font-size: 12.5px;
}
.legal-dl dt {
  font-family: var(--f-display); letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-dim); font-size: 11.5px; padding-top: 2px;
}
.legal-dl dd { margin: 0; color: var(--text-hi); font-family: var(--f-mono); font-size: 12px; }
.review {
  border-left: 2px solid #C9A227; background: rgba(70,56,10,.2); border-radius: 0 7px 7px 0;
  padding: 9px 13px; font-size: 11.5px; color: #E8D9A6; margin: 6px 0 12px; line-height: 1.6;
}

/* ── no-JS fallback ─────────────────────────────────────────────────────────
   Rendered only when scripting is off. Everything that does not depend on the
   live feed stays readable: who we are, the legal notice, and the map picture. */
.nojs { border: 1px solid var(--line); border-radius: 13px; padding: 22px 26px; margin-top: 22px;
        background: linear-gradient(180deg, rgba(4,26,46,.66), rgba(4,12,26,.7)); }
.nojs h3 { font-family: var(--f-display); font-size: 15px; letter-spacing: .2em;
           text-transform: uppercase; color: var(--text-hi); margin: 22px 0 8px; }
.nojs h3:first-child { margin-top: 0; }
.nojs p { font-size: 13px; color: var(--text); line-height: 1.7; margin: 0 0 11px; max-width: 74ch; }
.nojs a { color: var(--plasma-hot); }
.nojs-map { width: 100%; height: auto; border: 1px solid var(--line); border-radius: 10px; margin: 6px 0; }
.nojs-credit { font-size: 10.5px; color: var(--text-dim); }

/* screen-reader only */
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
      clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; gap: 26px; text-align: center; min-height: 0; padding-top: 34px; }
  .hero-badge { max-width: 270px; }
  .lede, .disclaimer { margin-left: auto; margin-right: auto; }
  .disclaimer { text-align: left; }
  .tags { justify-content: center; }
  .map-frame { grid-template-columns: 1fr; }
  .map-side { display: none; }
  .col { padding: 0 20px 48px; }
}

@media (prefers-reduced-motion: reduce) {
  /* Belt and braces first: kill EVERY animation and transition, including any added
     later. An enumerated list is only correct on the day it is written — this one
     cannot fall behind the stylesheet. */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* Then restore the correct STATIC appearance of anything whose resting state was
     only reached by animating to it. Stopping the motion must not leave the page
     half-drawn. */
  .hero-badge .mark, .hero-badge .word { -webkit-mask-image: none !important; mask-image: none !important; }
  .hero-badge .halo { opacity: 1; }
  .reveal > * { clip-path: none; }
  .skeleton::after { display: none; }
  .rail-item .lb, .rail-foot .txt { clip-path: none; }
  .rail.is-open .rail-item .lb { opacity: 1; }
}

/* ── utilities ──────────────────────────────────────────────────────────────
   These exist so the markup carries no style="" attributes. A CSP without
   'unsafe-inline' blocks inline styles, and the public page ships under one. */
.u-mt14 { margin-top: 14px; }
.u-w104 { width: 104px; }
.u-w76 { width: 76px; }
.u-w78p { width: 78%; }
.u-w86p { width: 86%; }
.u-w94p { width: 94%; }
.u-dot { width: 9px; height: 9px; border-radius: 50%; }
.u-lamp-sm { width: auto; height: auto; margin-left: 15px; }


/* ═══ MOBILE (≤560px) ═══════════════════════════════════════════════════════════
   One bundle, one set of markup, one focus order. The rail BECOMES the bottom tab
   bar rather than a second nav being bolted on, so the router, the `aria-current`
   logic and the keyboard order all keep working untouched.

   Three things this fixes, all measured 2026-08-07:
     1. the 78px rail stayed a sidebar and only opened on `mouseenter` — an event no
        phone fires, so labels were unreachable on touch
     2. `.map-side { display:none }` hid the roster, which is a PLAIN LIST and works
        perfectly at 390px — that was a layout decision, never a capability one
     3. the map canvas is unusable at this width (and has no zoom controls anywhere),
        so `/map` shows the roster + an honest note instead of a broken picture
   ------------------------------------------------------------------------------ */
@media (max-width: 560px) {
  /* ⚠ `height:100vh` is the classic iOS trap once there is a bottom bar: Safari counts
     the URL-bar area in `vh`, so the tab bar sits BELOW the visible viewport until you
     scroll. `dvh` tracks the viewport as the bar collapses. The 100vh above stays as the
     fallback for anything that does not know `dvh`.
     `min-height:620px` also has to go — a phone in landscape is shorter than that, and it
     would force the whole app taller than the screen. */
  .app { flex-direction: column; height: 100dvh; min-height: 0; }
  .main { order: 1; flex: 1; min-height: 0; }

  /* ── rail → bottom tab bar ────────────────────────────────────────────────
     `.is-open` is set by BOTH the hover handler and the localStorage pin; neither
     means anything here, so both selectors are neutralised together. */
  .rail, .rail.is-open {
    order: 2; width: 100%; flex: 0 0 auto; flex-basis: auto; height: auto;
    flex-direction: row; border-right: none; border-top: 1px solid var(--line-hi);
    background: rgba(3,10,22,.96); transition: none;
    padding-bottom: env(safe-area-inset-bottom);   /* clear the iPhone home indicator */
  }
  .rail::after { display: none; }          /* a vertical spine on a horizontal bar */
  .rail-pin, .rail-brand, .rail-foot { display: none; }
  /* nothing is lost: the logo is already the hero, and the player count is already
     the biggest number in the status block. */
  .rail-nav { display: flex; flex: 1; padding: 0; }
  .rail-ind { display: none; }             /* JS drives it on translateY — wrong axis
                                              here; aria-current styles the tab instead */
  .rail-item {
    flex: 1; flex-direction: column; justify-content: center; gap: 3px;
    height: auto; padding: 9px 0 10px; font-size: 9px; letter-spacing: .14em;
  }
  .rail-item:hover, .rail-item:focus-visible { background: none; }
  .rail-item .ic { width: auto; flex: 0 0 auto; }
  .rail-item svg { width: 19px; height: 19px; }
  .rail-item .lb { clip-path: none; opacity: 1; transition: none; }
  .rail-item[aria-current="page"] { color: var(--plasma-hot); }
  .rail-item[aria-current="page"]::before {
    content: ""; position: absolute; top: 0; left: 22%; right: 22%; height: 2px;
    background: var(--plasma-hot); box-shadow: 0 0 8px var(--plasma-hot);
  }

  /* ── home ─────────────────────────────────────────────────────────────────── */
  .col { padding: 0 16px 26px; }
  .hero { padding: 18px 0 4px; gap: 16px; }
  .hero-badge { max-width: 150px; }
  h1 { font-size: 26px; }
  .lede { font-size: 12.5px; }
  .section { margin-top: 26px; }

  /* status is the reason someone opens this on a phone — keep all three cells on
     one row but tighten the gutters, and let the count grow. */
  .status { gap: 11px; padding: 15px 16px; border-radius: 12px; }
  .count { min-width: 0; }
  .count .n { font-size: 30px; }
  .count .n i { font-size: 13px; }
  .count .cap { font-size: 8.5px; letter-spacing: .18em; }

  /* roster: scroll sideways instead of wrapping into a wall of chips. Bleeds to the
     screen edge so it reads as scrollable rather than clipped. */
  #rosterSkeleton .tags {
    flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
    margin-left: -16px; margin-right: -16px; padding: 0 16px 6px;
    scrollbar-width: none;
  }
  #rosterSkeleton .tags::-webkit-scrollbar { display: none; }
  #rosterSkeleton .chip { flex: 0 0 auto; }

  /* ── map: roster + honest note, canvas as a backdrop ──────────────────────── */
  .map-frame { grid-template-columns: 1fr; }
  .map-stage { opacity: .22; }
  .map-side {
    display: flex; position: absolute; inset: 0; width: auto;
    border-left: none; background: rgba(4,14,28,.93);
  }
  .map-side .top { padding: 14px 16px 11px; }
  .map-side h3 { font-size: 13px; }
  .map-desktop-note {
    display: block; margin: 12px 16px 4px; padding: 11px 12px; font-size: 11.5px;
    line-height: 1.6; color: var(--text); border: 1px solid var(--line-hi);
    border-left: 2px solid var(--plasma-hot); border-radius: 8px;
    background: rgba(4,148,252,.07);
  }
  .map-desktop-note b {
    display: block; margin-bottom: 4px; color: var(--text-hi);
    font-family: var(--f-display); font-size: 12px; letter-spacing: .06em;
    text-transform: uppercase;
  }
  .map-desktop-note .mono { color: var(--plasma-hot); }

  /* ── panels → bottom sheets ───────────────────────────────────────────────── */
  .scrim { padding: 0; place-items: end stretch; }
  .panel { width: 100%; max-height: 86vh; border-radius: 14px 14px 0 0; }
  .legal-dl { grid-template-columns: 1fr; gap: 2px 0; }
  .legal-dl dt { margin-top: 8px; }

  /* ── footer ───────────────────────────────────────────────────────────────── */
  .site-foot { flex-direction: column; align-items: center; text-align: center; gap: 14px; }
  .site-foot .fl { min-width: 0; }
  .partner { margin-left: 0; align-self: center; }
}
