/* ════════════════════════════════════════════════════════════
   D10 LEAKS: legal pages (Terms / Privacy)
   Matches the MERIDIAN homepage theme
   ════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
  --void:   #050508;
  --panel:  rgba(16,17,22,.55);
  --silver: #e9eaef;
  --muted:  #84858f;
  --line:   rgba(233,234,239,.12);
  --ice:    #ff1428;
  --red:    #ff1428;
  --blue:   #ff1428; /* legacy var, now maps to the red accent */
  --white:  #e9eaef;
  --mid:    #b9bbc6;
  --ease:   cubic-bezier(.16,1,.3,1);
}
/* overflow-x: clip (not hidden) stops decorative glows and oversized elements
   from widening the page and pushing the nav buttons off-screen, without
   breaking position: sticky on the nav the way overflow: hidden would. */
html, body { min-height: 100%; overflow-x: clip; background: var(--void); color: var(--silver); font-family: 'Space Grotesk', system-ui, sans-serif; font-weight: 300; -webkit-font-smoothing: antialiased; }
::selection { background: var(--ice); color: #fff; }

/* subtle backdrop glow */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(1100px 500px at 80% -10%, rgba(255,20,40,.08), transparent 60%),
    radial-gradient(900px 500px at 10% 110%, rgba(255,20,40,.05), transparent 60%);
}

nav {
  position: sticky; top: 0; z-index: 100;
  padding: 20px clamp(14px,4vw,48px);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: rgba(5,5,8,.82); backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
  border-bottom: 1px solid var(--line);
}
/* The logo is the only flexible item, so it gives up space before the buttons
   ever get pushed off the right edge. */
