@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,300..800&family=DotGothic16&family=Inter+Tight:wght@300;400;500;600;700&display=swap');

/* ============================================================================
   NIGHTFILM. The Drummer Records design system.

   One stylesheet for the whole site. A page contributes exactly one thing of
   its own: a :root block of colour world tokens, derived from its cover art.
   Everything else below is shared and must stay page agnostic.

   Adding a release means adding a cover and a token block. Nothing else.
   Full documentation: docs/redesign/DESIGN-SYSTEM.md
   ========================================================================= */


/* ----------------------------------------------------------- teletactile --
   TELETACTILE DR v1. Self hosted, no CDN. The knocked out eyebrow panel only.
   Measured off the file, not assumed: unitsPerEm 1000, every MAPPED glyph advance 819,
   so 0.819em per character. capHeight 756, xHeight 756 (identical, it is an all caps
   pixel design), typoAscender 800, typoDescender -200, winAscent 756, winDescent 126.
   111 codepoints, 114 glyphs.

   PROVENANCE. Modified Teletactile by Heaven Castro, 2020, with U+00B7 and U+22A0 mapped
   to glyphs whose outlines ARE the original .notdef drawing, verified byte for byte at 59
   pen operations each. THE MARK IS THE .notdef DRAWING AND THAT IS DELIBERATE. Do not
   "fix" it as an error. The consequence is in DESIGN-SYSTEM.md and matters: a codepoint
   MISSING from this font renders the same mark as the deliberate separator, so a coverage
   bug is invisible in a render. Check new strings against the cmap, never against the eye.

   font-display:block so the panel never flashes a fallback face. */
@font-face{
  font-family:'Teletactile DR';
  /* DOUBLE QUOTES ARE LOAD BEARING. tools/make-stage.sh rewrites root relative paths for the
     staging mirror with a sed that matches url( and url(" but NOT url('. Single quoted here,
     the path stays unprefixed on staging, resolves against the LIVE root where this font does
     not exist, 404s, and the panel silently falls back to ui-monospace. Caught in v31 only
     because document.fonts reported status "error"; the computed font-family still read
     "Teletactile DR", so it looked correct. */
  src:url("/assets/Teletactile-DR-v1.woff2") format("woff2"),
      url("/assets/Teletactile-DR-v1.ttf") format("truetype");
  font-weight:400;font-style:normal;font-display:block;
}


/* ---------------------------------------------------------------- tokens --
   Colour world tokens (--ink --deep --panel --haze --paper --glow --hair) are
   NOT defined here. Each page sets them inline. These are the defaults that
   apply if a page forgets, deliberately ugly enough to be noticed in review.
   -------------------------------------------------------------------------- */
:root{
  --ink:#0a0a0a; --deep:#141414; --panel:#1e1e1e;
  --haze:#999; --paper:#e8e8e8; --glow:#ff00ff; --hair:rgba(255,0,255,.15);

  /* type families. No serif: there is no serif in any Drummer cover art.
     One grotesque carries display, lead and body. The dot matrix face is held to
     eyebrows and section labels only, capped at .16em tracking, and never below
     12px: it is bitmap derived and 11px renders soft (tested at 1440 and 402). */
  --f-display:'Bricolage Grotesque', system-ui, sans-serif;
  --f-body:'Inter Tight', system-ui, -apple-system, sans-serif;
  /* SECTION LABELS ONLY. The eyebrow panel left this token in v31 and took --f-eyebrow.
     .slabel stays DotGothic16 THIS PASS and goes to Roboto Mono Light in the type
     migration. Do NOT put Teletactile on section labels as a consistency fix: the split
     is deliberate and the destination is Roboto Mono, not Teletactile. */
  --f-label:'DotGothic16', ui-monospace, monospace;
  /* The knocked out eyebrow panel, and nothing else on the site. */
  --f-eyebrow:'Teletactile DR', ui-monospace, monospace;
  --f-lead:'Bricolage Grotesque', system-ui, sans-serif;
  --title-w:600; --title-t:-.03em; --lead-i:normal;
  /* the lead voice is no longer italic, so it needs its own weight to stay a voice */
  --lead-w:400;

  /* type scale, fluid. t7 is the one bold move, t1 is the quietest label.
     t7 and t6 come down from the serif settings: a 600 grotesque carries far more
     visual mass per pixel than a thin high contrast serif did at the same size. */
  --t-7:clamp(54px,10vw,138px);
  --t-6:clamp(34px,6vw,74px);
  --t-5:clamp(28px,4.6vw,54px);
  --t-4:clamp(22px,2.8vw,36px);
  --t-3:clamp(18px,2.1vw,24px);
  --t-2:16px;
  --t-1:11px;

  /* spacing scale */
  --s-1:6px; --s-2:12px; --s-3:20px; --s-4:32px;
  /* Fixed, not vh based. With vh the section gap changed with window height, so
     "one section gap" was not a determinate number. --s-7 IS the section gap: 132px. */
  --s-5:56px;
  --s-6:96px;
  --s-7:132px;
  --s-8:200px;

  /* ONE SHARED TWO COLUMN GRID, used by every two column construct on every page:
     .split .triad__row .spec__row .contact .rail__item. Left column always starts at
     the rail, right column always starts at rail + --grid-l + --grid-gap. Verified
     with tools/ink.mjs and the grid probe. */
  --grid-l:300px; --grid-gap:40px;

  --gutter:clamp(22px,5vw,66px);
  /* The content column IS the prose measure. Narrowed from 1180 so a full measure
     block fills it and its ink centres on the page. A left anchored partial block
     carries an offset of width/4, so at 1180 nothing short of a full width block
     could ever centre. Verified with tools/ink.mjs. */
  --maxw:900px;

  --ease:cubic-bezier(.19,.66,.16,1);
  color-scheme:dark only;
}


/* ------------------------------------------------------------------ base -- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;background:var(--ink)}
body{
  background:var(--ink);color:var(--paper);
  font-family:var(--f-body);font-size:var(--t-2);line-height:1.75;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3,h4{font-weight:inherit;font-size:inherit}
::selection{background:var(--glow);color:var(--ink)}
:focus-visible{outline:2px solid var(--glow);outline-offset:3px}

/* screen reader only, for the real <h1> where the display title is not one */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}


