/* ===== 1. HOME — full-bleed ===== */
.hero {
  position: relative;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  transform-origin: top center;
  will-change: transform;
  animation: hero-zoom 30s ease-out forwards;
}

/* Slow automatic 10% zoom-in, independent of scroll: plays once on load and
   holds at the zoomed-in frame. Reduced-motion gets a static frame. */
@keyframes hero-zoom {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(1.1);
  }
}

.reduce-motion .hero__media img {
  animation: none;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: var(--z-decor);
  background: rgba(10, 10, 10, 0.52);
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: var(--z-decor);
  width: 100%;
  padding-inline: var(--space-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero__title {
  margin-bottom: var(--space-4);
}

.hero__title img {
  width: min(70vw, 480px);
  height: auto;
  filter: drop-shadow(0 2px 20px rgba(0, 0, 0, 0.45));
}

.hero__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.hero__scroll-cue {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: var(--z-decor);
  width: 32px;
  height: 32px;
  color: var(--color-white-muted);
}

/* ===== 2. BIO — pinned scroll-reveal mask + portrait/editorial stack =====
   A white layer with a triangle cut out (via clip-path) scales up
   automatically once the section enters the viewport, over a fixed
   duration, progressively revealing the Bio content underneath. Time-driven
   (js/reveal.js), not scroll-linked: a scroll-linked version left the
   reveal stuck unfinished whenever the section was reached via an anchor
   jump (e.g. clicking "Bio" in the nav) rather than incremental scrolling.
   Disabled under reduced-motion: the section just renders Bio in normal
   flow with no mask. */
.bio-reveal {
  position: relative;
  height: 100vh;
  background: var(--color-black);
}

.bio-reveal__pin {
  position: relative;
  height: 100%;
  overflow: hidden;
}

.bio-reveal__stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  background: var(--color-black);
}

/* Starts invisible: at the very start of the reveal the triangle is tiny, and
   showing a fully-legible (if miniature) copy of Bio through it just reads as
   visual noise. js/reveal.js fades this in once the hole has opened enough
   for the content to actually be worth seeing — until then the hole simply
   shows the stage's own black background. */
.bio-reveal__stage .bio {
  opacity: 0;
}

.reduce-motion .bio-reveal__stage .bio,
.no-js .bio-reveal__stage .bio {
  opacity: 1;
}

/* The triangle hole is drawn as a real clip-path (rect minus triangle,
   evenodd), not mask-image: an image used as mask-image is only "present"
   within its own sized+positioned box, and the masked element is fully
   hidden everywhere outside that box — the opposite of what a shrinking
   cover needs. clip-path: path() has no such limitation. Points are set
   directly by js/reveal.js every frame. */
.bio-reveal__mask {
  position: absolute;
  inset: 0;
  background: var(--color-white);
  pointer-events: none;
}

.reduce-motion .bio-reveal {
  height: auto;
}

.reduce-motion .bio-reveal__pin {
  position: static;
  height: auto;
}

.reduce-motion .bio-reveal__stage {
  position: static;
  display: block;
}

.reduce-motion .bio-reveal__mask {
  display: none;
}

/* Below 1024px the stacked single-column layout (portrait photo + text)
   is reliably taller than 100vh, clipping content. Reveal effect only
   on ≥1024px where the 2-column grid keeps content within the viewport. */
@media (max-width: 1023px) {
  .bio-reveal {
    height: auto;
  }

  .bio-reveal__pin {
    position: static;
    height: auto;
  }

  .bio-reveal__stage {
    position: static;
    display: block;
  }

  .bio-reveal__mask {
    display: none;
  }

  .bio-reveal__stage .bio {
    opacity: 1;
  }
}

.bio {
  width: 100%;
  padding-block: var(--space-5);
  display: grid;
  gap: var(--space-5);
}

.bio__media {
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
}

.bio__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.bio__inner {
  max-width: 68ch;
  margin-inline: auto;
}

.bio__title {
  margin-bottom: var(--space-3);
}

.bio__lead {
  font-size: var(--fs-400);
  font-family: var(--font-display);
  font-weight: 800;
  margin-bottom: var(--space-4);
  max-width: 100%;
}

.bio__body {
  color: var(--color-white-muted);
  font-size: var(--fs-200);
  margin-bottom: var(--space-3);
  max-width: 100%;
}

.bio__pullquote {
  font-family: var(--font-display);
  font-size: var(--fs-700);
  font-weight: 800;
  color: var(--color-yellow);
  line-height: 1;
  margin-block: var(--space-5);
}

.bio__pullquote span {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-200);
  font-weight: 500;
  color: var(--color-white-muted);
  margin-top: var(--space-1);
}

