/* colors_and_type.css is loaded directly from app/layout.tsx as a sibling
   <link> tag, so it's already in the cascade by the time this stylesheet
   parses. The previous @import here pointed at /assets/colors_and_type.css
   (legacy path) and 404'd on every page load. */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg-1);
  color: var(--fg-1);
  font-family: var(--font-body);
  font-size: var(--fs-16);
  line-height: var(--lh-loose);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; border: 0; background: none; color: inherit; }
a { color: inherit; text-decoration: none; }
input, textarea, select { font: inherit; color: inherit; }

/* ============ LAYOUT ============ */
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--sp-5);
}
.container-narrow {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 0 var(--sp-5);
}
section { padding: var(--sp-8) 0; }
@media (max-width: 720px) { section { padding: var(--sp-7) 0; } }

.eyebrow {
  font-family: var(--font-body);
  font-weight: var(--fw-medium);
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--fg-muted-text);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.eyebrow::before {
  content: "✦";
  color: var(--accent);
  font-size: 10px;
}

.section-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.25rem, 4.5vw, var(--fs-56));
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--fg-1);
  margin: var(--sp-3) 0 var(--sp-5);
  text-wrap: balance;
}
.section-title em {
  font-family: var(--font-script);
  font-style: normal;
  font-size: 1.25em;
  line-height: 0.9;
  color: var(--accent);
}

/* Per-section accent rotation: each section gets its own brand color */
#about .section-title em,
#about .eyebrow::before { color: var(--bm-purple); }
#music .section-title em,
#music .eyebrow::before { color: var(--bm-pink-lavender); }
#videos .section-title em,
#videos .eyebrow::before { color: var(--bm-purple); }
#videos .section-title em.alt { color: var(--bm-teal); }
#shows .section-title em,
#shows .eyebrow::before { color: var(--bm-blue); }
#gallery .section-title em,
#gallery .eyebrow::before { color: var(--bm-teal); }
.newsletter .section-title em,
.newsletter .eyebrow::before { color: var(--bm-pink); }
.section-lead {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--fs-20);
  line-height: var(--lh-normal);
  color: var(--fg-2);
  max-width: 60ch;
  margin: 0;
}

.section-head { margin-bottom: var(--sp-7); }

:root {
  /* The nav's height, in one place: it is both the element's own height and
     the distance an in-page anchor has to clear. Two hardcoded 64s would
     eventually disagree. Unconditional — no breakpoint changes it today,
     and if one ever does it overrides here rather than in two places. */
  --nav-h: 64px;
}

/* ============ TOP BANNERS ============ */
/* Server-rendered above .nav in app/page.tsx. The wrapper sticks above
   the nav so multiple banners stack cleanly instead of fighting for top:0. */
.site-banner-stack {
  position: sticky; top: 0; z-index: 60;
}
/* A banner carrying album art is 100–200px tall. Pinned, that plus the nav
   would hold a quarter of a phone screen hostage for the whole page — so a
   tall banner scrolls away and the nav takes top: 0 behind it. The thin
   text-only bar, which is what #320 pinned above the nav, is unchanged.
   site.js publishes --banner-h: 0 for this case by reading the stack's
   COMPUTED position rather than looking for this class, so the offset and
   the layout cannot disagree about which mode is in effect. */
.site-banner-stack.is-tall { position: relative; }
/* #493: on a phone even the text bar wraps to two lines (~103px), and with
   the 64px nav that pinned 167 of 844px -- a fifth of the screen -- for the
   whole page. Below 600px every banner scrolls away with the page and only
   the nav stays; trackBannerHeight() in site.js sees the non-sticky stack
   and drops the nav's offset to 0 on its own. The nav is solid there too:
   at 82% the text scrolling under it read through. */