/* -------------------------------------------------------- film overlays --
   Persistent across every page. This is most of what makes the site feel shot
   rather than rendered. Both sit above content and ignore pointer events.
   -------------------------------------------------------------------------- */
.grain{position:fixed;inset:0;z-index:60;pointer-events:none;opacity:.045;mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:240px}
.vignette{position:fixed;inset:0;z-index:59;pointer-events:none;
  background:radial-gradient(125% 100% at 50% 40%, transparent 52%, rgba(0,0,0,.7) 100%)}


/* ----------------------------------------------------------- reveal ------ */
.reveal{opacity:1}
@media(prefers-reduced-motion:no-preference){
  .reveal{opacity:0;transform:translateY(24px);
    transition:opacity 1.1s ease,transform 1.1s var(--ease)}
  .reveal.in{opacity:1;transform:none}
}


/* ------------------------------------------------------------ layout ----- */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}
/* .wrap--narrow deleted: it shifted the rail to 376. Use .measure on the inner
   block instead, so the section label stays on the rail. */
/* Each block carries HALF a section gap on each edge, so two adjacent blocks sum to
   exactly one section gap (132px) of ink to ink space instead of stacking two full
   ones. Measured before this: 135 to 299px between sections. */
.blk{padding:60px 0;position:relative}
.blk--tight{padding:44px 0}
.blk--tall{padding:88px 0}

/* light leak divider. Never more than one between two blocks. */
.rule{height:1px;max-width:var(--maxw);margin:0 auto;
  background:linear-gradient(90deg,transparent,var(--hair) 20%,var(--hair) 80%,transparent)}

/* Block to block inside a section, capped. Replaces the ad hoc inline margin-top
   overrides that were producing 160 to 165px runs. */
.blk > .wrap > * + *{margin-top:var(--blockgap,30px)}
.blk > .wrap > .rule + *, .blk > .wrap > * + .rule{margin-top:32px}

/* asymmetric two column. Set --split per instance, never a 50/50 default. */
.split{display:grid;grid-template-columns:1fr;gap:var(--s-5)}
@media(min-width:880px){
  .split{grid-template-columns:minmax(0,var(--grid-l)) minmax(0,1fr);
    gap:var(--grid-gap);align-items:start}
  .split--baseline{align-items:baseline}
  .split--end{align-items:end}
}

/* full bleed band, escapes the wrap */
.band{position:relative;width:100%;overflow:hidden}

/* A block on a different ground. Full bleed by default because .blk is full width
   and .wrap does the containing. Used to stop the page reading as one long column. */
.blk--panel{background:var(--deep)}

/* ONE LEFT RAIL. Every section label and content block starts at the same x.
   The former .indent / .indent--sm / .inset-r offsets are DELETED: measured at 1440
   they produced five different left edges (153/196/269/343/376) where there should be
   one rail at 196, and .inset-r cancelled the auto centring of .wrap so pitch context
   sat LEFT of the rail entirely. Rhythm now comes from ground, measure and column
   split, never from a wandering x position. */

/* Centre a narrow measure inside the content column instead of letting it hug the
   rail with an empty right half. Centres the BLOCK; text stays left aligned inside. */
.measure{margin-inline:auto;max-width:72ch}
.measure--tight{margin-inline:auto;max-width:60ch}

/* Lets an element climb into the block above it so the seam between two sections
   is a deliberate overlap rather than a gap. */
.rise{margin-top:clamp(-140px,-9vh,-56px);position:relative;z-index:2}


/* -------------------------------------------------------------- chrome --- */
.chrome{position:absolute;top:0;left:0;right:0;z-index:40;
  display:flex;justify-content:space-between;align-items:center;gap:var(--s-3);
  padding:22px var(--gutter);
  font-family:var(--f-body);font-size:var(--t-1);letter-spacing:.16em;
  text-transform:uppercase;color:#fff}
/* Left: wordmark then the breadcrumb. Right: the Drummer Records lockup, on every
   page without exception. */
.chrome__left{display:flex;align-items:baseline;gap:12px;min-width:0}
/* Nav now sits directly on the image, so it carries its own legibility scrim rather
   than relying on a bar behind it. */
.chrome::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:-1;
  background:linear-gradient(180deg,rgba(0,0,0,.34),rgba(0,0,0,.10) 58%,transparent)}
.chrome a{text-decoration:none;opacity:.72;transition:opacity .3s ease}
.chrome a:hover{opacity:1}
.chrome .dot{opacity:.5}
.chrome__lockup{display:block;height:26px;width:auto;opacity:.9;flex:none}
.chrome__lockup:hover{opacity:1}
/* Right group: Safety Tour mark then the Drummer Records lockup. James Tonic pages only.
   THE DRUMMER LOCKUP DOES NOT MOVE. This group is the last flex child of a space-between
   container, so its right edge stays on the gutter, and the lockup, as the group's own last
   child, keeps the exact x it had when there was no group. The tour mark grows leftward
   into empty nav. Gap is var(--s-2) 12px, tighter than the container's var(--s-3) 20px, so
   the two marks read as one right hand pair rather than two unrelated items. */
.chrome__right{display:flex;align-items:center;gap:var(--s-2);flex:none}
/* EQUAL OPTICAL INK HEIGHT, ratio 1.00. v25, Frank's direction, superseding the v23 0.84.
   Still measured on ink, not boxes: drummer-lockup.png is trimmed tight so its ink height
   IS its box height, while safety-tour-banner.png carries 47 of 512 rows of transparent
   padding, an ink fraction of 0.9082. So matching ink at 26px needs a 28.63px box.

   THE NEGATIVE MARGIN IS LOad BEARING, do not remove it as tidying. A 28.63px box would
   set the flex line and push the nav from 70 to 72.63, which A4 forbids. margin-block
   pulls the MARGIN box back to 26px so the flex line, the nav height and the Drummer
   lockup all stay exactly where they were, while the extra 2.63px of the image, which is
   transparent padding and nothing else, overhangs invisibly and well inside the scrim.
   Ink lands on 22 to 48, identical to the lockup. */
.chrome__tour{display:block;height:28.63px;width:auto;margin-block:-1.315px;
  opacity:.9;flex:none}
