:root{
  --paper:#EFEBE1; --paper2:#E5E0D3; --ink:#141310; --muted:#5C5849;
  --line:#CEC8B8; --accent:#EA4E1B; --accent-ink:#BE3F16; --on-accent:#FFFFFF;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--paper);color:var(--ink);font-family:"Newsreader",Georgia,serif;font-size:19px;line-height:1.6;-webkit-font-smoothing:antialiased;transition:background .3s,color .3s}
img{max-width:100%;display:block}
figure{margin:0}
a{color:var(--ink);text-decoration:none}
h1,h2,h3{font-family:"Archivo",Helvetica,Arial,sans-serif;font-weight:800;line-height:.98;margin:0 0 .3em;letter-spacing:-.03em}
p{margin:0 0 1rem}
.wrap{width:100%;max-width:1440px;margin:0 auto;padding:0 2.4rem}
.muted{color:var(--muted)}
.mono{font-family:"Space Mono",monospace;font-size:.74rem;letter-spacing:.02em;text-transform:uppercase}
.eyebrow{font-family:"Space Mono",monospace;font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin:0 0 1rem}
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--accent-ink);color:var(--on-accent);font-family:"Space Mono",monospace;font-size:.75rem;text-transform:uppercase;padding:.7rem 1.1rem}
.skip:focus{left:.5rem;top:.5rem}
.lk{font-family:"Space Mono",monospace;font-size:.72rem;letter-spacing:.03em;text-transform:uppercase;color:var(--accent-ink);border-bottom:1px solid var(--accent-ink);padding-bottom:2px;transition:opacity .18s}
.lk:hover{opacity:.6}
.lk--ink{color:var(--ink);border-color:var(--ink)}

/* ---- HEADER ---- */
/* Solid, not blurred: backdrop-filter re-blurs the strip on every scroll frame. */
.site-header{position:sticky;top:0;z-index:50;background:var(--paper);border-bottom:1px solid var(--ink)}
.nav{display:flex;align-items:center;gap:2rem;height:66px}
.brand{display:inline-flex;align-items:center;gap:.7rem;flex:0 0 auto;color:var(--ink)}
.brand__logo{height:2.3rem;width:auto;display:block;transition:opacity .18s}
.brand:hover .brand__logo{opacity:.7}
.brand__tag{font-family:"Space Mono",monospace;font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);border-left:1px solid var(--line);padding-left:.7rem;line-height:1.3;max-width:6.5rem}
.nav__links{display:flex;gap:1.7rem;list-style:none;margin:0 0 0 auto;padding:0;align-items:center}
.nav__links a{font-family:"Space Mono",monospace;font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;color:var(--ink)}
.nav__links a:hover,.nav__links a.is-active{color:var(--accent-ink)}
.nav__toggle{display:none;background:none;border:0;cursor:pointer;padding:.4rem;margin-left:auto}
.nav__toggle span{display:block;width:24px;height:1.5px;background:var(--ink);margin:6px 0}
@media(max-width:760px){
  .brand__tag{display:none}
  .nav__toggle{display:block}
  .nav__links{position:fixed;inset:66px 0 auto 0;flex-direction:column;gap:0;background:var(--paper);padding:.6rem 2.4rem 1.6rem;transform:translateY(-135%);visibility:hidden;transition:transform .25s,visibility 0s .25s;border-bottom:1px solid var(--ink);align-items:stretch;margin:0}
  .nav__links.is-open{transform:translateY(0);visibility:visible;transition:transform .25s,visibility 0s 0s}
  .nav__links li{width:100%;border-bottom:1px solid var(--line)}
  .nav__links a{display:block;padding:.85rem 0;font-size:.85rem}
}

/* A full-sentence tagline needs a wider measure than the short display quote the
   .q rule is tuned for. Extra class so it out-specifies the per-page .fine p.q. */
.fine p.q.q--long{font-size:clamp(1.02rem,1.15vw,1.26rem);line-height:1.16;max-width:26ch;letter-spacing:-.02em;margin-bottom:0}

/* ---- DISCLOSURE ROW INSIDE A .stack LIST (used by Elsewhere → Publishing) ----
   Specificity beats the per-page .stack rules regardless of source order. */