.logo { display: flex; align-items: center; gap: 11px; min-width: 0; overflow: hidden; font-family: 'Unbounded', sans-serif; font-size: clamp(11px,2.2vw,14px); font-weight: 500; letter-spacing: clamp(.14em,.9vw,.34em); color: var(--silver); text-decoration: none; white-space: nowrap; }
.logo span { color: #ff1428; text-shadow: 0 0 14px rgba(255,20,40,.5); }
.logo-img { height: 30px; width: auto; filter: drop-shadow(0 0 10px rgba(255,20,40,.4)); }
/* Buttons never shrink or wrap - the logo absorbs the squeeze instead */
.nav-actions { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.nav-join, .back-btn {
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: clamp(.14em,.7vw,.3em); text-transform: uppercase;
  padding: 11px clamp(13px,1.6vw,20px); border-radius: 999px;
  white-space: nowrap; text-decoration: none; flex: 0 0 auto;
  display: flex; align-items: center; gap: .5rem;
}
.nav-join {
  color: #fff; background: var(--ice); border: 1px solid var(--ice);
  box-shadow: 0 0 24px rgba(255,20,40,.32); transition: transform .25s, box-shadow .25s;
}
.nav-join:hover { transform: translateY(-1px); box-shadow: 0 0 34px rgba(255,20,40,.55); color: #fff; }
/* Same shape and weight as Join Discord, just not competing for attention */
.back-btn {
  color: var(--silver);
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.22);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: color .3s, border-color .3s, background .3s, transform .25s;
}
.back-btn:hover { color: #fff; border-color: rgba(255,20,40,.6); background: rgba(255,20,40,.12); transform: translateY(-1px); }
/* Drop the "to site" wording well before space actually runs out. Media queries
   measure innerWidth (scrollbar included) while the usable width is ~15px less,
   so a tight breakpoint leaves a band where the nav silently overflows. */
@media (max-width: 720px) {
  .bb-long { display: none; }
}
@media (max-width: 560px) {
  nav { padding: 16px 12px; gap: 8px; }
  .logo-img { height: 22px; }
  .nav-actions { gap: 7px; }
  .nav-join, .back-btn { font-size: 9px; letter-spacing: .16em; padding: 9px 12px; }
}
/* Narrow phones: the wordmark goes, the icon and both buttons stay */
/* 430, not 380. The wordmark needs 121px and the nav actions take 252, so
   between about 381 and 420 the logo box was ~116px with overflow:hidden
   and it silently truncated: the bar read "D10 LEAK" with the S sliced
   off. That band is iPhone 12/13/14 at 390 and plenty of Androids at 400
   to 414, so it was most phones. Dropping the wordmark and keeping the
   mark reads as deliberate; half a word does not. */
@media (max-width: 430px) {
  /* .logo carries min-width:0 and overflow:hidden so it can yield space to
     the buttons. With the wordmark at font-size:0 it yielded too much: at
     320px the box shrank to 21px while the icon inside is 43px wide, so the
     icon itself was sliced in half. The wordmark going was the intent; the
     icon going with it was not. */
  .logo { font-size: 0; gap: 0; flex: 0 0 auto; overflow: visible; }
  .logo-img { height: 24px; }
  .nav-actions { gap: 6px; }
  .nav-join, .back-btn { font-size: 8.5px; letter-spacing: .12em; padding: 8px 10px; }
}


.page-wrap { max-width: 800px; margin: 0 auto; padding: 4.5rem 1.5rem 6rem; }

.page-eyebrow {
  font-family: 'IBM Plex Mono', monospace; font-size: 11px;
  letter-spacing: .42em; text-transform: uppercase; color: var(--ice);
  margin-bottom: 1.2rem; display: flex; align-items: center; gap: 14px;
}
.page-eyebrow::before { content: ''; display: block; width: 34px; height: 1px; background: var(--ice); opacity: .7; }

h1 {
  font-family: 'Unbounded', sans-serif; font-size: clamp(28px, 5vw, 52px);
  font-weight: 200; line-height: 1.08; letter-spacing: -.01em;
  color: var(--silver);
  margin-bottom: .8rem;
}
.updated { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .3em; text-transform: uppercase; color: var(--muted); margin-bottom: 2.6rem; }
.rule { height: 1px; background: linear-gradient(90deg, var(--ice), transparent); margin-bottom: 2.6rem; opacity: .5; }

.page-wrap > p { font-size: .95rem; color: var(--mid); line-height: 1.9; margin-bottom: 1.6rem; }

/* glass section cards */
.legal-section {
  margin-bottom: 1.1rem;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px;
  padding: 1.5rem 1.6rem 1.3rem;
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  transition: border-color .35s, background .35s, transform .5s var(--ease);
}
.legal-section:hover { border-color: rgba(255,20,40,.4); background: rgba(255,255,255,.07); transform: translateY(-3px); }

.legal-section h2 {
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 400;
  letter-spacing: .3em; text-transform: uppercase; color: var(--ice);
  margin-bottom: .8rem; display: flex; align-items: center; gap: .7rem;
}
.legal-section h2::before { content: ''; display: block; width: 14px; height: 1px; background: var(--ice); flex-shrink: 0; }
/* unified keyboard focus ring (a11y) */
a:focus-visible, button:focus-visible { outline: 2px solid var(--ice); outline-offset: 3px; }

p { font-size: .92rem; color: var(--mid); line-height: 1.9; margin-bottom: .6rem; }
ul { padding-left: 0; list-style: none; margin-top: .4rem; }
li {
  font-size: .92rem; color: var(--mid); line-height: 1.8;
  padding: .35rem 0 .35rem 1.2rem; position: relative; border-bottom: 1px solid rgba(255,255,255,.05);
}
li:last-child { border-bottom: none; }
/* Accent rule instead of a dash character, matching .legal-section h2::before.
   top is the li's own top padding plus half a line-height, so the rule centres
   on the first line and follows the font size if that ever changes. */
li::before {
  content: ''; position: absolute; left: 0; top: calc(.35rem + .9em);
  width: 11px; height: 1px; background: var(--ice); opacity: .7;
}
a { color: var(--ice); text-decoration: none; transition: opacity .25s; }
a:hover { opacity: .75; text-decoration: underline; }
strong { color: var(--white); font-weight: 500; }

/* Flex list rather than a run-on sentence, so it wraps to tidy rows on phones
   instead of breaking mid-phrase. */
/* ════════════════════════════════════════════════════════════
   SITE FOOTER — brand column + link columns + bottom bar
   Replaces the single centred strip. Grid is auto-fit so the
   columns collapse to two on tablets and one on phones without
   a separate breakpoint per size.
   ════════════════════════════════════════════════════════════ */
footer {
  position: relative; isolation: isolate; overflow: hidden;
  border-top: 1px solid var(--line);
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1.25rem, 5vw, 3rem) 0;
  color: var(--muted);
  font-family: 'Space Grotesk', system-ui, sans-serif;
  font-size: .9rem; letter-spacing: normal; text-transform: none;
  /* The page's red glow sits bottom-left, which is exactly where the footer
     lands. Fade to flat void across the top of it so the footer reads as its
     own quiet block instead of the brightest thing on the page. */
  background: linear-gradient(to bottom, rgba(5,5,8,0) 0%, rgba(5,5,8,.78) 26%, var(--void) 58%);
}

/* ── night sky ──────────────────────────────────────────────────────────
   Static dust is painted once as background-image (zero per-frame cost).
   The shooting stars animate transform and opacity ONLY, so they live on the
   compositor and never trigger layout or paint — the same rule that keeps
   scrolling smooth elsewhere on the site.
   Star positions come from nth-child, not inline custom properties, because
   these pages ship a CSP with no 'unsafe-inline' and a style="" attribute
   would be dropped. */
.ft-sky {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
}

/* Two layers, because nth-child counts every child: stars and streaks in one
   container would shift each other's indices and neither set would match. */
.ft-dust,.ft-streaks{position:absolute;inset:0;pointer-events:none}

/* ── twinkle ─────────────────────────────────────────────────────────────
   The dust used to be a background-image, which is free to paint but cannot
   animate one dot at a time: the whole layer would have to blink at once.
   Each star is its own element now so they fade independently.
   Only opacity animates, so this stays on the compositor and never repaints,
   and the sizes and timings are all different or they pulse in unison and
   read as a strobe rather than a sky. */
.ft-star{position:absolute;border-radius:50%;background:#fff;opacity:var(--dim,.2);
  animation-name:ftTwinkle;animation-timing-function:ease-in-out;animation-iteration-count:infinite;will-change:opacity}
@keyframes ftTwinkle{
  0%,100%{opacity:var(--dim,.2)}
  50%{opacity:1}
}
.ft-star:nth-child(1){left:33.4%;top:20.7%;width:2.5px;height:2.5px;animation-duration:2.9s;animation-delay:2.9s;--dim:0.17}
.ft-star:nth-child(2){left:8.5%;top:50.6%;width:1.7px;height:1.7px;animation-duration:4.2s;animation-delay:0.4s;--dim:0.12}
.ft-star:nth-child(3){left:42.9%;top:77.5%;width:1.8px;height:1.8px;animation-duration:3.4s;animation-delay:3.5s;--dim:0.29}
.ft-star:nth-child(4){left:57.2%;top:41.3%;width:3.0px;height:3.0px;animation-duration:2.8s;animation-delay:4.7s;--dim:0.16}
.ft-star:nth-child(5){left:16.6%;top:17.9%;width:2.0px;height:2.0px;animation-duration:5.5s;animation-delay:1.0s;--dim:0.22}
.ft-star:nth-child(6){left:63.1%;top:39.3%;width:2.4px;height:2.4px;animation-duration:2.8s;animation-delay:0.3s;--dim:0.14}
.ft-star:nth-child(7){left:67.0%;top:43.9%;width:2.0px;height:2.0px;animation-duration:4.7s;animation-delay:2.5s;--dim:0.16}
.ft-star:nth-child(8){left:77.7%;top:66.7%;width:1.9px;height:1.9px;animation-duration:4.7s;animation-delay:2.9s;--dim:0.28}
.ft-star:nth-child(9){left:71.6%;top:32.2%;width:3.0px;height:3.0px;animation-duration:3.0s;animation-delay:2.3s;--dim:0.25}
.ft-star:nth-child(10){left:17.3%;top:49.1%;width:1.7px;height:1.7px;animation-duration:5.0s;animation-delay:4.2s;--dim:0.21}
.ft-star:nth-child(11){left:85.3%;top:34.4%;width:2.6px;height:2.6px;animation-duration:4.7s;animation-delay:3.2s;--dim:0.19}
.ft-star:nth-child(12){left:82.0%;top:87.4%;width:2.3px;height:2.3px;animation-duration:5.0s;animation-delay:0.3s;--dim:0.24}
.ft-star:nth-child(13){left:63.8%;top:91.4%;width:2.8px;height:2.8px;animation-duration:3.6s;animation-delay:2.1s;--dim:0.23}
.ft-star:nth-child(14){left:5.1%;top:46.8%;width:1.8px;height:1.8px;animation-duration:3.0s;animation-delay:0.3s;--dim:0.25}
.ft-star:nth-child(15){left:15.2%;top:28.8%;width:2.1px;height:2.1px;animation-duration:5.7s;animation-delay:0.4s;--dim:0.19}
.ft-star:nth-child(16){left:54.6%;top:82.2%;width:2.7px;height:2.7px;animation-duration:5.7s;animation-delay:1.5s;--dim:0.18}
.ft-star:nth-child(17){left:36.7%;top:82.3%;width:2.9px;height:2.9px;animation-duration:3.1s;animation-delay:1.0s;--dim:0.15}
.ft-star:nth-child(18){left:24.9%;top:48.7%;width:2.4px;height:2.4px;animation-duration:3.5s;animation-delay:0.0s;--dim:0.18}

.ft-shoot {
  position: absolute; top: -10%;
  width: 3px; height: 3px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 1px rgba(255,255,255,.7);
  opacity: 0;
  animation: ftShoot 7s linear infinite;
}
/* the trail, pointing back up-left along the direction of travel */
.ft-shoot::before {
  content: ''; position: absolute; right: 1px; top: 50%;
  width: 70px; height: 1.5px;
  background: linear-gradient(to left, rgba(255,255,255,.8), rgba(255,255,255,0));
  transform-origin: 100% 50%; transform: rotate(45deg);
}

/* Staggered so they never streak in unison, but often enough that you actually
   catch one without staring at the footer waiting. */
.ft-shoot:nth-child(1) { left: 14%; animation-delay: .4s;  animation-duration: 7s;  }
.ft-shoot:nth-child(2) { left: 38%; animation-delay: 2.1s; animation-duration: 8s;  }
.ft-shoot:nth-child(3) { left: 61%; animation-delay: 3.6s; animation-duration: 6.5s;}
.ft-shoot:nth-child(4) { left: 82%; animation-delay: 5.2s; animation-duration: 9s;  }
.ft-shoot:nth-child(5) { left: 26%; animation-delay: 6.8s; animation-duration: 7.5s;}

@keyframes ftShoot {
  0%   { transform: translate3d(0,0,0);         opacity: 0; }
  3%   { opacity: 1; }
  20%  { opacity: 0; }
  100% { transform: translate3d(300px,300px,0); opacity: 0; }
}

/* Reduced motion means NO MOVEMENT, not "delete the artwork". The previous
   display:none hid the stars outright from anyone whose OS has animations
   switched off, which on Windows is a very common default. They now sit still
   and lit instead, so the footer looks the same, it just doesn't move. */
/* Deliberately keeps moving under reduced motion, at the site owner's request.
   Safe-ish as decoration goes: a few 3px dots drifting inside the footer, no
   parallax, no full-page movement, nothing that follows the scroll. */
footer a { color: var(--mid); text-decoration: none; transition: color .3s var(--ease); }
footer a:hover { color: var(--ice); }
footer strong { color: var(--silver); font-weight: 500; }

.ft-top {
  position: relative; z-index: 1;
  max-width: 1180px; margin: 0 auto;
  display: grid; gap: clamp(28px, 4vw, 56px);
  grid-template-columns: minmax(240px, 1.6fr) repeat(auto-fit, minmax(150px, 1fr));
  align-items: start;
}

/* ── brand column ── */
.ft-brand-name {
  display: flex; align-items: center; gap: 9px;
  font-family: 'Unbounded', sans-serif; font-size: 1.02rem; font-weight: 500;
  color: var(--silver); letter-spacing: .01em; text-transform: uppercase;
}
.ft-brand-name img { width: 22px; height: 22px; object-fit: contain; }
.ft-brand-name span { color: var(--ice); }
.ft-blurb { margin: 16px 0 20px; font-size: .88rem; line-height: 1.7; color: var(--muted); max-width: 34ch; }
.ft-cta {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 10px 20px; border-radius: 8px;
  background: var(--red); color: #fff !important;
  font-size: .86rem; font-weight: 500;
  transition: background .3s var(--ease);
}
.ft-cta:hover { background: #e00f22; color: #fff !important; }

/* ── link columns ── */
.ft-col h3 {
  font-family: 'Unbounded', sans-serif;
  font-size: .74rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: var(--silver); margin-bottom: 16px;
}
.ft-col ul { list-style: none; display: grid; gap: 5px; }
/* 16px tall was under the 24px minimum touch target. The padding is taken
   out of the list gap above, so the visual spacing is unchanged and only
   the tappable area grows. */
.ft-col a { font-size: .88rem; display: inline-block; padding: 4px 0; }

/* ── bottom bar ── */
/* ── affiliated with ──────────────────────────────────────────────────────
   A named band above the footer proper, not a line tucked inside it. The
   first version sat between the link columns and the copyright at 26px tall,
   which read as fine print — the opposite of what a partner credit is for.

   Logos arrive in their own brand colours, which would read as a scatter of
   unrelated stickers in a row. Desaturating them to a common silver at rest
   makes the row read as one line, and returning the colour on hover rewards
   the person actually looking at it. */
.ft-affil {
  position: relative; z-index: 1;
  max-width: 1180px; margin: clamp(2.4rem, 4.5vw, 3.6rem) auto 0;
  padding-top: clamp(2.2rem, 4vw, 3rem);
  border-top: 1px solid var(--line);
  text-align: center;
}

.ft-affil h3 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px; letter-spacing: .34em; text-transform: uppercase;
  color: var(--muted); font-weight: 400;
  margin: 0 0 clamp(1.5rem, 3vw, 2.1rem);
}

.ft-affil-row {
  display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center;
  gap: clamp(2rem, 6vw, 5rem);
}

/* Marks only, under the heading — the same shape as the homepage row. The
   heading carries the meaning, so the names beside each logo were saying it
   twice. */
.ft-affil-item {
  display: inline-flex; align-items: center; justify-content: center;
  /* Clears the 44px tap minimum in both directions: a tall narrow mark like
     the B is only ~24px wide at logo height. */
  min-height: 44px; min-width: 44px; padding: 4px 6px;
  text-decoration: none; color: var(--muted);
  transition: color .35s var(--ease), transform .35s var(--ease);
}
.ft-affil-item:hover,
.ft-affil-item:focus-visible { color: var(--silver); transform: translateY(-3px); }

.ft-affil-item img {
  /* Height, never width: the marks have different aspect ratios and matching
     their widths would leave a tall narrow logo dwarfing a wide flat one. */
  height: clamp(32px, 3.4vw, 40px); width: auto; display: block;
  filter: grayscale(1) brightness(1.7); opacity: .8;
  transition: filter .35s var(--ease), opacity .35s var(--ease);
}
.ft-affil-item:hover img,
.ft-affil-item:focus-visible img { filter: none; opacity: 1; }


@media (max-width: 560px) {
  .ft-affil-row { gap: 1.6rem 2rem; }
}

@media (prefers-reduced-motion: reduce) {
  .ft-affil-item, .ft-affil-item img { transition: none; }
  .ft-affil-item:hover, .ft-affil-item:focus-visible { transform: none; }
}

.ft-bottom {
  position: relative; z-index: 1;
  max-width: 1180px; margin: clamp(2.2rem, 4vw, 3rem) auto 0;
  border-top: 1px solid var(--line);
  padding: 1.4rem 0 1.8rem;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 12px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9px; letter-spacing: .26em; text-transform: uppercase;
  text-align: center;
}
.foot-sep { opacity: .45; }

@media (max-width: 700px) {
  .ft-top { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
  /* Brand spans the full width on phones so the blurb doesn't get a 140px column */
  .ft-brand { grid-column: 1 / -1; }
}


@media (max-width: 560px) {
  footer { padding: 2.2rem 1.15rem 0; }
  /* 38px was under the 44px touch minimum, and this is the button that matters */
  .ft-cta { padding: 13px 22px; }
  .ft-bottom { letter-spacing: .18em; font-size: 8.5px; padding: 1.2rem 0 1.5rem; }
  .foot-sep { display: none; }              /* rows read cleaner without it */
}

/* ── Music Player (legal pages keep their own compact player) ── */
#music-player {
  position: fixed; bottom: 1.5rem; right: 1.5rem;
  display: none; flex-direction: column;
  width: 270px; border-radius: 16px;
  background: var(--panel);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--line);
  box-shadow: 0 10px 36px rgba(0,0,0,.55);
  overflow: hidden; z-index: 9000;
  opacity: 0; transform: translateY(12px);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
  pointer-events: none;
}
#music-player.visible  { opacity: 1; transform: translateY(0); pointer-events: auto; }

#mpProgress { width: 100%; height: 2px; background: rgba(233,234,239,.08); }
#mpFill { height: 100%; width: 0%; background: var(--ice); box-shadow: 0 0 8px rgba(255,20,40,.7); transition: width .4s linear; }

.mp-inner {
  display: flex; align-items: center; justify-content: space-between;
  padding: .7rem .85rem .7rem 1rem; gap: .5rem;
}
.mp-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
#mpTitle  {
  font-size: .74rem; font-weight: 500;
  color: var(--silver); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#mpArtist {
  font-family: 'IBM Plex Mono', monospace; font-size: .56rem; letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.mp-controls { display: flex; align-items: center; gap: .2rem; flex-shrink: 0; }
.mp-controls button {
  background: none; border: none; cursor: pointer; padding: 6px;
  color: var(--muted); border-radius: 50%; display: flex;
  align-items: center; justify-content: center;
  transition: color .25s, background .25s; line-height: 1;
}
.mp-controls button:hover { color: #fff; background: rgba(255,20,40,.25); }
#mpPlayPause { color: var(--silver); }
#mpClose { font-size: .72rem; opacity: .5; }
#mpClose:hover { opacity: 1; color: var(--ice); }

/* reopen pill */
#mp-reopen {
  position: fixed; bottom: 1.5rem; right: 1.5rem;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--line); cursor: pointer;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  color: var(--muted); font-size: 1rem;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none; z-index: 9000;
  transition: all .4s var(--ease);
  transform: scale(.8);
}
#mp-reopen.visible { opacity: 1; pointer-events: auto; transform: scale(1); }
#mp-reopen:hover   { color: var(--ice); border-color: rgba(255,20,40,.5); }