.chrome__tour:hover{opacity:1}
@media(max-width:640px){
  /* PART A revert. v11 stacked these into a centred column, which broke the hero's single
     left edge. Actions wrap naturally now, left aligned on the title x.

     v32 CLASS 1 REMOVAL: `flex-wrap:wrap` and `align-items:center` deleted from this block.
     The base `.hero__cta` rule declares both identically and always applies, so these two
     could never win and could never change anything. Provably inert, verified at seven
     widths. `flex-direction:row` and `justify-content:flex-start` are LIVE here and stay.
     `gap:12px 18px` is NOT removed: it is dead but its value differs from the base 14/26,
     so it is CLASS 3 dead intent and needs a decision, not a deletion. See v32 Part D. */
  .hero__cta{flex-direction:row;justify-content:flex-start;
    gap:12px 18px}
}
@media(max-width:560px){
  .chrome{font-size:9.5px;letter-spacing:.16em;padding:16px var(--gutter)}
  /* v31: the .eyebrow--mark rule that lived here has MOVED, see the revived block below
     the typography section. It was dead where it sat. */
  .chrome__kind{display:none}
  .chrome__lockup{height:20px}
  /* Ratio 1.00 held at 402: 20px of ink against the lockup's 20px, same margin trick. */
  .chrome__tour{height:22.02px;margin-block:-1.01px}
}


/* ----------------------------------------------------------- typography -- */
/* TRACKING IS 0, and that is the point of a monospace face: it carries its own spacing at
   0.819em per character. The old .16em was there to open up DotGothic16. Measured at 402,
   tracking 0 leaves 12px of headroom on the tightest panel, .04em leaves -3.8px and
   overflows two pages, so the .16em label cap is not just unnecessary here, anything above
   0 breaks the fit. SIZE STAYS 12px: 13px renders crispest, 12.4% intermediate pixels
   against 13.2%, but it overflows How It Goes and Steven Voe artist by 21px at 402 even at
   tracking 0. Crispness lost to the D4 no-wrap constraint, deliberately. */
.eyebrow{font-family:var(--f-eyebrow);font-size:12px;letter-spacing:0;text-transform:uppercase;
  color:var(--glow)}
/* THE BRAND MARK. On the How It Goes cover the wordmark is dark pixel type knocked out
   of a bright rectangle, inverted against the dark image. That inversion is the mark,
   more recognizable than the face alone. Exactly one per page, in the hero. Section
   labels never take it, or the device stops meaning anything. */
.eyebrow--mark{display:inline-block;background:var(--paper);color:var(--ink);
  padding:5px 11px 4px;border-radius:0}
/* REVIVED IN v31. This is the v11 C7 rule, moved from the 560 block near .chrome where it
   had been dead since it was written. There it sat at source order 41 against
   `.eyebrow{letter-spacing:.16em}` at 45 and `.eyebrow--mark{padding:...11px}` at 46, equal
   specificity, so only `white-space:nowrap` ever applied. Its tracking and padding reduction,
   the two declarations written specifically to make the Safety panel fit at 402, never ran.
   Here it is after both, so it wins on source order and does what it always claimed to do.
   The brand mark must not wrap. Tracking is a cap, not a floor, so it yields here rather
   than the 12px size floor or any of the panel's content. */
@media(max-width:560px){
  /* The .03em the v11 rule carried is gone: base tracking is now 0 and anything above it
     overflows at 402. The padding reduction is what this rule is for now, and it is the
     half of it that always mattered. */
  .eyebrow--mark{white-space:nowrap;padding:5px 8px 4px}
}
.title{font-family:var(--f-display);font-weight:var(--title-w);letter-spacing:var(--title-t);
  font-size:var(--t-7);line-height:.9;color:#fff;text-shadow:0 2px 80px rgba(0,0,0,.55)}
.subhead{font-family:var(--f-lead);font-style:var(--lead-i);font-weight:var(--lead-w);
  font-size:clamp(17px,2.1vw,25px);color:var(--paper);letter-spacing:-.01em}
.lead{font-family:var(--f-lead);font-style:var(--lead-i);font-weight:var(--lead-w);
  font-size:var(--t-4);line-height:1.3;letter-spacing:-.015em;color:var(--paper)}
.lead--hold{max-width:26ch;margin-inline:auto}
/* S2. A headline that would run past five lines in the narrow left column spans the
   full content width instead, and its prose drops beneath it, starting at the shared
   right column x so the grid still reads. */
.split--wide{display:block}
.split--wide > .lead{max-width:none;margin-bottom:32px}
@media(min-width:880px){
  .split--wide > .body{margin-left:calc(var(--grid-l) + var(--grid-gap))}
}
.body p{color:var(--haze);font-size:15.5px;line-height:1.95}
.body p+p{margin-top:var(--s-3)}
.body strong{color:var(--paper);font-weight:500}
.note{font-family:var(--f-body);font-size:13.5px;line-height:1.8;color:var(--haze)}

/* section label. The hairline finishes the line it starts. */
.slabel{font-family:var(--f-label);font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);display:block;margin-bottom:20px}
/* The first thing under a label never adds its own top margin on top of that.
   v29: the !important is gone. It was only ever there to beat `.blk > .wrap > * + *`,
   which is (0,2,0); this selector is (0,3,0) and beats it on specificity alone. Removing
   the !important is what lets a per list fold-in below win in turn, at (0,4,0). Nothing
   else changes: the audit in v29 A2 confirmed the !important suppressed exactly two
   things, this block gap and the five dead fold-ins. */
.blk > .wrap > .slabel + *{margin-top:0}

/* type as the art. A pull quote set at display scale. */
.pull{font-family:var(--f-display);font-weight:var(--title-w);font-style:normal;
  font-size:var(--t-6);line-height:1.06;letter-spacing:-.03em;color:#fff;max-width:18ch;margin-inline:auto}
.pull--sm{font-size:var(--t-4);line-height:1.25;font-weight:500;letter-spacing:-.02em}
.pull__src{display:block;margin-top:var(--s-4);font-family:var(--f-body);font-size:10.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--haze);font-style:normal}


/* ---------------------------------------------------------------- hero ---
   A held film still. Cover full bleed, graded down, fog, letterbox, slow zoom.
   -------------------------------------------------------------------------- */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;
  overflow:hidden}
