/* ==========================================================================
   HEWY MICHEAUX — CONTROL CENTER
   Georgia Piedmont in early autumn, run through a control-room interface.
   Moody and earthy, not neon. The grain layer and the low-saturation blooms
   are what hold that line — they soften every glow before it reads sci-fi.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* --- The five --- */
  --char:        #28231F;   /* background            */
  --cotton:      #F4F0EB;   /* text                  */
  --stone:       #899299;   /* secondary details     */
  --muscadine:   #7F2A65;   /* signature, sparingly  */
  --sorghum:     #915E4D;   /* warm accent           */

  /* --- Derived tints for ACCENT TEXT ---
     Measured against Char #28231F:
       muscadine raw  1.79:1  ✗ never as text
       sorghum   raw  2.90:1  ✗ never as text
       these two tints instead: */
  --muscadine-lt: #C77BAB;  /* 5.07:1 ✓ */
  --sorghum-lt:   #C98E77;  /* 5.64:1 ✓ */

  /* --- Shades of Char for layering --- */
  --char-deep:  #1C1815;
  --char-lift:  #332C27;
  --char-lift2: #3E3630;

  /* --- Glass --- */
  --glass-bg:       rgba(244, 240, 235, 0.045);
  --glass-bg-hover: rgba(244, 240, 235, 0.065);
  --glass-brd:      rgba(244, 240, 235, 0.11);
  --glass-brd-hi:   rgba(244, 240, 235, 0.22);
  --blur: 18px;

  /* --- Text --- */
  --ink:     var(--cotton);                  /* 13.7:1 */
  --ink-mid: rgba(244, 240, 235, 0.72);
  --ink-dim: var(--stone);                   /*  4.91:1 */

  /* --- Type --- */
  --display: "Fraunces", Georgia, serif;
  --body:    "Archivo", system-ui, sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, monospace;

  /* Perfect-fourth scale (1.333), fluid */
  --t-xs:  0.75rem;
  --t-sm:  0.8125rem;
  --t-base: 1rem;
  --t-md:  clamp(1.1rem, 0.4vw + 1rem, 1.25rem);
  --t-lg:  clamp(1.45rem, 1vw + 1.1rem, 1.9rem);
  --t-xl:  clamp(2rem, 2.2vw + 1.2rem, 3rem);
  --t-2xl: clamp(3rem, 6vw + 1rem, 6.5rem);

  --sp: 1rem;
  --radius: 18px;
  --ease: cubic-bezier(.22, .68, 0, 1);
}

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { scroll-behavior: smooth; }