@media (max-width: 600px) {
  .site-banner-stack { position: relative; }
}
.live-banner,
.announcement-banner {
  display: flex; align-items: center; justify-content: center;
  gap: 12px; flex-wrap: wrap;
  padding: 10px 20px;
  /* No shared `color` here on purpose. It used to be #fff, which both
     banners now override — leaving it would hand a future third banner
     white text on whatever ground it chose, which is the bug this change
     started from. Each banner states its own ink against its own
     background. */
  /* Manrope, not Instrument Serif. Instrument Serif ships ONE weight (400),
     and this bar asks for 650, 700 and 850 — so every glyph here was a
     synthetic bold, the browser smearing a 400 serif to fake weight. At
     14px, spaced, over a gradient, that is the blur. Manrope is variable
     300-800, so these weights render as real cuts; it is also what the
     brand guide assigns to labels and supporting information, which is
     what a banner is. */
  font-family: var(--font-body);
  font-size: 14px; font-weight: 700; letter-spacing: .06em;
  text-decoration: none;
  box-shadow: 0 1px 0 rgba(0, 0, 0, .08);
  transition: filter .15s ease;
}
.live-banner {
  /* Solid teal, the core identity color — /press says "use teal more often
     than pink when only one brand cue is needed", and a LIVE bar is exactly
     one cue. It also fixes the contrast: the old pink-to-purple gradient
     could not carry white OR dark text across its whole width (white 1.88
     at the pink end, dark 3.14 at the purple end), because the palette's
     pink was lightened to #FDA2C5 while this rule still assumed the deep
     #e64980 in its fallback. On flat teal, dark ink measures 6.93.
     Solid-vs-gradient also keeps it distinct from the announcement bar. */
  background: var(--accent, #3EB7B2);
  color: var(--fg-1, #1D1D1C);
  text-transform: uppercase;
}
.live-banner:hover { filter: brightness(1.06); }
.announcement-banner {
  text-transform: none;
  /* --ann-base and --ann-ink exist so "Normal" and "Default color" can be
     real. The size and color classes below are written against these, not
     against the inherited value — otherwise clearing a color inside a
     colored run just inherits that run's color back, and "Normal" inside
     a Large run means 85% of Large. One owner for the base size: the phone
     override changes --ann-base, not font-size. */
  --ann-base: 14px;
  font-size: var(--ann-base);
  /* Fallback, not decoration: --ann-ink is set by the bg-* class, and an
     undefined custom property with no fallback DROPS the whole declaration
     rather than erroring — the bar would quietly inherit the page's text
     color. That failure is already in this codebase's history (--bg-0,
     2026-08-25), so it gets a floor here. */
  color: var(--ann-ink, var(--fg-1, #1D1D1C));
}

/* ---- The bar's background, chosen in the admin ----
   Every one of these states its own ink, because the ink is what makes the
   color choices above it legible. The measured contrasts are on each rule;
   they are the floor the editor's color swatches are checked against. */

/* Default, and what every banner authored before this existed still gets.
   Dark ink, not white: this gradient runs teal to light pink, and white on
   it measures 2.44:1 at the teal end and 1.88:1 at the pink end — against
   4.5:1 for text this size. Dark ink on the SAME gradient measures 6.93 to
   8.96, so the brand colors are untouched and the words are readable.
   (The old --accent-warm fallback here was #C66B45, a terracotta left over
   from before the palette moved to #FDA2C5. Live it never applied, because
   --accent-warm is defined — but a stale fallback is exactly what made the
   .live-banner rule lie about its own contrast in #322.) */
.announcement-banner.bg-brand {
  background: linear-gradient(90deg, var(--accent, #3EB7B2) 0%, var(--accent-warm, #FDA2C5) 100%);
  --ann-ink: var(--fg-1, #1D1D1C);
}
/* Flat teal — the core identity color on its own. Dark ink: 6.93. */
.announcement-banner.bg-teal {
  background: var(--accent, #3EB7B2);
  --ann-ink: var(--fg-1, #1D1D1C);
}
/* Near-black. The one background where the light and mid palette colors
   are readable, so it is the right pick behind album art. Off-white on it
   measures 16.6. */
.announcement-banner.bg-ink {
  background: var(--bm-text-primary, #1D1D1C);
  --ann-ink: var(--bm-text-light, #FCFBFA);
}
/* Paper. Quiet, and the only one that needs a rule under it — without the
   border it dissolves into the nav, which is the same off-white. */
.announcement-banner.bg-paper {
  background: var(--bm-surface, #FCFBFA);
  --ann-ink: var(--bm-text-primary, #1D1D1C);
  border-bottom: 1px solid var(--border, #E8E5E0);
}

/* ---- Album art ----
   Sizes are named for how big they land on a desktop screen: ~1in, ~1.5in,
   ~2in at the CSS reference 96dpi. clamp() is what answers "and on mobile?"
   — the vw term shrinks the art with the viewport and the floor keeps it
   from turning into a stamp on a narrow phone. */
.announcement-banner-art {
  flex: 0 0 auto;
  object-fit: cover;
  border-radius: 6px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .22);
  /* Square, because it is album art. object-fit crops a photo that isn't. */
  aspect-ratio: 1 / 1;
}
.announcement-banner-art.size-sm { width: clamp(48px, 13vw,  96px); }
.announcement-banner-art.size-md { width: clamp(60px, 17vw, 144px); }
.announcement-banner-art.size-lg { width: clamp(72px, 22vw, 192px); }

/* The label and the message. Without art this wrapper is transparent to the
   layout — same row, same centering, same gap as before it existed. With
   art, the two stack beside the cover so a 2in image doesn't sit next to a
   single centred line. */
.announcement-banner-body {
  display: flex; align-items: center; justify-content: center;
  gap: 12px; flex-wrap: wrap;
  min-width: 0;
}
.announcement-banner.has-art {
  gap: 18px;
  padding: 14px 20px;
}
.announcement-banner.has-art .announcement-banner-body {
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.announcement-banner.has-art .announcement-banner-msg { text-align: left; }
.announcement-banner-label {
  font-size: 12px;
  font-weight: 850;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: 3px 8px;
  /* The border alone is softened. `opacity` here would dim the LABEL TEXT
     with it, and at 11px that drops it to ~4.4:1 over the teal half —
     under the 4.5 this change exists to clear. */
  border: 1px solid rgba(29, 29, 28, .55);
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  border-radius: 999px;
}
.announcement-banner-msg {
  font-weight: 650;
  letter-spacing: .02em;
  text-align: center;
}
.announcement-banner-msg a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

/* ---- The countdown (#458) ----
   Flip-clock tiles after the words: dark rounded cards, a seam across the
   middle, big light numerals, brand-colored unit labels beneath. The
   reference the artist picked was graphite-and-amber; this is the same
   object in her palette — ink cards, off-white digits, teal labels.

   The card is its own dark surface on EVERY banner background rather than
   inheriting --ann-ink. That is deliberate: the tiles read as a clock
   because they contrast with the bar they sit on, and on bg-ink they would
   otherwise vanish into it. The teal label is the one color that clears
   4.5:1 on this card (7.4) while still being a brand cue.

   It also lives on `.announcement-editor` previews in the admin, which is
   why nothing here depends on a variable only the live bar defines. */
.ann-countdown {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cd-gap);
  flex: 0 0 auto;
  /* MIDLINE ALIGNMENT. The banner centers each child's whole box, and this
     child is taller than the digits: the labels hang below them (and a
     caption sits above). Centering the box therefore lifts the digits off
     the line the announcement text sits on — visibly, by half the label.
     The clock is pushed back down by exactly that difference, so the middle
     of the numbers meets the middle of the words.

     Every term is a ratio of --cd, the one size the whole clock is built
     from, so this stays true at all three sizes and on a phone. */
  --cd-gap: calc(var(--cd) * .12);
  --cd-label-box: calc(var(--cd) * .468);   /* label line box */
  --cd-caption-box: calc(var(--cd) * .546); /* caption line box */
  --cd-shift: calc((var(--cd-label-box) + var(--cd-gap)) / 2);
  transform: translateY(var(--cd-shift));
}
/* With a caption the block also grows upward, which cancels most of the
   drop — the remaining correction is half the difference between them. */
.ann-countdown.has-caption {
  --cd-shift: calc((var(--cd-label-box) - var(--cd-caption-box)) / 2);
}
.ann-countdown-caption {
  font-size: calc(var(--cd) * .42);
  line-height: 1.3;
  font-weight: 750;
  letter-spacing: .14em;
  text-transform: uppercase;
  /* Inherits the bar's ink, so the caption belongs to the announcement
     above it rather than to the cards below it. */
  opacity: .85;
}
.ann-countdown-tiles {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--cd) * .3);
}
.ann-countdown-unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cd-gap);
}
/* Small / Medium / Large. One multiplier, because every measurement in the
   clock is an em on the tile's font-size — the cards, the digits, the labels
   and the gaps all follow it. Large is the size the clock shipped at, so a
   banner set up before the control existed is unchanged by it. */
/* --cd is the ONE measurement the clock is built from: the digits are set at
   it, and the cards, labels, caption, gaps and the midline correction above
   are all ratios of it. Size is therefore a single multiplier, and the phone
   override changes the base term alone. Large is the size the clock shipped
   at, so a banner set up before the control existed is unchanged by it. */
.ann-countdown { --ann-cd-scale: .78; --cd: calc(clamp(20px, 5.2vw, 34px) * var(--ann-cd-scale)); }
.ann-countdown.size-sm { --ann-cd-scale: .6; }
.ann-countdown.size-md { --ann-cd-scale: .78; }
.ann-countdown.size-lg { --ann-cd-scale: 1; }
.ann-countdown-tile {
  font-family: var(--font-body);
  font-size: var(--cd);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  /* Tabular figures keep the tile from breathing between "11" and "07";
     the min-width keeps a two-digit card the same size as a three-digit
     one's neighbours when a countdown runs past 99 days. */
  min-width: 1.85em;
  padding: .22em .18em;
  text-align: center;
  color: var(--bm-text-light, #FCFBFA);
  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, .10) 0%,
      rgba(255, 255, 255, .10) calc(50% - .5px),
      rgba(0, 0, 0, .34) calc(50% - .5px),
      rgba(0, 0, 0, .34) calc(50% + .5px),
      rgba(255, 255, 255, 0) calc(50% + .5px),
      rgba(255, 255, 255, 0) 100%),
    var(--bm-text-primary, #1D1D1C);
  border-radius: .22em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .13),
    0 2px 6px rgba(0, 0, 0, .28);
  /* The seam is drawn in the gradient above rather than as a border, so it
     stays a hairline at every tile size. */
}
/* The labels sit on the BAR, not on the card, so they take the bar's own ink
   — the same value every other word up there uses. The reference art put
   them in amber, and the brand answer to amber is teal; teal is also the
   background of one of the four bars and half the gradient of another, where
   a teal label is invisible. Ink is readable on all four by construction. */
.ann-countdown-label {
  /* Ratio of --cd, not an em of the bar: the midline correction above is
     computed from this exact line box, so the two must be written against
     the same term or the alignment drifts with the banner's font size. */
  font-size: calc(var(--cd) * .36);
  line-height: 1.3;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ann-ink, #1D1D1C);
  opacity: .82;
}
/* The midline correction moves the clock with a transform, which does not
   take part in layout — so the bar has to be told to leave room, or the
   labels hang past its bottom edge and into the nav. The reserve is the
   largest correction any size produces (half a label line box at the largest
   --cd), which is why it is a flat value rather than another ratio: the bar
   cannot see the child's variables. */
.announcement-banner:has(.ann-countdown) { padding-bottom: 22px; }

/* The flip. The top half tips forward for a moment as the number changes —
   enough to read as a flip clock, short enough not to be noise once a
   second. countdown.js restarts it by removing and re-adding the class. */
@keyframes ann-countdown-flip {
  0%   { transform: perspective(220px) rotateX(0deg); }
  45%  { transform: perspective(220px) rotateX(-13deg); }
  100% { transform: perspective(220px) rotateX(0deg); }
}
.ann-countdown-tile.is-flipping {
  animation: ann-countdown-flip .34s ease-out;
  transform-origin: 50% 50%;
}
/* Respect the system setting: the number still changes, it just doesn't
   move. */
@media (prefers-reduced-motion: reduce) {
  .ann-countdown-tile.is-flipping { animation: none; }
}

/* ---- Formatting the artist applies to a run of banner text ----
   Emitted by the editor as <span class="ann-f-… ann-s-… ann-c-…"> and
   allowed through by lib/sanitize-html.js on the `ann-` prefix. Sizes are
   in `em` so they scale with the banner's own responsive font-size instead
   of pinning a phone to a desktop measurement. */
.ann-f-body    { font-family: var(--font-body); }
/* Instrument Serif ships ONE weight. The banner's base 700 is therefore
   synthetic on it — the exact smear #321 removed — so a display run resets
   to the real cut and drops the tracking a serif does not want. */
.ann-f-display { font-family: var(--font-display); font-weight: 400; letter-spacing: .01em; }
/* Bellaboo is a script face and reads small at a shared size. */
/* No font-size here, deliberately. It would sit on the same element as the
   size class and one would silently win: picking Large and then Script
   dropped the Large. Bellaboo does read small — the Size control next to it
   is the answer, not a second rule fighting over the same property. */
.ann-f-script  { font-family: var(--font-script); font-weight: 400; letter-spacing: 0; }

/* Multiples of the bar's own base, not of the parent — so Normal is Normal
   wherever it lands, and Extra large is the same size whether or not it is
   nested inside something else. */
/* The fallback is load-bearing, not decoration. --ann-base is defined on
   .announcement-banner, and the ADMIN'S EDIT BOX is .announcement-editor — a
   different element that never had it. calc() with an undefined custom
   property is invalid, so the browser dropped the whole declaration and
   every size here did nothing in the box being typed into, while working
   correctly in the preview beside it. Exactly the failure the --ann-ink rule
   two hundred lines up carries a warning about; the warning was written and
   then not applied here. */
.ann-s-sm { font-size: calc(var(--ann-base, 14px) * 0.85); }
.ann-s-md { font-size: var(--ann-base, 14px); }
.ann-s-lg { font-size: calc(var(--ann-base, 14px) * 1.35); }
.ann-s-xl { font-size: calc(var(--ann-base, 14px) * 1.9); }

/* "Default color" — back to whatever ink the chosen background carries.
   A class that said `color: inherit` would inherit the enclosing run's
   color, which is the thing being cleared. */
.ann-c-none     { color: var(--ann-ink, var(--fg-1, #1D1D1C)); }
.ann-c-ink      { color: var(--bm-text-primary, #1D1D1C); }
.ann-c-charcoal { color: var(--bm-text-secondary, #282728); }
.ann-c-paper    { color: var(--bm-text-light, #FCFBFA); }
.ann-c-teal     { color: var(--bm-teal, #3EB7B2); }
.ann-c-pink     { color: var(--bm-pink, #FDA2C5); }
.ann-c-lavender { color: var(--bm-pink-lavender, #E3A4EF); }
.ann-c-blue     { color: var(--bm-blue, #1E4FB3); }
.ann-c-purple   { color: var(--bm-purple, #625DC7); }
.live-banner-dot {
  width: 8px; height: 8px; border-radius: 50%;
  /* Was white with a white pulse, which only read against the old dark
     gradient. On teal it follows the text. */
  background: currentColor;
  animation: live-banner-pulse 1.4s ease-out infinite;
}
@keyframes live-banner-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(29, 29, 28, .55); }
  70%  { box-shadow: 0 0 0 10px rgba(29, 29, 28, 0); }
  100% { box-shadow: 0 0 0 0 rgba(29, 29, 28, 0); }
}
.live-banner-label { font-weight: 800; }
.live-banner-gig { font-weight: 700; letter-spacing: .03em; text-transform: none; }
.live-banner-msg { font-weight: 600; letter-spacing: .04em; text-transform: none; }
.live-banner-arrow { font-weight: 700; }
@media (max-width: 480px) {
  .live-banner,
  .announcement-banner {
    padding: 8px 12px;
    gap: 8px;
  }
  .live-banner { font-size: 12.5px; }
  /* Through the variable, so the size classes shrink with the base instead
     of leaving "Extra large" at its desktop measurement on a phone. */
  .announcement-banner { --ann-base: 12.5px; }
  .live-banner-msg { display: none; }
  .announcement-banner-label {
    font-size: 10px;
    padding: 2px 7px;
  }
  /* One line moves the whole clock — cards, digits, labels, gaps and the
     midline correction, all of which are ratios of --cd. */
  .ann-countdown { --cd: calc(clamp(18px, 6.4vw, 26px) * var(--ann-cd-scale)); }
  .announcement-banner-msg {
    flex: 1 1 100%;
    line-height: 1.3;
  }
  /* .announcement-banner.has-art is two classes and outranks the padding
     set on .announcement-banner above, so the phone override has to match
     it. Without this the art variant kept its 14px/20px desktop padding on
     a 360px screen. */
  .announcement-banner.has-art {
    padding: 10px 12px;
    gap: 12px;
  }
}

/* The nav sticks BELOW the banner stack, not underneath it.
   Both were pinned at top: 0, so they occupied the same place and the
   banner — higher z-index — simply covered the nav once you scrolled. The
   old note here called that acceptable because the banner is the louder
   element; it is not, because it costs you the navigation for the whole
   page. Offsetting the nav by the stack's measured height keeps both.
   --banner-h is published by site.js and falls back to 0 when there is no
   banner, which is the ordinary case. */

/* An in-page anchor has to clear whatever is pinned above it — the nav
   always, and the banner stack when there is one. */
html { scroll-padding-top: calc(var(--banner-h, 0px) + var(--nav-h)); }

/* ============ NAV ============ */
.nav {
  position: sticky; top: var(--banner-h, 0px); z-index: 50;
  background: rgba(252, 251, 250, 0.82);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
  height: var(--nav-h);
  display: flex;
  align-items: center;
}
/* Solid on a phone (#493): see the banner note above. */
@media (max-width: 600px) { .nav { background: var(--bg-1); } }
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--sp-5);
  gap: var(--sp-5);
}
.nav-logo {
  display: inline-flex;
  align-items: center;
  height: 100%;
  text-decoration: none;
}
.nav-logo img {
  height: 56px;
  width: auto;
  display: block;
}
.nav-links {
  display: flex;
  gap: var(--sp-5);
  align-items: center;
  list-style: none;
  margin: 0; padding: 0;
}
.nav-links a {
  font-size: var(--fs-16);
  font-weight: 600;
  color: var(--nav-link, var(--fg-2));
  transition: color var(--dur-2) var(--ease-soft), opacity var(--dur-2) var(--ease-soft);
}
.nav-links a:hover { color: var(--nav-link, var(--accent)); opacity: 1; }

/* Each nav link wears a different palette color */
.nav-links li:nth-child(1) a { --nav-link: var(--bm-pink-lavender); }   /* Music */
.nav-links li:nth-child(2) a { --nav-link: var(--bm-purple); }          /* Videos */
.nav-links li:nth-child(3) a { --nav-link: var(--bm-blue); }            /* Shows */
.nav-links li:nth-child(4) a { --nav-link: var(--bm-teal); }            /* Merch */
.nav-links li:nth-child(5) a { --nav-link: var(--bm-pink); }            /* Gallery */
.nav-links li:nth-child(6) a { --nav-link: var(--bm-text-secondary); }  /* About */

.nav-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.nav-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  background: var(--bm-pink);
  color: var(--bm-text-primary);
  border-radius: var(--r-pill);
  font-size: var(--fs-14);
  font-weight: 600;
  transition: transform var(--dur-1) var(--ease-soft), box-shadow var(--dur-2) var(--ease-soft), background var(--dur-2) var(--ease-soft), color var(--dur-2) var(--ease-soft);
}
.nav-cta:hover { background: var(--bm-teal); color: var(--bm-text-light); box-shadow: var(--shadow-glow-teal); }
.nav-cta:active { transform: scale(0.98); }

/* Cart button in nav */
.nav-cart {
  display: inline-flex;
  align-items: center; justify-content: center;
  position: relative;
  width: 44px; height: 44px;
  margin-left: 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--fg-1);
  cursor: pointer;
  transition: border-color var(--dur-2), background var(--dur-2), color var(--dur-2);
}
.nav-cart:hover { border-color: var(--accent); color: var(--accent); }
.nav-cart-count {
  position: absolute;
  top: -4px; right: -4px;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--accent-warm); color: #fff;
  font-family: var(--font-mono);
  font-size: 10px; font-weight: 700;
  display: grid; place-items: center;
  line-height: 1;
  box-shadow: 0 0 0 2px var(--bg-1);
  transition: transform var(--dur-2) var(--ease-soft), opacity var(--dur-2);
}
.nav-cart-count[data-empty="true"] { opacity: 0; transform: scale(0.4); }
.nav-cart-count.bump { animation: cart-bump 0.42s var(--ease-soft); }
@keyframes cart-bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.45); }
  100% { transform: scale(1); }
}

.nav-burger { display: none; }
@media (max-width: 860px) {
  .nav-links { display: none; }
  .nav-burger {
    display: inline-flex;
    align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--r-pill);
    border: 1px solid var(--border);
  }
}

/* ============ BUTTONS ============ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 24px;
  border-radius: var(--r-pill);
  font-size: var(--fs-14);
  font-weight: 600;
  letter-spacing: 0.01em;
  transition: transform var(--dur-1) var(--ease-soft), box-shadow var(--dur-2) var(--ease-soft), background var(--dur-2) var(--ease-soft), color var(--dur-2) var(--ease-soft), border-color var(--dur-2) var(--ease-soft);
  border: 1px solid transparent;
  white-space: nowrap;
}
.btn:active { transform: scale(0.98); }
.btn-primary {
  background: var(--accent);
  color: var(--fg-on-dark);
}
.btn-primary:hover { box-shadow: var(--shadow-glow-teal); }
.btn-ghost {
  background: transparent;
  color: var(--fg-1);
  border-color: var(--border-strong);
}
.btn-ghost:hover { border-color: var(--fg-1); background: var(--fg-1); color: var(--fg-on-dark); }

/* ============ HERO ============ */
.hero {
  position: relative;
  padding: var(--sp-7) 0 var(--sp-6);
  overflow: hidden;
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: var(--sp-8);
  align-items: center;
}
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--sp-7); }
  /* Stacked, the photo leads (#461). Source order puts the words first
     because that is the reading order on a desktop's left column and the
     order a screen reader should hear; on a phone the photo is the thing
     worth the first screen, so it is moved visually and only visually. */
  .hero-photo-wrap { order: -1; }
  /* #497: at 721-980px the photo is capped at 560px tall (below), which
     makes a 4:5 card 448px wide -- and a grid item that stops short of its
     column sits at the START of it, so an iPad in portrait showed the photo
     in the left half with 40% of the width empty. Centre it. */
  .hero-photo-wrap { justify-self: center; width: min(100%, 448px); }
}
.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--fg-2);
  background: var(--bg-1);
}
.hero-eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--bm-pink);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 20%, transparent);
}
.hero-display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.75rem, 7.2vw, 6.5rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  color: var(--fg-1);
  margin: var(--sp-4) 0 var(--sp-5);
  text-wrap: balance;
}
.hero-display em {
  font-family: var(--font-script);
  font-style: normal;
  font-size: 1.25em;
  line-height: 0.9;
  color: var(--bm-pink);
}
.hero-display em + br + em,
.hero-display em:nth-of-type(2) {
  color: var(--bm-purple);
}
.hero-script {
  font-family: var(--font-script);
  font-size: clamp(3.12rem, 6.88vw, 5.62rem);
  color: var(--bm-pink-lavender);
  display: inline-block;
  transform: translateY(-4px) rotate(-2deg);
}
.hero-lead {
  font-size: var(--fs-18);
  font-weight: 300;
  line-height: var(--lh-normal);
  color: var(--fg-2);
  max-width: 50ch;
  margin: 0 0 var(--sp-6);
}
.hero-actions {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  align-items: center;
}
.hero-meta {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-5) var(--sp-6);
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.hero-meta-item {
  min-width: 0;
}
.hero-meta-item:nth-child(3) {
  grid-column: 1 / -1;
}
.hero-meta-item .label {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 4px;
}
.hero-meta-item .value {
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 700;
  font-size: 1.75rem;
  line-height: 1.05;
  color: var(--fg-1);
}
.hero-meta-item:nth-child(3) .value {
  white-space: nowrap;
}
.hero-photo-wrap {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--bm-surface-cool);
  box-shadow: var(--shadow-3);
}
.hero-photo-wrap img {
  width: 100%;
  height: 100%;
  /* The default is still fill-and-crop focused high (#459) — faces sit high
     in a portrait. site.js adds fit-cover / fit-contain and data-focus from
     the artist's setting; these two lines are what a visitor sees before it
     runs, and what /assets fallbacks get. */
  object-fit: cover;
  object-position: center 25%;
}
/* Fill the frame. The crop keeps whichever edge the artist chose. */
.hero-photo-wrap img.fit-cover { object-fit: cover; }
.hero-photo-wrap img.fit-cover[data-focus="top"]    { object-position: center top; }
.hero-photo-wrap img.fit-cover[data-focus="upper"]  { object-position: center 25%; }
.hero-photo-wrap img.fit-cover[data-focus="center"] { object-position: center center; }
.hero-photo-wrap img.fit-cover[data-focus="bottom"] { object-position: center bottom; }
/* Show the whole photo. The frame keeps its 4:5 so the page below does not
   move when a photo of a different shape is swapped in; the leftover space
   is the frame's own quiet wash rather than black bars. A wide photo lands
   centered in it. */
.hero-photo-wrap img.fit-contain {
  object-fit: contain;
  object-position: center center;
  background: var(--bm-surface-cool, #EFF5F4);
}
.hero-photo-tag {
  position: absolute;
  bottom: var(--sp-4);
  left: var(--sp-4);
  background: rgba(252, 251, 250, 0.92);
  backdrop-filter: blur(8px);
  border-radius: var(--r-pill);
  padding: 8px 14px;
  font-size: var(--fs-12);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--fg-1);
}
.hero-photo-tag .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-warm);
}

/* ============ MARQUEE / TICKER ============ */
.ticker {
  background: var(--fg-1);
  color: var(--fg-on-dark);
  padding: var(--sp-4) 0;
  overflow: hidden;
  border-top: 1px solid var(--fg-1);
  border-bottom: 1px solid var(--fg-1);
}
.ticker-track {
  display: flex;
  gap: var(--sp-8);
  width: max-content;
  animation: scroll 32s linear infinite;
}
.ticker-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--fs-40);
  white-space: nowrap;
}
.ticker-item span.dot { color: var(--bm-pink); }
.ticker-item:nth-child(3n) span.dot { color: var(--bm-pink-lavender); }
.ticker-item:nth-child(3n+1) span.dot { color: var(--bm-teal); }
.ticker-item:nth-child(3n+2) span.dot { color: var(--bm-purple); }
@keyframes scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ============ ABOUT ============ */
.about {
  background: var(--bm-surface-blush);
  padding-bottom: var(--sp-6);
}
.music { padding-top: var(--sp-6); }
.about-grid {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  align-items: center;
  gap: var(--sp-8);
}
@media (max-width: 860px) { .about-grid { grid-template-columns: 1fr; } }

.about-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--sp-6);
  box-shadow: var(--shadow-1);
}
.about-card h3 {
  font-family: var(--font-script);
  font-size: var(--fs-32);
  font-weight: 400;
  margin: 0 0 var(--sp-3);
  font-style: normal;
}
.about-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.88rem, 3.25vw, 2.50rem);
  line-height: 1.3;
  letter-spacing: var(--ls-tight);
  color: var(--fg-1);
  margin: 0;
  text-wrap: pretty;
}
.about-quote::before { content: "“"; color: var(--bm-pink); margin-right: 0.05em; }
.about-quote::after { content: "”"; color: var(--bm-pink); }
.about-body p {
  font-size: var(--fs-18);
  line-height: var(--lh-loose);
  color: var(--fg-2);
  margin: 0 0 var(--sp-4);
  text-wrap: pretty;
}
.about-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
  gap: var(--sp-5);
  gap: var(--sp-2);
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.about-stat:nth-child(1) .num { color: var(--bm-pink); }
.about-stat:nth-child(2) .num { color: var(--bm-purple); }
.about-stat:nth-child(3) .num { color: var(--bm-teal); }
.about-stat .num {
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 700;
  font-size: var(--fs-40);
  color: var(--accent);
  line-height: 1;
}
.about-stat .label {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-top: 4px;
}
.about-sig {
  font-family: var(--font-script);
  font-size: var(--fs-40);
  color: var(--fg-1);
  margin-top: var(--sp-5);
  display: inline-block;
}