.hero__still{position:absolute;inset:0;
  background-image:var(--cover);background-position:center 28%;background-size:cover;background-repeat:no-repeat;
  filter:saturate(.62) contrast(1.06) brightness(.6);
  transform:scale(1.05);animation:slowzoom 24s ease-out both}
@keyframes slowzoom{from{transform:scale(1.12)}to{transform:scale(1.05)}}
.hero__fog{position:absolute;inset:0;
  background:
    radial-gradient(78% 52% at 60% 30%, var(--hair), transparent 62%),
    linear-gradient(180deg, rgba(0,0,0,.42) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.88) 92%, var(--ink) 100%),
    linear-gradient(90deg, rgba(0,0,0,.55), transparent 62%)}
/* DEFECT 1. The top bar was a solid --ink band painted over the first 41px of the hero
   image, which is the black gap Frank saw. Measured: page top colour == --ink exactly,
   first hero image pixel at y=41 (1440) and y=22 (402), on all six pages. The nav was
   already position:absolute on a transparent background, and html/body/hero all had zero
   padding and margin, so the bar was the sole cause. The TOP bar is deleted. The bottom
   bar stays: it closes the hero into the page ground and sits below the image, not above. */
.letterbox{position:absolute;left:0;right:0;height:clamp(26px,4.5vh,52px);background:var(--ink);z-index:5}
.letterbox--b{bottom:0}
.hero__in{position:relative;z-index:6;max-width:var(--maxw);width:100%;margin:0 auto;
  padding:0 var(--gutter) clamp(64px,11vh,132px)}
.hero .eyebrow{margin-bottom:24px;animation:fade .9s ease .15s both}
.hero .title{animation:rise 1.1s var(--ease) .3s both}
.hero .subhead{margin-top:28px;animation:rise 1.1s var(--ease) .5s both}
.hero__cta{display:flex;gap:14px 26px;margin-top:38px;flex-wrap:wrap;align-items:center;
  animation:fade 1s ease .8s both}


/* A supplied wordmark standing in for a set title. Screen blend drops the black
   plate out of the artwork so it sits in the still rather than on top of it. */
.hero__wordmark{display:block;width:min(560px,88%);height:auto;margin:0 0 6px -14px;
  mix-blend-mode:screen;pointer-events:none;animation:rise 1.1s var(--ease) .3s both}
.hero .hero__wordmark+.subhead{margin-top:20px}

/* a second, smaller still. Used when a page has to introduce a second record. */
.hero--minor{min-height:62svh}
.hero--minor .title{font-size:var(--t-6)}

@keyframes rise{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}


/* The numbers, once per page, opening pitch context. A hairline row, not a stat bar:
   no cells, no borders between items, no display sized figures. */
.statrow{display:flex;flex-wrap:wrap;justify-content:center;gap:8px 34px;padding:15px 0;
  border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);margin-bottom:var(--s-5);
  font-family:var(--f-body);font-size:12.5px;color:var(--haze)}
.statrow b{color:var(--paper);font-weight:600}

/* Inline text links. Used wherever a list of destinations would otherwise become a
   table of printed URLs or a stack of arrowed rows. */
.inlinks{display:flex;flex-wrap:wrap;justify-content:center;gap:8px 26px;font-size:14.5px}
.inlinks a{color:var(--paper);text-decoration:none;border-bottom:1px solid var(--hair);
  padding-bottom:3px;transition:border-color .3s ease}
.inlinks a:hover{border-bottom-color:var(--glow)}


/* A hero line quote. Deliberately NOT .pull: it must sit under the title without
   competing with it, so it is set well below display scale, left aligned on the same
   x as the title and subtitle, and carries no attribution, eyebrow or label. */
.qline{font-family:var(--f-body);font-weight:400;font-size:clamp(13px,1.05vw,15px);
  line-height:1.5;letter-spacing:normal;font-style:normal;color:var(--haze);opacity:.55;
  margin:18px 0 0}
.hero .qline + .subhead{margin-top:20px}


/* -------------------------------------------------------------- actions -- */
/* ONE MATCHED SET, v25. Frank's direction, superseding the v23 arrangement of a solid
   accent slab beside underlined text links, which was three shapes doing one job.
   Every action now shares the same box: same height, padding, border weight, type and
   tracking. THE PRIMARY IS DISTINGUISHED BY COLOUR, NOT BY SHAPE. No solid slab.
   Square corners, because the system has no radius token and the only border-radius in
   this sheet is the 0 on .eyebrow--mark. */
.cta{font-family:var(--f-body);font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  text-decoration:none;display:inline-flex;align-items:center;gap:.7em;transition:all .3s ease;
  padding:12px 24px;border:1px solid var(--hair)}
/* Primary: accent hairline plus the page's own --hair as a low opacity accent wash, so the
   hero still reads through the button. --hair IS glow at low alpha and already exists per
   page, so no new token and no colour is invented here. Alpha is .15 on five pages and .20
   on Safety, which is that page's own hairline value carried over from the v24 revert. */
.cta--solid{color:var(--paper);background:var(--hair);border-color:var(--glow)}
.cta--solid:hover{color:var(--glow)}
/* Secondary: identical box, muted rule colour, body text label, accent kept for the arrow.
   The standalone underline is gone; the box replaces it. */
.cta--ghost{color:var(--paper);background:transparent;border-color:var(--hair)}
.cta--ghost:hover{border-color:var(--glow)}
.cta .arw{color:var(--glow);transition:transform .3s var(--ease)}
.cta:hover .arw{transform:translateX(4px)}

.slink{font-family:var(--f-body);font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  text-decoration:none;color:var(--paper);display:inline-flex;gap:.6em;align-items:center;
  padding-bottom:6px;border-bottom:1px solid var(--hair);transition:border-color .3s ease}
.slink:hover{border-bottom-color:var(--glow)}
.slink .arw{color:var(--glow);transition:transform .3s var(--ease)}
.slink:hover .arw{transform:translateX(4px)}
.slink-row{display:flex;gap:12px 22px;flex-wrap:wrap}

