/* V2 hero scroll cue: animated chevron under the CTA so visitors know
   there's more content (program) below. */
.hero-scroll-cue {
  position: absolute;
  bottom: 1rem; left: 50%;
  transform: translateX(-50%);
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(247,236,206,0.35);
  border-radius: 50%;
  color: var(--cream);
  text-decoration: none;
  z-index: 6;
  animation: scrollCueBob 1.8s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.hero-scroll-cue svg { width: 18px; height: 18px; }
.hero-scroll-cue:hover {
  background: var(--brass);
  border-color: var(--brass);
  color: var(--ink);
}
@keyframes scrollCueBob {
  0%, 100% { transform: translate(-50%, 0); opacity: 0.85; }
  50%      { transform: translate(-50%, 7px); opacity: 1; }
}
@media (max-width: 600px) {
  .hero-scroll-cue { bottom: 1.2rem; width: 34px; height: 34px; }
}

.program-carousel { padding: 4rem 0 5rem; }
.program-carousel .lineup-carousel-header { margin-bottom: 2rem; }
/* Standalone brass tag line — sits below the Headliners heading */
.section-tag-line {
  display: block;
  width: 88px; height: 2px;
  background: var(--brass);
  margin: 0;
}

.schedule-section {
  padding: 5rem 0 6rem;
  position: relative;
  background: var(--ink);
}
.schedule-cards {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
  margin-top: 2.4rem;
}

/* ═══════════════════════════════════════════════════════════════════════
   DAY POSTERS — each night is its own poster.
   Big headliner photo on the left half, line-up on the right half,
   own unique shade of blue (or a theme-night override).
   ═══════════════════════════════════════════════════════════════════════ */
.day-poster {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  min-height: 320px;
  background: var(--day-tint, var(--ink));
  border-radius: 4px;
  overflow: hidden;
  transition: transform 0.55s cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 0.55s ease;
}
@media (hover: hover) {
  /* No translateY on hover — that 4px lift created mouseleave/enter
     jitter at the poster's edges, which broke both the photo-hover
     name highlight (only triggered on the center of the photos) AND
     click registration on lineup names near the poster edges (mousedown
     and mouseup landed on different elements during the bounce). The
     box-shadow alone still reads as elevation. */
  .day-poster:hover {
    box-shadow:
      0 24px 60px rgba(0,0,0,0.55),
      0 0 0 1px rgba(200,144,42,0.12) inset;
  }
}
.day-poster.empty {
  min-height: 180px;
  grid-template-columns: 1fr;
  opacity: 0.5;
}
.dp-photo {
  position: relative;
  overflow: hidden;
  min-height: 320px;
  background: var(--ink);
}
@media (min-width: 601px) {
  /* Cap the day-poster's row height at the photo height — both columns
     fill the same vertical space, so the photo always reaches the bottom
     edge of the card (no day-tint strip). Any info content that would
     spill past gets clipped by the day-poster's overflow:hidden, but the
     tighter lineup padding/gap above keeps 3-act long-name days from
     overflowing in practice. */
  .day-poster {
    grid-template-rows: clamp(280px, 22vw, 320px);
    min-height: 0;
  }
  .dp-photo {
    min-height: 0;
    align-self: stretch;
  }
  .dp-info {
    min-height: 0;
    /* No overflow:hidden — it was clipping the font ascent of "JUL"
       above its line-box. .day-poster's own overflow:hidden still
       handles any actual content overflow at the bottom. */
  }
}
/* Collage cells: each photo lives in its own <div class="dp-photo-cell">,
   placed by CSS Grid. The .dp-photo-grid-N modifier classes below set the
   grid for 1 / 2 / 3 acts per night. */
.dp-photo-cell {
  position: relative;
  overflow: hidden;
  min-height: 0;
}
/* Bluish-monochrome treatment on every collage photo — near-grayscale
   with a cool blue duotone cast (grayscale → warm sepia → hue-rotated
   into the blues). Lifts to full natural colour on hover of the cell
   OR its matching lineup name, with a small zoom for the active one. */
.dp-photo-cell img {
  filter: grayscale(0.95) sepia(0.5) hue-rotate(178deg) saturate(1.4) brightness(1);
  /* No transition on `filter` — animating through hue-rotate produced
     a brief weird-color swing as the hue value crossed greens/yellows.
     Explicitly pin filter transition to 0s so no browser default sneaks
     in an implicit animation; only the zoom scale is transitioned. */
  transition: filter 0s, scale 0.35s ease;
  transform-origin: center;
}
@media (hover: hover) {
  .dp-photo-cell:hover img,
  .dp-photo-cell.name-hover img {
    filter: none;
    scale: 1.06;
  }
}
/* Photo cells also carry .dp-act-link (for click delegation) but must NOT
   inherit the time/name 2-column grid that .dp-act-link applies to lineup
   list items — that rule was forcing the <img> into a 70px-wide first
   column and producing the "super narrow super tall" photo bug. Reset
   here so .dp-photo-cell wins regardless of source order. */
.dp-photo-cell.dp-act-link {
  display: block;
  grid-template-columns: none;
  gap: 0;
  padding: 0;
  border-bottom: none;
  align-items: stretch;
}
.dp-photo-cell.dp-act-link:last-child { border-bottom: none; }
.dp-photo-cell img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.dp-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* ALL collage layouts use the SAME grid so the headliner photo is the
   same size and in the same position on every day, regardless of how
   many acts that night has. Days with 1 or 2 photos leave the unused
   cells showing day-tint, which keeps the visual rhythm consistent. */
/* Original poster collage layouts (the version you said was good). */
.dp-photo-grid-1 {
  display: block;
}
.dp-photo-grid-1 .dp-photo-cell { width: 100%; height: 100%; }

.dp-photo-grid-2 {
  display: grid;
  /* 50/50 split per Uri (2026-05-11 desktop pass). */
  grid-template-columns: 1fr 1fr;
  gap: 0;
}
.dp-photo-grid-2 .dp-photo-cell-0 { grid-column: 1; }
.dp-photo-grid-2 .dp-photo-cell-1 { grid-column: 2; }

.dp-photo-grid-3 {
  display: grid;
  /* Main photo gets 50% width; right stack of two takes the other 50%. */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 0;
}
.dp-photo-grid-3 .dp-photo-cell-0 { grid-column: 1; grid-row: 1 / span 2; }
.dp-photo-grid-3 .dp-photo-cell-1 { grid-column: 2; grid-row: 1; }
.dp-photo-grid-3 .dp-photo-cell-2 { grid-column: 2; grid-row: 2; }

.dp-photo-cell {
  display: block;
  text-decoration: none;
  color: inherit;
}
/* Cell positioning is scoped per-count above (.dp-photo-grid-1/2/3) —
   no global cell rules here. (Earlier dead "always-3-cell" rules were
   forcing cell-0 to span 2 rows on every day, including 1- and 2-act
   days, producing a tall narrow main photo + empty black space below
   the side cell. Removed.) */
/* The previous fade-to-tint overlay was covering the right photos of the
   collage. Removed entirely — the hard edge between .dp-photo and .dp-info
   reads clean against the unified tint and the photos stay fully visible. */
.dp-info {
  padding: 2.4rem 2.4rem 0.9rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  position: relative;
  z-index: 1;
}
.dp-date-block { padding-top: 0.3rem; }
.day-poster.empty .dp-info { padding: 2rem 2.4rem; }
/* Desktop only: pull the date row higher so long line-ups (e.g. 26.07
   Gonzalo's long featured-name string + Tigran below) have more vertical
   breathing room. Phone date-block header is untouched. */
@media (min-width: 601px) {
  .dp-info { padding-top: 1.2rem; }
  .dp-date-block { padding-top: 0; }
}
.dp-date-block {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  flex-wrap: wrap;
}
.dp-number {
  font-family: var(--font-display);
  font-size: clamp(3.4rem, 5.8vw, 5.2rem);
  color: var(--brass);
  line-height: 1;
  letter-spacing: 0.01em;
}
.dp-month {
  /* Bebas Neue — designed for caps, full cap-height. Inter at 1rem
     bold was rendering with short caps that looked clipped. */
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 400;
  letter-spacing: 0.34em;
  line-height: 1.1;
  color: rgba(247,236,206,0.85);
  text-transform: uppercase;
}
.dp-weekday {
  font-family: var(--font-head);
  font-style: italic;
  font-size: 1.5rem;
  color: rgba(247,236,206,0.88);
  margin-left: 0.4rem;
}
.dp-lineup {
  list-style: none;
  padding: 0; margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.dp-act-link {
  display: grid;
  grid-template-columns: 70px 1fr;
  align-items: baseline;
  gap: 0.9rem;
  padding: 0.3rem 0;
  text-decoration: none;
  border-bottom: 1px solid rgba(247,236,206,0.08);
  transition: border-color 0.35s ease;
}
.dp-act-link:last-child { border-bottom: 1px solid rgba(247,236,206,0.08); }
.dp-time {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: rgba(247,236,206,0.52);
  text-transform: uppercase;
}
.dp-name {
  font-family: var(--font-display);
  font-size: clamp(1.45rem, 2.4vw, 2rem);
  color: var(--brass);
  letter-spacing: 0.015em;
  font-weight: 400;
  line-height: 1.1;
  transition: color 0.3s ease, transform 0.3s ease;
}
/* Inline thumbnail next to each lineup row — visible on phone only.
   `display: contents` on the meta wrapper means time+name flow as if
   they were direct grid children on desktop, keeping the existing
   .dp-act-link grid (70px time | 1fr name) intact. */
.dp-act-thumb { display: none; }
.dp-act-meta { display: contents; }
/* Desktop split-name styling. Primary band name + featured names use
   the same big display font (Bebas Neue brass). Only "feat." (connector)
   and Trio/Quartet secondary suffixes render in the smaller italic serif
   white/cream treatment. */
@media (min-width: 601px) {
  .dp-name-primary,
  .dp-name-feat { color: var(--brass); }
  .dp-name-connector,
  .dp-name-secondary {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 1.1rem;
    font-weight: 400;
    letter-spacing: 0.005em;
  }
  .dp-name-connector { color: rgba(247,236,206,0.92); }
  .dp-name-secondary { color: rgba(247,236,206,0.85); }
  /* "Prince" inside Ida Nielsen Group A Prince Celebration: same color
     as the surrounding text (honey was too low-contrast against cream
     paper), highlighted by a slight italic tilt instead. Surrounding
     "A … Celebration" is upright so the italic on "Prince" reads. */
  .ida-prince-em {
    font-style: italic;
    font-weight: inherit;
    font-size: inherit;
    letter-spacing: inherit;
    color: inherit;
  }
  /* V5 desktop: non-themed (cream parchment) days — flip band names to
     ink so they punch against the cream surface. Themed days
     (Italy / Brazil / ACT) keep their original treatment. */
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-primary,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-feat {
    color: var(--ink);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-connector {
    color: rgba(14,29,51,0.72);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-secondary {
    color: rgba(14,29,51,0.62);
  }
}
/* Phone lineup — Ida's name lays out as:
     Line 1: "Ida Nielsen" big brass + "Group" small italic (connector)
     Line 2: "A Prince Celebration" (feat)
   Pulling primary back to inline-flow so the connector "Group" sits on
   the same line, then forcing feat to its own block under it. */
@media (max-width: 600px) {
  .dp-act-link[data-id="ida-nilsen-prince"] .dp-name-primary,
  .dp-act-link[data-id="ida-nilsen-prince"] .dp-name-connector {
    display: inline;
  }
  .dp-act-link[data-id="ida-nilsen-prince"] .dp-name-feat {
    display: block;
    margin-top: 0.15rem;
    /* Cancel the 0.4em offset that .dp-name-connector + .dp-name-feat
       adds — when feat goes on its own block line we want it flush-
       left with "Ida Nielsen" above. */
    padding-left: 0;
  }
}
@media (hover: hover) {
  .dp-act-link:hover .dp-name {
    color: #ffe6a8;
    transform: translateX(2px);
  }
  .dp-act-link:hover { border-bottom-color: rgba(200,144,42,0.45); }
  /* Cross-hover: hovering an artist's photo cell in the collage highlights
     the matching name on the right — brighter + slightly larger. */
  .dp-lineup .dp-act-link.photo-hover .dp-name {
    color: #ffe6a8;
    transform: translateX(2px) scale(1.06);
    transform-origin: left center;
  }
  .dp-lineup .dp-act-link.photo-hover {
    border-bottom-color: rgba(200,144,42,0.45);
  }
}
.dp-tbc {
  font-family: var(--font-head);
  font-style: italic;
  font-size: 1rem;
  color: rgba(247,236,206,0.4);
  margin: 0;
}

/* ── THEME: ITALY NIGHT (21.07) ─────────────────────────────────────────
   Default day tint stays. Italian identity comes from the top tricolore
   band, ITALIA watermark, sepia photo wash, and a MUTED tricolore on the
   info side only — desaturated green / dark cream / muted brick — so the
   flag is recognisable but doesn't shout. */
.day-poster.theme-italy {
  /* No background override here — inherits the day-tint from the JS-set
     CSS var (--day-tint) like every other day. */
}
.day-poster.theme-italy .dp-info {
  /* Actual Italian flag colours on the info side. A darkening overlay on
     top so cream + brass typography stays legible across all three bands
     (the unmuted white centre would otherwise wash out the type). */
  background:
    linear-gradient(rgba(0,0,0,0.55), rgba(0,0,0,0.55)),
    linear-gradient(90deg,
      #008c45 0%, #008c45 33.33%,
      #f4f5f0 33.33%, #f4f5f0 66.66%,
      #cd212a 66.66%, #cd212a 100%);
}
/* Top full-width tricolore band removed — Uri's feedback (2026-05-11):
   the info-side tricolore alone reads as Italy clearly, the top band is
   redundant. */
.day-poster.theme-italy::before { display: none; }
/* Italy/Brazil/ACT photo filters removed so the global bluish-duotone
   .dp-photo-cell img filter applies uniformly across all days. */
/* Theme fade overlay removed — was covering the collage's right photos. */
.day-poster.theme-italy .dp-info { position: relative; overflow: hidden; }
.day-poster.theme-italy .dp-info::before {
  content: 'ITALIA';
  position: absolute;
  right: -0.4rem; bottom: -0.6rem;
  font-family: var(--font-display);
  font-size: clamp(5.5rem, 11vw, 9.5rem);
  letter-spacing: 0.14em;
  color: rgba(244,217,127,0.22);  /* Italian gold, clearly visible */
  pointer-events: none;
  line-height: 0.82;
  white-space: nowrap;
}
.day-poster.theme-italy .dp-number,
.day-poster.theme-italy .dp-name {
  color: #f4d97f;  /* Italian gold */
}
.day-poster.theme-italy .dp-month,
.day-poster.theme-italy .dp-weekday {
  color: rgba(247,236,206,0.78);
}
.day-poster.theme-italy .dp-time {
  color: rgba(244,217,127,0.55);
}
@media (max-width: 600px) {
  /* Phone: only the top tricolore band — bottom band removed so it
     doesn't cover the ITALIA watermark. */
  .day-poster.theme-italy::before { height: 7px; }
  .day-poster.theme-italy .dp-info::before {
    font-size: clamp(3.4rem, 16vw, 5rem);
  }
}

/* ── THEME: BRAZILIAN NIGHT (28.07) ─────────────────────────────────────
   Deep tropical green poster with yellow "BRASILIANISCHE NACHT" tag,
   warm/saturated photo, and a soft yellow "BRASIL" watermark on the
   info side. Unmistakably Brazilian. */
.day-poster.theme-brazil {
  --day-tint: #0f2a1c;
  background: #0f2a1c;
}
/* Brazil photo filter removed — see note above .day-poster.theme-italy. */
.day-poster.theme-brazil .dp-number,
.day-poster.theme-brazil .dp-name {
  color: #ffdf00;  /* Brazilian flag yellow */
}
.day-poster.theme-brazil .dp-info { position: relative; overflow: hidden; }
.day-poster.theme-brazil .dp-info::before {
  content: 'BRASIL';
  position: absolute;
  right: -0.4rem; bottom: -0.6rem;
  font-family: var(--font-display);
  font-size: clamp(5.5rem, 12vw, 9.5rem);
  letter-spacing: 0.12em;
  pointer-events: none;
  line-height: 0.82;
  white-space: nowrap;
  /* Wordmark painted with the Brazilian flag colours — green field with
     a yellow diamond/lozenge and a blue celestial disc, clipped to the
     letterforms. The flag itself is invisible; only its colours show
     through the BRASIL letters. */
  background:
    radial-gradient(circle at 50% 60%, #002776 0%, #002776 11%, transparent 12%),
    radial-gradient(ellipse 46% 78% at 50% 50%, #ffdf00 0%, #ffdf00 92%, transparent 100%),
    #009c3b;
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  opacity: 0.55;  /* keep it watermark-y, not loud */
}
.dp-theme-tag {
  position: absolute;
  top: 1rem; left: 1rem;
  z-index: 5;
  font-family: var(--font-display);
  font-size: 0.8rem;
  letter-spacing: 0.22em;
  padding: 0.5rem 0.9rem;
  border-radius: 2px;
}
.dp-theme-tag-brazil {
  background: #ffdf00;
  color: #009c3b;
}
@media (max-width: 600px) {
  .day-poster.theme-brazil .dp-info::before { font-size: clamp(3.2rem, 16vw, 5rem); }
  .dp-theme-tag { font-size: 0.66rem; padding: 0.38rem 0.7rem; }
}

/* ── THEME: ACT WEEKEND (01.08 + 02.08) ─────────────────────────────────
   Minimalist label aesthetic. Near-black canvas, fine off-white hairline
   border, monochrome typography, big ACT wordmark with the red corner
   square that's part of the actmusic.com brand identity. */
.day-poster.theme-act {
  --day-tint: #0a0a0a;
  background: #0a0a0a;
  border: 1px solid rgba(255,255,255,0.08);
}
.day-poster.theme-act .dp-number { color: var(--cream); font-weight: 300; letter-spacing: 0; }
.day-poster.theme-act .dp-name {
  color: var(--cream);
  font-family: var(--font-head);
  font-style: normal;
  font-weight: 400;
}
.day-poster.theme-act .dp-month { color: rgba(247,236,206,0.55); }
.day-poster.theme-act .dp-weekday { color: rgba(247,236,206,0.65); }
.day-poster.theme-act .dp-time { color: rgba(247,236,206,0.45); }
/* ACT photo filter removed — global bluish duotone applies uniformly. */
.day-poster.theme-act .dp-info { position: relative; overflow: hidden; }
/* Real ACT Music logo in the bottom-right of the info area (SVG with the
   brand's own tight letterforms — no faked text + red square). */
.day-poster.theme-act .dp-act-logo {
  position: absolute;
  right: 1.3rem; bottom: 1rem;
  height: clamp(28px, 4.2vw, 44px);
  width: auto;
  display: block;
  pointer-events: none;
  opacity: 0.95;
}
.dp-theme-tag-act {
  background: transparent;
  color: var(--cream);
  font-family: 'Helvetica Neue', system-ui, sans-serif;
  font-size: 0.88rem;
  font-weight: 800;
  letter-spacing: 0.32em;
  border-left: 4px solid #cc0000;
  padding-left: 0.7rem;
  border-radius: 0;
}
@media (max-width: 600px) {
  .day-poster.theme-act .dp-act-logo {
    height: 26px;
    right: 1rem; bottom: 1rem;
  }
}

/* ── PHONE LAYOUT — festival-list style ──────────────────────────────
   On phone the big photo collage is hidden. Each day becomes a thin
   horizontal date header followed by one row per artist:
     [60×60 thumbnail]   small time
                         BIG SERIF NAME
   Last row's hairline is the bottom of the day — no dead space.
   Names are the hook. Photos are recognition-only at row scale. */
@media (max-width: 600px) {
  .schedule-cards { gap: 1.6rem; }

  .day-poster {
    display: block;
    grid-template-columns: 1fr;
    min-height: 0;
    background: var(--day-tint, var(--ink));
  }
  /* Hide the big photo collage — thumbnails ride inline next to names. */
  .day-poster .dp-photo { display: none; }

  .dp-info {
    padding: 0;
    gap: 0;
  }

  /* Day header: thin bar with date number + month + weekday */
  .dp-date-block {
    display: flex;
    align-items: baseline;
    gap: 0.7rem;
    flex-wrap: nowrap;
    padding: 0.95rem 1.2rem 0.7rem;
    background: rgba(0,0,0,0.18);
    border-bottom: 1px solid rgba(247,236,206,0.12);
  }
  .dp-number {
    font-size: 1.8rem;
    line-height: 1;
    flex: 0 0 auto;
  }
  .dp-month {
    font-size: 0.85rem;
    letter-spacing: 0.28em;
  }
  .dp-weekday {
    font-size: 0.85rem;
    flex: 1 1 auto;
    color: rgba(247,236,206,0.65);
  }

  /* Lineup as a list of full-width rows */
  .dp-lineup {
    margin: 0;
    padding: 0;
    gap: 0;
  }
  .dp-act { list-style: none; }
  .dp-act-link {
    display: block;
    padding: 1rem 1.2rem 1rem;
    border-bottom: 1px solid rgba(247,236,206,0.10);
    transition: background 0.2s ease;
  }
  .dp-act-link:last-child { border-bottom: 1px solid rgba(247,236,206,0.10); }
  .dp-act-link:active { background: rgba(255,255,255,0.04); }

  /* Thumbnails removed on phone per Uri — names are the show. */
  .dp-act-thumb { display: none; }
  .dp-act-meta {
    display: block;
  }
  .dp-time {
    display: block;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(247,236,206,0.5);
    margin-bottom: 0.25rem;
  }
  /* Two-tone artist name: primary (band) in brass and BIG, secondary
     (feat. / Trio / tagline) in cream and smaller below. */
  .dp-name {
    display: block;
    font-family: var(--font-display);
    color: var(--brass);
    font-weight: 400;
    letter-spacing: 0.005em;
    line-height: 1.02;
  }
  .dp-name-primary {
    display: block;
    font-size: 2.3rem;
    color: var(--brass);
    line-height: 1.02;
    letter-spacing: 0.002em;
  }
  .dp-name-secondary {
    display: block;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 1.05rem;
    color: rgba(247,236,206,0.85);
    line-height: 1.2;
    margin-top: 0.22rem;
    font-weight: 400;
  }
  /* "feat." + featured artists share one wrapped line below the
     band name. Connector stays cream; names stay brass. They render
     inline so "feat. Richard Bona & Dave Weckl" reads as a single
     italic phrase with the connector tonally separated. */
  .dp-name-connector {
    display: inline;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 1.05rem;
    color: rgba(247,236,206,0.78);
    font-weight: 400;
  }
  .dp-name-feat {
    display: inline;
    /* Phone: featured artist names should look like a smaller version of
       the primary band name — same Bebas Neue display font, NOT the
       Playfair italic. */
    font-family: var(--font-display);
    font-style: normal;
    font-size: 1.5rem;
    color: var(--brass);
    font-weight: 500;
    letter-spacing: 0.005em;
  }
  /* Wrap the connector+names onto a single new line below the primary,
     using the wrapper element they're injected after. The primary span
     forces a block, then connector + feat flow inline. We rely on the
     primary's display:block to create the line break. */
  .dp-name-primary + .dp-name-connector::before { content: ''; }
  .dp-name-connector + .dp-name-feat { padding-left: 0.4em; }

  /* Themed days — accent the day-header bar slightly. */
  .day-poster.theme-italy .dp-date-block {
    background: linear-gradient(90deg,
      rgba(0,140,69,0.32) 0%, rgba(0,140,69,0.32) 33.33%,
      rgba(244,245,240,0.18) 33.33%, rgba(244,245,240,0.18) 66.66%,
      rgba(205,33,42,0.32) 66.66%, rgba(205,33,42,0.32) 100%),
      rgba(0,0,0,0.35);
  }
  .day-poster.theme-brazil .dp-date-block {
    background:
      linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)),
      #0f2a1c;
  }
  .day-poster.theme-act .dp-date-block {
    background:
      linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0.35)),
      #0a0a0a;
  }

  /* Empty / TBA day */
  .dp-tbc {
    padding: 0.9rem 1.2rem;
    font-size: 0.95rem;
    color: rgba(247,236,206,0.45);
  }

  /* Default: hide the inherited bottom-right Italy / Brazil watermark
     on phone. We bring it back specifically as a vertical spine label
     on the right edge below. */
  .day-poster .dp-info::before { display: none; }
  .day-poster .dp-act-logo { display: none; }

  /* Vertical spine label for themed nights — "ITALIA" runs top-to-
     bottom on the right edge of the day card, "BRASIL" same on its
     night, so the theme is recognisable at a glance while scrolling. */
  .day-poster.theme-italy,
  .day-poster.theme-brazil { position: relative; }
  .day-poster.theme-italy::after,
  .day-poster.theme-brazil::after {
    position: absolute;
    right: 0.55rem;
    /* Anchor at top so the label grows downward with bigger font,
       instead of expanding equally up + down when centered. */
    top: 3.4rem;
    bottom: 0.8rem;
    transform: none;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    font-family: var(--font-display);
    font-size: 1.55rem;
    font-weight: 400;
    letter-spacing: 0.42em;
    text-transform: uppercase;
    pointer-events: none;
    z-index: 2;
    display: flex;
    align-items: flex-start;
  }
  .day-poster.theme-italy::after {
    content: 'ITALIA';
    color: rgba(244,217,127,0.55);
  }
  .day-poster.theme-brazil::after {
    content: 'BRASIL';
    color: rgba(255,223,0,0.55);
  }
  /* Phone fade-into-info-section overlay removed — same reason as desktop:
     was covering the right side of the photo collage. */
  .dp-info {
    padding: 1.2rem 1.4rem 1.6rem;
    gap: 1rem;
  }
  .dp-number { font-size: 3rem; }
  .dp-month { font-size: 1rem; letter-spacing: 0.3em; }
  .dp-weekday { font-size: 0.9rem; }
  .dp-act-link { grid-template-columns: 56px 1fr; gap: 0.7rem; padding: 0.4rem 0; }
  .dp-photo-cell.dp-act-link { grid-template-columns: none; gap: 0; padding: 0; }
  .dp-time { font-size: 0.62rem; letter-spacing: 0.18em; }
  .dp-name { font-size: 1.1rem; }
  /* Compact ticket pin on phone — the desktop "bigger + more visible"
     version was overlapping the artist name in the bottom-sheet. */
  .sheet-tickets-pin {
    font-size: 0.64rem;
    padding: 0.55rem 0.95rem;
    letter-spacing: 0.2em;
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      inset 0 -1px 0 rgba(0,0,0,0.25),
      0 3px 10px rgba(0,0,0,0.4);
  }
  .sheet-header { gap: 0.9rem; }
  /* Blink once on phone instead of twice — keeps the attention pulse
     without feeling repetitive. */
  .sheet-tickets-pin.is-fresh { animation-iteration-count: 1; }
  .sheet-tickets-pin.is-fresh::after { animation-iteration-count: 1; }
  /* Italy stripe — top edge on phone (since layout is stacked). */
  .day-poster.theme-italy::before {
    left: 0; right: 0; top: 0; bottom: auto;
    height: 4px; width: auto;
    background: linear-gradient(90deg,
      #008c45 0%, #008c45 33.33%,
      #f4f5f0 33.33%, #f4f5f0 66.66%,
      #cd212a 66.66%, #cd212a 100%);
  }
}
/* Hide the OLD day-card styles — entire .day-card layout is replaced. */
.day-card { display: none; }

/* ═══════════════════════════════════════════════════════════════════════
   TICKET PICKER MODAL — nested popup over the artist sheet.
   ═══════════════════════════════════════════════════════════════════════ */
.ticket-modal {
  position: fixed; inset: 0;
  z-index: 1300;
  display: none;
  align-items: flex-end; justify-content: center;
}
.ticket-modal.open { display: flex; }
.ticket-modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(6,14,28,0.75);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: ticketBackdropIn 0.35s ease-out;
}
@keyframes ticketBackdropIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.ticket-modal-card {
  position: relative;
  width: 100%;
  max-width: 480px;
  background: var(--ink);
  border: 1px solid rgba(247,236,206,0.18);
  border-radius: 6px 6px 0 0;
  padding: 2rem 1.6rem 1.6rem;
  color: var(--cream);
  animation: ticketCardIn 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes ticketCardIn {
  from { transform: translateY(40px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
@media (min-width: 700px) {
  .ticket-modal { align-items: center; }
  .ticket-modal-card { border-radius: 6px; margin-bottom: 0; }
}
.ticket-modal-close {
  position: absolute;
  top: 0.7rem; right: 0.7rem;
  width: 36px; height: 36px;
  background: transparent;
  border: 1px solid rgba(247,236,206,0.25);
  border-radius: 50%;
  color: var(--cream);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 0.25s, border-color 0.25s;
}
.ticket-modal-close svg { width: 16px; height: 16px; }
.ticket-modal-close:hover { background: var(--brass); border-color: var(--brass); color: var(--ink); }
.ticket-modal-eyebrow {
  font-family: var(--font-body);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 0.4rem;
}
.ticket-modal-title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 4vw, 2.2rem);
  letter-spacing: 0.02em;
  margin: 0 0 1.4rem;
  line-height: 1.05;
}
.ticket-options {
  display: flex; flex-direction: column;
  gap: 0.8rem;
}
.ticket-option {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.4rem 1rem;
  padding: 1.1rem 1.2rem;
  background: rgba(247,236,206,0.05);
  border: 1px solid rgba(247,236,206,0.18);
  border-radius: 4px;
  color: var(--cream);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.25s, border-color 0.25s, transform 0.25s;
}
.ticket-option:hover {
  border-color: var(--brass);
  background: rgba(200,144,42,0.08);
}
.ticket-option:active { transform: scale(0.98); }
.ticket-option-recommended {
  border-color: var(--brass);
  background: rgba(200,144,42,0.10);
}
.ticket-option-flag {
  position: absolute;
  top: -0.6rem; left: 1rem;
  font-family: var(--font-body);
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--brass);
  padding: 0.22rem 0.6rem;
  border-radius: 2px;
}
.ticket-option-label {
  grid-column: 1;
  font-family: var(--font-display);
  font-size: 1.25rem;
  letter-spacing: 0.02em;
}
.ticket-option-price {
  grid-column: 2;
  grid-row: 1 / span 2;
  font-family: var(--font-display);
  font-size: 1.75rem;
  color: var(--brass);
  align-self: center;
}
.ticket-option-meta {
  grid-column: 1;
  font-family: var(--font-head);
  font-style: italic;
  font-size: 0.85rem;
  color: rgba(247,236,206,0.7);
}
.ticket-option-cta {
  grid-column: 1 / -1;
  margin-top: 0.4rem;
  font-family: var(--font-body);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--brass);
}
.ticket-modal-note {
  font-family: var(--font-body);
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  color: rgba(247,236,206,0.45);
  margin: 1.1rem 0 0;
  text-align: center;
}
.day-card {
  position: relative;
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 1.2rem;
  padding: 1.2rem 1.4rem;
  background:
    linear-gradient(135deg, rgba(14,29,51,0.62), rgba(14,29,51,0.42));
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  border: 1px solid rgba(247,236,206,0.16);
  border-radius: 4px;
  transition: border-color 0.35s, transform 0.35s, background 0.35s, box-shadow 0.35s;
  overflow: hidden;
}
/* Soft warm glow that radiates from the date column on hover — gives the
   card an "illuminated" feel rather than a hard accent line. */
.day-card::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(ellipse at 8% 50%, rgba(200,144,42,0.16), transparent 55%);
  opacity: 0;
  transition: opacity 0.5s ease;
  z-index: 0;
}
.day-card > * { position: relative; z-index: 1; }
.day-card {
  transition:
    border-color 0.5s ease,
    transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1),
    background 0.5s ease,
    box-shadow 0.5s ease;
}
.day-card:hover {
  border-color: rgba(200,144,42,0.55);
  transform: translateY(-3px);
  background:
    linear-gradient(135deg, rgba(200,144,42,0.06), rgba(14,29,51,0));
  box-shadow:
    0 24px 48px -16px rgba(0,0,0,0.55),
    0 0 0 1px rgba(200,144,42,0.18) inset,
    0 16px 32px -10px rgba(200,144,42,0.18);
}
.day-card:hover::before { opacity: 1; }
/* Date number subtly grows + brightens, weekday turns brass on hover */
.day-card .dc-date .date {
  transition: color 0.35s ease, letter-spacing 0.45s cubic-bezier(0.2,0.8,0.2,1);
}
.day-card:hover .dc-date .date {
  color: #e6a836;  /* lighter brass with warmth */
  letter-spacing: 0.06em;
}
.day-card .dc-date .weekday {
  transition: color 0.35s ease;
}
.day-card:hover .dc-date .weekday { color: rgba(247,236,206,0.95); }
/* Right-side divider on the date column also gains warmth */
.day-card .dc-date {
  transition: border-color 0.5s ease;
}
.day-card:hover .dc-date {
  border-right-color: rgba(200,144,42,0.35);
}
.day-card.empty { opacity: 0.4; }
.day-card.empty:hover {
  border-color: rgba(247,236,206,0.12);
  transform: none;
  box-shadow: none;
  background: linear-gradient(135deg, rgba(247,236,206,0.04), rgba(14,29,51,0.0));
}
.day-card.empty:hover::before { opacity: 0; }

.dc-date {
  display: flex; flex-direction: column; gap: 0.2rem;
  border-right: 1px solid rgba(247,236,206,0.12);
  padding-right: 1.1rem;
}
.dc-date .date {
  font-family: var(--font-display);
  font-size: 2.1rem;
  letter-spacing: 0.04em;
  color: var(--brass);
  line-height: 1;
}
.dc-date .weekday {
  font-family: var(--font-head);
  font-style: italic;
  font-size: 0.85rem;
  color: rgba(247,236,206,0.7);
}
.dc-date .label {
  font-family: var(--font-body);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--brass);
  margin-top: 0.25rem;
}

