/* Worldclass Management — shared stylesheet
   Organised block by block; each section maps to one Gutenberg block. */

  :root{
    --ink:var(--wp--preset--color--ink,#0a0a0c);
    --ink-2:var(--wp--preset--color--ink-2,#141419);
    --paper:var(--wp--preset--color--paper,#ffffff);
    /* Neutral grey — equal channels, no hue. Was #f0f0f4, which carried a
       slight blue-violet cast from the old palette. Same lightness. */
    --paper-2:var(--wp--preset--color--paper-2,#f0f0f0);
    --line:var(--wp--preset--color--line,#dcdce4);
    /* Brand accents. --accent-light carries kickers, hover states and links on
       dark; --accent-deep carries buttons, links on light and focus rings. The
       pair matches the PDF brochure. (These were --teal and --violet until the
       WordPress port; the names had stopped describing the colours, which are
       purple and blue. The .bak files below still use the old names.)
       The -rgb twins carry the same colour as bare channels so the translucent
       washes below can be written rgba(var(--accent-light-rgb),.12) — that way a
       palette swap is these five lines and nothing else.

       The literals here are also the fallback half of the theme.json wiring: WP
       emits the same values as --wp--preset--color--accent-light and friends, and
       the block theme reads those. Outside WordPress there was
       no preset, so these values are what actually paint. Keep the two in sync.

       LEGACY SET — restore by pasting over the five lines below:
         --accent-light:#2fb89a;
         --accent-light-rgb:47,184,154;
         --accent-deep:#5a4bc4;
         --accent-deep-rgb:90,75,196;
         --grad:linear-gradient(100deg,#2fb89a 0%,#3f7fbf 45%,#6a4fd0 100%);
       (Full pre-swap copies also sit in assets/css/site.css.brand-teal-violet.bak
        and artist-services.html.brand-teal-violet.bak, from when that page
        carried the ramp again as an inline SVG gradient. The .srow__icon paint
        server still needs one, but site.js now reads its stops back out of
        --grad, so a swap here reaches it too.) */
    --accent-light:var(--wp--preset--color--accent-light,#bf70df);
    --accent-light-rgb:191,112,223;
    --accent-deep:var(--wp--preset--color--accent-deep,#1c49a7);
    --accent-deep-rgb:28,73,167;
    --grad:var(--wp--preset--gradient--brand,linear-gradient(100deg,#bf70df 0%,#6d5cc3 45%,#1c49a7 100%));
    --text-dark:var(--wp--preset--color--text-dark,#0f0f14);
    --text-mute:var(--wp--preset--color--text-mute,#55555f);
    /* Height of the bar in its top-of-page state: 18px padding, the 170px
       logo, 18px again. Page headers start UNDER the fixed bar, so they pad
       past this or the eyebrow line runs into the logo — which is exactly
       what happened when the logo grew and the padding stayed put. Anything
       clearing the bar should measure from here, not from a copied number. */
    --nav-h-top:206px;
    /* And the bar's height on a narrow screen once scrolled — now set by the
       44px menu button rather than the wordmark, which is shallower. Anything
       that parks itself directly beneath the bar measures from here. */
    --nav-h-mobile:56px;
    /* Height of the WordPress admin bar, which overlaps anything position:fixed
       at the top of the viewport. Zero here and outside WordPress, so serving
       the static build was unaffected; the theme raises it on body.admin-bar at the
       bottom of this file. Everything pinned to the top measures from it. */
    --admin-bar-h:0px;
    /* Inner bevel, taken off the logo artwork: a light rim catching the top
       edge and a dark one under the bottom, as if lit from above. One pair of
       inset shadows, shared by every FILLED button so the four of them cannot
       drift apart. Outlined buttons (.btn-ghost, .btn-line) deliberately skip
       it — there is no body to catch the light, and on white the highlight is
       invisible anyway. Keep both stops subtle: past about .3 on the top rim
       it stops reading as a machined edge and starts reading as a gel button.
       --bevel-ink is the same idea for near-black buttons, where the lower
       shadow has nothing left to darken. */
    --bevel:inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 0 rgba(0,0,0,.28);
    --bevel-ink:inset 0 1px 0 rgba(255,255,255,.10);
  }
  /* --accent-deep is deliberately dark — it carries links and buttons on the white
     bands, where it reads at 8:1. But it also terminates --grad, and a gradient
     headline on the near-black sections fades out over its last third: #1c49a7
     on --ink is 2.4:1, under the 3:1 large-text floor. So the dark bands run a
     ramp whose end stop is lifted to #2f63cf (3.6:1) — same hue, enough light
     to stay legible. Redefining the property rather than the rule means every
     descendant that paints with var(--grad) — headline fills, the 3px bars,
     .btn-primary — picks the lifted ramp up automatically.
     The brand colours themselves are untouched: this is the wash only. */
  .hero,.elite,.events,.page-head,.artists,.ahero,.abook,
  .srow--dark,.media--dark,footer,.nav{
    --grad:linear-gradient(100deg,#bf70df 0%,#7769d7 45%,#2f63cf 100%)}
  *{margin:0;padding:0;box-sizing:border-box}
  html{scroll-behavior:smooth}
  body{font-family:'Inter',sans-serif;color:var(--text-dark);background:var(--paper);-webkit-font-smoothing:antialiased;overflow-x:hidden}
  /* Cormorant defaults to old-style figures, where the 1 has no base serif and
     reads as an I (and digits sit at mixed heights). Lining figures give even,
     cap-height numerals — the right set for display use. */
  .serif{font-family:'Cormorant Garamond',serif;
    font-variant-numeric:lining-nums;font-feature-settings:"lnum" 1}
  /* background-clip:text paints the gradient only within the element's own box.
     Where line-height is under 1, that box ends up shorter than the glyphs and
     the tops of caps and the tails of descenders get no fill at all — they just
     vanish. Pad the box out to cover them, then pull it back with matching
     negative margins so nothing actually moves. */
  .grad-text{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
    padding-top:.16em;padding-bottom:.2em;margin-top:-.16em;margin-bottom:-.2em}

  /* ==========================================================
     BLOCK: wcl/nav
     Mirrors core/navigation: .nav__item--has-children ↔ .has-child,
     .nav__submenu ↔ .wp-block-navigation__submenu-container
     ========================================================== */
  /* Fixed rather than absolute so it rides along on scroll.
     The states are INVERTED on purpose: the bar carries its background by
     default, and JS removes it via .is-top while the page is at the top.
     That way, if the script never runs, you get a solid legible bar rather
     than white nav text invisible on a light section.

     The scrolled ground is FLAT ink, not the 88% it used to be. Once the page
     moves, the bar travels over the light sections, and a translucent ground
     let them bleed up through it — enough to wash out light-on-transparent
     logo artwork exactly where it needed to hold. Opaque also makes the
     backdrop blur pointless, so that is gone with it. At the top of the page
     the bar still disappears: the hero behind it is dark and full-bleed, and
     the transparency is the point of that treatment. */
  .nav{position:fixed;top:var(--admin-bar-h);left:0;right:0;z-index:30;display:flex;align-items:center;
    justify-content:space-between;padding:9px 48px;
    background:var(--ink);
    box-shadow:0 1px 0 rgba(255,255,255,.09),0 12px 30px rgba(0,0,0,.35);
    transition:padding .25s ease,background-color .25s ease,box-shadow .25s ease}
  .nav.is-top{padding:18px 48px;background:transparent;box-shadow:none}
  /* TWO lockups, one visible per state. At the top of the page the bar is
     tall and transparent over the hero, so the full badge has room; once it
     goes sticky the bar is 100px of ink across the whole screen, and a badge
     that deep either forces the bar taller or shrinks the wordmark under it
     to nothing. The wide cut is the same artwork set as one line — it fills
     a shallow bar instead of fighting it.
     Swapped by display, not opacity: both would otherwise occupy the flex
     row and the brand would keep the width of the wider one. */
  .nav__logo{width:100px;transition:width .25s ease}
  .nav.is-top .nav__logo{width:170px}
  /* .nav-scoped so it outranks the display:block in the brand-lockup block
     further down the file — same source-order trap the logo width hit. */
  .nav .nav__logo--word{display:none}
  .nav:not(.is-top) .nav__logo--mark{display:none}
  .nav:not(.is-top) .nav__logo--word{display:block;width:230px}
  /* Anchor targets must clear the bar in its scrolled state, which is what
     you're in whenever an in-page anchor fires. That bar is 70px tall now the
     scrolled state carries the wordmark (9px padding + a 52px lockup), so
     this leaves a deliberate ~20px gap. It tracks the SCROLLED lockup — grow
     that and this grows with it. */
  section[id],header[id]{scroll-margin-top:90px}
  @media(prefers-reduced-motion:reduce){
    .nav,.nav__logo{transition:none}
  }
  .nav .brand{font-family:'Cormorant Garamond',serif;font-size:22px;letter-spacing:3px;color:#fff;font-weight:600}
  .nav .brand small{display:block;font-family:'Inter';font-size:9px;letter-spacing:6px;font-weight:300;color:#b9b7c8;margin-top:-2px}
  /* margin-left:auto, not space-between's doing. Once the call button joins the
     row there are three items for space-between to spread, and it parked the
     menu in the middle of the bar with a wide gap before the phone. The auto
     margin takes all the free space on the menu's left instead, so the menu and
     the call button travel together as one right-hand group. */
  .nav__menu{display:flex;gap:24px;list-style:none;margin-left:auto}
  /* Labels never break. Without this the row runs out of width somewhere
     around 950px and "Book an artist" folds into three stacked words rather
     than the menu simply getting tighter. */
  .nav__item{white-space:nowrap}
  /* Phone number, carried IN the nav row rather than a utility strip above it.
     The bar is fixed and already swaps between two heights; a second strip
     would either double the chrome at the top of every page or slide away on
     scroll, which is precisely when someone has read enough to want to call.
     Ruled off on its left so it reads as a detail about the company and not
     another page in the list, and full strength rather than the .85 the menu
     links carry — the whole point is that it can be found at a glance. */
  .nav__item--tel{padding-left:22px;border-left:1px solid rgba(255,255,255,.18)}
  /* The number and the booking link are a pair at the right-hand end: the two
     things someone arrives wanting to do. Same white, same weight, so they
     read as one group rather than a nav item that happens to sit last. The
     number keeps its tighter tracking — digits, not a label. */
  .nav .nav__item--tel a,
  .nav .nav__item--book .nav__link{color:#fff;opacity:1;font-weight:500}
  .nav .nav__item--tel a{letter-spacing:1.4px}
  .nav a{color:#e8e7ef;text-decoration:none;font-size:12px;letter-spacing:2px;text-transform:uppercase;font-weight:400;opacity:.85;transition:opacity .2s}
  /* The brand is a link, so the rule above was dimming the logo to 85% and
     lifting it to full only on hover. Menu items earn that treatment; the
     identity does not — it stays at full strength in every state. */
  .nav a.nav__brand,.nav a.nav__brand:hover{opacity:1}
  .nav a:hover{opacity:1}
  .nav__item{position:relative}

  /* Parent with a submenu */
  .nav__item--has-children > .nav__link{display:inline-flex;align-items:center;gap:7px;padding-bottom:14px;margin-bottom:-14px}
  .nav__caret{width:8px;height:8px;flex:0 0 auto;stroke:currentColor;stroke-width:2.4;fill:none;transition:transform .25s ease,opacity .2s;opacity:.65}
  /* The caret states what the panel IS doing, so only .is-open turns it over.
     :hover used to be in this selector too, which flipped the arrow to "open"
     on any pointer over the item — and on a touch screen a tap leaves a hover
     state behind, so the arrow sat upside down over a list that was still
     collapsed. Hover only brightens it. On a real desktop hover the JS adds
     .is-open as the panel appears, so the arrow still turns exactly when the
     panel does. */
  .nav__item--has-children:hover .nav__caret{opacity:1}
  .nav__item--has-children.is-open .nav__caret{transform:rotate(180deg);opacity:1}

  /* Submenu panel */
  .nav__submenu{position:absolute;top:100%;left:-18px;min-width:218px;list-style:none;display:block;
    padding:8px;margin-top:12px;border-radius:4px;
    background:rgba(14,14,18,.86);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
    border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 50px rgba(0,0,0,.5);
    opacity:0;visibility:hidden;transform:translateY(-8px);
    transition:opacity .22s ease,transform .22s ease,visibility .22s}
  /* Gradient hairline picks up the brand ramp used on buttons and hover bars */
  .nav__submenu::before{content:'';position:absolute;left:0;right:0;top:0;height:2px;background:var(--grad);border-radius:4px 4px 0 0}
  /* focus-within is scoped to the panel, not the whole item — otherwise Escape
     can't close it, since returning focus to the trigger would reopen it */
  .nav__item--has-children:hover .nav__submenu,
  .nav__item--has-children.is-open .nav__submenu,
  .nav__submenu:focus-within{opacity:1;visibility:visible;transform:translateY(0)}
  /* Bridges the gap between trigger and panel so the pointer can travel down */
  .nav__submenu::after{content:'';position:absolute;left:0;right:0;top:-12px;height:12px}

  .nav__submenu a{display:block;position:relative;padding:12px 16px 12px 18px;border-radius:2px;opacity:1;
    white-space:nowrap;
    font-family:'Cormorant Garamond',serif;font-size:19px;letter-spacing:1px;text-transform:none;
    color:#fff;line-height:1.15;font-weight:600;transition:background .2s,color .2s}
  .nav__submenu a:hover,.nav__submenu a:focus-visible{background:rgba(255,255,255,.05)}
  /* Same left-bar motif as the roster cards */
  .nav__submenu a::before{content:'';position:absolute;left:0;top:12px;bottom:12px;width:2px;background:var(--grad);border-radius:2px;transform:scaleY(0);transform-origin:center;transition:transform .25s ease}
  .nav__submenu a:hover::before,.nav__submenu a:focus-visible::before{transform:scaleY(1)}
  .nav__toggle{display:none}
  /* Off above 1120px, where the number itself is in the row */
  .nav__call{display:none}
  @media(prefers-reduced-motion:reduce){
    .nav__submenu,.nav__caret,.nav__submenu a::before{transition:none}
  }

  /* ==========================================================
     BLOCK: wcl/hero
     Block attributes → eyebrow, heading, sub, ctaPrimary,
       ctaSecondary, mediaType (video|vimeo), mediaSrc, posterSrc
     Self-contained: no styles leak in or out of .hero
     ========================================================== */
  .hero{position:relative;min-height:100vh;background:var(--ink);display:flex;align-items:center;overflow:hidden}

  /* Media layer — swap <video> for a Vimeo <iframe> without touching anything else */
  .hero__media{position:absolute;inset:0;overflow:hidden;z-index:0}
  /* The still behind the hero film. It paints before the video has decoded
     and stays put if autoplay is refused, so it is the hero for anyone on
     low power mode or a data saver. No image here on purpose: it comes from
     the media library as an inline background-image on the element, which
     is why the shorthand still sets the framing but not a source. This used
     to be a 100KB base64 JPEG baked into this file, which was half the
     stylesheet's weight and unchangeable without editing CSS. */
  .hero__poster{position:absolute;inset:0;background:center 30%/cover no-repeat;opacity:.55}
  /* Fades up only once the video is actually playing, so there's no black flash */
  .hero__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 30%;opacity:0;transition:opacity .9s ease}
  .hero__video.is-playing{opacity:.55}
  /* Once the footage is running the still underneath must go, or you see both */
  .hero__media.is-playing .hero__poster{opacity:0;transition:opacity .9s ease}
  /* Vimeo swap-in: an iframe can't object-fit, so scale a 16:9 frame up to cover */
  /* A hosted film used as wallpaper. Sized to cover rather than fit, and
     then scaled up: YouTube paints its video title and channel name over
     the top of the frame and there is no parameter left to stop it, since
     modestbranding stopped doing anything. Overscaling pushes that chrome
     outside the visible area. Vimeo's background mode has no chrome to
     hide, so for Vimeo this only crops a little tighter.
     pointer-events:none keeps the whole thing unclickable either way. */
  .hero__media iframe{position:absolute;top:50%;left:50%;width:100vw;height:56.25vw;min-height:100vh;min-width:177.78vh;transform:translate(-50%,-50%) scale(1.35);border:0;pointer-events:none;
    transition:opacity .9s ease}
  /* Held back until the film is really playing (see the YouTube module in
     site.js), so the poster shows instead of the player loading and whatever
     YouTube paints over the start. Only JavaScript adds .is-waiting, so with
     no script the frame shows exactly as before. */
  .hero__media.is-waiting iframe{opacity:0}

  .hero__tint{position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,rgba(10,10,12,.94) 0%,rgba(10,10,12,.78) 42%,rgba(10,10,12,.42) 100%)}
  .hero__fade{position:absolute;inset:0;z-index:1;background:linear-gradient(to bottom,rgba(10,10,12,.5) 0%,transparent 25%,transparent 70%,rgba(10,10,12,.95) 100%)}
  /* Top padding reserves the header bar's height. Without it the eyebrow
     slides under the logo on shorter windows (~700px and below). */
  .hero__inner{position:relative;z-index:5;padding:150px 48px 40px;max-width:1180px;margin:0 auto;width:100%}
  .hero__logo{width:150px;height:auto;margin-bottom:30px;display:block}
  .hero__eyebrow{font-size:12px;letter-spacing:5px;text-transform:uppercase;color:#fff;font-weight:500;margin-bottom:26px}
  /* Sized so the headline sets on two lines at desktop widths — the 15ch
     measure was breaking it into four. */
  .hero h1{font-family:'Cormorant Garamond',serif;font-weight:600;font-size:clamp(40px,5.4vw,74px);
    line-height:1.02;color:#fff;letter-spacing:-1px;max-width:22ch}
  .hero h1 em{font-style:normal}
  .hero__sub{margin-top:28px;max-width:46ch;color:#fff;font-size:17px;line-height:1.7;font-weight:300}
  .cta-row{margin-top:40px;display:flex;gap:16px;flex-wrap:wrap}
  .btn{display:inline-block;padding:15px 30px;font-size:12px;letter-spacing:2px;text-transform:uppercase;text-decoration:none;font-weight:500;border-radius:2px;transition:transform .2s,box-shadow .2s}
  .btn-primary{background:var(--grad);color:#fff;box-shadow:var(--bevel)}
  .btn-primary:hover{transform:translateY(-2px);box-shadow:var(--bevel),0 10px 30px rgba(var(--accent-deep-rgb),.35)}
  .btn-ghost{border:1px solid rgba(255,255,255,.25);color:#fff}
  .btn-ghost:hover{border-color:#fff}
  .hero__scroll{position:absolute;bottom:30px;left:50%;transform:translateX(-50%);z-index:5;color:#6a6a78;font-size:11px;letter-spacing:3px;text-transform:uppercase}
  /* Motion-sensitive visitors get the still frame only */
  @media(prefers-reduced-motion:reduce){
    .hero__video,.hero__media iframe{display:none}
  }
  /* The desktop tint runs left→right, so on a narrow screen the darkest 42%
     swallows the whole column. Re-aim it top→bottom and let the footage through. */
  @media(max-width:860px){
    .hero__tint{background:linear-gradient(180deg,rgba(10,10,12,.58) 0%,rgba(10,10,12,.20) 38%,rgba(10,10,12,.26) 64%,rgba(10,10,12,.86) 100%)}
    .hero__fade{background:linear-gradient(to bottom,rgba(10,10,12,.32) 0%,transparent 28%,transparent 66%,rgba(10,10,12,.92) 100%)}
    .hero__inner{padding:120px 24px 40px}
    .hero__video.is-playing,.hero__poster{opacity:.72}
    /* No scrim panel behind the copy. A radial gradient inside a box still has
       the box's four edges, and against moving footage those edges read as a
       rectangle sitting on the video rather than as light. The text carries its
       own contrast instead — the shadows below travel with the glyphs, so there
       is no shape to notice. */
    .hero h1{text-shadow:0 2px 24px rgba(10,10,12,.55)}
    .hero__sub{text-shadow:0 1px 12px rgba(10,10,12,.6)}
  }

  /* SECTION SHELL */
  .side-label{position:absolute;left:18px;top:50%;transform:translateY(-50%) rotate(180deg);writing-mode:vertical-rl;font-family:'Cormorant Garamond',serif;font-size:74px;line-height:1;font-weight:600;letter-spacing:2px}
  section{position:relative}

  /* INTRO (light) */
  .intro{background:var(--paper)}
  /* Image bleeds to the left edge; copy sits to its right */
  /* Half and half, and that is load-bearing rather than a round number.
     Stack a reversed intro against a normal one and the two photographs
     sit on opposite sides; their inner edges only meet at the join if
     each column is exactly 50%, because mirroring puts the second edge
     at 100% minus the first. At the original 46% the two corners landed
     101px apart at 1265px wide and the seam read as a mistake. */
  .intro__top{display:grid;grid-template-columns:minmax(0,50%) 1fr;align-items:stretch}
  /* Square corners. Both classes are on the same element, and naming both
     is what makes this stick: .media further down the file sets a 3px
     radius at the same specificity, so a lone .intro__media reset loses
     on source order and silently does nothing. The placeholder inside
     is squared off with it, or its dashed corners curve inside a square
     frame. */
  .media.intro__media{border-radius:0;min-height:580px;background:none}
  .intro__media .media__ph{border-radius:0}
  .intro__copy{padding:96px 56px 88px 64px;max-width:660px}
  .intro .kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;margin-bottom:20px}
  .intro h2{font-family:'Cormorant Garamond',serif;font-size:46px;line-height:1.08;font-weight:600;margin-bottom:24px;letter-spacing:-.5px}
  .intro p{color:var(--text-mute);font-size:16px;line-height:1.8;margin-bottom:16px;font-weight:300}
  /* Buttons are inline-flex so the pair sits level regardless of label length,
     for the same reason .ahero__actions does it. */
  .intro__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px}
  .intro__actions .btn{display:inline-flex;align-items:center;justify-content:center}
  /* Mirrored layout: copy on the left, photograph on the right. The two
     columns are mirrored rather than merely reordered, so the photograph
     keeps its own half and does not land in the copy's.
     The copy's side padding mirrors with it, so the gap to the image stays
     64px and the outer gutter stays 56px whichever side it sits on. */
  .intro--reverse .intro__top{grid-template-columns:1fr minmax(0,50%)}
  .intro--reverse .intro__media{order:2}
  .intro--reverse .intro__copy{order:1;padding:96px 64px 88px 56px}
  /* ==========================================================
     BLOCK: wcl/showreel
     Ink band between the introduction and the roster, so the film reads as
     part of the same dark run as Elite and Events rather than a widget
     dropped into the page. The frame is a fixed 16/9 box with the player
     stretched to fill it: a <video> and an <iframe> then occupy exactly the
     same space, which is what makes the swap to Vimeo a one-element edit
     with no layout change.
     ========================================================== */
  .reel{background:var(--ink);padding:96px 48px}
  .reel__inner{max-width:960px;margin:0 auto;text-align:center}
  .reel .kicker{color:var(--accent-light)}
  .reel h2{font-family:'Cormorant Garamond',serif;font-size:clamp(30px,3.4vw,46px);
    font-weight:600;color:#fff;letter-spacing:-.5px;margin-bottom:38px}
  .reel__frame{position:relative;aspect-ratio:16/9;border-radius:4px;overflow:hidden;
    background:#000;box-shadow:0 30px 70px rgba(0,0,0,.55)}
  .reel__video{position:absolute;inset:0;width:100%;height:100%;display:block;border:0;
    object-fit:cover;background:#000}

  @media(max-width:860px){
    .reel{padding:44px 24px}
    .reel h2{margin-bottom:26px}
  }

  /* ==========================================================
     BLOCK: wcl/clients

     A LIGHT band, which is the opposite of what this slot wants visually —
     it replaced a dark social bar — and it is forced by the assets. Of the
     44 logos supplied, exactly one has transparency; the rest are opaque
     files with a background baked in, 20 of them light and 17 dark. No
     single blend mode covers both, so:

       ground        white (paper-2, to separate from the white section below)
       multiply      cancels the white backgrounds of the 20 light files
       .is-inverted  flips the 17 dark files first, so their black ground
                     becomes white and gets cancelled too, and their white
                     artwork becomes black and stays
       grayscale     one tone, so 36 different brand palettes read as a list
                     of names rather than a fruit salad

     THIS IS A WORKAROUND. Ask for transparent PNGs — ideally single-colour —
     and the invert class and the multiply both become unnecessary. The
     inversion is also wrong for any logo that is genuinely colourful rather
     than white-on-black; the flyer-style ones in the full grid are the
     files to check first.
     ========================================================== */
  .clients{background:var(--paper-2);border-top:1px solid var(--line);
    border-bottom:1px solid var(--line);padding:40px 48px}
  .clients__inner{max-width:1180px;margin:0 auto;text-align:center}
  .clients__head{font-size:11px;letter-spacing:3px;text-transform:uppercase;
    color:var(--text-mute);font-weight:500;margin-bottom:26px}
  .clients__row,.clients__grid{list-style:none;display:grid;align-items:center;
    gap:24px 34px;justify-items:center}
  .clients__row{grid-template-columns:repeat(6,1fr)}
  .clients__row img,.clients__grid img{max-width:100%;height:52px;object-fit:contain;display:block;
    mix-blend-mode:multiply;filter:grayscale(1);opacity:.78;transition:opacity .25s,filter .25s}
  .clients__row img.is-inverted,.clients__grid img.is-inverted{filter:invert(1) grayscale(1)}
  /* Seven files cannot be cancelled by either blend: four are pale artwork on
     a pale ground (under 1% dark pixels, so multiply erases them outright) and
     three sit on a mid-grey ground that neither multiply nor invert can clear.
     They opt out of the blend and keep their own tile — visibly different from
     the rest, which is worse than the row and better than a hole. Re-supplied
     as transparent PNGs, every one of them drops the class. */
  .clients__row img.is-chip,.clients__grid img.is-chip{mix-blend-mode:normal;
    padding:4px 6px;border-radius:3px;box-sizing:border-box}
  .clients__row li:hover img,.clients__grid li:hover img{opacity:1}
  .clients__more{display:inline-block;margin-top:26px;font-size:11px;letter-spacing:2px;
    text-transform:uppercase;color:var(--text-mute);text-decoration:none;
    border-bottom:1px solid var(--line);padding-bottom:3px;transition:color .2s,border-color .2s}
  .clients__more:hover{color:var(--text-dark);border-bottom-color:var(--text-dark)}

  /* The full roll — same treatment, more of them, its own heading */
  .clients--all{padding:96px 48px;border-top:0}
  .clients--all .kicker{color:var(--accent-deep);margin-bottom:16px}
  .clients--all h2{font-family:'Cormorant Garamond',serif;font-size:clamp(28px,3.2vw,42px);
    font-weight:600;color:var(--text-dark);letter-spacing:-.5px;margin-bottom:46px}
  /* The full roll can afford more size than the homepage strip: it is the
     point of its section rather than a supporting line under a hero. */
  .clients__grid{grid-template-columns:repeat(6,1fr);gap:44px 34px}
  .clients__grid img{height:58px}

  @media(max-width:860px){
    .clients{padding:32px 24px}
    .clients--all{padding:44px 24px}
    .clients__row{grid-template-columns:repeat(3,1fr);gap:20px}
    .clients__grid{grid-template-columns:repeat(3,1fr);gap:28px 20px}
    .clients__row img{height:38px}
    .clients__grid img{height:44px}
  }

  /* ELITE (dark) */
  .elite{background:var(--ink);padding:110px 48px 120px;overflow:hidden;position:relative}
  /* Sized in PERCENT, not pixels: at 120% of the section the eagle is wider
     than its own container and bleeds off both edges, so no whole silhouette
     is ever visible and it reads as texture on the ink rather than as a mark
     sitting in the corner. The section clips it (overflow:hidden), and the
     content above it carries z-index:1. */
  /* The eagle behind a dark band. Shared now: the roster band has carried
     it since the reference build and the artist page's booking section is
     the same idea at the other end of a page. Both sections are already
     position:relative with overflow:hidden and their inner at z-index 1,
     which is what lets this sit behind without moving anything.
     Placement stays per section: .abook is a 760px column and would be
     swamped by the width the 1080px roster band takes. */
  .watermark{position:absolute;height:auto;opacity:.16;pointer-events:none;z-index:0}
  .elite .watermark{right:-140px;top:50%;transform:translateY(-50%);width:120%}
  .elite .side-label{color:rgba(255,255,255,.06)}
  .elite-head,.roster{position:relative;z-index:1}
  .elite-head{max-width:1080px;margin:0 auto 56px;display:flex;justify-content:space-between;align-items:flex-end;gap:20px}
  .elite-head .kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-light);font-weight:500;margin-bottom:14px}
  .elite-head h2{font-family:'Cormorant Garamond',serif;font-size:52px;font-weight:600;color:#fff;line-height:1;letter-spacing:-.5px}
  .elite-head a{color:#c3c2cf;font-size:12px;letter-spacing:2px;text-transform:uppercase;text-decoration:none;border-bottom:1px solid var(--accent-light);padding-bottom:4px;white-space:nowrap;transition:color .2s}
  .elite-head a:hover{color:#fff}
  /* Holds .artist tiles — the same card the Elite roster page uses, so the
     two grids can't drift in subtitle or hover behaviour. Only the column
     count differs: a fixed 4 here (an 8-card preview reading as 4x2) against
     the roster page's auto-fill, which has a whole roster to lay out.
     This replaced a near-identical .card component that showed the act's
     MC/DJ role instead of its genre and had no hover treatment. */
  .roster{max-width:1080px;margin:0 auto;display:grid;grid-template-columns:repeat(4,1fr);gap:20px;list-style:none}

  /* SERVICES (light) */
  .svc{background:var(--paper-2);padding:110px 48px}
  .svc-inner{max-width:1080px;margin:0 auto}
  .svc .kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;margin-bottom:16px;text-align:center}
  .svc h2{font-family:'Cormorant Garamond',serif;font-size:46px;font-weight:600;text-align:center;margin-bottom:60px;letter-spacing:-.5px}
  /* The two service cards use the .bopt component from the Services page —
     the .svc-* card that used to live here was a second, near-identical
     card style for the same content, and the two had already drifted in
     copy and CTA wording. Only the section chrome is local now. */

  /* EVENTS (dark scroll strip) */
  .events{background:var(--ink);padding:100px 0 110px;position:relative;overflow:hidden}
  .ev-head{max-width:1080px;margin:0 auto 40px;padding:0 48px;display:flex;justify-content:space-between;align-items:flex-end;gap:20px}
  .ev-head .kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-light);font-weight:500;margin-bottom:14px}
  .ev-head h2{font-family:'Cormorant Garamond',serif;font-size:52px;font-weight:600;line-height:1;letter-spacing:-.5px;color:#fff}
  .ev-head p{color:#9998a6;font-size:14px;font-weight:300;margin-top:8px}
  .ev-nav{display:flex;gap:10px}
  .ev-nav button{width:46px;height:46px;border-radius:50%;border:1px solid rgba(255,255,255,.2);background:transparent;color:#fff;font-size:18px;cursor:pointer;transition:border-color .2s,background .2s;display:flex;align-items:center;justify-content:center}
  .ev-nav button:hover{border-color:var(--accent-light);background:rgba(var(--accent-light-rgb),.12)}
  /* site.js disables an arrow at the end of its travel and hides the pair when
     the strip fits. .ev-nav is display:flex, which beats the UA sheet's
     [hidden]{display:none}, so hiding has to be said here. */
  .ev-nav button:disabled{opacity:.3;cursor:default;border-color:rgba(255,255,255,.2);background:transparent}
  .ev-nav[hidden]{display:none}
  .strip-wrap{position:relative}
  .strip{display:flex;gap:22px;overflow-x:auto;scroll-behavior:smooth;padding:6px 48px 22px;scrollbar-width:none}
  .strip::-webkit-scrollbar{display:none}
  /* The caption sits BELOW the artwork, not over it — these are flyers that
     carry their own text, so nothing should cover them. */
  .poster{position:relative;flex:0 0 auto;cursor:pointer}
  .poster__media{position:relative;height:400px;border-radius:5px;overflow:hidden;
    background:var(--ink-2);border:1px solid rgba(255,255,255,.07)}
  .poster .fill{position:absolute;inset:12px;background:linear-gradient(150deg,#191922,#101018);border:1.5px dashed rgba(255,255,255,.22);border-radius:3px}
  .poster .ph{position:absolute;inset:12px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:rgba(255,255,255,.4)}
  .poster .ph svg{width:34px;height:34px;stroke:rgba(255,255,255,.35)}
  .poster .ph span{font-size:11px;letter-spacing:2px;text-transform:uppercase;font-weight:500}
  .poster .ov{padding:14px 2px 0}
  .poster .nm{font-family:'Cormorant Garamond',serif;font-size:22px;font-weight:600;line-height:1.05;color:#fff}
  .poster .dt{font-size:12px;letter-spacing:.5px;color:#b6b5c2;margin-top:6px;font-weight:300}
  .poster .bar{position:absolute;left:0;bottom:0;height:3px;width:0;background:var(--grad);transition:width .35s}
  .poster:hover .bar{width:100%}
  /* A poster with a ticket link is an <a>; without one it stays a <div>.
     .nm and .dt set their own colours, so only the underline has to go. */
  a.poster{display:block;text-decoration:none;color:inherit}
  a.poster:focus-visible{outline:2px solid var(--accent-light);outline-offset:4px;border-radius:5px}
  /* No width classes: a poster carries its own, worked out from the artwork's
     ratio at the strip's 400px height. Five preset widths could not match every
     flyer that arrives, and the ones that missed were cropping the line-up off
     the edge. wcl/event-poster writes the width inline; see poster-width.js. */
  .edge{position:absolute;top:0;bottom:22px;width:70px;pointer-events:none;z-index:3}
  .edge.l{left:0;background:linear-gradient(to right,var(--ink),transparent)}
  .edge.r{right:0;background:linear-gradient(to left,var(--ink),transparent)}
  /* Fewer posters than the rail holds. site.js sets this, because whether they
     fit depends on the artwork's widths and the viewport, not on how many
     there are. Centred, with nothing left to scroll to and so no arrows and no
     fades: a short row rather than a carousel that has run out. */
  .events.is-static .strip{justify-content:center;overflow-x:visible}
  .events.is-static .edge{display:none}

  /* BOOKING CTA (light) */
  .book{background:var(--paper);padding:120px 48px;text-align:center}
  .book .kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;margin-bottom:20px}
  .book h2{font-family:'Cormorant Garamond',serif;font-size:clamp(38px,5vw,60px);font-weight:600;line-height:1.05;max-width:16ch;margin:0 auto 22px;letter-spacing:-.5px}
  .book p{color:var(--text-mute);font-size:17px;max-width:48ch;margin:0 auto 38px;line-height:1.7;font-weight:300}
  /* The two-button variant of the CTA band. Both of these were inline styles
     repeated on all four pages that use it; they render identically here.
     Kept scoped to .book rather than folded into .btn-line, which is the other
     light-ground secondary button but a slightly different weight.
     Note this deliberately also beats .btn-ghost:hover's white border, exactly
     as the inline style did: on this light ground a white border is invisible,
     so the button's edge holds still on hover instead of vanishing. */
  .book .cta-row{justify-content:center}
  .book .btn-ghost{border-color:rgba(26,26,31,.25);color:#1a1a1f}
  .btn-dark{background:var(--ink);color:#fff;box-shadow:var(--bevel-ink)}
  .btn-dark:hover{transform:translateY(-2px)}
  /* Secondary button for LIGHT grounds — .btn-ghost is white-on-white there.
     Same role in the pair as .btn-ghost has on the dark sections. */
  .btn-line{border:1px solid var(--line);color:var(--text-dark);background:var(--paper)}
  .btn-line:hover{border-color:var(--accent-deep);transform:translateY(-2px)}

  /* FOOTER (dark) */
  footer{background:var(--ink);padding:70px 48px 40px;color:#c3c2cf}
  .foot-inner{max-width:1080px;margin:0 auto;display:grid;grid-template-columns:2fr 1fr 1fr;gap:50px}
  /* The wordmark artwork, not the eagle mark the nav carries. It is white on
     transparent, so it only works on the dark footer ground — never reuse it
     on paper. It is the whole of the first column now that the strapline is
     gone, so it is sized to hold that column on its own rather than to match
     a line of body copy: 340px is as wide as the 2fr column takes at the
     1080px cap, and it shrinks with the column below that. Keeps .nav__logo
     so site.js's error handler still swaps in the typeset .brand below if the
     file goes missing. */
  footer .foot-logo{width:340px;max-width:100%}
  footer .brand{font-family:'Cormorant Garamond',serif;font-size:24px;letter-spacing:3px;color:#fff;font-weight:600}
  footer .brand small{display:block;font-size:9px;letter-spacing:6px;color:#8a8998;margin-top:2px;font-family:'Inter';font-weight:300}
  /* Social row, sitting under the wordmark in the first column. Circles
     rather than bare glyphs: at 17px the SoundCloud waveform and the X both
     shrink to a smudge against a large dark field, and the ring gives each
     one a hit area that clears the 24px minimum without spacing the icons
     out. footer li carries a 10px bottom margin for the link columns, which
     a horizontal row does not want. */
  .foot-social{display:flex;gap:12px;margin-top:24px}
  .foot-social li{margin:0}
  .foot-social a{display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
    border:1px solid rgba(255,255,255,.14);color:#9998a6;
    transition:color .2s,border-color .2s,background-color .2s}
  .foot-social a:hover{color:#fff;border-color:transparent;background:var(--grad)}
  .foot-social svg{width:17px;height:17px;fill:currentColor;display:block}
  footer h4{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#fff;margin-bottom:16px;font-weight:500}
  footer ul{list-style:none}
  footer li{margin-bottom:10px}
  footer a{color:#9998a6;text-decoration:none;font-size:14px;transition:color .2s}
  footer a:hover{color:var(--accent-light)}
  .foot-bar{max-width:1080px;margin:46px auto 0;padding-top:24px;border-top:1px solid rgba(255,255,255,.08);display:flex;justify-content:space-between;font-size:12px;color:#6a6a78;flex-wrap:wrap;gap:10px}

  @media(max-width:860px){
    .nav{padding:6px 24px}
    .nav.is-top{padding:12px 24px}
    .nav__item--tel{display:none}
    .nav .nav__logo{width:56px}
    .nav.is-top .nav__logo{width:84px}
    .nav:not(.is-top) .nav__logo--word{width:150px}
    .intro__top{grid-template-columns:1fr}
    .intro__media{min-height:300px;order:-1}
    .intro__copy{padding:44px 24px 44px}
    /* One column on a phone, and the photograph sits on top whichever way
       round the desktop layout is. Every one of these has to be repeated for
       .intro--reverse: those are two-class selectors and they beat the
       single-class rules just above on specificity, media query or not.
       Miss the grid-template-columns one and a reversed intro stays in two
       columns on a 600px screen; miss the order one and its image drops
       below the copy. */
    .intro--reverse .intro__top{grid-template-columns:1fr}
    .intro--reverse .intro__media{order:-1}
    .intro--reverse .intro__copy{padding:44px 24px 44px}
    /* The full-bleed sections keep their desktop container on a phone —
       48px gutters and 110px of air — while the copy block beside them runs
       at 24px and 44px. Three different rhythms down one narrow page reads
       as three different templates, so they all take the intro's. */
    .elite{padding:44px 24px}
    .svc{padding:44px 24px}
    .roster{grid-template-columns:repeat(2,1fr)}
    .foot-inner{grid-template-columns:1fr;gap:30px}
    footer .foot-logo{width:260px}
    .side-label{display:none}
    .elite-head{flex-direction:column;align-items:flex-start}
    .ev-head{flex-direction:column;align-items:flex-start;padding:0 24px}
    .ev-nav{display:none}
    .strip{padding:6px 24px 22px}
    .edge{display:none}
  }

  /* Between the mobile panel and a comfortable desktop there is a band where
     the row no longer fits. The number goes first — it is the one item that is
     a convenience rather than navigation, and it is still in the footer and on
     Contact — then the gaps tighten before anything is allowed to wrap. */
  @media(max-width:1120px){
    .nav__item--tel{display:none}
    /* The number becomes a button. Ringed like the footer's socials, and a
       real 40px target rather than a 17px glyph. */
    .nav__call{display:grid;place-items:center;flex:0 0 auto;
      width:40px;height:40px;margin-left:16px;border-radius:50%;
      border:2px solid #fff;color:#fff;
      transition:background-color .2s}
    /* Ring is already full white, so hover fills rather than brightening the
       edge — there is nowhere brighter for the border to go. */
    .nav__call:hover{background:rgba(255,255,255,.16)}
    .nav__call svg{width:17px;height:17px;display:block;fill:none;stroke:currentColor;
      stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
  }
  @media(max-width:980px){
    .nav__menu{gap:18px}
    .nav{padding:9px 28px}
    .nav.is-top{padding:18px 28px}
  }

  /* ==========================================================
     BLOCK: wcl/nav — brand lockup
     Falls back to the typeset wordmark until the logo file exists
     ========================================================== */
  .nav__brand{display:flex;align-items:center;text-decoration:none}
  /* No width here. This rule sits after the nav block, so a width set here
     silently beat .nav__logo's scrolled size on source order alone — the
     shrink-on-scroll had been dead because of it. Sizing lives with the
     state that owns it: the nav block above, and footer .foot-logo below. */
  .nav__logo{height:auto;display:block}
  .nav__brand .brand{display:none}
  .nav__brand.is-fallback .brand{display:block}
  /* Non-navigating parent label — a button, styled as a nav link */
  button.nav__link{background:none;border:0;padding:0;font:inherit;cursor:pointer;
    font-size:12px;letter-spacing:2px;text-transform:uppercase;font-weight:400;color:#e8e7ef;opacity:.85;transition:opacity .2s}
  button.nav__link:hover{opacity:1}
  .nav a[aria-current="page"]{opacity:1;color:#fff}
  .nav__submenu a[aria-current="page"]::before{transform:scaleY(1)}
  /* ==========================================================
     BLOCK: wcl/page-header
     Attributes → kicker, title, intro
     Dark band that opens an interior page. Same treatment as the
     homepage roster section so the tiers read as one family.
     ========================================================== */
  .page-head{position:relative;background:var(--ink);padding:calc(var(--nav-h-top) + 34px) 48px 84px;overflow:hidden}
  .page-head .side-label{color:rgba(255,255,255,.06)}
  .page-head__inner{position:relative;z-index:1;max-width:1080px;margin:0 auto}
  /* The way back up, for a page that sits under another. Deliberately the
     same treatment as .ahero__back, which does the same job on an artist
     page: both sit on a scrimmed photograph and both lead back to the
     page above. */
  .page-head__back{display:inline-block;font-size:11px;letter-spacing:2px;text-transform:uppercase;
    color:#b9b7c8;text-decoration:none;margin-bottom:22px;
    border-bottom:1px solid rgba(255,255,255,.2);padding-bottom:3px}
  .page-head__back:hover,.page-head__back:focus-visible{color:#fff;border-bottom-color:var(--accent-light)}
  .page-head__kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:#fff;font-weight:500;margin-bottom:18px}
  .page-head__title{font-family:'Cormorant Garamond',serif;font-weight:600;font-size:clamp(58px,9vw,116px);line-height:.92;letter-spacing:-2px;margin-bottom:calc(26px - .2em)}
  /* Fluid, like the title above it. This was a flat 17px at every width, so a
     header that halved its headline from 116px to 58px kept its intro at desk
     size — on a phone the two ended up closer in weight than they are meant to
     be, and the paragraph ran wider than it reads. The ramp is gentle because
     the floor is body copy: 15px is as small as this should ever get, where
     the title can afford to lose half its size. */
  .page-head__intro{max-width:54ch;color:#fff;line-height:1.75;font-weight:300;
    font-size:clamp(15px,0.22vw + 14.2px,17px)}

  /* ==========================================================
     BLOCK: wcl/artist-grid
     Attributes → tier, artists[] (slug, name, role, image)
     Fixed 3:4 tiles so the grid stays tidy whatever the source
     images are, and however many artists the tier holds.
     ========================================================== */
  .artists{background:var(--ink);padding:0 48px 116px;position:relative}
  .artists__inner{max-width:1080px;margin:0 auto;position:relative;z-index:1}
  .artists__grid{list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(212px,1fr));gap:20px}
  .artist{position:relative}
  .artist__link{display:block;position:relative;aspect-ratio:3/4;border-radius:3px;overflow:hidden;
    background:var(--ink-2);text-decoration:none;transition:transform .3s ease;
    /* Hairline keeps empty tiles legible against the dark section */
    border:1px solid rgba(255,255,255,.07)}
  .artist__link:hover{transform:translateY(-3px)}
  .artist__link:focus-visible{outline:2px solid var(--accent-light);outline-offset:3px}

  /* Photo. --focus re-aims the crop per artist when a shot needs it. */
  .artist__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
    object-position:var(--focus,50% 22%);transition:transform .5s ease,filter .3s ease;filter:saturate(.85)}
  .artist__link:hover .artist__img{transform:scale(1.04);filter:saturate(1)}

  /* Placeholder underneath — what shows while an artist has no lead image */
  /* padding-bottom keeps the placeholder clear of the caption, which grows
     upward when a name wraps to two lines */
  .artist__ph{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
    padding-bottom:64px;background:linear-gradient(160deg,#1b1b24,#0e0e15)}
  .artist__ph b{font-family:'Cormorant Garamond',serif;font-size:56px;font-weight:500;color:rgba(255,255,255,.1);line-height:1}
  .artist__ph span{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:rgba(255,255,255,.18);font-weight:500}

  .artist__ov{position:absolute;inset:0;z-index:2;padding:20px;display:flex;flex-direction:column;justify-content:flex-end;
    background:linear-gradient(to top,rgba(10,10,12,.94) 0%,rgba(10,10,12,.2) 52%,transparent 100%)}
  .artist__name{font-family:'Cormorant Garamond',serif;font-size:22px;font-weight:600;line-height:1.05;color:#fff;display:block}
  /* Subtitle carries the act's genre */
  .artist__genre{font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:#a9a8b6;margin-top:5px;font-weight:400;display:block}
  .artist__genre--tbc{color:#6a6a78}
  .artist__bar{position:absolute;left:0;bottom:0;z-index:3;height:3px;width:0;background:var(--grad);transition:width .35s}
  .artist__link:hover .artist__bar,.artist__link:focus-visible .artist__bar{width:100%}

  @media(prefers-reduced-motion:reduce){
    .artist__link,.artist__img{transition:none}
    .artist__link:hover{transform:none}
    .artist__link:hover .artist__img{transform:none}
  }

  @media(max-width:860px){
    .page-head{padding:130px 24px 64px}
    .artists{padding:0 24px 84px}
    .artists__grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px}
    .artist__name{font-size:19px}
    /* 11px -> 10px. The genre line sits under a name that already wrapped to
       two or three lines in a half-width tile; a point smaller keeps it as
       the caption to the name rather than a competing second line. */
    .artist__genre{font-size:10px}
  }

  /* ==========================================================
     BLOCK: wcl/service-list
     Attributes → kicker, title, services[] (name, body)
     Long-form copy on paper: one row per service, hairline-separated.
     ========================================================== */
  .services{background:var(--paper);padding:96px 48px 40px}
  .services__inner{max-width:1080px;margin:0 auto}
  .services__head{max-width:62ch;margin-bottom:46px}
  .services__kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;margin-bottom:16px}
  .services__title{font-family:'Cormorant Garamond',serif;font-size:44px;font-weight:600;line-height:1.08;letter-spacing:-.5px;margin-bottom:18px}
  .services__lede{color:var(--text-mute);font-size:17px;line-height:1.8;font-weight:300}

  .service{display:grid;grid-template-columns:270px 1fr;gap:52px;padding:42px 0;border-top:1px solid var(--line)}
  .service:last-of-type{border-bottom:1px solid var(--line)}
  .service__index{font-size:11px;letter-spacing:2px;color:var(--text-mute);font-weight:500}
  .service__name{font-family:'Cormorant Garamond',serif;font-size:29px;font-weight:600;line-height:1.1;margin-top:8px;letter-spacing:-.3px}
  /* Keeps hyphenated terms whole so they wrap at the space instead */
  .nobr{white-space:nowrap}
  .service__body p{color:var(--text-mute);font-size:16px;line-height:1.85;font-weight:300}
  .service__body p + p{margin-top:15px}


  /* ==========================================================
     BLOCK: wcl/service-extras
     Chargeable extras. The fee tag is the point of this block —
     clients need to see these sit outside the standard package.
     ========================================================== */
  .extras{position:relative;overflow:hidden;padding:78px 48px 88px;
    background:linear-gradient(180deg,#13131c 0%,#0b0b11 58%,#08080c 100%)}
  .extras__inner{max-width:1080px;margin:0 auto}
  .extras__head{text-align:center;margin-bottom:44px}
  /* Kicker picks up the brand gradient */
  .extras__kicker{font-size:11px;letter-spacing:4px;text-transform:uppercase;font-weight:600;margin-bottom:14px;
    background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
    padding-top:.16em;padding-bottom:.2em;margin-top:-.16em}
  .extras__title{font-family:'Cormorant Garamond',serif;font-size:38px;font-weight:600;letter-spacing:-.4px;
    color:#fff;margin-bottom:12px}
  .extras__lede{color:#fff;font-size:15px;line-height:1.75;font-weight:300;max-width:54ch;margin:0 auto}

  /* Two columns straight on the band — no cards — split by a gradient hairline */
  .extras__grid{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:0;max-width:940px;margin:0 auto}
  .extras__grid::before{content:'';position:absolute;left:50%;top:6px;bottom:6px;width:1px;
    background:var(--grad);opacity:.55}
  .extra{background:none;border:0;border-radius:0;padding:0 44px}
  .extra:first-child{padding-left:0}
  .extra:last-child{padding-right:0}

  /* Solid gradient tag — a premium marker, not an apologetic outline */
  .extra__tag{display:inline-block;font-size:10px;letter-spacing:2px;text-transform:uppercase;font-weight:600;
    color:#fff;background:var(--grad);border:0;border-radius:99px;padding:8px 15px 8px 17px;
    margin-bottom:26px;line-height:1}
  .extra h3{font-family:'Cormorant Garamond',serif;font-size:26px;font-weight:600;letter-spacing:-.3px;
    color:#fff;margin-bottom:12px}
  .extra p{color:#fff;font-size:15px;line-height:1.8;font-weight:300}
  .extra p + p{margin-top:12px}
  /* Follows the copy rather than being pushed to the column foot — the two
     columns are very different lengths, and pinning it left the shorter one
     with its closing line stranded below a void. */
  .extra .extra__fee{margin-top:22px;padding-top:0;font-size:13px;color:#fff;font-weight:700;line-height:1.65}

  @media(max-width:860px){
    .services{padding:64px 24px 32px}
    .services__title{font-size:34px}
    .service{grid-template-columns:1fr;gap:14px;padding:32px 0}
    .service__name{font-size:25px;margin-top:4px}
    .extras{padding:56px 24px 64px}
    .extras__title{font-size:30px}
    .extras__grid{grid-template-columns:1fr;gap:0}
    /* Stacked, the two columns are different heights, so a rule at 50% of the
       grid cuts through the first one's copy. Hang it off the second item so
       it always lands on the actual boundary. */
    .extras__grid::before{display:none}
    .extra,.extra:first-child,.extra:last-child{padding:0}
    .extra + .extra{position:relative;margin-top:34px;padding-top:34px}
    .extra + .extra::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;
      background:var(--grad);opacity:.55}
  }

  /* ==========================================================
     BLOCK: wcl/booking-options
     The signposting block. Three routes, described well enough
     that a promoter picks the right one without guessing.
     ========================================================== */
  .bopts{background:var(--paper-2);padding:76px 48px 90px}
  .bopts__inner{max-width:1080px;margin:0 auto}
  .bopts__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-bottom:40px}
  .bopt{display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--line);border-radius:4px;
    padding:32px 30px 30px;transition:border-color .2s,transform .2s,box-shadow .2s}
  .bopt:hover{border-color:var(--accent-deep);transform:translateY(-3px);box-shadow:0 14px 34px rgba(26,26,31,.07)}
  .bopt__idx{font-size:11px;letter-spacing:2px;color:var(--text-mute);font-weight:500;margin-bottom:12px}
  .bopt h3{font-family:'Cormorant Garamond',serif;font-size:28px;font-weight:600;line-height:1.1;margin-bottom:12px;letter-spacing:-.3px}
  .bopt p{color:var(--text-mute);font-size:15px;line-height:1.75;font-weight:300;margin-bottom:20px}
  .bopt__need{list-style:none;margin-bottom:26px}
  .bopt__need li{font-size:13px;color:var(--text-mute);padding-left:16px;position:relative;margin-bottom:7px;font-weight:300}
  .bopt__need li::before{content:'';position:absolute;left:0;top:8px;width:5px;height:5px;border-radius:50%;background:var(--accent-light)}
  .bopt__need b{display:block;font-size:10px;letter-spacing:2px;text-transform:uppercase;color:var(--text-dark);
    font-weight:600;margin-bottom:10px;padding-left:0}
  .bopt .btn{margin-top:auto;text-align:center}

  /* Shared callout — used for the "committed booking" note and the enquiry redirect */
  .callout{max-width:1080px;margin:0 auto;background:#fff;border:1px solid var(--line);border-radius:4px;
    padding:22px 26px;position:relative;overflow:hidden;padding-left:30px}
  .callout::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad)}
  .callout p{color:var(--text-mute);font-size:15px;line-height:1.75;font-weight:300;max-width:78ch}
  .callout strong{color:var(--text-dark);font-weight:600}
  .callout a{color:var(--accent-deep);text-decoration:none;border-bottom:1px solid rgba(var(--accent-deep-rgb),.35)}
  .callout a:hover{border-bottom-color:var(--accent-deep)}

  /* Tier caveat on the dark roster pages. Deliberately NOT the .callout panel:
     a white slab on a black page reads as an error state and cuts the page in
     half between the hero and the grid. The gradient rule carries the emphasis
     instead, and the copy sits at hero-intro contrast. */
  /* The section has no top padding — the removed panel was supplying its own,
     so the note now has to clear the hero itself. Padding, not margin: as the
     first child of a section with no top padding, a margin collapses straight
     through and drags the dark section edge down, exposing the white body. */
  .roster-note{position:relative;max-width:1080px;margin:0 auto 40px;padding:62px 0 0 22px}
  .roster-note::before{content:'';position:absolute;left:0;top:calc(62px + .3em);bottom:.3em;
    width:2px;background:var(--grad)}
  .roster-note p{color:#fff;font-size:16px;line-height:1.75;font-weight:300;max-width:74ch;margin:0}
  .roster-note strong{font-weight:600}

  /* ==========================================================
     BLOCK: wcl/booking-form
     One instance per booking type. Gravity Forms replaces the
     markup at build; the behaviour it must keep is documented
     in the block script.
     ========================================================== */


  .req{color:#b4483a;margin-left:2px}

  /* Terms — the consent block, shared by the booking pages */
  .terms{background:var(--paper-2);border:1px solid var(--line);border-radius:4px;padding:22px 24px;margin-bottom:26px}
  .check{display:flex;gap:12px;align-items:flex-start}
  .check input{width:19px;height:19px;flex:0 0 auto;margin-top:2px;accent-color:var(--accent-deep)}
  .check label{font-size:14px;line-height:1.6;color:var(--text-dark)}
  /* Label and terms link are siblings inside this, so they read as one
     sentence while only the label text is bound to the checkbox. */
  .check__text{font-size:14px;line-height:1.6;color:var(--text-dark)}
  .terms__open{font-size:14px;color:var(--accent-deep);text-decoration:underline}
  .terms__open:hover,.terms__open:focus-visible{color:var(--ink)}
  .terms__note{font-size:13px;color:var(--text-mute);margin-top:14px;padding-left:31px;font-weight:300}

  /* Optional signature — capability is there, not forced into every booking */
  .sig summary{cursor:pointer;font-size:14px;font-weight:500;color:var(--accent-deep);margin-bottom:14px}
  .sig canvas{width:100%;height:150px;border:1px dashed var(--line);border-radius:3px;background:#fff;touch-action:none;display:block}
  .sig__bar{display:flex;gap:10px;align-items:center;margin-top:10px}
  .sig__bar button{background:none;border:1px solid var(--line);border-radius:3px;padding:7px 14px;font:inherit;
    font-size:12px;cursor:pointer;color:var(--text-mute)}
  .sig__bar button:hover{border-color:var(--text-dark);color:var(--text-dark)}
  /* Always-visible variant: the signature is the act of acceptance, so it is
     laid out as an ordinary required field rather than hidden behind a toggle. */



  /* Cross-links, so nobody is stuck in the wrong form */

  @media(max-width:860px){
    .bopts{padding:56px 24px 72px}
    .bopts__grid{grid-template-columns:1fr;gap:16px}
  }

  /* ==========================================================
     COMPONENT: media placeholder
     A drop-in image slot. Point it at where a file should live;
     until that file exists the labelled placeholder shows instead,
     holding the exact space the real image will occupy so layout
     never shifts when images land.
       .media--3x4 / --4x3 / --16x9 / --1x1   crop ratio
       .media--dark                            for dark sections
       --focus: 50% 20%                        re-aim a bad crop
     ========================================================== */
  .media{position:relative;overflow:hidden;border-radius:3px;background:var(--paper-2);display:block}
  .media--1x1{aspect-ratio:1/1}
  .media--4x3{aspect-ratio:4/3}
  .media--3x4{aspect-ratio:3/4}
  .media--16x9{aspect-ratio:16/9}
  /* The placeholder sits after the img in source order, so without these both
     being stacked explicitly it paints over any image that does load. */
  .media__img{position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover;object-position:var(--focus,50% 50%)}
  .media__ph{position:absolute;inset:0;z-index:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;
    background:linear-gradient(150deg,#eeeef3,#e2e2ea);color:#9a9aa6;
    border:1px dashed rgba(15,15,20,.18);border-radius:3px}
  .media__ph svg{width:24px;height:24px;stroke:currentColor;fill:none;stroke-width:1.4}
  .media__ph b{font-size:9px;letter-spacing:2px;text-transform:uppercase;font-weight:600}
  .media__ph i{font-size:10px;font-style:normal;opacity:.75;padding:0 14px;text-align:center;line-height:1.4}
  .media--dark{background:var(--ink-2)}
  .media--dark .media__ph{background:linear-gradient(150deg,#1b1b24,#0e0e15);color:rgba(255,255,255,.34);
    border-color:rgba(255,255,255,.13)}

  /* Slot in the service list's left column, under the heading */
  .service__media{margin-top:18px}
  /* Slot at the top of a booking option card */
  .bopt__media{margin:-4px 0 20px}

  /* Drop-in slots layered into the homepage's existing tiles. Each sits above
     its placeholder and below the caption, so a dropped-in file just appears. */
  /* Posters are flyers: the line-up runs to the edge of the artwork, so a
     crop cuts names off. Each poster is given its own artwork's width at
     the strip's height, which makes this a no-op, and it stays here as the
     guarantee: a width that is ever wrong letterboxes instead of cropping. */
  .poster .media__img{border-radius:4px;object-fit:contain}

  /* ==========================================================
     BLOCK: wcl/contact
     Two columns: enquiry form, and the role-based addresses so
     people can self-route and skip the form entirely.
     ========================================================== */
  .contact{background:var(--paper);padding:70px 48px 96px}
  .contact__inner{max-width:1080px;margin:0 auto;display:grid;grid-template-columns:1fr 360px;gap:64px;align-items:start}
  .contact__lead{font-size:12px;letter-spacing:2px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;
    padding-bottom:12px;margin-bottom:22px;border-bottom:1px solid var(--line)}

  .contact__details{background:var(--paper-2);border:1px solid var(--line);border-radius:4px;padding:28px 30px 30px}
  .contact__row{padding:16px 0;border-bottom:1px solid var(--line)}
  .contact__row:first-of-type{padding-top:0}
  .contact__row:last-of-type{border-bottom:0;padding-bottom:0}
  .contact__role{font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-mute);font-weight:500;margin-bottom:6px}
  .contact__row a{color:var(--text-dark);text-decoration:none;font-size:15px;font-weight:500;
    border-bottom:1px solid rgba(var(--accent-deep-rgb),.3);transition:border-color .2s,color .2s;word-break:break-word}
  .contact__row a:hover{color:var(--accent-deep);border-bottom-color:var(--accent-deep)}
  .contact__row p{font-size:15px;color:var(--text-dark);font-weight:400;line-height:1.6}
  .contact__row p.addr{color:var(--text-mute);font-weight:300;font-size:14px}

  /* ==========================================================
     COMPONENT: Gravity Forms styling
     Deliberately written against GF's own class names so the
     placeholder markup below can be swapped for a real Gravity
     Form without restyling. When GF is installed, either dequeue
     its default stylesheet or keep these rules after it.
     GF reference: .gform_wrapper > .gform > .gform_fields > .gfield
     ========================================================== */
  /* .gform_wrapper is written twice on purpose. Gravity Forms' foundation
     layer scopes its rules as .gform-theme--foundation :where(…), which is
     (0,2,0), and it prints them inline inside the form, after this sheet,
     so a tie goes to GF. Doubling the class takes these to (0,3,0) and
     settles it. The framework layer is switched off separately, in
     wcl_gf_form_html(). */
  .gform_wrapper.gform_wrapper .gform_fields{list-style:none;display:grid;gap:20px;margin:0;padding:0}
  .gform_wrapper.gform_wrapper .gfield_label{display:block;font-size:13px;font-weight:500;line-height:normal;margin-bottom:7px;color:var(--text-dark)}
  /* Sub-labels on a composite field: the parts of an address, a name, a date.
     They have to sit under the field's own label without competing with it, so
     they are a step smaller and muted where the parent label is 13px and dark.
     GF leaves them at the inherited 16px, which makes each part look like a
     field in its own right and the real label like a section heading. */
  .gform_wrapper.gform_wrapper .gform-field-label--type-sub{display:block;
    font-size:12px;font-weight:400;line-height:normal;color:var(--text-mute);
    margin:0 0 5px;letter-spacing:normal;text-transform:none}
  /* GF gutters its composite fields with padding on each column, which insets
     the whole address 6px from the field's own label and leaves its inputs
     narrower than every other input on the form. The negative margin cancels
     the outer edge of that padding and leaves the gutter between City and ZIP
     alone: pulling the padding itself would break GF's 50/50 column maths. */
  .gform_wrapper.gform_wrapper .ginput_complex{margin-left:-6px;margin-right:-6px;width:auto}
  .gform_wrapper.gform_wrapper .gfield_required{color:#b4483a;margin-left:2px;text-decoration:none}
  .gform_wrapper.gform_wrapper .gfield_optional{color:var(--text-mute);font-weight:300;font-size:13px;margin-left:4px}
  /* This design has no dark variant: the form sits on white whatever the
     visitor's OS is set to. Without saying so, a machine in dark mode paints
     the native parts of a control from its own dark palette, and a <select>
     whose box we have forced to white ends up with the OS's light text on it.
     The chosen artist read as blank. color-scheme covers the select popup, the
     date and time pickers and the scrollbars in one word; the option colours
     below are for the browsers that paint those from author styles instead. */
  .gform_wrapper{color-scheme:light}
  .gform_wrapper.gform_wrapper option{color:var(--text-dark);background-color:#fff}

  /* background-color, not the background shorthand: the shorthand resets
     background-repeat, position and size, and the select below sets all three
     for its arrow.

     The :not()s matter. A checkbox is an input too, and 13px of padding and a
     3px radius turned the terms tickbox into a 30px outlined rectangle. */
  .gform_wrapper.gform_wrapper .ginput_container input:not([type="checkbox"]):not([type="radio"]),
  .gform_wrapper.gform_wrapper .ginput_container select,
  .gform_wrapper.gform_wrapper .ginput_container textarea{width:100%;padding:13px 14px;border:1px solid var(--line);border-radius:3px;
    background-color:#fff;font-family:inherit;font-size:15px;line-height:normal;color:var(--text-dark);transition:border-color .15s,box-shadow .15s}

  /* Gravity Forms' foundation reset strips appearance from every control, and
     its framework theme is what normally draws them back. That theme is
     switched off for these forms (see wcl_gf_form_html), so the parts it drew
     have to be drawn here: without this a select has no arrow at all and a
     checkbox is an empty square that looks broken rather than unticked.

     The arrow is ours rather than the platform's so it is the same on every OS,
     and the padding on the right keeps a long artist name off it. */
  .gform_wrapper.gform_wrapper .ginput_container select{
    appearance:none;-webkit-appearance:none;padding-right:38px;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4l5-4.8' fill='none' stroke='%2355555f' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right 14px center;background-size:12px 8px}

  /* Native again, tinted. accent-color is what the reference build uses, and a
     real checkbox brings its own tick, its own focus ring and its own
     behaviour on a phone. */
  .gform_wrapper.gform_wrapper input[type="checkbox"],
  .gform_wrapper.gform_wrapper input[type="radio"]{
    appearance:auto;-webkit-appearance:auto;
    width:19px;height:19px;flex:0 0 auto;margin:2px 0 0;padding:0;
    border:0;border-radius:0;background:none;accent-color:var(--accent-deep)}

  /* The consent field: tickbox and its sentence on one line, the way .check
     sets it out in the reference build.

     Three classes, not two. Gravity Forms lays choice fields out with
     .gform-theme--framework .gfield--type-choice .ginput_container_consent,
     which is (0,3,0) — a tie with two — and it prints that sheet after ours,
     so a tie went to GF and the tickbox sat 1px from its label. This rule is
     also one of the few framework rules that carries no disable-framework
     guard, so switching that layer off does not reach it. */
  .gform_wrapper.gform_wrapper.gform_wrapper .ginput_container_consent{display:flex;gap:12px;align-items:flex-start}
  .gform_wrapper.gform_wrapper.gform_wrapper .gform-field-label--type-inline{font-size:14px;line-height:1.6;
    font-weight:400;color:var(--text-dark);margin:0}
  .gform_wrapper.gform_wrapper .ginput_container textarea{min-height:150px;resize:vertical}
  .gform_wrapper.gform_wrapper .ginput_container input:focus,
  .gform_wrapper.gform_wrapper .ginput_container select:focus,
  .gform_wrapper.gform_wrapper .ginput_container textarea:focus{outline:none;border-color:var(--accent-deep);box-shadow:0 0 0 3px rgba(var(--accent-deep-rgb),.13)}
  .gform_wrapper.gform_wrapper .gfield_description{font-size:12px;line-height:normal;color:var(--text-mute);margin-top:6px;font-weight:300}

  /* GF adds .gfield_error to the field wrapper and renders the message inside */
  .gform_wrapper.gform_wrapper .gfield_error input,
  .gform_wrapper.gform_wrapper .gfield_error select,
  .gform_wrapper.gform_wrapper .gfield_error textarea{border-color:#b4483a;background-color:#fdf7f6}
  .gform_wrapper.gform_wrapper .gfield_validation_message{display:none;font-size:13px;color:#b4483a;margin-top:6px}
  .gform_wrapper.gform_wrapper .gfield_error .gfield_validation_message{display:block}

  /* GF's submit-time error summary */
  .gform_wrapper.gform_wrapper .validation_error{display:none;border:1px solid #d9a49c;background:#fdf3f1;border-radius:4px;
    padding:18px 20px;margin-bottom:24px}
  .gform_wrapper.gform_wrapper .validation_error.is-shown{display:block}
  .gform_wrapper.gform_wrapper .validation_error h2{font-size:14px;font-weight:600;color:#93392d;margin-bottom:10px}
  .gform_wrapper.gform_wrapper .validation_error ul{list-style:none;font-size:14px}
  .gform_wrapper.gform_wrapper .validation_error li{margin-bottom:5px}
  .gform_wrapper.gform_wrapper .validation_error a{color:#93392d}

  .gform_wrapper.gform_wrapper .gform_footer{margin-top:26px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
  .gform_wrapper.gform_wrapper .gform_button{display:inline-block;padding:15px 30px;font-size:12px;letter-spacing:2px;
    text-transform:uppercase;font-weight:500;border:0;border-radius:2px;cursor:pointer;font-family:inherit;
    background:var(--grad);color:#fff;box-shadow:var(--bevel);transition:transform .2s,box-shadow .2s}
  .gform_wrapper.gform_wrapper .gform_button:hover{transform:translateY(-2px);box-shadow:var(--bevel),0 10px 30px rgba(var(--accent-deep-rgb),.35)}
  /* Visible by default. Gravity Forms only prints this when there is a
     confirmation to print, so hiding it in CSS meant a submitted booking
     came back to a page with the heading, the note, and nothing in
     between. The reference build's copy is a static panel its demo script
     switches on, and that one hides itself with the hidden attribute;
     .is-shown is what the script uses to beat it. */
  .gform_confirmation_wrapper{border:1px solid #9ccbb5;background:#f1f8f5;border-radius:4px;padding:28px 30px}
  .gform_confirmation_wrapper.is-shown{display:block}
  .gform_confirmation_wrapper h2{font-family:'Cormorant Garamond',serif;font-size:28px;font-weight:600;margin-bottom:10px}
  .gform_confirmation_wrapper p{color:var(--text-mute);font-size:15px;line-height:1.75;font-weight:300;margin-bottom:10px}

  @media(max-width:860px){
    .contact{padding:48px 24px 72px}
    .contact__inner{grid-template-columns:1fr;gap:40px}
  }

  /* ==========================================================
     BLOCK: wcl/artist-hero
     One template, many artists — so every rule here has to hold
     for a 1000px phone snap and a 2000px studio shot alike.
     ========================================================== */
  /* clamped rather than plain vh — on a very tall window 70vh becomes an
     absurd amount of empty hero above the fold */
  .ahero{position:relative;min-height:clamp(460px,70vh,760px);background:var(--ink);
    display:flex;align-items:flex-end;overflow:hidden}
  .ahero__media{position:absolute;inset:0;z-index:0}
  .ahero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
    object-position:var(--focus,50% 22%);opacity:.6}
  /* Shown when an artist has no lead image yet — an initial keeps the hero
     looking deliberate instead of blank */
  .ahero__ph{position:absolute;inset:0;background:linear-gradient(150deg,#1b1b24,#0c0c12);
    display:flex;align-items:center;justify-content:center}
  .ahero__ph b{font-family:'Cormorant Garamond',serif;font-weight:500;line-height:1;
    font-size:min(30vw,260px);color:rgba(255,255,255,.055)}
  /* Same scrim recipe as the homepage hero, so low-res shots still read as intentional */
  .ahero__tint{position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,rgba(10,10,12,.92) 0%,rgba(10,10,12,.7) 46%,rgba(10,10,12,.35) 100%)}
  .ahero__fade{position:absolute;inset:0;z-index:1;background:linear-gradient(to bottom,rgba(10,10,12,.75) 0%,transparent 32%,transparent 58%,rgba(10,10,12,.96) 100%)}
  .ahero__inner{position:relative;z-index:5;padding:150px 48px 60px;max-width:1080px;margin:0 auto;width:100%}
  .ahero__back{display:inline-block;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#b9b7c8;
    text-decoration:none;margin-bottom:26px;border-bottom:1px solid rgba(255,255,255,.2);padding-bottom:3px}
  .ahero__back:hover{color:#fff;border-bottom-color:var(--accent-light)}
  .ahero__role{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-light);font-weight:500;margin-bottom:14px}
  .ahero__name{font-family:'Cormorant Garamond',serif;font-weight:600;line-height:.95;letter-spacing:-2px;
    font-size:clamp(44px,7.5vw,102px);max-width:16ch;color:#fff;
    text-shadow:0 2px 30px rgba(10,10,12,.6)}

  /* ==========================================================
     BLOCK: wcl/artist-bio
     Narrow measure so a 60-word bio and a 220-word one both read
     as deliberate rather than as a gap or a wall.
     ========================================================== */
  .abio{background:var(--paper);padding:82px 48px}
  .abio__inner{max-width:660px;margin:0 auto}
  .abio__kicker{font-size:11px;letter-spacing:3px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;
    padding-bottom:12px;margin-bottom:26px;border-bottom:1px solid var(--line)}
  .abio p{font-size:17px;line-height:1.85;color:var(--text-mute);font-weight:300}
  .abio p + p{margin-top:18px}
  /* The tail of a long biography, folded away by site.js. It is open in
     the markup and the button is hidden, so with no JavaScript the whole
     bio simply reads. Its first paragraph needs the spacing that p + p
     would have given it, having no sibling above it any more. */
  .abio__rest p{margin-top:18px}
  .abio__toggle{margin-top:22px}
  /* Opening paragraph carries a little more weight — helps a short bio hold the page */
  .abio__inner > p:first-of-type{font-size:19px;line-height:1.75;color:var(--text-dark);font-weight:300}

  /* ==========================================================
     BLOCK: wcl/artist-media
     Video, gallery and music. Any section with no data is omitted
     entirely by the template rather than left as an empty heading.
     ========================================================== */
  .amedia{background:var(--paper-2);padding:78px 48px}
  .amedia__inner{max-width:1080px;margin:0 auto}
  .amedia__group + .amedia__group{margin-top:60px}
  .amedia__head{font-size:11px;letter-spacing:3px;text-transform:uppercase;color:var(--accent-deep);font-weight:600;
    padding-bottom:12px;margin-bottom:22px;border-bottom:1px solid var(--line)}
  .avideo{max-width:840px}
  /* Visually hidden, still read aloud. The gallery buttons carry their label
     this way: the thumbnail inside them is decorative and aria-hidden. */
  .screen-reader-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

  .agallery{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}

  /* A gallery thumbnail is a button, not a link: it opens the viewer, it does
     not navigate. The button is stripped back to nothing so the figure inside
     it looks exactly as it did when it was the grid item itself. */
  .agal__open{display:block;width:100%;padding:0;border:0;background:none;
    border-radius:3px;cursor:zoom-in;transition:transform .3s ease}
  .agal__open:hover{transform:translateY(-3px)}
  .agal__open:focus-visible{outline:2px solid var(--accent-light);outline-offset:3px}
  .agal__open .media{margin:0}

  /* The viewer. <dialog> puts this in the top layer, so it needs no z-index
     and cannot be trapped under a stacking context somewhere up the page. */
  .alightbox{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;
    padding:0;border:0;background:transparent;overflow:hidden}
  .alightbox::backdrop{background:rgba(6,6,9,.92)}
  .alightbox__stage{position:absolute;inset:0;display:flex;align-items:center;
    justify-content:center;padding:64px 78px}
  .alightbox__img{max-width:100%;max-height:100%;object-fit:contain;
    border-radius:4px;display:block}
  .alightbox__btn{position:absolute;display:flex;align-items:center;justify-content:center;
    width:46px;height:46px;border-radius:50%;border:1px solid rgba(255,255,255,.22);
    background:rgba(10,10,12,.55);color:#fff;font-size:22px;line-height:1;cursor:pointer;
    transition:border-color .2s,background .2s}
  .alightbox__btn:hover{border-color:var(--accent-light);background:rgba(var(--accent-light-rgb),.18)}
  .alightbox__btn:focus-visible{outline:2px solid var(--accent-light);outline-offset:3px}
  .alightbox__btn[disabled]{opacity:.3;cursor:default}
  .alightbox__btn[disabled]:hover{border-color:rgba(255,255,255,.22);background:rgba(10,10,12,.55)}
  .alightbox__close{top:18px;right:18px;font-size:26px}
  .alightbox__prev{left:18px;top:50%;transform:translateY(-50%)}
  .alightbox__next{right:18px;top:50%;transform:translateY(-50%)}
  .alightbox__count{position:absolute;left:0;right:0;bottom:20px;text-align:center;
    font-size:11px;letter-spacing:2px;text-transform:uppercase;color:rgba(255,255,255,.6)}
  .amusic{max-width:840px;min-height:160px;display:flex;align-items:center;justify-content:center;
    background:var(--paper);border:1px dashed var(--line);border-radius:4px;padding:26px;text-align:center}
  .amusic p{font-size:13px;color:var(--text-mute);font-weight:300;line-height:1.7}
  .amusic b{display:block;font-size:10px;letter-spacing:2px;text-transform:uppercase;color:var(--text-dark);
    font-weight:600;margin-bottom:8px}

  /* ==========================================================
     BLOCK: wcl/artist-book-bar
     Phone-only standing CTA. Hidden outright above 860px, where the hero's
     own buttons never travel far from view. It rides directly under the
     scrolled nav rather than at the foot of the screen: the thumb reaches
     the bottom more easily, but the bottom of an artist page is where the
     real booking block lives, and two competing CTAs in the same 100px was
     worse than the reach. Translated out of frame rather than display:none
     so it can slide in, and pointer-events go with it so the hidden bar
     never eats a tap meant for the page. The resting state also needs
     opacity AND visibility, not just the transform: -130% of its own height
     parks it behind the nav, which is fine once the nav is opaque but shows
     straight through the transparent top-of-page bar.
     ========================================================== */
  .abar{display:none}
  @media(max-width:860px){
    .abar{position:fixed;left:0;right:0;top:calc(var(--nav-h-mobile) + var(--admin-bar-h));z-index:25;
      display:flex;align-items:center;justify-content:center;gap:9px;
      padding:13px 20px;background:var(--grad);color:#fff;text-decoration:none;
      font-size:12px;letter-spacing:2px;text-transform:uppercase;font-weight:500;
      box-shadow:var(--bevel),0 10px 24px rgba(0,0,0,.4);
      transform:translateY(-130%);opacity:0;visibility:hidden;pointer-events:none;
      transition:transform .28s ease,opacity .28s ease,visibility 0s linear .28s}
    .abar.is-shown{transform:none;opacity:1;visibility:visible;pointer-events:auto;
      transition:transform .28s ease,opacity .28s ease,visibility 0s}
    .abar svg{width:15px;height:15px;flex:0 0 auto;fill:none;stroke:currentColor;
      stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  }
  @media(prefers-reduced-motion:reduce){
    .abar{transition:none}
  }

  /* ==========================================================
     BLOCK: wcl/artist-links — press pack and socials
     ========================================================== */
  .alinks{background:var(--paper);padding:70px 48px}
  .alinks__inner{max-width:1080px;margin:0 auto}
  .alinks__row{display:flex;gap:12px;flex-wrap:wrap}
  .alink{display:inline-flex;align-items:center;gap:9px;white-space:nowrap;padding:12px 20px;border:1px solid var(--line);
    border-radius:3px;text-decoration:none;color:var(--text-dark);font-size:13px;font-weight:500;
    background:var(--paper);transition:border-color .2s,transform .2s}
  .alink:hover{border-color:var(--accent-deep);transform:translateY(-2px)}

  /* ==========================================================
     BLOCK: wcl/artist-booking
     The fix for the current site's broken "Book now": the artist
     is attached before the client touches the form.
     ========================================================== */
  .abook{background:var(--ink);padding:82px 48px 90px;position:relative;overflow:hidden}
  .abook__inner{max-width:760px;margin:0 auto;position:relative;z-index:1}
  .abook .watermark{right:-90px;top:50%;transform:translateY(-50%);width:78%}
  .abook__kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;color:var(--accent-light);font-weight:500;margin-bottom:14px}
  .abook h2{font-family:'Cormorant Garamond',serif;font-size:clamp(32px,4.4vw,50px);font-weight:600;color:#fff;
    line-height:1.05;letter-spacing:-.5px;margin-bottom:16px}
  /* No measure cap here. .abook__inner is already a 760px column, which is
     a comfortable measure on its own, and the 56ch limit broke this one
     sentence onto a second line with two words on it. */
  .abook__lede{color:#9998a6;font-size:16px;line-height:1.75;font-weight:300;margin-bottom:34px}
  /* Artist is fixed on this page — shown, not chosen */
  .abook__locked{display:flex;align-items:center;gap:14px;background:rgba(255,255,255,.05);
    border:1px solid rgba(255,255,255,.12);border-radius:4px;padding:15px 20px;margin-bottom:24px}
  .abook__locked .l{font-size:10px;letter-spacing:2px;text-transform:uppercase;color:#8a8998;font-weight:500}
  .abook__locked .n{font-family:'Cormorant Garamond',serif;font-size:21px;font-weight:600;color:#fff;line-height:1}

  /* The three booking routes. A list, not a button row: the labels are
     different lengths and each needs a line of explanation, so equal-width
     buttons would either truncate or leave the choice unexplained. Full-width
     rows stack cleanly at every size and give the tap target real height. */
  .abook__choices{list-style:none;display:grid;gap:10px;margin-bottom:30px}
  .achoice{display:flex;align-items:center;gap:18px;padding:20px 22px;text-decoration:none;
    background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);border-radius:4px;
    transition:border-color .2s,background-color .2s,transform .2s}
  .achoice:hover,.achoice:focus-visible{border-color:var(--accent-light);background:rgba(255,255,255,.07);transform:translateY(-2px)}
  .achoice__idx{flex:0 0 auto;font-family:'Cormorant Garamond',serif;font-variant-numeric:lining-nums;
    font-size:20px;font-weight:600;color:var(--accent-light);line-height:1;opacity:.85}
  .achoice__body{display:block}
  .achoice__title{display:block;font-size:15px;font-weight:500;color:#fff;letter-spacing:.2px;margin-bottom:4px}
  .achoice__note{display:block;font-size:13px;line-height:1.6;color:#9998a6;font-weight:300}
  /* Pushed right by margin-left:auto so it stays pinned to the edge however
     long the copy runs; nudged on hover to read as "go". */
  .achoice__go{flex:0 0 auto;margin-left:auto;width:17px;height:17px;stroke:var(--accent-light);fill:none;
    stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s}
  .achoice:hover .achoice__go{transform:translateX(3px)}
  .abook__note{font-size:13px;line-height:1.7;color:#8a8998;font-weight:300}
  .abook__note a{color:#c3c2cf;text-decoration:none;border-bottom:1px solid rgba(255,255,255,.28)}
  .abook__note a:hover{color:#fff;border-bottom-color:#fff}
  @media(prefers-reduced-motion:reduce){
    .achoice,.achoice__go{transition:none}
    .achoice:hover{transform:none}
    .achoice:hover .achoice__go{transform:none}
  }

  /* Dark-background overrides for the GF-classed form */
  .abook .gform_wrapper .gfield_label{color:#e8e7ef}
  .abook .gform_wrapper .ginput_container input,
  .abook .gform_wrapper .ginput_container textarea{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.16);color:#fff}
  .abook .gform_wrapper .ginput_container input:focus,
  .abook .gform_wrapper .ginput_container textarea:focus{border-color:var(--accent-light);box-shadow:0 0 0 3px rgba(var(--accent-light-rgb),.16)}
  .abook .gform_wrapper .gfield_description{color:#8a8998}
  .abook .gform_wrapper .gfield_error input,
  .abook .gform_wrapper .gfield_error textarea{border-color:#e08e82;background:rgba(180,72,58,.12)}
  .abook .gform_wrapper .gfield_validation_message{color:#e08e82}
  .abook .gform_wrapper .validation_error{background:rgba(180,72,58,.14);border-color:rgba(224,142,130,.5)}
  .abook .gform_wrapper .validation_error h2{color:#f0b8b0}
  .abook .gform_wrapper .validation_error a{color:#f0b8b0}
  .abook .gform_confirmation_wrapper{background:rgba(var(--accent-light-rgb),.1);border-color:rgba(var(--accent-light-rgb),.4)}
  .abook .gform_confirmation_wrapper h2{color:#fff}
  .abook .gform_confirmation_wrapper p{color:#c3c2cf}

  @media(max-width:860px){
    .ahero__inner{padding:120px 24px 44px}
    .ahero__tint{background:linear-gradient(180deg,rgba(10,10,12,.6) 0%,rgba(10,10,12,.35) 45%,rgba(10,10,12,.9) 100%)}
    .abio{padding:56px 24px}
    .abio__inner > p:first-of-type{font-size:17px}
    .amedia{padding:56px 24px}
    .agallery{grid-template-columns:repeat(2,1fr);gap:10px}
    .alightbox__stage{padding:64px 16px 78px}
    .alightbox__prev{left:50%;top:auto;bottom:52px;transform:translateX(calc(-50% - 34px))}
    .alightbox__next{right:auto;left:50%;top:auto;bottom:52px;transform:translateX(calc(-50% + 34px))}
    .alightbox__count{bottom:20px}
    .alinks{padding:48px 24px}
    .abook{padding:56px 24px 64px}
  }

  /* ==========================================================
     BLOCK: wcl/roster-grid (Live / Friends)
     The lighter tiers: photo and name only, no click-through.
     Shares the Elite grid's proportions so the three roster pages
     read as a set, minus every interactive affordance — these
     tiles aren't links and shouldn't pretend to be.
     ========================================================== */
  .page-head--light .page-head__title{font-size:clamp(46px,6.5vw,84px)}
  .page-head--light{padding:calc(var(--nav-h-top) + 14px) 48px 68px}

  .artist__card{display:block;position:relative;aspect-ratio:3/4;border-radius:3px;overflow:hidden;
    background:var(--ink-2);border:1px solid rgba(255,255,255,.07)}
  .artists--display .artist__img{filter:saturate(.85)}
  .artists--display .artist__ov{background:linear-gradient(to top,rgba(10,10,12,.94) 0%,rgba(10,10,12,.18) 46%,transparent 100%)}
  .artists--display .artist__name{font-size:20px}
  /* Count line — the roster changes, so say how big it currently is */
  .artists__count{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#6a6a78;
    font-weight:500;margin-bottom:26px}

  @media(max-width:860px){
    .page-head--light{padding:120px 24px 52px}
    .artists--display .artist__name{font-size:17px}
  }

  /* Sub-group heading, used only if a roster tier is split by genre */
  .artists__group{font-family:'Cormorant Garamond',serif;font-size:30px;font-weight:600;color:#fff;
    margin:44px 0 20px;padding-bottom:12px;border-bottom:1px solid rgba(255,255,255,.1)}
  .artists__group:first-of-type{margin-top:0}
  /* Callout sits on the dark roster background here */

  /* ==========================================================
     BLOCK: wcl/team
     A small team presented as a small team — generous cards, few
     of them, no padding the grid out to look bigger than it is.
     ========================================================== */
  .team{background:var(--paper-2);padding:76px 48px 90px}
  .team__inner{max-width:1080px;margin:0 auto}
  /* Two up, not three. At three across a card is ~340px wide, which puts the
     longer bios at roughly 45 characters a line — a newspaper column of
     15px text, and the reason they read as long. Two across gives ~470px of
     measure, a normal 70-ish characters, and halves the height with it.
     auto-fit rather than a fixed 2, so the last card still fills the row on
     the way down to the single-column breakpoint. */
  .team__grid{list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(430px,1fr));gap:28px}
  /* Uneven bios make uneven cards. Aligning to the top rather than stretching
     stops a one-paragraph card being padded out to match a three-paragraph
     neighbour, which is what makes a grid of them look broken. */
  .team__grid{align-items:start}
  .member{background:var(--paper);border:1px solid var(--line);border-radius:4px;overflow:hidden;
    display:flex;flex-direction:column}
  .member .media{border-radius:0;border-bottom:1px solid var(--line)}
  .member__body{padding:26px 28px 28px;display:flex;flex-direction:column;flex:1}
  .member__name{font-family:'Cormorant Garamond',serif;font-size:27px;font-weight:600;line-height:1.1;
    letter-spacing:-.3px;margin-bottom:6px}
  .member__role{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--accent-deep);
    font-weight:600;margin-bottom:16px}
  .member__bio{font-size:15px;line-height:1.8;color:var(--text-mute);font-weight:300}
  .member__bio + .member__bio{margin-top:12px}
  .member__contact{margin-top:18px;padding-top:16px;border-top:1px solid var(--line);font-size:13px}
  .member__contact a{color:var(--text-dark);text-decoration:none;border-bottom:1px solid rgba(var(--accent-deep-rgb),.3);
    word-break:break-word}
  .member__contact a:hover{color:var(--accent-deep);border-bottom-color:var(--accent-deep)}

  @media(max-width:860px){
    .team{padding:52px 24px 68px}
    .team__grid{grid-template-columns:1fr;gap:20px}
  }

  /* ==========================================================
     BLOCK: wcl/page-header — background image
     Same treatment as the homepage hero video: image, then a
     two-part scrim (left-weighted for the copy, plus top and
     bottom fades) so the type stays readable over any crop.
     ========================================================== */
  .page-head__bg{position:absolute;inset:0;z-index:0;width:100%;height:100%;
    object-fit:cover;object-position:var(--focus,center 42%);opacity:.42}
  .page-head__scrim{position:absolute;inset:0;z-index:0;background:
    linear-gradient(90deg,rgba(10,10,12,.93) 0%,rgba(10,10,12,.78) 46%,rgba(10,10,12,.45) 100%),
    linear-gradient(to bottom,rgba(10,10,12,.6) 0%,rgba(10,10,12,0) 38%,rgba(10,10,12,.8) 100%)}
  /* Watermark sits above the photo, so drop it right back when both are present */

  @media(max-width:860px){
    /* Narrow screens: re-aim the scrim top-to-bottom, as on the hero */
    .page-head__scrim{background:
      linear-gradient(to bottom,rgba(10,10,12,.72) 0%,rgba(10,10,12,.5) 42%,rgba(10,10,12,.88) 100%)}
    .page-head__bg{opacity:.5}
  }

  /* SoundCloud embed. The provider's snippet ships without a height, so it
     collapses to ~150px unless one is set — visual players want 300px. */
  .amusic-embed{max-width:840px}
  /* height is the fallback only. The artist template sets its own inline,
     worked out from the player URL: a single track is 166 and a fixed 300
     left a third of the box empty under one. */
  .amusic-embed iframe{display:block;width:100%;height:300px;border:0;border-radius:4px}

  /* ==========================================================
     BLOCK: wcl/artist-hero — above-the-fold actions
     Book / press pack / music, reachable without scrolling. Each
     one appears only if its destination exists, so an artist with
     no press pack gets two buttons rather than a dead one.
     ========================================================== */
  .ahero__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px}
  /* inline-flex, not the .btn default of inline-block. These sit in a flex row
     that stretches every button to the tallest one — set by the SoundCloud
     button, whose 16px icon inflates its line box. A stretched inline-block
     lays its text from the top and dumps the extra height underneath, so the
     label on an icon-less button like "Book now" rode ~3px high. Centring each
     button's own content makes the stretch land evenly above and below. */
  .ahero__actions .btn{padding:13px 26px;display:inline-flex;align-items:center;justify-content:center}
  .ahero__actions .btn-ghost{background:rgba(255,255,255,.06);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
  /* No vertical-align here — as a flex item the icon is centred by the rule
     above, and vertical-align has no effect on it. */
  .ahero__actions .btn svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2;
    margin-left:7px}
  /* Anchored media groups must clear the sticky bar like sections do */
  .amedia__group[id]{scroll-margin-top:110px}

  @media(max-width:860px){
    .ahero__actions{gap:9px;margin-top:24px}
    .ahero__actions .btn{padding:12px 18px;font-size:11px}
  }

  /* SoundCloud mark. Filled, not stroked — the button's default icon style is
     a 2px stroke, which at 15px was thicker than the gaps inside the cloud and
     collapsed it into an unreadable blob. */
  .icon-sc{width:16px !important;height:16px !important;fill:currentColor;stroke:none}

  /* ==========================================================
     Social icon row on the artist profile. Optional per artist —
     only the platforms actually supplied get rendered.
     ========================================================== */
  .asocials{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}
  .asocial{width:44px;height:44px;border-radius:50%;border:1px solid var(--line);background:var(--paper);
    display:inline-flex;align-items:center;justify-content:center;color:var(--text-mute);
    transition:color .2s,border-color .2s,transform .2s}
  .asocial:hover{color:var(--accent-deep);border-color:var(--accent-deep);transform:translateY(-2px)}
  .asocial:focus-visible{outline:2px solid var(--accent-deep);outline-offset:3px}
  .asocial svg{width:18px;height:18px;fill:currentColor;stroke:none}
  /* Marks that are genuinely outlines rather than solid glyphs */
  .asocial svg.sic-stroke{fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round}
  .asocial svg .sic-dot{fill:currentColor;stroke:none}
  /* Press pack sits above the icons, so give it room */
  .alinks__row + .asocials{margin-top:14px}

  /* YouTube embed. aspect-ratio keeps it 16:9 at any width — an iframe has no
     intrinsic ratio, so without this it collapses to the default 150px. */
  iframe.avideo{display:block;width:100%;max-width:840px;aspect-ratio:16/9;height:auto;border:0;border-radius:4px}

  /* .alink icons need the same stroke treatment the .btn icons get, or they
     fall back to a default fill and the arrow renders as a solid blob. */
  .alink svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:2;
    stroke-linecap:round;stroke-linejoin:round;margin-left:7px;vertical-align:-1px}

  /* Submenus on nav items near the right edge open right-aligned, or a
     246px panel hanging left-to-right would push off the viewport. */
  .nav__submenu--right{left:auto;right:-18px}

  /* ==========================================================
     BLOCK: wcl/booking-options — image-led cards
     Bigger image with the title set into it. Overrides the earlier
     .bopt rules (later in the file wins at equal specificity).
     ========================================================== */
  .bopt{padding:0;overflow:hidden}
  .bopt__media{margin:0;border-radius:0;border-bottom:1px solid var(--line)}
  .bopt__media .media__img{transition:transform .5s ease}
  .bopt:hover .bopt__media .media__img{transform:scale(1.04)}

  /* Scrim carries the type over both a photo and the dark empty state */
  .bopt__overlay{position:absolute;inset:0;z-index:3;display:flex;flex-direction:column;justify-content:flex-end;
    padding:22px 24px;background:linear-gradient(to top,rgba(10,10,12,.92) 0%,rgba(10,10,12,.45) 48%,rgba(10,10,12,.12) 100%)}
  .bopt__overlay .bopt__idx{font-size:10px;letter-spacing:2.5px;color:rgba(255,255,255,.65);
    font-weight:500;margin-bottom:9px}
  .bopt__overlay h3{font-family:'Cormorant Garamond',serif;font-size:30px;font-weight:600;line-height:1.05;
    letter-spacing:-.4px;color:#fff;margin:0;text-shadow:0 2px 18px rgba(10,10,12,.5)}

  .bopt__body{padding:26px 28px 30px;display:flex;flex-direction:column;flex:1}
  .bopt__body p{color:var(--text-mute);font-size:15px;line-height:1.75;font-weight:300;margin-bottom:20px}

  @media(max-width:860px){
    .bopt__overlay{padding:18px 20px}
    .bopt__overlay h3{font-size:26px}
    .bopt__body{padding:22px 22px 26px}
  }

  /* Card image is clickable as well as the button. It's pointer-only —
     tabindex="-1" and aria-hidden keep it out of the tab order so the card
     doesn't present the same destination twice to keyboard and screen readers. */
  .bopt__link{display:block;text-decoration:none}

  /* ==========================================================
     BLOCK: wcl/legal
     Long-form policy text — narrow measure, clear heading rhythm.
     ========================================================== */
  .legal{background:var(--paper);padding:72px 48px 96px}
  .legal__inner{max-width:680px;margin:0 auto}
  .legal__updated{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-mute);
    font-weight:500;padding-bottom:14px;margin-bottom:26px;border-bottom:1px solid var(--line)}
  .legal__lede{font-size:17px;line-height:1.8;color:var(--text-dark);font-weight:300;margin-bottom:8px}
  .legal h2{font-family:'Cormorant Garamond',serif;font-size:27px;font-weight:600;letter-spacing:-.3px;
    margin:44px 0 14px;line-height:1.15}
  .legal p{font-size:15px;line-height:1.85;color:var(--text-mute);font-weight:300;margin-bottom:14px}
  .legal ul{margin:0 0 18px 0;padding-left:0;list-style:none}
  .legal li{position:relative;padding-left:20px;font-size:15px;line-height:1.8;color:var(--text-mute);
    font-weight:300;margin-bottom:9px}
  .legal li::before{content:'';position:absolute;left:2px;top:12px;width:5px;height:5px;border-radius:50%;
    background:var(--accent-light)}
  .legal a{color:var(--accent-deep);text-decoration:none;border-bottom:1px solid rgba(var(--accent-deep-rgb),.35);
    transition:border-color .2s;word-break:break-word}
  .legal a:hover{border-bottom-color:var(--accent-deep)}
  .legal__address{font-style:normal;font-size:15px;line-height:1.9;color:var(--text-mute);font-weight:300}

  /* Footer bar picks up the privacy link */
  .foot-bar a{color:#9998a6;text-decoration:none;border-bottom:1px solid rgba(255,255,255,.18);transition:color .2s,border-color .2s}
  .foot-bar a:hover{color:#fff;border-bottom-color:var(--accent-light)}

  @media(max-width:860px){
    .legal{padding:52px 24px 72px}
    .legal h2{font-size:24px;margin:34px 0 12px}
  }

  /* ==========================================================
     Homepage services head — same left/right split as the Elite
     block, restyled for a light background.
     ========================================================== */
  .svc-head{max-width:1080px;margin:0 auto 56px;display:flex;justify-content:space-between;
    align-items:flex-end;gap:20px}
  .svc-head .kicker{text-align:left;margin-bottom:14px}
  .svc-head h2{text-align:left;margin-bottom:0}
  .svc-head a{color:var(--text-mute);font-size:12px;letter-spacing:2px;text-transform:uppercase;
    text-decoration:none;border-bottom:1px solid var(--accent-deep);padding-bottom:4px;white-space:nowrap;
    transition:color .2s}
  .svc-head a:hover{color:var(--text-dark)}

  @media(max-width:860px){
    .svc-head{flex-direction:column;align-items:flex-start;margin-bottom:36px}
  }

  /* ==========================================================
     BLOCK: wcl/footer — punchier treatment
     Overrides the flat ink block: brand gradient across the top
     edge, a deeper graded ground, and a soft brand bloom in the
     corner so the foot of the page doesn't just die to black.
     ========================================================== */
  footer{position:relative;overflow:hidden;
    background:linear-gradient(180deg,#13131c 0%,#0b0b11 55%,#08080c 100%)}
  /* Gradient edge ties the footer to the buttons and display type */
  footer::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad)}
  /* Bloom sits behind everything and never intercepts clicks */
  footer::after{content:'';position:absolute;right:-160px;bottom:-260px;width:640px;height:640px;
    border-radius:50%;pointer-events:none;
    background:radial-gradient(circle,rgba(var(--accent-deep-rgb),.30) 0%,rgba(var(--accent-light-rgb),.10) 45%,transparent 70%)}
  .foot-inner,.foot-bar{position:relative;z-index:1}

  /* Column headings get a short gradient rule */
  footer h4{position:relative;padding-bottom:12px;margin-bottom:18px}
  footer h4::after{content:'';position:absolute;left:0;bottom:0;width:26px;height:2px;
    background:var(--grad);border-radius:2px}

  footer{color:#fff}
  footer p{color:#fff}
  footer a{color:#fff}
  footer a:hover{color:var(--accent-light)}
  footer li{color:#fff}
  /* The address line was an inline muted grey — now a class, still white */
  .foot-note{color:#fff;font-size:13px;opacity:.82}
  .foot-bar{color:#fff}
  /* footer a sets 14px, but this row runs at 12px — match the plain text */
  .foot-bar a{color:#fff;font-size:inherit;border-bottom-color:rgba(255,255,255,.35)}
  .foot-bar a:hover{color:var(--accent-light);border-bottom-color:var(--accent-light)}
  footer li a{position:relative}
  .foot-bar{border-top-color:rgba(255,255,255,.12)}

  @media(max-width:860px){
    footer::after{right:-240px;bottom:-320px;width:480px;height:480px}
  }

  /* ==========================================================
     BLOCK: wcl/nav — mobile menu
     Under 860px the bar collapses to a toggle and the menu becomes
     a full-screen panel. Submenus are shown inline rather than as
     hover dropdowns, since there's no hover to work with.
     ========================================================== */
  @media(max-width:860px){
    .nav__brand{position:relative;z-index:60}

    .nav__toggle{display:flex;flex-direction:column;justify-content:center;gap:5px;
      width:44px;height:44px;padding:0;background:none;border:0;cursor:pointer;
      position:relative;z-index:60}
    /* Burger state: the panel takes the menu out of flow, so the call button
       and the burger are the only things left beside the logo. They pair at
       the right edge — call first, burger last, because the burger belongs at
       the edge — and the auto margin does the pushing, since the row's
       space-between has nothing to distribute once the menu is gone.
       z-index 60 keeps it tappable over the open panel, like the burger. */
    .nav__call{order:2;margin-left:auto;margin-right:14px;position:relative;z-index:60}
    .nav__toggle{order:3}
    .nav__toggle span{display:block;width:24px;height:2px;margin:0 auto;border-radius:2px;background:#fff;
      transition:transform .3s ease,opacity .2s ease}
    .nav.is-open .nav__toggle span:nth-child(1){transform:translateY(7px) rotate(45deg)}
    .nav.is-open .nav__toggle span:nth-child(2){opacity:0}
    .nav.is-open .nav__toggle span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

    /* Panel. Inside .nav's stacking context, so it covers the page but the
       brand and toggle (z-index 60) stay on top of it. */
    .nav__menu{display:block;position:fixed;inset:var(--admin-bar-h) 0 0;z-index:50;padding:104px 26px 56px;overflow-y:auto;
      background:rgba(10,10,12,.97);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);
      opacity:0;visibility:hidden;transform:translateY(-10px);
      transition:opacity .28s ease,transform .28s ease,visibility .28s}
    .nav.is-open .nav__menu{opacity:1;visibility:visible;transform:none}

    .nav__item{border-bottom:1px solid rgba(255,255,255,.09);padding:15px 0}
    .nav__item:last-child{border-bottom:0}
    .nav__menu > .nav__item > a,
    .nav__menu > .nav__item > .nav__link{font-family:'Cormorant Garamond',serif;font-size:27px;
      font-weight:600;letter-spacing:0;text-transform:none;color:#fff;opacity:1;padding:0;margin:0}
    .nav__menu > .nav__item > a[aria-current="page"]{color:var(--accent-light)}

    /* Submenus collapse inline and expand on tap — no hover to reveal them */
    .nav__submenu,.nav.is-open .nav__submenu{position:static;opacity:1;visibility:visible;transform:none;
      min-width:0;margin:0;background:none;border:0;box-shadow:none;
      -webkit-backdrop-filter:none;backdrop-filter:none;
      overflow:hidden;max-height:0;padding:0;
      transition:max-height .32s ease,padding .32s ease}
    .nav__item--has-children.is-open > .nav__submenu{max-height:360px;padding:6px 0 4px}
    .nav__submenu::before,.nav__submenu::after{display:none}
    .nav__submenu a{padding:11px 0 11px 16px}
    .nav__submenu a::before{top:9px;bottom:9px}

    /* Caret is the affordance now that the list starts closed */
    .nav__menu > .nav__item--has-children > .nav__link{display:flex;align-items:center;
      justify-content:space-between;width:100%}
    .nav__caret{display:block;width:13px;height:13px;opacity:.75;flex:0 0 auto}
  }
  /* Page must not scroll behind the open panel */
  body.nav-open{overflow:hidden}

  /* ==========================================================
     BLOCK: wcl/social-bar
     Three equal segments under the hero, divided by hairlines.
     ========================================================== */

  /* ==========================================================
     BLOCK: wcl/service-intro + wcl/service-row
     Typography-led alternating layout: each service gets its own
     band, sides swap row to row, and the image runs full-bleed to
     the outer edge of its side so a real photo drops straight in.
     No divider rules — the bands and whitespace do that work.
     ========================================================== */

  .srow{display:grid;grid-template-columns:1fr 1fr;align-items:stretch;position:relative;overflow:hidden}
  .srow--light{background:var(--paper)}
  .srow--dark{background:var(--ink)}
  /* Image leads on even rows. Order, not direction, so the DOM keeps
     content-before-image for screen readers and mobile. */
  .srow--reverse .srow__media{order:-1}

  .srow__content{display:flex;align-items:center;padding:88px 56px}
  .srow--reverse .srow__content{justify-content:flex-start}
  .srow__inner{position:relative;max-width:520px;margin-left:auto;padding-left:8px}
  .srow--reverse .srow__inner{margin-left:0;margin-right:auto}

  .srow__title,.srow__lead,.srow__inner p{position:relative;z-index:1}
  .srow__title{font-size:clamp(34px,3.6vw,46px);font-weight:600;line-height:1.06;letter-spacing:-.6px;
    margin-bottom:18px}
  /* The one-line entry point — heavier than the body beneath it */
  .srow__lead{font-size:19px;line-height:1.6;font-weight:500;margin-bottom:20px;max-width:34ch}
  .srow__inner p:not(.srow__lead){font-size:15px;line-height:1.85;font-weight:300;color:var(--text-mute)}
  .srow__inner p:not(.srow__lead) + p{margin-top:13px}

  .srow--light .srow__title,.srow--light .srow__lead{color:var(--text-dark)}
  .srow--dark .srow__title{color:#fff}
  .srow--dark .srow__lead{color:#fff}
  .srow--dark .srow__inner p:not(.srow__lead){color:#a8a7b4}

  /* Full-bleed media: no radius, fills its half edge to edge */
  .srow__media{border-radius:0;min-height:540px;background:none}
  .srow--dark .srow__media .media__ph{background:linear-gradient(150deg,#1b1b24,#0e0e15);
    color:rgba(255,255,255,.34);border-color:rgba(255,255,255,.14)}

  @media(max-width:860px){
    .srow{grid-template-columns:1fr}
    /* image above the copy on every row, whichever side it leads on */
    .srow__media,.srow--reverse .srow__media{order:-1;min-height:280px}
    .srow__content{padding:44px 24px 56px}
    .srow__inner{max-width:none;margin:0;padding-left:0}
    .srow__lead{font-size:17px;max-width:none}
  }

  /* Row link (WCM Friends → the roster page) */
  .srow__link{margin-top:18px}
  .srow__link a{font-size:13px;letter-spacing:1.5px;text-transform:uppercase;font-weight:500;
    text-decoration:none;padding-bottom:4px;border-bottom:1px solid var(--accent-light);transition:color .2s}
  .srow--light .srow__link a{color:var(--text-dark)}
  .srow--light .srow__link a:hover{color:var(--accent-deep);border-bottom-color:var(--accent-deep)}
  .srow--dark .srow__link a{color:#fff}
  .srow--dark .srow__link a:hover{color:var(--accent-light)}

  /* The same underlined link, available as a button treatment so it can sit in
     a .cta-row alongside the filled and outlined ones rather than needing its
     own control. Everything .btn gives a button is undone here: no padding,
     no border box, no bevel. What is left is the rule under the words.

     It takes its colour from the ground it is on, the way .srow__link a does,
     because it is text rather than a shape and has nothing of its own to sit
     against. Dark sections are listed explicitly; anything else is light. */
  .btn-underline{padding:0;border:0;background:none;box-shadow:none;border-radius:0;
    font-size:13px;letter-spacing:1.5px;font-weight:500;
    padding-bottom:4px;border-bottom:1px solid var(--accent-light);
    color:var(--text-dark);transition:color .2s,border-color .2s}
  .btn-underline:hover{color:var(--accent-deep);border-bottom-color:var(--accent-deep);
    transform:none;box-shadow:none}
  .srow--dark .btn-underline,
  .hero .btn-underline,
  .reel .btn-underline,
  .tiers .btn-underline,
  .extras .btn-underline,
  .ahero .btn-underline{color:#fff}
  .srow--dark .btn-underline:hover,
  .hero .btn-underline:hover,
  .reel .btn-underline:hover,
  .tiers .btn-underline:hover,
  .extras .btn-underline:hover,
  .ahero .btn-underline:hover{color:var(--accent-light);border-bottom-color:var(--accent-light)}

  /* The eyebrow alternative to the icon, for rows that are not services.
     Enlisted in the .kicker selector list further down for its size and
     tracking; only the colour is per-ground, the same pair the titles use. */
  .srow--light .srow__inner .kicker{color:var(--accent-deep)}
  .srow--dark .srow__inner .kicker{color:var(--accent-light)}

  /* Buttons, for rows that close with them rather than with a text link.
     inline-flex so a pair sits level whatever the labels are, which is the
     same reason .intro__actions and .ahero__actions do it. */
  .srow .cta-row{margin-top:30px;gap:12px}
  .srow .cta-row .btn{display:inline-flex;align-items:center;justify-content:center}

  /* Service icons — stroked with the shared brand gradient paint server,
     so they read the same on both the light and dark bands. The gradient
     elements are built from --grad by site.js; the colour after each url() is
     the paint fallback, used if that reference ever fails to resolve. Without
     one a missing paint server draws nothing at all, so the icons would just
     silently disappear rather than dropping to a flat brand colour. */
  .srow__icon{display:block;width:38px;height:38px;margin-bottom:22px;
    fill:none;stroke:url(#wcl-grad) var(--accent-deep);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
  /* SVG paint servers are referenced by id, so the dark-band ramp can't come
     from the var(--grad) override — it needs its own gradient element.
     Its fallback is --accent-light: --accent-deep is the deep accent and vanishes on --ink. */
  .srow--dark .srow__icon{stroke:url(#wcl-grad-dark) var(--accent-light)}
  @media(max-width:860px){
    .srow__icon{width:32px;height:32px;margin-bottom:18px}
  }

  /* ==========================================================
     BLOCK: wcl/service-extras — edge and bloom
     Additions to the block defined above; kept here because they
     depend on what precedes the band on the page.
     ========================================================== */
  /* WCM Friends (dark) runs straight into this band, so the gradient edge does
     double duty: brand device, and a clean boundary between two dark sections. */
  .extras::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);z-index:2}
  /* Bloom mirrored from the footer's — teal-led and on the opposite side, so the
     two dark bands feel related without looking like the same block twice. */
  .extras::after{content:'';position:absolute;left:-170px;top:-240px;width:620px;height:620px;
    border-radius:50%;pointer-events:none;z-index:0;
    background:radial-gradient(circle,rgba(var(--accent-light-rgb),.26) 0%,rgba(var(--accent-deep-rgb),.12) 46%,transparent 70%)}
  .extras__inner{position:relative;z-index:1}

  /* Parent Services page: two options rather than three */
  /* Two cards, each a true half of the 1080px container. They were already two
     across, but capped at 840px inside it, which left each card at 38% of the
     column — narrower than a third of the same container and reading as though
     a third card had gone missing. The cap is gone rather than widened, so the
     pair simply follows .svc-inner / .bopts__inner like everything else on the
     page. Home and Services both use this class, so they cannot drift. */
  .bopts__grid--two{grid-template-columns:repeat(2,1fr)}
  .bopt__pending{font-size:13px;color:var(--text-mute);font-style:italic;margin:-8px 0 20px}
  @media(max-width:860px){
    .bopts__grid--two{grid-template-columns:1fr}
  }

  /* ==========================================================
     Eyebrow / kicker — one consistent treatment site-wide.
     These had drifted to 11–12px, 3–5px tracking, weights 500/600
     and five different margins. Only the colour stays contextual
     (white in the page heroes, violet on light, gradient where used).
     ========================================================== */
  /* ADD NEW BLOCKS HERE. This selector list IS the eyebrow component — there
     is no bare .kicker rule — so a new section that writes .kicker and does
     not enlist it here silently renders as plain lowercase body text. */
  .hero__eyebrow,
  .page-head__kicker,
  .intro .kicker,
  .srow__inner .kicker,
  .elite-head .kicker,
  .svc .kicker,
  .svc-head .kicker,
  .ev-head .kicker,
  .book .kicker,
  .reel .kicker,
  .clients--all .kicker,
  .services__kicker,
  .extras__kicker,
  .abook__kicker{font-size:12px;letter-spacing:4px;text-transform:uppercase;font-weight:600;
    margin-bottom:16px}
  /* No links sit in this position — it's a label, not navigation */
  .page-head__kicker a,.hero__eyebrow a{color:inherit;text-decoration:none}

  /* ==========================================================
     BLOCK: wcl/tiers
     Column set for grouped lists — the three event-management
     services, and the three road/tour packages.
     ========================================================== */
  .tiers{position:relative;overflow:hidden;padding:76px 48px 86px;
    background:linear-gradient(180deg,#13131c 0%,#0b0b11 58%,#08080c 100%)}
  .tiers::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);z-index:2}
  .tiers::after{content:'';position:absolute;right:-170px;bottom:-240px;width:620px;height:620px;
    border-radius:50%;pointer-events:none;z-index:0;
    background:radial-gradient(circle,rgba(var(--accent-deep-rgb),.26) 0%,rgba(var(--accent-light-rgb),.10) 46%,transparent 70%)}
  .tiers__inner{position:relative;z-index:1;max-width:1080px;margin:0 auto}
  .tiers__head{margin-bottom:40px;max-width:60ch}
  .tiers__title{font-family:'Cormorant Garamond',serif;font-size:32px;font-weight:600;color:#fff;
    letter-spacing:-.4px;margin-bottom:10px}
  .tiers__lede{color:#fff;font-size:15px;line-height:1.75;font-weight:300}

  .tiers__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}
  .tier{padding:0 34px}
  .tier:first-child{padding-left:0}
  .tier:last-child{padding-right:0}
  .tier + .tier{border-left:1px solid rgba(255,255,255,.14)}
  .tier h3{font-family:'Cormorant Garamond',serif;font-size:23px;font-weight:600;color:#fff;
    letter-spacing:-.2px;margin-bottom:18px}
  .tier ul{list-style:none;margin:0;padding:0}
  .tier li{position:relative;padding-left:20px;margin-bottom:11px;
    color:#fff;font-size:14px;line-height:1.65;font-weight:300}
  .tier li::before{content:'';position:absolute;left:0;top:8px;width:5px;height:5px;border-radius:50%;
    background:var(--grad)}

  @media(max-width:860px){
    .tiers{padding:56px 24px 64px}
    .tiers__grid{grid-template-columns:1fr;gap:32px}
    .tier,.tier:first-child,.tier:last-child{padding:0}
    .tier + .tier{border-left:0;padding-top:32px;border-top:1px solid rgba(255,255,255,.14)}
  }

  /* Secondary line under a page-header intro — e.g. the booking redirect on Contact.
     Styled here rather than inline so it can be reused and restyled in one place. */
  .page-head__aside{margin-top:14px;max-width:54ch;color:#fff;line-height:1.7;font-weight:300;
    font-size:clamp(14px,0.11vw + 13.6px,15px)}
  .page-head__aside a{color:#fff;text-decoration:none;border-bottom:1px solid var(--accent-light);
    padding-bottom:2px;transition:color .2s}
  .page-head__aside a:hover{color:var(--accent-light)}

  /* ==========================================================
     Action rows on a phone
     Below 560px none of these rows can hold two buttons side by side —
     the widest pair needs 519px of viewport — so they stop pretending and
     become a single column. Full width once stacked: a button sized to its
     own label leaves a ragged left-aligned stub in a column of full-width
     content, and the shorter label ends up with the smaller tap target for
     no reason anyone can see.
     Grid rather than flex-wrap so the stack is stated rather than emergent —
     with wrap, the point at which they break depends on how long someone
     makes a label, and the two states look different for no reason.
     ========================================================== */
  @media(max-width:560px){
    .cta-row,.intro__actions,.ahero__actions{display:grid;grid-template-columns:1fr}
    .cta-row .btn,.intro__actions .btn,.ahero__actions .btn{width:100%;
      display:inline-flex;align-items:center;justify-content:center}
  }

  /* ==========================================================
     WORDPRESS ADMIN BAR
     Inert without body.admin-bar, so this has no effect on the reference
     build.

     WordPress changes the bar twice, and at two DIFFERENT widths. Read
     wp-includes/css/admin-bar.css before touching these numbers:

       <= 782px  the bar grows from 32px to 46px, still position:fixed
       <= 600px  it becomes position:absolute and scrolls away with the page

     So between 601px and 782px it is 46px AND still pinned, which is the
     case that bites: offsetting by 0 there slides the nav underneath it.
     Only below 600px does it leave, and there a permanent 46px offset
     would strand the nav below an admin bar that is no longer on screen.
     That last band keys off .is-top, which site.js already maintains as
     "scrolled to the very top" for the nav's own styling.

     .nav__menu inherits the property from .nav, which is what carries
     .is-top. .abar does not, and does not need to: it only ever appears
     once the hero has scrolled past, by which point the admin bar has
     gone with it.
     ========================================================== */
  body.admin-bar{--admin-bar-h:32px}
  @media screen and (max-width:782px){
    body.admin-bar{--admin-bar-h:46px}
  }
  @media screen and (max-width:600px){
    body.admin-bar{--admin-bar-h:0px}
    body.admin-bar .nav.is-top{--admin-bar-h:46px}
  }