/* Action row at 402. Side padding drops to 12px because the full 24px would push Safety
   from two rows to three and move the whole hero stack. Measured: 4px to 12px is the band
   that holds every page's current row count, so this sits at the top of it.
   The 1px row gap reduction is arithmetic, not taste: the old two row height was one 46.1
   solid plus one 45.1 ghost plus a 14px gap. Equalising the boxes makes both 46.1, so the
   gap gives back the 1px and the row's outer height, and everything above it, does not move.
   This block must stay AFTER the .cta rules above; the 640px .hero__cta block earlier in
   this file is already dead on source order and is not the place to put this. */
@media(max-width:560px){
  .cta{padding:12px 12px}
  .hero__cta{gap:13px 26px}
}



/* -------------------------------------------------------------- imagery -- */
/* square cover, framed, lit from behind by the world's glow */
.art{aspect-ratio:1/1;overflow:hidden;border:1px solid var(--hair);position:relative;
  box-shadow:0 40px 90px -50px rgba(0,0,0,.9), 0 0 80px -40px var(--hair)}
.art img{width:100%;height:100%;object-fit:cover;filter:saturate(.8)}
/* Text placeholder shown only if the cover image fails to load (onerror adds
   .art--fallback). Preserves the artist/title where the art would have been. */
.art__fallback{display:none}
.art--fallback{display:flex;align-items:center;justify-content:center;background:var(--panel)}
.art--fallback .art__fallback{display:block;text-align:center;padding:var(--s-4);
  font-family:var(--f-display);font-size:var(--t-4);line-height:1.15;color:var(--paper)}

/* press photo. Graded to sit in the world rather than punch out of it. */
.plate{overflow:hidden;border:1px solid var(--hair);position:relative}
.plate img{width:100%;height:100%;object-fit:cover;
  filter:saturate(.55) contrast(1.06) brightness(.92);transition:filter .6s ease}
.plate:hover img{filter:saturate(.8) contrast(1.04) brightness(1)}
.plate::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 55%,rgba(0,0,0,.45))}
.plate--tall{aspect-ratio:3/4}
.plate--wide{aspect-ratio:16/9}

/* A2. Plate row: three across at the CONTENT MEASURE, equal height, equal gutters,
   tops and bottoms on one baseline. Stacks full width at 402 in the same order. */
.plates{display:grid;grid-template-columns:1fr;gap:var(--grid-gap)}
@media(min-width:760px){.plates{grid-template-columns:repeat(3,1fr)}}
.plate--sq{aspect-ratio:4/5}
.plate--sq img{width:100%;height:100%;object-fit:cover}

/* C1. A cover that spans the full content measure, so nothing sits beside it and the
   block's ink centres on the page. CSS crop only, the file is untouched. */
.art--band{aspect-ratio:16/7;width:100%;border:1px solid var(--hair);overflow:hidden}
.art--band img{width:100%;height:100%;object-fit:cover;object-position:center 38%;filter:saturate(.8)}

/* A4. Six stats rendered 4 + 2. Cap the row so it balances 3 + 3 at 1440. */
@media(min-width:900px){.statrow{max-width:640px;margin-inline:auto}}

/* A6. The follow row was reading as a wrap of the link row above it. */
.foot__grid + .inlinks{margin-top:var(--s-5)}

/* two up image band, deliberately unequal */
.strip{display:grid;grid-template-columns:1fr;gap:3px}
@media(min-width:760px){.strip{grid-template-columns:var(--strip,1.45fr 1fr)}}


/* --------------------------------------------------------------- triad ---
   Editorial row list. Big name, small place, quiet description. Carries real
   content (people, cities, records), never decoration.
   -------------------------------------------------------------------------- */
.triad{border-top:1px solid var(--hair)}
.triad__row{display:grid;grid-template-columns:1fr;gap:6px 34px;
  padding:clamp(22px,3.4vh,34px) 0;border-bottom:1px solid var(--hair)}
@media(min-width:720px){
  .triad__row{grid-template-columns:minmax(0,var(--grid-l)) minmax(0,1fr);
    gap:var(--grid-gap);align-items:baseline}
}
.triad__name{font-family:var(--f-display);font-weight:var(--title-w);letter-spacing:-.028em;
  font-size:var(--t-5);line-height:.98;color:#fff;display:block}
.triad__place{font-family:var(--f-body);font-size:var(--t-1);letter-spacing:.16em;
  text-transform:uppercase;color:var(--glow);display:block;margin-top:12px}
.triad__desc{color:var(--haze);font-size:15px;line-height:1.7}


/* Press quotes as one running list: quote, attribution, hairline. Never at display
   scale, never in a grid of cards. */
.quotes{border-top:1px solid var(--hair)}
.quotes blockquote{padding:var(--s-4) 0;border-bottom:1px solid var(--hair);margin:0}
.quotes p{font-family:var(--f-body);font-size:16px;line-height:1.7;color:var(--paper);
  margin:0}
.quotes cite{display:block;margin-top:10px;font-family:var(--f-body);font-size:12.5px;
  color:var(--haze);font-style:normal}


/* ---------------------------------------------------------------- rail ---
   Discography. A vertical hairline with records hung off it, ordered. Reads as
   a timeline, not a card wall.
   -------------------------------------------------------------------------- */
.rail{position:relative;border-top:1px solid var(--hair)}
.rail__item{display:grid;grid-template-columns:1fr;gap:var(--s-3);
  padding:var(--s-5) 0;border-bottom:1px solid var(--hair);position:relative}
@media(min-width:860px){
  /* B2. The date column was taking the full 300px shared left column, leaving only 246px
     of text and wrapping one title and four meta lines. It now takes only what its longest
     string needs, "NOVEMBER 27, 2025", plus the gutter. */
  .rail__item{grid-template-columns:minmax(0,156px) minmax(0,1fr);
    gap:var(--grid-gap);align-items:start}
  /* S3. The thumbnail lives INSIDE the right column, so rows with artwork and rows
     without both start their record block on the same shared right column x. No row
     holds an empty art slot open. */
  .rail__body{display:flex;gap:var(--s-4);align-items:start}
  .rail__body > .rail__art{flex:none}
  .rail__body > div{flex:1;min-width:0}
}
.rail__when{font-family:var(--f-body);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--glow);padding-top:8px}
.rail__art{width:150px;max-width:100%}
.rail__name{font-family:var(--f-display);font-weight:var(--title-w);letter-spacing:-.025em;font-size:var(--t-4);
  line-height:1.05;color:#fff;display:block}
.rail__meta{font-family:var(--f-body);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);margin-top:10px}
.rail__desc{color:var(--haze);font-size:15px;line-height:1.8;margin-top:var(--s-3)}
.rail__links{margin-top:var(--s-3)}