.dc-slots {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6rem 1rem;
  align-items: start;
}
@media (max-width: 1024px) {
  .dc-slots { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .dc-slots { grid-template-columns: 1fr; }
}
.dc-slot {
  display: flex; flex-direction: column; gap: 0.15rem;
}
.dc-slot-label {
  font-family: var(--font-body);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--brass);
  opacity: 0.85;
}
.dc-artist {
  display: block;
  position: relative;
  width: 100%;
  /* Portrait 4:5 — works for both portrait headshots and landscape press
     photos (mild side crop), so every card frames the artist consistently. */
  aspect-ratio: 4/5;
  background: linear-gradient(135deg, var(--ink), #1f3658);
  border-radius: 3px;
  overflow: hidden;
  text-decoration: none;
  margin-bottom: 0.4rem;
  transition: transform 0.35s cubic-bezier(0.2,0.8,0.2,1), box-shadow 0.35s;
  border: 1px solid rgba(247,236,206,0.10);
}
.dc-artist-thumb {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Bias toward upper third where most press-photo faces live; per-artist
     overrides via the imagePos field on artists.js. */
  object-position: 50% 28%;
  filter: brightness(0.88) saturate(1.05);
  transition: transform 0.7s cubic-bezier(0.2,0.8,0.2,1), filter 0.35s;
}
.dc-artist::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(14,29,51,0.0) 40%, rgba(14,29,51,0.95) 100%);
  z-index: 1;
}
.dc-artist:hover {
  transform: translateY(-2px);
  border-color: var(--brass);
  box-shadow: 0 10px 22px rgba(0,0,0,0.4);
}
.dc-artist:hover .dc-artist-thumb {
  transform: scale(1.06);
  filter: brightness(0.95) saturate(1.1);
}
.dc-artist-name {
  position: absolute;
  left: 0.7rem; right: 0.7rem; bottom: 0.65rem;
  z-index: 2;
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--cream);
  line-height: 1.18;
  text-align: center;
  text-shadow: 0 2px 8px rgba(0,0,0,0.85);
  transform-origin: center bottom;
  transition: font-size 0.4s cubic-bezier(0.2, 0.8, 0.2, 1),
              text-shadow 0.4s ease;
}
/* On hover the name grows for emphasis — feels editorial, not gimmicky.
   Different effect than the headliners (which get the arpeggio reveal). */
