/* ============================================================
   DETERMIND — determind-official.com
   Design system derived from "Determind Portfolio 2026_v3".

   Colours were sampled from the deck itself, not chosen:
   #0c0c0c covers 37% of the deck surface, #e4e4e4 covers 11%.
   The deck contains NO accent colour — deliberately no red here,
   unlike stargazing-records.com. Restraint is the brand.

   Type: Anton (display) and Lato (body) match the deck exactly.
   The deck's label font, Agrandir, is a commercial licence and
   cannot ship on the web — Space Grotesk stands in for it.
   ============================================================ */

:root{
  /* ground */
  --bg:          #0c0c0c;
  --surface:     #181818;
  --surface-2:   #242424;
  --line:        #2e2e2e;
  --line-strong: #454545;

  /* ink */
  --text:        #e4e4e4;
  --text-dim:    #8a8a8a;
  --white:       #ffffff;
  --ivory:       #f0f0e4;   /* light panel — the deck's contents page */

  /* type */
  --display: 'Anton', 'Arial Narrow', sans-serif;
  --label:   'Space Grotesk', system-ui, sans-serif;
  --body:    'Lato', system-ui, sans-serif;

  /* rhythm */
  --wrap: 1280px;
  --gut: clamp(20px, 4vw, 56px);
  --rail-h: 58px;
}

*{ box-sizing:border-box; }
html{
  scroll-behavior:smooth;
  /* iOS inflates type when a phone is turned to landscape unless told not to */
  -webkit-text-size-adjust:100%; text-size-adjust:100%;

  /* Guard against a stray wide child sidescrolling the page.
     This MUST be `clip` on <html>, not `hidden` on <body>. Per spec, an element
     with overflow-x:hidden and overflow-y:visible has its overflow-y forced to
     `auto` — which turns <body> into its own scroll container and leaves the
     document itself with almost nothing to scroll. The page then sticks a few
     pixels down and window.scrollY never advances, which silently kills every
     scroll-driven behaviour on the site. `clip` has no such side effect.
     Older Safari ignores it, which is harmless: the responsive audit found no
     horizontal overflow on any page at any width, so this is a seatbelt. */
  overflow-x:clip;
}
body{
  margin:0; background:var(--bg); color:var(--text);
  font-family:var(--body); font-size:16px; line-height:1.65;
  -webkit-font-smoothing:antialiased;
  /* the default blue-grey flash on tap looks like a bug on a dark site */
  -webkit-tap-highlight-color:transparent;
}
/* Long Vietnamese titles in a narrow column must break rather than overflow. */
h1,h2,h3,p,a,span{ overflow-wrap:break-word; }
/* `height:auto` is not cosmetic. Where an <img> carries width/height attributes
   for layout stability AND a CSS width, the HTML height wins on the other axis
   and the picture stretches — the pack artwork rendered 338×1000 instead of a
   square. This lets the aspect ratio survive the attributes. */
img{ max-width:100%; height:auto; display:block; }
a{ color:inherit; text-decoration:none; }
h1,h2,h3{
  font-family:var(--display); font-weight:400; margin:0;
  text-transform:uppercase; line-height:.92; letter-spacing:.01em;
}

.wrap{ max-width:var(--wrap); margin:0 auto; padding:0 var(--gut); }
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ============================================================
   HEADER — DTRMND mark left, nav right
   One sticky bar, same pattern as stargazing-records.com. The deck's
   four-column rail was dropped: it repeated the brand name twice and
   spent 58px of every screen on a year and a section label the visitor
   can already see.
   ============================================================ */
/* The bar was 82% opaque with a backdrop blur. Over the dark sections that read
   beautifully; over the ivory panels enough light bled through to lift the bar
   towards mid-grey, and dim-grey labels on mid-grey are unreadable. The site
   now has four light sections, so the bar is opaque. */