/* ---------------------------------------------------------------- spec ---
   Hairline key/value list. Release data, credits, anything tabular. Never a
   bordered table, never cards.
   -------------------------------------------------------------------------- */
.spec{border-top:1px solid var(--hair)}
/* The value column carries a hard minimum so it can never collapse. The label column
   is the one that yields. Measured failure before this: 18px value cells at 402 and 0px
   when the table was nested inside a grid column. */
.spec__row{display:grid;
  grid-template-columns:minmax(0,var(--grid-l)) minmax(360px,1fr);
  gap:var(--grid-gap);min-height:52px;padding:15px 0;border-bottom:1px solid var(--hair);
  align-items:baseline}
/* At narrow widths the row stacks: label, then value, both full width, one hairline. */
@media(max-width:760px){
  .spec__row{grid-template-columns:1fr;gap:5px;min-height:0;padding:13px 0}
}
.spec__k{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);min-width:0;overflow-wrap:normal;word-break:normal}
.spec__v{font-family:var(--f-body);font-size:14.5px;color:var(--paper);min-width:0;
  overflow-wrap:normal;word-break:normal}
/* URLs are single unbreakable tokens. Without an explicit break they push the grid
   wider than the viewport and the whole page scrolls sideways on a phone. */
.spec__v--mono{font-size:13px;letter-spacing:.01em;font-variant-numeric:tabular-nums}
.spec-cols{display:grid;grid-template-columns:1fr;gap:var(--s-7)}


/* ------------------------------------------------------------ downloads --
   Filmic hairline list. Rows step right on hover like a contact sheet.
   -------------------------------------------------------------------------- */
.dl{border-top:1px solid var(--hair)}
.dl a{display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center;
  padding:clamp(18px,2.6vh,26px) 0;border-bottom:1px solid var(--hair);
  text-decoration:none;transition:padding-left .3s ease}
.dl a:hover{padding-left:14px}
/* v29. `.dl a:last-child{padding-bottom:0}` REMOVED. It was a third last-child override,
   separate from the two shared ones, and it was the widest asymmetry on the site: 23.4px
   above the first row's ink against 0 below the last row's, on all six pages. Its comment
   claimed it folded the bottom padding into the section's, but the row has its own
   border-bottom, so the last row was simply sitting on its rule with no space at all. */
.dl__t{display:block;font-family:var(--f-lead);font-style:var(--lead-i);font-weight:500;font-size:var(--t-3);letter-spacing:-.015em;
  color:var(--paper)}
.dl__d{display:block;font-family:var(--f-body);font-size:13px;color:var(--haze);margin-top:5px}
.dl__go{font-family:var(--f-body);font-size:var(--t-1);letter-spacing:.16em;text-transform:uppercase;
  color:var(--glow);white-space:nowrap}
/* When the affordance is a literal URL, never uppercase it. Paths are case sensitive
   and a shouted URL reads as a different address than the one it links to. */
.dl__go--url{text-transform:none;letter-spacing:.04em;font-size:12px;
  white-space:normal;word-break:break-all;text-align:right}
@media(max-width:640px){
  .dl a{grid-template-columns:1fr;gap:8px}
  .dl__go{white-space:normal}
}
/* a quiet heading inside a long list, so 12 rows read as groups */
.dl__group{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);padding:var(--s-5) 0 var(--s-2);border-bottom:1px solid var(--hair)}


/* --------------------------------------------------------------- aside ---
   Marginal note beside the body copy. The pitch lives here rather than in a
   three column wall.
   -------------------------------------------------------------------------- */
.aside{border-left:1px solid var(--hair);padding-left:var(--s-4)}
.aside+.aside{margin-top:var(--s-5)}
.aside__h{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--glow);margin-bottom:var(--s-3)}
.aside p{color:var(--haze);font-size:14.5px;line-height:1.85}
.aside ul{list-style:none}
.aside li{color:var(--haze);font-size:14.5px;line-height:1.9;padding-left:18px;position:relative}
.aside li::before{content:"";position:absolute;left:0;top:.85em;width:6px;height:1px;background:var(--glow)}
.aside strong{color:var(--paper);font-weight:500}


/* Video embed. Responsive 16/9 container. The iframe markup itself is carried over
   from the live tree unchanged: never alter a video id, URL or title. */
.embeds{display:grid;grid-template-columns:1fr;gap:var(--s-4)}
@media(min-width:760px){.embeds{grid-template-columns:1fr 1fr}}
.embed{position:relative;aspect-ratio:16/9;border:1px solid var(--hair);overflow:hidden;
  background:var(--panel)}
.embed iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.embed__cap{font-family:var(--f-body);font-size:12.5px;color:var(--haze);margin-top:10px}


/* ---------------------------------------------------------------- tour ---
   Full bleed band. The only centred block in the system, which is what makes
   it land after so much left aligned type.
   -------------------------------------------------------------------------- */
.tour{padding:60px 0;position:relative;text-align:center}
.tour__eye{font-family:var(--f-body);font-size:var(--t-1);letter-spacing:.16em;text-transform:uppercase;
  color:var(--glow);margin-bottom:var(--s-3)}
.tour__mark{display:block;width:min(440px,88%);height:auto;margin:0 auto var(--s-4);
  mix-blend-mode:screen}
.tour__line{font-family:var(--f-lead);font-style:var(--lead-i);font-weight:var(--lead-w);font-size:clamp(21px,3vw,36px);
  line-height:1.25;letter-spacing:-.02em;color:#fff;margin:0 auto var(--s-4);max-width:30ch}
.tour__cta{font-family:var(--f-body);font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  text-decoration:none;color:var(--paper);border-bottom:1px solid var(--glow);padding-bottom:6px}


/* ------------------------------------------------------------- contact --- */
.contact{display:grid;grid-template-columns:1fr;gap:var(--s-6)}
@media(min-width:820px){.contact{grid-template-columns:minmax(0,var(--grid-l)) minmax(0,1fr);
  gap:var(--grid-gap)}}
.contact__k{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--glow);margin-bottom:var(--s-2)}
.contact__v{font-family:var(--f-lead);font-style:var(--lead-i);font-weight:var(--lead-w);font-size:var(--t-3);color:#fff}
.contact__v a{text-decoration:none;border-bottom:1px solid var(--hair)}
.contact__v a:hover{border-bottom-color:var(--glow)}
.contact__tags{margin-top:var(--s-3);font-family:var(--f-body);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--haze)}