/* ============ MUSIC / AUDIO PLAYER ============ */
.music-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--sp-7);
  align-items: stretch;
}
.music-right {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.music-right .tracklist {
  /* flex-basis 0, not auto. With `auto` the list's own content is its
     starting size, so twelve tracks made .music-right taller than the
     player, the stretched grid row grew to match, and the player gained a
     slab of dead space underneath instead of the list scrolling. At 0 the
     list starts from nothing and takes the space the PLAYER defines, which
     is what `overflow-y: auto` here was always for. */
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
.music-right .tracklist::-webkit-scrollbar { width: 6px; }
.music-right .tracklist::-webkit-scrollbar-track { background: transparent; }
.music-right .tracklist::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.music-right .tracklist::-webkit-scrollbar-thumb:hover { background: var(--fg-muted); }
@media (max-width: 900px) {
  .music-grid { grid-template-columns: 1fr; align-items: start; }
  /* One column, align-items: start — so there is no player column defining
     the height and nothing for the list to fill. flex-basis 0 would leave it
     at 0px, and with overflow visible the rows would paint OUT of a
     zero-height box, straight over the streaming links below. The desktop
     basis must not follow us down here. */
  .music-right .tracklist { flex: 1 1 auto; overflow-y: visible; }
}

.player-card {
  background: linear-gradient(180deg, var(--fg-1) 0%, #2a2928 100%);
  color: var(--fg-on-dark);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-3);
  position: relative;
  overflow: hidden;
}
.player-art {
  aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bm-surface-cool);
  margin-bottom: var(--sp-5);
  position: relative;
}
.player-art-grad {
  width: 100%;
  height: 100%;
  background:
    radial-gradient(ellipse at 25% 25%, var(--grad-1, var(--bm-pink)) 0%, transparent 55%),
    radial-gradient(ellipse at 75% 30%, var(--grad-2, var(--bm-pink-lavender)) 0%, transparent 55%),
    radial-gradient(ellipse at 70% 80%, var(--grad-3, var(--bm-teal)) 0%, transparent 60%),
    linear-gradient(135deg, var(--grad-2, var(--bm-pink-lavender)), var(--grad-3, var(--bm-teal-soft)));
  display: grid;
  place-items: center;
}
.player-art-grad .wordmark {
  font-family: var(--font-logo);
  font-size: 64px;
  color: rgba(29,29,28,0.85);
  transform: rotate(-4deg);
  text-align: center;
  line-height: 0.9;
}
.player-art-grad .wordmark small {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4em;
  color: rgba(29,29,28,0.7);
  margin-top: 4px;
  transform: rotate(0deg);
}
.player-track-info {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}
.player-track-info .title {
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--fs-40);
  line-height: 1.1;
  margin: 0;
}
.player-track-info .meta {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: rgba(252,251,250,0.6);
  margin-top: 6px;
}
.player-track-info .duration {
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  color: rgba(252,251,250,0.7);
}
.player-progress {
  position: relative;
  height: 4px;
  background: rgba(252,251,250,0.15);
  border-radius: 2px;
  cursor: pointer;
  margin-bottom: 6px;
}
/* #483: the bar is 4px tall -- a thumb cannot land on it. This invisible band
   is part of the element, so a touch anywhere in its 40px starts a seek; seekTo()
   reads only X from the bar's own rect, so the maths is unchanged. */
