/* ============================================================
   EVERMORE — design system
   Cinematic, motion-first. Two brand colours, one typeface.
   The family name is o + U+0308 (combining diaeresis), NOT the
   precomposed ö. Escaped spelling must come first or everything
   silently falls back to Arial.
   ============================================================ */

@font-face{font-family:"So\0308 hne";src:url('/wp-content/uploads/2024/08/Sohne-Buch.woff2') format('woff2');font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:"So\0308 hne";src:url('/wp-content/uploads/2024/08/Sohne-Kraftig.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"So\0308 hne";src:url('/wp-content/uploads/2024/08/Sohne-Halbfett.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"So\0308 hne";src:url('/wp-content/uploads/2024/08/Sohne-Dreiviertelfett.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"So\0308 hne";src:url('/wp-content/uploads/2024/08/Sohne-Fett.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}

:root{
  /* palette — ink, then three neutral tiers of white for text, with the
     brand mint reserved as the single accent. Mint is never the body
     colour: it only marks what is interactive, current or being hovered,
     which is what makes it read as the brand rather than as a tint. */
  --ink:#0B0B0B;
  --ink-2:#141414;
  --ink-3:#1E1E1E;
  --mint:#E6FFF9;
  /* The light field is paper, not mint. Mint filling a whole viewport
     reads as a pastel product page; the same mint as a hairline, a
     hover fill or one display word reads as a brand. Every full-bleed
     light surface therefore uses --field and mint stays an accent. To
     put the mint fields back, change this one value. */
  --field:#E6FFF9;
  --paper:#FFFFFF;
  --paper-dim:rgba(255,255,255,.72);
  --paper-faint:rgba(255,255,255,.60);
  --line:rgba(255,255,255,.18);
  --line-strong:rgba(255,255,255,.40);
  --line-soft:rgba(255,255,255,.07);

  --font:"So\0308 hne","Söhne","Helvetica Neue",Helvetica,Arial,sans-serif;

  /* type — fluid, never vw alone */
  --t-display:clamp(3.25rem,11.5vw,13rem);
  --t-hero:clamp(2.75rem,8.5vw,9rem);
  --t-xl:clamp(2rem,5.5vw,5rem);
  --t-lg:clamp(1.5rem,3.2vw,2.75rem);
  --t-md:clamp(1.125rem,1.8vw,1.5rem);
  --t-body:clamp(1rem,.9rem + .45vw,1.1875rem);
  --t-label:.75rem;

  /* 8pt spacing */
  --s1:.5rem; --s2:1rem; --s3:1.5rem; --s4:2rem; --s5:3rem;
  --s6:4rem; --s7:6rem; --s8:8rem; --s9:12rem;
  --gutter:clamp(1.25rem,4vw,4rem);
  --maxw:1680px;

  /* motion — one easing family, one set of durations */
  --ease:cubic-bezier(.16,1,.3,1);
  --ease-io:cubic-bezier(.65,.05,.36,1);
  /* ace.nl's menu curve, measured off their panel: fast off the mark, then
     a long soft landing. Used both ways, in and out. */
  --ease-menu:cubic-bezier(.17,.17,0,1);
  --d-menu:.9s;
  /* quintInOut: the curtain's curve, slow at both ends, fast through the middle */
  --ease-curtain:cubic-bezier(.86,0,.07,1);
  --d-fast:.32s;
  --d-mid:.72s;
  --d-slow:1.1s;
  --d-reveal:1.15s;
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-tap-highlight-color:transparent}
/* ^ a touch browser flashes a blue box on anything tapped; on the burger
   and the menu's close button that flash was most of the "glitch" */
html{
  color-scheme:dark;
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  /* the menu sets overflow:hidden on body; without a reserved gutter a
     desktop with a classic scrollbar shifts the whole page sideways */
  scrollbar-gutter:stable;
}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}
.lenis.lenis-stopped{overflow:hidden}

body{
  margin:0;
  background:var(--ink);
  color:var(--paper);
  font-family:var(--font);
  font-weight:400;
  font-size:var(--t-body);
  line-height:1.55;
  letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}

img,video{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
h1,h2,h3,h4,p,figure,blockquote{margin:0}
ul,ol{margin:0;padding:0;list-style:none}

::selection{background:var(--mint);color:var(--ink)}

.skip{
  position:absolute;left:-9999px;top:0;z-index:999;
  background:var(--mint);color:var(--ink);padding:1rem 1.25rem;font-weight:500;
}
.skip:focus{left:0}

:focus-visible{
  outline:2px solid var(--paper);
  outline-offset:4px;
  border-radius:2px;
}

/* film grain — the cheap trick that makes a flat page feel shot
   rather than rendered. One 100-byte SVG, GPU-composited. */
body::after{
  content:"";
  position:fixed;
  inset:0;
  z-index:9999;
  pointer-events:none;
  opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  /* static and viewport-sized (25 Sept 2026, "de site laggt"): it was
     inset:-50% (four screens of layer) jittering forever, blended over
     every frame of the whole site. At .035 the movement was invisible. */
}

/* ------------------------------------------------------------
   LAYOUT
   ------------------------------------------------------------ */
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}
.section{position:relative;padding-block:clamp(4rem,10vw,var(--s9))}
.bleed{position:relative;width:100%}

.rule{height:1px;background:var(--line);border:0;margin:0}

/* ------------------------------------------------------------
   TYPE
   ------------------------------------------------------------ */
.display{
  font-size:var(--t-display);
  font-weight:600;
  line-height:.86;
  letter-spacing:-.045em;
}
/* The footer CTA heading, only. It used to reuse .display (the 13rem cap,
   bigger than even the homepage's own hero), which is disproportionate for
   a line repeated on 24 of 27 pages: bigger than any actual page headline,
   on the one element that appears everywhere. --t-xl is the same scale as
   a section heading like "Artists A-Z", which is loud enough to read as a
   call to action without out-shouting the page it sits under. */
.cta__title{
  font-size:var(--t-xl);
  font-weight:600;
  line-height:.94;
  letter-spacing:-.03em;
}
.hero-type{
  font-size:var(--t-hero);
  font-weight:600;
  line-height:.9;
  letter-spacing:-.04em;
}
/* the homepage line is a statement, not a shout: deliberately a step
   down from the artist-name scale so the roster stays the loudest thing */
/* The homepage headline is the one line that has to carry the whole
   agency, so it is set larger than any other hero on the site and
   tighter than the body tracking. It is a seven word sentence, so it is
   capped at 7.5rem and 13ch: three lines on every screen. */
.hero-type--home{font-size:clamp(2.75rem,7vw,7.5rem);line-height:.92;letter-spacing:-.025em;max-width:13ch}
/* Mint stops being the field and becomes one word. splitLines() rewrites
   the h1 into one .reveal per line; the claim is "Built for the ones who
   challenge the ordinary." and max-width keeps "ordinary." alone on the
   last line at every width, so the accent lands on it and nowhere else. Before the split runs,
   and with JS off, the line is plain white: a degraded accent, not a
   broken headline. This is the ONLY place mint is ever a text colour. */
.hero-type--home .reveal:last-child > span{color:var(--mint)}
.h-xl{font-size:var(--t-xl);font-weight:600;line-height:.98;letter-spacing:-.035em}
.h-lg{font-size:var(--t-lg);font-weight:500;line-height:1.08;letter-spacing:-.025em}
.h-md{font-size:var(--t-md);font-weight:500;line-height:1.25;letter-spacing:-.015em}

.label{
  font-size:var(--t-label);
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--paper-faint);
  line-height:1.2;
}
.lead{
  font-size:clamp(1.25rem,2.4vw,2rem);
  font-weight:400;
  line-height:1.3;
  letter-spacing:-.02em;
  max-width:22ch;
}
.body{max-width:62ch;color:var(--paper-dim)}
/* legal pages: clauses stacked, sub-items A. to I. indented under their clause */
.legal{display:grid;gap:.9em;max-width:64ch}
.legal .body{max-width:none}
.legal__sub{padding-left:1.5em}
.body p + p{margin-top:var(--s2)}
/* The first paragraph of a bio is set as a lead: larger, full white, a
   shorter measure. Two sizes of text in one column is what makes a long
   biography read as edited rather than pasted. */
.body--lead > p:first-child{
  font-size:clamp(1.1875rem,.95rem + .85vw,1.625rem);line-height:1.32;letter-spacing:-.015em;
  color:var(--paper);max-width:38ch;
}
.body--lead > p:first-child + p{margin-top:var(--s3)}
.dim{color:var(--paper-dim)}

/* ------------------------------------------------------------
   MOTION — reveals
   Text reveals line by line behind a mask. The wrapper clips,
   the inner element slides up. Set by JS per line.
   ------------------------------------------------------------ */
.reveal{overflow:hidden;display:block}
/* Display type is set at line-height .9, so the mask would clip every
   descender (the p in "Irreplaceable.", "a person"). The padding gives
   the glyphs room below the line and the negative margin takes it back,
   so line spacing is unchanged; the hidden offset grows to match. */
.hero-type .reveal,.cta__title .reveal,.h-lg .reveal,.statement__line .reveal{padding-bottom:.16em;margin-bottom:-.16em}
.reveal > *{
  display:block;
  transform:translate3d(0,130%,0);
  transition:transform var(--d-reveal) var(--ease);
  transition-delay:var(--delay,0ms);
}
.is-in .reveal > *,.reveal.is-in > *{transform:translate3d(0,0,0)}

/* generic fade-and-rise for blocks that are not type */
.rise{
  opacity:0;
  transform:translate3d(0,40px,0);
  transition:opacity var(--d-mid) var(--ease),transform var(--d-mid) var(--ease);
  transition-delay:var(--delay,0ms);
}
.is-in .rise,.rise.is-in{opacity:1;transform:none}

/* media that scales down into place as it enters */
.media{position:relative;overflow:hidden;background:var(--ink-2)}
.media img,.media video{
  width:100%;height:100%;object-fit:cover;
  transform:scale(1.18);
  transition:transform 1.4s var(--ease);
}
.is-in .media img,.is-in .media video,.media.is-in img,.media.is-in video{transform:scale(1)}

/* a line that draws itself */
.draw{transform:scaleX(0);transform-origin:left;transition:transform var(--d-slow) var(--ease);transition-delay:var(--delay,0ms)}
.is-in .draw,.draw.is-in{transform:scaleX(1)}

/* ------------------------------------------------------------
   HEADER
   ------------------------------------------------------------ */
/* The logo and the menu words are plain white at every scroll position and
   over every background. No blend mode: difference would tint them against
   whatever photo happens to sit behind, and the mark is the one thing on the
   site that must always look like itself. A drop shadow, not a colour shift,
   is what keeps them readable over a bright frame. */
/* The header is absolute, not fixed: the logo and the words scroll away
   with the page, as ace.nl's do, and come back the moment you return to the
   top. Only the burger is fixed (see HEADER COLLAPSE below). */