@media (min-width: 1024px) {
  .bio {
    padding-block-start: 12vh;
    grid-template-columns: minmax(320px, 34%) 1fr;
    gap: var(--space-7);
    grid-template-rows: auto 1fr;
  }
}

/* On 1080p screens (height ≤ 1100px) the bio content overflows the 100vh
   clip boundary. Compress vertical spacing so everything stays visible. */
@media (min-width: 1024px) and (max-height: 1100px) {
  .bio {
    padding-block-start: 5vh;
  }

  .bio__lead {
    margin-bottom: var(--space-3);
  }

  .bio__body {
    margin-bottom: var(--space-2);
  }

  .bio__pullquote {
    margin-block: var(--space-3);
  }
}

@media (min-width: 1024px) {

  .bio__title {
    grid-column: 2;
    grid-row: 1;
    align-self: end;
    margin-bottom: var(--space-2);
  }

  .bio__media {
    grid-column: 1;
    grid-row: 1 / span 2;
    aspect-ratio: auto;
  }

  .bio__inner {
    grid-column: 2;
    grid-row: 2;
    margin-inline: 0;
  }
}

/* ===== 3. PRESS — full-bleed horizontal carousel, see css/press-carousel.css ===== */
.press {
  padding-block: var(--space-7);
  background: var(--color-black-soft);
  overflow: hidden;
}

.press__title {
  margin-bottom: var(--space-4);
}

@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* ===== 4. MUSIC — asymmetric split 40/60 ===== */
.split {
  padding-block: var(--space-7);
  background: var(--color-black);
  display: grid;
  gap: var(--space-5);
}

.split__text {
  max-width: 44ch;
}

.split__text p {
  color: var(--color-white-muted);
  margin-block: var(--space-3);
}

.split__embed {
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-black-soft);
}

.track-list-wrap {
  margin-top: var(--space-3);
}

.track-list__label {
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-white-muted);
  margin-bottom: var(--space-2);
}

.track-list {
  display: flex;
  flex-direction: column;
}

.track-list__item {
  border-bottom: 1px solid rgba(247, 247, 245, 0.08);
}

.track-list__item:first-child {
  border-top: 1px solid rgba(247, 247, 245, 0.08);
}

.track-list__item a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-3);
  text-decoration: none;
  color: var(--color-white);
}

.track-list__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.track-list__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-300);
}

.track-list__sub {
  font-size: var(--fs-100);
  color: var(--color-white-muted);
  margin-top: var(--space-1);
}

.track-list__badge {
  flex-shrink: 0;
  font-weight: 700;
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-yellow);
  border: 1px solid var(--color-yellow);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  white-space: nowrap;
}

.track-list__item a:hover .track-list__badge,
.track-list__item a:focus-visible .track-list__badge {
  background: var(--color-yellow);
  color: var(--color-black);
}

@media (min-width: 1024px) {
  .split--music {
    grid-template-columns: 2fr 3fr;
    align-items: center;
  }

  .split--music .track-list-wrap {
    grid-column: 1 / -1;
  }

  .split--podcast {
    grid-template-columns: 3fr 2fr;
  }

  .split--podcast .split__embed {
    order: -1;
  }
}

/* ===== 5. LIVE SETS — title above the player, triangle texture behind it ===== */
.live-sets {
  position: relative;
  background: var(--color-black);
  padding-block: var(--space-7);
  overflow: hidden;
}