/* ---------------------------------------------------------- global foot --
   The no dead ends guarantee. Same on every page in every stage.
   -------------------------------------------------------------------------- */
.foot{border-top:1px solid var(--hair);padding:44px 0 40px;margin-top:60px}
/* v15 A1 ROOT CAUSE. This was display:flex with flex-wrap, so whenever the left column
   content was wide the two columns exceeded the measure and WRAPPED. Markup was identical
   on all six pages but three of them rendered stacked and three rendered two up, which is
   exactly the split Frank saw. It is now the shared page grid, so both columns land on the
   same x as every other column and cannot wrap. */
/* A1. The shared 300px left column could not hold the longest identity strings, which
   measured 438px (How It Goes), 325px (I Wish) and 311px (Back From The Dead) and wrapped
   mid title. The footer left column is widened to fit the longest. NOTE: this moves the
   footer RIGHT column off the shared 676px x, which is the A3 conflict reported to Frank.
   The left column still starts at 336 like every other left column. */
/* D1. v16 widened the left column to 460 and the right fell to 268, which wrapped the
   five item site link row on ALL SIX pages. Left keeps what the longest identity needs
   (438px), the gap tightens, and the right takes the rest. */
.foot__grid{display:grid;grid-template-columns:minmax(0,446px) minmax(0,1fr);
  gap:20px;align-items:start}
@media(max-width:760px){.foot__grid{grid-template-columns:1fr;gap:var(--s-5)}}
.foot__k{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);margin-bottom:var(--s-2)}
.foot__v{font-family:var(--f-lead);font-style:var(--lead-i);font-weight:var(--lead-w);font-size:20px;color:#fff}
.foot__v a{text-decoration:none;border-bottom:1px solid transparent;transition:border-color .3s ease}
.foot__v a:hover{border-bottom-color:var(--glow)}
.foot__nav{display:flex;flex-wrap:wrap;gap:10px 22px;
  font-family:var(--f-body);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase}
.foot__nav a{text-decoration:none;color:var(--haze);transition:color .3s ease}
.foot__nav a:hover{color:var(--glow)}
.foot__mark{font-family:var(--f-body);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--haze);opacity:.65;margin-top:var(--s-6)}


/* ------------------------------------------------------- reduced motion --
   Everything decorative stops. Nothing structural depends on animation, so the
   page is complete and static.
   -------------------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
  .hero__still{transform:scale(1.05);animation:none}
  .reveal{opacity:1;transform:none}
}


/* ============================================================================
   BANNED PATTERNS. Deleted at component level, not per instance, so no later
   stage can reuse them. Reference for what this site must never resemble:
   a generated template portfolio. Full rationale: docs/redesign/DESIGN-SYSTEM.md

   1. Label with a trailing hairline welded to the text (LABEL --------).
      DELETED from .slabel. Labels are plain text; a divider is .rule, full width,
      on its own line.
   2. Outlined tag chips (.pill / .pill-row). DELETED. Their content always already
      existed in the metadata line beside them. Sole surviving inverted element is
      .eyebrow--mark, the brand mark, one per page.
   3. Oversized ghost numerals in margins (01 02 03). Never existed here. Never add.
   4. Repeated decorative ornaments. The light leak stays a gradient in the page
      fabric (.rule), never a stamped glyph.
   5. Italic numbered kickers ("01, Playlist Curation"). Never.
   6. Bordered cell grids for flat lists. .spec is hairline rows only: no vertical
      rules, no enclosing box. Match it for any new tabular data.
   7. One accent word coloured or italicised inside a headline. Never, in any face.
   8. Buttons as outlined rectangles with centred tracked text. CTAs are text links
      (.cta--ghost, .slink, .inlinks) or the solid panel button (.cta--solid).
   9. Hero stat strip (.hero__meta). DELETED. Numbers appear once per page, as
      .statrow opening pitch context.
  10. Wandering per section indents (.indent, .indent--sm, .inset-r, .wrap--narrow).
      DELETED. Measured at 1440 they gave five different left edges where there should
      be one rail. Rhythm comes from ground, measure and column split, never from x.
  11. Centre aligned text, and centred widget blocks. Text is always left aligned
      inside its block. .measure centres the BLOCK, never the text.
   ========================================================================= */


/* ============================================================================
   S1 CONTINUED. List components carried their own first row top padding and last
   row bottom padding, which summed with the section padding on top of it. Measured
   as label to ink gaps of 82px and section gaps 25 to 40px over cap. Fold them in.
   ========================================================================= */
/* LABEL FOLD-IN, v29. The dead -18px rule is REPLACED, not left in the sheet doing
   nothing. It never applied because it was (0,2,0) against an !important; these are
   (0,4,0) against the (0,3,0) zeroing rule above, so they are live and measurable.

   A ruled list opens with its own first row padding, and that padding differs per list,
   so one shared value cannot land them all. Each value below is set so label to first
   ink lands at roughly 40px on every list, comfortably inside the 48px guide, and each
   was measured rather than derived, because the first ink's offset inside its row
   depends on whether the row opens with type or with a cover image.
   If a list's row padding changes, re-measure these. */
.blk > .wrap > .slabel + .rail{margin-top:-38px}
.blk > .wrap > .slabel + .quotes{margin-top:-16px}
.blk > .wrap > .slabel + .dl{margin-top:-11px}
/* The rail needs 9px more at 402. The row is single column there, so the first ink is the
   date line rather than the cover and it sits lower inside the same 56px padding: -38px
   lands 49, one pixel over the guide, and -47px lands 40, matching 1440. Measured, not
   derived. This block MUST stay after the base fold-ins above; an identical rule placed
   earlier in the sheet loses on source order at equal specificity, which is exactly how
   the original -18px fold-in died. */