.hdr{
  position:absolute;
  inset:0 0 auto 0;
  z-index:100;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  padding:clamp(1rem,2.2vw,1.75rem) var(--gutter);
  color:var(--paper);
  pointer-events:none;
  /* coming back after the menu: visible at once, faded in while the panel
     is still leaving. It had visibility on a .34s delay in this direction
     too, so the header was missing for a third of a second after the menu
     closed and then popped in. */
  transition:opacity .5s var(--ease) .2s,visibility 0s linear 0s;
}
.hdr > *{pointer-events:auto}
/* one even scrim across the top instead of a shadow per element: a blurred
   shadow behind white type leaves a visible smudge on the ink pages */
.hdr::before{
  content:"";position:absolute;inset:0 0 auto 0;height:260%;z-index:-1;
  /* Eased, not linear, and starting near solid ink. A straight .62 -> 0
     ramp ends with a kink the eye reads as an edge: over the hero's own
     scrim it left a bright ridge ~140px down on a phone, "an overlay that
     stops there". And a phone's status bar is painted in theme-color ink,
     so a top at .62 sat under it as a lighter band. Now it starts at the
     ink the status bar already is and fades out with no visible end. */
  background:linear-gradient(180deg,rgba(11,11,11,.9) 0%,rgba(11,11,11,.72) 12%,rgba(11,11,11,.5) 28%,rgba(11,11,11,.31) 45%,rgba(11,11,11,.16) 62%,rgba(11,11,11,.06) 78%,rgba(11,11,11,.015) 90%,rgba(11,11,11,0) 100%);
  pointer-events:none;
  transition:opacity var(--d-fast) linear;
}
.hdr__logo{display:block;width:clamp(120px,11vw,168px);flex:none}
.hdr__logo img{width:100%;height:auto}
.hdr__nav{display:flex;align-items:center;gap:clamp(1.25rem,2.4vw,2.5rem)}
.hdr__nav a{
  font-size:.875rem;font-weight:500;letter-spacing:.02em;
  position:relative;padding-block:.25rem;
  color:var(--paper);
}
/* Every underline on the site moves one way, measured off ace.nl's nav:
   it grows out of the middle to both ends and shrinks back into it, on an
   in-out curve that is fastest halfway (25 Sept 2026). */
.hdr__nav a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:center;
  transition:transform .45s var(--ease-io);
}
.hdr__nav a:hover::after,.hdr__nav a[aria-current]::after{transform:scaleX(1)}

@media (max-width:860px){
  .hdr__nav{display:none}
  .hdr__burger{display:block}
}

/* ------------------------------------------------------------
   MENU — a mint card that slides out from under the burger.
   Not a full-screen takeover: the page stays visible behind a
   scrim, so the menu reads as a drawer you opened rather than a
   different page you landed on. This is the site's third mint
   field and the only one that is not page content; it is allowed
   because it is transient and because it is the one moment the
   brand colour carries navigation.
   ------------------------------------------------------------ */
.menu{
  position:fixed;inset:0;z-index:200;
  /* the closed panel is parked past the right edge; without this it widens
     the document and every page gets a horizontal scrollbar. clip, not
     hidden: a hidden box is still a scroll container, and focusing the
     close button mid-slide scrolled it and snapped the panel into place */
  overflow:hidden;overflow:clip;
  visibility:hidden;pointer-events:none;
  /* The exit has to survive long enough to be watched. visibility:hidden
     applied on the same frame .is-open is dropped hides the panel before it
     has moved one pixel, so the menu did not close, it vanished, and the
     slide ran out its full duration off-screen where nobody could see it.
     Hold visibility until the panel is actually gone. Same delayed-
     visibility shape the collapsing header already uses. */
  transition:visibility 0s linear var(--d-menu);
}
.menu.is-open{visibility:visible;pointer-events:auto;transition-delay:0s}
.menu__scrim{
  position:absolute;inset:0;
  background:rgba(11,11,11,.72);
  /* the page underneath loses half its colour as well as its light, as it
     does under ace's menu */
  -webkit-backdrop-filter:grayscale(.5);backdrop-filter:grayscale(.5);
  /* one even fade both ways, shorter than the panel, as ace's is */
  opacity:0;transition:opacity .45s var(--ease-io);
}
.menu.is-open .menu__scrim{opacity:1}

/* Half the screen, full height, flush to the edges. Not a card: the mint
   runs off three sides so it reads as the page being split in two, with the
   site still there, dimmed, in the other half. */
.menu__panel{
  position:absolute;top:0;right:0;bottom:0;
  /* half the screen, as the reference does it, but capped: past ~1760px a
     true half is an ocean of mint with five words floating in it */
  width:min(50vw,880px);
  display:flex;flex-direction:column;
  background:var(--field);color:var(--ink);
  padding:clamp(1.25rem,2.2vw,1.9rem) clamp(1.5rem,3.4vw,3.5rem) clamp(1.75rem,3.4vw,3.25rem);
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
  transform:translate3d(100%,0,0);
  /* the largest surface the site ever moves, and a scroll container on top
     of that: promote it or the compositor re-rasters paper every frame */
  will-change:transform;
  /* One curve both ways, ace's, at ace's .9s (measured: 90% in by ~500ms,
     settled by ~950ms). It was .72s expo-out in and .52s accelerating out,
     and on a phone that read as a flash: a full-width panel covered the
     screen in ~90ms, sat there empty while the words staged in, and on the
     way out shot off the edge. The agency: "langzamer en soepeler zoals
     bij ace". */
  transition:transform var(--d-menu) var(--ease-menu);
}
.menu.is-open .menu__panel{transform:translate3d(0,0,0)}

.menu__head{
  flex:none;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
}
.menu__panel .hdr__logo{width:clamp(104px,9vw,148px);flex:none}
/* the mark is white on transparent; on a mint field it has to be ink */
.menu__panel .hdr__logo img{filter:invert(1)}

.menu__close{
  flex:none;position:relative;
  width:46px;height:46px;margin-right:-11px;
  background:none;border:0;padding:0;cursor:pointer;
  border-radius:50%;
}
/* ace.nl's close: both bars pivot on their left end, so on hover the cross
   swings open into one flat dash (their --ty/--rotation to 0, .3s on their
   curve). 9.19px is 26px x .3536, half the cross's height. The left edge
   splits the difference: cross ~2px left of centre, dash ~2px right. */
.menu__close span{
  position:absolute;left:calc(50% - 11.1px);top:50%;
  width:26px;height:1.5px;margin-top:-.75px;
  background:var(--ink);
  transform-origin:left center;
  transition:transform .3s cubic-bezier(.17,.17,0,1);
}
.menu__close span:nth-child(1){transform:translateY(9.19px) rotate(-45deg)}
.menu__close span:nth-child(2){transform:translateY(-9.19px) rotate(45deg)}
@media (hover:hover) and (pointer:fine){
  .menu__close:hover span{transform:none}
}

/* Right aligned and at display size: the nav is the whole point of the half,
   so it sits in the optical centre with the contact block under it. */
.menu__nav{
  flex:1 1 auto;
  display:flex;flex-direction:column;align-items:flex-end;justify-content:center;
  text-align:right;
  padding-block:clamp(1.75rem,6vh,4.5rem);
  gap:clamp(.1rem,.5vw,.35rem);
}
.menu__nav a{
  display:block;position:relative;
  font-size:clamp(2rem,3.7vw,3.625rem);
  font-weight:500;line-height:1.12;letter-spacing:-.035em;
  color:var(--ink);
}
.menu__nav a::after{
  content:"";position:absolute;left:0;bottom:.08em;width:100%;height:2px;
  background:var(--ink);transform:scaleX(0);transform-origin:right;
  transition:transform var(--d-fast) var(--ease);
}
@media (hover:hover){
  .menu__nav a:hover::after{transform:scaleX(1);transform-origin:right}
}
.menu__nav a[aria-current]::after{transform:scaleX(1);transform-origin:right}
/* The words are staged behind the panel: each item carries its own
   data-delay, so they climb in one after another once the paper has
   arrived instead of all five racing the slide. Going the other way that
   staging is wrong, a menu you are dismissing must not make you wait for
   the last word to leave, so on close nothing inside the panel moves at
   all: the words and the contact block ride out on the paper, the way ace
   does it, and ev.js parks them below again once the panel is gone.
   (They used to leave upward first, which emptied the panel and then slid
   a blank sheet of mint away: the "cheap" half of the phone complaint.) */
.menu__nav .reveal > *{transition-duration:.8s}
.menu.is-closing .menu__nav .reveal > *{transition:none}

/* label column, value column, one row each: the same shape as the footer.
   It used to carry no reveal at all and popped in instantly with the
   panel, which is why the whole menu read as faster than ace's: ace's own
   cascade lands its contact block last, around 700-1000ms in, well after
   the nav has staged in, so the sequence has a visible "settling" beat at
   the end. Our five nav words already finish staging in around 460ms
   (last data-delay) plus their own reveal; this starts after that and
   settles about 550ms later, giving the same three-stage feel: panel,
   then nav, then contact. */
.menu__foot{
  flex:none;
  display:grid;grid-template-columns:auto 1fr;
  column-gap:clamp(1.25rem,2.6vw,2.5rem);row-gap:.55rem;
  align-items:baseline;
  font-size:clamp(.9375rem,1.05vw,1.0625rem);
  margin:0;
  opacity:0;transform:translate3d(0,14px,0);
  transition:opacity .6s var(--ease),transform .6s var(--ease);
}
.menu.is-open .menu__foot{
  opacity:1;transform:translate3d(0,0,0);
  transition-delay:.6s;
}
/* closing: the contact block stays put and leaves with the panel */
.menu.is-closing .menu__foot{opacity:1;transform:translate3d(0,0,0);transition:none}
.menu:not(.is-open):not(.is-closing) .menu__foot{transition:none}
.menu__foot dt{color:rgba(11,11,11,.58);white-space:nowrap}
.menu__foot dd{margin:0;min-width:0;overflow-wrap:anywhere;font-weight:500}
.menu__foot a{
  color:var(--ink);
  text-decoration:underline;text-decoration-color:transparent;
  text-underline-offset:3px;text-decoration-thickness:1px;
  transition:text-decoration-color var(--d-fast) linear;
}
.menu__foot a:hover{text-decoration-color:currentColor}
.menu :focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* Under 900 the half becomes the whole: 50vw of a phone is a column too
   narrow for the nav to stay at display size. */
