/* ---------------------------------------------------------------------------
   Yes Please — site styles

   Rewritten from the 2023 style2.css. The visual design is unchanged; what
   changed is where the colours come from. Every per-section colour rule
   (.roster_active #nav, #tv { background }, and ~120 lines like them) is gone,
   replaced by custom properties that includes/render.php emits per section and
   assets/js/site.js promotes to :root as you scroll. No section slug appears
   in a selector here, which is what lets slugs be editable data.

   Sections in this file:
     1  Tokens and reset          6  Content sections
     2  Typography                7  Roster
     3  Nav                       8  Contact
     4  Hero                      9  Responsive
     5  Chevrons                 10  Motion and print
   --------------------------------------------------------------------------- */

/* == 1. Tokens and reset =================================================== */

:root {
  --nav-w: 200px;
  --bar-h: 0px;          /* the nav becomes a top bar on small screens */
  --sidebar-w: 30%;
  --logo-w: 80;          /* hero logo width, percent of the hero. The mask
                            below is derived from it, so they can't drift. */

  /* Set by render_palette_style(), then updated live by the scroll observer. */
  --nav-accent: #E795D5;
  --nav-grad-end: #9B95E7;
  --nav-ink: #1A1A1A;

  --hero-bg: #E3D5F1;
  --hero-lqip: none;

  /* Section-scoped; these are the fallbacks before any section is active. */
  --wash-alpha: 0.7;
  --bg: #E3D5F1;
  --bg-rgb: 227, 213, 241;
  --ink: #6D5686;
  --accent: #966AC2;
  --head: #9B78BB;

  --ease: 0.3s ease-in-out;
  --radius: 30px;
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0;
  background: var(--hero-bg);
  color: black;
  font-family: "mixta-pro", Georgia, serif;
  font-style: normal;
  font-weight: 500;
  font-size: 16px;
  overflow-x: hidden;
}

#container { position: relative; }

img { max-width: 100%; }

/* Anchors land below nothing — the nav is a left rail, not a top bar — but on
   mobile it becomes a top bar, so the offset is defined with the breakpoint. */
[id] { scroll-margin-top: 0; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  z-index: 2000;
  padding: 12px 20px;
  background: #1A1A1A;
  color: white;
  font-weight: 600;
}
.skip-link:focus { top: 0; }

/* One visible focus style for the whole site. The 2023 build had none. */
a:focus-visible,
button:focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 3px;
  border-radius: 2px;
}


/* == 2. Typography ========================================================= */

p {
  font-size: 16px;
  line-height: 20px;
  margin: 0 0 20px;
}

a {
  text-decoration: none;
  border: none;
  color: black;
  transition: color var(--ease), background var(--ease), opacity var(--ease);
}

h3 {
  color: white;
  font-size: clamp(24px, 4vw, 40px);
  margin: 0 0 30px;
}


/* == 3. Nav ================================================================ */

#nav {
  position: fixed;
  z-index: 1000;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--nav-w);
  overflow: hidden;      /* clips the panel below while it is off to the left */
  color: var(--nav-ink);
  text-align: left;
  background: transparent;
  transition: color var(--ease);
}

/* The nav's colour lives here rather than on #nav itself, so it can slide in
   from the left the way the heading panel does. On the hero it is off-screen
   and the menu sits straight on the video.

   Two layers: the accent as a background-COLOR so it can interpolate between
   sections, and the fade to the shared periwinkle end stop as an image on top.
   The gradient is why yp_nav_ink() judges contrast against the midpoint of the
   two rather than the accent — the links are anchored to the bottom. */
#nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--nav-accent);
  background-image: linear-gradient(to bottom, transparent, var(--nav-grad-end));
  transform: translateX(-100%);
  transition: transform var(--ease), background-color var(--ease);
}
.content_active #nav::before { transform: translateX(0); }
/* Opening the mobile menu brings the bar's colour in with it — the overlay
   below is opaque, so a transparent bar above it would look severed. */