.player-progress::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: -16px; bottom: -20px; /* stays inside the gaps: the title above, the times below */
}
.player-progress:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }
.player-progress-fill {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  background: var(--accent);
  border-radius: 2px;
  width: 0%;
  transition: width 0.1s linear;
}
.player-progress-knob {
  position: absolute;
  right: -6px; top: 50%;
  transform: translateY(-50%);
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(62,183,178,0.18);
}
.player-times {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 12px;
  color: rgba(252,251,250,0.55);
  margin-bottom: var(--sp-4);
}
.player-status {
  min-height: 18px;
  margin: calc(-1 * var(--sp-2)) 0 var(--sp-3);
  font-size: var(--fs-12);
  line-height: 1.4;
  color: rgba(252,251,250,0.72);
  text-align: center;
}
.player-status[data-state="error"] {
  color: var(--bm-pink);
}
.player-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}
.player-btn {
  width: 40px; height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: rgba(252,251,250,0.7);
  transition: color var(--dur-2), background var(--dur-2);
}
.player-btn:hover { color: var(--fg-on-dark); background: rgba(252,251,250,0.08); }
.player-btn.play {
  width: 56px; height: 56px;
  background: var(--accent);
  color: var(--fg-on-dark);
}
.player-btn.play:hover { background: var(--accent); box-shadow: var(--shadow-glow-teal); }

.tracklist {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.tracklist-row {
  display: grid;
  /* num | title/sub | tag pill. Duration was removed (it's shown in
     the player preview when a track is selected). */
  grid-template-columns: 32px 1fr auto;
  gap: var(--sp-4);
  align-items: center;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-sm);
  transition: background var(--dur-2);
  cursor: pointer;
  text-align: left;
  width: 100%;
  border: 1px solid transparent;
}
.tracklist-row:hover { background: var(--bm-surface-cool); }
.tracklist-row.active {
  background: var(--bm-surface-cool);
  border-color: var(--border);
}
.tracklist-row .num {
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  color: var(--fg-muted);
  text-align: center;
}
.tracklist-row.active .num { color: var(--accent); }
.tracklist-row .play-icon, .tracklist-row .pause-icon { display: none; }
.tracklist-row.active .play-icon, .tracklist-row:hover .play-icon { display: block; }
/* The row that is actually playing shows pause instead — clicking it again
   stops, and the glyph says so. A YouTube row never reaches this state: its
   playback lives in the modal, so it keeps showing play. */
.tracklist-row.active.is-playing .play-icon { display: none; }
.tracklist-row.active.is-playing .pause-icon { display: block; }
.tracklist-row.active .num.show, .tracklist-row:hover .num.show { display: none; }
.tracklist-row .info .title {
  font-family: var(--font-script);
  font-style: normal;
  font-size: 1.75rem;
  color: var(--fg-1);
  line-height: 1.1;
}
.tracklist-row .info .sub {
  font-size: var(--fs-12);
  color: var(--fg-muted);
  margin-top: 2px;
}
.tracklist-row .tag {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: var(--r-pill);
  background: var(--bm-surface-blush);
  color: var(--fg-2);
}
.tracklist-row .tag { background: var(--bm-surface-blush); color: var(--bm-pink); }
.tracklist-row .tag.live { background: var(--bm-surface-cool); color: var(--bm-teal); }
.tracklist-row .tag.demo { background: color-mix(in srgb, var(--bm-purple) 12%, white); color: var(--bm-purple); }
.tracklist-row .tag.color-pink     { background: var(--bm-surface-blush); color: var(--bm-pink); }
.tracklist-row .tag.color-lavender { background: color-mix(in srgb, var(--bm-pink-lavender) 18%, white); color: color-mix(in srgb, var(--bm-pink-lavender) 80%, var(--fg-1)); }
.tracklist-row .tag.color-purple   { background: color-mix(in srgb, var(--bm-purple) 12%, white); color: var(--bm-purple); }
.tracklist-row .tag.color-teal     { background: var(--bm-surface-cool); color: var(--bm-teal); }
.tracklist-row .tag.color-blue     { background: var(--bm-surface-cool); color: var(--bm-blue); }
.tracklist-row .tag.color-amber    { background: color-mix(in srgb, #d97706 12%, white); color: #b45309; }
.tracklist-row .tag.color-charcoal { background: color-mix(in srgb, var(--fg-1) 10%, white); color: var(--fg-1); }
.tracklist-row .tag.color-cream    { background: var(--bm-surface-blush); color: var(--fg-2); }
.tracklist-row .duration {
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  color: var(--fg-muted);
}

.streaming-row {
  /* Never shrink: it is a sibling of a flex:1 scrolling list, and the
     default flex-shrink:1 let the list take the whole column and squash
     these links to zero height. */
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.streaming-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  font-size: var(--fs-12);
  font-weight: 500;
  color: var(--fg-2);
  transition: all var(--dur-2) var(--ease-soft);
}
.streaming-link:hover { color: var(--fg-1); border-color: var(--fg-1); }

/* Streaming brand colors — applied to the icon only, label stays neutral */
.streaming-icon { flex-shrink: 0; transition: color var(--dur-2) var(--ease-soft), transform var(--dur-2) var(--ease-soft); }
.streaming-link[data-social="spotify"] .streaming-icon { color: #1DB954; }
.streaming-link[data-social="apple"]   .streaming-icon { color: #FA243C; }
.streaming-link[data-social="youtube"] .streaming-icon { color: #FF0000; }
.streaming-link:hover .streaming-icon { transform: scale(1.08); }

/* ============ VIDEOS ============ */
.videos { background: var(--bg-2); padding: var(--sp-6) 0; }
.video-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--sp-5);
  /* Align thumbs to the top so their column matches the featured's
     height instead of stretching past it — required for the internal
     scroll on .video-thumbs to actually kick in. */
  align-items: start;
}
@media (max-width: 860px) { .video-grid { grid-template-columns: 1fr; } }

.video-featured {
  position: relative;
  aspect-ratio: 16/9;
  border-radius: var(--r-md);
  overflow: hidden;
  cursor: pointer;
  background: var(--fg-1);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-2) var(--ease-soft), box-shadow var(--dur-2) var(--ease-soft);
}
.video-featured:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}
.video-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Poster framing, set per video in the admin (Poster mode / Keep which
   part). Fill crops to the frame from the chosen edge; Show whole letterboxes
   on the card's dark ground so nothing is cut off. */
.video-poster[data-focus="top"]    { object-position: center top; }
.video-poster[data-focus="upper"]  { object-position: center 25%; }
.video-poster[data-focus="center"] { object-position: center center; }
.video-poster[data-focus="bottom"] { object-position: center bottom; }
.video-poster.fit-contain { object-fit: contain; background: var(--fg-1); }
.video-thumbs {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  /* Cap the column at the featured tile's approximate height so a long
     video list doesn't make the section grow indefinitely. The actual
     featured tile is aspect-ratio 16:9 — at typical desktop widths this
     lands around 360–480px tall, so we use 480px as a comfortable
     ceiling. Inner overflow becomes a styled scrollbar. */
  max-height: 480px;
  overflow-y: auto;
  /* Tiny padding-right so the scrollbar doesn't sit on top of thumbs. */
  padding-right: 4px;
  /* Custom scrollbar — subtle, on-brand. */
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--fg-1) 30%, transparent) transparent;
}
.video-thumbs::-webkit-scrollbar { width: 8px; }
.video-thumbs::-webkit-scrollbar-track { background: transparent; }
.video-thumbs::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--fg-1) 22%, transparent);
  border-radius: 999px;
}
.video-thumbs::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--fg-1) 38%, transparent);
}
/* Mobile: drop the cap entirely — the column collapses below the
   featured tile and a 480px-tall scrollbox would feel awkward there. */
@media (max-width: 860px) {
  .video-thumbs { max-height: none; padding-right: 0; }
}
.video-thumb-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--sp-4);
  align-items: center;
  padding: var(--sp-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--dur-2);
}
.video-thumb-row:hover { background: var(--bg-1); }
.video-thumb-row .thumb {
  position: relative;
  aspect-ratio: 16/9;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--fg-1);
}
.video-meta .title {
  font-family: var(--font-script);
  font-style: normal;
  font-size: 1.75rem;
  line-height: 1.1;
  color: var(--fg-1);
  margin: 0 0 4px;
}
.video-meta .sub {
  font-size: var(--fs-12);
  color: var(--fg-muted);
}
.video-play-icon {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 64px; height: 64px;
  background: rgba(252,251,250,0.92);
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--fg-1);
  transition: transform var(--dur-2) var(--ease-soft), background var(--dur-2);
  pointer-events: none;
}
.video-featured:hover .video-play-icon,
.video-thumb-row:hover .video-play-icon {
  transform: translate(-50%, -50%) scale(1.08);
  background: var(--accent);
  color: var(--fg-on-dark);
}
.video-play-icon-sm {
  width: 36px; height: 36px;
}
.video-overlay-tag {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  background: rgba(29,29,28,0.7);
  backdrop-filter: blur(8px);
  color: var(--fg-on-dark);
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Side-card tag pill — lives inside .video-meta beside the title.
   Smaller and lighter weight than the featured overlay so it sits
   politely next to the script-font title in the narrow meta column. */
.video-meta-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-bottom: 4px;
}
.video-meta-head .title { margin: 0; }
.video-meta-tag {
  display: inline-flex; align-items: center;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: rgba(29,29,28,0.85);
  color: var(--fg-on-dark);
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Tag library colors — shared by the featured tile's overlay pill and
   the side-card's inline meta pill so both renderings stay in sync. */
/* #482: white on teal/pink/amber measured 2.4:1 and lower at 10px, so
   those three fills take dark text (6.9:1 on teal). */
.video-overlay-tag.color-pink,     .video-meta-tag.color-pink     { background: var(--bm-pink); color: var(--fg-1); }
.video-overlay-tag.color-lavender, .video-meta-tag.color-lavender { background: var(--bm-pink-lavender); color: var(--fg-1); }
.video-overlay-tag.color-purple,   .video-meta-tag.color-purple   { background: var(--bm-purple); color: var(--fg-on-dark); }
.video-overlay-tag.color-teal,     .video-meta-tag.color-teal     { background: var(--bm-teal); color: var(--fg-1); }
.video-overlay-tag.color-blue,     .video-meta-tag.color-blue     { background: var(--bm-blue); color: var(--fg-on-dark); }
.video-overlay-tag.color-amber,    .video-meta-tag.color-amber    { background: #d97706; color: var(--fg-1); }
.video-overlay-tag.color-charcoal, .video-meta-tag.color-charcoal { background: var(--fg-1); color: var(--fg-on-dark); }
.video-overlay-tag.color-cream,    .video-meta-tag.color-cream    { background: var(--bm-surface-blush); color: var(--fg-1); }
.video-feature-cap {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: var(--sp-7) var(--sp-5) var(--sp-5);
  background: linear-gradient(180deg, transparent, rgba(29,29,28,0.85));
  color: var(--fg-on-dark);
}
.video-feature-cap .title {
  font-family: var(--font-script);
  font-style: normal;
  font-size: clamp(1.88rem, 4.38vw, 3.12rem);
  line-height: 1.1;
  margin: 0;
}
.video-feature-cap .sub {
  font-size: var(--fs-12);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-top: 6px;
  opacity: 0.8;
}

/* "More on Instagram" pill below the video grid — replaces a plain
   text "Watch more on YouTube →" link. Uses an Instagram-flavored
   pink→lavender gradient that still reads on-brand for the site. */
.more-on-instagram {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: linear-gradient(135deg, var(--bm-pink) 0%, var(--bm-pink-lavender) 100%);
  color: var(--fg-on-dark);
  font-size: var(--fs-13);
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--r-pill);
  transition: transform var(--dur-2) var(--ease-soft), box-shadow var(--dur-2) var(--ease-soft);
  box-shadow: var(--shadow-1);
}
.more-on-instagram:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-2);
}
.more-on-instagram svg { display: block; }