@media (hover: hover) {
  .dc-artist:hover .dc-artist-name {
    font-size: 1.4rem;
    text-shadow: 0 3px 12px rgba(0,0,0,0.9);
  }
}
/* Secondary line for "feat." artists — smaller + slightly faded so it
   reads as a credit, not part of the headline. */
.dc-artist-name .dc-feat {
  display: block;
  font-size: 0.78em;
  font-weight: 400;
  font-style: italic;
  color: rgba(247,236,206,0.85);
  margin-top: 0.15em;
}
.dc-empty {
  font-family: var(--font-head);
  font-style: italic;
  color: rgba(247,236,206,0.4);
  font-size: 0.85rem;
}
.dc-slot.empty .dc-slot-label { opacity: 0.6; }
.dc-slot-tbc {
  font-family: var(--font-head);
  font-style: italic;
  font-size: 0.85rem;
  color: rgba(247,236,206,0.35);
  padding: 0.18rem 0;
}

@media (max-width: 720px) {
  .day-card {
    grid-template-columns: 1fr;
    gap: 0.6rem;
    padding: 0.9rem 1rem 1rem;
  }
  .dc-date {
    border-right: none;
    border-bottom: 1px solid rgba(247,236,206,0.12);
    padding-right: 0;
    padding-bottom: 0.6rem;
    flex-direction: row;
    align-items: baseline;
    gap: 0.7rem;
  }
  .dc-date .date { font-size: 1.4rem; }
  .dc-date .weekday { font-size: 0.78rem; }
  .dc-date .label { margin-top: 0; font-size: 0.5rem; }
}
/* Mobile: each artist becomes a contact-row — small circular face thumbnail
   on the left, slot label + name to the right. Keeps the visual hook of the
   photos while making the page scannable instead of dominated by 56 huge
   rectangles. */
/* ── MOBILE BOTTOM SHEET ─────────────────────────────────────
   On phone, tapping an artist opens this sheet sliding up from below
   instead of full-page navigation. Hidden on desktop (>600px). */
/* Sheet must sit ABOVE the page nav (z=1000) — when it's fully expanded
   the close X needs to be reachable, not hidden behind the brand bar. */
.sheet-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.78);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  z-index: 1098;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.32s ease, visibility 0s linear 0.32s;
}
.sheet-backdrop.open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.32s ease, visibility 0s linear 0s;
}
.artist-sheet {
  /* iOS Safari's bottom toolbar is translucent — its blur samples the
     pixels directly underneath it. If the sheet ends at the visible
     viewport bottom (e.g. `inset: 0` or `bottom: 0`), those pixels are
     the actual page (day cards / hero) and "leak through" the toolbar.
     Fix: anchor only at top with `100lvh` (LARGE viewport, ignores
     chrome) so the sheet's dark background extends INTO the chrome
     area, giving iOS only the sheet to sample. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;       /* fallback */
  height: 100lvh;      /* large viewport — covers under iOS chrome */
  z-index: 1099;
  background: var(--ink);
  color: var(--cream);
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  padding-bottom: env(safe-area-inset-bottom, 0);
  overflow: hidden;
  transform: translateY(100%);
  transition: transform 0.42s cubic-bezier(0.2,0.8,0.2,1);
  display: flex; flex-direction: column;
  box-shadow: 0 -10px 40px rgba(0,0,0,0.5);
  /* When closed, the sheet still exists in the DOM. On desktop the
     override centers it on screen with opacity:0 — an INVISIBLE element
     that still intercepts every click/hover beneath it. pointer-events:
     none releases pointer control until .open is added. */
  pointer-events: none;
}
.artist-sheet.open {
  transform: translateY(0);
  pointer-events: auto;
}
.sheet-handle {
  width: 40px; height: 4px;
  background: rgba(247,236,206,0.3);
  border-radius: 999px;
  margin: 10px auto 0;
}
/* Close X — lives inside .sheet-photo at top-left so it visually attaches
   to the photo and travels WITH the sheet as you drag it down. */
.sheet-close {
  position: absolute;
  top: 14px; left: 14px;
  width: 40px; height: 40px;
  background: rgba(14,29,51,0.45);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  border: 1px solid rgba(247,236,206,0.32);
  border-radius: 50%;
  color: var(--cream); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 4;
  padding: 0;
  transition: background 0.25s, border-color 0.25s, color 0.25s;
}
.sheet-close svg { width: 18px; height: 18px; pointer-events: none; }
.sheet-close:active {
  background: var(--brass);
  border-color: var(--brass);
  color: var(--ink);
}
/* Hide the page nav while the sheet is open so the close X (and the
   sheet's own header content) isn't blocked by the brand bar above. */
body.sheet-open #nav { top: -140px !important; }
/* When the artist sheet is open on phone, blank out all the body's
   direct children EXCEPT the sheet itself + its backdrop + the
   nested ticket modal. iOS Safari's translucent bottom toolbar
   samples whatever is under it on screen even through fixed
   elements — by hiding the page content there's nothing for iOS
   to reflect except the dark body background. */
@media (max-width: 600px) {
  body.sheet-open {
    background: var(--ink) !important;
  }
  body.sheet-open > section,
  body.sheet-open > header,
  body.sheet-open > footer,
  body.sheet-open > div:not(.sheet-backdrop):not(.ticket-modal),
  body.sheet-open > aside:not(.artist-sheet) {
    visibility: hidden;
  }
}
/* Larger touch target on the drag handle so it's easy to grab */
.sheet-handle {
  position: relative;
  cursor: grab;
  touch-action: none;
}
.sheet-handle::before {
  content: '';
  position: absolute;
  inset: -10px -50% -10px -50%;  /* big invisible hit area around the visible bar */
}
.sheet-handle:active { cursor: grabbing; }
.sheet-photo {
  position: relative;
  width: 100%;
  /* 16/10 → 16/12 (= 4/3) — Uri 2026-05-12: photo on the phone
     bottom-sheet was too short, ~20% more vertical so faces read.
     Bio + tags below still visible (sheet content scrolls). Desktop
     override (later) sets aspect-ratio:auto and uses full column.
     `flex-shrink: 0` so the photo keeps its aspect-ratio'd height
     and isn't squeezed by long content below. */
  aspect-ratio: 16/12;
  flex: 0 0 auto;
  overflow: hidden;
  margin-top: 12px;
  background: var(--ink);
}
.sheet-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity 0.18s ease;
}
.sheet-photo::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 60%, var(--ink) 100%);
}

/* ── THEME NIGHTS ON THE SHEET ─────────────────────────────────────────
   Match the day-poster theming when an artist of a themed night opens. */