.nav{
  position:sticky; top:0; z-index:100;
  background:#0c0c0c;
  border-bottom:1px solid var(--line);
  transition:background .35s ease, box-shadow .35s ease;
}
.nav.scrolled{ background:#080808; box-shadow:0 8px 30px rgba(0,0,0,.5); }
.nav-inner{
  max-width:var(--wrap); margin:0 auto; padding:14px var(--gut);
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  transition:padding .35s ease;
}
.nav.scrolled .nav-inner{ padding:9px var(--gut); }

.brand{ display:flex; align-items:center; gap:13px; flex:none; }
.brand img{
  height:38px; width:auto; display:block;
  transition:transform .4s cubic-bezier(.2,.7,.3,1), height .35s ease;
}
.brand:hover img{ transform:scale(1.07); }
.nav.scrolled .brand img{ height:30px; }
.brand span{
  font-family:var(--display); font-size:20px; letter-spacing:.04em;
  color:var(--white); text-transform:uppercase; line-height:1;
  transition:font-size .35s ease;
}
.nav.scrolled .brand span{ font-size:17px; }

/* Was --text-dim (#8a8a8a). At 12px, uppercase and tracked out to .18em that
   is far fainter than the same grey in a paragraph — tracking thins the strokes
   and there is less of each letter to catch the eye. #c9c9c9 keeps the
   hierarchy under the active item while staying comfortably legible. */
.nav a{
  font-family:var(--label); font-size:12px; letter-spacing:.16em;
  text-transform:uppercase; color:#c9c9c9;
  padding:8px 0; transition:color .2s ease; position:relative;
}
.nav a:hover, .nav a.is-active{ color:var(--white); }
.nav a.is-active::after{
  content:''; position:absolute; left:0; right:0; bottom:2px;
  height:1px; background:var(--white);
}
.nav-links{ display:flex; align-items:center; gap:clamp(16px,2.6vw,34px); margin-left:auto; }
/* Book is the one action the whole site exists to produce. It was an outlined
   button in the same dim grey as the ordinary links — the least prominent thing
   in the header. Solid white, so it reads as a button and not as a fifth link. */
.nav-links .btn{
  padding:12px 22px; background:var(--white); color:#0c0c0c;
  border-color:var(--white); font-weight:600;
}
.nav-links .btn::before{ content:none; }
.nav-links .btn:hover, .nav-links .btn:focus-visible{
  background:transparent; color:var(--white); border-color:var(--white);
}
.nav-toggle{
  display:none; background:none; border:0; color:var(--text);
  font-size:22px; cursor:pointer; padding:4px 8px; margin-left:auto;
}

/* ============================================================
   SECTION FURNITURE
   ============================================================ */
.section{ padding:clamp(56px,9vh,110px) 0; }
.section.tight{ padding:clamp(36px,6vh,68px) 0; }
.eyebrow{
  font-family:var(--label); font-size:11px; letter-spacing:.28em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 14px;
}
.title{ font-size:clamp(30px,5.2vw,62px); color:var(--white); }
.lede{
  font-size:clamp(15px,1.5vw,18.5px); line-height:1.7;
  color:var(--text); max-width:62ch; margin:20px 0 0;
}
.rule{ height:1px; background:var(--line); border:0; margin:0; }

/* ============================================================
   HERO — the deck's cover composition
   The name is set enormous and the figure stands in front of it, so the
   two overlap. Type and portrait share one grid cell and are separated
   by z-index rather than by columns.
   ============================================================ */
.hero{ position:relative; overflow:hidden; border-bottom:1px solid var(--line); }
.hero-inner{
  max-width:var(--wrap); margin:0 auto; padding:clamp(26px,5vh,54px) var(--gut) 0;
  position:relative; min-height:min(88vh,860px);
  display:flex; flex-direction:column; justify-content:flex-end;
}
.hero-stage{ position:relative; width:100%; }

/* the name — sized to fill the measure, sitting behind the figure */
.hero h1{
  font-size:clamp(64px,15.5vw,250px); color:var(--white);
  line-height:.82; letter-spacing:-.012em; text-align:center;
  position:relative; z-index:1; margin:0;
  /* optical: Anton carries side bearings that make a centred line look
     left-heavy at display size */
  padding-left:.02em;
}
.hero .kicker{
  font-family:var(--label); font-size:clamp(10px,1.15vw,13px);
  letter-spacing:.34em; text-transform:uppercase;
  color:var(--text-dim); text-align:center; margin:0 0 clamp(10px,1.6vh,20px);
  position:relative; z-index:4;   /* above the figure, which rises past it */
}
.hero-media{
  position:relative; z-index:2;
  /* The figure sits in front of the name. Measured at 1318px: at -19vw the head
     rose 49px past the kicker's baseline, and dim grey type over dark hair is
     unreadable however the z-index falls. -12vw clears it at every width. */
  margin-top:clamp(-160px,-12vw,-50px);
  display:flex; justify-content:center; pointer-events:none;
}
/* A true alpha cut-out, not a photo on a black plate. The background was
   flood-filled away from the frame edges inward so the black suit survived —
   a plain dark-pixel threshold would have erased the jacket along with it. */
.hero-media img{
  width:auto; height:clamp(330px,52vw,620px); max-width:100%;
  object-fit:contain; display:block;
}
.hero-under{
  position:relative; z-index:3; text-align:center;
  margin-top:clamp(-40px,-3vw,-14px); padding-bottom:clamp(30px,5vh,58px);
}
.hero .lede{ margin-left:auto; margin-right:auto; text-align:center; }
.hero .affil{
  font-family:var(--label); font-size:clamp(11px,1.2vw,14px);
  letter-spacing:.14em; text-transform:uppercase; color:var(--text-dim);
  margin:20px 0 0;
}
.hero .affil b{ color:var(--text); font-weight:600; }
.hero-cta{ display:flex; gap:12px; flex-wrap:wrap; margin-top:30px; }
.hero .hero-cta{ justify-content:center; }

.btn{
  font-family:var(--label); font-size:12px; letter-spacing:.16em;
  text-transform:uppercase; font-weight:600;
  padding:14px 26px; border:1px solid var(--line-strong);
  color:var(--text); background:transparent; cursor:pointer;
  transition:background .22s ease, color .22s ease, border-color .22s ease;
}
.btn:hover{ background:var(--white); color:var(--bg); border-color:var(--white); }
.btn.solid{ background:var(--white); color:var(--bg); border-color:var(--white); }
.btn.solid:hover{ background:transparent; color:var(--white); }

/* ============================================================
   STAT STRIP
   ============================================================ */
.stats{
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:clamp(14px,3vw,40px); border-top:1px solid var(--line);
  padding-top:clamp(22px,3vh,34px);
}
.stat-num{
  font-family:var(--display); font-size:clamp(30px,4.6vw,56px);
  color:var(--white); line-height:1; margin:0 0 8px;
}
.stat-label{
  font-family:var(--label); font-size:10.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--text-dim); margin:0;
}

/* ============================================================
   CREDIT GRID
   The deck's core pattern: photo, then a centred caption block of
   NAME / venue / years. Reused for residencies, brands, festivals.
   ============================================================ */
.credit-grid{ display:grid; gap:clamp(16px,2.4vw,28px); }
.credit-grid.c2{ grid-template-columns:repeat(2,1fr); }
.credit-grid.c3{ grid-template-columns:repeat(3,1fr); }
.credit-grid.c4{ grid-template-columns:repeat(4,1fr); }

.credit .shot{
  aspect-ratio:3/4; overflow:hidden; background:var(--surface);
  border:1px solid var(--line);
}
.credit .shot img{
  width:100%; height:100%; object-fit:cover; object-position:center 30%;
  filter:grayscale(.2) contrast(1.05);
  transition:transform .6s cubic-bezier(.2,.7,.3,1), filter .4s ease;
}
.credit:hover .shot img{ transform:scale(1.05); filter:grayscale(0) contrast(1.08); }
.credit .c-name{
  font-family:var(--display); font-size:clamp(15px,1.7vw,21px);
  color:var(--white); margin:14px 0 3px; text-transform:uppercase;
}
.credit .c-sub{
  font-family:var(--label); font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text); margin:0 0 5px; font-weight:600;
}
.credit .c-year{
  font-family:var(--label); font-size:10.5px; letter-spacing:.14em;
  color:var(--text-dim); margin:0;
}
.credit.center{ text-align:center; }

/* logo row */
.logo-row{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:clamp(16px,3vw,44px); align-items:center;
  margin-top:clamp(28px,4vh,52px); padding-top:clamp(22px,3vh,34px);
  border-top:1px solid var(--line);
}
.logo-row img{
  max-height:34px; width:auto; margin:0 auto; opacity:.62;
  filter:grayscale(1) brightness(1.7); transition:opacity .3s ease;
}
.logo-row img:hover{ opacity:1; }

/* ============================================================
   FEATURE BLOCK — used for Buddha-Bar / Stargazing credentials
   ============================================================ */