@media(max-width:560px){
  .blk > .wrap > .slabel + .rail{margin-top:-47px}
}
.blk > .wrap > .slabel + .spec{margin-top:-1px}
/* v27. `.rail__item` REMOVED from both overrides, not adjusted. A ruled list row is
   bounded by its own rules on both sides: `.rail` carries border-top and every
   `.rail__item` carries border-bottom, so row 1 and row 5 each sit between two rules
   exactly like the interior rows do. The 16px and 10px were therefore a real row
   asymmetry, not section edge padding, and v22, v23 and v25 explained them wrongly.
   Discography rows are now a uniform 56/56 from `.rail__item` alone.
   DO NOT reintroduce a first-child or last-child padding override on a ruled list. */
/* v29. THE SWEEP. Every remaining ruled list follows v27's discography treatment:
   removed from these overrides rather than given a per list override of its own.
   Downloads went first, it was the widest asymmetry on the site at 16 top against 0
   bottom, on all six pages. What is left below is deliberately empty of ruled lists.

   EXCLUDED BY DESIGN, do not add them here:
     .crow  contact rows are asymmetric on purpose, tuned in v20 row 8f to centre the
            ink in the band. 8f says do not restore the asymmetry. Untouched.
     .foot__nav  has no rules and no padding. Already symmetric by having nothing. */
/* (no ruled list first-child or last-child padding overrides remain) */
.blk > .wrap > .triad + *, .blk > .wrap > .rail + *,
.blk > .wrap > .dl + *, .blk > .wrap > .spec + *{margin-top:32px}

/* C2. "The Drummer Records press team" measured ~331px against the shared 300px column.
   Appended so it wins on order: the value size yields rather than the grid. */
.contact__v{font-size:19px;line-height:1.35}
/* The press team line measured ~310px against the shared 300px column. It runs on one
   line into the 40px column gap rather than the grid changing or the type shrinking
   further. No collision: the gap absorbs the overflow. */
@media(min-width:820px){.contact__v--run{white-space:nowrap}}

/* v14 TAIL. One canonical component. Gaps folded so the tail cannot balloon: the six
   tails measured 627 to 2493px before this, a 298% spread. */
#contact .contact__v + .contact__v{margin-top:6px}
#contact .contact__tags{margin-top:18px}
.contact__k--follow{margin-top:40px}
.contact__k--follow + .inlinks{margin-top:14px}
.foot__v + .foot__nav{margin-top:14px}
.foot__k + .foot__nav{margin-top:14px}
.foot__mark{margin-top:40px}

/* v15 B1. CONTACT as three hairline rows at the metadata table rhythm. Nothing in the
   contact section is set larger than a metadata table value. */
.crow{display:grid;grid-template-columns:minmax(0,var(--grid-l)) minmax(360px,1fr);
  gap:var(--grid-gap);min-height:52px;padding:15px 0;border-bottom:1px solid var(--hair);
  align-items:baseline}
.crow--full{display:block;min-height:0}
.crow--follow{display:block;min-height:0;border-bottom:none;padding:13px 0 9px}
.crow__v{font-family:var(--f-body);font-size:14.5px;color:var(--paper);font-weight:400}
.crow__v a{text-decoration:none;border-bottom:1px solid var(--hair)}
.contact-rows{border-top:1px solid var(--hair)}
@media(max-width:760px){.crow{grid-template-columns:1fr;gap:5px;min-height:0;padding:13px 0}}
.foot__mark{margin-top:36px}

/* v17 A1. The contact row now carries a single value. */
.crow--one{display:block;min-height:52px;padding:15px 0}

/* v17 B1/B2. FOURTH APPROVED CENTRING EXCEPTION, Frank's explicit direction. The routing
   line centres horizontally on the content measure and vertically inside its hairline row.
   Approved list is now: Safety Tour lockup, Pitch Context stat row, follow rows, routing. */
.crow--full{display:flex;align-items:center;justify-content:center;min-height:52px;padding:2px 0 0}
#contact .crow--full .contact__tags{text-align:center;margin:0}

/* v17 C2. Artwork and text are centred against each other inside a discography row, so
   neither column hangs past the other. Measured before: art hung +37px on four rows and
   text hung 29px past the art on How It Goes. */
@media(min-width:860px){
  .rail__body{align-items:center}
  .rail__item{align-items:center}
}
/* C4. The How It Goes billing line was wrapping at 376px. Tighten its tracking so the
   longest meta string holds one line without changing the artwork box or the type size. */
.rail__meta{letter-spacing:.05em}

/* D1. Appended so it wins on order. The five item site link row needs 291px and the right
   column is 302px, but at the base 22px gap it still wrapped. Tightening the gap on the
   site row only, not the identity row. */
.foot__grid > div:last-child .foot__nav{gap:8px 14px}

/* v19 A1. FIFTH APPROVED CENTRING EXCEPTION. The contact email row centres on both axes,
   matching the routing line above it. This REVERSES Frank's v17 left align call: his v17
   reasoning was that the email sat directly under the CONTACT label, and the v18 reorder
   put the centred routing line between them, which removed that anchoring. */
.crow--one{display:flex;align-items:center;justify-content:center;text-align:center;
  min-height:52px;padding:15px 0}

/* v19 B1. On I Wish THE RECORD the square cover was 149px taller than its one paragraph
   text block. The TEXT COLUMN now sets the image height: the grid row stretches to the
   text, and the figure takes that height with aspect-ratio 1 so width follows height.
   No distortion, no crop, no object-position trickery. That page only. */
@media(min-width:880px){
  /* CSS cannot size an image from a sibling's content height without circularity: the
     image is in the column that would set the row height. align-items:stretch only grew
     the TEXT box to the image. So the cover takes an explicit square that matches the
     measured text ink height (181px) instead. Aspect ratio preserved exactly, no crop,
     no distortion, width follows height. */
  .split--fit{align-items:start}
  .split--fit > .art{width:181px;height:181px;aspect-ratio:1/1;justify-self:start}
}

/* v20 B4: follow row, mobile. .crow{padding:13px 0} in the 760 block outranks
   .crow--follow by source order and restores symmetric padding. The .inlinks anchor
   carries padding-bottom:3px + 1px border (the underline offset), so its ink sits 2px
   above its box centre. 15/11 shifts the box down 2px. Total 26px, band unchanged. */
@media(max-width:760px){.crow--follow{padding:15px 0 11px}}