.nav-open #nav::before { transform: translateX(0); }

/* On the hero the menu sits straight on the footage. Sampling behind the menu
   strip gives luminance 51 to 187, so no colour is reliably readable there and
   no contrast ratio can be claimed — white is simply the better bet against a
   mean of ~102. Shadows were tried and dropped: they don't suit the design,
   and this audience will cope. */
body:not(.content_active):not(.nav-open) #nav,
body:not(.content_active):not(.nav-open) #nav-menu a,
body:not(.content_active):not(.nav-open) #introfooter h2 {
  color: #fff;
}
body:not(.content_active):not(.nav-open) .nav-toggle span {
  background: #fff;
}

#top_nav_home {
  display: block;
  position: absolute;
  inset: 30px 40px auto 40px;
  z-index: 20;
  opacity: 0;
  transition: opacity var(--ease);
}
#top_nav_home img { display: block; height: 80%; }
.content_active #top_nav_home { opacity: 1; }

.nav-wordmark {
  color: var(--nav-ink);
  font-weight: 700;
  font-size: 20px;
}

#introfooter {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--nav-w);
  text-align: center;
  color: var(--nav-ink);
  opacity: 1;
  transition: opacity var(--ease);
}
.content_active #introfooter { opacity: 0; }

#introfooter h2 {
  margin: 0;
  padding: 25px;
  width: 100%;
  font-weight: 800;
  font-size: clamp(16px, 1.6vw, 22px);
  line-height: 1.25;
  text-align: left;
  color: var(--nav-ink);
}

#nav-menu ul {
  position: absolute;
  bottom: 20px;
  left: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

#nav-menu li {
  display: block;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-size: clamp(16px, 1.6vw, 22px);
  line-height: 20px;
}

#nav-menu a {
  display: block;
  padding: 5px;
  overflow: hidden;
  font-weight: 600;
  color: var(--nav-ink);
  opacity: 0.85;
}
#nav-menu a:hover,
#nav-menu a.current {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
}

/* Hamburger — hidden until the sidebar collapses. */
.nav-toggle {
  display: none;
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  z-index: 30;
  width: 44px;
  height: 44px;
  padding: 10px;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  height: 2px;
  margin: 4px 0;
  border-radius: 2px;
  background: var(--nav-ink);
  transition: transform var(--ease), opacity var(--ease);
}
.nav-open .nav-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }


/* == 4. Hero and the fixed video ========================================== */

/* The footage is pinned to the viewport behind the whole page; the sections
   scroll over it. Deliberately NOT inside #container — a fixed child there
   would still work, but keeping it a sibling makes the stacking obvious:
   this layer is at z-index 0, everything in the container is above it.

   Full-bleed: the nav has no background on the hero, so the footage runs
   behind it. This also keeps the layer aligned with #video_mask and the logo,
   which span the whole hero — inset one and not the others and the cut-out
   drifts off-centre. */
#video-layer {
  position: fixed;
  inset: var(--bar-h) 0 0 0;
  z-index: 0;
  overflow: hidden;
  background: var(--hero-bg) var(--hero-lqip) center / cover no-repeat;
  pointer-events: none;
}

#hero-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

#hero {
  position: relative;
  z-index: 5;
  margin-top: var(--bar-h);
  height: calc(100vh - var(--bar-h));
  height: calc(100svh - var(--bar-h));   /* stops the iOS URL-bar jump */
  overflow: hidden;
  /* Transparent: the fixed layer behind provides the picture. */
}