@media (max-width:900px){
  .menu__panel{width:100%;padding-top:clamp(1rem,2.2vw,1.75rem);padding-inline:var(--gutter)}
  /* Full screen, the panel's head lands exactly where the header was: same
     logo size and position, and the X centred on the burger it replaces.
     They sat 4px, 11px and 16px apart, so every open and close ended with
     the logo and the button jumping, which read as a glitch. */
  .menu__head{height:calc(clamp(120px,11vw,168px) * .2559)}
  .menu__panel .hdr__logo{width:clamp(120px,11vw,168px)}
  .menu__close{margin-right:-1.5px}
  /* the scrim is entirely behind an opaque panel here, so a full-screen
     backdrop filter would be repainted every frame of the slide for nothing */
  .menu__scrim{-webkit-backdrop-filter:none;backdrop-filter:none}
}
/* landscape phone: very short, so the nav gives up its breathing room first */
@media (max-height:560px){
  .menu__nav{padding-block:clamp(1rem,3vh,2rem)}
  .menu__nav a{font-size:clamp(1.5rem,5.4vh,2.25rem)}
  .menu__foot{row-gap:.35rem;font-size:.9375rem}
  .menu__panel .hdr__logo{width:100px}
}
@media (max-height:420px){
  .menu__panel{padding:1rem 1.25rem 1.25rem}
  .menu__nav{padding-block:.75rem}
}

/* ------------------------------------------------------------
   HERO
   ------------------------------------------------------------ */
.hero{
  position:relative;
  min-height:100svh;
  max-height:none;
  display:flex;
  align-items:flex-end;
  overflow:hidden;
  padding-block:var(--s6) clamp(2rem,6vw,var(--s6));
}
.hero__media{
  position:absolute;inset:0;z-index:0;
  overflow:hidden;
}
.hero__media img,.hero__media video{
  width:100%;height:100%;object-fit:cover;object-position:var(--fx,50%) var(--fy,32%);
  transform:scale(1.1);
}
/* The montage frames are stacked and crossfaded. Only the first carries a
   real src; initHeroMontage() fills the rest in one at a time and stops the
   moment the hero leaves the viewport, so a visitor who scrolls straight
   past downloads exactly one photograph rather than eighteen. */
.hero__frame{
  position:absolute;inset:0;
  opacity:0;
  transition:opacity 1.6s linear;
}
.hero__frame.is-on{opacity:1}
/* only the visible frame keeps a standing layer; the one fading in is
   promoted by its own transition. All eighteen used to hold one. */
.hero__frame.is-on{will-change:transform}
.no-js .hero__frame{opacity:0}
.no-js .hero__frame.is-on{opacity:1}
/* only the visible frame keeps a standing layer; the one fading in is
   promoted by its own transition. All eighteen used to hold one. */
.hero__frame.is-on{will-change:transform}

.hero__media::after{
  content:"";position:absolute;inset:0;
  /* This used to sit over one near-black frame and could afford to be
     almost clear through the middle. It now has to carry white display type
     over the whole roster, half of which is shot in daylight, so it is
     deeper everywhere and deepest where the headline actually lands. */
  background:linear-gradient(180deg,rgba(11,11,11,.66) 0%,rgba(11,11,11,.34) 22%,rgba(11,11,11,.54) 50%,rgba(11,11,11,.84) 78%,rgba(11,11,11,.96) 100%);
}
.hero__inner{position:relative;z-index:1;width:100%}

.hero__meta{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);
  align-items:baseline;justify-content:space-between;
  margin-top:var(--s4);padding-top:var(--s2);
  border-top:1px solid var(--line);
}
@media (max-height:520px) and (orientation:landscape){
  .hero,.panel,.artist__hero{min-height:0;height:auto;padding-block:5.5rem 1.5rem}
  .hero__meta{margin-top:var(--s2)}
}

/* ------------------------------------------------------------
   PANELS — the roster as full-bleed previews (homepage)
   One near-screen-high frame per artist. 86svh, not 100svh:
   at full height eighteen of them never end.
   ------------------------------------------------------------ */
.panels{position:relative}
.panel{
  position:relative;
  min-height:clamp(520px,86svh,920px);
  display:flex;align-items:flex-end;
  overflow:hidden;
  padding:var(--s6) var(--gutter) clamp(2rem,6vw,var(--s6));
  color:var(--paper);text-decoration:none;
  border-top:1px solid rgba(255,255,255,.08);
}
.panel__media{position:absolute;inset:0;z-index:0;overflow:hidden}
.panel__media img{
  width:100%;height:100%;object-fit:cover;object-position:var(--fx,50%) var(--fy,26%);
  /* the parallax loop writes scale(1.1) translate3d(...) over this; the 10%
     is the headroom the translate eats, so never animate it back to 1 */
  transform:scale(1.1);
}
.panel__media::after{
  content:"";position:absolute;inset:0;
  /* the name sits at roughly 78% of the frame, so the scrim has to be well
     under way by then: white display type over a bright photo is unreadable */
  background:linear-gradient(180deg,rgba(11,11,11,.32) 0%,rgba(11,11,11,.06) 30%,rgba(11,11,11,.38) 56%,rgba(11,11,11,.74) 78%,rgba(11,11,11,.95) 100%);
}
.panel__inner{position:relative;z-index:1;width:100%;max-width:var(--maxw);margin-inline:auto}
.panel__name{margin-top:.2em;transition:translate .7s cubic-bezier(.17,.17,0,1)}
/* Hover, as ace's work tiles do it: a veil over the photograph lifts, the
   name slides right and a short mint bar draws in ahead of it. No zoom:
   the photograph is already scaled for the parallax. The mint is the bar,
   not the name, so the name stays readable on any frame. */
.panel__media::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:rgba(11,11,11,.2);transition:opacity .25s linear;
}
/* The bar rides on the name: parked one slide-width to its left, so when
   the name moves over it draws into exactly the space the name left. */
.panel__name{position:relative}
.panel__name::before{
  content:"";position:absolute;left:-2.5rem;top:.44em;width:32px;height:3px;background:var(--mint);
  transform:scaleX(0);transform-origin:left;
  transition:transform .3s cubic-bezier(.17,.17,0,1);
}
@media (hover:hover){
  .panel:hover .panel__media::before{opacity:0}
  .panel:hover .panel__name{translate:2.5rem 0}
  .panel:hover .panel__name::before{transform:scaleX(1);transition-delay:.12s}
}
.panel:focus-visible .panel__name{translate:2.5rem 0}
.panel:focus-visible .panel__name::before{transform:scaleX(1)}
.panel__foot{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:var(--s2) var(--s4);margin-top:var(--s3);
  padding-top:var(--s2);border-top:1px solid var(--line);
}
.panel:focus-visible{outline:2px solid var(--mint);outline-offset:-6px}
/* The roster photography is all landscape. In a tall phone frame `cover`
   crops away two thirds of the width and the face goes with it, so the
   preview gets shorter and the crop is anchored higher up. */
@media (max-width:700px){
  .panel{min-height:clamp(400px,62svh,620px)}
  .panel__media img{object-position:var(--fx,50%) var(--fy,18%)}
}

/* ------------------------------------------------------------
   ROSTER GRID
   ------------------------------------------------------------ */
.roster{
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  /* The row gap stays larger than the column gap. At an equal gap the tiles
     close into a contact sheet: one artist's frame runs straight into the
     next and the page reads as a directory of available stock rather than a
     roster. Dead level, never staggered: at this width an alternating drop
     puts names at two different heights in every row and reads as a layout
     fault. */
  gap:clamp(2.25rem,3.6vw,3.5rem) clamp(1.25rem,2vw,1.75rem);
}
/* Five across on a desktop, four from 1439 down, three from laptop down,
   two from tablet down. The `sizes` attribute in picture() assumes exactly
   this ladder: 20vw above 1439, 25vw to 1200, 33vw to 900, 50vw at 899 and
   under. Change one and change the other, or a phone downloads a desktop
   derivative. */
@media (max-width:1439px){.roster{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:1199px){.roster{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:899px){.roster{grid-template-columns:repeat(2,minmax(0,1fr))}}
.card{position:relative;display:block}
/* 4/3, not the source's own 3/2 and not a portrait frame. 19 of the 20
   thumbs are 3:2 landscape, so a tall tile crops a third off the sides and
   pushes off-centre subjects out of frame; 4/3 takes 11%, which the
   object-position absorbs, and buys the height the name needs inside. */
.card__media{
  position:relative;overflow:hidden;
  aspect-ratio:4/3;
  background:var(--ink-2);
  /* the name is sized against the tile, not the viewport: at 1199px the
     grid drops to three and the tiles get WIDER, so a vw-based name shrank
     exactly where it had more room */
  container-type:inline-size;
}
.card__media img{
  width:100%;height:100%;object-fit:cover;object-position:var(--fx,50%) var(--fy,42%);
  transform:scale(1.06);
  filter:grayscale(1) contrast(1.05);
  transition:transform 1.1s var(--ease),filter var(--d-mid) var(--ease);
}
/* ------------------------------------------------------------
   PHOTOGRAPHS: focal points and portrait companions (Sept 2026)
   Most press photography is shot upright and every frame here is
   landscape, so a portrait master cut to a band and then cover-fitted
   into a tall phone frame kept a third of its width and was blown up
   three times: faces out of frame and soft. Two fixes, both driven by
   _src/images.json:
   - "focus": [x,y] per image, emitted as --fx/--fy, is where the crop
     anchors in every frame the image appears in (hero, preview, tile,
     Up next). Frames without one keep their old anchor as fallback.
   - "portrait": a 2:3 companion cut from the same master. picture()
     wraps hero, preview and Up next in <picture> with a
     (orientation:portrait) source, so an upright screen gets the
     upright photograph. Its own focal point is --px/--py, and
     data-pf marks the images that have one.
   ------------------------------------------------------------ */
picture{display:contents}
@media (orientation:portrait){
  html img[data-pf]{object-position:var(--px,50%) var(--py,30%)}
}
/* "upright": a photograph with no landscape frame in it. On a landscape
   screen it is shown whole, full height against the right edge, and fades
   into the ink on its left where the name sits, instead of being cropped
   to a band that is all face. */
@media (orientation:landscape){
  html img[data-upright]{
    display:block;width:auto;height:100%;aspect-ratio:2/3;max-width:100%;
    margin-left:auto;object-fit:cover;object-position:50% 50%;
    transform-origin:100% 50%;
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 45%);
            mask-image:linear-gradient(90deg,transparent 0,#000 45%);
  }
}
.card:hover .card__media img,.card:focus-visible .card__media img{
  transform:scale(1);filter:grayscale(0) contrast(1);
}
@media (hover:none){
  .card__media img{filter:grayscale(0) contrast(1);transform:scale(1)}
  .row__thumb{opacity:1;transform:none}
}
/* The scrim is what makes the name legible, so unlike the old decorative
   one it does not lift on hover: half this roster is shot in daylight and
   the hover gesture is the colour coming back, not the type going. Measured
   against the rendered pixels behind every name by _src/checks/roster.mjs. */
.card__media::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,
    transparent 32%,
    rgba(11,11,11,.24) 54%,
    rgba(11,11,11,.56) 69%,
    rgba(11,11,11,.80) 84%,
    rgba(11,11,11,.90) 100%);
}
/* Lower left, inside the frame, on the same optical margin as the tile's
   own edge. */