/* ============ SHOWS / CALENDAR ============ */
.shows { padding: var(--sp-6) 0; }
.shows-head {
  display: flex;
  justify-content: space-between;
  align-items: end;
  gap: var(--sp-5);
  flex-wrap: wrap;
  margin-bottom: var(--sp-7);
}
.shows-tabs {
  display: inline-flex;
  background: var(--bm-surface-cool);
  border-radius: var(--r-pill);
  padding: 4px;
  gap: 2px;
}
.shows-tab {
  padding: 8px 18px;
  border-radius: var(--r-pill);
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--fg-2);
  transition: all var(--dur-2) var(--ease-soft);
}
.shows-tab.active {
  background: var(--bg-1);
  color: var(--fg-1);
  box-shadow: var(--shadow-1);
}

.shows-list {
  display: flex;
  flex-direction: column;
}
.show-row {
  display: grid;
  grid-template-columns: 90px 1fr auto auto;
  gap: var(--sp-5);
  align-items: center;
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-2);
}
.show-row:first-child { border-top: 1px solid var(--border); }
.show-row:hover { background: var(--bm-surface-cool); margin: 0 calc(-1 * var(--sp-4)); padding-left: var(--sp-4); padding-right: var(--sp-4); border-radius: var(--r-sm); }
@media (max-width: 960px) {
  .show-row { grid-template-columns: 70px 1fr; gap: var(--sp-4); }
  /* Badges and links get separate wrapping rows; never overlap on phones. */
  .show-row .show-meta-extra {
    grid-column: 2 / -1;
    grid-row: 2;
    align-self: center;
    justify-self: start;
  }
  .show-row .show-actions {
    grid-column: 2 / -1;
    grid-row: 3;
    align-self: center;
    justify-self: start;
  }
  /* Shrink the ticket pill so it matches the badge size visually
     instead of dominating the row. */
  .show-tickets {
    padding: 4px 12px;
    font-size: var(--fs-12);
    letter-spacing: 0.04em;
  }
}

/* Show-info wraps optional event photo + text. Flex so the photo sits to the left
   when present and the text reflows neatly, without any change to the show-row grid. */
.show-info {
  display: flex; align-items: center; gap: var(--sp-4); min-width: 0;
}
.show-info-text { min-width: 0; flex: 1; }
.show-photo {
  flex: 0 0 auto;
  width: 56px; height: 56px;
  border-radius: var(--r-sm);
  background-size: cover; background-position: center;
  background-color: var(--bm-surface-cool);
  border: 1px solid var(--border);
}
@media (max-width: 720px) {
  .show-photo { width: 44px; height: 44px; }
}

/* Optional venue link — looks like the venue name but underlines on hover. */
.venue-link {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-1) var(--ease-soft);
}
.venue-link:hover { border-bottom-color: var(--accent); }

/* Tiny map-pin icon next to the venue name — links out to Google Maps. */
/* #483: the icons were 22x22 tap targets sitting side by side. The box is now
   44x44 with the icon centred in it, and the negative vertical margin keeps
   the row exactly as tall as before, so only the hit area grew. */
.show-map-pin {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin: -11px 0 -11px -5px;
  border-radius: 50%;
  color: var(--fg-2); background: transparent;
  vertical-align: -3px;
  transition: color var(--dur-1) var(--ease-soft), background var(--dur-1) var(--ease-soft);
}
.show-map-pin:hover { color: var(--accent); background: var(--bm-surface-cool); }

/* Calendar icon next to map-pin — downloads an .ics for upcoming shows. */
.show-cal {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin: -11px 0 -11px -18px;
  border-radius: 50%;
  color: var(--fg-2); background: transparent;
  vertical-align: -3px;
  transition: color var(--dur-1) var(--ease-soft), background var(--dur-1) var(--ease-soft);
}
.show-cal:hover { color: var(--accent); background: var(--bm-surface-cool); }
.show-date {
  text-align: center;
  border-right: 1px solid var(--border);
  padding-right: var(--sp-4);
}
.show-date .month {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--accent-warm);
  font-weight: 600;
}
.show-date .day {
  font-family: var(--font-display);
  font-size: var(--fs-40);
  line-height: 1;
  color: var(--fg-1);
  font-weight: 400;
  margin: 4px 0 2px;
}
.show-date .dow {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.show-info .venue {
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--fs-32);
  line-height: 1.2;
  color: var(--fg-1);
  margin: 0;
}
.show-info .city {
  font-size: var(--fs-14);
  color: var(--fg-2);
  margin-top: 2px;
}
.show-info .city .sep { color: var(--fg-muted); margin: 0 6px; }
.show-meta-extra {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 240px;
  font-size: var(--fs-12);
  color: var(--fg-muted);
  letter-spacing: 0.04em;
}
.show-meta-extra .badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--bm-surface-blush);
  color: var(--fg-2);
  font-weight: 500;
  margin-right: 6px;
}
.show-meta-extra .badge { background: var(--bm-surface-blush); color: var(--bm-pink); }
.show-meta-extra .badge.solo { background: var(--bm-surface-cool); color: var(--bm-blue); }
.show-meta-extra .badge.full { background: color-mix(in srgb, var(--bm-purple) 14%, white); color: var(--bm-purple); }

/* Tag library colors — mirror the swatch palette used in admin → Tags so
   the public pill matches the color Brooklyn picks there. */
.show-meta-extra .badge.color-pink     { background: var(--bm-surface-blush); color: var(--bm-pink); }
.show-meta-extra .badge.color-lavender { background: color-mix(in srgb, var(--bm-pink-lavender) 18%, white); color: color-mix(in srgb, var(--bm-pink-lavender) 80%, var(--fg-1)); }
.show-meta-extra .badge.color-purple   { background: color-mix(in srgb, var(--bm-purple) 14%, white); color: var(--bm-purple); }
.show-meta-extra .badge.color-teal     { background: var(--bm-surface-cool); color: var(--bm-teal); }
.show-meta-extra .badge.color-blue     { background: var(--bm-surface-cool); color: var(--bm-blue); }
.show-meta-extra .badge.color-amber    { background: color-mix(in srgb, #d97706 12%, white); color: #b45309; }
.show-meta-extra .badge.color-charcoal { background: color-mix(in srgb, var(--fg-1) 10%, white); color: var(--fg-1); }
.show-meta-extra .badge.color-cream    { background: var(--bm-surface-blush); color: var(--fg-2); }
.show-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; max-width: 280px; }
.show-actions:empty { display: none; }
.show-venue-link { font-size: var(--fs-12); text-decoration: underline; text-underline-offset: 3px; padding: 10px 0; }
.show-event-note { font-size: var(--fs-12); color: var(--fg-2); margin-top: 6px; overflow-wrap: anywhere; }
.show-actions a, .show-status { overflow-wrap: anywhere; max-width: 100%; }
.show-tickets {
  padding: 3px 10px;
  background: var(--fg-1);
  color: var(--fg-on-dark);
  border-radius: var(--r-pill);
  font-size: var(--fs-12);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1.5;
  transition: background var(--dur-2);
}
a.show-tickets:hover { background: var(--accent); }
.show-tickets.sold {
  background: transparent;
  color: var(--fg-muted);
  border: 1px solid var(--border);
}
.show-tickets.sold:hover { background: transparent; color: var(--fg-muted); }
.show-tickets.past {
  background: transparent;
  color: var(--fg-muted);
  border: 1px solid var(--border);
}
/* Gig-status colors flow from Settings → Tags → Gig status. The pill
   pulls the same palette as every other tag swatch in the system. The
   color- classes win against the default .show-tickets dark fill. */
.show-tickets.color-pink     { background: var(--bm-pink); color: var(--fg-on-dark); border: none; }
.show-tickets.color-lavender { background: var(--bm-pink-lavender); color: var(--fg-1); border: none; }
.show-tickets.color-purple   { background: var(--bm-purple); color: var(--fg-on-dark); border: none; }
.show-tickets.color-teal     { background: var(--bm-teal); color: var(--fg-on-dark); border: none; }
.show-tickets.color-blue     { background: var(--bm-blue); color: var(--fg-on-dark); border: none; }
.show-tickets.color-amber    { background: #d97706; color: var(--fg-on-dark); border: none; }
.show-tickets.color-charcoal { background: var(--fg-1); color: var(--fg-on-dark); border: none; }
.show-tickets.color-cream    { background: var(--bm-surface-blush); color: var(--fg-1); border: 1px solid var(--border); }
/* Anchor variant (Tickets link) should keep its hover lift, but only if
   the user hasn't pinned a swatch — once a color class is in play, the
   hover preserves that color so the link doesn't flash to teal. */
a.show-tickets.color-pink:hover     { background: var(--bm-pink); }
a.show-tickets.color-lavender:hover { background: var(--bm-pink-lavender); }
a.show-tickets.color-purple:hover   { background: var(--bm-purple); }
a.show-tickets.color-teal:hover     { background: var(--bm-teal); }
a.show-tickets.color-blue:hover     { background: var(--bm-blue); }
a.show-tickets.color-amber:hover    { background: #d97706; }
a.show-tickets.color-charcoal:hover { background: var(--fg-1); }
a.show-tickets.color-cream:hover    { background: var(--bm-surface-blush); color: var(--fg-1); }

.shows-empty {
  text-align: center;
  padding: var(--sp-9) var(--sp-5);
  color: var(--fg-muted);
  font-style: normal;
  font-family: var(--font-body);
  font-size: var(--fs-18);
  font-weight: 600;
}

/* "Show more / Show fewer" pagination control under the upcoming +
   past gigs lists. Renders only when the list has more rows than the
   page size, so short lists stay clean. */
.shows-more {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-5);
}
.shows-more-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 22px;
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--fg-1);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: border-color var(--dur-2), background var(--dur-2), color var(--dur-2);
}
.shows-more-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.shows-more-btn svg {
  transition: transform var(--dur-2);
}

