/* =========================================================================
   LOUD — landing page
   Plain hand-written CSS. No build step. Square corners everywhere.
   All fonts self-hosted. All motion gated on prefers-reduced-motion.

   The flypost language: nothing sits straight. Display type is Anton sheared
   -10deg, every block carries a small rotation, and colour "echoes" sit
   behind the headline like a misprint. Those three moves are the whole kit —
   see the MECHANICS block below before adding a fourth.
   ========================================================================= */

/* ----------------------------- Fonts (self-hosted) ----------------------- */
@font-face {
  font-family: "Anton";
  src: url("assets/fonts/anton-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/archivo-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/archivo-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/archivo-800.woff2") format("woff2");
  font-weight: 800; font-style: normal; font-display: swap;
}

/* --------------------------------- Tokens -------------------------------- */
:root {
  --ink:      #0A0A0C;
  --band:     #16151C;
  --text:     #FFFFFF;
  --muted:    rgba(255,255,255,0.60);
  --faint:    rgba(255,255,255,0.35);
  --hair:     rgba(255,255,255,0.12);
  --yellow:   #FFC400;
  --magenta:  #E9008F;
  --cyan:     #00C2FF;

  --wrap: 1280px;
  --pad: clamp(20px, 4vw, 48px);
}

/* --------------------------------- Reset --------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; border-radius: 0; }

html { -webkit-text-size-adjust: 100%; }
body {
  background:
    radial-gradient(60% 40% at 85% 5%,  rgba(233,0,143,0.28), rgba(233,0,143,0) 60%),
    radial-gradient(50% 30% at 5% 45%,  rgba(0,194,255,0.14), rgba(0,194,255,0) 60%),
    var(--ink);
  background-repeat: no-repeat;
  color: var(--text);
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 400;
  line-height: 1.5;
  overflow-x: clip;            /* skew/rotate must never scroll the page */
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: var(--yellow); }
a:hover { color: var(--text); }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--pad); }

.skip-link {
  position: absolute; left: -9999px;
  background: var(--yellow); color: var(--ink);
  font-weight: 800; padding: 10px 16px; z-index: 10;
}
.skip-link:focus { left: 12px; top: 12px; }

:focus-visible { outline: 3px solid var(--cyan); outline-offset: 3px; }

/* ------------------------------- MECHANICS -------------------------------
   .dw     display line: Anton, uppercase, sheared. The shear is the brand.
   .echo   the misprint. An aria-hidden duplicate sits behind the real text,
           offset a few px in cyan or magenta. It must be a real element and
           not a text-shadow wherever the text wraps, because a shadow tracks
           every line box and the offset stops reading as one printing plate.
   .stick  a slapped sticker: solid fill, no radius, small rotation.
   .tape   translucent strip of packing tape across a corner.
   .ticks  the dashed progress bar — a repeating gradient, not a solid fill.
   ------------------------------------------------------------------------ */
.dw {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 0.82;
  transform: skewX(-10deg);
}

.echo-wrap { position: relative; display: inline-block; }
.echo {
  position: absolute; inset: 0;
  pointer-events: none;
  user-select: none;
}
.echo--cyan    { color: var(--cyan);    opacity: 0.55; translate: -5px -4px; }
.echo--magenta { color: var(--magenta); opacity: 0.55; translate:  5px  4px; }
.echo-top { position: relative; }