.card__row{
  position:absolute;z-index:2;left:0;right:0;bottom:0;
  display:flex;flex-direction:column;gap:.15rem;
  padding:0 clamp(.75rem,1.1vw,1.1rem) clamp(.7rem,1vw,1rem);
  min-width:0;
}
/* The city under the name. A name on its own under a photograph is a
   caption; a name with the room the artist works out of is a roster entry,
   and it is the first thing a booker actually needs. Sentence case: .label
   is the only thing on this site set in caps. */
.card__meta{
  font-size:clamp(.6875rem,4cqw,.8125rem);line-height:1.3;
  color:rgba(255,255,255,.68);
}
.card__name{
  font-size:clamp(.9375rem,6.2cqw,1.5rem);
  font-weight:500;letter-spacing:-.02em;line-height:1.1;
  color:var(--paper);
  /* the tile is narrow: let a long name wrap, and only break inside a word
     when the word itself genuinely does not fit */
  min-width:0;overflow-wrap:break-word;
  transition:color var(--d-fast) var(--ease);
}
.card:hover .card__name,.card:focus-visible .card__name{color:var(--mint)}

/* ------------------------------------------------------------
   MARQUEE — collaborations
   ------------------------------------------------------------ */
.marquee{
  position:relative;overflow:hidden;
  padding-block:var(--s3);
  border-block:1px solid var(--line-soft);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
.marquee__track{
  display:flex;width:max-content;
  animation:marquee var(--speed,60s) linear infinite;
  will-change:transform;
}
/* Pause on hover only where hover is real: on a touch screen a tap leaves
   :hover stuck and the strip froze until you tapped somewhere else. */
@media (hover:hover){.marquee:hover .marquee__track{animation-play-state:paused}}
.marquee__group{display:flex;align-items:center;gap:clamp(2rem,3.6vw,3.5rem);padding-right:clamp(2rem,3.6vw,3.5rem)}
.marquee img{
  /* the masters are 150x150, so 86px is about 1.15x on a 2x screen. These are
     flat marks inverted to white silhouettes, which carries that; a photo at
     the same ratio would not. Do not push past this without bigger sources. */
  height:clamp(54px,6.2vw,86px);width:auto;
  /* These were at .62 and read as greyed-out placeholders rather than as
     the rooms the roster actually plays. They are the agency's proof; a
     proof you have to squint at is not proof. Full white, one weight. */
  opacity:1;filter:grayscale(1) brightness(0) invert(1);
  transition:opacity var(--d-fast) linear;
}
.marquee img:hover{opacity:.7}
@keyframes marquee{to{transform:translate3d(-50%,0,0)}}

/* ------------------------------------------------------------
   LINKS & BUTTONS
   ------------------------------------------------------------ */
.btn{
  display:inline-flex;align-items:center;gap:.75rem;
  padding:1.05rem 1.9rem;
  border:1px solid var(--line);
  border-radius:100px;
  font-size:.9375rem;font-weight:500;letter-spacing:.01em;
  position:relative;overflow:hidden;
  /* isolation:isolate is load-bearing, not decoration. The fills below are
     ::after at z-index:-2 and ::before at z-index:-1, and a negative z-index
     child paints in the NEAREST ANCESTOR stacking context, not inside its
     own element. position:relative with z-index:auto does not create one and
     neither does overflow:hidden, so without this the fills escaped all the
     way to the root and painted at step 2 of the root's order, which is
     before step 3, where the backgrounds of non-positioned blocks are
     painted. Every .field section is exactly such a block, so its paper
     background covered the fill and the label was left floating on it: at
     REST, on every page, not just on hover. Isolating here keeps both fills
     inside the button, above its own transparent background and below its
     label, which is what the comment underneath always claimed. */
  isolation:isolate;
  transition:color var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease),scale .2s var(--ease);
  min-height:48px;
}
.btn::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:var(--mint);
  transform:translate3d(0,101%,0);
  transition:transform .55s var(--ease);
}
.btn:hover,.btn:focus-visible{color:var(--ink);border-color:var(--mint)}
.btn:hover::before,.btn:focus-visible::before{transform:translate3d(0,0,0)}
/* The filled variants carry their fill in ::after, not in background.

   .btn's hover fill is a ::before at z-index:-1, which paints in the
   negative layer BEHIND the element's own background. On the hollow
   .btn that is fine, there is no background to hide behind. Give the
   button an opaque background and the fill is buried: .btn--solid
   went white-on-mint on hover and .btn--ink went ink-on-ink, so
   "Book <artist>" and every button on a mint field lost its label
   the moment you pointed at it. Both were live.

   So the resting fill is ::after at z-index:-2 and the hover fill is
   ::before at z-index:-1 on top of it, with the element's own
   background transparent. Negative layers paint in ascending order
   and the label, being inline content, paints above both. The slide
   survives, which is the point: these buttons are not supposed to
   cross-fade. */
.btn--solid{background:transparent;color:var(--ink);border-color:var(--mint)}
.btn--solid::after{content:"";position:absolute;inset:0;z-index:-2;background:var(--mint)}
.btn--solid::before{background:var(--ink)}
.btn--solid:hover,.btn--solid:focus-visible{color:var(--paper);border-color:var(--paper)}
.btn i{position:relative;display:block;flex:none;width:12px;height:10px}
/* The chevron slides right while a shaft grows in behind it, so ">"
   becomes "->" under the pointer, as ace's buttons do. Two pseudo-elements
   so the head can move without the shaft being dragged through its
   rotation. */
.btn i::before,.btn i::after{content:"";position:absolute;top:50%;left:0}
.btn i::before{
  width:6px;height:6px;margin-top:-3px;
  border-right:1.5px solid currentColor;border-top:1.5px solid currentColor;
  transform:rotate(45deg);
  transition:translate .2s cubic-bezier(.4,0,.2,1);
}
.btn i::after{
  width:10px;height:1.5px;margin-top:-.75px;background:currentColor;
  transform:scaleX(0);transform-origin:left;
  transition:transform .2s cubic-bezier(.4,0,.2,1);
}
.btn:hover i::before,.btn:focus-visible i::before{translate:4px 0}
.btn:hover i::after,.btn:focus-visible i::after{transform:scaleX(1)}
/* pressed: `scale`, not transform, because the magnetic pull writes an
   inline transform on the same button and the two must compose */
.btn:active{scale:.97}

.ulink{
  position:relative;display:inline-block;padding-block:.45rem;
  min-height:24px;
}
.ulink::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:currentColor;
  transform:scaleX(1);transform-origin:center;
  transition:transform .45s var(--ease-io);
}
.ulink:hover::after{transform:scaleX(0)}

/* big list rows, e.g. artists A-Z and jobs */
.rows{border-top:1px solid var(--line)}
.row{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding-block:clamp(1rem,2.2vw,1.75rem);
  border-bottom:1px solid var(--line);
  position:relative;overflow:hidden;
}
.row__name{
  font-size:clamp(1.5rem,4vw,3.25rem);font-weight:600;
  letter-spacing:-.035em;line-height:1;
  transition:transform var(--d-mid) var(--ease);
}
.row:hover .row__name{transform:translateX(clamp(.5rem,1.5vw,1.5rem))}
.row__meta{display:flex;align-items:center;gap:var(--s3);flex:none}
.row__thumb{
  width:clamp(88px,9vw,140px);aspect-ratio:3/2;object-fit:cover;object-position:center 42%;
  opacity:0;transform:translateY(12px) scale(.96);
  transition:opacity var(--d-fast) var(--ease),transform var(--d-fast) var(--ease);
}
.row:hover .row__thumb{opacity:1;transform:none}
@media (max-width:520px){.row__thumb{display:none}}

/* ------------------------------------------------------------
   FORMS
   ------------------------------------------------------------ */
.formrow{display:block;margin-bottom:var(--s3)}
.formrow > span{display:block;margin-bottom:.5rem;color:var(--paper-dim)}
.formrow input,.formrow textarea,.formrow select{
  width:100%;
  background:transparent;
  color:var(--paper);
  border:0;border-bottom:1.5px solid var(--line-strong);
  border-radius:0;
  padding:.9rem 0;
  font:inherit;font-size:1.0625rem;
  min-height:52px;
  transition:border-color var(--d-fast) var(--ease);
}
.formrow textarea{min-height:140px;resize:vertical}
.formrow input::placeholder,.formrow textarea::placeholder{color:var(--paper-faint)}
.formrow input:focus,.formrow textarea:focus,.formrow select:focus{
  border-bottom-color:var(--paper);
  outline:2px solid var(--paper);
  outline-offset:3px;
}
/* The booking form follows the agency's own booking sheet: five groups,
   each headed by a label over a hairline, short fields paired two up. */
.formset{border:0;margin:0 0 clamp(3rem,6vw,4.5rem);padding:0;min-width:0}
.formset > legend{display:block;width:100%;padding:0 0 1rem;margin-bottom:var(--s4);border-bottom:1px solid var(--line);color:var(--paper)}
.formset__note{margin:-.5rem 0 0;font-size:.875rem;line-height:1.5;color:var(--paper-faint);max-width:52ch}
.formset__note--field{margin:-1rem 0 var(--s4)}
.formpair{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:clamp(1.25rem,2.5vw,2rem)}
@media (max-width:560px){.formpair{grid-template-columns:minmax(0,1fr)}}
.formrow--select{position:relative}
.formrow--select select{appearance:none;-webkit-appearance:none;line-height:inherit;padding-right:2rem;cursor:pointer}
.formrow--select::after{content:"";position:absolute;right:.35rem;bottom:calc(.9rem + .5lh);width:7px;height:7px;border:solid var(--paper-dim);border-width:0 1.5px 1.5px 0;transform:translateY(50%) rotate(45deg);pointer-events:none}
.formrow select option{background:var(--ink-2);color:var(--paper)}
/* Booking form, the promoter's side of it. Only the essentials are
   required and every other label carries a quiet "Optional"; Yes / No is
   two radio pills, the artists are pills to tick, the timetable is slots
   with native time inputs (a phone scrolls them on its own wheel). Mint
   marks only what is filled or current, as everywhere else. */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.formlead{font-size:.9375rem;line-height:1.5;color:var(--paper-faint);margin:0 0 var(--s5)}
.formrow > .label{display:flex;align-items:baseline;justify-content:space-between;gap:1rem}
.opt{font-size:.8125rem;font-weight:400;letter-spacing:0;text-transform:none;color:var(--paper-faint)}
.formrow input[type=date],.formrow input[type=time]{color-scheme:dark;text-align:left}
.formrow input[type=date]::-webkit-date-and-time-value,.formrow input[type=time]::-webkit-date-and-time-value{text-align:left}
.formrow input[type=date]::-webkit-calendar-picker-indicator,.formrow input[type=time]::-webkit-calendar-picker-indicator{opacity:.55;cursor:pointer}
.formrow input[type=number]{-moz-appearance:textfield}
.formrow input[type=number]::-webkit-inner-spin-button,.formrow input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
.formrow input:user-invalid,.formrow textarea:user-invalid{border-bottom-style:dashed;border-bottom-color:var(--paper)}
.formset{scroll-margin-top:7rem}