/* Italy — tricolore stripe along the bottom of the photo. */
.artist-sheet.theme-italy .sheet-photo::before {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 4px;
  z-index: 4;
  background: linear-gradient(90deg,
    #008c45 0%, #008c45 33.33%,
    #f4f5f0 33.33%, #f4f5f0 66.66%,
    #cd212a 66.66%, #cd212a 100%);
}

/* Brazilian Night — yellow tag on the photo + green-tinted bottom fade. */
.artist-sheet.theme-brazil .sheet-photo::after {
  background: linear-gradient(180deg, transparent 55%, #133225 100%);
}
.artist-sheet.theme-brazil .sheet-photo::before {
  content: 'BRASILIANISCHE NACHT';
  position: absolute;
  /* Top-right — top-left has the .sheet-close button. */
  top: 0.9rem; right: 0.9rem;
  z-index: 4;
  font-family: var(--font-display);
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  padding: 0.35rem 0.7rem;
  background: #ffdf00;
  color: #009c3b;
}
html[lang="en"] .artist-sheet.theme-brazil .sheet-photo::before {
  content: 'BRAZILIAN NIGHT';
}
.artist-sheet.theme-brazil { background: #0e1e1a; }

/* ACT label weekend — minimal black sheet with the ACT mark. */
.artist-sheet.theme-act { background: #0a0a0a; }
.artist-sheet.theme-act .sheet-photo::after {
  background: linear-gradient(180deg, transparent 55%, #0a0a0a 100%);
}
.artist-sheet.theme-act .sheet-photo::before {
  content: 'ACT';
  position: absolute;
  top: 0.9rem; right: 0.9rem;
  z-index: 4;
  font-family: 'Helvetica Neue', system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  color: var(--cream);
  border-left: 3px solid #cc0000;
  padding-left: 0.55rem;
}
.sheet-content {
  position: relative;
  /* Big bottom padding so the YouTube embed (last item in the sheet)
     can scroll fully past iOS Safari's dynamic bottom toolbar — the
     toolbar covers ~50-90px when visible, plus safe-area for the
     home indicator. */
  padding: 1.4rem 1.5rem calc(2rem + env(safe-area-inset-bottom, 0px) + 6rem);
  overflow-y: auto;
  flex: 1 1 auto;
}
.sheet-eyebrow {
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--brass);
  margin-bottom: 0.8rem;
}
.sheet-name {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  letter-spacing: 0.02em;
  line-height: 0.98;
  color: var(--brass);
  margin-bottom: 0.7rem;
  /* Reserve room on the right for the Tickets button so long names never
     run under it. */
  padding-right: 5.5rem;
  /* Sweep-in reveal when sheet opens */
  opacity: 0;
  transform: translateY(14px);
  filter: blur(6px);
  transition: opacity 0.5s ease, transform 0.55s cubic-bezier(0.2,0.8,0.2,1), filter 0.5s ease;
}
.artist-sheet.open .sheet-name {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  transition-delay: 0.18s;
}
/* Secondary part of an artist name (parenthetical / feat. / ensemble suffix)
   appears on its own line, smaller, so it doesn't fight the Tickets button. */
.sheet-name-sub {
  display: block;
  font-family: var(--font-head);
  /* Upright so the italic "Prince" inside .ida-prince-em can read as a
     deliberate accent (italic-in-upright). */
  font-style: normal;
  font-weight: 400;
  font-size: 0.62em;
  letter-spacing: 0.01em;
  /* Sheet base is cream paper - ink so the sub-line ("Trio", "Group …",
     "feat. …", "A Prince Celebration", etc.) actually reads. Themed
     dark sheets (ACT / Brazil / Italy) override back to cream below. */
  color: rgba(14,29,51,0.78);
  margin-top: 0.25em;
  padding-right: 0;
}
.sheet-cred {
  font-family: var(--font-head);
  font-style: italic;
  font-size: 0.95rem;
  color: rgba(247,236,206,0.85);
  margin-bottom: 0.9rem;
}
.sheet-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1rem; }
.sheet-tag {
  font-family: var(--font-body);
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(247,236,206,0.85);
  padding: 0.3rem 0.65rem;
  border: 1px solid rgba(247,236,206,0.25);
  border-radius: 999px;
}
.sheet-bio {
  font-family: var(--font-body);
  font-size: 0.92rem;
  line-height: 1.55;
  color: rgba(247,236,206,0.86);
  margin-bottom: 1.4rem;
}
/* Embedded performance video — placeholder frame today, real <iframe>
   when the YouTube URL is wired in per artist. Lives in the sheet content
   so visitors don't bounce to YouTube to hear the artist play. */
.sheet-video {
  margin: 0 0 1.4rem;
}
.sheet-video-frame {
  position: relative;
  border: 1px solid rgba(247,236,206,0.16);
  border-radius: 6px;
  background: #0a0f1d;
  overflow: hidden;
  aspect-ratio: 16 / 9;
}
.sheet-video-label {
  position: absolute;
  top: 0.9rem; left: 1rem;
  z-index: 2;
  font-family: var(--font-body);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--brass);
  background: rgba(14,29,51,0.7);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
}
.sheet-video-placeholder {
  appearance: none;
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.85rem;
  background:
    radial-gradient(circle at 50% 50%, rgba(200,144,42,0.10) 0%, transparent 60%),
    #0a0f1d;
  border: 0;
  color: rgba(247,236,206,0.55);
  cursor: default;
  transition: color 0.25s ease;
}
.sheet-video-placeholder svg {
  width: 64px;
  height: 64px;
}
.sheet-video-placeholder-text {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}
.sheet-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Social row — small pill buttons with brand-style icons. Placeholder
   hrefs ("#") for now; wire to real artist data later. */
.sheet-socials {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.4rem;
  margin: 0 0 1.4rem;
}
.sheet-social {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.36rem 0.7rem 0.36rem 0.58rem;
  border: 1px solid rgba(247,236,206,0.22);
  border-radius: 999px;
  color: rgba(247,236,206,0.82);
  text-decoration: none;
  font-family: var(--font-body);
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transition: color 0.25s ease, border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}
.sheet-social svg {
  width: 13px; height: 13px;
  flex: 0 0 auto;
}
@media (hover: hover) {
  .sheet-social:hover {
    color: var(--brass);
    border-color: var(--brass);
    background: rgba(200,144,42,0.08);
    transform: translateY(-1px);
  }
}
/* Square Tickets button: sticky inside .sheet-content so it stays visible
   while the bio scrolls. Initial position aligns with the artist NAME row
   (eyebrow takes top, name takes second row, button rides at name's line).
   margin-bottom: -3.6rem pulls the eyebrow/name up so they flow next to
   the floated button instead of below it. */
/* Header row: eyebrow+name on the left, tickets pin on the right, bottom-
   aligned so the pin sits flush with the baseline of the name (not the
   top). Replaces the previous float/sticky placement. */
.sheet-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.4rem;
  margin-bottom: 0.9rem;
}
.sheet-header-text { flex: 1 1 auto; min-width: 0; }
.sheet-header .sheet-name { padding-right: 0; margin-bottom: 0; }
.sheet-tickets-pin {
  flex: 0 0 auto;
  position: relative;
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  /* 3D-feeling brass: gradient + bevel highlights + drop shadow so the
     button reads as a raised CTA rather than a flat tag. */
  background: linear-gradient(180deg, #e8b048 0%, #c8902a 55%, #9a6d20 100%);
  padding: 0.95rem 1.55rem;
  border-radius: 4px;
  border: 1px solid rgba(255,224,160,0.35);
  text-decoration: none;
  z-index: 3;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    inset 0 -1px 0 rgba(0,0,0,0.25),
    0 6px 18px rgba(0,0,0,0.5),
    0 1px 3px rgba(0,0,0,0.45);
  transition: background 0.25s, transform 0.18s ease, box-shadow 0.25s ease;
}
.sheet-tickets-pin:hover {
  background: linear-gradient(180deg, #f4c25a 0%, #d6a040 55%, #ad7d28 100%);
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 -1px 0 rgba(0,0,0,0.25),
    0 9px 22px rgba(0,0,0,0.55),
    0 1px 3px rgba(0,0,0,0.45);
}
.sheet-tickets-pin:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.35),
    0 2px 6px rgba(0,0,0,0.4);
}
/* Attention pulse: first time the pin is visible (on sheet open) it
   emits two expanding rings + a brightness flash, then settles. The JS
   adds .is-fresh on openSheet and removes it after 2.4s. */
.sheet-tickets-pin.is-fresh {
  animation: ticketPinFlash 0.9s ease-out 2;
}
.sheet-tickets-pin.is-fresh::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 2px;
  pointer-events: none;
  box-shadow: 0 0 0 0 rgba(255, 224, 160, 0.65);
  animation: ticketPinRing 1.2s ease-out 2;
}
@keyframes ticketPinFlash {
  0%, 100% { background: var(--brass); }
  40% { background: #ffe6a8; box-shadow: 0 4px 14px rgba(0,0,0,0.35), 0 0 18px rgba(255,224,160,0.7); }
}
@keyframes ticketPinRing {
  0%   { box-shadow: 0 0 0 0 rgba(255,224,160,0.65); }
  100% { box-shadow: 0 0 0 18px rgba(255,224,160,0); }
}

/* ── DESKTOP MODAL OVERRIDES FOR THE ARTIST SHEET ───────────────────────
   Phone is a bottom-sheet (handle + slide-up). Desktop reshapes that into
   a centered two-column modal: smaller photo on the left, content
   (eyebrow / name / cred / tags / socials / bio) on the right with the
   tickets pin riding on the name row. Phone styles untouched. */
@media (min-width: 601px) {
  .artist-sheet {
    /* Center on screen instead of anchoring to the bottom edge. */
    top: 50%;
    left: 50%;
    right: auto;
    bottom: auto;
    width: min(1280px, 95vw);
    max-height: 88vh;
    border-top-left-radius: 14px;
    border-top-right-radius: 14px;
    border-bottom-left-radius: 14px;
    border-bottom-right-radius: 14px;
    /* Two-column layout — overrides the default flex-column stack. Wider
       photo column gives landscape images horizontal room so band members
       aren't cropped off the sides. */
    display: grid;
    grid-template-columns: 460px 1fr;
    grid-template-rows: 100%;
    /* Closed: nudge down + fade. Open: settle centered + fade in. */
    transform: translate(-50%, -46%);
    opacity: 0;
    transition: transform 0.42s cubic-bezier(0.2,0.8,0.2,1),
                opacity 0.32s ease;
    box-shadow: 0 30px 80px rgba(0,0,0,0.55);
    overflow: hidden;
  }
  .artist-sheet.open {
    transform: translate(-50%, -50%);
    opacity: 1;
  }
  /* Drag handle is mobile-only. */
  .sheet-handle { display: none; }
  /* Photo column: fills full modal height; no fixed aspect ratio. */
  .sheet-photo {
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    margin-top: 0;
  }
  /* Whisper-soft right-edge fade — ends with partial darkening (~50% ink)
     rather than full ink so the photo is barely touched at the edge. */
  .sheet-photo::after {
    background: linear-gradient(90deg, transparent 90%, rgba(14,29,51,0.5) 100%);
  }
  /* Italy bottom tricolore stripe still works (4px bottom of left photo). */
  /* Brazil + ACT corner tags also still anchor to photo top-right — unchanged. */
  .sheet-content {
    padding: 2.4rem 2.6rem 2rem 1.4rem;
    overflow-y: auto;
    height: 100%;
  }
  .sheet-name {
    font-size: 2.7rem;
  }
  .sheet-cred {
    font-size: 1rem;
  }
  .sheet-bio {
    font-size: 0.95rem;
    line-height: 1.62;
  }
  .sheet-tickets-pin {
    top: 2.4rem;
  }
  .sheet-close {
    /* Stays at top-left of photo column — easier to spot on the dark photo. */
    top: 14px; left: 14px;
  }
}
.sheet-more {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-body);
  font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95rem 1.3rem;
  border-radius: 2px;
  border: 1px solid var(--brass);
  background: transparent;
  color: var(--brass);
  transition: background 0.25s, color 0.25s;
}
.sheet-more:hover { background: var(--brass); color: var(--ink); }
/* The previous rule "@media (min-width:601px) { .sheet-backdrop, .artist-sheet { display:none } }"
   hid the sheet entirely on desktop — that's why clicking a band on
   computer "did nothing". Sheet now shows on every screen size. */

@media (max-width: 600px) {
  /* Legacy V2 day-card "sticky section" rules below — kept dead since
     .day-card { display: none } hides those elements in V3. */
  .schedule-section { padding: 2.5rem 0 4rem; }
  .day-card {
    /* Override desktop grid — sticky needs the date row in normal block flow */
    display: block;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    overflow: visible;
  }
  .day-card:hover {
    background: none;
    border: none;
    transform: none;
    box-shadow: none;
  }
  .day-card::before { display: none; }
  .dc-date {
    position: sticky;
    top: 0;
    z-index: 5;
    background: rgba(14, 29, 51, 0.98);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    /* Span full width — offset the .wrap container's left/right padding */
    margin-left: -1.4rem; margin-right: -1.4rem;
    padding: 0.85rem 1.4rem;
    border-top: 1px solid rgba(247,236,206,0.06);
    border-bottom: 1px solid rgba(247,236,206,0.12);
    border-right: none;
    flex-direction: row;
    align-items: baseline;
    gap: 0.7rem;
  }
  .dc-slots { padding: 0.7rem 0 1rem; grid-template-columns: 1fr; gap: 0.6rem; }
  .dc-slot { gap: 0; }
  /* Slot label is shown as a chip on the banner instead of above */
  .dc-slot-label { display: none; }
  /* Each artist becomes a full-width landscape banner with the slot label
     chip top-left and the name overlaid bottom-left. Faces actually read. */
  .dc-artist {
    aspect-ratio: 16/7;
    height: auto;
    background: linear-gradient(135deg, var(--ink), #1f3658);
    border: 1px solid rgba(247,236,206,0.1);
    border-radius: 4px;
    margin-bottom: 0;
    padding: 0;
    overflow: hidden;
    position: relative;
    display: block;
  }
  .dc-artist::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(14,29,51,0.0) 35%, rgba(14,29,51,0.92) 100%);
    z-index: 1;
  }
  .dc-artist:hover { transform: none; box-shadow: none; border-color: rgba(247,236,206,0.18); }
  .dc-artist-thumb {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    flex: none;
    border-radius: 0;
    object-fit: cover;
    object-position: 50% 25%;
    border: none;
    filter: brightness(0.92) saturate(1.05);
  }
  .dc-artist-name {
    position: absolute;
    left: 0.85rem; right: 0.85rem; bottom: 0.65rem;
    z-index: 2;
    font-family: var(--font-head);
    font-size: 1.05rem;
    line-height: 1.15;
    color: var(--cream);
    text-shadow: 0 1px 6px rgba(0,0,0,0.7);
  }
  /* Slot label chip — top-right corner. Most press photos place the
     subject at center/left, so right-side keeps it from landing on faces. */
  .dc-artist[data-slot]::before {
    content: attr(data-slot);
    position: absolute;
    top: 0.55rem; right: 0.6rem;
    z-index: 2;
    font-family: var(--font-body);
    font-size: 0.5rem;
    font-weight: 500;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--brass);
    background: rgba(14,29,51,0.6);
    padding: 0.25rem 0.55rem;
    border-radius: 999px;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
  }
  .dc-slot-tbc {
    font-size: 0.85rem;
    padding: 0.6rem 0.85rem;
    color: rgba(247,236,206,0.45);
    display: block;
  }
  .dc-slot.empty {
    background: rgba(247,236,206,0.03);
    border: 1px dashed rgba(247,236,206,0.1);
    border-radius: 4px;
  }
  .dc-slot.empty .dc-slot-label {
    display: block;
    padding: 0.5rem 0.85rem 0;
    font-size: 0.5rem;
    letter-spacing: 0.24em;
  }
}

/* ═══════════════════════════════════════════════════════════════════
 * V5 OVERRIDES — cream/parchment everywhere. Kill every remaining blue.
 * Day-posters, popup sheet, ticket modal: all flip to warm cream surfaces
 * with ink type and brass accents. Photos keep their treatment.
 * ═══════════════════════════════════════════════════════════════════ */