/* The logo cut-out: the footage is drained of colour everywhere except through
   the logo shape. Scrolls away with the hero, as the logo does — only the
   footage stays put.

   Two mask layers, solid minus hole. The old single-layer version stretched a
   mask to `cover` the hero, which only lined up while the logo was full width;
   shrink the logo and the cut-out no longer matches it, and you can't just
   scale the mask down because then it stops covering the hero at all.

   Splitting it means the hole can be sized off --logo-w — so it tracks the
   logo at any size — while the solid layer still covers everything.

   tools/build-hero-mask.php registers the hole against the logo and writes it
   onto a canvas identical to images/logo_glow.png, so the hole layer is simply
   drawn at the logo's own size and position. Re-run that tool if either piece
   of artwork changes; don't hand-tune numbers here. */
#video_mask {
  position: absolute;
  inset: 0;

  -webkit-mask-image: linear-gradient(#000, #000), var(--hero-mask);
  mask-image: linear-gradient(#000, #000), var(--hero-mask);
  -webkit-mask-size: 100% 100%, calc(var(--logo-w) * 1%) auto;
  mask-size: 100% 100%, calc(var(--logo-w) * 1%) auto;
  -webkit-mask-position: center, center;
  mask-position: center, center;
  -webkit-mask-repeat: no-repeat, no-repeat;
  mask-repeat: no-repeat, no-repeat;
  -webkit-mask-composite: source-out, source-over;
  mask-composite: subtract, add;

  -webkit-backdrop-filter: saturate(0.3);
  backdrop-filter: saturate(0);
}

/* Without layer compositing the hole can't be punched, and a hero that is
   entirely drained of colour is worse than one that isn't — so drop it. */
@supports not (mask-composite: subtract) {
  #video_mask { display: none; }
}

#hero h1 {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
}

#logo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--logo-w) * 1%);
  transform: translate(-50%, -50%);
}

.hero-wordmark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: clamp(40px, 10vw, 120px);
  font-weight: 800;
  white-space: nowrap;
}


/* == 5. Chevrons =========================================================== */

.next {
  position: absolute;
  right: 20px;
  bottom: 0;
  z-index: 4;
  width: 50px;
  text-align: center;
}

.next a {
  display: inline-block;
  padding: 5px 5px 15px;
  border-radius: var(--radius) var(--radius) 0 0;
  background: rgba(0, 0, 0, 0);
  /* Was `white`, which measured 1.39:1 against the pastel backgrounds — the
     chevrons were effectively invisible until hover. Not --accent either:
     the accents are far too light for an icon (news is 1.20:1 on its own
     background). --ink is the one value the AA floor guarantees. */
  color: var(--ink);
}
.next a:hover {
  transform: translate(0, 5px);
  background: white;
}
/* The hero chevron is over the footage rather than a flat colour. */
#hero .next a { color: #fff; }
#hero .next a:hover { color: var(--ink); }

.chevron-icon { display: block; width: 30px; height: 30px; }


/* == 6. Content sections =================================================== */

.content_block {
  position: relative;
  z-index: 6;
  min-height: 100vh;
  padding-left: calc(var(--sidebar-w) + var(--nav-w));
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: var(--ink);
}

/* The wash lives on a pseudo-element, not on .content_block itself.
   backdrop-filter makes an element the containing block for any fixed
   descendant, and .content_sidebar is fixed — putting the filter on the block
   would quietly turn the heading panel into an absolutely positioned one and
   it would scroll away instead of staying pinned. A pseudo-element can't have
   element children, so the problem disappears. */
.content_block::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* A wash rather than a fill, so the fixed video reads through it. */
  background: rgba(var(--bg-rgb), var(--wash-alpha));
  /* Drain the colour from the footage behind, and squeeze it into its light
     half. The squeeze is not cosmetic: at 70% opacity over unrestricted
     footage the body text falls to 2.17:1, which is unreadable. Bounding the
     backdrop lets includes/colour.php guarantee 4.5:1 against the worst case
     for about six points of extra text darkness — see YP_WASH_FLOOR. */
  -webkit-backdrop-filter: grayscale(1) contrast(0.3) brightness(1.6);
  backdrop-filter: grayscale(1) contrast(0.3) brightness(1.6);
}