/* pills: the ticked state is filled, so it is mint */
.chip span,.seg__opt span{
  display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:.55rem 1.1rem;
  border:1.5px solid var(--line-strong);border-radius:100px;font-size:.9375rem;font-weight:500;line-height:1.1;
  color:var(--paper);cursor:pointer;user-select:none;-webkit-user-select:none;
  transition:background var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease),color var(--d-fast) var(--ease);
}
.chip,.seg__opt{position:relative;display:inline-flex}
.chip input,.seg__opt input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.chip input:checked + span,.seg__opt input:checked + span{background:var(--mint);border-color:var(--mint);color:var(--ink)}
.chip input:focus-visible + span,.seg__opt input:focus-visible + span{outline:2px solid var(--paper);outline-offset:3px}
@media (hover:hover){
  .chip:hover input:not(:checked) + span,.seg__opt:hover input:not(:checked) + span{border-color:var(--paper)}
}
.picks__list{display:flex;flex-wrap:wrap;gap:.5rem;padding-top:.35rem}
.picks__list[hidden]{display:none}
.picks.is-enhanced > input{display:none}
.seg__opts{display:flex;gap:.5rem;padding-top:.35rem}
.seg__opt span{min-width:5.25rem}
.seg{margin-bottom:var(--s3)}
@media (max-width:560px){
  .chip span{padding:.5rem .85rem;font-size:.875rem;min-height:42px}
  .picks__list{gap:.4rem}
}

/* the offer: currency and amount on one underline */
.money__row{display:flex;align-items:stretch;gap:1rem}
.money__cur{position:relative;flex:none}
.money__cur select{width:auto;appearance:none;-webkit-appearance:none;line-height:inherit;padding-right:1.6rem;font-weight:500;cursor:pointer}
.money__cur::after{content:"";position:absolute;right:.3rem;top:50%;width:7px;height:7px;border:solid var(--paper-dim);border-width:0 1.5px 1.5px 0;transform:translateY(-75%) rotate(45deg);pointer-events:none}
.money__row input{flex:1 1 auto;min-width:0}

/* timetable slots */
.slots.is-enhanced > .formrow{display:none}
.slots__head,.slot{display:grid;grid-template-columns:minmax(0,7.5rem) minmax(0,7.5rem) minmax(0,1fr) 44px;column-gap:clamp(.75rem,2vw,1.5rem);align-items:end}
.slots__head{margin-bottom:.1rem}
.slots__head span{color:var(--paper-dim)}
.slot{margin-bottom:.35rem}
.slot .formrow{margin:0}
.slot__x{
  position:relative;width:44px;height:44px;margin-bottom:4px;border:0;background:none;border-radius:50%;cursor:pointer;color:var(--paper-faint);
  transition:color var(--d-fast) var(--ease),background var(--d-fast) var(--ease);
}
.slot__x::before,.slot__x::after{content:"";position:absolute;left:50%;top:50%;width:14px;height:1.5px;background:currentColor;transform:translate(-50%,-50%) rotate(45deg)}
.slot__x::after{transform:translate(-50%,-50%) rotate(-45deg)}
.slot__x:focus-visible{outline:2px solid var(--paper);outline-offset:0}
@media (hover:hover){.slot__x:hover{color:var(--ink);background:var(--mint)}}
.slots__list .slot:only-child .slot__x{visibility:hidden}
.slot.is-new{animation:slot-in .5s var(--ease) both}
@keyframes slot-in{from{opacity:0;transform:translate3d(0,-.5rem,0)}}
.slots__add{
  display:inline-flex;align-items:center;gap:.7rem;margin-top:1.1rem;min-height:44px;padding:.55rem 1.15rem .55rem .9rem;
  border:1.5px dashed var(--line-strong);border-radius:100px;background:none;color:var(--paper);font:inherit;font-size:.9375rem;font-weight:500;cursor:pointer;
  transition:border-color var(--d-fast) var(--ease),background var(--d-fast) var(--ease),color var(--d-fast) var(--ease);
}
.slots__add::before{content:"+";font-size:1.25rem;line-height:1;font-weight:400}
.slots__add:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
@media (hover:hover){.slots__add:hover{border-style:solid;border-color:var(--mint);background:var(--mint);color:var(--ink)}}
.slots__add[hidden]{display:none}
@media (max-width:560px){
  .slots__head,.slot{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 44px;column-gap:.75rem}
  .slots__head span:nth-child(3){display:none}
  .slot{row-gap:0;padding-bottom:.9rem;margin-bottom:.9rem;border-bottom:1px solid var(--line)}
  .slot > :nth-child(3){grid-column:1 / 3;grid-row:2}
  .slot > .slot__x{grid-column:3;grid-row:1}
  .slots__list .slot:last-child{border-bottom:0;margin-bottom:0}
}

/* contracting: one switch opens the three roles */
.switch{display:flex;align-items:center;gap:1rem;cursor:pointer;font-size:1rem;line-height:1.4;color:var(--paper-dim);padding:.25rem 0}
.switch input{
  appearance:none;-webkit-appearance:none;margin:0;flex:none;cursor:pointer;
  width:50px;height:28px;border-radius:100px;position:relative;
  background:var(--ink-3);border:1.5px solid var(--line-strong);
  transition:background var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease);
}
.switch input::before{content:"";position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;background:var(--paper);transition:transform var(--d-fast) var(--ease),background var(--d-fast) var(--ease)}
.switch input:checked{background:var(--mint);border-color:var(--mint)}
.switch input:checked::before{transform:translateX(22px);background:var(--ink)}
.switch input:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
.switch:has(input:checked){color:var(--paper)}
.formmore{display:none;padding-top:var(--s4)}
.formset:has([data-more]:checked) .formmore{display:block;animation:slot-in .5s var(--ease) both}
.formrole + .formrole{margin-top:var(--s3)}
.formrole__h{font-size:1rem;font-weight:500;color:var(--paper);margin:0 0 .25rem}

/* the section index in the left column, desktop only */
.bkidx ol{list-style:none;margin:0;padding:0;display:grid;gap:.15rem}
.bkidx a{display:inline-flex;align-items:center;gap:.75rem;padding:.4rem 0;font-size:.9375rem;font-weight:500;color:var(--paper-faint);text-decoration:none;transition:color var(--d-fast) var(--ease)}
.bkidx a::before{content:"";width:1.25rem;height:1.5px;background:currentColor;transform-origin:left center;transform:scaleX(.45);transition:transform .45s var(--ease)}
.bkidx a:hover{color:var(--paper)}
.bkidx a.is-current{color:var(--mint)}
.bkidx a.is-current::before{transform:none}
.bkidx a.is-done::after{content:"";width:5px;height:9px;margin-left:.1rem;border:solid var(--paper-dim);border-width:0 1.5px 1.5px 0;transform:translateY(-2px) rotate(45deg)}
.bkidx a:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
@media (max-width:899px){.bkidx{display:none}}

/* ------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------ */
/* The footer is mint, and it is the same field as the "Get in touch" block
   above it: one block of brand colour closing every page, divided by a
   hairline inside the wrap rather than a seam across the full bleed.

   Its shape is the reference's: link columns at the top, a long open middle,
   then the agency's line at display size on the left with the mark blown up
   opposite it, and a plain bar of nav and copyright underneath. The empty
   middle is the point. Close it up and the footer becomes a sitemap. */
.ftr.field{padding-block:clamp(3rem,7vw,var(--s7)) clamp(1.25rem,2.4vw,2rem)}
/* One grid, filled column by column, so the second group in each column
   lines up with its neighbours. Nested per-column grids cannot align rows
   across columns, and with an uneven number of values they drifted. */
.ftr__grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  grid-template-rows:auto auto;
  grid-auto-flow:column;
  gap:clamp(1.75rem,3vw,2.5rem) var(--s4);
  align-content:start;
}
/* the CTA is already mint, so the two must not stack their padding or read
   as two bands: drop the footer's own top space and mark the division */
.field + .ftr.field{padding-top:0}
.field + .ftr .ftr__grid{
  border-top:1px solid rgba(11,11,11,.16);
  padding-top:clamp(2.5rem,5vw,4rem);
}
/* dl carries a UA default block margin that nothing else in the reset
   touches (the h1/h2/h3/h4/p/figure/blockquote reset above never listed
   it), so on the single-column mobile layout each group's own margin
   stacked on top of .ftr__grid's row-gap and doubled the visual gap
   between "Contact", "Address", "Follow us" etc. from the intended 28px
   to ~58px, reading as five disconnected, oddly-spaced fragments rather
   than one list. */
.ftr dl{display:grid;gap:0;align-content:start;margin:0}
/* sentence case, same size as the values, one tone down: a footer heading is
   a whisper, not a section label, so it does not take .label's caps */
.ftr dt{color:rgba(11,11,11,.5);margin-bottom:.1rem}
.ftr dd{margin:0}
.ftr dl{font-size:clamp(.9375rem,1.02vw,1.0625rem);line-height:1.62}
/* no rest-state underline: four columns of them turned the block into a mesh */
.ftr a{
  text-decoration:underline;text-decoration-color:transparent;
  text-underline-offset:3px;text-decoration-thickness:1px;
  transition:text-decoration-color var(--d-fast) linear;
}
.ftr a:hover{text-decoration-color:currentColor}

.ftr__sign{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:var(--s4);
  margin-top:clamp(4rem,13vw,13rem);
}
.ftr__say{
  font-size:clamp(2rem,3.4vw,3.25rem);
  font-weight:600;line-height:1.02;letter-spacing:-.04em;
  flex:none;
}
/* the mark is white on transparent; on a mint field it has to be ink.
   Sized to sit beside the line, not over it: at min(38%,560px) it was the
   biggest thing in the footer and read as a banner (agency, 25 Sept 2026). */
.ftr__mark{
  width:clamp(9rem,17vw,15rem);height:auto;flex:none;
  filter:invert(1);
}

.ftr__bottom{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);justify-content:space-between;
  align-items:baseline;
  margin-top:clamp(2rem,4vw,3.25rem);
  font-size:.9375rem;
}
/* ace's order: the legal links in ink, then the copyright alone in grey */
.ftr__legal{display:flex;flex-wrap:wrap;align-items:baseline;gap:.35rem var(--s3);font-weight:500}
.ftr__legal a[aria-current]{text-decoration-color:currentColor}
.ftr__copy{color:rgba(11,11,11,.5)}
.ftr__nav{display:flex;flex-wrap:wrap;gap:.35rem var(--s3);font-weight:500}
.ftr__nav a[aria-current]{text-decoration-color:currentColor}