.feature{
  display:grid; grid-template-columns:1.1fr .9fr;
  gap:clamp(22px,4vw,58px); align-items:center;
}
.feature.rev{ direction:rtl; }
.feature.rev > *{ direction:ltr; }
.feature-media{ display:grid; grid-template-columns:repeat(2,1fr); gap:10px; }
.feature-media img{
  width:100%; aspect-ratio:1; object-fit:cover;
  border:1px solid var(--line); filter:grayscale(.15);
}
.feature-media img:first-child{ grid-column:1/-1; aspect-ratio:16/10; }
/* Cover-art variant: sleeve artwork is square and carries type, so the default
   16:10 lead crop would slice the title off. Three equal squares instead. */
.feature-media.covers{ grid-template-columns:repeat(3,1fr); }
.feature-media.covers img,
.feature-media.covers img:first-child{ grid-column:auto; aspect-ratio:1; }
.badge{
  display:inline-block; font-family:var(--label); font-size:10.5px;
  letter-spacing:.16em; text-transform:uppercase; font-weight:600;
  border:1px solid var(--line-strong); padding:5px 12px; margin:0 0 16px;
  color:var(--text);
}

/* ============================================================
   MEDIA TILES — mixtapes / videos
   ============================================================ */
.tile-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  gap:clamp(12px,2vw,22px);
}
.tile{ position:relative; overflow:hidden; border:1px solid var(--line); background:var(--surface); }
.tile img{
  width:100%; aspect-ratio:3/4; object-fit:cover;
  transition:transform .5s cubic-bezier(.2,.7,.3,1), opacity .3s ease;
}
.tile:hover img{ transform:scale(1.04); opacity:.72; }
.tile .play{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  opacity:0; transition:opacity .3s ease;
}
.tile:hover .play{ opacity:1; }
.tile .play span{
  width:52px; height:52px; border-radius:50%; border:1.5px solid var(--white);
  display:flex; align-items:center; justify-content:center; background:rgba(12,12,12,.5);
}
.tile.video img{ aspect-ratio:16/9; }

/* ============================================================
   VIDEO — click-to-load
   The YouTube iframe is NOT in the HTML. A local poster stands in
   until the visitor clicks, at which point interactive.js swaps in
   a youtube-nocookie iframe. Six embeds on one page would otherwise
   cost roughly 3 MB and a dozen third-party requests on first paint.
   ============================================================ */
.vid-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:clamp(16px,2.6vw,30px); }
.vid-grid.lead{ grid-template-columns:1fr; }

.vid{ border:1px solid var(--line); background:var(--surface); }
.vid-frame{
  position:relative; width:100%; aspect-ratio:16/9; overflow:hidden;
  background:#000; cursor:pointer; border:0; padding:0; display:block;
}
.vid-frame img{
  width:100%; height:100%; object-fit:cover;
  filter:grayscale(.2) contrast(1.05) brightness(.86);
  transition:transform .6s cubic-bezier(.2,.7,.3,1), filter .4s ease;
}
.vid-frame:hover img{ transform:scale(1.03); filter:grayscale(0) contrast(1.08) brightness(.95); }
.vid-frame iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
.vid-play{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  pointer-events:none;
}
.vid-play span{
  width:clamp(54px,6vw,76px); height:clamp(54px,6vw,76px); border-radius:50%;
  border:1.5px solid rgba(255,255,255,.85); background:rgba(12,12,12,.42);
  display:flex; align-items:center; justify-content:center;
  backdrop-filter:blur(2px); transition:background .3s ease, transform .3s ease;
}
.vid-frame:hover .vid-play span{ background:rgba(255,255,255,.92); transform:scale(1.06); }
.vid-play svg{ width:34%; height:auto; fill:var(--white); margin-left:8%; transition:fill .3s ease; }
.vid-frame:hover .vid-play svg{ fill:#0c0c0c; }
.vid-meta{ padding:16px 18px 18px; }
.vid-meta h3{ font-size:clamp(16px,1.8vw,23px); color:var(--white); margin:0 0 7px; }
.vid-meta p{
  font-family:var(--label); font-size:11px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--text-dim); margin:0;
}

/* mixtape covers — square, all link to SoundCloud */
.mix-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(178px,1fr));
  gap:clamp(10px,1.6vw,18px);
}
/* The sleeve artwork already carries its own title, so the caption sits
   underneath rather than as an overlay — an overlaid gradient would obscure
   artwork that a booker is being asked to judge. */
.mix{ display:block; }
.mix .frame{ overflow:hidden; border:1px solid var(--line); background:var(--surface); }
/* The covers are 3:4 portrait artwork. A square crop was slicing the tops
   and bottoms off the designs, so the frame matches the source. */
.mix img{
  width:100%; aspect-ratio:3/4; object-fit:cover;
  filter:grayscale(.18); transition:transform .5s cubic-bezier(.2,.7,.3,1), filter .4s ease;
}
.mix:hover img{ transform:scale(1.05); filter:grayscale(0); }
.mix .cap{
  display:block; padding:10px 1px 0;
  font-family:var(--label); font-size:10.5px; letter-spacing:.11em;
  text-transform:uppercase; color:var(--text-dim); font-weight:600;
  transition:color .25s ease;
}
.mix:hover .cap{ color:var(--white); }

/* ============================================================
   DISCOGRAPHY + AUDIO
   One <audio> element for the whole page, driven by a sticky bar at the
   bottom. Twenty separate players would each buffer independently and
   fight each other for playback.
   ============================================================ */
.disc-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(178px,1fr));
  gap:clamp(12px,1.8vw,22px);
}
.disc{ position:relative; text-align:left; background:none; border:0; padding:0; cursor:pointer; color:inherit; width:100%; }
.disc .art{
  position:relative; overflow:hidden; border:1px solid var(--line); background:var(--surface);
  aspect-ratio:1;
}
.disc .art img{
  width:100%; height:100%; object-fit:cover;
  transition:transform .5s cubic-bezier(.2,.7,.3,1), filter .35s ease;
}
.disc:hover .art img{ transform:scale(1.05); filter:brightness(.62); }
.disc .art .pc{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  opacity:0; transition:opacity .28s ease;
}
.disc:hover .art .pc, .disc.is-playing .art .pc{ opacity:1; }
.disc .art .pc span{
  width:46px; height:46px; border-radius:50%; border:1.5px solid rgba(255,255,255,.9);
  background:rgba(12,12,12,.45); display:flex; align-items:center; justify-content:center;
}
.disc .art .pc svg{ width:16px; fill:var(--white); }
.disc.is-playing .art{ border-color:var(--line-strong); }
.disc .d-title{
  font-family:var(--display); font-size:clamp(13px,1.4vw,17px); color:var(--white);
  margin:11px 0 3px; text-transform:uppercase; line-height:1.1;
}
.disc .d-artist{
  font-family:var(--label); font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-dim); margin:0;
}
.disc .tag{
  display:inline-block; margin-top:7px; font-family:var(--label); font-size:9px;
  letter-spacing:.16em; padding:3px 7px; border:1px solid var(--line-strong); color:var(--text);
}