/* Without backdrop-filter there is no way to bound what shows through, so
   fall back to the solid colour the palette was derived from. */
@supports not ((backdrop-filter: grayscale(1)) or (-webkit-backdrop-filter: grayscale(1))) {
  .content_block::before { background: var(--bg); }
}

/* Deliberately no `overflow: hidden` here. It existed only to contain the
   long-dead .content_image, and it silently clipped anything taller than the
   viewport — a trap now that the copy is client-editable. */

.content_block.is-active { z-index: 10; }

.content_sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  /* Fully off the left edge. It used to rest at -30% + nav width, which was
     invisible only because the nav had an opaque background covering it —
     now that the nav is clear on the hero, that overhang showed as a white
     slab behind the menu. */
  left: calc(var(--sidebar-w) * -1);
  width: var(--sidebar-w);
  display: block;
  text-align: center;
  color: black;
  background: rgba(255, 255, 255, var(--wash-alpha));
  background: white;
  transition: left var(--ease);
}
@supports not ((backdrop-filter: grayscale(1)) or (-webkit-backdrop-filter: grayscale(1))) {
  .content_sidebar { background: white; }
}
.content_active .content_sidebar { left: var(--nav-w); }

.content_sidebar h3 {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: none;
  width: 100%;
  margin: 0;
  padding: 0 20px;
  font-weight: 800;
  font-size: clamp(22px, 3.4vw, 40px);
  line-height: 1.1;
  color: var(--head);
}
.is-active .content_sidebar h3 { display: block; }

.content_content {
  padding: 50px;
  text-align: left;
  font-family: "mixta-didone", Georgia, serif;
  column-gap: 50px;
}
/* Two columns only where there's genuinely room for two readable measures. */
@media (min-width: 1100px) {
  .content_content[data-columns="2"] { columns: 2; }
}

.content_content p {
  max-width: 700px;
  min-width: 100%;
  margin: 0 auto 20px;
  padding: 0;
  font-size: clamp(17px, 1.5vw, 20px);
  line-height: 1.5;
}

.content_content a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.content_content a:hover { color: black; }

.content_content ul,
.content_content ol { font-size: clamp(17px, 1.5vw, 20px); line-height: 1.5; }

.content_content img { height: auto; border-radius: 4px; }

.content_content figure { margin: 0 0 20px; }
.content_content figcaption { font-size: 15px; opacity: 0.8; }


/* == 7. Roster ============================================================= */

#roster-filter {
  margin: 0 -10px 30px 0;
  font-size: 18px;
  color: inherit;
}
#roster-filter span { margin-right: 10px; }

#roster-filter button {
  margin: 0 10px 0 0;
  padding: 2px 4px;
  border: 0;
  border-radius: 3px;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 18px;
  cursor: pointer;
  transition: color var(--ease), opacity var(--ease);
}
#roster-filter button:hover,
#roster-filter button[aria-pressed="true"] {
  color: black;
  text-decoration: underline;
  text-underline-offset: 4px;
}

#roster-list { margin-left: -5px; }

.roster-group + .roster-group { margin-top: 26px; }

.roster-group-title {
  margin: 0 0 8px 5px;
  font-family: "mixta-pro", Georgia, serif;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.65;
}

.roster-names { margin: 0; }

#roster-list a,
#roster-list span {
  display: inline-block;
  margin: 0 5px;
  color: inherit;
  font-weight: 600;
  font-family: "mixta-pro", Georgia, serif;
  text-decoration: none;
  transition: opacity var(--ease), color var(--ease);
}
#roster-list a:hover { color: black; }

#roster-list .top_artist {
  font-size: clamp(20px, 2.4vw, 30px);
  margin: 0 15px 0 5px;
}

/* The dimming rules themselves are generated per filter key in
   render_palette_style(), so adding a channel in the admin needs no CSS. */


/* == 8. Contact ============================================================ */