.stack details>summary{list-style:none;display:flex;align-items:baseline;justify-content:space-between;gap:1rem;padding:.6rem 0;cursor:pointer;
  font-family:"Space Mono",monospace;font-size:.7rem;letter-spacing:.03em;text-transform:uppercase;color:var(--ink);transition:padding-left .18s,color .18s}
.stack details>summary::-webkit-details-marker{display:none}
.stack details>summary::marker{content:""}
.stack details>summary:hover{color:var(--accent-ink);padding-left:.35rem}
.stack details[open]>summary{color:var(--accent-ink)}
.stack details>summary .arw{display:inline-block;transition:transform .22s cubic-bezier(.2,.8,.2,1)}
.stack details[open]>summary .arw{transform:rotate(180deg)}
.stack details ul{list-style:none;margin:0 0 .55rem;padding:.1rem 0 0 .9rem;border-left:1px solid var(--line)}
.stack details ul li{border-bottom:0;border-top:0}
.stack details ul a{padding:.32rem 0;font-size:.66rem;color:var(--muted)}
.stack details ul a:hover{color:var(--accent-ink)}
.stack details ul a .arw{font-size:.62rem}

@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}


/* ============================================================
   OPTION A — "REEL"
   One artist per screen. The photograph is the layout; the name
   sits on it. Nothing else competes. Scroll-snapped so it plays
   like a slideshow you drive.
   ============================================================ */
main{scroll-snap-type:y proximity}
/* anchor jumps must clear the 66px sticky header */
#top,#roster,#about,#elsewhere,#contact,.frame{scroll-margin-top:66px}

/* ---- MASTHEAD ----
   Sized by its contents, not by the viewport: the wordmark and the lede sit
   side by side and the first artist frame starts immediately under the cue rule. */