/* ============ MERCH ============ */
.merch { background: var(--bm-surface-cool); }
.merch-filter {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  background: var(--bm-surface-cool);
  padding: 4px;
  border-radius: var(--r-pill);
  margin-bottom: var(--sp-6);
}
.merch-filter button {
  padding: 8px 18px;
  border-radius: var(--r-pill);
  border: 0;
  background: transparent;
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--fg-2);
  cursor: pointer;
  transition: all var(--dur-2) var(--ease-soft);
  font-family: var(--font-body);
}
.merch-filter button.active {
  background: var(--bg-1);
  color: var(--fg-1);
  box-shadow: var(--shadow-1);
}
.merch-filter button:hover:not(.active) { color: var(--fg-1); }

.merch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  grid-auto-rows: 1fr;
  gap: var(--sp-5) var(--sp-4);
}
.merch-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--bg-1);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: transform var(--dur-2) var(--ease-soft);
}
.merch-card:hover { transform: translateY(-3px); }

.merch-photo {
  position: relative;
  aspect-ratio: 1/1;
  background: var(--bm-surface-cool);
  border-radius: var(--r-md);
  overflow: hidden;
  margin-bottom: var(--sp-3);
}
.merch-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity var(--dur-2);
}
.merch-photo .merch-img {
  position: absolute; inset: 0;
  opacity: 0;
}
.merch-photo .merch-img.active { opacity: 1; }

.merch-tag-overlay {
  position: absolute;
  top: 12px; left: 12px;
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  background: var(--bg-1);
  color: var(--fg-1);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  font-weight: 600;
}
.merch-tag-overlay.sold { background: var(--fg-1); color: var(--fg-on-dark); }
.merch-tag-overlay.low { background: var(--accent-warm); color: var(--fg-1); }
.merch-tag-overlay.preorder { background: var(--accent); color: var(--fg-on-dark); }

/* Merch "Badge" tag (m.tag from the library) — opposite corner from the
   inventory pill so both can show simultaneously without overlapping. */
.merch-badge-overlay {
  position: absolute;
  top: 12px; right: 12px;
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  background: var(--bg-1);
  color: var(--fg-1);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  font-weight: 600;
  z-index: 2;
}
.merch-badge-overlay.color-pink     { background: var(--bm-pink); color: var(--fg-1); }
.merch-badge-overlay.color-lavender { background: var(--bm-pink-lavender); color: var(--fg-1); }
.merch-badge-overlay.color-purple   { background: var(--bm-purple); color: var(--fg-on-dark); }
.merch-badge-overlay.color-teal     { background: var(--bm-teal); color: var(--fg-1); }
.merch-badge-overlay.color-blue     { background: var(--bm-blue); color: var(--fg-on-dark); }
.merch-badge-overlay.color-amber    { background: #d97706; color: var(--fg-1); }
.merch-badge-overlay.color-charcoal { background: var(--fg-1); color: var(--fg-on-dark); }
.merch-badge-overlay.color-cream    { background: var(--bm-surface-blush); color: var(--fg-1); }

.merch-photo-nav {
  position: absolute;
  top: 50%; transform: translateY(-50%);
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(252,251,250,0.92);
  color: var(--fg-1);
  border: 0;
  display: grid; place-items: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-2), background var(--dur-2);
  z-index: 2;
}
.merch-photo-nav.prev { left: 10px; }
.merch-photo-nav.next { right: 10px; }
.merch-photo:hover .merch-photo-nav { opacity: 1; }
.merch-photo-nav:hover { background: var(--bg-1); }
/* #494: hover never happens on a touch screen, and the phone rule below
   only starts at 720px -- an iPad showed no arrows at all, and a keyboard
   user could tab onto an invisible one. */
.merch-photo-nav:focus-visible { opacity: 1; outline: 2px solid var(--accent); outline-offset: 2px; }
@media (hover: none) {
  .merch-photo-nav { opacity: 1; background: rgba(252,251,250,0.85); }
}

.merch-dots {
  position: absolute;
  bottom: 10px; left: 0; right: 0;
  display: flex;
  justify-content: center;
  gap: 5px;
  z-index: 2;
}
.merch-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(252,251,250,0.55);
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: all var(--dur-2);
}
.merch-dot.active { background: var(--bg-1); width: 18px; border-radius: 3px; }

.merch-meta {
  /* Wider horizontal padding than the 4px it used to carry so the script
     title below can bleed its overhanging swashes into this padding via a
     negative margin without escaping the (overflow:hidden) card. */
  padding: 0 10px 4px;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.merch-cat {
  font-size: 10px;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--accent-warm);
  font-weight: 600;
  margin-bottom: 4px;
}
.merch-name {
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--fs-32);
  line-height: 1.15;
  /* The line-clamp needs overflow:hidden, which also clips the script
     font's swashes (the "C" curl, trailing flourishes) at the text edges.
     Pad the clip box horizontally so those overhangs render inside it, then
     pull the box back out with a matching negative margin so the text still
     lines up with the eyebrow and subtitle. The negative margin stays inside
     the card because .merch-meta now carries 10px of horizontal padding. */
  margin: 0 -8px 4px;
  padding: 0 8px;
  color: var(--fg-1);
  min-height: calc(2 * 1.15em);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.merch-sub {
  font-size: var(--fs-14);
  color: var(--fg-2);
  margin-bottom: var(--sp-3);
  line-height: var(--lh-normal);
  min-height: calc(1 * var(--lh-normal) * 1em);
}
.merch-row {
  display: flex;
  justify-content: space-between;
  margin-top: auto;
  align-items: baseline;
  gap: var(--sp-3);
}
.merch-price {
  font-family: var(--font-display);
  font-size: var(--fs-20);
  font-weight: 600;
  color: var(--fg-1);
}
.merch-sizes {
  font-size: var(--fs-12);
  color: var(--fg-muted);
  letter-spacing: 0.06em;
}
.merch-empty {
  grid-column: 1 / -1;
  padding: 56px 24px;
  text-align: center;
  color: var(--fg-muted);
  font-style: normal;
  font-family: var(--font-body);
  font-size: var(--fs-16);
  font-weight: 600;
}

@media (max-width: 720px) {
  .merch-grid { grid-template-columns: repeat(2, 1fr); gap: var(--sp-4) var(--sp-3); }
  .merch-name { font-size: var(--fs-20); }
  .merch-photo-nav { opacity: 1; width: 32px; height: 32px; background: rgba(252,251,250,0.85); }
}
@media (max-width: 420px) {
  .merch-grid { grid-template-columns: 1fr; }
  .merch-filter button { padding: 7px 14px; font-size: 13px; }
}

/* ============ PHOTO GALLERY — playful asymmetric mosaic ============ */
.gallery {
  background: linear-gradient(135deg, var(--bm-surface-blush) 0%, var(--bm-surface-cool) 100%);
  overflow: hidden;
}
.gallery-mosaic {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: 60px;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}
.gallery-tile {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bm-surface-cool);
  cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-3) var(--ease-soft), box-shadow var(--dur-3) var(--ease-soft);
}
.gallery-tile:hover { transform: translateY(-4px) rotate(0deg) !important; box-shadow: var(--shadow-3); z-index: 2; }
.gallery-tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-4) var(--ease-soft);
}
.gallery-tile:hover img { transform: scale(1.04); }

/* Tile size + position presets */
.gt-1  { grid-column: span 5; grid-row: span 7; transform: rotate(-1.2deg); }
.gt-2  { grid-column: span 4; grid-row: span 4; transform: rotate(1.5deg); }
.gt-3  { grid-column: span 3; grid-row: span 5; transform: rotate(-2deg); }
.gt-4  { grid-column: span 4; grid-row: span 3; transform: rotate(0.8deg); }
.gt-5  { grid-column: span 3; grid-row: span 4; transform: rotate(-0.8deg); }
.gt-6  { grid-column: span 5; grid-row: span 6; transform: rotate(1.4deg); }
.gt-7  { grid-column: span 4; grid-row: span 5; transform: rotate(-1.6deg); }
.gt-8  { grid-column: span 3; grid-row: span 4; transform: rotate(2deg); }

.gallery-tile img.pos-upper  { object-position: center 25%; }
.gallery-tile img.pos-center { object-position: center center; }

/* Decorative scribble accents (desktop only — read as "X" on small screens) */
@media (min-width: 901px) {
.gallery-mosaic::before,
.gallery-mosaic::after {
  content: "";
  position: absolute;
  width: 80px; height: 80px;
  background-repeat: no-repeat;
  background-size: contain;
  pointer-events: none;
  opacity: 0.5;
  z-index: 0;
}
.gallery-mosaic::before {
  top: -10px; left: 36%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80' fill='none' stroke='%233EB7B2' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M10 40 Q 25 20, 40 40 T 70 40'/%3E%3C/svg%3E");
}
.gallery-mosaic::after {
  bottom: -10px; right: 28%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80' fill='none' stroke='%23FDA2C5' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M10 50 Q 25 30, 40 50 T 70 50'/%3E%3C/svg%3E");
}
}

/* Mobile: simpler 2-column stagger */
@media (max-width: 720px) {
  .gallery-mosaic {
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 50px;
  }
  .gt-1 { grid-column: span 6; grid-row: span 6; }
  .gt-2, .gt-3, .gt-4, .gt-5, .gt-6, .gt-7, .gt-8 { grid-column: span 3; grid-row: span 4; }
}

/* ============ BOOKING ============ */
.booking { background: var(--fg-1); color: var(--fg-on-dark); position: relative; overflow: hidden; }
.booking::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 15% 0%, color-mix(in srgb, var(--bm-pink) 22%, transparent) 0%, transparent 45%),
    radial-gradient(ellipse at 85% 100%, color-mix(in srgb, var(--bm-purple) 28%, transparent) 0%, transparent 50%);
  pointer-events: none;
}
.booking .container { position: relative; }
.booking .section-title { color: var(--fg-on-dark); }
.booking .section-title em { color: var(--bm-pink); }
.booking .section-lead { color: rgba(252,251,250,0.7); }
.booking .eyebrow { color: rgba(252,251,250,0.6); }
.booking .eyebrow::before { color: var(--bm-pink-lavender); }
.booking-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: var(--sp-8);
  align-items: start;
}
@media (max-width: 900px) { .booking-grid { grid-template-columns: 1fr; } }