.email a {
  display: inline-block;
  margin-top: 30px;
  padding: 20px;
  border-radius: 60px;
  background: white;
  color: black;
  font-size: clamp(20px, 2vw, 25px);
  font-weight: 700;
  text-decoration: none;
}
.email a:hover {
  background: var(--ink);
  color: white;
}

#social_links {
  margin-top: 35px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

/* Inline SVG, not the old socialicons webfont — which had no glyph rules for
   .facebook/.instagram/.twitter, so these rendered as empty circles. */
.socialicon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: white;
  color: black;
}
.socialicon:hover {
  background: var(--ink);
  color: white;
}
.social-icon { width: 24px; height: 24px; display: block; }


/* == 9. Responsive ========================================================= */

/* Sidebar heading panel becomes a top band; the rail stays. */
@media screen and (max-width: 1000px) {
  .content_sidebar {
    position: absolute;
    top: 0;
    bottom: auto;
    left: var(--nav-w);
    width: calc(100% - var(--nav-w));
    height: 180px;
  }
  .content_active .content_sidebar { left: var(--nav-w); }
  .content_sidebar h3 { display: block; }
  .content_block { padding-left: var(--nav-w); padding-top: 180px; }
}

@media screen and (max-width: 760px) {
  .next { display: none; }
}

/* Below 760px the rail becomes a top bar with a real menu. The 2023 build
   just shrank the rail to 100px and left it there — 27% of a 375px screen,
   permanently, with no way to dismiss it. */
@media screen and (max-width: 760px) {
  :root { --nav-w: 0px; --bar-h: 64px; }

  #nav {
    right: 0;
    bottom: auto;
    width: 100%;
    height: 64px;
    overflow: visible;
    background: rgba(255,255,255,0.4);
  }
  #nav::before { display: none; }

  #top_nav_home {
    inset: 0 auto 0 16px;
    display: flex;
    align-items: center;
    width: 120px;
    opacity: 1;
  }

  #introfooter { display: none; }

  .nav-toggle { display: block; }

  #nav-menu {
    position: fixed;
    inset: 64px 0 0 0;
    background: var(--nav-accent);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--ease), transform var(--ease), visibility var(--ease);
    overflow-y: auto;
  }
  .nav-open #nav-menu {
    transform: none;
    opacity: 1;
    visibility: visible;
  }

  #nav-menu ul {
    position: static;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  #nav-menu li { font-size: 26px; line-height: 1.5; }
  #nav-menu a { padding: 10px 4px; }

  /* Anchors must clear the fixed top bar. */
  [id] { scroll-margin-top: var(--bar-h); }


  .content_sidebar {
    position: static;
    height: auto;
    width: 100%;
    padding: 28px 25px 0;
    text-align: left;
    background: transparent;
  }
  .content_sidebar h3 {
    position: static;
    transform: none;
    display: block;
    padding: 0;
    color: var(--head);
  }
  .content_active .content_sidebar { left: auto; }

  .content_block {
    padding-left: 0;
    padding-top: 64px;
    min-height: 100svh;
  }

  .content_content { padding: 25px; }
  .email a { padding: 14px 20px; }
  .socialicon { width: 48px; height: 48px; }
}

@media screen and (max-width: 420px) {
  #social_links { gap: 10px; }
  #roster-filter,
  #roster-filter button { font-size: 16px; }
}


/* == 10. Motion and print ================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* site.js also declines to start the video; this covers the poster case. */
  #hero-video { display: none; }
  #video-layer {
    background-image: var(--hero-poster);
    background-size: cover;
    background-position: center;
  }
}

@media print {
  .content_block::before { background: var(--bg) !important; backdrop-filter: none !important; }
  .content_sidebar { background: white !important; backdrop-filter: none !important; }
  #nav, .next, #video-layer, #video_mask { display: none !important; }
  .content_block { min-height: 0; padding: 0; page-break-inside: avoid; }
  .content_sidebar { position: static; width: auto; }
  .content_content { columns: 1; padding: 0; }
}