.mast{padding-top:clamp(1.5rem,3vw,2.4rem);scroll-snap-align:start}
.mast__row{display:flex;align-items:flex-end;justify-content:space-between;gap:clamp(1.5rem,4vw,3.5rem);flex-wrap:wrap}
.mast h1{font-size:clamp(2.1rem,6.4vw,5.2rem);font-weight:800;letter-spacing:-.05em;text-transform:uppercase;margin:0;line-height:.87}
.mast__lede{font-family:"Newsreader",serif;font-style:italic;font-size:clamp(.98rem,1.4vw,1.2rem);max-width:30ch;margin:0 0 .4rem;line-height:1.35;color:var(--muted)}
.mast__cue{border-top:1px solid var(--ink);margin-top:clamp(1rem,2vw,1.6rem);padding:.5rem 0 clamp(.7rem,1.4vw,1.1rem);
  display:flex;justify-content:flex-end;align-items:baseline;gap:1rem;
  font-family:"Space Mono",monospace;font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.mast__cue span:last-child{animation:nudge 2.4s ease-in-out infinite}
@keyframes nudge{0%,100%{transform:none}50%{transform:translateY(3px)}}
@media(max-width:820px){.mast__row{flex-direction:column;align-items:flex-start;gap:1rem}.mast__lede{margin-bottom:0}}

/* ---- THE REEL ---- */
.frame{position:relative;height:calc(100svh - 66px);scroll-snap-align:start;overflow:hidden;background:var(--paper2);content-visibility:auto;contain-intrinsic-size:auto 100svh}
/* No CSS filter here on purpose: the warm grade is baked into the webp files by
   build-images.py. A filter on a 100vw x 100svh layer is recomputed by the GPU on
   every scroll frame and was the single biggest source of scroll jank. */
.frame img{width:100%;height:100%;object-fit:cover;object-position:center 28%}
/* grain + a scrim only where type sits, so the photo stays a photo */
.frame::after{content:"";position:absolute;inset:0;pointer-events:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");background-size:150px 150px;opacity:.07}
.frame__scrim{position:absolute;inset:auto 0 0 0;height:52%;pointer-events:none;background:linear-gradient(to top,rgba(10,9,7,.72),rgba(10,9,7,.34) 42%,transparent)}
.frame__cap{position:absolute;left:0;right:0;bottom:0;padding:0 2.4rem 2.4rem;z-index:3;color:#EFEBE1}
.frame__name{font-family:"Archivo",sans-serif;font-weight:800;font-size:clamp(2.4rem,8.5vw,7.5rem);letter-spacing:-.05em;text-transform:uppercase;line-height:.9;margin:0;color:#EFEBE1}
.frame__name a{color:inherit}
.frame__name a:hover{color:var(--accent)}
.frame__foot{display:flex;flex-wrap:wrap;align-items:baseline;gap:.6rem 1.6rem;margin-top:.9rem}
.frame__cat{font-family:"Space Mono",monospace;font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;opacity:.72}
.frame__links{display:flex;gap:1.2rem;margin-left:auto}
.frame__links a{font-family:"Space Mono",monospace;font-size:.68rem;letter-spacing:.05em;text-transform:uppercase;color:#EFEBE1;border-bottom:1px solid rgba(239,235,225,.5);padding-bottom:2px;transition:color .18s,border-color .18s}
.frame__links a:hover{color:var(--accent);border-color:var(--accent)}
@media(max-width:640px){
  .frame__cap{padding-left:1.4rem;padding-right:1.4rem}
  .frame__links{margin-left:0;flex-basis:100%;gap:1rem}
}

/* ---- FINE PRINT ---- */
.fine{border-top:1px solid var(--ink);display:grid;grid-template-columns:repeat(3,1fr);scroll-snap-align:start}
.fine__col{padding:clamp(1.8rem,3vw,2.6rem) 0 clamp(2rem,4vw,3rem)}
.fine__col + .fine__col{border-left:1px solid var(--line);padding-left:clamp(1.4rem,3vw,2.6rem)}
.fine__col:not(:last-child){padding-right:clamp(1.4rem,3vw,2.6rem)}
.fine h2{font-family:"Space Mono",monospace;font-weight:400;font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--accent-ink);margin:0 0 1rem;line-height:1.4}
.fine p{font-family:"Newsreader",serif;font-size:1.02rem;line-height:1.5;max-width:34ch}
.fine p.q{font-family:"Archivo",sans-serif;font-weight:800;font-size:1.5rem;line-height:1.05;letter-spacing:-.035em;text-transform:uppercase;max-width:14ch;margin-bottom:.9rem}
.fine p.q em{font-style:normal;color:var(--accent)}
.stack{list-style:none;margin:0;padding:0}
.stack li{border-bottom:1px solid var(--line)}
.stack li:first-child{border-top:1px solid var(--line)}
.stack a,.stack span.li{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;padding:.6rem 0;font-family:"Space Mono",monospace;font-size:.7rem;letter-spacing:.03em;text-transform:uppercase;transition:padding-left .18s,color .18s}
.stack a:hover{color:var(--accent-ink);padding-left:.35rem}
.stack .arw{color:var(--muted)}
.stack .val{color:var(--muted);text-transform:none;letter-spacing:0;font-family:"Newsreader",serif;font-size:.92rem}
@media(max-width:900px){
  .fine{grid-template-columns:1fr}
  .fine__col + .fine__col{border-left:0;border-top:1px solid var(--line);padding-left:0}
  .fine__col:not(:last-child){padding-right:0}
  .fine__col{padding:1.6rem 0}
}
.foot{border-top:1px solid var(--ink);display:flex;flex-wrap:wrap;gap:.4rem 2rem;align-items:center;padding:.85rem 0 1.7rem;
  font-family:"Space Mono",monospace;font-size:.66rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.foot__soc{display:flex;gap:1rem;margin-left:auto;align-items:center}
.foot__soc a{line-height:0;color:var(--ink)}
.foot__soc a:hover{color:var(--accent-ink)}
.foot__soc svg{width:16px;height:16px;fill:currentColor;display:block}
@media(max-width:640px){.foot{gap:.35rem .9rem;font-size:.62rem}.foot__soc{margin-left:0;flex-basis:100%;padding-top:.4rem}}

/* ---- TOUCH TARGETS ----------------------------------------------------
   The mono links are ~13px tall by design. On touch devices each one gets a
   transparent 44px hit area via ::after — hit area only, so nothing moves by
   a pixel. WCAG 2.5.8 wants 24x24 CSS px; this clears it with room. Applied
   only where neighbours are far enough apart that the areas can't overlap. */
@media (hover: none) {
  .frame__links a, .stack a, .stack details > summary, .nav__links a, .foot__soc a { position: relative; }
  .frame__links a::after,
  .stack a::after,
  .stack details > summary::after,
  .foot__soc a::after {
    content: ""; position: absolute; left: -8px; right: -8px;
    top: 50%; transform: translateY(-50%); height: 44px;
  }
  /* the nav drawer rows are already full-width blocks with real padding */
  .nav__toggle { padding: .75rem; margin: -.35rem; }
}

/* ---- ROSTER MENU IN THE HEADER ----------------------------------------
   Generated by build.py from artists.json, so it can never drift from the
   roster. Opens on hover and on focus (keyboard), and on tap inside the
   phone drawer. */
.nav__drop{position:relative}
.nav__drop>button{font-family:"Space Mono",monospace;font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink);background:none;border:0;padding:0;cursor:pointer;display:inline-flex;align-items:baseline;gap:.35rem}
.nav__drop>button:hover,.nav__drop>button[aria-expanded="true"]{color:var(--accent-ink)}
.nav__caret{display:inline-block;font-size:.62rem;transition:transform .22s cubic-bezier(.2,.8,.2,1)}
.nav__drop>button[aria-expanded="true"] .nav__caret{transform:rotate(180deg)}
.nav__drop>ul{position:absolute;top:calc(100% + 1.15rem);left:-1.1rem;min-width:13rem;list-style:none;margin:0;padding:.5rem 0;
  background:var(--paper);border:1px solid var(--ink);opacity:0;visibility:hidden;transform:translateY(-5px);
  transition:opacity .18s,transform .18s,visibility 0s .18s;max-height:min(70vh,32rem);overflow-y:auto}
/* Open state is driven ONLY by aria-expanded, which the button toggles. Opening
   on :hover or :focus-within as well made the menu impossible to close by
   clicking: the pointer or the focus ring held it open. */
.nav__drop>button[aria-expanded="true"]+ul{
  opacity:1;visibility:visible;transform:none;transition:opacity .18s,transform .18s,visibility 0s 0s}
.nav__drop>ul li{border:0}
.nav__drop>ul a{display:block;padding:.42rem 1.15rem;font-family:"Space Mono",monospace;font-size:.7rem;
  letter-spacing:.03em;text-transform:uppercase;color:var(--ink);transition:color .15s,padding-left .15s}
.nav__drop>ul a:hover{color:var(--accent-ink);padding-left:1.45rem}

@media(max-width:760px){
  /* inside the drawer the menu is an accordion, not a floating panel */
  .nav__drop>button{display:flex;width:100%;justify-content:space-between;padding:.85rem 0;font-size:.85rem}
  .nav__drop>ul{position:static;opacity:1;visibility:visible;transform:none;border:0;background:transparent;
    padding:0 0 .7rem;max-height:none;overflow:visible;display:none;transition:none}
  .nav__drop>button[aria-expanded="true"]+ul{display:block}
  .nav__drop>ul a{padding:.5rem 0 .5rem 1rem;font-size:.78rem;color:var(--muted)}
  .nav__drop>ul a:hover{padding-left:1.2rem}
}

/* ---- PHONES: SHOW THE PHOTOGRAPH, NOT A SLICE OF IT --------------------
   A full-height frame on a portrait phone forces `cover` to scale by height,
   which throws away roughly half the width of a landscape press photo — heads
   and instruments end up outside the frame. Giving every frame the same 4:3
   box instead means the photo fills the width and gets trimmed top and bottom,
   which is the crop that costs the least. It also makes every artist exactly
   the same height, so the rhythm down the page is even.
   Snapping is off here: with more than one frame per screen it fights the
   scroll instead of helping it. */
@media (max-width: 820px) {
  main { scroll-snap-type: none; }
  .frame {
    height: auto;
    aspect-ratio: 4 / 3;
    scroll-snap-align: none;
    contain-intrinsic-size: auto 300px;
  }
  .frame__scrim { height: 62%; }
  .frame__cap { padding-bottom: 1.5rem; }
  .frame__name { font-size: clamp(1.9rem, 7.4vw, 3rem); }
}