.stick {
  display: inline-block;
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  letter-spacing: 0.1em;
  background: var(--yellow); color: var(--ink);
  padding: 4px 10px;
}
.stick--cyan    { background: var(--cyan);    color: var(--ink); }
.stick--magenta { background: var(--magenta); color: #fff; }
.stick--white   { background: #fff;           color: var(--ink); font-family: "Archivo", system-ui, sans-serif; font-weight: 800; letter-spacing: 0.06em; }

.tape {
  position: absolute;
  background: rgba(255,255,255,0.28);
  width: 64px; height: 22px;
}

.ticks {
  height: 5px;
  background: repeating-linear-gradient(90deg, rgba(255,255,255,0.20) 0 8px, transparent 8px 13px);
}
.ticks > i {
  display: block; height: 100%;
  background: repeating-linear-gradient(90deg, var(--yellow) 0 8px, transparent 8px 13px);
}

/* Every rotation on the page routes through this custom property so the
   reduced-motion / narrow-viewport rules at the bottom can flatten the lot
   in two declarations instead of hunting each one down. */
[data-rot] { transform: rotate(var(--rot, 0deg)); }

/* ------------------------------- Site header ------------------------------ */
.site-header { position: relative; z-index: 5; }
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding-block: 26px;
}

.logo {
  position: relative;
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 22px; letter-spacing: 0.16em;
  color: var(--yellow);
  text-decoration: none;
  --rot: -2deg;
}
.logo .echo { color: var(--cyan); opacity: 0.5; translate: 2px -2px; }
.logo:hover { color: var(--yellow); }

.nav { display: flex; gap: 32px; align-items: center; }
.nav a {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 13px; letter-spacing: 0.22em;
  color: var(--muted); text-decoration: none;
}
.nav a:hover { color: var(--text); }
.nav .btn { color: var(--ink); }

.btn {
  display: inline-block;
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  letter-spacing: 0.1em;
  text-decoration: none;
  background: var(--yellow); color: var(--ink);
  padding: 8px 16px;
  --rot: 2deg;
}
.btn:hover { background: #fff; color: var(--ink); }
.btn--big  { font-size: clamp(17px, 2vw, 20px); letter-spacing: 0.06em; padding: 14px 26px; --rot: -1.5deg; }
.btn--ghost {
  background: none; color: var(--text);
  border: 3px solid #fff; padding: 11px 26px; --rot: 1deg;
}
.btn--ghost:hover { background: #fff; color: var(--ink); }

/* The nav collapses to a toggle under 860px. */
.nav-toggle {
  display: none;
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 13px; letter-spacing: 0.22em;
  background: none; border: 2px solid var(--faint); color: var(--text);
  padding: 8px 14px; cursor: pointer;
}

/* ---------------------------------- Hero ---------------------------------- */
.hero {
  display: flex; align-items: center; gap: 40px;
  padding-block: 40px 72px;
}
.hero-copy { flex: 1; min-width: 0; }

.hero h1 {
  font-size: clamp(52px, 9vw, 120px);
  --rot: -2deg;
  transform: rotate(var(--rot)) skewX(-10deg);
  transform-origin: left center;
}
.hero h1 .loud { color: var(--yellow); }

.hero-tag { margin-top: 34px; --rot: -1deg; }
.hero-tag .stick { font-size: clamp(13px, 1.6vw, 16px); padding: 6px 14px; }

/* Scoped to the lede by class, NOT `.hero p`. The phone mock lives inside
   .hero too, so a bare descendant selector reached into the artboard and
   restyled the artist sticker: muted white text on a white background (so it
   vanished), font-size in px (so `top` in em stopped scaling with --pw and the
   sticker landed 90px low, over the transport), and a 480px max-width. A
   selector that broad inside a container holding a drawn UI will keep finding
   new things to break. */
.hero-lede {
  margin-top: 16px; max-width: 480px;
  font-size: 16px; font-weight: 600; line-height: 1.5;
  color: var(--muted);
}
.hero-cta { margin-top: 30px; display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }

/* --------------------------------- Phones ---------------------------------
   Drawn in CSS rather than shipped as images: they are flat colour and type,
   so bitmaps would only add bytes and a re-encode step for every copy change.

   ONE coordinate space, 390x844, for every screen on the page. The hero used
   to be cut against 340x700 with its own bespoke .phone-* classes while the
   screens strip used 390x844 — two systems drawing the same app, which meant
   any change to the design had to be made twice and in different units. Now
   --pw is the only thing that varies and everything inside is em, so a screen
   keeps its designed proportions at any size.

   Border and radius are the artboard's own (2px / 28px), not a stylised
   handset.
   ------------------------------------------------------------------------ */
.phone-tilt { flex: none; }

.phone {
  --pw: 340px;
  --pwref: 390;                        /* the artboard's own width */

  /* ONE ARTBOARD PIXEL. Every offset in the screen below is written as the
     design's own number times this, so the CSS reads as the artboard does and
     nothing has to be divided by 16 by hand.

     It replaces sizing those offsets in `em`, which has a trap that is easy to
     walk into twice: `top`, `left` and `bottom` in em resolve against the
     element's OWN font-size, so any element that set both — a caption at
     `font-size: 0.6875em` positioned at `bottom: 4em` — silently landed at 69%
     of where it was meant to. --u depends on nothing but --pw. */
  --u: calc(var(--pw) / var(--pwref));

  position: relative;
  width: var(--pw);
  aspect-ratio: 390 / 844;
  flex: none;
  background: var(--ink);
  border: 2px solid var(--hair);
  border-radius: 28px;
  overflow: hidden;
  font-size: calc(16 * var(--u));      /* the strip's screens still scale in em */
}
/* ------------------------- Now Playing (the hero) --------------------------
   The 1c artboard, whole, at its designed 390x844. Every number below is the
   value straight off the artboard, multiplied by --u (one artboard pixel), so
   the screen holds its proportions at any --pw and nothing here depends on an
   element's own font-size. See --u on .phone for why that matters.
   ------------------------------------------------------------------------ */
.phone--now {
  background:
    radial-gradient(120% 60% at 90% 0%,  rgba(233,0,143,0.30), rgba(233,0,143,0) 60%),
    radial-gradient(100% 50% at 0% 100%, rgba(0,194,255,0.14), rgba(0,194,255,0) 60%),
    var(--ink);
  box-shadow: 24px 24px 0 rgba(233,0,143,0.25);
}

.now-mark {
  position: absolute; left: calc(24 * var(--u)); top: calc(22 * var(--u));
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: calc(15 * var(--u)); letter-spacing: 0.22em; color: var(--yellow);
  transform: rotate(-2deg);
}
.now-dials {
  position: absolute; right: calc(20 * var(--u)); top: calc(16 * var(--u));
  font-size: calc(13 * var(--u)); letter-spacing: 0.1em;
  padding: calc(5 * var(--u)) calc(10 * var(--u));
  transform: rotate(4deg);
}

.now-art {
  position: absolute; left: calc(38 * var(--u)); top: calc(70 * var(--u));
  width: calc(305 * var(--u)); height: calc(305 * var(--u));
  transform: rotate(-3deg);
}
.now-art > .art {
  position: relative;
  width: 100%; height: 100%;
  background: linear-gradient(135deg, var(--magenta) -20%, var(--ink) 55%, var(--cyan) 130%);
  border: calc(2 * var(--u)) solid var(--hair);
  display: flex; align-items: flex-end; padding: calc(16 * var(--u));
}
.now-art .art .init {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: calc(64 * var(--u)); line-height: 0.8; color: rgba(255,255,255,0.25);
  transform: skewX(-10deg);
}

/* THE SPECTRUM — the app's 8-bit analyzer, open on the hero's sleeve.
   Twelve bands on a scrim so the cover reads through; 20-unit cell pitch
   (16 fill + 4 gap); cyan cells fixed at the floor, yellow above, one
   magenta peak cap riding each column. The columns JUMP between cell
   heights — steps(1), nothing eases — because in the app the levels are
   quantised to cells from the real audio, and easing here would sell a
   smoothness the product deliberately does not have. */
.vz { position: absolute; inset: 0; background: rgba(10, 10, 12, 0.45); }
.vz-row {
  position: absolute;
  left: calc(10 * var(--u)); right: calc(10 * var(--u)); bottom: calc(10 * var(--u));
  height: calc(240 * var(--u));
  display: flex; gap: calc(4 * var(--u)); align-items: flex-end;
}
.vz-row i { flex: 1; display: flex; flex-direction: column; animation: vzB 1.7s steps(1, end) infinite; }
.vz-row i::before {
  content: ''; height: calc(16 * var(--u)); flex: none;
  background: var(--magenta); opacity: 0.95;
}
.vz-row i::after {
  content: ''; flex: 1;
  background-image:
    repeating-linear-gradient(to top, rgba(255, 196, 0, 0.9) 0 calc(16 * var(--u)), transparent calc(16 * var(--u)) calc(20 * var(--u))),
    repeating-linear-gradient(to top, rgba(0, 194, 255, 0.9) 0 calc(16 * var(--u)), transparent calc(16 * var(--u)) calc(20 * var(--u)));
  background-position: top, bottom;
  background-repeat: no-repeat;
  background-size: 100% max(0px, calc(100% - calc(80 * var(--u)))), 100% calc(80 * var(--u));
}
.vz-row i:nth-child(1)  { animation: vzD 1.9s steps(1, end) infinite; }
.vz-row i:nth-child(2)  { animation: vzB 1.7s steps(1, end) -0.3s infinite; }
.vz-row i:nth-child(3)  { animation: vzB 2.3s steps(1, end) -0.9s infinite; }
.vz-row i:nth-child(4)  { animation: vzA 1.3s steps(1, end) -0.7s infinite; }
.vz-row i:nth-child(5)  { animation: vzC 1.9s steps(1, end) -0.5s infinite; }
.vz-row i:nth-child(6)  { animation: vzA 2.3s steps(1, end) -1.1s infinite; }
.vz-row i:nth-child(7)  { animation: vzC 1.7s steps(1, end) -1.3s infinite; }
.vz-row i:nth-child(8)  { animation: vzA 2.9s steps(1, end) -0.2s infinite; }
.vz-row i:nth-child(9)  { animation: vzC 2.3s steps(1, end) -1.7s infinite; }
.vz-row i:nth-child(10) { animation: vzB 1.9s steps(1, end) -1.1s infinite; }
.vz-row i:nth-child(11) { animation: vzD 1.3s steps(1, end) -0.4s infinite; }
.vz-row i:nth-child(12) { animation: vzD 2.3s steps(1, end) -1.5s infinite; }
@keyframes vzA { 0%, 100% { height: calc(120 * var(--u)); } 12% { height: calc(180 * var(--u)); } 24% { height: calc(80 * var(--u)); }  36% { height: calc(220 * var(--u)); } 50% { height: calc(140 * var(--u)); } 62% { height: calc(240 * var(--u)); } 74% { height: calc(100 * var(--u)); } 86% { height: calc(160 * var(--u)); } }
@keyframes vzB { 0%, 100% { height: calc(60 * var(--u)); }  15% { height: calc(140 * var(--u)); } 30% { height: calc(200 * var(--u)); } 45% { height: calc(100 * var(--u)); } 60% { height: calc(160 * var(--u)); } 75% { height: calc(40 * var(--u)); }  90% { height: calc(120 * var(--u)); } }
@keyframes vzC { 0%, 100% { height: calc(200 * var(--u)); } 10% { height: calc(140 * var(--u)); } 25% { height: calc(240 * var(--u)); } 40% { height: calc(160 * var(--u)); } 55% { height: calc(220 * var(--u)); } 70% { height: calc(120 * var(--u)); } 85% { height: calc(180 * var(--u)); } }
@keyframes vzD { 0%, 100% { height: calc(40 * var(--u)); }  14% { height: calc(100 * var(--u)); } 28% { height: calc(60 * var(--u)); }  42% { height: calc(160 * var(--u)); } 58% { height: calc(80 * var(--u)); }  72% { height: calc(140 * var(--u)); } 88% { height: calc(40 * var(--u)); } }

/* The five-bar chip on the sleeve corner — the spectrum's toggle in the app,
   drawn here in its INVERTED (open) state: yellow plate, ink bars. */
.bars {
  position: absolute; right: calc(12 * var(--u)); bottom: calc(12 * var(--u));
  display: flex; align-items: flex-end; gap: calc(3 * var(--u));
  height: calc(26 * var(--u)); padding: calc(5 * var(--u)) calc(6 * var(--u));
  background: var(--yellow);
}
.bars i { display: block; width: calc(4 * var(--u)); background: var(--ink); }
.bars i:nth-child(1) { height: 45%; }
.bars i:nth-child(2) { height: 80%; }
.bars i:nth-child(3) { height: 100%; }
.bars i:nth-child(4) { height: 60%; }
.bars i:nth-child(5) { height: 35%; }
/* Two strips, opposite corners — the flyer is taped down, not floating. */
.now-art .tape { width: calc(64 * var(--u)); height: calc(22 * var(--u)); transform: rotate(-45deg); }
.now-art .tape:nth-of-type(1) { left: calc(-32 * var(--u)); top: calc(-11 * var(--u)); }
.now-art .tape:nth-of-type(2) { right: calc(-32 * var(--u)); bottom: calc(-11 * var(--u)); }

.now-title {
  position: absolute; left: calc(14 * var(--u)); top: calc(412 * var(--u));
  background: var(--yellow); color: var(--ink);
  padding: calc(8 * var(--u)) calc(16 * var(--u)) calc(10 * var(--u));
  transform: rotate(1.5deg);
}
.now-title span {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: calc(38 * var(--u)); line-height: 0.8; text-transform: uppercase; letter-spacing: -0.02em;
}
/* Two metadata objects, as the app draws them now: who made it on the white
   sticker, which record on the cyan outline. One line with a separator had to
   truncate to hold both, and these do not. */
.now-artist {
  position: absolute; left: calc(26 * var(--u)); top: calc(474 * var(--u));
  background: #fff; color: var(--ink);
  padding: calc(4 * var(--u)) calc(10 * var(--u));
  transform: rotate(-1.2deg);
  font-size: calc(13 * var(--u)); font-weight: 800; white-space: nowrap;
}
.now-album {
  position: absolute; left: calc(30 * var(--u)); top: calc(505 * var(--u));
  color: var(--cyan);
  box-shadow: inset 0 0 0 calc(2 * var(--u)) var(--cyan);
  padding: calc(3 * var(--u)) calc(9 * var(--u));
  transform: rotate(0.8deg);
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: calc(12 * var(--u)); letter-spacing: 0.08em; white-space: nowrap;
}

.now-bar {
  position: absolute; left: calc(24 * var(--u)); top: calc(540 * var(--u));
  width: calc(330 * var(--u)); transform: rotate(-1deg);
}
.now-bar .ticks { height: calc(5 * var(--u)); }
.now-bar .times {
  display: flex; justify-content: space-between; margin-top: calc(6 * var(--u));
  font-size: calc(12 * var(--u)); font-weight: 600; color: rgba(255,255,255,0.5);
  font-variant-numeric: tabular-nums;
}

.now-controls {
  position: absolute; left: calc(24 * var(--u)); right: calc(24 * var(--u)); bottom: calc(104 * var(--u));
  display: flex; align-items: center; justify-content: space-between;
}
.ctl {
  width: calc(72 * var(--u)); height: calc(72 * var(--u));
  border: calc(3 * var(--u)) solid #fff;
  display: flex; align-items: center; justify-content: center;
}
.ctl-inner { display: flex; transform: skewX(-10deg); }
.ctl-inner .bar { width: calc(5 * var(--u)); height: calc(26 * var(--u)); background: #fff; }
.ctl-inner .tri { width: calc(20 * var(--u)); height: calc(26 * var(--u)); background: #fff; }
.tri--prev { clip-path: polygon(100% 0, 0 50%, 100% 100%); }
.tri--next { clip-path: polygon(0 0, 100% 50%, 0 100%); }
.ctl--play { width: calc(120 * var(--u)); height: calc(120 * var(--u)); background: var(--yellow); border: 0; }
.ctl--play .pause { display: flex; gap: calc(10 * var(--u)); transform: skewX(-10deg); }
.ctl--play .pause i { display: block; width: calc(15 * var(--u)); height: calc(56 * var(--u)); background: var(--ink); }

.now-shuffle {
  position: absolute; left: calc(24 * var(--u)); bottom: calc(64 * var(--u));
  font-size: calc(11 * var(--u)); letter-spacing: 0.14em;
  padding: calc(4 * var(--u)) calc(8 * var(--u));
}
.now-feet {
  position: absolute; left: 0; right: 0; bottom: calc(24 * var(--u));
  display: flex; justify-content: space-between; padding: 0 calc(24 * var(--u));
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: calc(14 * var(--u)); color: var(--faint);
}
.now-feet .l { transform: rotate(-2deg)  skewX(-10deg); }
.now-feet .r { transform: rotate(1.5deg) skewX(-10deg); }

/* -------------------------------- Sections -------------------------------- */
.section { padding-block: 56px 64px; border-top: 2px solid var(--hair); }
.section > .wrap > h2 {
  font-size: clamp(34px, 5vw, 48px);
  --rot: -1.2deg;
  transform: rotate(var(--rot)) skewX(-10deg);
  transform-origin: left center;
}

.cards {
  margin-top: 36px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px;
}
.card {
  border: 2px solid rgba(255,255,255,0.14);
  padding: 24px;
  background: rgba(255,255,255,0.02);
}
.card:nth-child(1) { --rot: -0.8deg; }
.card:nth-child(2) { --rot:  0.7deg; }
.card:nth-child(3) { --rot: -0.5deg; }
.card .stick { font-size: 14px; }
.card p { margin-top: 14px; font-size: 14px; font-weight: 600; line-height: 1.5; color: rgba(255,255,255,0.65); }

/* Screens strip — the nav promises SCREENS, so it has to land somewhere. */
.screens { margin-top: 36px; display: flex; gap: clamp(20px, 4vw, 44px); flex-wrap: wrap; }
.screens figure { display: flex; flex-direction: column; gap: 12px; }
.screens .phone { --pw: 260px; box-shadow: 16px 16px 0 rgba(0,194,255,0.18); }
.screens figcaption {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 13px; letter-spacing: 0.22em; color: var(--muted);
}

/* ---------------------------- Also from Grunt -----------------------------
   The sibling strip: Stray's page carries the mirror of this, pointing back
   at LOUD. Thin on purpose — it follows the stores and must not compete. */
.sibling-inner { display: flex; align-items: center; gap: 32px; flex-wrap: wrap; }
.sibling-copy { flex: 1 1 420px; }
.sibling-eyebrow { font-size: 13px; letter-spacing: 0.14em; }
.sibling-title {
  margin-top: 16px;
  font-size: clamp(34px, 5vw, 44px);
  transform: rotate(-1.2deg) skewX(-10deg);
  transform-origin: left center;
  text-shadow: 4px 0 0 var(--cyan);
}
.sibling-tag { margin-top: 14px; display: inline-block; }
.sibling-tag .stick { font-size: 12px; }
.sibling-body { margin-top: 12px; max-width: 54ch; font-size: 14px; font-weight: 600; line-height: 1.5; color: rgba(255,255,255,0.65); }
.sibling-btn { flex: 0 0 auto; }

/* --------------------------------- Footer --------------------------------- */
.site-footer {
  display: flex; justify-content: space-between; align-items: center;
  gap: 20px; flex-wrap: wrap;
  padding-block: 24px; border-top: 2px solid var(--hair);
}
.site-footer small { font-size: 12px; font-weight: 600; color: var(--faint); }
.site-footer nav { display: flex; gap: 24px; }
.site-footer a {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 12px; letter-spacing: 0.22em; color: rgba(255,255,255,0.5);
  text-decoration: none;
}
.site-footer a:hover { color: var(--text); }

/* ---------------------------- Screen variants -----------------------------
   Each artboard's own backdrop. The geometry is inherited from .phone.
   ------------------------------------------------------------------------ */
.phone--list, .phone--posters, .phone--crates {
  box-shadow: 16px 16px 0 rgba(0,194,255,0.18);
}
.phone--list    { background: radial-gradient(120% 55% at 10% 0%, rgba(233,0,143,0.24), rgba(233,0,143,0) 60%), var(--ink); }
.phone--crates  { background: radial-gradient(120% 55% at 85% 0%, rgba(233,0,143,0.26), rgba(233,0,143,0) 60%), var(--ink); }
.phone--posters {
  background:
    radial-gradient(120% 55% at 90% 100%, rgba(233,0,143,0.22), rgba(233,0,143,0) 60%),
    radial-gradient(90% 40% at 0% 0%,     rgba(0,194,255,0.12), rgba(0,194,255,0) 60%),
    var(--ink);
}

.scr { position: absolute; inset: 0; padding: 1.5em; display: flex; flex-direction: column; overflow: hidden; }
.scr-head { display: flex; justify-content: space-between; align-items: flex-start; }

/* --sh is the misprint colour. A text-shadow is right here and wrong in the
   hero: these titles are always one line, so there is no wrap for the offset
   to break apart on, and a shadow costs no extra element. */
.scr-title {
  font-size: 3.5em;
  transform: rotate(-2deg) skewX(-10deg);
  transform-origin: left center;
  text-shadow: 4px 0 0 var(--sh, var(--cyan));
}
.scr-shuffle { font-size: 0.8125em; letter-spacing: 0.08em; padding: 0.375em 0.625em; margin-top: 0.375em; }
.scr-new {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 0.8125em; letter-spacing: 0.28em; color: var(--yellow);
  margin-top: 0.5em; transform: rotate(2deg);
}
.scr-sub { margin-top: 0.625em; font-size: 0.8125em; font-weight: 600; color: rgba(255,255,255,0.5); }

/* Track rows. Grid placement is explicit so the optional play caret on the
   current track does not shunt the other two columns along. */
.rows { list-style: none; padding: 0; margin-top: 1.125em; }
.rows li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  column-gap: 0.625em;
  align-items: center;
  padding: 0.875em 0.5em;
  border-bottom: 2px solid var(--hair);
}
.rows li > .tri  { grid-column: 1; grid-row: 1 / 3; width: 0.6875em; height: 0.875em; background: var(--yellow); transform: skewX(-10deg); }
.rows li > b     { grid-column: 2; grid-row: 1; font-size: 0.9375em; font-weight: 600; }
.rows li > em    { grid-column: 2; grid-row: 2; font-size: 0.75em; font-weight: 600; font-style: normal; color: rgba(255,255,255,0.5); }
.rows li > span  { grid-column: 3; grid-row: 1 / 3; font-size: 0.75em; font-weight: 600; color: rgba(255,255,255,0.5); }
.rows li.is-playing > b,
.rows li.is-playing > span { color: var(--yellow); }
.rows li:nth-child(1) { transform: rotate(-0.7deg); }
.rows li:nth-child(2) { transform: rotate(0.5deg)  translateX(6px); }
.rows li:nth-child(3) { transform: rotate(-0.4deg) translateX(-4px); }
.rows li:nth-child(4) { transform: rotate(0.8deg)  translateX(3px); }
.rows li:nth-child(5) { transform: rotate(-0.6deg); }
.rows li:nth-child(6) { transform: rotate(0.4deg)  translateX(8px); }
.rows li:nth-child(7) { transform: rotate(-0.9deg) translateX(-3px); }
.rows--tight { margin-top: 0.375em; }
.rows--tight li { padding: 0.75em 0; }

/* Playlists as torn flyers. The clip-path is the tear — a run of alternating
   points along the bottom edge only. */
.posters { margin-top: 1.25em; display: flex; flex-direction: column; gap: 1.125em; }
.poster { position: relative; }
.torn {
  background: var(--g);
  border: 2px solid rgba(255,255,255,0.14);
  padding: 1.25em 1.125em 1.625em;
  clip-path: polygon(0 0, 100% 0, 100% 92%, 94% 100%, 88% 93%, 80% 100%, 72% 94%, 63% 100%,
                     55% 93%, 46% 100%, 38% 94%, 29% 100%, 21% 93%, 12% 100%, 5% 94%, 0 100%);
}
.torn .dw { display: block; font-size: 2.75em; }
.torn em { display: block; margin-top: 0.5em; font-size: 0.75em; font-weight: 600; font-style: normal; color: rgba(255,255,255,0.6); }
.tag {
  position: absolute; right: 0.75em; top: -0.625em;
  border: 3px solid #fff; color: #fff; background: var(--ink);
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 0.75em; letter-spacing: 0.1em; padding: 0.25em 0.5em;
}
.tag--cyan    { border-color: var(--cyan);    color: var(--cyan); }
.tag--magenta { border-color: var(--magenta); color: var(--magenta); }

/* Crates */
.chips { margin-top: 1em; display: flex; gap: 0.75em; align-items: center; }
.chip {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 0.875em; letter-spacing: 0.06em; padding: 0.3125em 0.75em;
  border: 2px solid var(--faint); color: var(--muted);
}
.chip.is-on { background: var(--yellow); color: var(--ink); border-color: var(--yellow); }

.crates { margin-top: 1.375em; display: grid; grid-template-columns: 1fr 1fr; gap: 1.25em 1em; }
.crate { position: relative; }
.crate .sleeve { aspect-ratio: 1; background: var(--g); border: 2px solid rgba(255,255,255,0.14); }
.crate .tape { left: 50%; top: -0.5em; width: 3.25em; height: 1em; translate: -50% 0; transform: rotate(-4deg); }
.crate b  { display: block; margin-top: 0.5em; font-family: "Anton", "Archivo", system-ui, sans-serif; font-weight: 400; font-size: 1em; text-transform: uppercase; }
.crate em { display: block; font-size: 0.75em; font-weight: 600; font-style: normal; color: rgba(255,255,255,0.5); }

.heavy { align-self: flex-start; margin-top: 1.5em; font-size: 0.75em; letter-spacing: 0.14em; }

/* The letter squares — the jump tiles from My Tunes, quoted at mock scale.
   In the app every square opens an alphabet grid that jumps the list; here
   they just have to read as what they are. */
.ltile {
  align-self: flex-start;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2em; height: 2em; margin-top: 1em;
  background: var(--yellow); color: var(--ink);
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 1.125em; line-height: 1;
  transform: rotate(var(--rot, -1.5deg)) skewX(-6deg);
}
.ltile + .rows { margin-top: 0.25em; }

.phone--queue {
  background: radial-gradient(120% 55% at 90% 0%, rgba(0,194,255,0.16), rgba(0,194,255,0) 60%), var(--ink);
}

/* ------------------------- The device switch ------------------------------
   PHONE / TABLET PORTRAIT / TABLET LANDSCAPE, CSS only: three radios ahead of
   the stage, :checked deciding which mock shows and which chip reads lit. The
   radios stay real and focusable — arrow keys walk them — they are just drawn
   as zero-size, with the focus ring forwarded to the visible chip.
   Each mock carries its own --u (one artboard pixel at its reference width),
   the same system as .phone, so the app's coordinate classes keep working
   inside them. */
.devices { margin-top: 28px; }
.dev-pick { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; pointer-events: none; }

.dev-switch { display: flex; gap: 12px; flex-wrap: wrap; }
.dev-switch .chip { font-size: 13px; letter-spacing: 0.08em; padding: 8px 14px; cursor: pointer; }
#dev-phone:checked ~ .dev-switch label[for="dev-phone"],
#dev-tabp:checked  ~ .dev-switch label[for="dev-tabp"],
#dev-tabl:checked  ~ .dev-switch label[for="dev-tabl"] {
  background: var(--yellow); color: var(--ink); border-color: var(--yellow);
}
#dev-phone:focus-visible ~ .dev-switch label[for="dev-phone"],
#dev-tabp:focus-visible  ~ .dev-switch label[for="dev-tabp"],
#dev-tabl:focus-visible  ~ .dev-switch label[for="dev-tabl"] {
  outline: 3px solid var(--cyan); outline-offset: 3px;
}

.dev-stage { margin-top: 32px; min-height: 480px; }
.dev { display: none; }
#dev-phone:checked ~ .dev-stage .dev--phone,
#dev-tabp:checked  ~ .dev-stage .dev--tabp,
#dev-tabl:checked  ~ .dev-stage .dev--tabl { display: block; }

.tab {
  --u: calc(var(--tw) / var(--tref));
  position: relative;
  width: var(--tw);
  max-width: 100%;
  aspect-ratio: var(--tar);
  font-size: calc(16 * var(--u));
  background:
    radial-gradient(120% 60% at 90% 0%, rgba(233,0,143,0.24), rgba(233,0,143,0) 60%),
    var(--ink);
  border: 2px solid var(--hair);
  border-radius: 20px;
  overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.75em;
  box-shadow: 16px 16px 0 rgba(0,194,255,0.18);
}
/* --tw must hold only units that resolve the same everywhere it is used —
   px and vw, never %. A percentage inside --tw resolves against the parent's
   WIDTH where --u sizes a box and against the parent's FONT-SIZE where it
   sizes type, which turned the landscape mock into 0.3px text. */
.tab--phone { --tw: min(230px, 60vw); --tref: 390;  --tar: 390 / 780; }
.tab--port  { --tw: min(340px, 84vw); --tref: 800;  --tar: 800 / 1150; font-size: calc(26 * var(--u)); }
.tab--land  { --tw: min(620px, 88vw); --tref: 1210; --tar: 1210 / 800; font-size: calc(24 * var(--u)); flex-direction: row; align-items: stretch; gap: 0; }

.mini-art {
  width: calc(var(--as) * var(--u)); aspect-ratio: 1;
  background: linear-gradient(135deg, var(--magenta) -20%, var(--ink) 55%, var(--cyan) 130%);
  border: 2px solid var(--hair);
  transform: rotate(-3deg);
  display: flex; align-items: flex-end; padding: 0.625em;
}
.mini-art span {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 2em; line-height: 0.8; color: rgba(255,255,255,0.25); transform: skewX(-10deg);
}
.mini-title {
  background: var(--yellow); color: var(--ink);
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 1.25em; letter-spacing: -0.01em;
  padding: 0.25em 0.5em; transform: rotate(1.5deg);
}
.mini-artist {
  background: #fff; color: var(--ink);
  font-size: 0.6875em; font-weight: 800;
  padding: 0.25em 0.625em; transform: rotate(-1.2deg);
}
.mini-ctls { display: flex; align-items: center; gap: 1.25em; margin-top: 0.25em; }
.mini-ctls .tri { width: 0.875em; height: 1.125em; background: #fff; transform: skewX(-10deg); }
.mini-ctls b { position: relative; width: 2.5em; height: 2.5em; background: var(--yellow); }
.mini-ctls b::before, .mini-ctls b::after {
  content: ''; position: absolute; top: 0.625em; bottom: 0.625em; width: 0.375em;
  background: var(--ink); transform: skewX(-10deg);
}
.mini-ctls b::before { left: 0.75em; }
.mini-ctls b::after  { right: 0.75em; }

.tab-pane { flex: 1.25; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.75em; }
.tab-rail {
  flex: 1; border-left: 2px solid var(--hair);
  padding: 1.25em 1.25em 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.625em;
  overflow: hidden;
}
.rail-head {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 1.375em; letter-spacing: 0.04em; transform: skewX(-10deg);
}
.rail-stick { font-size: 0.625em; letter-spacing: 0.14em; }
.rail-rows { list-style: none; padding: 0; width: 100%; }
.rail-rows li {
  display: flex; justify-content: space-between; gap: 1em;
  font-size: 0.75em; font-weight: 600;
  padding: 0.5em 0; border-bottom: 2px solid var(--hair);
}
.rail-rows li span { color: rgba(255,255,255,0.5); }
.rail-rows li.is-playing b, .rail-rows li.is-playing span { color: var(--yellow); }

/* ------------------------------- Sections' lede --------------------------- */
.section-lede { margin-top: 18px; max-width: 640px; font-size: 15px; font-weight: 600; line-height: 1.6; color: rgba(255,255,255,0.65); }

/* --------------------------------- Stores ---------------------------------
   Both honest: neither store has it yet, and the section says so instead of
   drawing dead badges that look like buttons. */
.stores { margin-top: 36px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; max-width: 760px; }
.store {
  position: relative;
  border: 2px solid rgba(255,255,255,0.14);
  padding: 28px 24px 24px;
  background: rgba(255,255,255,0.02);
}
.store-name { display: block; font-size: 30px; transform: rotate(-1deg) skewX(-10deg); transform-origin: left center; }
.store-soon { position: absolute; right: 14px; top: -12px; font-size: 13px; letter-spacing: 0.12em; }
.store p { margin-top: 14px; font-size: 14px; font-weight: 600; line-height: 1.5; color: rgba(255,255,255,0.65); }
/* The one card with somewhere to go. A store that is merely coming has no
   button, so this is not a shared slot sitting empty — the presence of the
   button IS the difference between the two cards. */
.store-btn { margin-top: 18px; --rot: -1.2deg; }

/* ------------------------------ Legal pages -------------------------------
   privacy.html. Long-form reading in the flypost voice: the display grammar
   (shear, echo, stickers) stays on the headings, and the body text drops the
   poster tricks entirely — a privacy policy earns trust by being effortless
   to read, not by shouting. No JS on these pages, so the header nav here is
   always visible rather than behind the toggle.
   ------------------------------------------------------------------------ */
.legal-nav ul { display: flex; gap: 26px; list-style: none; margin: 0; padding: 0; }
.legal-nav a {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-size: 14px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.7); text-decoration: none;
}
.legal-nav a:hover { color: var(--text); }

.legal-head { padding-block: 48px 8px; }
.legal-eyebrow { margin: 0 0 18px; }
.legal-eyebrow .stick { font-size: 13px; letter-spacing: 0.14em; --rot: -1.5deg; transform: rotate(var(--rot)); display: inline-block; }
.legal-title {
  font-size: clamp(44px, 7vw, 76px);
  --rot: -1.2deg;
  /* Rotation AND the brand shear, stated together like .hero h1 — [data-rot]
     alone would win the cascade over .dw and rotate without shearing. */
  transform: rotate(var(--rot)) skewX(-10deg);
  transform-origin: left center;
}
.legal-title .loud { color: var(--yellow); }
.legal-updated { margin-top: 22px; font-size: 13px; font-weight: 600; letter-spacing: 0.06em; color: var(--faint); }

.legal { padding-block: 24px 72px; }
.legal-wrap { max-width: 720px; }
.legal-wrap h2 {
  font-family: "Anton", "Archivo", system-ui, sans-serif;
  font-weight: 400; text-transform: uppercase; letter-spacing: 0.01em;
  font-size: clamp(24px, 3.2vw, 32px); line-height: 1;
  transform: skewX(-10deg); transform-origin: left bottom;
  color: var(--yellow);
  margin: 52px 0 16px; padding-top: 28px;
  border-top: 2px solid var(--hair);
}
.legal-wrap h3 {
  font-size: 17px; font-weight: 800; letter-spacing: 0.01em;
  color: var(--text); margin: 28px 0 8px;
}
.legal-wrap p, .legal-wrap li { font-size: 15.5px; line-height: 1.7; color: rgba(255,255,255,0.78); }
.legal-wrap p { margin: 0 0 14px; }
.legal-wrap ul { margin: 0 0 14px; padding-left: 22px; }
.legal-wrap li { margin-bottom: 8px; }
.legal-wrap li::marker { color: var(--cyan); }
.legal-wrap strong { color: var(--text); }
.legal-wrap code {
  font-size: 0.9em; padding: 1px 6px;
  background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.12);
}
.legal-lead { font-size: 18px; font-weight: 600; color: var(--text); }
.legal-note {
  border-left: 3px solid var(--magenta);
  padding: 10px 0 10px 16px;
  color: rgba(255,255,255,0.6);
}
.legal-tablewrap { overflow-x: auto; margin: 0 0 14px; }
.legal-table { border-collapse: collapse; width: 100%; min-width: 420px; }
.legal-table th, .legal-table td {
  text-align: left; vertical-align: top;
  font-size: 14.5px; line-height: 1.55;
  padding: 10px 14px 10px 0;
  border-bottom: 1px solid var(--hair);
}
.legal-table thead th {
  font-family: "Anton", "Archivo", system-ui, sans-serif; font-weight: 400;
  text-transform: uppercase; letter-spacing: 0.1em; font-size: 12px;
  color: var(--cyan);
}
.legal-table tbody th { font-weight: 800; color: var(--text); }
.legal-table td { color: rgba(255,255,255,0.75); }

/* -------------------------------- Responsive ------------------------------ */
@media (max-width: 1080px) {
  .hero { gap: 28px; }
  .phone { --pw: 280px; }
}

@media (max-width: 860px) {
  .nav {
    display: none;
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: flex-start; gap: 0;
    background: var(--band); border-block: 2px solid var(--hair);
    padding: 8px var(--pad) 20px;
  }
  .nav a { padding-block: 14px; }
  .nav-toggle { display: block; }
  .nav-toggle[aria-expanded="true"] + .nav { display: flex; }
  .header-inner { position: relative; }

  .hero { flex-direction: column; align-items: flex-start; padding-bottom: 56px; }
  .hero-lede { max-width: none; }
  .phone { --pw: min(340px, 82vw); box-shadow: 16px 16px 0 rgba(233,0,143,0.25); }

  .cards { grid-template-columns: 1fr; }
  .stores { grid-template-columns: 1fr; }
  .dev-stage { min-height: 0; }
}

/* Under ~560px the rotations cost more legibility than they buy character:
   a -2deg shear on a 52px headline eats the gutter on a 360px screen. Keep
   the shear on the display face, drop the per-block rotation. */
@media (max-width: 560px) {
  [data-rot], .card, .hero-tag { transform: none; }
  .hero h1, .section > .wrap > h2, .legal-title { transform: skewX(-10deg); }
  /* ...but not inside a phone mock, where the jitter is the artwork. */
  .phone [data-rot] { transform: rotate(var(--rot, 0deg)); }
  .screens .phone { --pw: min(300px, 84vw); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