/* sticky player bar */
.audio-bar{
  position:fixed; left:0; right:0; bottom:0; z-index:120;
  background:rgba(10,10,10,.95); backdrop-filter:blur(14px);
  border-top:1px solid var(--line-strong);
  transform:translateY(110%); transition:transform .35s cubic-bezier(.2,.7,.3,1);
}
.audio-bar.up{ transform:none; }
.audio-bar-inner{
  max-width:var(--wrap); margin:0 auto;
  /* the home-indicator strip on a modern iPhone sits under the bar */
  padding:11px var(--gut) calc(11px + env(safe-area-inset-bottom));
  display:flex; align-items:center; gap:14px;
}
.ab-play{
  flex:none; width:40px; height:40px; border-radius:50%;
  border:1px solid var(--line-strong); background:var(--white); color:#0c0c0c;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
}
.ab-play svg{ width:15px; fill:currentColor; }
.ab-meta{ min-width:0; flex:none; max-width:38%; }
.ab-title{
  font-family:var(--display); font-size:14px; color:var(--white);
  text-transform:uppercase; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin:0;
}
.ab-artist{
  font-family:var(--label); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--text-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin:2px 0 0;
}
.ab-seek{ flex:1; height:3px; background:var(--line-strong); position:relative; cursor:pointer; }
.ab-seek-fill{ position:absolute; inset:0 auto 0 0; width:0; background:var(--white); }
.ab-time{
  font-family:var(--label); font-size:10.5px; letter-spacing:.06em;
  color:var(--text-dim); flex:none; font-variant-numeric:tabular-nums;
}
.ab-close{ flex:none; background:none; border:0; color:var(--text-dim); cursor:pointer; font-size:18px; line-height:1; padding:4px; }
.ab-close:hover{ color:var(--white); }
.has-audio-bar{ padding-bottom:66px; }

/* ============================================================
   MASHUP PACK — numbered tracklist
   ============================================================ */
.pack{ display:grid; grid-template-columns:minmax(0,340px) 1fr; gap:clamp(24px,4vw,52px); align-items:start; }
.pack-art{ border:1px solid #c9c9bd; overflow:hidden; }
.pack-art img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; }
.pack-dl{ margin-top:16px; display:flex; flex-direction:column; gap:9px; }
.pack-dl .btn{ text-align:center; }
.pack-meta{ font-family:var(--label); font-size:10.5px; letter-spacing:.13em;
  text-transform:uppercase; color:#5a5a52; margin:0; }

.tracklist{ border-top:1px solid #c9c9bd; }
.trk{
  display:grid; grid-template-columns:34px 1fr auto; align-items:center; gap:14px;
  width:100%; padding:14px 4px; background:none; border:0; border-bottom:1px solid #c9c9bd;
  cursor:pointer; text-align:left; color:inherit; transition:padding-left .25s ease;
}
.trk:hover{ padding-left:12px; }
/* The number and the play icon occupy the same cell — the icon replaces the
   number on hover. Both need an explicit grid-area: placing only the icon
   pushed every auto-placed sibling one column to the right and bumped the
   duration onto a second row. */
.trk-n{
  grid-area:1/1; align-self:center;
  font-family:var(--label); font-size:11px; letter-spacing:.1em; color:#5a5a52;
}
.trk:hover .trk-n, .trk.is-playing .trk-n{ visibility:hidden; }
.trk-ico{ grid-area:1/1; align-self:center; justify-self:start; opacity:0; transition:opacity .2s ease; }
.trk:hover .trk-ico, .trk.is-playing .trk-ico{ opacity:1; }
.trk-ico svg{ width:14px; fill:#0c0c0c; }
.trk-t{ min-width:0; }
.trk-title{ font-family:var(--display); font-size:clamp(14px,1.5vw,18px); color:#0c0c0c;
  text-transform:uppercase; line-height:1.15; margin:0; }
.trk-artist{ font-family:var(--label); font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:#5a5a52; margin:3px 0 0; }
.trk-time{ font-family:var(--label); font-size:11px; color:#5a5a52; font-variant-numeric:tabular-nums; }
.trk-get{ color:#5a5a52; display:flex; align-items:center; padding:4px; }
.trk-get:hover{ color:#0c0c0c; }
.trk-get svg{ width:15px; fill:currentColor; }

/* ============================================================
   DOWNLOAD GATE
   A native <dialog> rather than a hand-rolled overlay: it brings focus
   trapping, Esc-to-close and inertness of the page behind it for free.
   ============================================================ */
.gate{
  border:1px solid var(--line-strong); background:var(--bg); color:var(--text);
  padding:0; max-width:min(680px,92vw); width:100%;
}
.gate::backdrop{ background:rgba(6,6,6,.82); backdrop-filter:blur(3px); }
.gate-inner{ display:grid; grid-template-columns:200px 1fr; gap:clamp(18px,3vw,30px); padding:clamp(20px,3vw,30px); }
.gate-art{ border:1px solid var(--line); overflow:hidden; align-self:start; }
.gate-art img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; }
.gate h3{ font-size:clamp(21px,3vw,30px); color:var(--white); margin:0 0 6px; }
.gate-meta{
  font-family:var(--label); font-size:10.5px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 18px;
}
.gate .field{ margin-bottom:14px; }
.gate .btn{ width:100%; }
.gate-x{
  position:absolute; top:10px; right:12px; background:none; border:0;
  color:var(--text-dim); font-size:22px; line-height:1; cursor:pointer; padding:4px 8px;
}
.gate-x:hover{ color:var(--white); }
.gate-done h3{ margin-bottom:10px; }
.gate-done p{ color:var(--text-dim); font-size:14px; margin:0 0 6px; }
@media (max-width:560px){
  .gate-inner{ grid-template-columns:1fr; }
  .gate-art{ max-width:180px; }
}

/* ============================================================
   FORM
   ============================================================ */
.form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:16px 18px; margin-top:30px; }
.field{ display:flex; flex-direction:column; gap:7px; }
.field.wide{ grid-column:1/-1; }
.field label{
  font-family:var(--label); font-size:10.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--text-dim);
}
.field input, .field select, .field textarea{
  font-family:var(--body);
  /* 16px is not a style choice — below it, iOS Safari zooms the whole page in
     when the field is focused and never zooms back out. */
  font-size:16px; color:var(--text);
  background:var(--surface); border:1px solid var(--line);
  padding:13px 14px; width:100%; border-radius:0;
  min-height:48px;
  transition:border-color .2s ease, background .2s ease;
}
.field textarea{ min-height:132px; resize:vertical; }
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color:var(--line-strong); background:var(--surface-2);
}
.field select{ appearance:none; cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--text-dim) 50%),linear-gradient(135deg,var(--text-dim) 50%,transparent 50%);
  background-position:calc(100% - 19px) 21px, calc(100% - 14px) 21px;
  background-size:5px 5px, 5px 5px; background-repeat:no-repeat;
}
/* Honeypot. Parked off-canvas with left:-9999px it still counted toward the
   page's scroll width on some mobile browsers; clipping hides it without
   occupying any space at all. */
.hp{
  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; border:0; opacity:0;
}
.form-note{ font-size:13px; color:var(--text-dim); margin:14px 0 0; }
.form-status{ margin-top:16px; font-size:15px; }
.form-status.err{ color:#ff8a7a; }
.form-done{
  border:1px solid var(--line-strong); padding:clamp(26px,4vw,44px); text-align:center;
}
.form-done h3{ font-size:clamp(22px,3vw,36px); color:var(--white); margin:0 0 12px; }
.form-done p{ color:var(--text-dim); margin:0; }

/* social row */
.social{ display:flex; gap:10px; flex-wrap:wrap; margin-top:18px; }
.social a{
  width:40px; height:40px; border:1px solid var(--line-strong);
  display:flex; align-items:center; justify-content:center;
  color:var(--text-dim); transition:color .2s ease, border-color .2s ease, background .2s ease;
}
.social a:hover{ color:var(--bg); background:var(--white); border-color:var(--white); }
.social svg{ width:17px; height:17px; fill:currentColor; }

/* platform links */
.link-list{ display:grid; grid-template-columns:repeat(2,1fr); gap:0; margin-top:34px; }
.link-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:18px;
  padding:20px 4px; border-top:1px solid var(--line); transition:padding-left .3s ease;
}
.link-row:hover{ padding-left:14px; }
.link-row:last-child, .link-row:nth-last-child(2){ border-bottom:1px solid var(--line); }
.link-row .lr-name{
  font-family:var(--display); font-size:clamp(16px,1.9vw,24px);
  color:var(--white); text-transform:uppercase;
}
.link-row .lr-sub{
  font-family:var(--label); font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--text-dim); text-align:right; flex:none;
}