@media (max-width:900px){
  .ftr__grid{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:none;grid-auto-flow:row}
  .ftr__sign{flex-direction:column;align-items:flex-start;gap:clamp(2rem,7vw,3rem)}
  .ftr__mark{width:clamp(8rem,38vw,12rem)}
}
@media (max-width:540px){
  .ftr__grid{grid-template-columns:minmax(0,1fr);grid-auto-flow:row}
}

/* ------------------------------------------------------------
   ARTIST DETAIL
   ------------------------------------------------------------ */
.artist__hero{min-height:92svh}
/* Contact and booking: ace.nl's split. Note left, hairline, h1 and a
   label | value list right; the form below sits in the same right column. */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);padding-top:clamp(7rem,14vw,11rem)}
.split__note{font-size:.9375rem;font-weight:400;line-height:1.5;color:var(--paper-faint);max-width:30ch;padding-right:var(--s4)}
.split__main{border-left:1px solid var(--line);padding-left:clamp(2rem,4.5vw,4rem);padding-bottom:var(--s3)}
.cgrid{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:clamp(1.5rem,2.5vw,2.25rem);row-gap:1.1rem;margin:clamp(2rem,4vw,3rem) 0 0;align-items:baseline}
.cgrid dt{font-size:.8125rem;color:var(--paper-faint);white-space:nowrap}
.cgrid dd{margin:0;min-width:0;overflow-wrap:anywhere;font-size:clamp(1.0625rem,.95rem + .45vw,1.3125rem);font-weight:500}
.cgrid a{color:var(--paper);text-decoration:none;transition:color .2s}
.cgrid a:hover{color:var(--mint)}
.split--body{padding-top:clamp(4rem,8vw,6.5rem);padding-bottom:clamp(4rem,10vw,8rem)}
.split--body .split__form{padding-left:clamp(2rem,4.5vw,4rem)}
.split__aside{padding-right:var(--s5)}
@media (min-width:900px){.split__aside{position:sticky;top:clamp(7rem,14vh,9rem);align-self:start}}
@media (max-width:899px){
  .split{grid-template-columns:minmax(0,1fr);padding-top:clamp(6.5rem,24vw,8rem)}
  .split__note{margin-bottom:var(--s4)}
  .split__main{padding-left:clamp(1.25rem,6vw,2rem)}
  .split--body{padding-top:var(--s6)}
  .split--body > :empty{display:none}
  .split--body .split__form{padding-left:0}
  .split__aside{order:2;padding-right:0;margin-top:var(--s6)}
}
.artist__body{
  display:grid;gap:var(--s5) clamp(2rem,6vw,6rem);
  grid-template-columns:minmax(0,1fr);
}
@media (min-width:900px){
  .artist__body{grid-template-columns:minmax(0,.9fr) minmax(0,1.4fr)}
  /* On the two form pages the left column is two lines of contact detail
     against a form that runs 700px further down, so it used to sit at the
     top of a dead column. Pinned, it travels with the form instead. */
  .artist__body--pin > :first-child{position:sticky;top:clamp(7rem,14vh,9rem);align-self:start}
}
.links{display:flex;flex-wrap:wrap;gap:.75rem}

/* Players sit there loaded and ready. Two tracks means two players side by
   side, three means three; a single wide strip stretched the artwork and
   looked broken. They are lazy, so the fetch still waits for the scroll. */
.embeds{
  display:grid;gap:clamp(.75rem,1.4vw,1.25rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr));
  max-width:1120px;
}
/* A lone player must not eat the full 1120px. auto-fit gives a single
   child the whole track, which stretched SoundCloud's artwork into a
   letterbox band and read as broken, the same fault the grid was added
   to fix for two and three. 560px is what a player gets in the two-up
   case, so one track looks like half a pair rather than a special one. */
.embeds:has(.embed:only-child){max-width:560px}
.embed{
  border:1px solid var(--line);
  background:var(--ink-2);
  height:clamp(300px,25vw,360px);
  overflow:hidden;
  transition:border-color var(--d-fast) var(--ease);
}
.embed:hover{border-color:var(--mint)}
.embed iframe{display:block;width:100%;height:100%;border:0}

/* The map is a detail in the contact column, not a landscape band. */
.map{
  position:relative;width:100%;max-width:440px;aspect-ratio:4/3;
  border:1px solid var(--line);background:var(--ink-2);overflow:hidden;
}
.map iframe{
  display:block;width:100%;height:100%;border:0;
  filter:grayscale(1) invert(.92) contrast(.92);
}

/* ------------------------------------------------------------
   PAGE TRANSITIONS (cross-document, progressively enhanced)
   ------------------------------------------------------------ */
/* The page transition is the curtain (see CURTAIN below), not a cross-document
   view transition. The two cannot both run: the curtain covers the whole
   viewport for the entire swap, so a root snapshot animation underneath it is
   invisible work, and the evhero morph is invisible with it. navigation:none
   is therefore deliberate, not an oversight. */
@view-transition{navigation:none}

/* The photograph is the transition. A roster tile keeps its own frame and
   grows into the artist hero it links to, and one artist hero hands over to
   the next through the pager, because both carry the same name. JS tags the
   tile on the way out; the destination already carries the name in CSS. */

/* ------------------------------------------------------------
   HEADER AWAY — the burger
   The header scrolls away with the page and .hdr.is-away is set
   the moment it has left the viewport. It is reversible, not
   one-way: scroll back to the top and the header is simply there
   again and the burger undoes itself. That is the reference's
   behaviour (ace.nl toggles .in-vp on its nav by position, never
   by scroll direction), on the agency's instruction (Sept 2026),
   and it replaces the old one-way collapse.
   ------------------------------------------------------------ */
/* Fixed on its own, lined up with the vertical centre of the logo row it
   sits in at the top: pad + (logo height - 33px) / 2, and the logo is
   1024x262, so its height is its width x .2559. */
.hdr__burger{
  position:fixed;z-index:1;
  top:calc(clamp(1rem,2.2vw,1.75rem) + (clamp(120px,11vw,168px) * .2559 - 33px) / 2);
  right:var(--gutter);
  display:block;width:43px;height:33px;flex:none;
  border:0;padding:0;background:none;cursor:pointer;
  border-radius:4px;
  pointer-events:auto;
}
/* The fill is a pseudo-element so it can grow without dragging the bars
   through the same transform. It grows as a dot swelling into the block:
   a circle clip opening from nothing at the centre to past the corners, on
   the reference's own .5s standard curve, and it closes the same way. A
   clip, not a scaled 150% circle inside overflow:hidden, because this
   button carries no overflow:hidden (::after is its enlarged tap area).
   Both layers carry a positive z-index: a negative one escapes to the root
   stacking context and paints under the section background, which is the
   bug the .btn block documents at length.
   Flat, like the reference: no border, no shadow, at any scroll position.
   Both were tried and the agency rejected both as an edge drawn around the
   mint. --field IS --mint, so over the CTA and the footer the block merges
   into the paper and what you see there is the two ink bars. Accepted. */
.hdr__burger::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:var(--mint);border-radius:4px;
  clip-path:circle(0 at 50% 50%);
  transition:clip-path .5s cubic-bezier(.4,0,.2,1),transform var(--d-fast) var(--ease);
}
.hdr.is-away .hdr__burger::before{clip-path:circle(75% at 50% 50%)}
/* 43x33 is the reference's size and it is under the 44px touch minimum.
   The hit area is pushed back out to 49x47 here, without moving the block
   or clipping it. */
.hdr__burger::after{content:"";position:absolute;inset:-7px -3px}
/* White on the page while the header is there, ink on the mint once the
   fill has grown. `scale` and `translate` are separate properties, so the
   draw-in and the hover nudge never fight over one transform. */
.hdr__burger span{
  position:absolute;left:11px;right:11px;height:2px;z-index:1;
  background:var(--paper);
  transform-origin:left center;
  scale:1 1;
  transition:scale .3s cubic-bezier(.17,.17,0,1),translate var(--d-fast) var(--ease),background-color .2s linear;
}
.hdr.is-away .hdr__burger span{background:var(--ink)}
.hdr__burger span:nth-child(1){top:12px}
.hdr__burger span:nth-child(2){top:19px}

/* Desktop, where the words are the menu: at the top of the page the burger
   does not exist, not even as bars. Once the header has gone the dot
   blooms, then the bars draw from the left, the bottom one at 200ms and the
   top one at 300ms. Back at the top it all folds away at once, with no
   delay: undoing must not make you wait. visibility follows the fill out so
   the hidden button is out of the tab order, not just invisible. */
@media (min-width:861px){
  .hdr:not(.is-away) .hdr__burger{
    visibility:hidden;pointer-events:none;
    transition:visibility 0s linear .5s;
  }
  .hdr:not(.is-away) .hdr__burger span{scale:0 1;transition-delay:0s}
  .hdr.is-away .hdr__burger span:nth-child(1){transition-delay:.3s,0s,0s}
  .hdr.is-away .hdr__burger span:nth-child(2){transition-delay:.2s,0s,0s}
}
@media (hover:hover){
  .hdr__burger:hover::before{transform:scale(1.09)}
  .hdr__burger:hover span:nth-child(1){translate:0 -1px}
  .hdr__burger:hover span:nth-child(2){translate:0 1px}
}

/* Menu open: the header goes entirely. The panel carries its own mark and
   its own close button, so leaving a second logo and a burger floating over
   the dimmed half would just be two of everything. */
body.is-menu-open .hdr{opacity:0;visibility:hidden;transition:opacity .3s var(--ease-io),visibility 0s linear .3s}
/* On a phone the panel is the full width and its logo and close button land
   exactly where the header's are, so the panel simply slides over the
   header: fading it out as well made the logo blink off before the paper
   reached it, and blink back in after the paper had gone. */
@media (max-width:900px){
  body.is-menu-open .hdr{opacity:1;visibility:visible;transition:none}
}

/* ------------------------------------------------------------
   ROSTER INDEX — the A-Z name list
   ------------------------------------------------------------ */
.rindex{
  columns:4;column-gap:clamp(1.5rem,3vw,3rem);
  border-top:1px solid var(--line);padding-top:var(--s3);
}
/* On /artists/ the list sits above the photo grid and reads as the same
   object: five columns to match the five tiles under it. */
.rindex--wide{columns:5}
@media (max-width:1199px){.rindex--wide{columns:4}}
.rindex__item{
  display:block;break-inside:avoid;
  padding-block:.34rem;
  font-size:clamp(1rem,1.35vw,1.1875rem);
  font-weight:400;letter-spacing:-.01em;
  color:var(--paper-faint);
  transition:color var(--d-fast) var(--ease);
}
.rindex__item:hover,.rindex__item:focus-visible{color:var(--mint)}
.rindex__item.is-current{color:var(--paper)}
.rindex__item.is-current::before{
  content:"";display:inline-block;width:.5rem;height:1px;
  background:var(--mint);vertical-align:middle;margin-right:.5rem;
}
@media (max-width:900px){.rindex{columns:3}}
@media (max-width:620px){.rindex{columns:2}}