/* Day-poster card: warm parchment fill instead of dark blue. */
.day-poster { background: var(--day-tint, #f0e4c6); }
.dp-photo { background: rgba(14,29,51,0.10); }

/* All info-column text now reads ink-on-cream. */
.dp-month { color: rgba(14,29,51,0.78); }
.dp-weekday { color: rgba(14,29,51,0.78); }
.dp-time { color: rgba(14,29,51,0.55); }
.dp-name { color: var(--brass); }
.dp-act-link { border-bottom-color: rgba(14,29,51,0.10); }
.dp-act-link:last-child { border-bottom-color: rgba(14,29,51,0.10); }
@media (hover: hover) {
  .dp-act-link:hover .dp-name { color: #8a5e15; }
  .dp-act-link:hover { border-bottom-color: rgba(200,144,42,0.45); }
}

/* Connector / secondary on desktop split-name (was cream-faded on dark). */
@media (min-width: 601px) {
  .dp-name-connector { color: rgba(14,29,51,0.72); }
  .dp-name-secondary { color: rgba(14,29,51,0.62); }
}

/* Italy / Brazil / ACT themed nights — keep their original dark/colour
   treatments as INTENTIONAL exceptions on the cream paper. Italian flag
   bands on Italy night, deep tropical green on Brazil, black on ACT.
   On these dark surfaces, the V5 ink-on-cream type would disappear — so
   the date/lineup text flips back to cream tones for the themed days. */
.day-poster.theme-italy .dp-month,
.day-poster.theme-italy .dp-weekday,
.day-poster.theme-italy .dp-time,
.day-poster.theme-brazil .dp-month,
.day-poster.theme-brazil .dp-weekday,
.day-poster.theme-brazil .dp-time,
.day-poster.theme-act .dp-month,
.day-poster.theme-act .dp-weekday,
.day-poster.theme-act .dp-time { color: rgba(247,236,206,0.85); }
.day-poster.theme-italy .dp-act-link,
.day-poster.theme-italy .dp-act-link:last-child,
.day-poster.theme-brazil .dp-act-link,
.day-poster.theme-brazil .dp-act-link:last-child,
.day-poster.theme-act .dp-act-link,
.day-poster.theme-act .dp-act-link:last-child {
  border-bottom-color: rgba(247,236,206,0.18);
}
.day-poster.theme-italy .dp-name-connector,
.day-poster.theme-italy .dp-name-secondary,
.day-poster.theme-brazil .dp-name-connector,
.day-poster.theme-brazil .dp-name-secondary,
.day-poster.theme-act .dp-name-connector,
.day-poster.theme-act .dp-name-secondary { color: rgba(247,236,206,0.78); }

/* Phone festival-list date-block on non-themed days: ink-on-cream. */
@media (max-width: 600px) {
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-date-block {
    background: rgba(14,29,51,0.08);
    color: var(--ink);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info { background: transparent; }
  /* Phone non-themed days: the secondary line ("Brothers" / "A Tribute to
     Prince" / "Trio" / "feat. …") was cream-white-on-cream from the base
     phone CSS — unreadable on parchment. Flip to ink tones on cream.
     2026-05-14: primary + feat darkened from brass → ink so band names
     read confidently on every parchment day-tint on phone. */
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-primary,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-feat {
    color: var(--ink);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-secondary {
    color: rgba(14,29,51,0.72);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-connector {
    color: rgba(14,29,51,0.78);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-time {
    color: rgba(14,29,51,0.55);
  }
}

/* ── ARTIST POPUP SHEET — flip to cream ─────────────────────────── */
.artist-sheet {
  background: var(--cream);
  color: var(--ink);
}
.sheet-photo { background: rgba(14,29,51,0.08); }
.sheet-photo::after {
  background: linear-gradient(180deg, transparent 60%, rgba(14,29,51,0.10) 100%);
}
.sheet-content { color: var(--ink); }
.sheet-eyebrow { color: rgba(14,29,51,0.62); }
.sheet-name { color: var(--brass); }
@media (max-width: 600px) {
  /* Themed-day popups (Italy / Brazil / ACT) — match the bigger
     primary-name size used by the non-themed cream popups. Color,
     texture-or-not, and everything else stays as before; only the
     size moves. */
  .artist-sheet.theme-act .sheet-name,
  .artist-sheet.theme-brazil .sheet-name,
  .artist-sheet.theme-italy .sheet-name {
    font-size: clamp(2.1rem, 10vw, 3.2rem) !important;
    line-height: 0.92 !important;
  }
  /* Phone popup — band name in near-black ink at a bigger size so it
     reads as the loudest thing on the sheet. Texture: fractal-noise
     paper grain clipped to the type, so the ink looks risograph /
     letterpress-printed rather than digitally flat. Themed dark popups
     keep their plain brass treatment. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name {
    font-size: clamp(2.1rem, 10vw, 3.2rem) !important;
    line-height: 0.92 !important;
    letter-spacing: 0.008em;
    font-weight: 700;
    /* Blue Note Records cobalt — a recognizable deep navy that lives
       inside the festival's existing blue palette. Texture is a
       darker, gentler noise (soft-light blend) so the blue stays
       clearly blue and doesn't get washed-out by the grain. */
    background-color: #050d24;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.55  0 0 0 0 0.65  0 0 0 0 0.85  0 0 0 0.28 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 180px 180px;
    background-blend-mode: soft-light;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
  /* Wrap "X Group" headlines (Ida) on one no-wrap line so the small
     "Group" can't be pushed to its own line. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name .sheet-name-row {
    display: block;
    white-space: nowrap;
  }
  /* Sub-line sits inside the textured .sheet-name container — its own
     fill must be restored or it inherits the transparent fill from the
     parent and disappears. Opaque medium gray (not alpha-blended) so
     the parent's textured-blue background-clip:text can't bleed
     through the half-transparent fill — that bleed was making
     "Quartet" appear blue with only its descender reading as gray. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name .sheet-name-sub {
    /* Darker gray base + the same fractal-noise paper-grain clipped
       through the type, so the sub-line reads as a tonal match to the
       big textured band name (just smaller, italic, dimmer). Opaque
       fill underneath stops the parent's blue clip from bleeding. */
    background-color: #4f5358;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.78  0 0 0 0 0.78  0 0 0 0 0.78  0 0 0 0.32 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 180px 180px;
    background-blend-mode: soft-light;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
  /* "Group" inside Ida's headline — render small italic on the same
     line as the primary name, like a feat./Trio/Quartet treatment.
     Re-establishes solid black fill (parent is texture-clipped to
     transparent). */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name .sheet-name-connector {
    display: inline;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 0.4em;
    font-weight: 400;
    letter-spacing: 0.01em;
    padding-left: 0.2em;
    vertical-align: 0.3em;
    background-color: #4f5358;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.78  0 0 0 0 0.78  0 0 0 0 0.78  0 0 0 0.32 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 180px 180px;
    background-blend-mode: soft-light;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
  /* Sub-line ("Quartet", "Brothers", "feat. …", "Farewell Tour",
     "A Prince Celebration") on the cream popup — italic Playfair serif
     in dark gray so it's visually clearly distinct from the big blue
     Bebas band name above (different font, different style, different
     colour). Italic "Prince" inside still reads as a tonal accent. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name-sub {
    color: #7a7a7a;
    font-size: 0.56em !important;
    font-family: var(--font-head);
    font-style: italic;
    font-weight: 400;
    letter-spacing: 0.012em;
    line-height: 1.05;
    margin-top: 0.32em;
    opacity: 1;
  }
  /* Inside an italic sub-line, flip "Prince" back to upright so it
     still reads as the deliberate accent (upright-in-italic). */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name-sub .ida-prince-em {
    font-style: normal;
  }
  /* Pin the Tickets button to the TOP of the name area so it doesn't
     slide down when the name has a sub-line. */
  .sheet-header { align-items: flex-start; }
  .sheet-tickets-pin { align-self: flex-start; margin-top: 0.4rem; }
}
.sheet-cred { color: rgba(14,29,51,0.72); }
.sheet-tags .sheet-tag {
  background: rgba(14,29,51,0.08);
  color: var(--ink);
  border-color: rgba(14,29,51,0.18);
}
.sheet-bio { color: rgba(14,29,51,0.78); }
.sheet-socials .sheet-social {
  background: rgba(14,29,51,0.06);
  color: var(--ink);
  border-color: rgba(14,29,51,0.18);
}
.sheet-socials .sheet-social:hover {
  background: var(--brass);
  color: var(--cream);
  border-color: var(--brass);
}
.sheet-video-frame { background: rgba(14,29,51,0.08); }
.sheet-video-label { color: rgba(14,29,51,0.65); }
.sheet-video-placeholder { color: rgba(14,29,51,0.55); }
.sheet-video-placeholder-text { color: rgba(14,29,51,0.55); }
.sheet-close,
.sheet-handle { color: var(--ink); }

/* Sheet desktop right-edge fade now blends into cream, not ink. */
@media (min-width: 601px) {
  .sheet-photo::after {
    background: linear-gradient(90deg, transparent 90%, rgba(14,29,51,0.10) 100%);
  }
}

/* Tickets pin stays brass but lives on cream now — keep contrast. */

/* ── TICKETS MODAL — cream ──────────────────────────────────────── */
.ticket-modal-card {
  background: var(--cream);
  color: var(--ink);
}
.ticket-modal-card h3 { color: var(--ink); }
.ticket-modal-card p { color: rgba(14,29,51,0.72); }
.ticket-modal-close {
  color: var(--ink);
  border-color: rgba(14,29,51,0.25);
}
.ticket-option {
  background: rgba(14,29,51,0.04);
  border-color: rgba(14,29,51,0.15);
  color: var(--ink);
}
.ticket-option:hover {
  background: rgba(200,144,42,0.10);
  border-color: var(--brass);
}
.ticket-option strong { color: var(--ink); }
.ticket-option span { color: rgba(14,29,51,0.7); }

/* Schedule section bg should be transparent so the body cream shows. */
.schedule-section { background: transparent; }

/* ── Themed dark popup sheets (ACT, Brazil) — flip text back to cream ─
   The V5 base `.artist-sheet { background: cream; color: ink }` override
   gets beaten by `.artist-sheet.theme-act { background: #0a0a0a }` (more
   specific), so the sheet stays black on ACT nights — but my ink-on-cream
   text colors above carry over and become invisible. Same for Brazil's
   deep-green sheet. These rules restore cream-on-dark type for those
   themed popups. */
.artist-sheet.theme-act,
.artist-sheet.theme-brazil { color: var(--cream); }
.artist-sheet.theme-act .sheet-eyebrow,
.artist-sheet.theme-brazil .sheet-eyebrow { color: rgba(247,236,206,0.62); }
.artist-sheet.theme-act .sheet-name,
.artist-sheet.theme-brazil .sheet-name { color: var(--brass); }
/* Desktop popup, non-themed days — keep the brass color but clip the
   same fractal-noise paper grain through it so it reads as printed
   ink/leaf rather than flat digital fill. Themed sheets keep plain
   brass (the dark backgrounds already give the type enough character). */
@media (min-width: 601px) {
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name {
    background-color: #c8902a;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.18  0 0 0 0 0.10  0 0 0 0 0.02  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 180px 180px;
    background-blend-mode: multiply;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
  /* The sub-line inside the textured .sheet-name needs its own solid
     fill — otherwise it inherits transparent and disappears. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name .sheet-name-sub {
    -webkit-text-fill-color: rgba(14, 29, 51, 0.78);
    color: rgba(14, 29, 51, 0.78);
    background: none;
  }
  /* "Group" inline accent — small italic next to primary, like
     feat./Trio styling. */
  .artist-sheet:not(.theme-act):not(.theme-brazil):not(.theme-italy) .sheet-name .sheet-name-connector {
    display: inline;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 0.5em;
    font-weight: 400;
    letter-spacing: 0.01em;
    padding-left: 0.2em;
    vertical-align: 0.3em;
    -webkit-text-fill-color: rgba(14, 29, 51, 0.78);
    color: rgba(14, 29, 51, 0.78);
    background: none;
  }
}
.artist-sheet.theme-act .sheet-name-sub,
.artist-sheet.theme-brazil .sheet-name-sub { color: rgba(247,236,206,0.85); }
/* Italia popup background is cream (no dark theme override) — give the
   sub-line the same italic-Playfair / dark-gray treatment as the rest
   of the cream popups so "20 Years Handful of Soul" /
   "Italian Soundtracks" actually reads instead of disappearing into
   the paper. */
.artist-sheet.theme-italy .sheet-name-sub {
  color: #4f5358;
  font-family: var(--font-head);
  font-style: italic;
  font-weight: 400;
  font-size: 0.56em;
  letter-spacing: 0.012em;
  line-height: 1.05;
  margin-top: 0.32em;
}
.artist-sheet.theme-act .sheet-cred,
.artist-sheet.theme-brazil .sheet-cred { color: rgba(247,236,206,0.78); }
.artist-sheet.theme-act .sheet-bio,
.artist-sheet.theme-brazil .sheet-bio { color: rgba(247,236,206,0.85); }
.artist-sheet.theme-act .sheet-tags .sheet-tag,
.artist-sheet.theme-brazil .sheet-tags .sheet-tag {
  background: rgba(247,236,206,0.08);
  color: var(--cream);
  border-color: rgba(247,236,206,0.18);
}
.artist-sheet.theme-act .sheet-socials .sheet-social,
.artist-sheet.theme-brazil .sheet-socials .sheet-social {
  background: rgba(247,236,206,0.06);
  color: var(--cream);
  border-color: rgba(247,236,206,0.18);
}
.artist-sheet.theme-act .sheet-video-frame,
.artist-sheet.theme-brazil .sheet-video-frame {
  background: rgba(247,236,206,0.08);
}
.artist-sheet.theme-act .sheet-video-label,
.artist-sheet.theme-act .sheet-video-placeholder,
.artist-sheet.theme-act .sheet-video-placeholder-text,
.artist-sheet.theme-brazil .sheet-video-label,
.artist-sheet.theme-brazil .sheet-video-placeholder,
.artist-sheet.theme-brazil .sheet-video-placeholder-text {
  color: rgba(247,236,206,0.65);
}
.artist-sheet.theme-act .sheet-photo::after,
.artist-sheet.theme-brazil .sheet-photo::after {
  background: linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.55) 100%);
}
@media (min-width: 601px) {
  .artist-sheet.theme-act .sheet-photo::after,
  .artist-sheet.theme-brazil .sheet-photo::after {
    background: linear-gradient(90deg, transparent 90%, rgba(0,0,0,0.5) 100%);
  }
}

/* Partner cards that should NOT be flattened to a dark silhouette.
   Rolling Stone has a 3D striped wordmark that turns to mush under the
   brightness(0)/invert filter — let it render in its natural greys. */
.partner-card.partner-card--no-invert img {
  filter: none;
  opacity: 1;
}

/* ── Venues showcase — force readable cream type on the photo ──────
   The V5 `.section-dark h2 { color: var(--ink) }` rule was beating
   `.showcase-venue-name` (lower specificity) and painting the villa
   name dark navy on top of the photo. These higher-specificity rules
   re-assert the bright-cream readable values. */
.section-dark .showcase-venue-name {
  color: #fff8e0;
  text-shadow: 0 4px 28px rgba(0,0,0,0.7), 0 1px 2px rgba(0,0,0,0.55);
}
.section-dark .showcase-venue-tag {
  color: #ffe9aa;
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
}
.section-dark .showcase-venue-body {
  color: #f7ecce;
  text-shadow: 0 1px 8px rgba(0,0,0,0.5);
}
/* V5: dt + dd were vertically misaligned because dt is 0.62rem while dd
   is 0.92rem and the grid defaulted to align-items: stretch — the smaller
   dt text "rode up" the box while dd sat lower. Centre-align the row so
   each label + value share an optical baseline. dt also gets a brighter
   colour + drop-shadow + slightly bigger size so the photo behind it
   doesn't drown the label. */
.section-dark .showcase-venue-meta {
  align-items: center;
  gap: 1.2rem 1.4rem;
}
.section-dark .showcase-venue-meta dt {
  color: #ffd57a;
  font-size: 0.72rem;
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
}
.section-dark .showcase-venue-meta dd {
  color: #f7ecce;
  text-shadow: 0 1px 6px rgba(0,0,0,0.55);
}

/* ── Lineup name hover — much louder on cream ────────────────────
   With dark blue surfaces gone, the previous "lighter brass" hover
   color (#ffe6a8) is barely visible. Push the active name into a
   deep saturated brass + scale up so the highlight is obvious. */
@media (hover: hover) {
  .dp-act-link:hover .dp-name,
  .dp-lineup .dp-act-link.photo-hover .dp-name {
    color: #6b3f0c;
    font-weight: 600;
    /* scale 1.14 made the longest names (Dejan Jovanovic Orchestra feat.
       Boban Marković, Gonzalo Rubalcaba Quintett feat. …) overflow the
       day-poster's clipped right edge. Drop to 1.05 — colour + weight do
       most of the hover signaling anyway. */
    transform: translateX(2px) scale(1.05);
    transform-origin: left center;
  }
  .dp-act-link:hover,
  .dp-lineup .dp-act-link.photo-hover {
    border-bottom-color: rgba(107,63,12,0.55);
  }
  /* On the desktop split-name (primary / connector / feat), brighten
     each segment so the whole featured-artists line lights up together. */
  .dp-act-link:hover .dp-name-primary,
  .dp-act-link:hover .dp-name-feat,
  .dp-lineup .dp-act-link.photo-hover .dp-name-primary,
  .dp-lineup .dp-act-link.photo-hover .dp-name-feat { color: #6b3f0c; }
  .dp-act-link:hover .dp-name-connector,
  .dp-act-link:hover .dp-name-secondary,
  .dp-lineup .dp-act-link.photo-hover .dp-name-connector,
  .dp-lineup .dp-act-link.photo-hover .dp-name-secondary { color: rgba(14,29,51,0.92); }
  /* Themed dark days (ACT black, Brazil deep green): the ink-on-cream
     hover color above turns invisible. Lift the secondary "Trio /
     Quartet" suffix + connector to a cream-tone on hover so it stays
     readable against the dark surface. */
  .day-poster.theme-act .dp-act-link:hover .dp-name-secondary,
  .day-poster.theme-act .dp-act-link:hover .dp-name-connector,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover .dp-name-secondary,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover .dp-name-connector,
  .day-poster.theme-brazil .dp-act-link:hover .dp-name-secondary,
  .day-poster.theme-brazil .dp-act-link:hover .dp-name-connector,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover .dp-name-secondary,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover .dp-name-connector {
    color: rgba(247,236,206,0.92);
  }
  /* Italy + Brazil + ACT: hovering the band name was making it DARKER
     (deep brass #6b3f0c), which sinks into the green/red/black surfaces.
     Override the primary-name hover here so it brightens to pure white
     instead — visible across every stripe / dark themed bg. */
  .day-poster.theme-italy .dp-act-link:hover .dp-name,
  .day-poster.theme-italy .dp-act-link:hover .dp-name-primary,
  .day-poster.theme-italy .dp-act-link:hover .dp-name-feat,
  .day-poster.theme-italy .dp-lineup .dp-act-link.photo-hover .dp-name,
  .day-poster.theme-italy .dp-lineup .dp-act-link.photo-hover .dp-name-primary,
  .day-poster.theme-italy .dp-lineup .dp-act-link.photo-hover .dp-name-feat,
  .day-poster.theme-brazil .dp-act-link:hover .dp-name,
  .day-poster.theme-brazil .dp-act-link:hover .dp-name-primary,
  .day-poster.theme-brazil .dp-act-link:hover .dp-name-feat,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover .dp-name,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover .dp-name-primary,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover .dp-name-feat,
  .day-poster.theme-act .dp-act-link:hover .dp-name,
  .day-poster.theme-act .dp-act-link:hover .dp-name-primary,
  .day-poster.theme-act .dp-act-link:hover .dp-name-feat,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover .dp-name,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover .dp-name-primary,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover .dp-name-feat {
    color: #ffffff;
  }
  .day-poster.theme-italy .dp-act-link:hover,
  .day-poster.theme-italy .dp-lineup .dp-act-link.photo-hover,
  .day-poster.theme-brazil .dp-act-link:hover,
  .day-poster.theme-brazil .dp-lineup .dp-act-link.photo-hover,
  .day-poster.theme-act .dp-act-link:hover,
  .day-poster.theme-act .dp-lineup .dp-act-link.photo-hover {
    border-bottom-color: rgba(255, 255, 255, 0.55);
  }
}

/* ── Photo-backed section headers — summer atmosphere ────────────
   The lineup heading and jam-sessions section now ride on top of a
   villa photo with a soft overlay. Cream type with drop shadow stays
   readable while the photo reinforces the open-air feel. */
.section-photo-header {
  position: relative;
  background-size: cover;
  background-position: center 40%;
  padding: clamp(5rem, 11vw, 9rem) clamp(1.6rem, 5vw, 4rem) clamp(4rem, 9vw, 7rem);
  text-align: center;
  margin-bottom: 4rem;
  overflow: hidden;
}
.section-photo-header .section-photo-overlay {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(14,29,51,0.25) 0%,
      rgba(14,29,51,0.45) 60%,
      rgba(14,29,51,0.62) 100%);
  pointer-events: none;
}
.section-photo-header .section-photo-content {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
}
.section-photo-header .section-tag {
  color: #ffe9aa;
  text-shadow: 0 1px 8px rgba(0,0,0,0.55);
}
.section-photo-header h2.big-h {
  color: #fff5d4 !important;
  text-shadow: 0 3px 22px rgba(0,0,0,0.55), 0 1px 2px rgba(0,0,0,0.45);
}
.section-photo-header h2.big-h em { color: var(--brass); }
.section-photo-header .section-rule { background: var(--brass); margin: 0 auto 1.4rem; }
.section-photo-header .jam-teaser {
  color: #ffe9aa;
  text-shadow: 0 1px 8px rgba(0,0,0,0.55);
}

/* Section-as-photo-bg (jam sessions). Same overlay pattern but applied
   to the whole <section>, with the body text centered on top. The
   tall top-padding pushes the headline + body down so they sit on the
   darker lower third of the night-villa photo. */
.section-photo-bg {
  position: relative;
  background-size: cover;
  background-position: center 35%;
  padding: clamp(11rem, 22vw, 18rem) 1rem clamp(6rem, 12vw, 9rem);
  overflow: hidden;
}
.section-photo-overlay-dark {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(14,29,51,0.65) 0%,
      rgba(14,29,51,0.78) 60%,
      rgba(14,29,51,0.85) 100%);
  pointer-events: none;
  z-index: 1;
}
.jam-on-photo { color: #ffe9aa !important; text-shadow: 0 1px 8px rgba(0,0,0,0.55); }
.jam-on-photo-title {
  color: #fff5d4 !important;
  text-shadow: 0 3px 22px rgba(0,0,0,0.6);
  position: relative;
  /* Display:inline-block + auto margins lets us anchor the asterisk-star
     to the top-left edge of the actual text without nudging the centered
     heading off its column. The parent wrap already has text-align:center. */
  display: inline-block;
  margin-left: auto;
  margin-right: auto;
}
/* Brass "bonus" asterisk-star floating above the top-left of the "A".
   Absolute / sits outside the text-flow so the heading itself stays
   visually balanced. */
/* Zero-width inline anchor sits right before the "A" in "After".
   The asterisk-star is positioned absolute relative to this anchor so it
   lands at the top-left of the "A" regardless of how the heading wraps. */
.jam-star-anchor {
  position: relative;
  display: inline;
}
.jam-star-anchor::before {
  content: '★';
  position: absolute;
  top: -0.15em;
  right: 0;
  margin-right: 0.02em;
  font-size: 0.32em;
  color: var(--brass);
  text-shadow: 0 2px 10px rgba(0,0,0,0.55);
  line-height: 1;
  pointer-events: none;
  white-space: nowrap;
}
.jam-on-photo-title em { color: var(--brass) !important; }
.jam-on-photo-body p { color: #f7ecce !important; text-shadow: 0 1px 8px rgba(0,0,0,0.55); }
.jam-on-photo-body p strong { color: #fff5d4 !important; }
.section-photo-bg .section-rule { background: var(--brass) !important; }

/* About section: two-column on desktop — text left, vertical-ish villa
   photo on the right. Phone collapses to single column (photo hidden
   to avoid duplicate of the gallery already above). */
@media (min-width: 901px) {
  .about-grid {
    display: grid;
    grid-template-columns: 1.7fr 1fr;
    gap: 4rem;
    align-items: start;
  }
  .about-photo {
    position: sticky;
    top: 6rem;
    aspect-ratio: 3/4;
    overflow: hidden;
    border-radius: 4px;
    box-shadow: 0 24px 48px -16px rgba(0,0,0,0.35);
  }
  .about-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 40%;
    display: block;
  }
}
@media (max-width: 900px) {
  .about-photo { display: none; }
}

/* ── Sheet close button — always-readable, never transparent ─────
   Was a translucent dark pill that disappeared against dark photo
   regions. Now a solid ink disc with a cream X — reads on any photo. */
.sheet-close {
  background: var(--ink) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  border: 1.5px solid rgba(247,236,206,0.85) !important;
  color: var(--cream) !important;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
}
.sheet-close:hover {
  background: var(--brass) !important;
  border-color: var(--brass) !important;
  color: var(--ink) !important;
}

/* ── Presented-by (top, under hero) — cream-darker surface ─────────
   Moved up from the bottom of the page so visitors meet the partners
   right after the hero. Cream-darker (deeper toast tone) bg with ink
   type and brass accents. Logo silhouettes stay ink against the warm
   bg. The taller padding gives the section room for two large logos. */
.presented-top-section {
  background: #e6d4a0;
  color: var(--ink);
  padding: clamp(5rem, 9vw, 8rem) clamp(1.4rem, 5vw, 4rem) clamp(5rem, 9vw, 7rem);
}
.presented-top-section .section-tag { color: rgba(14,29,51,0.62); }
.presented-top-section h2 { color: var(--ink); }
.presented-top-section h2 em { color: var(--brass); font-style: normal; }
.presented-top-section .section-rule { background: var(--brass); }
.presented-top-section .body-text p { color: rgba(14,29,51,0.78); }
.presented-top-section .body-text p strong { color: var(--ink); }
.presented-top-section .presented-logo {
  /* On the cream-darker surface, partner logos render as ink silhouettes
     instead of cream — match the V5 partners row. */
  filter: brightness(0) invert(0.18);
  opacity: 0.95;
}
@media (max-width: 600px) {
  /* Phone: drop the cream-darker tone — let the section sit on the
     regular body cream so it reads as one continuous surface from
     hero down through the Programm banner. */
  .presented-top-section { background: transparent; }
}

/* ── Lineup banner — huge "Programm" word over the garden photo ────
   The old "Open Air am Havelufer" tag/heading/teaser stack has been
   replaced with a single oversized word so the section reads instantly
   as the programme entry point. */
.section-photo-header-programm {
  padding-top: clamp(7rem, 14vw, 12rem);
  padding-bottom: clamp(5rem, 11vw, 9rem);
}
.section-photo-programm {
  font-family: var(--font-display);
  font-size: clamp(5rem, 22vw, 18rem) !important;
  line-height: 0.92 !important;
  letter-spacing: 0.04em;
  color: #fff5d4 !important;
  text-shadow: 0 4px 28px rgba(0,0,0,0.7), 0 1px 2px rgba(0,0,0,0.5);
  text-transform: uppercase;
  margin: 0;
  /* Compensate for the trailing letter-spacing after the final "M" so the
     optical centre of the strokes (not the bounding-box centre) lands on
     the page centre. Without this, the trailing 0.04em pushes the visible
     text slightly off-centre toward the right. */
  text-indent: -0.04em;
  position: relative;
}
/* One-shot sun-glint that sweeps diagonally across the PROGRAMM glyphs.
   The ::after duplicates the text on top of the original, masked to the
   text via background-clip so the bright streak only shows inside the
   letter shapes. Triggered by JS adding `.shine-on` when the heading
   enters the viewport. */
/* Sun-glint sweep CLIPPED to the PROGRAMM letters — not the photo behind.
   The ::after duplicates the H2 text on top with text-fill transparent,
   then paints a sliding bright streak via background-clip: text. The
   `mix-blend-mode: plus-lighter` makes the ::after invisible everywhere
   except where the streak gradient is bright — so the H2's cream colour
   + drop-shadow show through normally, and the streak only adds light. */
/* Sun-glint streak clipped to the PROGRAMM letters. The ::after duplicates
   the heading text and paints a bright/gold gradient inside the glyph
   shapes — opaque, no blend-mode trickery (which made the highlight
   invisible against the already-bright cream baseline). With opacity 0
   baseline and an opacity 0→1→0 keyframe, the overlay is fully gone
   before and after the sweep so nothing sticks. */
.section-photo-programm::after {
  content: var(--shine-text, 'PROGRAMM');
  position: absolute;
  inset: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-indent: inherit;
  text-align: center;
  background-image: linear-gradient(65deg,
    rgba(255, 255, 255, 0) 30%,
    rgba(255, 255, 255, 0.95) 44%,
    rgba(255, 255, 255, 1) 50%,
    rgba(255, 255, 255, 0.95) 56%,
    rgba(255, 255, 255, 0) 70%);
  background-size: 70% 100%;
  background-repeat: no-repeat;
  background-position: -75% 0;
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  filter: drop-shadow(0 0 14px rgba(255, 255, 255, 0.9));
  text-shadow: none;
  pointer-events: none;
  opacity: 0;
}
.section-photo-programm.shine-on::after {
  animation: programmShine 0.85s cubic-bezier(0.3, 0.4, 0.4, 1) forwards;
}
@keyframes programmShine {
  0%   { background-position: -75% 0; opacity: 0; }
  8%   { opacity: 1; }
  82%  { background-position: 175% 0; opacity: 1; }
  100% { background-position: 175% 0; opacity: 0; }
}
/* Add a brief brightness + white halo pulse on the whole heading so the
   white streak reads as actual light catching the surface (cream-on-cream
   alone is too low-contrast to perceive). Synchronised with the streak. */
.section-photo-programm.shine-on {
  animation: programmPulse 0.85s cubic-bezier(0.3, 0.4, 0.4, 1) forwards;
}
@keyframes programmPulse {
  0%   { filter: brightness(1) drop-shadow(0 0 0 transparent); }
  50%  { filter: brightness(1.35) drop-shadow(0 0 22px rgba(255, 255, 255, 0.75)); }
  100% { filter: brightness(1) drop-shadow(0 0 0 transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .section-photo-programm::after { display: none; }
}

/* ════════════════════════════════════════════════════════════════════
   DESKTOP-ONLY V4-NAVY PALETTE on the full-lineup day cards.
   Phone is locked (its own navy palette + photo days lives inside
   `@media (max-width: 600px)` already). This block ONLY paints the
   desktop poster info column navy and re-tints the text so nothing
   is ever dark-on-dark. Themed days (italy / brazil / act) keep their
   intentional flag/colour treatments via higher specificity.
   ═════════════════════════════════════════════════════════════════════ */
@media (min-width: 601px) {
  /* Per-day --day-tint overrides. The `.day-poster { background:
     var(--day-tint, #f0e4c6) }` base already paints from this var, so
     setting it per data-date is enough to change the right-side info
     column from cream parchment to navy. */
  /* program.js sets `--day-tint` via inline style="--day-tint:#XXX" on
     every poster — `!important` is required here to beat that. */
  .day-poster[data-date="20.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #1F3556 !important; background: #1F3556 !important; }
  .day-poster[data-date="22.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #2e4565 !important; background: #2e4565 !important; }
  .day-poster[data-date="23.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #08152b !important; background: #08152b !important; }
  .day-poster[data-date="24.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #3d5d8a !important; background: #3d5d8a !important; }
  .day-poster[data-date="25.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #1F3556 !important; background: #1F3556 !important; }
  .day-poster[data-date="26.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #154b86 !important; background: #154b86 !important; }
  .day-poster[data-date="27.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #0e1d33 !important; background: #0e1d33 !important; }
  .day-poster[data-date="29.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #2e4565 !important; background: #2e4565 !important; }
  .day-poster[data-date="30.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #154b86 !important; background: #154b86 !important; }
  .day-poster[data-date="31.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) { --day-tint: #2e4565 !important; background: #2e4565 !important; }

  /* Band names: bright white with a very fine grain inside the
     letterforms (background-clip: text + low-alpha fractal-noise SVG),
     so they read as "printed on the textured paper" rather than flat
     pixels. Heavier weight + clear cream-on-navy contrast. */
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-primary,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-feat {
    color: transparent;
    -webkit-text-fill-color: transparent;
    background-image:
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.18 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"),
      linear-gradient(#ffffff, #ffffff);
    background-size: 240px 240px, 100% 100%;
    background-repeat: repeat, no-repeat;
    -webkit-background-clip: text;
            background-clip: text;
    font-weight: 600;
  }
  @media (hover: hover) {
    .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-act-link:hover .dp-name {
      /* On hover, kick the grain off momentarily by overriding with a
         solid bright fill so the active name is the brightest thing. */
      background-image: linear-gradient(#fffbe8, #fffbe8);
    }
    /* Mirror the underline-on-hover effect when the matching PHOTO is
     hovered — without this the name highlight appears but the underline
     stays invisible (cream at 0.14 alpha). */
    .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-lineup .dp-act-link.photo-hover {
      border-bottom-color: rgba(247, 236, 206, 0.55);
    }
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-month,
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-weekday {
    color: rgba(247, 236, 206, 0.86);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-time {
    color: rgba(247, 236, 206, 0.62);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-connector {
    color: rgba(247, 236, 206, 0.86);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-name-secondary {
    color: rgba(247, 236, 206, 0.74);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-act-link {
    border-bottom-color: rgba(247, 236, 206, 0.14);
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-act-link:last-child {
    border-bottom-color: transparent;
  }
  /* Hover: dim cream-tinted brass to a brighter brass so it reads as
     active state against the navy. Previous hover (#8a5e15, darker
     brass) was meant for cream backgrounds — invisible on navy. */
  @media (hover: hover) {
    .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-act-link:hover .dp-name {
      color: #e6b250;
    }
    .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-act-link:hover {
      border-bottom-color: rgba(232, 178, 80, 0.55);
    }
  }

  /* Organic noise + soft light gradient on the navy info column. The SVG
     fractal-noise gives the navy a fine grain (like dyed paper / suede),
     and a low-opacity radial highlight from the top-left adds a subtle
     sense of depth — light catching a 3D-ish material rather than a flat
     fill. Both blend with the navy via overlay / soft-light so the hue
     stays unchanged. */
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info {
    position: relative;
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image:
      radial-gradient(circle at 18% 14%,
        rgba(255, 255, 255, 0.12),
        rgba(255, 255, 255, 0) 60%),
      radial-gradient(circle at 100% 100%,
        rgba(0, 0, 0, 0.20),
        rgba(0, 0, 0, 0) 55%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    background-size: 100% 100%, 100% 100%, 240px 240px;
    background-repeat: no-repeat, no-repeat, repeat;
    mix-blend-mode: soft-light;
    pointer-events: none;
    z-index: 0;
  }
  .day-poster:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info > * {
    position: relative;
    z-index: 1;
  }

  /* Crumpled-paper variant — only the BRIGHTER navy days (24.07 / 26.07 /
     30.07). Uses SVG turbulence at LOW baseFrequency so the noise pattern
     resolves into large soft splotches instead of fine grain, plus high
     contrast color matrix + overlay blend so the patches read as light
     hitting creases in a folded sheet. Combined with the existing
     top-left highlight, the surface starts to feel like a slightly
     crumpled coloured paper sheet rather than a flat fill. */
  .day-poster[data-date="24.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info::after,
  .day-poster[data-date="26.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info::after,
  .day-poster[data-date="30.07"]:not(.theme-italy):not(.theme-brazil):not(.theme-act) .dp-info::after {
    /* Water ripples — horizontally-stretched SVG `turbulence` (low X freq,
       higher Y freq) produces noise patches that stretch sideways and
       stack vertically, the way ripples on a calm surface look when seen
       from above. A second pass adds longer slow swells underneath.
       feTurbulence type='turbulence' (not fractalNoise) flows smoothly. */
    background-image:
      radial-gradient(circle at 18% 16%,
        rgba(255, 255, 255, 0.18),
        rgba(255, 255, 255, 0) 60%),
      radial-gradient(circle at 95% 95%,
        rgba(0, 0, 0, 0.20),
        rgba(0, 0, 0, 0) 60%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='400'><filter id='w1'><feTurbulence type='turbulence' baseFrequency='0.006 0.055' numOctaves='3' seed='7' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.14 0'/></filter><filter id='w2'><feTurbulence type='turbulence' baseFrequency='0.002 0.018' numOctaves='2' seed='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.07 0'/></filter><rect width='100%' height='100%' filter='url(%23w2)'/><rect width='100%' height='100%' filter='url(%23w1)'/></svg>");
    background-size: 100% 100%, 100% 100%, 1000px 400px;
    background-repeat: no-repeat, no-repeat, repeat;
    mix-blend-mode: overlay;
    opacity: 0.9;
  }
}

/* ── Phone-only special-day backgrounds ────────────────────────────
   Brazil day: full Brazilian-flag colour bands on the card background
   (mirrors how Italy day uses the tricolore on .dp-info). Victor Wooten
   day (24.07): his stage photo behind the lineup, with a dark overlay
   so the cream text stays readable. */
@media (max-width: 600px) {
  /* Brazil — the actual Brazilian flag (green field + yellow diamond +
     blue disc) rendered via inline SVG, then darkened slightly so the
     cream lineup text stays readable on top. */
  .day-poster.theme-brazil {
    background:
      linear-gradient(rgba(0,0,0,0.42), rgba(0,0,0,0.42)),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 20' preserveAspectRatio='xMidYMid slice'><rect width='28' height='20' fill='%23009c3b'/><polygon points='14,1.7 26.3,10 14,18.3 1.7,10' fill='%23ffdf00'/><circle cx='14' cy='10' r='3.5' fill='%23002776'/></svg>") center / cover no-repeat !important;
  }
  /* Photo-background days (phone only): Dee Dee 20.07, Victor 24.07,
     Tigran 26.07 (silver wash), Samara 29.07. Each gets the artist's
     stage photo full-bleed with a dark vignette overlay so cream text
     stays readable. Tigran's overlay is silvery-grey instead of navy
     to give that night a "silver" feel per Uri's note. */
  .day-poster[data-date="20.07"] {
    background:
      linear-gradient(180deg,
        rgba(14,29,51,0.45) 0%,
        rgba(14,29,51,0.55) 35%,
        rgba(14,29,51,0.80) 100%),
      url('/assets/img/artists/dee-dee-bridgewater.jpg') 50% 20% / cover no-repeat !important;
    color: var(--cream);
  }
  .day-poster[data-date="25.07"] {
    background:
      linear-gradient(180deg,
        rgba(14,29,51,0.45) 0%,
        rgba(14,29,51,0.55) 35%,
        rgba(14,29,51,0.78) 100%),
      url('/assets/img/victor-wooten.jpg') 32% 22% / cover no-repeat !important;
    color: var(--cream);
  }
  .day-poster[data-date="26.07"] {
    /* Tigran's hero shot — standing in the silver elevator chamber. The
       photo itself reads silver/metal, so the overlay is a soft dark
       vignette (not a silver wash) so cream text stays readable without
       further desaturating the existing palette. */
    background:
      linear-gradient(180deg,
        rgba(14,29,51,0.35) 0%,
        rgba(14,29,51,0.50) 40%,
        rgba(14,29,51,0.75) 100%),
      url('/assets/img/artists/tigran-hamasyan-hero.jpg') 50% 20% / cover no-repeat !important;
    color: var(--cream);
  }
  .day-poster[data-date="29.07"] {
    background:
      linear-gradient(180deg,
        rgba(14,29,51,0.45) 0%,
        rgba(14,29,51,0.55) 35%,
        rgba(14,29,51,0.80) 100%),
      url('/assets/img/artists/samara-joy.jpg') 50% 12% / cover no-repeat !important;
    color: var(--cream);
  }

  /* V4-navy variations — wider spread so each night reads as a
     visibly different blue/midnight tone. Mid base, deep midnight,
     bright royal, slate-grey, saturated cobalt, soft denim. */
  .day-poster[data-date="22.07"] {
    background:
      linear-gradient(180deg,
        rgba(14,29,51,0.45) 0%,
        rgba(14,29,51,0.55) 35%,
        rgba(14,29,51,0.80) 100%),
      url('/assets/img/artists/ledisi.webp') 50% 22% / cover no-repeat !important;
    color: var(--cream);
  }
  .day-poster[data-date="23.07"] { --day-tint: #08152b !important; background: #08152b !important; }
  .day-poster[data-date="24.07"] { --day-tint: #3d5d8a !important; background: #3d5d8a !important; }
  .day-poster[data-date="27.07"] { --day-tint: #0e1d33 !important; background: #0e1d33 !important; }
  .day-poster[data-date="30.07"] { --day-tint: #154b86 !important; background: #154b86 !important; }
  .day-poster[data-date="31.07"] { --day-tint: #2e4565 !important; background: #2e4565 !important; }

  /* 27.07 — festival logo as a watermark behind the lineup. CSS mask
     paints a cream-tinted shape clipped to the logo SVG so it reads
     against the dark navy backdrop. */
  .day-poster[data-date="27.07"] {
    position: relative;
    background: #0e1d33 !important;
  }
  .day-poster[data-date="27.07"]::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(247,236,206,0.28);
    -webkit-mask-image: url('/assets/img/logo-designer.svg');
    mask-image: url('/assets/img/logo-designer.svg');
    /* Right side, dropped down so the painted "bridge" line at the top
     of the logo art sits just below the date-block underline instead
     of having the underline crossing the middle of the logo. */
    -webkit-mask-position: 96% 16%;
    mask-position: 96% 16%;
    -webkit-mask-size: 38% auto;
    mask-size: 38% auto;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    pointer-events: none;
    z-index: 0;
  }
  .day-poster[data-date="27.07"] > * { position: relative; z-index: 1; }

  /* PHONE TEXTURE: same fractal-noise + soft-light treatment used on the
     desktop navy days, applied to the phone non-themed non-photo days so
     the cards read as a material rather than a flat fill. Skips photo
     days (20/22/25/26/29), themed days (italy 21 / brazil 28 / act),
     and is safely under .day-poster's own children via z-index. The
     27.07 logo watermark stays intact because that uses ::before and
     this uses ::after on the SAME element. */
  .day-poster[data-date="23.07"],
  .day-poster[data-date="24.07"],
  .day-poster[data-date="30.07"],
  .day-poster[data-date="31.07"] {
    position: relative;
  }
  .day-poster[data-date="23.07"]::after,
  .day-poster[data-date="24.07"]::after,
  .day-poster[data-date="27.07"]::after,
  .day-poster[data-date="30.07"]::after,
  .day-poster[data-date="31.07"]::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image:
      radial-gradient(circle at 18% 14%,
        rgba(255, 255, 255, 0.12),
        rgba(255, 255, 255, 0) 60%),
      radial-gradient(circle at 100% 100%,
        rgba(0, 0, 0, 0.20),
        rgba(0, 0, 0, 0) 55%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    background-size: 100% 100%, 100% 100%, 240px 240px;
    background-repeat: no-repeat, no-repeat, repeat;
    mix-blend-mode: soft-light;
    pointer-events: none;
    z-index: 0;
  }
  .day-poster[data-date="23.07"] > *,
  .day-poster[data-date="24.07"] > *,
  .day-poster[data-date="30.07"] > *,
  .day-poster[data-date="31.07"] > * {
    position: relative;
    z-index: 1;
  }

  /* On every PHOTO day + every DARKER non-themed day on phone, flip text
     to cream-tones so it reads against the dark/photo surface. */
  .day-poster[data-date="20.07"] .dp-date-block,
  .day-poster[data-date="24.07"] .dp-date-block,
  .day-poster[data-date="26.07"] .dp-date-block,
  .day-poster[data-date="29.07"] .dp-date-block,
  .day-poster[data-date="22.07"] .dp-date-block,
  .day-poster[data-date="23.07"] .dp-date-block,
  .day-poster[data-date="25.07"] .dp-date-block,
  .day-poster[data-date="27.07"] .dp-date-block,
  .day-poster[data-date="30.07"] .dp-date-block,
  .day-poster[data-date="31.07"] .dp-date-block {
    background: rgba(14,29,51,0.42);
  }
  .day-poster[data-date="20.07"] .dp-number,
  .day-poster[data-date="20.07"] .dp-month,
  .day-poster[data-date="20.07"] .dp-weekday,
  .day-poster[data-date="24.07"] .dp-number,
  .day-poster[data-date="24.07"] .dp-month,
  .day-poster[data-date="24.07"] .dp-weekday,
  .day-poster[data-date="26.07"] .dp-number,
  .day-poster[data-date="26.07"] .dp-month,
  .day-poster[data-date="26.07"] .dp-weekday,
  .day-poster[data-date="29.07"] .dp-number,
  .day-poster[data-date="29.07"] .dp-month,
  .day-poster[data-date="29.07"] .dp-weekday,
  .day-poster[data-date="22.07"] .dp-number,
  .day-poster[data-date="22.07"] .dp-month,
  .day-poster[data-date="22.07"] .dp-weekday,
  .day-poster[data-date="23.07"] .dp-number,
  .day-poster[data-date="23.07"] .dp-month,
  .day-poster[data-date="23.07"] .dp-weekday,
  .day-poster[data-date="25.07"] .dp-number,
  .day-poster[data-date="25.07"] .dp-month,
  .day-poster[data-date="25.07"] .dp-weekday,
  .day-poster[data-date="27.07"] .dp-number,
  .day-poster[data-date="27.07"] .dp-month,
  .day-poster[data-date="27.07"] .dp-weekday,
  .day-poster[data-date="30.07"] .dp-number,
  .day-poster[data-date="30.07"] .dp-month,
  .day-poster[data-date="30.07"] .dp-weekday,
  .day-poster[data-date="31.07"] .dp-number,
  .day-poster[data-date="31.07"] .dp-month,
  .day-poster[data-date="31.07"] .dp-weekday {
    color: var(--cream) !important;
    text-shadow: 0 1px 6px rgba(0,0,0,0.55);
  }
  .day-poster[data-date="20.07"] .dp-time,
  .day-poster[data-date="24.07"] .dp-time,
  .day-poster[data-date="26.07"] .dp-time,
  .day-poster[data-date="29.07"] .dp-time,
  .day-poster[data-date="22.07"] .dp-time,
  .day-poster[data-date="23.07"] .dp-time,
  .day-poster[data-date="25.07"] .dp-time,
  .day-poster[data-date="27.07"] .dp-time,
  .day-poster[data-date="30.07"] .dp-time,
  .day-poster[data-date="31.07"] .dp-time {
    color: rgba(247,236,206,0.78) !important;
    text-shadow: 0 1px 6px rgba(0,0,0,0.55);
  }
  .day-poster[data-date="20.07"] .dp-name,
  .day-poster[data-date="20.07"] .dp-name-primary,
  .day-poster[data-date="20.07"] .dp-name-feat,
  .day-poster[data-date="24.07"] .dp-name,
  .day-poster[data-date="24.07"] .dp-name-primary,
  .day-poster[data-date="24.07"] .dp-name-feat,
  .day-poster[data-date="26.07"] .dp-name,
  .day-poster[data-date="26.07"] .dp-name-primary,
  .day-poster[data-date="26.07"] .dp-name-feat,
  .day-poster[data-date="29.07"] .dp-name,
  .day-poster[data-date="29.07"] .dp-name-primary,
  .day-poster[data-date="29.07"] .dp-name-feat,
  .day-poster[data-date="22.07"] .dp-name,
  .day-poster[data-date="22.07"] .dp-name-primary,
  .day-poster[data-date="22.07"] .dp-name-feat,
  .day-poster[data-date="23.07"] .dp-name,
  .day-poster[data-date="23.07"] .dp-name-primary,
  .day-poster[data-date="23.07"] .dp-name-feat,
  .day-poster[data-date="25.07"] .dp-name,
  .day-poster[data-date="25.07"] .dp-name-primary,
  .day-poster[data-date="25.07"] .dp-name-feat,
  .day-poster[data-date="27.07"] .dp-name,
  .day-poster[data-date="27.07"] .dp-name-primary,
  .day-poster[data-date="27.07"] .dp-name-feat,
  .day-poster[data-date="30.07"] .dp-name,
  .day-poster[data-date="30.07"] .dp-name-primary,
  .day-poster[data-date="30.07"] .dp-name-feat,
  .day-poster[data-date="31.07"] .dp-name,
  .day-poster[data-date="31.07"] .dp-name-primary,
  .day-poster[data-date="31.07"] .dp-name-feat {
    color: var(--cream) !important;
    text-shadow: 0 2px 12px rgba(0,0,0,0.55);
  }
  .day-poster[data-date="20.07"] .dp-name-connector,
  .day-poster[data-date="20.07"] .dp-name-secondary,
  .day-poster[data-date="24.07"] .dp-name-connector,
  .day-poster[data-date="24.07"] .dp-name-secondary,
  .day-poster[data-date="26.07"] .dp-name-connector,
  .day-poster[data-date="26.07"] .dp-name-secondary,
  .day-poster[data-date="29.07"] .dp-name-connector,
  .day-poster[data-date="29.07"] .dp-name-secondary,
  .day-poster[data-date="22.07"] .dp-name-connector,
  .day-poster[data-date="22.07"] .dp-name-secondary,
  .day-poster[data-date="23.07"] .dp-name-connector,
  .day-poster[data-date="23.07"] .dp-name-secondary,
  .day-poster[data-date="25.07"] .dp-name-connector,
  .day-poster[data-date="25.07"] .dp-name-secondary,
  .day-poster[data-date="27.07"] .dp-name-connector,
  .day-poster[data-date="27.07"] .dp-name-secondary,
  .day-poster[data-date="30.07"] .dp-name-connector,
  .day-poster[data-date="30.07"] .dp-name-secondary,
  .day-poster[data-date="31.07"] .dp-name-connector,
  .day-poster[data-date="31.07"] .dp-name-secondary {
    color: rgba(247,236,206,0.85) !important;
    text-shadow: 0 1px 8px rgba(0,0,0,0.5);
  }
  .day-poster[data-date="20.07"] .dp-act-link,
  .day-poster[data-date="24.07"] .dp-act-link,
  .day-poster[data-date="26.07"] .dp-act-link,
  .day-poster[data-date="29.07"] .dp-act-link,
  .day-poster[data-date="22.07"] .dp-act-link,
  .day-poster[data-date="23.07"] .dp-act-link,
  .day-poster[data-date="25.07"] .dp-act-link,
  .day-poster[data-date="27.07"] .dp-act-link,
  .day-poster[data-date="30.07"] .dp-act-link,
  .day-poster[data-date="31.07"] .dp-act-link {
    border-bottom-color: rgba(247,236,206,0.20);
  }

  /* Brazil day (28.07) — flag bg cycles through bright yellow, dark
     blue and green, so no single text colour reads cleanly across all
     three bands. Solution: cream text with a heavy dark drop-shadow
     halo that punches through every band — readable on yellow, green
     AND blue without resorting to a pill backdrop. */
  .day-poster.theme-brazil .dp-name,
  .day-poster.theme-brazil .dp-name-primary,
  .day-poster.theme-brazil .dp-name-feat {
    color: var(--cream) !important;
    text-shadow:
      0 0 14px rgba(0,0,0,0.85),
      0 1px 6px rgba(0,0,0,0.90),
      0 0 3px rgba(0,0,0,0.95);
  }
  .day-poster.theme-brazil .dp-name-connector,
  .day-poster.theme-brazil .dp-name-secondary {
    color: rgba(247,236,206,0.92) !important;
    text-shadow: 0 0 10px rgba(0,0,0,0.8), 0 1px 4px rgba(0,0,0,0.85);
  }
  .day-poster.theme-brazil .dp-time {
    color: rgba(247,236,206,0.85) !important;
    text-shadow: 0 0 8px rgba(0,0,0,0.8), 0 1px 4px rgba(0,0,0,0.85);
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   BJK MEMBER DISCOUNT + PRESENTED-BY BRANDING (2026-05-17)
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Artist popup: Tickets pin + compact BJK perk stacked together ──── */
.sheet-tickets-stack {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
}
/* Desktop: cancel the legacy `.sheet-tickets-pin { top: 2.4rem }` offset
   so the pin no longer overlaps the perk below it. Stack now positions
   itself; the pin sits at its natural top of the stack. */
@media (min-width: 601px) {
  .sheet-tickets-pin { top: 0; }
}
/* Phone: the locked rule `.sheet-tickets-pin { align-self: flex-start }`
   targeted the pin when it was a direct child of .sheet-header. Now it
   lives inside the stack, so that align-self pulls the pin to the LEFT
   edge of the column instead of staying right-aligned. Move the
   alignment / top-offset to the stack itself, and let the pin inherit
   the stack's flex-end. */
@media (max-width: 600px) {
  .sheet-tickets-pin { align-self: auto; margin-top: 0; }
  /* Stack mirrors the tickets pin width via `align-items: stretch` —
     pin keeps its natural width, perk fills the same horizontal space. */
  .sheet-tickets-stack {
    align-self: flex-start;
    margin-top: 0.4rem;
    align-items: stretch;
  }
  /* Compact two-line text perk on phone. The desktop big "50%" number
     is hidden here; both lines centred so nothing slides out. */
  .sheet-bjk-perk {
    box-sizing: border-box;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.42rem 0.4rem;
    gap: 0.18rem;
  }
  .sheet-bjk-perk-pct { display: none; }
  .sheet-bjk-perk-lines {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.18rem;
    width: 100%;
  }
  .sheet-bjk-perk-line {
    font-size: 0.55rem;
    letter-spacing: 0.16em;
    white-space: normal;
    text-align: center;
  }
  .sheet-bjk-perk-cta {
    font-size: 0.5rem;
    letter-spacing: 0.16em;
    white-space: normal;
    text-align: center;
  }
}
.sheet-bjk-perk {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.65rem;
  background: rgba(200,144,42,0.10);
  border: 1px solid rgba(200,144,42,0.38);
  border-radius: 4px;
  text-decoration: none;
  transition: background 0.2s, border-color 0.2s;
}
.sheet-bjk-perk:hover {
  background: rgba(200,144,42,0.18);
  border-color: var(--brass);
}
.sheet-bjk-perk-pct {
  font-family: var(--font-display);
  font-size: 1.45rem;
  line-height: 1;
  color: var(--brass);
  letter-spacing: 0.01em;
  flex: 0 0 auto;
}
.sheet-bjk-perk-lines {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.sheet-bjk-perk-line {
  font-family: var(--font-body);
  font-size: 0.55rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.sheet-bjk-perk-cta {
  font-family: var(--font-body);
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brass);
  white-space: nowrap;
}
/* Themed dark popups (ACT / Brazil) keep cream-on-dark */
.artist-sheet.theme-act .sheet-bjk-perk,
.artist-sheet.theme-brazil .sheet-bjk-perk {
  background: rgba(200,144,42,0.14);
  border-color: rgba(200,144,42,0.45);
}
.artist-sheet.theme-act .sheet-bjk-perk-line,
.artist-sheet.theme-brazil .sheet-bjk-perk-line {
  color: var(--cream);
}

/* ── Artist popup: Presented-by strip at sheet bottom ───────────────── */
.sheet-presented-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  margin: 0.4rem 0 0.6rem;
  padding: 1rem 0 0.4rem;
  border-top: 1px solid rgba(14,29,51,0.10);
}
.sheet-presented-label {
  font-family: var(--font-body);
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: rgba(14,29,51,0.55);
}
.sheet-presented-logo {
  height: 30px;
  width: auto;
  filter: brightness(0) invert(0.18);
  opacity: 0.86;
}
.sheet-presented-x {
  color: rgba(14,29,51,0.4);
  font-family: var(--font-head);
  font-style: italic;
  font-size: 0.85rem;
}
.artist-sheet.theme-act .sheet-presented-strip,
.artist-sheet.theme-brazil .sheet-presented-strip {
  border-top-color: rgba(247,236,206,0.15);
}
.artist-sheet.theme-act .sheet-presented-label,
.artist-sheet.theme-brazil .sheet-presented-label {
  color: rgba(247,236,206,0.55);
}
.artist-sheet.theme-act .sheet-presented-logo,
.artist-sheet.theme-brazil .sheet-presented-logo {
  filter: brightness(0) invert(1);
  opacity: 0.84;
}
.artist-sheet.theme-act .sheet-presented-x,
.artist-sheet.theme-brazil .sheet-presented-x {
  color: rgba(247,236,206,0.4);
}

/* ── Ticket modal: member row spans full width with a dashed divider
       above. BJK tag on the left, member price on the right — both
       baseline-aligned with the regular price above. ───────────────── */
.ticket-option .ticket-option-price {
  grid-row: 1;
}
.ticket-option .ticket-option-member {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  margin-top: 0.7rem;
  padding-top: 0.75rem;
  border-top: 1px dashed rgba(14,29,51,0.20);
}
.ticket-option .ticket-option-member-tag {
  font-family: var(--font-body);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--brass);
  padding: 0.32rem 0.6rem;
  border-radius: 2px;
  white-space: nowrap;
}
.ticket-option .ticket-option-member-amount {
  font-family: var(--font-display);
  font-size: 1.75rem;
  line-height: 1;
  color: var(--brass);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.ticket-modal-bjk-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  margin-top: 1rem;
  padding: 0.95rem 1.1rem;
  background: var(--brass);
  color: var(--ink);
  text-decoration: none;
  border-radius: 4px;
  transition: filter 0.25s, transform 0.2s;
}
.ticket-modal-bjk-cta:hover {
  filter: brightness(1.06);
  transform: translateX(2px);
}
.ticket-modal-bjk-line {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.ticket-modal-bjk-arrow {
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1;
}

/* ── Jam-sessions: Curator credit ───────────────────────────────────── */
.jam-curator-credit {
  margin: 1.4rem 0 0;
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(247,236,206,0.7);
  text-shadow: 0 1px 4px rgba(0,0,0,0.7);
}
.jam-curator-credit em {
  display: inline-block;
  font-family: var(--font-head);
  font-style: italic;
  font-weight: 400;
  font-size: 1.5em;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--cream);
  margin-left: 0.35em;
  transform: translateY(0.05em);
}
@media (min-width: 601px) {
  .jam-curator-credit { font-size: 0.78rem; }
  .jam-curator-credit em { font-size: 2em; }
}

/* ── About: BJK × ZigZag partnership line ───────────────────────────── */
.about-partnership-line {
  margin: 2rem 0 1.2rem !important;
  padding: 0.9rem 1.1rem;
  border-left: 2px solid var(--brass);
  background: rgba(200,144,42,0.05);
  font-family: var(--font-head);
  font-style: italic;
  font-size: 1.02rem;
  line-height: 1.45;
  color: var(--ink);
}
.about-partnership-line strong {
  font-style: normal;
  font-weight: 500;
  color: var(--ink);
}

/* ── YouTube tap-catcher (phone only) ───────────────────────────────── */
.sheet-video-tap-catcher {
  position: absolute;
  inset: 0;
  z-index: 5;
  appearance: none;
  border: 0;
  background: rgba(10, 15, 29, 0.46);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.sheet-video-tap-catcher::before {
  content: '';
  width: 78px;
  height: 78px;
  border-radius: 50%;
  background: rgba(247,236,206,0.94);
  box-shadow: 0 6px 24px rgba(0,0,0,0.45);
}
.sheet-video-tap-catcher::after {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border-left: 22px solid var(--ink);
  border-top: 14px solid transparent;
  border-bottom: 14px solid transparent;
  transform: translateX(5px);
}

/* ── Phone: enlarge the artist popup video frame for thumb safety ───── */
@media (max-width: 600px) {
  .sheet-video {
    margin-left: -1rem;
    margin-right: -1rem;
  }
  .sheet-video-frame {
    border-radius: 0;
  }
}