/* gallery masonry-ish */
.gal-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  gap:10px;
}
.gal-grid img{
  width:100%; aspect-ratio:1; object-fit:cover;
  border:1px solid var(--line); filter:grayscale(.25);
  transition:filter .4s ease, transform .5s ease;
}
.gal-grid img:hover{ filter:grayscale(0); transform:scale(1.02); }

/* ============================================================
   IVORY PANEL — the deck's one light page, used for contrast
   ============================================================ */
.ivory{ background:var(--ivory); color:#141414; }
.ivory .title, .ivory .stat-num{ color:#0c0c0c; }
.ivory .eyebrow, .ivory .c-year, .ivory .stat-label{ color:#5a5a52; }
.ivory .lede, .ivory .c-sub{ color:#2a2a26; }
.ivory .rule, .ivory .stats{ border-color:#c9c9bd; }
.ivory .btn{ border-color:#2a2a26; color:#141414; }
.ivory .btn:hover{ background:#0c0c0c; color:var(--ivory); border-color:#0c0c0c; }
/* .badge inherits --text (#e4e4e4), which is invisible on the ivory panel. */
.ivory .badge{ color:#141414; border-color:#5a5a52; }
.ivory .c-name, .ivory .vid-meta h3, .ivory .lr-name, .ivory h3{ color:#0c0c0c; }
.ivory .foot a, .ivory .link-row{ border-color:#c9c9bd; }

/* ============================================================
   FOOTER
   ============================================================ */
.foot{ border-top:1px solid var(--line); padding:clamp(38px,6vh,64px) 0 34px; }
.foot-grid{ display:grid; grid-template-columns:1.2fr 1fr 1fr; gap:clamp(20px,4vw,48px); }
.foot h3{ font-size:clamp(20px,2.4vw,30px); color:var(--white); margin:0 0 14px; }
.foot a{ color:var(--text-dim); font-size:14px; display:block; padding:4px 0; transition:color .2s; }
.foot a:hover{ color:var(--white); }
.foot .f-label{
  font-family:var(--label); font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 12px;
}
.foot-base{
  margin-top:clamp(26px,4vh,44px); padding-top:22px; border-top:1px solid var(--line);
  display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap;
  font-family:var(--label); font-size:11px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-dim);
}

/* ============================================================
   MOTION — three intentional moments, per the approved design rules
   ============================================================ */
/* Content is visible by default and only hidden once the inline head script has
   confirmed JS is running. Without this, a JS failure would leave most of the
   page at opacity 0 — an invisible site is a worse outcome than no animation. */
.js .reveal{ opacity:0; transform:translateY(22px); }
.js .reveal.in{ opacity:1; transform:none; transition:opacity .7s ease, transform .7s cubic-bezier(.2,.7,.3,1); }
@media (prefers-reduced-motion:reduce){
  .reveal, .reveal.in, .js .reveal, .js .reveal.in{ opacity:1; transform:none; transition:none; }
  html{ scroll-behavior:auto; }
}

/* ============================================================
   REFINEMENT — the small stuff

   Nothing here changes the layout. It is the difference between a page that
   is correct and a page that feels made: where the eye lands, what happens
   under the cursor, how an image arrives. The deck's restraint still rules —
   no accent colour, no bounce, nothing that announces itself.
   ============================================================ */

/* ---- anchors clear the sticky header ----
   Jumping to #mashup or #enquiry used to park the heading underneath the
   header, so the visitor landed mid-paragraph on the section they asked for. */
:target,
section[id],
[id]{ scroll-margin-top:calc(var(--nav-h,72px) + 18px); }

/* ---- selection ----
   The browser default is a blue that exists nowhere else on this site. */
::selection{ background:var(--white); color:var(--bg); }
.ivory ::selection{ background:#0c0c0c; color:var(--ivory); }

/* ---- keyboard focus ----
   Removing outlines is a common tidy-up and an accessibility failure. This
   keeps a visible ring for keyboard users and hides it for mouse users, which
   is what :focus-visible is for. */
:focus-visible{
  outline:2px solid var(--white); outline-offset:3px; border-radius:1px;
}
.ivory :focus-visible{ outline-color:#0c0c0c; }

/* ---- scrollbar ---- */
@supports selector(::-webkit-scrollbar){
  ::-webkit-scrollbar{ width:11px; height:11px; }
  ::-webkit-scrollbar-track{ background:var(--bg); }
  ::-webkit-scrollbar-thumb{ background:#333; border:3px solid var(--bg); border-radius:99px; }
  ::-webkit-scrollbar-thumb:hover{ background:#4d4d4d; }
}
html{ scrollbar-color:#333 var(--bg); scrollbar-width:thin; }

/* ---- reading progress ----
   A one-pixel hairline under the header. On a page as long as Music it is the
   only cue telling you whether you are near the end. */
.progress{
  position:absolute; left:0; bottom:-1px; height:1px; width:100%;
  transform:scaleX(0); transform-origin:0 50%;
  background:linear-gradient(90deg,rgba(255,255,255,.25),var(--white));
  pointer-events:none;
}

/* ---- images arrive rather than appear ----
   Lazily-loaded photographs used to snap in at full opacity the instant they
   decoded, which reads as a flicker while you scroll. */
.js img[data-fade]{ opacity:0; transform:scale(1.012); }
.js img[data-fade].loaded{
  opacity:1; transform:none;
  transition:opacity .65s ease, transform .9s cubic-bezier(.2,.7,.3,1);
}

/* ---- staggered reveal ----
   A grid of twelve cards arriving as one block reads as a layout shift. Given
   35ms between neighbours it reads as a sequence. */
.js .reveal{ transition-delay:var(--d,0s); }

/* ---- display headings wipe up behind their own edge ---- */
.js .title.reveal,
.js h1.reveal{ clip-path:inset(-20% -20% 0 -20%); }

/* ---- buttons fill from the left ----
   Outline buttons take the sweep; solid ones are already filled, so they keep
   the straight inversion. The rule reads as: empty things fill, full things
   invert. */
.btn{ position:relative; overflow:hidden; isolation:isolate; }
.btn::before{
  content:''; position:absolute; inset:0; z-index:-1; background:var(--white);
  transform:scaleX(0); transform-origin:left center;
  transition:transform .42s cubic-bezier(.65,0,.35,1);
}
.btn.solid::before{ content:none; }
.btn:hover{ background:transparent; }
.btn.solid:hover{ background:transparent; }
.btn:hover::before{ transform:scaleX(1); }
.ivory .btn::before{ background:#0c0c0c; }
.ivory .btn:hover{ background:transparent; color:var(--ivory); }

/* ---- text links underline from the left ---- */
.foot a, .link-row .lr-name{ position:relative; }
.foot a::after{
  content:''; position:absolute; left:0; bottom:6px; height:1px; width:100%;
  background:currentColor; transform:scaleX(0); transform-origin:left;
  transition:transform .34s cubic-bezier(.65,0,.35,1);
}
.foot a:hover::after{ transform:scaleX(1); }

/* ---- cards lift ---- */
.credit .shot, .mix .frame, .disc .art, .vid-frame{
  transition:border-color .3s ease, box-shadow .45s ease, transform .45s cubic-bezier(.2,.7,.3,1);
}
.credit:hover .shot, .mix:hover .frame, .disc:hover .art{
  border-color:var(--line-strong);
  box-shadow:0 18px 40px -22px rgba(0,0,0,.9);
  transform:translateY(-3px);
}

/* ---- the stat numbers count up; hold their width so nothing jitters ---- */
.stat-num{ font-variant-numeric:tabular-nums; }

/* ---- hero portrait drifts a little slower than the page ----
   Two planes moving at slightly different speeds is what gives the composition
   depth. Kept to a few pixels: any more and it reads as a broken sticky. */
.hero-media img{ will-change:transform; }

/* ---- now-playing pulse on the audio bar ---- */
.ab-play.playing::after{
  content:''; position:absolute; inset:-5px; border-radius:50%;
  border:1px solid rgba(255,255,255,.5); animation:pulse 2.1s ease-out infinite;
}
.ab-play{ position:relative; }
@keyframes pulse{
  0%{ transform:scale(.86); opacity:.85; }
  70%{ transform:scale(1.25); opacity:0; }
  100%{ opacity:0; }
}

/* ---- a playing row is legible at a glance ---- */
.trk.is-playing{ background:rgba(12,12,12,.045); }
.trk.is-playing .trk-title{ font-weight:400; }
.disc.is-playing .d-title{ color:var(--white); }

/* Every moment above is opt-in. Someone who has asked their operating system
   for less motion gets the same site, still and immediate. */
@media (prefers-reduced-motion:reduce){
  .js img[data-fade], .js img[data-fade].loaded{ opacity:1; transform:none; transition:none; }
  .js .reveal{ transition-delay:0s !important; }
  .btn::before{ transition:none; }
  .foot a::after{ transition:none; }
  .credit:hover .shot, .mix:hover .frame, .disc:hover .art{ transform:none; }
  .progress{ display:none; }
  .ab-play.playing::after{ animation:none; opacity:0; }
  .hero-media img{ transform:none !important; }
}


/* A transparent cut-out is not a photograph in a frame. The border, the fill
   and the desaturation all belong to rectangular images — on an alpha PNG they
   draw a box around empty space. */
/* The `:first-child` in `.feature-media img:first-child{aspect-ratio:16/10}`
   outranks a plain `.portrait-cut img`, so the cut-out was being letterboxed
   into a landscape box — the figure shrank to a third of the column and
   floated. Matching that specificity lets the real 693×1500 shape through. */
.portrait-cut img,
.portrait-cut img:first-child{
  border:0; background:none; filter:none;
  width:auto; max-width:100%; height:auto;
  /* Capped by height, not width. Freed from the 16:10 box the cut-out went the
     other way and rendered 1094px tall — taller than the form beside it, so the
     portrait read as the subject of the section and the booking form as a
     footnote. It should sit alongside the form, not tower over it. */
  /* Sized against the text column beside it (~630px at a typical laptop
     height), not against the viewport alone — the portrait should read as
     the equal of the booking form, a little taller, never dwarfing it. The
     vh middle value keeps that relationship on other screen sizes; the
     clamp ends stop it collapsing on short windows or ballooning on big
     ones. */
  max-height:clamp(440px, 72vh, 760px);
  aspect-ratio:auto; object-fit:contain;
  margin-left:auto; margin-right:auto;
}

/* ============================================================
   PACK PAGE — the link-in-bio destination

   Arrives from an Instagram bio, on a phone, on cellular, inside an in-app
   browser. One job: hear it, take it. No nav bar, because every other link
   is a way to lose someone who came for one thing.
   ============================================================ */
.pack-page{ background:var(--ivory); }
.pack-page main.section{ padding-top:clamp(26px,4vh,48px); }

/* ---- light header ----
   Same nav, inverted for the ivory page. Colours only: the layout, the
   hamburger and the drawer behaviour are inherited, so there is one
   navigation in the codebase rather than two that drift apart. */
.nav--light{ background:var(--ivory); border-bottom-color:#c9c9bd; }
.nav--light.scrolled{ background:#f4f4ea; box-shadow:0 8px 30px rgba(0,0,0,.14); }
.nav--light .brand span{ color:#0c0c0c; }
.nav--light .brand img{ filter:invert(1); }
/* `.nav--light a`, not `.nav--light .nav a` — the class sits ON the header, so
   the second form looks for a .nav nested inside it and matches nothing. That
   left the links at the dark-theme #c9c9c9 on ivory: 1.4:1, invisible. */
.nav--light a{ color:#4a4a42; }
.nav--light a:hover,
.nav--light a.is-active{ color:#0c0c0c; }
.nav--light a.is-active::after{ background:#0c0c0c; }
.nav--light .nav-toggle{ color:#0c0c0c; }
/* Book inverts too — dark on ivory reads as the primary action here. */
.nav--light .nav-links .btn{
  background:#0c0c0c; color:var(--ivory); border-color:#0c0c0c;
}
.nav--light .nav-links .btn:hover,
.nav--light .nav-links .btn:focus-visible{
  background:transparent; color:#0c0c0c; border-color:#0c0c0c;
}
.nav--light :focus-visible{ outline-color:#0c0c0c; }
.pack-outro{ background:var(--bg); color:var(--text); }
.pack-outro .title{ color:var(--white); }
.pack-outro .hero-cta{ margin-top:26px; }
.pack-outro .social{ justify-content:center; margin-top:26px; }

/* Instagram's in-app browser cannot reliably save a 97 MB file on iOS — it
   starts, then silently does nothing. Better to say so than to let someone
   tap Download three times and give up. */
.inapp-note{
  border:1px solid #0c0c0c; background:rgba(12,12,12,.05);
  padding:14px 16px; margin-top:24px; max-width:62ch;
  font-size:14.5px; line-height:1.55; color:#141414;
}
.inapp-note b{ font-weight:700; }

/* ============================================================
   RESPONSIVE

   Four stops, each earning its place:
     1024  tablet landscape — the two-up feature block starts to pinch
      900  tablet portrait  — columns collapse, nav becomes a drawer
      700  large phone      — everything goes single column
      560  phone            — type and spacing retune
      380  small phone      — last-resort trims

   Phones are the majority of traffic to an artist site: a booker checks a
   name from a phone long before they open a laptop. So these rules are not
   damage control, they are the primary layout.
   ============================================================ */

@media (max-width:1024px){
  .feature{ grid-template-columns:1fr .95fr; gap:clamp(20px,3vw,38px); }
  .pack{ grid-template-columns:minmax(0,280px) 1fr; gap:clamp(20px,3vw,34px); }
}

@media (max-width:900px){
  .hero-inner{ min-height:auto; }
  .hero-media img{ height:clamp(280px,56vw,420px); }
  .feature, .feature.rev{ grid-template-columns:1fr; direction:ltr; }
  .credit-grid.c4{ grid-template-columns:repeat(2,1fr); }
  .credit-grid.c3{ grid-template-columns:repeat(2,1fr); }
  .foot-grid{ grid-template-columns:1fr 1fr; }
  .vid-grid{ grid-template-columns:1fr; }
  .link-list{ grid-template-columns:1fr; }
  .link-row:nth-last-child(2){ border-bottom:0; }
  /* Anything narrower than 900px is a touch device in practice — footer links
     get a thumb-sized row from here down, not just on phones. */
  .foot a{ padding:11px 0; }
  .social a{ width:46px; height:46px; }

  /* ---- nav drawer ----
     Fixed rather than absolute so a long menu can scroll on a short screen,
     and so the page behind cannot be reached past it. */
  .nav-inner{ position:relative; }
  .nav-toggle{
    display:flex; align-items:center; justify-content:center;
    min-width:44px; min-height:44px; margin-left:auto; font-size:24px;
  }
  .nav-links{
    display:none; position:fixed; top:var(--nav-h,62px); left:0; right:0;
    max-height:calc(100dvh - var(--nav-h,62px));
    overflow-y:auto; -webkit-overflow-scrolling:touch;
    /* Fully opaque, not a frosted panel: at 98% the hero wordmark ghosted
       through behind the menu items. A navigation menu has one job. */
    background:#0a0a0a;
    /* stop a flick inside the menu from scrolling the page underneath it */
    overscroll-behavior:contain;
    border-bottom:1px solid var(--line);
    flex-direction:column; align-items:stretch; gap:0;
    padding:6px var(--gut) calc(20px + env(safe-area-inset-bottom)); z-index:90;
  }
  .nav-links.open{ display:flex; }
  .nav-links a{
    padding:16px 2px; border-bottom:1px solid var(--line);
    font-size:14px; letter-spacing:.16em; min-height:52px;
    display:flex; align-items:center; color:#e0e0e0;
  }
  .nav-links a.is-active{ color:var(--white); }
  .nav-links a.is-active::after{ display:none; }
  .nav-links a:last-child{ border-bottom:0; }
  .nav-links .btn{
    margin-top:16px; text-align:center; justify-content:center;
    padding:17px 20px; background:var(--white); color:#0c0c0c; border-color:var(--white);
  }
  /* the drawer on the ivory pages */
  .nav--light .nav-links{ background:var(--ivory); border-bottom-color:#c9c9bd; }
  .nav--light .nav-links a{ color:#2a2a26; border-bottom-color:#c9c9bd; }
  .nav--light .nav-links a.is-active{ color:#0c0c0c; }
  .nav--light .nav-links .btn{ background:#0c0c0c; color:var(--ivory); border-color:#0c0c0c; }

  /* Backdrop behind the open drawer — tapping it closes the menu. */
  .nav-scrim{
    position:fixed; inset:var(--nav-h,62px) 0 0; background:rgba(0,0,0,.55);
    z-index:80; opacity:0; pointer-events:none; transition:opacity .25s ease;
  }
  .nav-scrim.on{ opacity:1; pointer-events:auto; }
  body.nav-open{ overflow:hidden; }
}

@media (max-width:700px){
  /* ---- hero ----
     The figure and the wordmark share one column. On a laptop the name is far
     wider than the body, so the head lands in the counter of the letters and
     both read. Below ~700px the name is barely wider than the shoulders, and
     at -13vw the head sat squarely over the R and M: the brand name, the one
     word on the page that has to survive, was unreadable. So on phones the
     figure drops to a shoulders-only overlap and the name gets the room. */
  .hero h1{ font-size:clamp(56px,18vw,120px); }
  .hero-media{ margin-top:clamp(-30px,-4.5vw,-10px); }
  .hero-media img{ height:clamp(300px,72vw,430px); }
  .hero-under{ margin-top:clamp(-22px,-3vw,-8px); }

  .title{ font-size:clamp(34px,8vw,54px); }
  .section{ padding:clamp(46px,7vh,80px) 0; }

  /* ---- mashup pack ----
     Was the worst break on the site: the art column held its 340px and left
     the tracklist about 90px, so every Vietnamese title wrapped one word per
     line and the durations collided with the artist names. */
  .pack{ grid-template-columns:1fr; gap:26px; }
  .pack > div:first-child{
    display:grid; grid-template-columns:minmax(0,138px) 1fr;
    gap:16px; align-items:start;
  }
  .pack-dl{ margin-top:0; align-self:center; }
  /* "Download the pack" is 17 tracked-out characters. At the default 26px of
     side padding it broke onto a second line beside the sleeve, leaving the
     word PACK stranded — the tracking gives back the 20px needed. */
  .pack-dl .btn{ padding:15px 10px; letter-spacing:.11em; }

  .form-grid{ grid-template-columns:1fr; }
  .feature-media{ grid-template-columns:1fr 1fr; }
  .disc-grid, .mix-grid{ grid-template-columns:repeat(2,1fr); }
  .gal-grid{ grid-template-columns:repeat(2,1fr); }

  /* footer links need a thumb-sized row, not a text baseline */
  .foot a{ padding:11px 0; }
  .social a{ width:46px; height:46px; }
}

@media (max-width:560px){
  .stats{ grid-template-columns:repeat(2,1fr); row-gap:26px; }
  .credit-grid.c4, .credit-grid.c3, .credit-grid.c2{ grid-template-columns:1fr 1fr; }
  .foot-grid{ grid-template-columns:1fr; }
  .mix-grid{ grid-template-columns:1fr 1fr; }
  .gal-grid{ grid-template-columns:1fr 1fr; }

  /* The sub-label used to be display:none here, which quietly deleted the
     venue and the year — the two facts a booker actually scans for. It stacks
     under the name instead. */
  .link-row{ flex-direction:column; align-items:flex-start; gap:4px; padding:16px 4px; }
  .link-row .lr-sub{ text-align:left; }

  .trk{ grid-template-columns:26px 1fr auto; gap:11px; padding:13px 2px; }
  .trk-title{ font-size:15px; }

  /* audio bar: play, title and scrubber survive; the clock is the first thing
     to go when there is no room for all four */
  .ab-time{ display:none; }
  .ab-meta{ max-width:46%; }
  .audio-bar-inner{ gap:11px; }

  .gate-inner{ padding:18px; }
  .gate-art{ max-width:150px; }
}

@media (max-width:380px){
  .hero h1{ font-size:clamp(46px,17vw,70px); }
  .stat-num{ font-size:30px; }
  .credit-grid.c4, .credit-grid.c3, .credit-grid.c2{ gap:14px; }
  .pack > div:first-child{ grid-template-columns:1fr; }
  .pack-dl{ margin-top:14px; }
}

/* ============================================================
   TOUCH

   Everything below only applies to devices with no real pointer. On iOS a tap
   latches :hover until you tap elsewhere, so any hover rule that moves layout
   leaves the page looking stuck. These neutralise the movement and, more
   usefully, make the affordances that were hover-only permanently visible —
   a play triangle nobody can hover over is a play triangle nobody finds.
   ============================================================ */
@media (hover:none){
  .trk:hover{ padding-left:2px; }
  .link-row:hover{ padding-left:4px; }
  .brand:hover img{ transform:none; }
  .credit:hover .shot img{ transform:none; }
  .mix:hover img, .disc:hover .art img, .vid-frame:hover img{ transform:none; }
  .gal-grid img:hover{ transform:none; }

  /* the number stays; the icon is for playback state only */
  .trk:hover .trk-n{ visibility:visible; }
  .trk.is-playing .trk-n{ visibility:hidden; }
  .trk:hover .trk-ico{ opacity:0; }
  .trk.is-playing .trk-ico{ opacity:1; }

  /* sleeves are tappable — say so */
  .disc .art .pc{ opacity:.9; }
  .disc .art .pc span{ width:40px; height:40px; background:rgba(12,12,12,.55); }
  .tile .play{ opacity:.9; }
}

/* Give every control a thumb-sized target regardless of viewport. */
@media (pointer:coarse){
  .btn{ min-height:48px; display:inline-flex; align-items:center; justify-content:center; }
  .ab-close, .gate-x{ min-width:44px; min-height:44px; display:flex; align-items:center; justify-content:center; }
  .ab-play{ width:46px; height:46px; }
  /* The scrubber stays a 3px line but gains a 40px-tall invisible grab area.
     Padding would have stretched the fill, which is inset:0 on this box —
     a pseudo-element leaves both the visuals and the seek maths untouched. */
  .ab-seek::before{ content:''; position:absolute; left:0; right:0; top:-19px; bottom:-19px; }
  .trk{ min-height:56px; }
  .foot a{ padding:11px 0; }
}