.booking-info p {
  color: rgba(252,251,250,0.75);
  font-size: var(--fs-18);
  line-height: var(--lh-loose);
  margin: 0 0 var(--sp-5);
}
.booking-checklist {
  list-style: none;
  padding: 0; margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.booking-checklist li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-16);
  color: rgba(252,251,250,0.85);
}
.booking-checklist li:nth-child(1)::before { background: rgba(253,162,197,0.18); border-color: rgba(253,162,197,0.4); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23FDA2C5' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); }
.booking-checklist li:nth-child(2)::before { background: rgba(227,164,239,0.18); border-color: rgba(227,164,239,0.4); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23E3A4EF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); }
.booking-checklist li:nth-child(3)::before { background: rgba(98,93,199,0.22); border-color: rgba(98,93,199,0.45); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23625DC7' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); }
.booking-checklist li:nth-child(4)::before { background: rgba(62,183,178,0.18); border-color: rgba(62,183,178,0.4); }
.booking-checklist li::before {
  content: "";
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(62,183,178,0.18);
  border: 1px solid rgba(62,183,178,0.4);
  display: grid; place-items: center;
  color: var(--accent);
  flex-shrink: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%233EB7B2' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.form {
  background: rgba(252,251,250,0.04);
  border: 1px solid rgba(252,251,250,0.08);
  border-radius: var(--r-md);
  padding: var(--sp-6);
}
.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}
@media (max-width: 600px) { .form-row { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: 6px; }
.field.full { grid-column: 1 / -1; }
.field label {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: rgba(252,251,250,0.55);
  font-weight: 500;
}
.field input,
.field select,
.field textarea {
  background: rgba(252,251,250,0.06);
  border: 1px solid rgba(252,251,250,0.12);
  border-radius: var(--r-sm);
  padding: 12px 14px;
  color: var(--fg-on-dark);
  font-size: var(--fs-16);
  font-family: var(--font-body);
  transition: border-color var(--dur-2);
  outline: none;
}
.field input::placeholder,
.field textarea::placeholder { color: rgba(252,251,250,0.35); }
.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--accent); }
.field textarea { min-height: 120px; resize: vertical; line-height: var(--lh-normal); }
.field select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23FCFBFA' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 38px; }
.field select option { background: var(--fg-1); color: var(--fg-on-dark); }
.form-submit {
  margin-top: var(--sp-4);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.form-fineprint {
  font-size: var(--fs-12);
  color: rgba(252,251,250,0.5);
  max-width: 40ch;
  text-wrap: pretty;
  line-height: 1.45;
}
.form-success {
  background: rgba(62,183,178,0.15);
  border: 1px solid rgba(62,183,178,0.3);
  border-radius: var(--r-md);
  padding: var(--sp-7) var(--sp-6);
  text-align: center;
  color: var(--fg-on-dark);
}
.form-success .check {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--accent);
  display: grid; place-items: center;
  margin: 0 auto var(--sp-4);
}
.form-success h3 {
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--fs-40);
  margin: 0 0 var(--sp-3);
  color: var(--fg-on-dark);
}
.form-success p {
  color: rgba(252,251,250,0.75);
  margin: 0;
}

/* ============ NEWSLETTER ============ */
.newsletter {
  background: var(--bm-surface-cool);
  text-align: center;
}
.newsletter .container-narrow > .eyebrow { display: inline-flex; }
.newsletter h2 { margin: var(--sp-3) auto var(--sp-3); }
.newsletter p { font-size: var(--fs-18); color: var(--fg-2); max-width: 50ch; margin: 0 auto var(--sp-6); }
.newsletter-form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-width: 480px;
  margin: 0 auto;
}
.newsletter-names {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
}
.newsletter-names input {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 12px 18px;
  font-size: var(--fs-16);
  outline: none;
  width: 100%;
  transition: border-color var(--dur-2);
}
.newsletter-names input:focus { border-color: var(--accent); }
.newsletter-form > input[type="email"],
.newsletter-form > input[type="tel"] {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 12px 18px;
  font-size: var(--fs-16);
  outline: none;
  width: 100%;
  transition: border-color var(--dur-2);
}
.newsletter-form > input[type="email"]:focus,
.newsletter-form > input[type="tel"]:focus { border-color: var(--accent); }
.newsletter-form button {
  padding: 12px 20px;
  background: var(--fg-1);
  color: var(--fg-on-dark);
  border: 0;
  border-radius: var(--r-pill);
  font-size: var(--fs-14);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--dur-2);
}
.newsletter-form button:hover { background: var(--accent); }
@media (max-width: 480px) {
  .newsletter-names { grid-template-columns: 1fr; }
}
/* SMS keyword opt-in (#244). This is the second opt-in path, not a
   footnote to the form, and it is the one carrier vetting compares against
   the 10DLC filing — so it sits with the form at readable size rather than
   in the 10px consent print below it. Deliberately a div, not a p: the
   `.newsletter p` rule above sets an 18px/50ch/centred style that a bare
   `.newsletter-sms-cta` class selector would lose to on specificity. A div
   sidesteps the fight entirely, and keeps these rules working the same on
   both surfaces without a descendant selector to maintain. */
.newsletter-sms {
  max-width: 480px;
  margin: var(--sp-4) auto 0;
}
.newsletter-sms-or {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-12);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.newsletter-sms-or::before,
.newsletter-sms-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}
.newsletter-sms-cta {
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-16);
  color: var(--fg-1);
  text-align: center;
}
.newsletter-sms-cta strong {
  font-weight: 700;
  letter-spacing: 0.04em;
}
.newsletter-sms-cta a {
  color: inherit;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-2);
}
.newsletter-sms-cta a:hover { color: var(--accent); }
.newsletter-sms-cta a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.newsletter-consent {
  max-width: 480px;
  margin: 8px auto 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--fg-muted-text);
  text-align: center;
}
.newsletter-consent-choice {
  max-width: 480px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 2px auto 4px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--fg-muted-text);
  text-align: left;
  cursor: pointer;
}
.newsletter-consent-choice input[type="checkbox"] {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 1px 0 0;
  accent-color: var(--accent);
}
.newsletter-consent-choice a,
.newsletter-consent a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.newsletter-note {
  font-size: var(--fs-12);
  color: var(--fg-muted);
  margin-top: var(--sp-3);
}

/* ============ FOOTER ============ */
.footer {
  background: var(--fg-1);
  color: var(--fg-on-dark);
  padding: var(--sp-8) 0 var(--sp-5);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--sp-7);
  margin-bottom: var(--sp-7);
}
@media (max-width: 860px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 500px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-logo {
  width: 220px;
  max-width: 100%;
  height: auto;
  filter: brightness(0) invert(1);
  margin-bottom: var(--sp-3);
}
.footer-brand .wordmark {
  font-family: var(--font-logo);
  font-size: 56px;
  line-height: 1;
  color: var(--fg-on-dark);
}
.footer-brand .tag {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: rgba(252,251,250,0.5);
  margin-top: 6px;
}
.footer-brand p {
  color: rgba(252,251,250,0.6);
  font-size: var(--fs-14);
  line-height: var(--lh-normal);
  margin: var(--sp-4) 0 var(--sp-4);
  max-width: 30ch;
}
.footer h4 {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: rgba(252,251,250,0.5);
  font-weight: 600;
  margin: 0 0 var(--sp-3);
}
.footer-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.footer-list a {
  font-size: var(--fs-14);
  color: rgba(252,251,250,0.85);
  transition: color var(--dur-2);
}
.footer-list a:hover { color: var(--accent); }
.footer-socials { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); }
.footer-social-link {
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1.5px solid var(--social-color, rgba(252,251,250,0.5));
  background: transparent;
  display: grid; place-items: center;
  color: var(--social-color, rgba(252,251,250,0.7));
  transition: all var(--dur-2) var(--ease-soft);
}
.footer-social-link[data-social="instagram"] { --social-color: var(--bm-pink-lavender); }
.footer-social-link[data-social="facebook"]  { --social-color: var(--bm-teal); }
.footer-social-link[data-social="youtube"]   { --social-color: var(--bm-pink); }
.footer-social-link:hover {
  background: var(--social-color, var(--accent));
  border-color: var(--social-color, var(--accent));
  color: var(--bm-text-primary);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px -6px var(--social-color, var(--accent));
}
.footer-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: var(--sp-5);
  border-top: 1px solid rgba(252,251,250,0.1);
  font-size: var(--fs-12);
  color: rgba(252,251,250,0.45);
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.footer-sig {
  font-family: var(--font-script);
  font-size: var(--fs-32);
  color: rgba(252,251,250,0.7);
}

/* ============ MODAL ============ */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(29,29,28,0.85);
  backdrop-filter: blur(8px);
  z-index: 100;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5);
  animation: fadeIn var(--dur-3) var(--ease-soft);
}
.modal.open { display: flex; }
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.modal-content {
  position: relative;
  width: 100%;
  max-width: 1024px;
  aspect-ratio: 16/9;
  background: black;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-3);
  animation: pop var(--dur-3) var(--ease-soft);
}
@keyframes pop {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}
.modal-close {
  position: absolute;
  top: -48px; right: 0;
  color: var(--fg-on-dark);
  width: 40px; height: 40px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(252,251,250,0.1);
  border: 1px solid rgba(252,251,250,0.2);
}
.modal-close:hover { background: rgba(252,251,250,0.2); }
.modal iframe { width: 100%; height: 100%; border: 0; }

/* Reveal-on-scroll */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--ease-soft), transform 0.7s var(--ease-soft);
}
.reveal.in { opacity: 1; transform: translateY(0); }

/* ============================================================
   Skip link (a11y) + mobile menu
   ============================================================ */
.skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  background: var(--fg-1);
  color: var(--fg-on-dark);
  padding: 8px 14px;
  border-radius: var(--r-sm);
  font-size: var(--fs-14);
  font-weight: 600;
  z-index: 200;
  transition: top var(--dur-2);
}
.skip-link:focus { top: 8px; }

.mobile-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--bg-1);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-2);
  padding: var(--sp-3) var(--sp-5) var(--sp-5);
  flex-direction: column;
  gap: 0;
  z-index: 99;
}
.mobile-menu[data-open="true"] { display: flex; }
.mobile-menu a {
  display: block;
  padding: 14px 4px;
  font-size: var(--fs-18);
  font-weight: 500;
  color: var(--fg-1);
  border-bottom: 1px solid var(--border);
  text-decoration: none;
}
.mobile-menu a:last-child { border-bottom: 0; }
.mobile-menu .mobile-menu-cta {
  margin-top: var(--sp-3);
  background: var(--fg-1);
  color: var(--fg-on-dark);
  text-align: center;
  border-radius: var(--r-pill);
  padding: 14px 24px;
  border-bottom: 0;
  font-weight: 600;
}

/* ============================================================
   Tablet (≤ 980px)
   ============================================================ */
@media (max-width: 980px) {
  :root {
    --sp-9: 80px;
    --sp-8: 56px;
    --sp-7: 40px;
  }
  .container { padding: 0 var(--sp-4); }
  .hero { padding: var(--sp-6) 0 var(--sp-7); }
  .hero-photo-wrap { aspect-ratio: 4/5; max-height: 560px; }
  .video-thumb-row { grid-template-columns: 130px 1fr; }
}

/* ============================================================
   Mobile (≤ 720px)
   ============================================================ */