body {
  min-height: 100vh;
  background: var(--char);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { font-family: var(--display); line-height: 1.05; font-weight: 600; }
a { color: inherit; }
ul { list-style: none; padding: 0; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--muscadine-lt);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Visible to screen readers, not to eyes. Used on the email field labels. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   3. ATMOSPHERE
   Three fixed layers: blooms drift, contours sit still, grain covers all.
   -------------------------------------------------------------------------- */
.atmosphere {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* A night sky is DARKEST overhead and lifts toward the horizon, where
     the last of the day and the far-off storm still sit. The earlier
     gradient ran the other way, which flattened the moon into the murk. */
  background:
    radial-gradient(130% 50% at 50% 100%, rgba(145, 94, 77, .12) 0%, rgba(145, 94, 77, 0) 62%),
    linear-gradient(to bottom,
      #120F0D 0%,
      #191413 26%,
      #221D1A 52%,
      #2B2521 76%,
      #1F1A17 100%);
}

.bloom {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: .5;
  mix-blend-mode: screen;
  will-change: transform;
}

/* Muscadine is the signature — one bloom only, kept low and slow. */
.bloom--muscadine {
  width: 46vw; height: 46vw; min-width: 420px; min-height: 420px;
  top: -12%; left: 52%;
  background: radial-gradient(circle, rgba(127,42,101,.55) 0%, rgba(127,42,101,0) 68%);
  animation: driftA 34s var(--ease) infinite alternate;
}
.bloom--sorghum {
  width: 40vw; height: 40vw; min-width: 360px; min-height: 360px;
  top: 38%; left: -8%;
  background: radial-gradient(circle, rgba(145,94,77,.5) 0%, rgba(145,94,77,0) 68%);
  animation: driftB 44s var(--ease) infinite alternate;
}
/* Cool counterweight so the warmth doesn't go monochrome-orange. */
.bloom--stone {
  width: 34vw; height: 34vw; min-width: 300px; min-height: 300px;
  top: 68%; left: 62%;
  background: radial-gradient(circle, rgba(137,146,153,.3) 0%, rgba(137,146,153,0) 70%);
  animation: driftC 52s var(--ease) infinite alternate;
}

@keyframes driftA {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(-8vw, 10vh, 0) scale(1.18); }
  100% { transform: translate3d(5vw, -4vh, 0) scale(.94); }
}
@keyframes driftB {
  0%   { transform: translate3d(0,0,0) scale(1.05); }
  50%  { transform: translate3d(12vw, -8vh, 0) scale(.9); }
  100% { transform: translate3d(-4vw, 6vh, 0) scale(1.2); }
}
@keyframes driftC {
  0%   { transform: translate3d(0,0,0) scale(.95); }
  100% { transform: translate3d(-10vw, -12vh, 0) scale(1.15); }
}

/* Ridge contours. Pulled well back now that the sky carries the scene —
   at the old opacity they cut across the moon and read as scratches. */
.topo {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  color: var(--stone);
  opacity: .055;
}

/* --- Nocturnal treeline -------------------------------------------------
   Two depths of silhouette with a mist band between them. Anchored to the
   bottom of the viewport so it reads as a horizon the page scrolls past.
   Polygons are generated in script.js, seeded off the page filename. */
.treeline {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  width: 100%;
  display: block;
  pointer-events: none;
}
.treeline--far {
  height: clamp(120px, 23vh, 260px);
  opacity: .62;
  filter: blur(1.7px);
}
.treeline--near {
  height: clamp(165px, 31vh, 350px);
  opacity: .96;
}

/* --- The sky: moon, halo, drifting cloud -------------------------------
   All built from gradients rather than blurred elements — a gradient is
   already soft and costs the compositor far less across this many
   full-width layers. */
.moon {
  position: absolute;
  width: clamp(76px, 7.5vw, 132px);
  aspect-ratio: 1;
  border-radius: 50%;
  /* Warm bone-white, not blue-white: this moon is over Georgia in autumn. */
  background:
    radial-gradient(circle at 63% 70%, rgba(150,142,132,.30) 0%, rgba(150,142,132,0) 34%),
    radial-gradient(circle at 34% 30%, rgba(146,138,128,.26) 0%, rgba(146,138,128,0) 26%),
    radial-gradient(circle at 40% 36%, #F7F3ED 0%, #EAE3DA 44%, #D2C8BB 68%, #AFA495 100%);
  box-shadow:
    0 0 26px 3px rgba(244, 240, 235, .30),
    0 0 70px 16px rgba(244, 240, 235, .16),
    0 0 160px 50px rgba(214, 208, 199, .07);
  transform: translate(-50%, -50%);
  animation: moonRise 420s linear infinite alternate;
}
@keyframes moonRise {
  from { transform: translate(-50%, -50%); }
  to   { transform: translate(-50%, -64%); }
}

.moonglow {
  position: absolute;
  width: clamp(360px, 46vw, 760px);
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgba(244, 240, 235, .17) 0%,
    rgba(214, 208, 199, .09) 24%,
    rgba(137, 146, 153, .045) 46%,
    transparent 70%);
}

/* Clouds pass IN FRONT of the moon — their dark core is what makes it
   slip behind them. The faint light rim on the leading edge is the moon
   catching their top. */
.cloud {
  position: absolute;
  left: 0;
  border-radius: 50%;
  background:
    radial-gradient(ellipse at 44% 34%, rgba(168, 174, 180, .10) 0%, rgba(168, 174, 180, 0) 56%),
    radial-gradient(ellipse at 50% 50%, rgba(24, 20, 18, .92) 0%, rgba(24, 20, 18, .74) 40%, rgba(24, 20, 18, 0) 73%);
  will-change: transform;
  animation: cloudDrift linear infinite;
}
@keyframes cloudDrift {
  from { transform: translateX(-75vw); }
  to   { transform: translateX(115vw); }
}

/* --- Heat lightning ----------------------------------------------------
   Silent and far off. Painted behind the treeline so it silhouettes the
   trees instead of lighting them from the front. Gentle on purpose:
   roughly one flicker a second at well under half opacity, never a
   strobe, and switched off entirely under reduced motion. */
.heat {
  position: absolute;
  left: 0; right: 0;
  bottom: 16%;
  height: 30vh;
  opacity: 0;
  background: radial-gradient(ellipse 58% 100% at var(--hx, 50%) 100%,
    rgba(244, 240, 235, .55) 0%,
    rgba(201, 142, 119, .30) 30%,
    rgba(137, 146, 153, .12) 52%,
    transparent 72%);
  animation: heatFlash ease-out infinite;
}
@keyframes heatFlash {
  0%, 88%      { opacity: 0; }
  89.2%        { opacity: .26; }
  90.4%        { opacity: .05; }
  92.0%        { opacity: .34; }
  93.4%        { opacity: .08; }
  95.0%        { opacity: .16; }
  96.6%, 100%  { opacity: 0; }
}

/* --- Low fog along the tree line --------------------------------------- */
.fog {
  position: absolute;
  left: -30%; right: -30%;
  bottom: var(--fb, 5%);
  height: var(--fh, 20vh);
  background: linear-gradient(to top,
    rgba(152, 159, 165, var(--fa, .14)) 0%,
    rgba(152, 159, 165, calc(var(--fa, .14) * .4)) 42%,
    transparent 100%);
  will-change: transform;
  animation: fogDrift ease-in-out infinite alternate;
}
@keyframes fogDrift {
  from { transform: translateX(-7%) scaleY(.92); }
  to   { transform: translateX(8%)  scaleY(1.14); }
}

/* --- DOWNTOWN ----------------------------------------------------------
   Furthest layer on the ground. Buildings are LIGHTER than the near
   trees, not darker — at night a distant city is lifted by its own light
   pollution, so painting it dark would push it forward instead of back. */
.city {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: clamp(175px, 32vh, 360px);
}
.wins rect { fill: rgba(238, 206, 152, .62); }

/* Only ~1 in 8 windows animates. steps(1) makes it a switch, not a fade —
   a light goes on, it doesn't ramp. Cycles are 22-70s so the skyline
   changes at a believable pace rather than twinkling. */
.win--flick {
  animation-name: winFlick;
  animation-timing-function: steps(1, end);
  animation-iteration-count: infinite;
}
@keyframes winFlick {
  0%, 44%    { opacity: 1; }
  45%, 77%   { opacity: 0; }
  78%, 100%  { opacity: 1; }
}

/* Aviation beacons. A true signal red would shout against this palette,
   so these are pulled toward brick — still unmistakably a tower light. */
.beacon {
  fill: rgba(196, 74, 58, .92);
  animation-name: beaconBlink;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
@keyframes beaconBlink {
  0%, 38%   { opacity: .16; }
  46%, 58%  { opacity: 1; }
  66%, 100% { opacity: .16; }
}

/* --- The freight ------------------------------------------------------- */
.train {
  position: absolute;
  left: 0;
  bottom: clamp(60px, 10vh, 122px);
  width: 0; height: 0;
  animation-name: trainRun;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
/* Crosses over the first ~58% of the cycle, then the line sits empty.
   Trains are occasional; one permanently on screen would read as decor. */
@keyframes trainRun {
  0%          { transform: translateX(-26vw); opacity: 0; }
  4%          { opacity: 1; }
  52%         { opacity: 1; }
  58%, 100%   { transform: translateX(122vw); opacity: 0; }
}
/* Bright enough to read as a headlight at this distance. The wide warm
   halo is most of what sells it — the lamp itself is only a few pixels. */
.train__beam {
  position: absolute; left: 0; bottom: -1px;
  width: 7px; height: 4px;
  border-radius: 50%;
  background: rgba(255, 248, 232, 1);
  box-shadow:
    0 0 6px 2px rgba(255, 244, 214, .85),
    0 0 16px 5px rgba(248, 224, 168, .55),
    0 0 40px 13px rgba(226, 186, 120, .26);
}
/* The cars trail behind the light, with gaps between them. */
.train__cars {
  position: absolute; right: 5px; bottom: -1px;
  width: clamp(90px, 11vw, 170px); height: 5px;
  background: repeating-linear-gradient(90deg,
    #0E0C0A 0 15px, rgba(14, 12, 10, .2) 15px 18px);
  opacity: .88;
}

/* --- The juke joint ---------------------------------------------------- */
.juke {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: clamp(150px, 27vh, 300px);
}
/* A tube that's been failing for years and nobody has fixed it. */
.juke__sign {
  animation: jukeFlicker 6.4s linear infinite;
}
@keyframes jukeFlicker {
  0%, 40%     { opacity: 1; }
  41%         { opacity: .22; }
  42.5%       { opacity: 1; }
  56%         { opacity: 1; }
  57%         { opacity: .12; }
  58.5%       { opacity: .85; }
  59.5%       { opacity: .3; }
  61%, 100%   { opacity: 1; }
}

/* --- THE LAND ----------------------------------------------------------
   Power lines, a landmark on the horizon, and a fence in front. All three
   share the treeline's 1440x320 viewBox with the ground at y=320, so
   everything stands on the same floor. Their heights differ, and that
   difference is the depth. */
.lines {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: clamp(215px, 41vh, 460px);
  opacity: .92;
}
.landmark {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: clamp(180px, 34vh, 380px);
}
.fence {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: clamp(74px, 13vh, 150px);
}

/* The same breeze moves the wires and the near trees. Tiny amounts —
   at more than about a degree it stops reading as wind and starts
   reading as a glitch. */
.sway, .treeline--near {
  transform-origin: 50% 100%;
  animation: breeze 13s ease-in-out infinite alternate;
}
.treeline--near { animation-duration: 17s; }
@keyframes breeze {
  from { transform: rotate(-0.18deg) translateX(-0.25%); }
  to   { transform: rotate(0.18deg)  translateX(0.25%); }
}

/* Porch light and its moths. */
.porch-glow {
  transform-box: fill-box;
  transform-origin: center;
  animation: porchFlicker 7s ease-in-out infinite;
}
@keyframes porchFlicker {
  0%, 100% { opacity: .95; }
  43%      { opacity: .82; }
  47%      { opacity: 1; }
  62%      { opacity: .88; }
}
/* The <g class="moths"> carries an inline transform-origin at the bulb's
   coordinates. transform-origin does NOT inherit on its own, so every
   moth has to ask for it explicitly — without this they orbit the centre
   of the whole 1440x320 canvas and swing across the entire scene. */
.moths { transform-box: view-box; }
.moth {
  animation: mothCircle linear infinite;
  transform-box: view-box;
  transform-origin: inherit;
}
.moth--1 { animation-duration: 5.5s; }
.moth--2 { animation-duration: 8.2s; animation-direction: reverse; }
.moth--3 { animation-duration: 6.7s; animation-delay: -2s; }
@keyframes mothCircle {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* --- Kudzu creeping in from the edges ---------------------------------
   --kudzu (0 → 1) is set from scroll position in script.js. At the top of
   the page the vines sit mostly off-screen; by the bottom they've crept
   well in. It IS the South's most persistent weed — it should feel like
   it's winning. */
.kudzu {
  position: absolute;
  top: 0; bottom: 0;
  width: clamp(88px, 13vw, 210px);
  height: 100%;
  opacity: calc(.25 + var(--kudzu, 0) * .65);
  transition: opacity .3s linear;
  pointer-events: none;
}
.kudzu--left {
  left: 0;
  transform: translateX(calc(-42% + var(--kudzu, 0) * 42%));
}
.kudzu--right {
  right: 0;
  transform: translateX(calc(42% - var(--kudzu, 0) * 42%));
}

/* --- Fireflies and foxfire --------------------------------------------
   Two different rhythms on purpose: the firefly BLINKS (hard pulse,
   quick), the foxfire FADES (slow swell). That difference is what makes
   one read as an insect and the other as something on a rotting log. */
.motes { position: absolute; inset: 0; }
.motes span {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
  animation-iteration-count: infinite;
}

.motes .fly {
  background: rgba(226, 206, 138, .95);
  box-shadow: 0 0 8px rgba(226, 206, 138, .55);
  animation-name: firefly;
  animation-timing-function: ease-out;
}
@keyframes firefly {
  0%, 62%   { opacity: 0;   transform: translate3d(0, 0, 0); }
  66%       { opacity: .9;  }
  70%       { opacity: .15; }
  73%       { opacity: .75; }
  78%       { opacity: 0;   }
  100%      { opacity: 0;   transform: translate3d(14px, -22px, 0); }
}

.motes .fox {
  box-shadow: 0 0 7px rgba(244, 240, 235, .22);
  animation-name: foxfire;
  animation-timing-function: ease-in-out;
}
@keyframes foxfire {
  0%, 100% { opacity: 0;   transform: translate3d(0, 0, 0); }
  18%      { opacity: .6; }
  50%      { opacity: .22; transform: translate3d(16px, -30px, 0); }
  82%      { opacity: .5;  }
}

/* --- Scene variants ------------------------------------------------------
   script.js hangs scene-0…3 off the seed so no two pages glow the same. */
.scene-1 .bloom--muscadine { top: -20%; left: 14%; }
.scene-1 .bloom--sorghum   { top: 30%;  left: 64%; }
.scene-1 .bloom--stone     { top: 72%;  left: 8%;  }
.scene-1 .topo             { opacity: .04; }

.scene-2 .bloom--muscadine { top: 22%;  left: 70%; }
.scene-2 .bloom--sorghum   { top: -14%; left: 22%; }
.scene-2 .bloom--stone     { top: 58%;  left: 40%; }
.scene-2 .topo             { opacity: .07; transform: scaleY(-1); }

.scene-3 .bloom--muscadine { top: 48%;  left: 30%; }
.scene-3 .bloom--sorghum   { top: 6%;   left: 58%; }
.scene-3 .bloom--stone     { top: -10%; left: -6%; }
.scene-3 .topo             { opacity: .05; transform: scaleX(-1); }

.grain {
  position: absolute;
  inset: -50%;
  width: 200%; height: 200%;
  opacity: .085;
  mix-blend-mode: overlay;
  animation: grainShift 1.2s steps(3) infinite;
}
@keyframes grainShift {
  0%   { transform: translate(0, 0); }
  33%  { transform: translate(-2%, 1%); }
  66%  { transform: translate(1%, -2%); }
  100% { transform: translate(0, 0); }
}

/* --------------------------------------------------------------------------
   4. MASTHEAD
   -------------------------------------------------------------------------- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: calc(var(--sp) * 2);
  padding: calc(var(--sp) * 1.1) clamp(1rem, 3vw, 2.5rem);
  background: rgba(28, 24, 21, 0.6);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--glass-brd);
}

.mark { display: flex; align-items: center; gap: .8rem; text-decoration: none; }
/* Profile circle, top-left. An empty ring until assets/profile/profile.jpg
   exists — the ring itself is the placeholder. Char and Field Stone only:
   this will hold a photo of the artist, so no Sorghum anywhere near it. */
.mark__avatar {
  position: relative;
  width: 40px; height: 40px;
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  border: 1.5px solid rgba(137, 146, 153, .6);
  background: rgba(28, 24, 21, .55);
  transition: border-color .3s;
}
.mark__avatar img {
  width: 100%; height: 100%;
  object-fit: cover;          /* a slightly-off-square photo crops, never stretches */
  display: block;
}
.mark__avatar.has-photo { border-color: rgba(244, 240, 235, .38); }
.mark:hover .mark__avatar { border-color: rgba(244, 240, 235, .6); }
.mark__type { display: flex; flex-direction: column; line-height: 1.15; }
.mark__type strong {
  font-family: var(--display);
  font-variation-settings: "SOFT" 20, "WONK" 1;
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: -0.015em;
}
.mark__type em {
  font-style: normal;
  font-size: var(--t-xs);
  color: var(--ink-dim);
}

.masthead__nav { display: flex; gap: 1.6rem; margin-left: auto; }
.masthead__nav a {
  text-decoration: none;
  font-size: var(--t-sm);
  color: var(--ink-mid);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: color .25s, border-color .25s;
}
.masthead__nav a:hover { color: var(--ink); border-bottom-color: var(--muscadine-lt); }
.masthead__nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--muscadine); }

.masthead__status { display: flex; align-items: center; gap: .55rem; }
.status-text { font-size: var(--t-xs); color: var(--ink-dim); }
.pulse {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muscadine-lt);
  box-shadow: 0 0 0 0 rgba(199,123,171,.6);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(199,123,171,.55); }
  70%  { box-shadow: 0 0 0 9px rgba(199,123,171,0); }
  100% { box-shadow: 0 0 0 0 rgba(199,123,171,0); }
}

/* --------------------------------------------------------------------------
   5. THE ASYMMETRIC DECK
   12 columns that interlock rather than sit in tidy rows — panels differ in
   both span and height so no two edges line up predictably.
   -------------------------------------------------------------------------- */
.deck {
  position: relative;
  z-index: 10;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: minmax(150px, auto);
  gap: clamp(.9rem, 1.4vw, 1.4rem);
  padding: clamp(1rem, 3vw, 2.5rem);
  max-width: 1600px;
  margin-inline: auto;
  perspective: 1400px;   /* shared vanishing point for every tilt */
}

.panel--hero     { grid-column: 1 / 8;  grid-row: 1 / 3; }
.panel--sync     { grid-column: 8 / 13; grid-row: 1 / 4; }
.panel--routing  { grid-column: 1 / 5;  grid-row: 3 / 4; }
.panel--signal   { grid-column: 5 / 8;  grid-row: 3 / 4; }
.panel--notes    { grid-column: 1 / 7;  grid-row: 4 / 5; }
.panel--press    { grid-column: 7 / 13; grid-row: 4 / 5; }
/* Field Notes. Hidden while the config list is empty; when quotes are
   added it appears as its own full-width row, so the grid above never
   has to re-flow around it. */
.panel--woodshed { grid-column: 1 / 13; grid-row: 5 / 6; }
.panel[hidden]   { display: none !important; }

/* --------------------------------------------------------------------------
   6. GLASS PANEL + 3D TILT
   JS writes --rx/--ry (rotation) and --mx/--my (sheen position).
   -------------------------------------------------------------------------- */
.panel {
  --rx: 0deg;
  --ry: 0deg;
  --mx: 50%;
  --my: 50%;

  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  backdrop-filter: blur(var(--blur)) saturate(130%);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(130%);
  box-shadow:
    0 1px 0 0 rgba(244,240,235,.06) inset,
    0 18px 45px -20px rgba(0,0,0,.75);
  /* Perspective lives on .deck so every panel shares one vanishing point;
     applying it again here would compound the foreshortening. */
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  transform-style: preserve-3d;
  transition:
    transform .5s var(--ease),
    background-color .4s ease,
    border-color .4s ease,
    box-shadow .4s ease;
}

/* While the pointer is down/over, snap responsiveness up. */
.panel.is-tilting { transition: transform .08s linear, background-color .4s ease, border-color .4s ease; }

.panel:hover {
  background: var(--glass-bg-hover);
  border-color: var(--glass-brd-hi);
  box-shadow:
    0 1px 0 0 rgba(244,240,235,.1) inset,
    0 28px 60px -22px rgba(0,0,0,.85),
    0 0 42px -14px rgba(127,42,101,.45);
}

/* Specular sheen that tracks the cursor — this is what sells the glass. */
.panel__sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s ease;
  background: radial-gradient(
    380px circle at var(--mx) var(--my),
    rgba(244,240,235,.10) 0%,
    rgba(199,123,171,.07) 35%,
    transparent 68%
  );
}
.panel:hover .panel__sheen { opacity: 1; }