/* now-playing toast */
#now-playing-toast {
  position: fixed; bottom: 5.6rem; right: 1.5rem;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--silver);
  font-family: 'IBM Plex Mono', monospace; font-size: .62rem; letter-spacing: .22em;
  padding: .55rem 1.1rem;
  border-radius: 999px; backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  white-space: nowrap; opacity: 0; transform: translateY(8px);
  /* Above #enter-screen (9500). The track starts the instant Enter is
     pressed, so at 9001 the toast appeared UNDERNEATH an opaque overlay that
     takes a second to fade — by the time it was visible it was already on its
     way out, which is why the title never seemed to show on these pages. */
  z-index: 9600; transition: opacity .4s ease, transform .4s ease;
  pointer-events: none;
}


/* Touch devices: drop the live backdrop blur for near-opaque panels. A sticky
   blurred nav plus a column of blurred cards forces the compositor to re-sample
   the page every scroll frame, which is what makes content paint late on
   phones. Visually near-identical, far cheaper. */
@media (max-width: 900px), (hover: none) {
  nav { background: rgba(5,5,8,.97); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .back-btn { background: rgba(255,255,255,.09); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .legal-section {
    background: rgba(13,14,19,.94);
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .legal-section:hover { transform: none; }
  /* The music-player chrome is position:fixed, so a blurred backdrop on it gets
     re-sampled on EVERY scroll frame for the whole page rather than once. These
     three stay on screen the entire time you scroll, which makes them the most
     expensive blur here despite being the smallest. */
  #music-player, #mp-reopen, #now-playing-toast {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  #music-player      { background: rgba(13,14,19,.96); }
  #mp-reopen         { background: rgba(13,14,19,.94); }
  #now-playing-toast { background: rgba(13,14,19,.94); }
}

/* CSP-safe hide. These pages ship style-src without 'unsafe-inline', so a
   style="display:none" attribute in the markup is dropped by the browser.
   The player toggles this class instead. */
.is-hidden { display: none !important; }


/* ════════════════════════════════════════════════════════════
   NAV AUDIO CONTROL
   Ported from meridian.css so the sub-pages carry the same player
   as the homepage: a pill in the header with an AUDIO dropdown,
   not a box floating in the corner. IDs match the homepage exactly,
   so site-player.js drives both without branching.
   ════════════════════════════════════════════════════════════ */
#audio-ctrl{position:relative;display:flex;align-items:center;gap:2px;border:1px solid var(--line);border-radius:999px;background:var(--panel);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);padding:2px}
#sound-toggle{display:flex;align-items:center;padding:9px 11px 9px 13px;border-radius:999px;color:var(--muted);background:none;border:0;cursor:pointer;transition:color .35s,background .35s}
#sound-toggle:hover{color:var(--silver);background:rgba(255,255,255,.05)}
#sound-toggle.active{color:var(--ice)}
#audio-ctrl.is-muted #sound-toggle{color:var(--muted)}
#audio-menu-btn{display:flex;align-items:center;justify-content:center;padding:9px 11px;border-radius:999px;font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--muted);background:none;border:0;cursor:pointer;transition:color .35s,background .35s}
#audio-menu-btn:hover{color:var(--silver);background:rgba(255,255,255,.05)}
#audio-menu-btn[aria-expanded="true"]{color:var(--ice)}
.ac-caret{width:12px;height:12px;transition:transform .35s var(--ease)}
#audio-menu-btn[aria-expanded="true"] .ac-caret{transform:rotate(180deg)}

#audio-menu{position:absolute;top:calc(100% + 12px);right:0;width:min(252px,calc(100vw - 24px));background:rgba(11,12,16,.82);border:1px solid var(--line);border-radius:16px;backdrop-filter:blur(26px) saturate(130%);-webkit-backdrop-filter:blur(26px) saturate(130%);box-shadow:0 16px 44px rgba(0,0,0,.6);padding:16px;opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .35s var(--ease),transform .35s var(--ease),visibility .35s;z-index:14}
#audio-menu.open{opacity:1;visibility:visible;transform:translateY(0)}
.am-head{display:flex;flex-direction:column;padding-bottom:13px}
.am-eyebrow{font-family:'IBM Plex Mono',monospace;font-size:8px;letter-spacing:.34em;text-transform:uppercase;color:var(--ice);display:flex;align-items:center;gap:8px}
.am-eyebrow::before{content:"";width:18px;height:1px;background:var(--ice);opacity:.7}
.am-title{font-size:14px;font-weight:500;color:var(--silver);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:9px}
.am-artist{font-family:'IBM Plex Mono',monospace;font-size:9px;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:3px}
.am-prog{height:3px;border-radius:2px;background:rgba(233,234,239,.1);overflow:hidden;margin-bottom:14px}
#mpFill{height:100%;width:0%;background:var(--ice);box-shadow:0 0 8px rgba(255,20,40,.7)}
.am-row{display:flex;flex-direction:column;gap:7px}
.am-btn{display:flex;align-items:center;gap:11px;padding:11px 13px;border-radius:11px;font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--silver);background:rgba(255,255,255,.05);border:1px solid var(--line);cursor:pointer;transition:border-color .3s,background .3s,color .3s;width:100%;text-align:left}
.am-btn svg{width:15px;height:15px;flex-shrink:0;color:var(--ice)}
.am-btn:hover{border-color:rgba(255,20,40,.5);background:rgba(255,20,40,.12);color:#fff}
.am-btn--primary{background:rgba(255,20,40,.14);border-color:rgba(255,20,40,.4)}
#mp-icon-play{display:none}
/* site-player.js toggles these icons, so keep them out of the visual flow */
.sr-icon{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}

@media (max-width:900px) and (pointer:coarse){
  /* same reason as the rest of this file: no blurred layers on touch */
  #audio-ctrl{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(16,17,22,.92)}
  #audio-menu{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(11,12,16,.97)}
}


/* ════════════════════════════════════════════════════════════
   NAV MENU (hamburger + overlay)
   Same component as the homepage. Unlike there, it shows at every
   width on sub-pages, because it replaces the old "back to site"
   button rather than collapsing a row of section links.
   ════════════════════════════════════════════════════════════ */
.hamburger{display:flex;flex-direction:column;gap:5px;padding:12px;background:none;border:0;cursor:pointer}
.hamburger span{display:block;width:22px;height:1.5px;background:var(--silver);transition:transform .35s var(--ease),opacity .3s}
.hamburger.open span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
.hamburger.open span:nth-child(2){opacity:0}
.hamburger.open span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}

/* Below the nav (z-index 100), exactly like the homepage, where #nav is 12
   and #mmenu is 11. If the overlay covers the header the hamburger goes
   with it, and the X you close with is buried under the menu. */
/* The overlay used to be justify-content:center with overflow visible. With
   twelve links on a landscape phone that put up to six of them at negative
   offsets, off the top of the screen, with no way to scroll to them: a
   centred flex column that overflows is unreachable in both directions.
   safe center keeps it centred while it fits and falls back to flex-start
   once it does not, so overflow scrolls normally. overscroll-behavior
   stops that scroll chaining into the page behind it. */
#mmenu{position:fixed;inset:0;z-index:90;background:rgba(5,5,8,.92);backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);display:flex;flex-direction:column;align-items:center;justify-content:center;justify-content:safe center;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:78px 20px 34px;gap:8px;opacity:0;visibility:hidden;transition:opacity .45s var(--ease),visibility .45s}
#mmenu.open{opacity:1;visibility:visible}
#mmenu .nav-link{font-family:'IBM Plex Mono',monospace;font-size:14px;letter-spacing:.3em;text-transform:uppercase;color:var(--muted);text-decoration:none;background:none;border:0;cursor:pointer;padding:14px;transition:color .35s}
#mmenu .nav-link:hover{color:var(--ice)}
.mmenu-discord{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.3em;text-transform:uppercase;color:var(--ice);text-decoration:none;margin-top:22px;border:1px solid rgba(255,20,40,.4);padding:14px 28px;border-radius:999px}
.mmenu-discord:hover{background:rgba(255,20,40,.12)}

/* The overlay is fixed and blurred, so on touch it gets the same treatment as
   every other blurred layer here: opaque instead, no per-frame re-sampling. */
@media (max-width:900px) and (pointer:coarse){
  #mmenu{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(5,5,8,.985)}
}

/* ── shared closing CTA block ────────────────────────────────────────────
   Lives here, not in packs.css, because pricing and reviews use it too and
   neither of those loads packs.css. They were rendering it as bare links. */
.pk-foot{margin:56px 0 10px;padding:34px 30px;text-align:center;
  border:1px solid var(--line);border-radius:18px;background:rgba(16,17,22,.5)}
.pk-foot h2{font-family:'Unbounded',sans-serif;font-weight:200;font-size:22px;
  color:var(--silver);margin:0 0 10px;letter-spacing:-.01em}
.pk-foot p{color:var(--muted);max-width:52ch;margin:0 auto;line-height:1.7;font-size:15px}
.pk-foot-actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:22px}
.pk-cta{display:inline-block;font-family:'IBM Plex Mono',monospace;
  font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:#fff;
  text-decoration:none;border:1px solid rgba(255,20,40,.6);border-radius:999px;
  padding:12px 24px;transition:background .3s var(--ease),color .3s var(--ease)}
.pk-cta:hover{background:rgba(255,20,40,.14)}
.pk-cta--ghost{border-color:rgba(233,234,239,.2);color:var(--muted)}
.pk-cta--ghost:hover{background:rgba(255,255,255,.04);color:var(--silver)}
@media (max-width:640px){
  .pk-foot{margin:38px 0 6px;padding:26px 20px}
  .pk-foot h2{font-size:18px}
  .pk-foot p{font-size:14px}
  .pk-foot-actions{gap:9px;margin-top:18px}
  .pk-cta{padding:11px 18px;font-size:10px;letter-spacing:.16em}
}

/* ── logo shine ──────────────────────────────────────────────────────────
   The same white sweep the loader runs across the logo, and the same one
   baked into the Discord embed thumbnail, so the mark behaves consistently
   wherever it appears.

   The overlay is masked to logo.png's own alpha. Without that the band would
   show as a rectangle over the transparent corners instead of tracking the
   artwork.

   This animates background-position, which does repaint, unlike the star
   field which is opacity only. That is deliberate: the element is 30x30, so
   the repaint is ~900px and costs nothing measurable, and it is the same
   technique loadShine already uses on the loader. Doing it transform-only
   would need a second wrapper element on every page to separate the moving
   band from the mask, which is not worth it at this size.                */
.logo { position: relative; }
.logo::after {
  content: ''; position: absolute; left: 0; top: 50%;
  /* logo.png is 16:9 and .logo-img is height-constrained to 30px, so the mark
     renders ~53px wide. A 30px overlay only covered its left third. */
  width: 54px; height: 30px; transform: translateY(-50%);
  pointer-events: none;
  background: linear-gradient(115deg,
    transparent 40%, rgba(255,255,255,.85) 50%, transparent 60%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  -webkit-mask: url(/logo.png) center / contain no-repeat;
          mask: url(/logo.png) center / contain no-repeat;
  mix-blend-mode: screen;
  animation: logoShine 4.5s ease-in-out infinite;
}
/* Sweeps across, then waits, so it reads as an occasional glint rather than
   a constantly moving nav. */
@keyframes logoShine {
  0%   { background-position: 190% 0; }
  35%  { background-position: -90% 0; }
  100% { background-position: -90% 0; }
}

/* ════════════════════════════════════════════════════════════
   ENTRY LOADER (sub-pages)

   The same screen the homepage shows, for people who arrive straight
   on /packs or /pricing from a Discord button. They were getting the
   site with no warning that music starts, which for commercial tracks
   is worse than the usual autoplay surprise. The homepage already
   said "Music will play on entry"; these pages never did.

   Ported verbatim from meridian.css apart from one omission: the
   WebGL gun canvas. That needs three.js, 121KB plus GPU setup, and
   loading it on every sub-page to decorate a splash screen would undo
   most of the weight work. The logo plate, its glow and the shine
   sweep carry the same identity on their own.
   ════════════════════════════════════════════════════════════ */
/* z-index 50 is right on the homepage, whose nav sits at 12. These pages put
   the nav at 100 and the music player higher still, so at 50 the loader
   covered the page but left the nav, the audio control and the hamburger
   sitting on top of it, all clickable. 9500 clears everything here except
   the skip link. */
#enter-screen{position:fixed;inset:0;z-index:9500;background:var(--void);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:30px;transition:opacity 1s var(--ease),visibility 1s}
#enter-screen.done,#enter-screen.hidden{opacity:0;visibility:hidden}
#loaderGun{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:0}
#loadLogo{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:1;width:clamp(72px,12vw,110px);height:auto;border-radius:14px;filter:drop-shadow(0 0 26px rgba(255,20,40,.35));opacity:0;pointer-events:none}
/* WebGL unavailable, blocked, or the CDN did not answer: hide the canvas and
   show the still logo instead, so the screen still looks deliberate. */
#enter-screen.fallback #loaderGun{display:none}
#enter-screen.fallback #loadLogo{opacity:1}
#loadScrim{position:absolute;inset:0;z-index:1;pointer-events:none;background:radial-gradient(ellipse 62% 54% at 50% 50%,rgba(5,5,8,.78),rgba(5,5,8,.4) 58%,transparent 100%)}
#loadContent{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:30px}
.load-logo-wrap{position:relative;display:inline-flex;align-items:center;justify-content:center;margin-bottom:-6px;isolation:isolate}
.load-underglow{position:absolute;left:50%;bottom:-26%;width:140%;height:62%;transform:translateX(-50%);pointer-events:none;z-index:-1;background:radial-gradient(ellipse at center,rgba(255,20,40,.92),rgba(255,20,40,.3) 46%,transparent 72%);filter:blur(11px);animation:loadUnder 2.4s ease-in-out infinite}
.load-plate{position:relative;display:inline-block;line-height:0;border-radius:14px;overflow:hidden;filter:drop-shadow(0 0 18px rgba(255,20,40,.45));animation:loadPulse 2.4s ease-in-out infinite}
.load-logo{width:clamp(62px,9vw,92px);height:auto;border-radius:14px;display:block}
.load-shine{position:absolute;inset:0;pointer-events:none;background:linear-gradient(115deg,transparent 38%,rgba(255,255,255,.92) 50%,transparent 62%);background-size:280% 100%;background-repeat:no-repeat;background-position:160% 0;mix-blend-mode:screen;animation:loadShine 3.6s ease-in-out infinite}
@keyframes loadShine{0%{background-position:160% 0}40%{background-position:-60% 0}100%{background-position:-60% 0}}
@keyframes loadUnder{0%,100%{opacity:.5;transform:translateX(-50%) scaleX(.9)}50%{opacity:1;transform:translateX(-50%) scaleX(1.12)}}
@keyframes loadPulse{0%,100%{filter:drop-shadow(0 0 15px rgba(255,20,40,.4))}50%{filter:drop-shadow(0 0 34px rgba(255,20,40,.8))}}
#loadMark{font-family:'Unbounded',sans-serif;font-weight:200;font-size:clamp(26px,5vw,44px);letter-spacing:.42em;text-indent:.42em}
#loadMark i{font-style:normal;color:var(--ice)}
#loadBar{width:min(320px,60vw);height:1px;background:var(--line);position:relative}
#loadFill{position:absolute;inset:0;background:var(--ice);transform-origin:left;transform:scaleX(0);box-shadow:0 0 18px var(--ice)}
#loadMeta{display:flex;justify-content:space-between;width:min(320px,60vw);font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;color:var(--muted)}
#enterBtn{opacity:0;visibility:hidden;transform:translateY(14px);transition:opacity .7s var(--ease),transform .7s var(--ease),border-color .4s,background .4s,box-shadow .4s,visibility .7s;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.34em;text-transform:uppercase;padding:18px 44px;border-radius:999px;color:var(--silver);background:rgba(11,12,16,.55);border:1px solid rgba(255,255,255,.18);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);box-shadow:0 8px 26px rgba(0,0,0,.5)}
#enterBtn.ready{opacity:1;visibility:visible;transform:translateY(0)}
#enterBtn:hover{background:rgba(255,20,40,.16);border-color:rgba(255,20,40,.6);color:#fff;box-shadow:0 0 30px rgba(255,20,40,.32)}
#loadHint{font-family:'IBM Plex Mono',monospace;font-size:9px;letter-spacing:.4em;color:var(--muted);text-transform:uppercase;opacity:0;transition:opacity .7s var(--ease) .15s}
#enter-screen .show-hint #loadHint,#enterBtn.ready~#loadHint{opacity:1}
.load-underglow{ background:radial-gradient(ellipse at center,rgba(255,20,40,.92),rgba(255,20,40,.3) 46%,transparent 72%); }
.load-plate{ filter:drop-shadow(0 0 18px rgba(255,20,40,.5)); }
@keyframes loadUnder{0%,100%{opacity:.5;transform:translateX(-50%) scaleX(.9)}50%{opacity:1;transform:translateX(-50%) scaleX(1.12)}}
@keyframes loadPulse{0%,100%{filter:drop-shadow(0 0 15px rgba(255,20,40,.45))}50%{filter:drop-shadow(0 0 34px rgba(255,20,40,.85))}}

/* ── the audio button shows its own state ────────────────────────────────
   The word "AUDIO" is gone from the dropdown; the caret carries it. In its
   place the toggle shows a speaker: with sound waves while the music plays,
   struck through when it is muted. One glance, no reading.

   Driven entirely off #audio-ctrl.is-muted, which the homepage player and the
   sub-page player both already maintain — no JS change, and no second source
   of truth to fall out of step. */
.ac-ico{width:17px;height:17px;display:none;flex:0 0 auto}
.ac-ico--on{display:block}
#audio-ctrl.is-muted .ac-ico--on{display:none}
#audio-ctrl.is-muted .ac-ico--off{display:block}
/* Both states occupy the same width so the nav does not shuffle sideways
   every time somebody mutes. */
#sound-toggle{justify-content:center;min-width:40px}
/* Muted is a state, not an error, but it should read as "off" rather than
   sitting the same grey as the idle button. */
#audio-ctrl.is-muted #sound-toggle{color:#6f717b}