@media (max-width: 720px) {
  :root {
    --fs-56: 40px;
    --fs-44: 32px;
    --fs-32: 24px;
    --fs-24: 20px;
    --fs-20: 17px;
    --sp-9: 64px;
    --sp-8: 44px;
    --sp-7: 32px;
  }
  body { font-size: var(--fs-14); }
  .container, .container-narrow { padding: 0 var(--sp-3); }
  section { padding: var(--sp-7) 0; }

  /* Nav */
  .nav-cta { display: none; }
  /* keep nav sticky on mobile so the hamburger is always reachable */

  /* Hero */
  .hero-display { font-size: clamp(2rem, 8vw, 2.6rem); }
  .hero-lead { font-size: var(--fs-16); }
  .hero-actions .btn { flex: 1; justify-content: center; }
  .hero-meta {
    gap: var(--sp-4);
  }
  .hero-meta-item .value {
    font-size: 1.55rem;
  }
  .hero-photo-wrap { aspect-ratio: 4/5; }

  /* Ticker */
  .ticker-item { font-size: var(--fs-24); gap: var(--sp-3); }
  .ticker-track { gap: var(--sp-5); }

  /* Music */
  .player-card { padding: var(--sp-5); }
  .player-track-info .title { font-size: var(--fs-24); }
  .tracklist-row { grid-template-columns: 28px 1fr auto; padding: var(--sp-3); gap: var(--sp-3); }
  .tracklist-row .tag { display: none; }
  .tracklist-row .info .title { font-size: var(--fs-18); }
  .streaming-row { justify-content: center; }
  .streaming-link { flex: 1 1 auto; justify-content: center; min-width: 0; }

  /* Videos */
  .video-thumb-row { grid-template-columns: 110px 1fr; gap: var(--sp-3); }
  .video-feature-cap { padding: var(--sp-5) var(--sp-4) var(--sp-4); }
  .video-feature-cap .title { font-size: var(--fs-20); }

  /* Shows */
  .shows-head { gap: var(--sp-3); margin-bottom: var(--sp-5); }
  .show-row { padding: var(--sp-4) 0; }
  .show-info .venue { font-size: var(--fs-18); }
  .show-meta-extra { margin-top: var(--sp-2); }
  .show-actions { margin-top: var(--sp-2); }

  /* Gallery */
  .gallery-tile { transform: rotate(0deg) !important; }

  /* Booking */
  .booking { padding: var(--sp-7) 0; }
  .form { padding: var(--sp-5); }
  .form-submit { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .form-submit .btn { justify-content: center; }
  .form-fineprint { text-align: center; }

  /* Footer */
  .footer { padding: var(--sp-7) 0 var(--sp-4); }
  .footer-bottom { flex-direction: column; gap: var(--sp-2); text-align: center; }
}

/* Extra-small (≤ 420px) */
@media (max-width: 420px) {
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn { width: 100%; }
  .hero-meta {
    grid-template-columns: 1fr;
    gap: var(--sp-3);
  }
  .hero-meta-item:first-child {
    grid-column: auto;
  }
  .hero-meta-item .value {
    font-size: 1.45rem;
  }
  .hero-photo-tag { font-size: 10px; padding: 6px 10px; }
  .player-controls { gap: var(--sp-3); }
  .player-btn.play { width: 56px; height: 56px; }
  .nav-logo img { height: 44px; }
}

/* Inputs need 16px+ on iOS to avoid auto-zoom */
@media (max-width: 720px) {
  input, select, textarea { font-size: 16px !important; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .ticker-track { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* ============================================================
   CART — slide-out drawer + add-to-cart UI on merch cards
   ============================================================ */

/* Add-to-cart row on merch card */
.merch-buy {
  display: flex; gap: 8px; align-items: stretch;
  margin-top: auto;
  padding-top: var(--sp-3);
}
.merch-size {
  flex: 0 0 auto;
  min-width: 84px;
  padding: 0 12px;
  height: 42px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--bg-1);
  font-family: var(--font-body);
  font-size: var(--fs-14);
  color: var(--fg-1);
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%231D1D1C' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 28px;
  transition: border-color var(--dur-2);
}
.merch-size:focus { outline: none; border-color: var(--accent); }
.merch-add {
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 42px;
  padding: 0 16px;
  border: 0; border-radius: var(--r-pill);
  background: var(--accent); color: var(--fg-on-dark);
  font-family: var(--font-body); font-size: var(--fs-14); font-weight: 600;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-soft), transform var(--dur-1);
}
.merch-add:hover { background: var(--accent-warm); color: var(--fg-1); }
.merch-add:active { transform: scale(0.98); }
.merch-add:disabled {
  background: var(--bg-2); color: var(--fg-muted);
  cursor: not-allowed; opacity: 0.7;
}
.merch-add.added {
  background: var(--accent);
  pointer-events: none;
}

/* Drawer + overlay */
.cart-overlay {
  position: fixed; inset: 0;
  background: rgba(29,29,28,0.55);
  backdrop-filter: blur(6px);
  z-index: 90;
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-soft);
}
.cart-overlay[data-open="true"] { opacity: 1; }

.cart-drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(440px, 92vw);
  background: var(--bg-1);
  z-index: 100;
  display: flex; flex-direction: column;
  box-shadow: -16px 0 40px rgba(29,29,28,0.18);
  transform: translateX(100%);
  transition: transform var(--dur-4) var(--ease-soft);
  overflow: hidden;
}
.cart-drawer[data-open="true"] { transform: translateX(0); }
/* #479: `display:flex` above outranks the UA's [hidden] rule, so the closed
   drawer stayed laid out off-canvas -- its shadow leaked down the right edge
   of phones and iPads, and Tab walked into its invisible buttons. openCart()
   un-hides it a frame before sliding it in, so the transition still runs. */
.cart-drawer[hidden], .cart-overlay[hidden] { display: none; }

.cart-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px;
  padding: 22px 24px 18px;
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
.cart-eyebrow {
  display: block;
  font-size: 12px; letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  color: var(--accent-warm); font-weight: 600; margin-bottom: 4px;
}
.cart-title {
  font-family: var(--font-script); font-style: normal; font-weight: 400;
  font-size: 40px; line-height: 1.1; margin: 0;
  letter-spacing: -0.01em;
}
.cart-title em { color: var(--accent); }
.cart-close {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0; background: transparent; color: var(--fg-2);
  border-radius: 50%; cursor: pointer;
  transition: background var(--dur-2);
}
.cart-close:hover { background: var(--bg-2); color: var(--fg-1); }

.cart-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 8px 24px 20px;
  -webkit-overflow-scrolling: touch;
}
.cart-empty {
  padding: 56px 16px;
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.cart-empty .icon {
  width: 64px; height: 64px;
  border-radius: 50%;
  background: var(--bm-surface-blush);
  display: grid; place-items: center;
  color: var(--accent-warm);
}
.cart-empty .ttl {
  font-family: var(--font-body); font-style: normal; font-weight: 700;
  font-size: 24px; color: var(--fg-1);
}
.cart-empty .body { color: var(--fg-2); font-size: var(--fs-14); max-width: 28ch; line-height: var(--lh-normal); }
.cart-empty .keep-shopping {
  margin-top: 4px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 20px;
  border-radius: var(--r-pill);
  background: var(--fg-1); color: var(--fg-on-dark);
  font-size: var(--fs-14); font-weight: 600;
  cursor: pointer; border: 0;
}

.cart-line {
  display: grid;
  grid-template-columns: 72px 1fr auto;
  gap: 14px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
  align-items: start;
}
.cart-line:last-child { border-bottom: 0; }
.cart-line-img {
  width: 72px; height: 88px;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--bg-2);
}
.cart-line-img img {
  width: 100%; height: 100%; object-fit: cover;
}
.cart-line-info { min-width: 0; }
.cart-line-name {
  font-size: var(--fs-14); font-weight: 600;
  line-height: 1.3; margin: 0 0 2px;
  color: var(--fg-1);
}
.cart-line-meta {
  font-size: 12px; color: var(--fg-muted);
  margin-bottom: 10px;
  line-height: 1.4;
}
.cart-qty {
  display: inline-flex; align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  height: 30px;
  background: var(--bg-1);
}
.cart-qty button {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border: 0; background: transparent;
  color: var(--fg-1); cursor: pointer;
  font-size: 14px; line-height: 1;
}
.cart-qty button:hover { color: var(--accent); }
.cart-qty button:disabled { color: var(--fg-muted); cursor: not-allowed; }
.cart-qty .q {
  min-width: 22px; text-align: center;
  font-family: var(--font-mono); font-size: 12px;
  color: var(--fg-1); font-variant-numeric: tabular-nums;
}
.cart-line-right {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 8px;
}
.cart-line-price {
  font-family: var(--font-mono);
  font-size: var(--fs-14);
  color: var(--fg-1);
  font-variant-numeric: tabular-nums;
}
.cart-line-remove {
  border: 0; background: transparent;
  color: var(--fg-muted); cursor: pointer;
  font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 0;
}
.cart-line-remove:hover { color: var(--accent-warm); }

.cart-foot {
  flex: 0 0 auto;
  padding: 18px 24px max(20px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  background: var(--bg-1);
  display: flex; flex-direction: column; gap: 12px;
}
.cart-summary-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-body); font-style: normal; font-weight: 700;
  font-size: 20px;
  color: var(--fg-1);
}
.cart-summary-row span:last-child {
  font-family: var(--font-mono); font-style: normal;
  font-size: 22px;
  font-variant-numeric: tabular-nums;
}
.cart-summary-row.minor {
  font-weight: 500; font-size: 14px; color: var(--fg-2);
  margin-bottom: 4px;
}
.cart-summary-row.minor span:last-child { font-size: 14px; }
.cart-summary-note {
  font-size: 12px; color: var(--fg-muted);
  margin-top: 2px;
}
.cart-summary-note:empty { display: none; }
/* Ship / Local pickup segmented control (#407) */
.cart-fulfillment {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px;
  padding: 4px; margin-bottom: 12px;
  background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--r-sm);
}
.cart-fulfillment button {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 8px 10px; border-radius: calc(var(--r-sm) - 2px);
  font-family: var(--font-body); font-size: 13px; font-weight: 600;
  color: var(--fg-2); transition: background .15s, color .15s;
}
.cart-fulfillment button[aria-pressed="true"] {
  background: var(--bg-1); color: var(--fg-1); box-shadow: var(--shadow-1);
}
.cart-checkout {
  width: 100%; justify-content: center;
  height: 50px; font-size: var(--fs-14);
}
.cart-checkout:disabled {
  background: var(--bg-2); color: var(--fg-muted);
  cursor: not-allowed; box-shadow: none;
}
.cart-trust {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px; flex-wrap: wrap;
  font-size: 11px; color: var(--fg-muted);
  letter-spacing: 0.04em;
}
.cart-trust .trust-item {
  display: inline-flex; align-items: center; gap: 5px;
}

/* Toast — "added to bag" */
.cart-toast {
  position: fixed;
  top: 24px; left: 50%;
  transform: translateX(-50%) translateY(-20px);
  background: var(--fg-1); color: var(--fg-on-dark);
  padding: 12px 20px;
  border-radius: var(--r-pill);
  font-size: var(--fs-14); font-weight: 500;
  display: inline-flex; align-items: center; gap: 8px;
  box-shadow: var(--shadow-3);
  opacity: 0; pointer-events: none;
  z-index: 120;
  transition: opacity var(--dur-3), transform var(--dur-3) var(--ease-soft);
}
.cart-toast[data-show="true"] {
  opacity: 1; transform: translateX(-50%) translateY(0);
}
.cart-toast .check {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--accent);
  display: grid; place-items: center;
  color: var(--fg-on-dark);
}

@media (max-width: 720px) {
  .cart-drawer { width: 100vw; }
  .cart-title { font-size: 26px; }
  .merch-buy { flex-direction: column; }
  .merch-size { width: 100%; }
}

/* ============ TOUCH TARGETS (#496) ============
   44px is the smallest target a thumb reliably hits. The round icon buttons
   above grew outright (4-8px, barely visible); the text links below only
   grow on a touch screen, where the extra height is the point and the mouse
   layout stays exactly as designed. */
@media (pointer: coarse) {
  .streaming-link, .cart-fulfillment button { min-height: 44px; }
  .footer-list { gap: 0; }
  .footer-list a { display: inline-block; padding: 12px 0; }
}

/* ============ SECTION SURFACES (2026-09-29) ============
   public/section-order.js decides which sections change colour so that no
   two neighbours match; these are the shades it may choose. Two classes of
   specificity, so they win over each section's own background, including
   spotlight.css, which loads after this file. */
[data-section-block][data-surface="canvas"] { background: var(--bg-1); }
[data-section-block][data-surface="warm"]   { background: var(--bm-surface-warm); }
[data-section-block][data-surface="cool"]   { background: var(--bm-surface-cool); }
[data-section-block][data-surface="blush"]  { background: var(--bm-surface-blush); }
.ticker[data-surface="accent"] { background: var(--bm-teal); color: var(--fg-1); border-color: var(--bm-teal); }