.panel__body {
  position: relative;
  z-index: 2;
  padding: clamp(1.2rem, 2vw, 1.9rem);
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: .9rem;
  transform: translateZ(40px);  /* content floats above the glass */
}

.panel__head { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.panel__head h2 {
  font-size: var(--t-lg);
  font-variation-settings: "SOFT" 30, "WONK" 1;
  letter-spacing: -0.02em;
}
.panel__lede { font-size: var(--t-sm); color: var(--ink-mid); max-width: 52ch; }

/* --------------------------------------------------------------------------
   7. SHARED BITS
   -------------------------------------------------------------------------- */
.readout {
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
  letter-spacing: .02em;
}
.readout--dim { opacity: .65; }

.eyebrow {
  font-size: var(--t-xs);
  color: var(--sorghum-lt);
  letter-spacing: .06em;
}

.chip {
  font-family: var(--mono);
  font-size: 10px;
  padding: .28rem .6rem;
  border-radius: 999px;
  border: 1px solid var(--glass-brd-hi);
  color: var(--ink-mid);
  white-space: nowrap;
}
.chip--clear { border-color: rgba(199,123,171,.5); color: var(--muscadine-lt); background: rgba(127,42,101,.14); }
.chip--open  { border-color: rgba(201,142,119,.5); color: var(--sorghum-lt);  background: rgba(145,94,77,.14); }
.chip--sold  { color: var(--ink-dim); opacity: .6; }
.chip--hold  { border-style: dashed; }

.action {
  margin-top: auto;
  align-self: flex-start;
  font-size: var(--t-sm);
  text-decoration: none;
  padding: .6rem 1.1rem;
  border-radius: 999px;
  border: 1px solid var(--glass-brd-hi);
  color: var(--ink);
  transition: background .3s, border-color .3s, transform .3s var(--ease);
}
.action:hover { background: rgba(244,240,235,.08); border-color: var(--muscadine-lt); transform: translateY(-2px); }
/* Cotton on solid Muscadine = 7.65:1 */
.action--solid { background: var(--muscadine); border-color: var(--muscadine); color: var(--cotton); }
.action--solid:hover { background: #953077; border-color: var(--muscadine-lt); }

/* --------------------------------------------------------------------------
   8. HERO
   -------------------------------------------------------------------------- */
.panel--hero .panel__body { flex-direction: column; justify-content: center; }
.panel--hero { display: grid; grid-template-columns: 1fr auto; }

/* Sized for a long, all-caps title: "INSIDE HEWY'S THOUGHTS" at the old
   --t-2xl ran wider than the panel. balance keeps the lines even. */
.hero__title {
  font-size: clamp(2.1rem, 3.3vw + .6rem, 4.2rem);
  font-weight: 900;
  font-variation-settings: "SOFT" 0, "WONK" 1, "opsz" 144;
  letter-spacing: -0.025em;
  line-height: .95;
  text-wrap: balance;
  background: linear-gradient(168deg, var(--cotton) 8%, #D9CFC6 46%, var(--sorghum-lt) 104%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__sub { font-size: var(--t-sm); color: var(--ink-mid); max-width: 44ch; }
.hero__sub em { color: var(--ink); font-style: italic; }

.player { display: flex; align-items: center; gap: 1rem; margin-top: .4rem; }

.play {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem 1.1rem .55rem .9rem;
  border-radius: 999px;
  border: 1px solid rgba(199,123,171,.45);
  background: rgba(127,42,101,.2);
  font-size: var(--t-sm);
  transition: background .3s, border-color .3s;
}
.play:hover { background: rgba(127,42,101,.35); border-color: var(--muscadine-lt); }
.play__icon {
  width: 0; height: 0;
  border-left: 9px solid var(--cotton);
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}
.play[aria-pressed="true"] .play__icon {
  width: 9px; height: 11px;
  border: none;
  border-left: 3px solid var(--cotton);
  border-right: 3px solid var(--cotton);
}

.wave { display: flex; align-items: center; gap: 2px; height: 42px; flex: 1; min-width: 0; }
.wave span {
  flex: 1;
  min-width: 2px;
  border-radius: 1px;
  background: var(--stone);
  opacity: .42;
  height: var(--h, 30%);
  transition: height .18s ease, opacity .3s, background-color .3s;
}
.wave span.is-played { background: var(--muscadine-lt); opacity: .9; }

/* "Coming soon": the button is genuinely disabled and the wave is a flat,
   dim line — nothing animates, nothing pretends to be the track. */
.play[disabled] {
  cursor: default;
  background: rgba(244, 240, 235, .05);
  border-color: var(--glass-brd);
  color: var(--ink-mid);
}
.play[disabled]:hover { background: rgba(244, 240, 235, .05); border-color: var(--glass-brd); }
.play.is-soon .play__icon { display: none; }
.wave.is-idle span { opacity: .2; }
.wave.is-seekable { cursor: pointer; }

.player__meta { display: flex; flex-direction: column; align-items: flex-end; gap: .15rem; }

.spec { display: flex; gap: 1.8rem; flex-wrap: wrap; margin-top: .5rem; }
.spec div { display: flex; flex-direction: column; gap: .15rem; }
.spec dt { font-size: 10px; color: var(--ink-dim); letter-spacing: .08em; }
.spec dd { font-size: var(--t-sm); }

/* --- Featured cover --------------------------------------------------
   A 4:5 frame. The 1:1 cover sits in the upper square; the SAME image,
   scaled up, blurred and darkened, fills everything around and below it —
   the cover expanding into its own frame. Whatever its colours, the frame
   takes them on, with no design work per release.
   The empty fallback is Char only: covers often show the artist, and
   Sorghum never sits behind images of the artist. */
.cover {
  position: relative;
  z-index: 2;
  align-self: center;
  width: clamp(160px, 17vw, 250px);
  aspect-ratio: 4 / 5;
  margin: clamp(1.2rem, 2vw, 1.9rem) clamp(1.2rem, 2vw, 1.9rem) clamp(1.2rem, 2vw, 1.9rem) 0;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--glass-brd-hi);
  background: linear-gradient(160deg, var(--char-lift2), var(--char-deep));
  transform: translateZ(25px);
}
.cover__backdrop {
  position: absolute;
  inset: -18%;
  width: 136%; height: 136%;
  object-fit: cover;
  filter: blur(24px) saturate(1.25) brightness(.6);
}
.cover__square {
  position: absolute;
  left: 8%; right: 8%; top: 6.4%;          /* 6.4% of height = 8% of width */
  aspect-ratio: 1;
  display: grid; place-items: center;
  border-radius: 8px;
  overflow: hidden;
  background: rgba(20, 17, 15, .55);
  border: 1px solid rgba(244, 240, 235, .12);
  box-shadow: 0 18px 38px -16px rgba(0, 0, 0, .85);
}
.cover__art { width: 100%; height: 100%; object-fit: cover; display: block; }
.cover__soon {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-dim);
  text-align: center;
  padding: .6rem;
  line-height: 1.5;
}
.cover.has-cover .cover__soon { display: none; }

/* --------------------------------------------------------------------------
   9. SYNC VAULT
   -------------------------------------------------------------------------- */
.filters { display: flex; gap: .4rem; flex-wrap: wrap; }
.filter {
  font-size: var(--t-xs);
  padding: .3rem .75rem;
  border-radius: 999px;
  border: 1px solid var(--glass-brd);
  color: var(--ink-mid);
  transition: all .25s;
}
.filter:hover { border-color: var(--glass-brd-hi); color: var(--ink); }
.filter.is-active { background: rgba(127,42,101,.28); border-color: var(--muscadine-lt); color: var(--cotton); }

.vault { display: flex; flex-direction: column; gap: 1px; margin-top: .3rem; }
.vault__row {
  display: grid;
  grid-template-columns: 1fr auto auto auto auto;
  gap: .8rem;
  align-items: center;
  padding: .6rem .5rem;
  border-bottom: 1px solid rgba(244,240,235,.06);
  transition: background .25s, opacity .3s, transform .3s;
}
.vault__row:hover { background: rgba(244,240,235,.05); }
.vault__row.is-hidden { display: none; }
.vault__name { font-size: var(--t-sm); }
.vault__mood { font-size: 10px; color: var(--sorghum-lt); font-family: var(--mono); }

/* --------------------------------------------------------------------------
   10. ROUTING
   -------------------------------------------------------------------------- */
.dates { display: flex; flex-direction: column; }
.dates li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: .9rem;
  align-items: center;
  padding: .65rem 0;
  border-bottom: 1px solid rgba(244,240,235,.06);
}
.dates li:last-child { border-bottom: none; }
.dates__when { color: var(--sorghum-lt); }
.dates__where { font-size: var(--t-sm); display: flex; flex-direction: column; line-height: 1.25; }
.dates__where strong { font-weight: 500; }
.dates__where { color: var(--ink-dim); }
.dates__where strong { color: var(--ink); }

/* --------------------------------------------------------------------------
   11. SIGNAL
   -------------------------------------------------------------------------- */
/* This panel is only 3 of 12 columns wide, so the numbers get their own
   scale rather than borrowing --t-xl, which overflowed at 1440px. */
.stats { display: flex; gap: 1.4rem; flex-wrap: wrap; }
.stat { display: flex; flex-direction: column; min-width: 0; }
.stat__num {
  font-family: var(--display);
  font-size: clamp(1.7rem, 2.1vw, 2.5rem);
  font-weight: 700;
  font-variation-settings: "SOFT" 10, "WONK" 0;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.03em;
}
.stat__label { font-size: 10px; color: var(--ink-dim); letter-spacing: .05em; margin-top: .3rem; }

.regions { display: flex; flex-direction: column; gap: .5rem; margin-top: auto; }
.regions li { display: grid; grid-template-columns: 78px 1fr; gap: .7rem; align-items: center; font-size: var(--t-xs); color: var(--ink-mid); }
.bar { height: 3px; border-radius: 2px; background: rgba(244,240,235,.1); position: relative; overflow: hidden; }
.bar::after {
  content: "";
  position: absolute; inset: 0;
  width: var(--pct);
  border-radius: 2px;
  background: linear-gradient(90deg, var(--sorghum), var(--muscadine));
  transform-origin: left;
  animation: growBar 1.4s var(--ease) both;
}
@keyframes growBar { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* --------------------------------------------------------------------------
   12. WOODSHED / NOTES / KIT
   -------------------------------------------------------------------------- */
.shed { display: flex; flex-direction: column; gap: .9rem; }
.shed li { padding-left: .9rem; border-left: 1px solid rgba(201,142,119,.35); }
.shed h3 { font-size: var(--t-sm); font-weight: 600; font-family: var(--body); margin-bottom: .15rem; }
.shed p { font-size: var(--t-xs); color: var(--ink-mid); }

.note { border-left: 2px solid rgba(199,123,171,.45); padding-left: 1rem; }
.note p {
  font-family: var(--display);
  font-size: var(--t-md);
  font-variation-settings: "SOFT" 60, "WONK" 1;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.01em;
}
.note cite { display: block; margin-top: .5rem; font-size: var(--t-xs); font-style: normal; color: var(--ink-dim); }

.kit { display: flex; flex-direction: column; gap: .55rem; }
.kit li { display: flex; align-items: center; gap: .7rem; font-size: var(--t-sm); color: var(--ink-mid); }
.kit .readout { color: var(--sorghum-lt); }

/* --------------------------------------------------------------------------
   13. FOOTER
   -------------------------------------------------------------------------- */
.footer {
  position: relative; z-index: 10;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: .5rem;
  padding: 2rem clamp(1rem, 3vw, 2.5rem) 3rem;
  font-size: var(--t-xs);
  color: var(--ink-dim);
  border-top: 1px solid var(--glass-brd);
  margin-top: 2rem;
}
.footer a { color: var(--sorghum-lt); }

/* Social icon row — footer on every page, and the Press contact panel.
   Icon marks only, one shared height, so seven brands read as one row. */
.socials { display: flex; flex-wrap: wrap; align-items: center; gap: .85rem 1.15rem; }
.social {
  display: inline-flex; align-items: center; justify-content: center;
  height: 32px; min-width: 28px;
  text-decoration: none;
  opacity: .86;
  transition: opacity .3s, transform .3s var(--ease);
}
.social:hover { opacity: 1; transform: translateY(-2px); }
.social:focus-visible { outline-offset: 5px; }
.social img { height: 26px; width: auto; display: block; }
.social__name { font-size: var(--t-xs); color: var(--ink-mid); }

.footer__socials { flex-basis: 100%; order: 2; margin-top: .6rem; }

.footer__legal {
  flex-basis: 100%;
  order: 3;
  margin-top: .9rem;
  padding-top: .9rem;
  border-top: 1px solid rgba(244, 240, 235, .07);
  color: var(--ink-dim);
  opacity: .85;
}

/* --------------------------------------------------------------------------
   13b. PAGE TRANSITIONS
   Cross-document View Transitions where supported (Chrome/Edge/Safari 18+);
   a fade-and-lift fallback everywhere else, driven by .is-leaving in JS.
   The masthead gets its own transition name so it stays put while the page
   body swaps underneath it — that's what makes it feel like one app.
   -------------------------------------------------------------------------- */
@view-transition { navigation: auto; }

.masthead   { view-transition-name: masthead; }
.atmosphere { view-transition-name: atmosphere; }   /* never re-animates */

::view-transition-old(root) { animation: pageOut .3s var(--ease) both; }
::view-transition-new(root) { animation: pageIn .48s var(--ease) both; }

@keyframes pageOut { to   { opacity: 0; transform: translateY(-12px) scale(.994); filter: blur(3px); } }
@keyframes pageIn  { from { opacity: 0; transform: translateY(16px)  scale(.994); filter: blur(3px); } }

/* Fallback for browsers without cross-document view transitions. */
.pagewrap { transition: opacity .28s var(--ease), transform .28s var(--ease), filter .28s var(--ease); }
body.is-leaving .pagewrap { opacity: 0; transform: translateY(-12px); filter: blur(3px); }

/* Entrance stagger. `backwards` (not `both`) is deliberate: once the
   animation ends the element falls back to its normal rule, which is what
   lets the tilt transform take over afterwards. */
.panel { animation: riseIn .65s var(--ease) backwards; animation-delay: calc(var(--i, 0) * 65ms); }
@keyframes riseIn { from { opacity: 0; transform: translateY(22px); } }

/* --------------------------------------------------------------------------
   13c. PLATFORM LINKS
   -------------------------------------------------------------------------- */
.platforms { display: flex; flex-wrap: wrap; gap: .55rem; }

.platform {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 46px; padding: 0 1.15rem;
  border-radius: 12px;
  border: 1px solid var(--glass-brd);
  background: rgba(244, 240, 235, .04);
  text-decoration: none;
  overflow: hidden;
  position: relative;
  transition: background .35s var(--ease), border-color .35s var(--ease),
              transform .35s var(--ease), box-shadow .35s var(--ease);
}
.platform::before {           /* muscadine wash that wipes across on hover */
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(120deg, transparent, rgba(127,42,101,.35), transparent);
  transform: translateX(-100%);
  transition: transform .6s var(--ease);
}
.platform:hover {
  background: rgba(244, 240, 235, .08);
  border-color: var(--muscadine-lt);
  transform: translateY(-3px);
  box-shadow: 0 12px 26px -14px rgba(0,0,0,.9), 0 0 24px -10px rgba(127,42,101,.6);
}
.platform:hover::before { transform: translateX(100%); }

.platform img { height: 19px; width: auto; display: block; position: relative; z-index: 1; }
/* Solid-black marks flipped to near-Cotton so they read on Char. */
.platform--invert img { filter: invert(1) brightness(1.55) contrast(1.05); }
.platform__name { font-size: var(--t-sm); position: relative; z-index: 1; }
.platform.has-logo .platform__name { display: none; }   /* badge already has the wordmark */

/* --- Tile variant: the home page grid that links to each service page --- */
.platforms--tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(185px, 1fr));
  gap: .7rem;
}
.platforms--tiles .platform {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: .55rem;
  min-height: 116px;
  padding: 1.15rem;
  border-radius: 14px;
}
.platforms--tiles .platform img { height: 26px; max-width: 100%; }
.platforms--tiles .platform__name {
  font-family: var(--display);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: -.015em;
}
.platform__blurb {
  font-size: var(--t-xs);
  color: var(--ink-dim);
  line-height: 1.45;
  position: relative; z-index: 1;
}