/* ------------------------------------------------------------
   PAGER, one artist back, one forward, alphabetically
   ------------------------------------------------------------ */
.pager{
  display:grid;grid-template-columns:1fr 1fr;gap:var(--s3);
  border-top:1px solid var(--line);
  margin-block:clamp(3rem,7vw,6rem);
  padding-top:clamp(2rem,4vw,3.5rem);
}
.pager__side{display:flex;flex-direction:column;gap:.5rem;min-width:0}
.pager__side--next{text-align:right;align-items:flex-end}

/* The arrow is a drawn rule with a head, not a glyph: a typeface arrow sits
   on the baseline at whatever weight the font feels like, and next to a 12px
   tracked label it reads as punctuation. This one is the same hairline the
   page is already divided by, so it belongs to the layout. It grows outward
   on hover, away from the centre, which is the direction you are going. */
.pager__top{display:flex;align-items:center;gap:.85rem}
.pager__side--next .pager__top{flex-direction:row-reverse}
.pager__arrow{
  position:relative;display:block;flex:none;
  width:clamp(1.75rem,3.5vw,2.75rem);height:1px;
  background:currentColor;color:var(--paper-faint);
  transition:color var(--d-fast) var(--ease),transform var(--d-fast) var(--ease);
}
.pager__arrow::after{
  content:"";position:absolute;top:50%;
  width:.45rem;height:.45rem;
  border-top:1px solid currentColor;border-right:1px solid currentColor;
}
.pager__side--prev .pager__arrow::after{left:0;transform:translateY(-50%) rotate(-135deg)}
.pager__side--next .pager__arrow::after{right:0;transform:translateY(-50%) rotate(45deg)}
.pager__side:hover .pager__arrow,.pager__side:focus-visible .pager__arrow{color:var(--mint)}
/* it slides, it does not grow: widening the rule reflows the label next to it
   and the word jitters sideways on every hover */
.pager__side--prev:hover .pager__arrow,
.pager__side--prev:focus-visible .pager__arrow{transform:translate3d(-.5rem,0,0)}
.pager__side--next:hover .pager__arrow,
.pager__side--next:focus-visible .pager__arrow{transform:translate3d(.5rem,0,0)}
.pager__name{
  font-size:clamp(1.35rem,3vw,2.25rem);
  font-weight:600;letter-spacing:-.03em;line-height:1.05;
  color:var(--paper);
  transition:color var(--d-fast) var(--ease);
  overflow-wrap:anywhere;
}
.pager__side:hover .pager__name,.pager__side:focus-visible .pager__name{color:var(--mint)}
.pager__side .label{transition:color var(--d-fast) var(--ease)}
.pager__side:hover .label{color:var(--mint)}

/* ------------------------------------------------------------
   PROFILE LINKS — Instagram, SoundCloud, Spotify, RA
   ------------------------------------------------------------ */
.plinks{display:flex;flex-direction:column;border-top:1px solid var(--line)}
.plink{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  padding-block:.9rem;
  border-bottom:1px solid var(--line);
  font-size:1rem;font-weight:400;
  color:var(--paper-dim);
  transition:color var(--d-fast) var(--ease),padding-left var(--d-fast) var(--ease);
}
.plink i{
  width:7px;height:7px;flex:none;
  border-right:1.5px solid currentColor;border-top:1.5px solid currentColor;
  transform:rotate(45deg);
  transition:transform var(--d-fast) var(--ease);
}
.plink:hover,.plink:focus-visible{color:var(--mint);padding-left:.5rem}
.plink:hover i{transform:rotate(45deg) translate3d(2px,-2px,0)}

/* ------------------------------------------------------------
   SECTION HEAD + TILES
   ------------------------------------------------------------ */
.sechead{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s4);flex-wrap:wrap}
.section--tight{padding-block:clamp(3rem,7vw,6rem)}
.tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(.75rem,1.4vw,1.25rem)}
.media--tile{aspect-ratio:3/2}
@media (max-width:900px){.tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* ------------------------------------------------------------
   CURSOR — a mint box that grows under the pointer on roster art
   ------------------------------------------------------------ */
.cursor{
  position:fixed;top:0;left:0;z-index:300;
  pointer-events:none;
  display:flex;align-items:center;justify-content:center;
  padding:.5rem 1rem;border-radius:100px;
  background:var(--mint);color:var(--ink);
  font-size:.75rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  opacity:0;transform:translate3d(-50%,-50%,0) scale(.4);
  transition:opacity .28s var(--ease),transform .28s var(--ease);
  will-change:transform;
}
.cursor.is-on{opacity:1;transform:translate3d(-50%,-50%,0) scale(1)}
@media (hover:none),(pointer:coarse){.cursor{display:none}}

/* ------------------------------------------------------------
   HERO VIDEO + MAP
   ------------------------------------------------------------ */
.hero--roster .hero__media{background:var(--ink)}
.hero__poster{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
}
.hero__video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
  transform:scale(1.04);
  opacity:0;transition:opacity .9s var(--ease);
}
.hero__video.is-playing{opacity:1}

/* ------------------------------------------------------------
   MINT SURFACES — the one high-contrast move
   Mint is the accent everywhere else. Twice per page it stops
   being an accent and becomes the whole field, with black type
   on it. That inversion is the loudest thing the site does, so
   it only happens where the page asks for a decision.
   ------------------------------------------------------------ */
.field{
  background:var(--field);
  color:var(--ink);
  padding-block:clamp(3.5rem,9vw,7.5rem);
  position:relative;
}
.field .label{color:rgba(11,11,11,.58)}
.field ::selection{background:var(--ink);color:var(--mint)}
.field :focus-visible{outline-color:var(--ink)}

.statement__line{
  font-size:clamp(1.9rem,5.2vw,4.75rem);
  font-weight:500;line-height:1.02;letter-spacing:-.035em;
  max-width:20ch;
}
/* The rest of the same paragraph, set small and pushed to the opposite side.
   The statement is the thing you take in; this is the thing you read if you
   want more. Two sizes on one field is the hierarchy the old wall of even
   display type did not have. */
.statement__note{
  margin-top:clamp(2.5rem,6vw,5rem);
  margin-left:auto;
  max-width:46ch;
  color:rgba(11,11,11,.66);
  font-size:clamp(1rem,1.25vw,1.125rem);
  line-height:1.55;
}
@media (max-width:760px){.statement__note{margin-left:0;max-width:none}}
/* the footer is the same mint field, so the CTA gives up most of its bottom
   space: stacked, the two paddings left ~180px of dead colour */
.cta{padding-bottom:clamp(2.5rem,5vw,4rem)}
.cta__row{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:var(--s3) var(--s4);
  margin-top:clamp(2rem,4.5vw,3.5rem);
  padding-top:var(--s2);
  border-top:1px solid rgba(11,11,11,.22);
}
.cta__say{max-width:32ch;color:rgba(11,11,11,.7)}

.btn--ink{background:transparent;color:var(--mint);border-color:var(--ink)}
.btn--ink::after{content:"";position:absolute;inset:0;z-index:-2;background:var(--ink)}
/* The hover fill is mint, not white. On the ink pages the hollow .btn
   already fills mint on hover, and mint marking what is interactive is
   the rule the whole site runs on. This variant only ever sits on a
   .field, where a white fill is a 4% step away from the paper behind it
   and reads as the button emptying out rather than lighting up. */
.btn--ink::before{background:var(--mint)}
.btn--ink:hover,.btn--ink:focus-visible{color:var(--ink);border-color:var(--ink)}

/* ------------------------------------------------------------
   LOADER — first arrival only
   A black field, the mark, and one mint line filling. It is
   capped at a second: a preloader that outstays the page it is
   hiding is just a slow site with a logo on it.
   ------------------------------------------------------------ */
.load{
  position:fixed;inset:0;z-index:400;
  background:var(--ink);
  display:grid;place-items:center;
  clip-path:inset(0 0 0 0);
  transition:clip-path .85s var(--ease);
}
.load.is-done{clip-path:inset(0 0 100% 0)}
.load__inner{display:grid;gap:1.1rem;justify-items:center;width:min(240px,54vw)}
.load__logo{width:100%;height:auto}
.load__bar{width:100%;height:2px;background:var(--line);overflow:hidden}
.load__bar i{
  display:block;height:100%;width:100%;background:var(--mint);
  transform:scaleX(0);transform-origin:left;
  transition:transform .35s linear;
}
html.is-loading{overflow:hidden}
.no-js .load{display:none}
.no-js .curtain{display:none}

/* ------------------------------------------------------------
   CURTAIN — the page transition

   A paper panel that wipes up over the page you are leaving, holds
   while the next document loads, and wipes up off the top to reveal
   it. Both phases travel the same direction, so it reads as one
   continuous sweep with the page swapped underneath.

   It is paper on an ink site for the same reason the menu and the
   consent bar are: it has to be a different surface from the page or
   there is nothing to see. Transient, so the two-fields-per-page rule
   does not apply.

   The element is display:none until one of two classes is set, which
   is what makes this safe on a static site. .is-arriving is set by a
   blocking script in <head>, before first paint, and only when the
   previous page flagged the click, so a direct arrival, a crawler, a
   browser with JS off and a page restored from bfcache all get no
   curtain rather than a stuck one. The lift is a CSS animation with
   fill:both, so once it is up it stays up even if the JS never runs.
   ------------------------------------------------------------ */
.curtain{
  position:fixed;inset:0;z-index:300;
  display:none;
  background:var(--field);
  pointer-events:none;
  will-change:clip-path;
}
html.is-arriving .curtain,html.is-leaving .curtain{display:block}
.curtain__inner{padding-top:clamp(1.4rem,2.6vw,2rem)}
/* the mark is white on transparent; on paper it has to be ink */
.curtain__mark{width:clamp(108px,11vw,150px);height:auto;filter:invert(1)}

/* leaving: the panel grows up from the bottom edge and holds */
html.is-leaving .curtain{animation:curtain-drop .48s var(--ease-curtain) both}
@keyframes curtain-drop{from{clip-path:inset(100% 0 0 0)}to{clip-path:inset(0 0 0 0)}}

/* arriving: it keeps going, off the top, uncovering the new page */
html.is-arriving .curtain{animation:curtain-lift .76s var(--ease-curtain) both}
@keyframes curtain-lift{from{clip-path:inset(0 0 0 0)}to{clip-path:inset(0 0 100% 0)}}

/* ------------------------------------------------------------
   BOOKING CHOOSER — which inbox this enquiry should land in
   ------------------------------------------------------------ */