/* Same triangle silhouette used in the Bio reveal, tiled as a faint white
   filled-icon texture (the same idea as martingarrix.com's +/x background
   grid), sitting behind the player. */
.live-sets__texture {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  pointer-events: none;
  background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><path d='M32 16 L46 48 L18 48 Z' fill='%23f7f7f5' opacity='0.18'/></svg>"),
    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><path d='M32 16 L46 48 L18 48 Z' fill='%23f7f7f5' opacity='0.12'/></svg>");
  background-size: 64px 64px;
  background-position: 0 0, 32px 32px;
}

.live-sets__inner {
  position: relative;
  z-index: var(--z-decor);
}

.live-sets__title {
  margin-bottom: var(--space-4);
}

.live-sets__layout {
  display: grid;
  gap: var(--space-3);
}

.live-sets__frame {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.live-sets__embed {
  aspect-ratio: 16 / 9;
  width: 100%;
}

/* "Up next" list: YouTube's own playlist embed only exposes its sidebar via
   a hidden expand control, not a persistent panel, regardless of iframe
   width (tested) — so this is our own list, built from the playlist's real
   videos, clicking an item swaps the player's src. */
.live-sets__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-height: 360px;
  overflow-y: auto;
  background: var(--color-black-soft);
  border-radius: var(--radius-md);
  padding: var(--space-2);
}

.live-sets__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1);
  text-align: left;
  cursor: pointer;
  color: var(--color-white-muted);
}

.live-sets__item img {
  flex-shrink: 0;
  width: 84px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.live-sets__item span {
  font-size: var(--fs-100);
  line-height: 1.3;
}

.live-sets__item:hover,
.live-sets__item:focus-visible {
  background: var(--color-black-soft);
  color: var(--color-white);
}

.live-sets__item[aria-current="true"] {
  background: var(--color-black-soft);
  color: var(--color-yellow);
}

.live-sets__more {
  display: inline-block;
  margin-top: var(--space-3);
  font-size: var(--fs-100);
  color: var(--color-white-muted);
}

.live-sets__more:hover,
.live-sets__more:focus-visible {
  color: var(--color-yellow);
}

@media (min-width: 1024px) {
  .live-sets__layout {
    grid-template-columns: 2.2fr 1fr;
    align-items: start;
  }

  /* Height is set inline by js/live-sets.js to exactly match the player's
     rendered height — aspect-ratio combined with grid stretch can make a
     sibling derive its width FROM a stretched height instead of the other
     way around, which blew the player way past the viewport when tried. */
  .live-sets__list {
    max-height: none;
  }
}

/* ===== 6. PODCAST — uses .split--podcast above ===== */
.podcast {
  background: var(--color-black-soft);
}

.podcast__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

@media (min-width: 480px) {
  .podcast__links {
    flex-wrap: nowrap;
  }

  .podcast__links .btn {
    flex: 1 1 0;
    justify-content: center;
    padding-inline: var(--space-2);
    font-size: var(--fs-100);
  }
}

/* ===== 7. GALLERY — full-bleed Pinterest-style bento grid, click to open
   lightbox ===== A dense grid (grid-auto-flow: dense) with a handful of
   cells spanning extra columns/rows in a repeating cycle, so photos read as
   genuinely different sizes (wider, taller, bigger), not just a uniform
   masonry of same-width columns. Runs edge to edge of the viewport — no
   .container on the grid itself, just the title above it. Click/tap any
   photo to open it full-size via the shared lightbox (js/lightbox.js). */
.gallery-grid {
  padding-block: var(--space-7);
  background: var(--color-black);
}

.gallery-grid__title {
  margin-bottom: var(--space-4);
}

.gallery-grid__grid {
  display: grid;
  grid-auto-flow: dense;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 150px;
  gap: var(--space-2);
  padding-inline: var(--space-2);
}

.gallery-grid__item {
  overflow: hidden;
  background: var(--color-black-soft);
}

.gallery-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s var(--ease-out-expo);
}