/* --- Service pages --- */
/* --- The service page header IS the platform's mark ---------------------
   The <h1> holds the platform name as text; .has-mark (set by JS once the
   image loads) swaps that for the logo. Until then — or if the image fails
   — the text heading stands in and inherits the normal page-head styling. */
.service-mark {
  display: flex;
  align-items: flex-end;
  min-height: clamp(44px, 6vw, 78px);
}
.service-mark.has-mark {
  /* page-head h1 paints its text with a clipped gradient; an image child
     needs those neutralised or it inherits a transparent fill. */
  background: none;
  -webkit-text-fill-color: currentColor;
  color: var(--ink);
}
.service-mark.has-mark .service-mark__text { display: none; }

.service-mark__img {
  height: clamp(44px, 6vw, 78px);
  width: auto;
  display: block;
  filter: drop-shadow(0 8px 24px rgba(0, 0, 0, .6));
  transition: filter .35s var(--ease);
}
.service-mark__img--invert {
  filter: invert(1) brightness(1.55) contrast(1.05)
          drop-shadow(0 8px 24px rgba(0, 0, 0, .6));
}

/* The mark is the link to the artist profile. */
.service-mark__link {
  display: inline-flex;
  align-items: flex-end;
  text-decoration: none;
  color: inherit;
  border-radius: 10px;
  transition: transform .35s var(--ease);
}
.service-mark__link:hover { transform: translateY(-3px); }