.pick{position:fixed;inset:0;z-index:350;display:grid;place-items:center;padding:var(--gutter)}
.pick__scrim{
  position:absolute;inset:0;background:rgba(6,6,6,.72);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  opacity:0;transition:opacity var(--d-fast) linear;
}
.pick.is-open .pick__scrim{opacity:1}
.pick__panel{
  position:relative;width:min(560px,100%);
  background:var(--ink-2);border:1px solid var(--mint);
  padding:clamp(1.5rem,3.5vw,2.5rem);
  max-height:88vh;overflow-y:auto;
  opacity:0;transform:translate3d(0,18px,0) scale(.98);
  transition:opacity var(--d-fast) var(--ease),transform var(--d-mid) var(--ease);
}
.pick.is-open .pick__panel{opacity:1;transform:none}
.pick__rows{margin-top:clamp(1.5rem,3vw,2rem);border-top:1px solid var(--line)}
.pick__row{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  padding:1rem 0;border-bottom:1px solid var(--line);
  transition:color var(--d-fast) var(--ease),padding-left var(--d-fast) var(--ease);
}
.pick__row:hover,.pick__row:focus-visible{color:var(--mint);padding-left:.5rem}
.pick__name{display:block;font-weight:500}
.pick__mail{display:block;font-size:.875rem;color:var(--paper-faint);margin-top:.15rem}
.pick__row i{
  width:7px;height:7px;flex:none;
  border-right:1.5px solid currentColor;border-top:1.5px solid currentColor;
  transform:rotate(45deg);
}
.pick__close{
  margin-top:clamp(1.25rem,2.5vw,1.75rem);
  font-size:var(--t-label);font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  color:var(--paper-faint);padding-block:.5rem;
}
.pick__close:hover{color:var(--mint)}

/* ------------------------------------------------------------
   COOKIE CONSENT — a centred dialog, modelled on ace.nl's
   The agency asked for ace's cookie dialog by name (Sept 2026) and
   called the old bottom bar cheap. Same shape as theirs: a dark card
   in the middle of the screen, no backdrop and no scroll lock (the
   page stays usable behind it), Consent / Details / About tabs with
   the current one underlined in mint, and a row of toggles.
   Not copied: Cookiebot's pre-ticked boxes and single OK. Marketing
   starts off, and Decline, Allow selection and Allow all are the same
   .btn at the same size, one click each. A refusal that is harder to
   reach than the accept is not consent, and it is the first thing a
   regulator looks at. It is a dark card, not a paper field: over an
   ink page it is lifted by a hairline and a long soft shadow.
   ------------------------------------------------------------ */
.consent{
  /* Above the header (100), below the menu (200). The menu is a full
     takeover and must cover this. */
  position:fixed;z-index:150;
  inset:0;margin:auto;
  width:min(900px,calc(100% - 16px));
  height:fit-content;max-height:calc(100svh - 16px);
  display:flex;flex-direction:column;
  background:var(--ink-2);color:var(--paper);
  border:1px solid var(--line);border-radius:8px;
  box-shadow:0 32px 68px rgba(0,0,0,.45);
  opacity:0;transform:translate3d(0,14px,0);
  transition:opacity .33s var(--ease-io),transform .33s var(--ease-io);
}
.consent[hidden]{display:none}
.consent.is-in{
  opacity:1;transform:translate3d(0,0,0);
  transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .7s var(--ease);
}
.consent__tabs{display:flex;flex:none;border-bottom:1px solid var(--line)}
.consent__tabs button{
  flex:1 1 0;height:60px;position:relative;
  font-size:.9375rem;font-weight:500;color:var(--paper-faint);
  transition:color var(--d-fast) var(--ease);
}
.consent__tabs button::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;
  background:var(--mint);transform:scaleX(0);
  transition:transform var(--d-fast) var(--ease);
}
.consent__tabs button[aria-selected="true"]{color:var(--mint)}
.consent__tabs button[aria-selected="true"]::after{transform:scaleX(1)}
@media (hover:hover){.consent__tabs button:hover{color:var(--paper)}
  .consent__tabs button[aria-selected="true"]:hover{color:var(--mint)}}

.consent__body{
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:clamp(1.25rem,2.6vw,2rem) clamp(1.25rem,3vw,2.25rem);
}
/* one height for all three tabs, so switching tabs does not jump the
   centred card up and down; a long Details pane scrolls inside it */
.consent__body{height:13.5rem}
.consent__pane{min-height:0}
.consent__title{font-size:1.1875rem;font-weight:600;letter-spacing:-.01em;line-height:1.3}
.consent__pane p{font-size:.9375rem;line-height:1.6;color:var(--paper-dim);max-width:70ch}
.consent__title + p{margin-top:.6rem}
.consent__pane p + p{margin-top:.75rem}
.consent__cat{border-bottom:1px solid var(--line)}
.consent__cat:first-child{border-top:1px solid var(--line)}
.consent__cat summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:center;gap:.6rem;
  padding-block:.9rem;font-weight:500;
}
.consent__cat summary::-webkit-details-marker{display:none}
.consent__cat summary::after{
  content:"";width:7px;height:7px;margin-left:auto;margin-right:4px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg);transition:transform var(--d-fast) var(--ease);
}
.consent__cat[open] summary::after{transform:rotate(-135deg)}
.consent__cat summary span{
  font-size:.75rem;font-weight:600;min-width:1.5rem;height:1.25rem;padding:0 .4rem;
  display:inline-grid;place-items:center;border-radius:100px;
  background:var(--ink-3);color:var(--paper-dim);
}
.consent__cat > p{font-size:.875rem;color:var(--paper-faint);margin-bottom:.6rem}
.consent__cat dl{
  display:grid;grid-template-columns:auto 1fr;gap:.4rem 1.25rem;
  margin:0 0 1rem;font-size:.875rem;line-height:1.5;
}
.consent__cat dt{font-weight:500;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8125rem}
.consent__cat dd{margin:0;color:var(--paper-dim)}

.consent__foot{
  flex:none;display:flex;align-items:stretch;
  border-top:1px solid var(--line);
}
.consent__toggles{display:flex;flex:1 1 auto}
.consent__toggle{
  flex:1 1 0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.6rem;
  padding:1rem;font-size:.875rem;font-weight:500;cursor:pointer;
  border-right:1px solid var(--line);
}
/* the switch: a native checkbox, restyled, so it keeps its keyboard and
   screen reader behaviour for free */
.consent__toggle input{
  appearance:none;-webkit-appearance:none;margin:0;flex:none;cursor:pointer;
  width:50px;height:28px;border-radius:100px;position:relative;
  background:var(--ink-3);border:1.5px solid var(--line-strong);
  transition:background var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease);
}
.consent__toggle input::before{
  content:"";position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;
  background:var(--paper);
  transition:transform var(--d-fast) var(--ease),background var(--d-fast) var(--ease);
}
.consent__toggle input:checked{background:var(--mint);border-color:var(--mint)}
.consent__toggle input:checked::before{transform:translateX(22px);background:var(--ink)}
.consent__toggle input:disabled{cursor:not-allowed;opacity:.55}
.consent__toggle:has(input:disabled){cursor:default}
.consent__actions{
  flex:none;display:flex;align-items:center;gap:.5rem;
  padding:1rem clamp(1rem,2vw,1.5rem);
}
.consent__actions .btn{padding:.75rem 1.25rem;min-height:44px;font-size:.875rem;justify-content:center}
.consent :focus-visible{outline:2px solid var(--mint);outline-offset:2px}

@media (max-width:760px){
  /* phone: pinned under the burger rather than centred, as ace does it */
  .consent{inset:72px 8px auto 8px;margin:0;width:auto;max-height:calc(100svh - 80px)}
  .consent__foot{flex-direction:column}
  .consent__toggles{flex-direction:column;border-bottom:1px solid var(--line)}
  .consent__toggle{flex-direction:row;justify-content:space-between;border-right:0;padding:.7rem 1.25rem}
  .consent__toggle + .consent__toggle{border-top:1px solid var(--line)}
  .consent__actions{flex-direction:column;align-items:stretch;padding:1rem 1.25rem}
  .consent__tabs button{height:52px}
  .consent__body{height:auto}
}

/* the footer's own reopen link: a button, dressed as the links next to it */
.no-js [data-consent-open]{display:none}

/* ------------------------------------------------------------
   REDUCED MOTION — everything above degrades to a plain page
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-delay:0s!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
  .reveal > *{transform:none!important}
  /* the block above kills durations but not delays, and the menu holds its
     visibility on a delay so the exit can be watched; with no exit to watch
     that is just an invisible overlay lingering for half a second */
  .menu{transition-delay:0s!important}
  .menu__foot{opacity:1!important;transform:none!important;transition-delay:0s!important}
  .rise{opacity:1!important;transform:none!important}
  .media img,.media video,.panel__media img,.card__media img{transform:none!important}
  .draw{transform:scaleX(1)!important}
  .hero__video{display:none}
  .load{display:none!important}
  .cursor{display:none!important}
  .consent.is-in{transform:none!important;opacity:1!important}
  body::after{display:none}
  @view-transition{navigation:none}
  .curtain{display:none !important;animation:none !important}
}

/* no-JS: never leave content hidden behind a reveal */
.no-js .reveal > *{transform:none}
.no-js .rise{opacity:1;transform:none}
.no-js .media img,.no-js .media video{transform:none}
.no-js .cursor{display:none}
.no-js .consent{display:none}

/* ------------------------------------------------ brand platform (Sept 2026)
   Intro line under a page h1 (/artists/, /booking/, /contact/). */
.intro{margin-top:2rem;max-width:44ch}
/* /about-us/: why, how, who, one labelled row each, then the closing line. */
.about__row + .about__row{margin-top:clamp(4.5rem,9vw,8rem)}
.about__h{font-size:clamp(1.75rem,1rem + 3vw,4rem);font-weight:500;line-height:1.05;letter-spacing:-.02em;color:var(--paper);max-width:22ch;margin-bottom:clamp(1.25rem,2.5vw,2rem)}
.about__h .reveal{padding-bottom:.16em;margin-bottom:-.16em}
.split--about{padding-bottom:clamp(3rem,6vw,5rem)}
.split--about .split__main{padding-top:0;padding-bottom:clamp(3rem,8vw,7rem)}
/* /about-us/ and /jobs/ open on their photograph, with the heading set over
   it (25 Sept 2026: a full-bleed frame between the heading and the copy "sat
   in the way"). Same shape as an artist hero, shorter, so the copy under it
   still shows at the bottom of the first screen on most laptops. */
.hero--page{min-height:clamp(520px,78svh,880px)}
.hero--page .split{padding-top:0;padding-bottom:0}
.hero--page .split__main{padding-bottom:0}
/* ends on solid ink, so the photograph dissolves into the page below
   instead of stopping on a visible edge */
.hero--page .hero__media::after{background:linear-gradient(180deg,rgba(11,11,11,.66) 0%,rgba(11,11,11,.34) 22%,rgba(11,11,11,.54) 50%,rgba(11,11,11,.86) 80%,var(--ink) 100%)}
.about__closer{margin-top:clamp(3.5rem,8vw,6rem);max-width:22ch}