.gallery-grid__item:hover img,
.gallery-grid__item:focus-within img {
  transform: scale(1.05);
}

.reduce-motion .gallery-grid__item img {
  transition: none;
}

.gallery-grid__item:nth-child(7n+1) {
  grid-column: span 2;
  grid-row: span 2;
}

.gallery-grid__item:nth-child(7n+4) {
  grid-row: span 2;
}

.gallery-grid__item:nth-child(7n+6) {
  grid-column: span 2;
}

@media (min-width: 768px) {
  .gallery-grid__grid {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 180px;
  }
}

@media (min-width: 1024px) {
  .gallery-grid__grid {
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 200px;
  }
}

/* ===== 8. GIGS — "LIVE GIGS" cursor-reveal marquee + Bandsintown widget ===== */
.gigs {
  padding-block: var(--space-6) var(--space-7);
  background: var(--color-black-soft);
  overflow: hidden;
}

.gigs-marquee {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-6);
}

.gigs-marquee__row {
  position: relative;
  height: clamp(2.5rem, 7vw, 5.5rem);
  overflow: hidden;
}

.gigs-marquee__track {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  white-space: nowrap;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 6vw, 4.5rem);
  letter-spacing: 0.01em;
  will-change: transform;
}

.gigs-marquee__track--outline {
  color: var(--color-white);
}

/* The mask lives on this static wrapper (not on the scrolling track itself):
   masking the moving element directly would make the spotlight drift with
   the scroll instead of staying anchored to the cursor. */
.gigs-marquee__mask {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle 160px at var(--mx, -999px) var(--my, -999px), black 0%, black 55%, transparent 100%);
  mask-image: radial-gradient(circle 160px at var(--mx, -999px) var(--my, -999px), black 0%, black 55%, transparent 100%);
}

.gigs-marquee__track--fill {
  color: var(--color-yellow);
}

.gigs-marquee__row--left .gigs-marquee__track {
  animation: marquee-scroll 26s linear infinite;
}

.gigs-marquee__row--right .gigs-marquee__track {
  animation: marquee-scroll-reverse 22s linear infinite;
}

@keyframes marquee-scroll-reverse {
  from {
    transform: translateX(-50%);
  }
  to {
    transform: translateX(0);
  }
}

.reduce-motion .gigs-marquee__track {
  animation: none;
}

.gigs-bit {
  max-width: 1100px;
  margin-inline: auto;
}

/* Bandsintown ships its own light-theme boxes regardless of the widget's
   data-* color params; force every surface to match the page. */
.gigs-bit .bit-widget,
.gigs-bit .bit-follow-section-wrapper,
.gigs-bit .bit-play-my-city-wrapper {
  background: transparent !important;
}

.gigs-bit .bit-follow-section-heading-text,
.gigs-bit .bit-play-my-city-heading-text {
  color: var(--color-white-muted) !important;
  font-family: var(--font-body) !important;
  font-size: var(--fs-200) !important;
  margin-bottom: var(--space-2) !important;
}

/* Pill CTAs: Follow, Play My City, RSVP, Tickets, Notify Me */
.gigs-bit .bit-follow-section-cta,
.gigs-bit .bit-play-my-city-cta,
.gigs-bit .bit-rsvp.bit-button,
.gigs-bit .bit-offers.bit-button {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  background: var(--color-yellow) !important;
  color: var(--color-black) !important;
  border: none !important;
  border-radius: var(--radius-btn) !important;
  padding: var(--space-2) var(--space-4) !important;
  font-family: var(--font-body) !important;
  font-weight: 600 !important;
  font-size: var(--fs-100) !important;
  text-transform: uppercase !important;
  text-decoration: none !important;
  white-space: nowrap !important;
}

.gigs-bit .bit-rsvp-placeholder {
  display: none !important;
}

.gigs-bit .bit-upcoming-events-show-all-button {
  display: flex !important;
  justify-content: center !important;
  margin-top: var(--space-4) !important;
  background: transparent !important;
  color: var(--color-white-muted) !important;
  font-family: var(--font-body) !important;
  font-size: var(--fs-100) !important;
  text-transform: uppercase !important;
  letter-spacing: 0.06em !important;
  cursor: pointer !important;
}