/* Two hover rules, because `filter` is a single property: the inverted
   Bandcamp mark has to keep its invert() or it flips back to black. */
.service-mark__link:hover .service-mark__img {
  filter: drop-shadow(0 14px 32px rgba(0, 0, 0, .75)) brightness(1.07);
}
.service-mark__link:hover .service-mark__img--invert {
  filter: invert(1) brightness(1.7) contrast(1.05)
          drop-shadow(0 14px 32px rgba(0, 0, 0, .75));
}

.service-mark__link:focus-visible {
  outline: 2px solid var(--muscadine-lt);
  outline-offset: 8px;
}

.service-stage {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--glass-brd);
  background: var(--char-deep);
  min-height: 300px;
}
.service-stage iframe { display: block; width: 100%; min-height: 380px; border: 0; }

.action.is-disabled { opacity: .5; pointer-events: none; }

/* --------------------------------------------------------------------------
   13d. MAILING LIST
   -------------------------------------------------------------------------- */
.signup { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.signup__field {
  flex: 1 1 210px; min-width: 0;
  background: rgba(244, 240, 235, .05);
  border: 1px solid var(--glass-brd);
  border-radius: 999px;
  padding: .72rem 1.15rem;
  color: var(--ink);
  font: inherit; font-size: var(--t-sm);
  transition: border-color .3s, background .3s, box-shadow .3s;
}
.signup__field::placeholder { color: var(--ink-dim); }
.signup__field:focus {
  outline: none;
  border-color: var(--muscadine-lt);
  background: rgba(244, 240, 235, .08);
  box-shadow: 0 0 0 4px rgba(127, 42, 101, .18);
}
.signup__btn {
  padding: .72rem 1.35rem; border-radius: 999px;
  background: var(--muscadine); color: var(--cotton);   /* 7.65:1 */
  font-size: var(--t-sm);
  transition: background .3s, transform .3s var(--ease), box-shadow .3s;
}
.signup__btn:hover { background: #953077; transform: translateY(-2px); box-shadow: 0 10px 24px -12px rgba(127,42,101,.9); }
.signup__btn[disabled] { opacity: .55; cursor: wait; transform: none; }

.signup__msg {
  flex-basis: 100%; font-size: var(--t-xs); min-height: 1.2em;
  opacity: 0; transform: translateY(-4px);
  transition: opacity .35s, transform .35s;
}
.signup__msg.is-shown { opacity: 1; transform: none; }
.signup__msg.is-ok   { color: var(--sorghum-lt); }
.signup__msg.is-err  { color: var(--muscadine-lt); }

/* --------------------------------------------------------------------------
   13e. SUB-PAGE HEADERS
   -------------------------------------------------------------------------- */
.page-head {
  position: relative; z-index: 10;
  max-width: 1600px; margin-inline: auto;
  padding: clamp(2rem, 5vw, 4rem) clamp(1rem, 3vw, 2.5rem) .5rem;
}
.page-head h1 {
  font-size: var(--t-2xl);
  font-weight: 900;
  font-variation-settings: "SOFT" 0, "WONK" 1, "opsz" 144;
  letter-spacing: -0.045em; line-height: .88;
  background: linear-gradient(168deg, var(--cotton) 10%, #D9CFC6 50%, var(--sorghum-lt) 105%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.page-head p { font-size: var(--t-md); color: var(--ink-mid); max-width: 56ch; margin-top: .8rem; }

/* --------------------------------------------------------------------------
   13f. LISTEN PAGE
   -------------------------------------------------------------------------- */
.listen { display: grid; grid-template-columns: minmax(230px, 300px) 1fr; gap: clamp(.9rem, 1.4vw, 1.4rem); }

.tracklist { display: flex; flex-direction: column; gap: 1px; }
.tracklist__item {
  display: grid; grid-template-columns: 1fr auto; gap: .6rem; align-items: center;
  width: 100%; text-align: left;
  padding: .7rem .6rem;
  border-radius: 8px;
  border-bottom: 1px solid rgba(244,240,235,.06);
  transition: background .28s, padding-left .28s var(--ease), color .28s;
}
.tracklist__item:hover { background: rgba(244,240,235,.05); padding-left: .95rem; }
.tracklist__item.is-current { background: rgba(127,42,101,.22); padding-left: .95rem; }
.tracklist__item.is-current .tracklist__title { color: var(--cotton); }
.tracklist__title { font-size: var(--t-sm); display: block; }
.tracklist__sub { font-size: 10px; color: var(--ink-dim); font-family: var(--mono); }

.embed-tabs { display: flex; gap: .4rem; flex-wrap: wrap; }
.embed-tab {
  font-size: var(--t-xs); padding: .35rem .8rem; border-radius: 999px;
  border: 1px solid var(--glass-brd); color: var(--ink-mid);
  transition: all .28s var(--ease);
}
.embed-tab:hover { border-color: var(--glass-brd-hi); color: var(--ink); transform: translateY(-1px); }
.embed-tab.is-active { background: rgba(127,42,101,.3); border-color: var(--muscadine-lt); color: var(--cotton); }

.embed-stage {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--glass-brd);
  background: var(--char-deep);
  min-height: 232px;
  transition: opacity .35s var(--ease);
}
.embed-stage.is-swapping { opacity: 0; }
.embed-stage iframe { display: block; width: 100%; height: 100%; min-height: 232px; border: 0; }
.embed-stage--video iframe { aspect-ratio: 16 / 9; min-height: 0; }

.embed-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .6rem; padding: 2.5rem 1.5rem; text-align: center; min-height: 232px;
  color: var(--ink-dim);
}
.embed-empty strong { font-family: var(--display); font-size: var(--t-md); color: var(--ink-mid); font-weight: 600; }
.embed-empty span { font-size: var(--t-xs); max-width: 40ch; }

.open-in { display: flex; flex-direction: column; gap: .6rem; }
.open-in__label { font-size: var(--t-xs); color: var(--ink-dim); }

/* --------------------------------------------------------------------------
   13g. SHOWS PAGE
   -------------------------------------------------------------------------- */
.showlist { display: flex; flex-direction: column; }
.showlist li {
  display: grid; grid-template-columns: 90px 1fr auto; gap: 1.2rem; align-items: center;
  padding: 1.1rem .4rem;
  border-bottom: 1px solid rgba(244,240,235,.07);
  transition: background .3s, padding-left .3s var(--ease);
}
.showlist li:hover { background: rgba(244,240,235,.04); padding-left: .9rem; }
.showlist__date { font-family: var(--mono); font-size: var(--t-sm); color: var(--sorghum-lt); }
.showlist__venue { font-family: var(--display); font-size: var(--t-md); font-weight: 600; letter-spacing: -.01em; }
.showlist__city { font-size: var(--t-xs); color: var(--ink-dim); display: block; }
.showlist__cta {
  font-size: var(--t-xs); text-decoration: none; padding: .5rem 1rem; border-radius: 999px;
  border: 1px solid var(--glass-brd-hi); color: var(--ink);
  transition: background .3s, border-color .3s, transform .3s var(--ease);
}
.showlist__cta:hover { background: rgba(127,42,101,.3); border-color: var(--muscadine-lt); transform: translateY(-2px); }

/* --------------------------------------------------------------------------
   13h. GENERIC SUB-PAGE BLOCKS
   -------------------------------------------------------------------------- */
.stack { display: flex; flex-direction: column; gap: 1rem; }
.prose p { font-size: var(--t-sm); color: var(--ink-mid); max-width: 64ch; }
.prose p + p { margin-top: .7rem; }
.prose strong { color: var(--ink); font-weight: 500; }

/* Direct-child selectors are load-bearing here: `.deck--flow .panel` would
   also hit panels nested inside .listen and blow out its 2-column grid. */
.deck--flow { grid-auto-rows: auto; }
.deck--flow > .panel { grid-column: span 12; }
.deck--flow > .panel--half { grid-column: span 6; }

/* --------------------------------------------------------------------------
   14. RESPONSIVE
   Tablet reflows to 6 columns; phone collapses to a single column.
   -------------------------------------------------------------------------- */
@media (max-width: 1100px) {
  .deck { grid-template-columns: repeat(6, 1fr); }
  .panel--hero     { grid-column: 1 / 7; grid-row: auto; }
  .panel--sync     { grid-column: 1 / 4; grid-row: auto; }
  .panel--routing  { grid-column: 4 / 7; grid-row: auto; }
  .panel--signal   { grid-column: 1 / 4; grid-row: auto; }
  .panel--notes    { grid-column: 4 / 7; grid-row: auto; }
  .panel--press    { grid-column: 1 / 7; grid-row: auto; }
  .panel--woodshed { grid-column: 1 / 7; grid-row: auto; }
}

@media (max-width: 720px) {
  /* Single column, tilt disabled in JS, perspective removed. */
  .deck {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
    perspective: none;
  }
  .panel {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
    transform: none !important;   /* hard stop on any residual tilt */
  }
  .panel__body { transform: none; }
  .cover { transform: none; }

  .masthead { flex-wrap: wrap; gap: .8rem 1.2rem; }
  .masthead__nav { margin-left: 0; order: 3; width: 100%; gap: 1.1rem; }
  .masthead__status { margin-left: auto; }

  .panel--hero { grid-template-columns: 1fr; }
  /* Smaller on phones so the cover doesn't eat the first screen. */
  .cover { width: 150px; margin: 0 clamp(1.2rem,2vw,1.9rem) clamp(1.2rem,2vw,1.9rem); align-self: flex-start; }

  .player { flex-wrap: wrap; }
  .wave { order: 3; width: 100%; flex-basis: 100%; }
  .player__meta { margin-left: auto; align-items: flex-end; }

  .vault__row { grid-template-columns: 1fr auto auto; }
  .vault__row .readout:nth-of-type(2),
  .vault__row .vault__mood { display: none; }

  .bloom { filter: blur(70px); opacity: .42; }

  /* Listen page stacks: tracklist above the player. */
  .listen { grid-template-columns: 1fr; }
  .deck--flow > .panel--half { grid-column: span 12; }

  /* Shows collapse to two rows so the venue name keeps its size. */
  .showlist li { grid-template-columns: 70px 1fr; gap: .5rem .9rem; }
  .showlist__cta { grid-column: 2; justify-self: start; margin-top: .4rem; }

  .platform { flex: 1 1 auto; justify-content: center; }
}

/* --------------------------------------------------------------------------
   15. REDUCED MOTION
   Glowing animated gradients are exactly the thing that triggers vestibular
   symptoms, so everything ambient stops. Layout and colour stay intact.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .bloom { animation: none; }
  .grain { animation: none; }
  .panel { transform: none !important; animation: none !important; }
  .bar::after { transform: scaleX(1); }

  /* The universal `*` rule above can't reach view-transition pseudo-elements,
     so the page-swap animation has to be switched off by name. */
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none !important; }
  .pagewrap { transition: none !important; }
  body.is-leaving .pagewrap { opacity: 1; transform: none; filter: none; }

  /* Ambient movement is exactly what this setting exists to stop.
     The moon, clouds, fog and treeline all STAY — they're scenery, and
     removing them would strip the page of its character for no benefit.
     What stops is the motion, and the flashing goes entirely: flicker is
     the one thing here that could actually harm someone. */
  .cloud { animation: none; transform: translateX(22vw); }
  .fog   { animation: none; transform: none; }
  .moon  { animation: none; transform: translate(-50%, -50%); }
  .heat  { animation: none; opacity: 0; }
  .motes { display: none; }

  /* The land stays — poles, fence, shed and kudzu are scenery. Only the
     motion stops: no breeze, no circling moths, no flickering bulb, and
     the kudzu sits at a fixed depth instead of tracking the scroll. */
  .sway, .treeline--near { animation: none; transform: none; }
  .porch-glow, .moth     { animation: none; }

  /* Downtown stays lit, it just stops changing. The train parks mid-crossing
     rather than vanishing — with the animation off it would otherwise be
     stuck at its off-screen starting frame. */
  .win--flick  { animation: none; opacity: 1; }
  .beacon      { animation: none; opacity: .85; }
  .juke__sign  { animation: none; opacity: 1; }
  .train       { animation: none; transform: translateX(58vw); opacity: 1; }
  .kudzu { transition: none; opacity: .55; }
  .kudzu--left  { transform: translateX(-14%); }
  .kudzu--right { transform: translateX(14%); }
}


/* --------------------------------------------------------------------------
   16. "COMING SOON" STATES
   Mailing list, shows and the sync catalogue all say so plainly instead
   of showing a form that collects nothing or a list that isn't real.
   -------------------------------------------------------------------------- */
.soon { display: flex; flex-direction: column; gap: .7rem; }
.soon__label {
  font-family: var(--display);
  font-size: var(--t-md);
  font-weight: 600;
  font-variation-settings: "SOFT" 30, "WONK" 1;
  letter-spacing: -.01em;
}

/* .showlist li is a 3-column grid; the empty row needs to override it,
   hence the doubled class for specificity. */
.showlist .showlist__none,
.vault .vault__none {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .45rem;
  padding: 1rem .2rem;
  border-bottom: none;
}
.showlist .showlist__none:hover { background: none; padding-left: .2rem; }
.showlist__none strong,
.vault__none strong {
  font-family: var(--display);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: -.01em;
}
.showlist__none span,
.vault__none span { font-size: var(--t-sm); color: var(--ink-mid); max-width: 48ch; }
.showlist__none .action { margin-top: .5rem; }