.gigs-bit .bit-logo-link {
  opacity: 0.6;
}

/* js/gigs-fix.js extracts each event's real data out of Bandsintown's own
   (asynchronously-rendered, frequently cascade-fighting) markup and builds
   these plain rows instead — no selectors in common with their stylesheet,
   so there is nothing left for it to collide with. Originals are hidden,
   not removed. Mobile keeps a simple stacked card; desktop becomes a row. */
.gig-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-block: var(--space-3);
  border-bottom: 1px solid rgba(247, 247, 245, 0.1);
}

.gig-row__date {
  display: flex;
  flex-direction: column;
}

.gig-row__date-text {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-100);
  text-transform: uppercase;
  color: var(--color-yellow);
}

.gig-row__loc {
  font-size: var(--fs-100);
  color: var(--color-white-muted);
}

.gig-row__venue a {
  color: var(--color-white);
  font-family: var(--font-body);
  font-weight: 600;
  text-decoration: none;
}

.gig-row__actions {
  display: flex;
  gap: var(--space-2);
}

.gig-row__actions .btn {
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-100);
}

@media (max-width: 767px) {
  .gig-row__actions .btn {
    padding: 6px var(--space-2);
  }

  .gig-row__actions {
    justify-content: center;
  }
}

/* !important: the live Bandsintown widget injects its own stylesheet
   asynchronously, configured with a white link color (data-text-color) that
   can otherwise leak onto these custom buttons via a bare "a" selector.
   Text on the yellow Tickets button must stay black for contrast. */
.gig-row__actions .btn-primary {
  color: var(--color-black) !important;
}

@media (min-width: 768px) {
  .gig-row {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
  }

  .gig-row__date {
    flex: 0 0 170px;
  }

  .gig-row__venue {
    flex: 1 1 auto;
    min-width: 0;
  }

  .gig-row__actions {
    flex: 0 0 auto;
  }
}

/* ===== 9. PRESS KIT — split with image ===== */
.press-kit-promo {
  padding-block: var(--space-7);
  background: var(--color-black);
  display: grid;
  gap: var(--space-5);
}

.press-kit-promo__img {
  border-radius: 0;
  overflow: hidden;
}

.press-kit-promo__img img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

.press-kit-promo__text {
  align-self: center;
  max-width: 44ch;
}

.press-kit-promo__text p {
  color: var(--color-white-muted);
  margin-block: var(--space-3);
}

@media (min-width: 1024px) {
  .press-kit-promo {
    grid-template-columns: 2fr 3fr;
    align-items: center;
  }
}

/* ===== 10. CONTACT — footer grid ===== */
.contact {
  padding-block: var(--space-7) var(--space-5);
  background: var(--color-black);
  border-top: 1px solid rgba(247, 247, 245, 0.08);
}

.contact__title {
  margin-bottom: var(--space-5);
}

.contact__grid {
  display: grid;
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}

.contact__group h3 {
  font-size: var(--fs-200);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-yellow);
  margin-bottom: var(--space-2);
}

.contact__group a {
  display: block;
  color: var(--color-white-muted);
  margin-bottom: var(--space-1);
}

.contact__group a:hover,
.contact__group a:focus-visible {
  color: var(--color-white);
}

.contact__socials {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}

.contact__socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  border: 1px solid rgba(247, 247, 245, 0.16);
  color: var(--color-white-muted);
}

.contact__socials svg {
  width: 18px;
  height: 18px;
}

.contact__socials a:hover,
.contact__socials a:focus-visible {
  background: var(--color-yellow);
  color: var(--color-black);
  border-color: var(--color-yellow);
}

.contact__foot {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--fs-100);
  color: var(--color-white-muted);
  border-top: 1px solid rgba(247, 247, 245, 0.08);
  padding-top: var(--space-3);
}

@media (min-width: 768px) {
  .contact__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
