/* ==========================================================================
   Components
   ========================================================================== */

/* ---- Buttons ---- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 1.05em 1.7em;
  border-radius: 999px;
  border: 1px solid transparent;
  transition: transform var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
  white-space: nowrap;
}

.btn:active {
  transform: scale(0.97);
}

/* Primary CTA: a slowly drifting accent gradient, a hairline highlight along
   the top edge, and a light sweep that crosses the button on a loop. The
   button clips both pseudo-elements, so it stays a positioned, hidden-overflow
   box (position comes from .btn). */
.btn--primary {
  background: linear-gradient(
    90deg,
    var(--accent),
    var(--accent-deep),
    var(--accent),
    var(--accent-deep),
    var(--accent),
    var(--accent-deep),
    var(--accent)
  );
  background-size: 400% 100%;
  animation: btn-gradient 12s ease infinite;
  color: var(--on-accent);
  overflow: hidden;
  isolation: isolate;
  /* Kept tight: the source design's 67px spread bled a green haze across
     whatever sat behind the button. */
  box-shadow: 0 6px 16px rgba(97, 206, 112, 0.18);
}

/* Light sweep, under the label so the text stays legible. */
.btn--primary::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 50px;
  height: 100%;
  background: #fff;
  box-shadow: 0 0 30px 20px rgba(255, 255, 255, 0.67);
  transform: skewX(-20deg);
  mix-blend-mode: plus-lighter;
  opacity: 0;
  pointer-events: none;
  animation: btn-sheen 4s linear infinite;
}

/* Hairline edge highlight, drawn as a masked 1px border. */
.btn--primary::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(to left, rgba(255, 255, 255, 0.38), transparent);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* Lift any real child (icon, span) above both effect layers. Bare text nodes
   are already painted above the pseudo-elements at z-index 0/1. */
.btn--primary > * {
  position: relative;
  z-index: 2;
}

.btn--primary:hover {
  filter: brightness(1.08);
  box-shadow: 0 8px 22px rgba(97, 206, 112, 0.32);
}

@keyframes btn-gradient {
  0%,
  100% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
}

@keyframes btn-sheen {
  0% {
    opacity: 0;
    left: -15%;
  }
  25% {
    opacity: 0.2;
  }
  50% {
    opacity: 0.4;
  }
  75% {
    opacity: 0.2;
  }
  100% {
    opacity: 0;
    left: 115%;
  }
}

/* The looping motion is decorative — drop it when the visitor opts out. */
@media (prefers-reduced-motion: reduce) {
  .btn--primary {
    animation: none;
    background: var(--accent);
  }

  .btn--primary::before {
    animation: none;
    opacity: 0;
  }
}

.btn--outline {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}

.btn--outline:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.btn--ghost {
  padding: 0;
  border-radius: 0;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-body);
  color: var(--text);
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.15em;
}

.btn--ghost:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.btn__icon {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
}

.btn--block {
  width: 100%;
  justify-content: center;
}

/* ---- Icon buttons (social) ---- */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  color: var(--text-secondary);
  transition: border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.icon-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-2px);
}

.icon-btn svg {
  width: 1.196rem;
  height: 1.196rem;
  fill: currentColor;
}

.icon-btn img {
  width: 1.196rem;
  height: 1.196rem;
  object-fit: contain;
}

/* Bandcamp reads noticeably smaller than the other marks at the same
   box size — an extra 8% on top of the general +4% above (button
   container stays the same, icon just sits a bit bigger inside it). */
.icon-btn[href*="bandcamp.com"] svg {
  width: 1.292rem;
  height: 1.292rem;
}

/* ---- Site nav ---- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  padding-block: var(--space-md);
  transition: padding-block var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
  border-bottom: 1px solid transparent;
}

/* .nav is a positioned, z-indexed box, so it forms a stacking context: the
   mobile panel inside it can never rise above --z-nav on its own, whatever
   z-index it carries. Lifting the header itself while the menu is open is
   what actually puts the panel over the modal and everything else.
   main.js sets .has-menu-open on <body> alongside .is-open. */
body.has-menu-open .nav {
  z-index: var(--z-menu);
  /* .nav.is-scrolled applies a backdrop-filter, which makes the header a
     compositing group: its children are blended with what is *behind* the
     header, so the page showed straight through the panel's opaque black.
     Dropping the filter while the menu is open is what actually fixes it —
     the panel's own background then paints normally. */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: transparent;
  border-color: transparent;
}

.nav.is-scrolled {
  padding-block: var(--space-xs);
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-color: var(--border);
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.nav__logo {
  display: block;
  width: 132px;
  color: var(--text);
}

.nav__logo img {
  width: 100%;
  display: block;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.nav__links a {
  position: relative;
  padding-block: 0.3em;
  color: var(--text-secondary);
  transition: color var(--dur-fast) var(--ease-out);
}

.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

/* Hover only — this used to also trigger on [aria-current="page"], but
   with the hash-router every link in the active view's group resolved
   to "current" at once, so the underline showed on almost everything
   permanently instead of just on hover. */
.nav__links a:hover {
  color: var(--text);
}

.nav__links a:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.nav__toggle {
  display: none;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  align-items: center;
  justify-content: center;
  color: var(--text);
  background: transparent;
  /* Safari shrinks an unsized flex child to nothing; keep the circle. */
  flex-shrink: 0;
}

/* The icon carried no intrinsic size. Blink falls back to 300×150 and the
   flex centring hides it; WebKit collapses it instead, so the hamburger was
   invisible on iOS. Every other icon button in here sizes its svg — this one
   was simply missed. */
.nav__toggle svg {
  display: block;
  width: 1.35rem;
  height: 1.35rem;
  flex-shrink: 0;
}

/* The panel chrome (close button, footer, index numbers) is mobile-only;
   on desktop .nav__links stays a plain inline row. */
.nav__panel-head,
.nav__panel-foot {
  display: none;
}

/* The links live in a wrapper for the mobile panel's grid. On desktop that
   wrapper has to carry the row layout itself, otherwise .nav__links' gap
   applies to the single wrapper and every link collapses together. */
.nav__panel-links {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
}

.nav__links a[data-nav-index]::before {
  content: none;
}

@media (max-width: 860px) {
  /* ---- Full-screen menu panel ---- */
  .nav__links {
    position: fixed;
    inset: 0;
    z-index: var(--z-menu);
    display: grid;
    grid-template-rows: auto 1fr auto;
    gap: 0;
    padding: var(--space-md) var(--container-pad) var(--space-xl);
    /* Opaque: the panel must fully hide the page behind it, including while
       it is still sliding in. */
    background: var(--bg);
    font-size: inherit;
    text-transform: none;
    /* Slides in as a whole rather than being clipped: a clip-path reveal cut
       away the panel's own background mid-animation, so page content showed
       through the menu until the transition finished. */
    /* The panel itself never moves — a sliding box leaves part of the
       viewport uncovered while it travels, letting the page show through.
       It fades in over the full screen instead, and the rows inside it are
       what animate (see the staggered links below). */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease-out),
      visibility 0s linear var(--dur-base);
  }

  .nav__links.is-open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity var(--dur-fast) var(--ease-out), visibility 0s linear;
  }

  /* ---- Header row: close button ---- */
  .nav__panel-head {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    min-height: 2.6rem;
  }

  .nav__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    color: var(--text);
    background: transparent;
    transition: border-color var(--dur-fast) var(--ease-out),
      color var(--dur-fast) var(--ease-out),
      transform var(--dur-base) var(--ease-out);
  }

  .nav__close svg {
    width: 1.1rem;
    height: 1.1rem;
  }

  .nav__close:hover,
  .nav__close:focus-visible {
    border-color: var(--accent);
    color: var(--accent);
    transform: rotate(90deg);
  }

  /* ---- Links ---- */
  .nav__panel-links {
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* align-items must be reset: the desktop rule sets it to `center`, which
       here would centre each row and leave the rules ragged. */
    align-items: stretch;
    gap: var(--space-xs);
  }

  .nav__links a[data-nav-index] {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    padding-block: var(--space-2xs);
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 1.2rem + 4vw, 2.75rem);
    font-weight: var(--fw-semibold);
    letter-spacing: -0.01em;
    line-height: 1.15;
    color: var(--text);
    /* Each link is nudged in and faded; .is-open staggers them via
       transition-delay below, so they arrive in sequence. */
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--dur-base) var(--ease-out),
      transform var(--dur-base) var(--ease-out),
      color var(--dur-fast) var(--ease-out);
  }

  .nav__links a[data-nav-index]::before {
    content: attr(data-nav-index);
    flex-shrink: 0;
    font-size: var(--fs-eyebrow);
    font-weight: var(--fw-medium);
    letter-spacing: 0.1em;
    color: var(--accent);
    opacity: 0.7;
  }

  /* Hairline under each row, so the list reads as a stack. */
  .nav__links a[data-nav-index] .nav__link-text {
    flex: 1;
    padding-bottom: var(--space-xs);
    border-bottom: 1px solid var(--border);
    transition: border-color var(--dur-fast) var(--ease-out);
  }

  .nav__links a[data-nav-index][aria-current] {
    color: var(--accent);
  }

  .nav__links a[data-nav-index]:active .nav__link-text {
    border-color: var(--accent);
  }

  /* The underline animation on desktop links has no place here. */
  .nav__links a::after {
    content: none;
  }

  /* Staggered entrance — index numbers keep the order readable. */
  .nav__links.is-open a[data-nav-index] {
    opacity: 1;
    transform: translateY(0);
  }

  /* Computed from the row's own index so the cascade covers any number of
     links — a hardcoded list silently dropped the delay on extra items. */
  .nav__links.is-open a[data-nav-index] {
    transition-delay: calc(0.04s + sibling-index() * 0.06s);
  }

  /* sibling-index() is recent; this fallback keeps the stagger where it is
     unsupported. Both blocks stay in sync by using the same step. */
  @supports not (transition-delay: calc(sibling-index() * 1s)) {
    .nav__links.is-open a[data-nav-index]:nth-child(1) { transition-delay: 0.10s; }
    .nav__links.is-open a[data-nav-index]:nth-child(2) { transition-delay: 0.16s; }
    .nav__links.is-open a[data-nav-index]:nth-child(3) { transition-delay: 0.22s; }
    .nav__links.is-open a[data-nav-index]:nth-child(4) { transition-delay: 0.28s; }
    .nav__links.is-open a[data-nav-index]:nth-child(5) { transition-delay: 0.34s; }
    .nav__links.is-open a[data-nav-index]:nth-child(6) { transition-delay: 0.40s; }
    .nav__links.is-open a[data-nav-index]:nth-child(7) { transition-delay: 0.46s; }
    .nav__links.is-open a[data-nav-index]:nth-child(8) { transition-delay: 0.52s; }
  }

  /* ---- Footer: CTA + socials ---- */
  .nav__panel-foot {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--dur-base) var(--ease-out),
      transform var(--dur-base) var(--ease-out);
  }

  .nav__links.is-open .nav__panel-foot {
    opacity: 1;
    transform: translateY(0);
    transition-delay: 0.46s;
  }

  .nav__panel-cta {
    justify-content: center;
    width: 100%;
  }

  .nav__panel-social {
    display: flex;
    justify-content: center;
    gap: var(--space-sm);
  }

  .nav__toggle {
    display: inline-flex;
  }

  /* The header CTA duplicates the one inside the panel. */
  .nav__actions .btn {
    display: none;
  }
}

@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  /* No slide: appear in place, opacity only. */
  .nav__links,
  .nav__links.is-open {
    transform: none;
    transition: opacity var(--dur-fast) linear, visibility var(--dur-fast) linear;
  }

  .nav__links a[data-nav-index],
  .nav__panel-foot {
    transform: none;
    transition-delay: 0s !important;
  }
}

/* ---- Panel / card ---- */
.panel {
  background: rgba(10, 10, 10, 0.72);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(1.75rem, 1.4rem + 1.6vw, 3rem);
  backdrop-filter: blur(6px);
}

.panel--accent-border {
  border-color: var(--accent-line);
}

/* ---- Reference / club-logo wall (djjoep.nl-style desktop tile grid) ---- */
.logo-wall {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.logo-wall__tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  aspect-ratio: 4 / 3;
  background: var(--bg);
  padding: var(--space-md);
  text-align: center;
  transition: background-color var(--dur-base) var(--ease-out);
}

.logo-wall__tile:hover {
  background: var(--bg-elevated-2);
}

.logo-wall__name {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: clamp(0.95rem, 0.85rem + 0.4vw, 1.15rem);
  letter-spacing: 0.01em;
  color: var(--text-tertiary);
  transition: color var(--dur-base) var(--ease-out);
}

.logo-wall__city {
  display: block;
  margin-top: 0.3em;
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  opacity: 0.7;
}

.logo-wall__tile:hover .logo-wall__name {
  color: var(--accent);
}

/* Real club logos: shown as a small rounded badge, desaturated by
   default and brought to full colour on hover — this reads as one
   consistent, disciplined system regardless of how varied the source
   artwork is (flat marks, photographic badges, gradients, …). */
.logo-wall__badge {
  width: 3.75rem;
  height: 3.75rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated-2);
  border: 1px solid var(--border-strong);
}

.logo-wall__badge img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05) brightness(1.05);
  transition: filter var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

.logo-wall__tile:hover .logo-wall__badge img {
  filter: grayscale(0);
  transform: scale(1.05);
}

@media (max-width: 980px) {
  .logo-wall {
    grid-template-columns: repeat(3, 1fr);
  }
}

.logo-wall-viewport {
  position: relative;
}

.logo-wall__prev,
.logo-wall__next {
  display: none;
}

/* Mobile: endless vertical scrolling through 11+ tiles is tedious, so
   this becomes a horizontal snap-slider instead — two tiles fully in
   view, a third peeking to signal "there's more", advance via the
   arrows or a plain swipe (overflow-x scroll handles that natively). */
@media (max-width: 640px) {
  .logo-wall {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: var(--space-xs);
    background: none;
    border: none;
    border-radius: 0;
  }

  .logo-wall::-webkit-scrollbar {
    display: none;
  }

  .logo-wall__tile {
    flex: 0 0 46%;
    scroll-snap-align: start;
    aspect-ratio: 4 / 3;
    padding: var(--space-sm);
    gap: var(--space-2xs);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
  }

  .logo-wall__badge {
    width: 2.75rem;
    height: 2.75rem;
  }

  .logo-wall__name {
    font-size: var(--fs-small);
  }

  .logo-wall__city {
    font-size: 0.65rem;
  }

  .logo-wall__prev,
  .logo-wall__next {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.65);
    border: 1px solid var(--border-strong);
    color: var(--text);
    backdrop-filter: blur(4px);
    z-index: 2;
    transition: opacity var(--dur-base) var(--ease-out);
  }

  .logo-wall__prev {
    left: var(--space-xs);
  }

  .logo-wall__next {
    right: var(--space-xs);
  }

  .logo-wall__prev svg,
  .logo-wall__next svg {
    width: 1.1rem;
    height: 1.1rem;
  }

  .logo-wall__prev.is-hidden,
  .logo-wall__next.is-hidden {
    opacity: 0;
    pointer-events: none;
  }

  /* Half the usual headline-to-content gap — the default felt too far
     from the tiles once the slider layout kicks in. */
  #clubs .section-head {
    margin-bottom: calc(var(--space-xl) * 0.5);
  }
}

/* ---- Video-enabled reference tile (currently: Schrotty) ----
   Logo + name stay exactly as on every other tile; hover only adds a
   quiet green lift/glow plus a play affordance and the clip hint — kept
   restrained on purpose so the grid doesn't look "gamified". Touch
   devices can't hover, so `(hover: none)` shows the same affordance
   permanently there instead of never at all. */
.logo-wall__tile--video {
  position: relative;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

.logo-wall__tile--video::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 42%, var(--accent-dim) 0%, rgba(97, 206, 112, 0) 72%);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
  pointer-events: none;
}

.logo-wall__tile--video:hover,
.logo-wall__tile--video:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 16px 32px -18px rgba(97, 206, 112, 0.4);
  z-index: 1;
  outline: none;
}

.logo-wall__tile--video:active {
  transform: translateY(-2px) scale(0.99);
}

.logo-wall__tile--video:hover::before,
.logo-wall__tile--video:focus-visible::before {
  opacity: 1;
}

.logo-wall__play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.75rem;
  height: 2.75rem;
  transform: translate(-50%, -50%) scale(0.85);
  color: var(--accent);
  opacity: 0;
  filter: drop-shadow(0 0 12px rgba(97, 206, 112, 0.5));
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  pointer-events: none;
}

.logo-wall__play svg {
  width: 100%;
  height: 100%;
}

.logo-wall__tile--video:hover .logo-wall__play,
.logo-wall__tile--video:focus-visible .logo-wall__play {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.logo-wall__hint {
  position: absolute;
  left: 50%;
  bottom: var(--space-sm);
  transform: translate(-50%, 4px);
  font-family: var(--font-body);
  font-size: 0.65rem;
  font-weight: var(--fw-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

.logo-wall__tile--video:hover .logo-wall__hint,
.logo-wall__tile--video:focus-visible .logo-wall__hint {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Coarse-pointer / touch devices never trigger :hover — show the same
   affordance permanently instead so the tile stays discoverable. */
@media (hover: none) {
  .logo-wall__tile--video::before {
    opacity: 0.6;
  }

  .logo-wall__tile--video .logo-wall__play {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }

  .logo-wall__tile--video .logo-wall__hint {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

/* ---- Music player ---- */
.player {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-elevated);
}

/* Compact variant: just a play/pause toggle styled as a pill button,
   e.g. dropped into the hero actions row — no waveform/track list. */
.player--inline {
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
  display: inline-flex;
}

.player__play--inline svg {
  width: 1.1em;
  height: 1.1em;
}

/* ---- Player stage (background media + now-playing controls) ---- */
.player__stage {
  position: relative;
  min-height: 24rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--space-lg);
  overflow: hidden;
}

.player__stage-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 22%;
}

.player__stage-texture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  mix-blend-mode: overlay;
  opacity: 0.5;
}

.player__stage-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.25) 35%,
    rgba(0, 0, 0, 0.75) 100%
  );
}

.player__meta {
  position: relative;
  z-index: 1;
}

.player__title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(1.5rem, 1.3rem + 1vw, 2rem);
}

.player__artist {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  margin-top: 0.15em;
}

.player__stats {
  display: flex;
  align-items: center;
  gap: 0.4em;
  margin-top: var(--space-xs);
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-medium);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.player__stats svg {
  width: 0.9em;
  height: 0.9em;
}

.player__transport {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.player__play {
  flex-shrink: 0;
  width: 3.75rem;
  height: 3.75rem;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.player__play:hover {
  transform: scale(1.06);
  border-color: var(--accent);
  color: var(--accent);
}

.player__play svg {
  width: 1.2rem;
  height: 1.2rem;
}

.player__wave {
  flex: 1;
  min-width: 0;
  height: 3.5rem;
  display: flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
}

.player__wave-bar {
  flex: 1;
  background: rgba(255, 255, 255, 0.4);
  border-radius: 2px;
  min-width: 2px;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.player__wave-bar.is-played {
  background: var(--accent);
}

.player__time {
  font-size: var(--fs-eyebrow);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* Prev/next/mute — inline in the same row as play + waveform now, right
   after the play button (was a separate row before, which let the wave
   stretch full-width and cross straight over the portrait). */
.player__secondary {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.player__secondary button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  color: var(--text-secondary);
  transition: color var(--dur-fast) var(--ease-out);
}

.player__secondary button:hover,
.player__secondary button[aria-pressed="true"] {
  color: var(--accent);
}

.player__secondary svg {
  width: 1.1rem;
  height: 1.1rem;
}

@media (max-width: 640px) {
  .player__transport {
    flex-wrap: wrap;
  }
  /* Time sits up on the button row (right-aligned, level with
     play/prev/next/mute) instead of down on the waveform row. The
     waveform then gets its own full-width row underneath. */
  .player__wave {
    order: 3;
    flex: 1 1 100%;
  }
  .player__time {
    order: 2;
    margin-left: auto;
  }
}

/* ---- Track list (below the stage) ---- */
.player__list {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-elevated);
  overflow: hidden;
}

/* Loose diagonal brush-stroke, echoing the brand's paint-stroke motif —
   decorative, sits behind the rows. */
.player__list::before {
  content: "";
  position: absolute;
  top: -20%;
  left: 8%;
  width: 34%;
  height: 140%;
  background: rgba(255, 255, 255, 0.05);
  transform: rotate(18deg);
  border-radius: 40% 60% 55% 45% / 50%;
  pointer-events: none;
}

.player__row {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--border);
  background: transparent;
  transition: background-color var(--dur-base) var(--ease-out);
}

.player__row:last-child {
  border-bottom: 0;
}

.player__row:hover {
  background: rgba(255, 255, 255, 0.03);
}

.player__row.is-active {
  background: var(--accent-dim);
}

.player__row-thumb {
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-sm);
  object-fit: cover;
  filter: grayscale(0.5);
}

.player__row-index {
  color: var(--text-tertiary);
  margin-right: 0.6em;
}

.player__row-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-small);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player__row-time {
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.player__row-links {
  display: flex;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.player__row-links a {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  transition: color var(--dur-fast) var(--ease-out);
}

.player__row-links a:hover {
  color: var(--accent-hover);
}

.player__row-links svg {
  width: 0.95em;
  height: 0.95em;
  fill: currentColor;
}

@media (max-width: 720px) {
  .player__row-links {
    display: none;
  }
}

/* ---- Gig / event list ---- */
.gig-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--space-2xl);
}

.gig-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg);
  background: var(--bg);
  transition: background-color var(--dur-base) var(--ease-out);
}

/* Button keeps its own size under pressure — .gig-item__info (min-width:
   0) is the one that's allowed to shrink/wrap, so the "Anfragen" button
   never visually compresses on narrow screens. */
.gig-item > .btn {
  flex-shrink: 0;
}

.gig-item:hover {
  background: var(--bg-elevated);
}

/* Same badge treatment as .logo-wall__badge in the club-references
   section above — same size, border, radius and grayscale-to-colour
   hover, so the two sections read as one consistent system.
   `contain` + padding (rather than `cover`) so every logo sits with the
   same breathing room inside its badge regardless of how much each
   source file's own artwork bleeds to its edges — with `cover`, a
   full-bleed logo and a logo with built-in white space around its mark
   ended up looking like inconsistent gaps before the divider even
   though the badge box itself is always the same size. */
.gig-item__logo {
  width: 3.75rem;
  height: 3.75rem;
  flex-shrink: 0;
  padding: 0.5rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated-2);
  border: 1px solid var(--border-strong);
  transition: border-color var(--dur-base) var(--ease-out);
}

.gig-item__logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: grayscale(1) contrast(1.05) brightness(1.05);
  transition: filter var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

.gig-item:hover .gig-item__logo {
  border-color: var(--accent-line);
}

.gig-item:hover .gig-item__logo img {
  filter: grayscale(0);
  transform: scale(1.05);
}

/* Below this width the logo + its gaps started crowding out the date/
   button (button getting clipped, date wrapping to 3 lines) — shrink the
   logo further and tighten the row's own gap/padding just enough to give
   the (unchanged) button and text room again. */
@media (max-width: 560px) {
  .gig-item {
    gap: var(--space-sm);
    padding: var(--space-md);
  }
  .gig-item__info {
    padding-left: var(--space-sm);
  }
  /* Smaller "Anfragen" button frees up width for the date/place text. */
  .gig-item .btn {
    padding: 0.75em 1.15em;
    font-size: 0.75rem;
  }
}

@media (max-width: 480px) {
  .gig-item__logo {
    width: 2.75rem;
    height: 2.75rem;
    padding: 0.35rem;
  }
}

/* Narrow phones: the fixed-size button (unchanged) plus logo left very
   little room for the date/place text — trim gap and padding further so
   text still gets enough width to wrap cleanly instead of the row
   overflowing its rounded container. */
@media (max-width: 420px) {
  .gig-item {
    flex-wrap: nowrap;
    gap: var(--space-xs);
    padding: var(--space-sm);
  }
  .gig-item__logo {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0.25rem;
  }
  .gig-item__info {
    padding-left: var(--space-xs);
  }
}

.gig-item__info {
  min-width: 0;
  padding-left: var(--space-md);
  border-left: 2px solid var(--border-strong);
  transition: border-color var(--dur-base) var(--ease-out);
  /* Fixed regardless of how many lines the date/place text wraps to, so
     every tile's divider is the same length and all tiles line up —
     both within a row and across rows. */
  min-height: 3.75rem;
}

.gig-item:hover .gig-item__info {
  border-color: var(--accent);
}

.gig-item__date {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: clamp(1rem, 0.92rem + 0.4vw, 1.2rem);
  letter-spacing: 0.01em;
}

.gig-item__place {
  font-size: var(--fs-small);
  color: var(--text-secondary);
  margin-top: 0.35em;
}

@media (max-width: 720px) {
  .gig-list {
    grid-template-columns: 1fr;
  }
}

/* ---- USP tiles (events page) — bento grid: one big media tile, two
   smaller media tiles top-right, one plain dark tile (no photo, by
   design — see ref. Assets/References/USPs.png) and one media tile
   bottom-right. Named grid-template-areas (rather than nth-child/DOM
   order) so which tile is "big" or "dark" stays obvious and easy to
   re-arrange. ---- */
.usp-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  grid-template-rows: repeat(2, minmax(15rem, auto));
  grid-template-areas:
    "main sound tech"
    "main flex content";
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.usp-tile--main {
  grid-area: main;
}
.usp-tile--sound {
  grid-area: sound;
}
.usp-tile--tech {
  grid-area: tech;
}
.usp-tile--flex {
  grid-area: flex;
}
.usp-tile--content {
  grid-area: content;
}

.usp-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: var(--bg);
  padding: var(--space-lg) var(--space-md);
  transition: background-color var(--dur-base) var(--ease-out);
}

.usp-tile--main {
  padding: var(--space-xl) var(--space-lg);
}

.usp-tile--flex:hover {
  background: var(--bg-elevated);
}

.usp-tile__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}

.usp-tile:hover .usp-tile__media {
  transform: scale(1.04);
}

.usp-tile__scrim {
  position: absolute;
  inset: 0;
  /* Above the tint layers below, so the text keeps its dark backing. */
  z-index: 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.1) 0%,
    rgba(0, 0, 0, 0.55) 58%,
    rgba(0, 0, 0, 0.92) 100%
  );
}

/* Accent wash over the photo. The image is desaturated first so the tint
   reads as one colour rather than fighting whatever hues are in the shot;
   the accent layer is then blended over it, under the existing scrim. */
.usp-tile--tinted .usp-tile__media {
  filter: grayscale(1) contrast(1.08) brightness(0.78);
}

.usp-tile--tinted::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--accent);
  /* `color` alone only recolours and reads washed out over mid greys;
     screen lifts the accent into the highlights so the tint is visible. */
  mix-blend-mode: screen;
  opacity: 0.38;
  pointer-events: none;
}

/* A second, softer pass adds depth so the tint is not a flat sheet. */
.usp-tile--tinted::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    145deg,
    rgba(97, 206, 112, 0.42) 0%,
    rgba(97, 206, 112, 0.14) 45%,
    rgba(0, 0, 0, 0.4) 100%
  );
  mix-blend-mode: multiply;
  pointer-events: none;
}

.usp-tile__body {
  position: relative;
  z-index: 1;
}

.usp-tile__icon {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--accent-dim);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-md);
  transition: background-color var(--dur-base) var(--ease-out);
}

.usp-tile--media .usp-tile__icon {
  background: rgba(97, 206, 112, 0.22);
  backdrop-filter: blur(6px);
}

.usp-tile:hover .usp-tile__icon {
  background: var(--accent);
  color: var(--on-accent);
}

.usp-tile__icon svg {
  width: 1.3rem;
  height: 1.3rem;
}

.usp-tile h3 {
  font-size: var(--fs-h3);
  line-height: 1.2;
  margin-bottom: var(--space-sm);
  color: var(--text);
}

.usp-tile--main h3 {
  font-size: var(--fs-h2);
}

.usp-tile p {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 30ch;
}

.usp-tile--main p {
  font-size: var(--fs-body);
  max-width: 26ch;
}

/* Flexibel-Format tile: no photo, on purpose — tags instead of copy. */
.usp-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.usp-tags li {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.5em 0.9em;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--bg-elevated-2);
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: var(--fw-medium);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.usp-tags li::before {
  content: "";
  width: 0.35em;
  height: 0.35em;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent);
}

/* ---- "Event mit Sasuma planen" link below the grid ---- */
.usp-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  transition: gap var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.usp-cta:hover {
  gap: var(--space-sm);
  color: var(--accent-hover);
}

.usp-cta svg {
  width: 1.1em;
  height: 1.1em;
  transition: transform var(--dur-fast) var(--ease-out);
}

.usp-cta:hover svg {
  transform: translateX(3px);
}

@media (max-width: 980px) {
  .usp-grid {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: auto;
    grid-template-areas:
      "main main"
      "sound tech"
      "flex content";
  }

  .usp-tile--main {
    min-height: 20rem;
  }
}

@media (max-width: 640px) {
  .usp-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "main"
      "sound"
      "tech"
      "flex"
      "content";
  }

  .usp-tile {
    min-height: 14rem;
  }

  .usp-tile--main {
    min-height: 18rem;
  }
}

/* ---- Timeline (Ablauf) — scroll-charged progress line ----
   process-steps.js writes the 0..1 scroll fraction to a single
   --timeline-progress custom property on .timeline__line-track; every
   value below that reads from it, so this file never needs to know
   which breakpoint (horizontal vs. vertical) is currently active. Each
   step's .is-active class is a one-way latch set by that same script —
   the fill itself keeps scrubbing with scroll, but a step's reveal
   plays once and stays revealed. */
.timeline {
  position: relative;
}

.timeline__line-track {
  --timeline-progress: 0;
  position: absolute;
  top: 1.375rem; /* vertical centre of the 2.75rem node circle */
  /* Node 1's / node 3's horizontal centre in the 3-col grid below,
     accounting for its `gap` eating into the naive 1/6 + 1/6 split
     (see the derivation in the git history if this ever needs
     re-deriving) — keeps the line exactly node-centre to node-centre
     regardless of container width. */
  left: calc(100% / 6 - var(--space-lg) / 3);
  right: calc(100% / 6 - var(--space-lg) / 3);
  height: 1px;
}

.timeline__line-base {
  position: absolute;
  inset: 0;
  background: var(--border-strong);
}

.timeline__line-fill {
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform-origin: left center;
  transform: scaleX(var(--timeline-progress));
  box-shadow: 0 0 12px rgba(97, 206, 112, 0.5);
}

/* Small blurred marker riding the fill's leading edge — only visible
   while a scroll is actually in progress (see process-steps.js), never
   a static decoration. */
.timeline__line-glow {
  position: absolute;
  top: 50%;
  left: calc(var(--timeline-progress) * 100%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(97, 206, 112, 0.9) 0%, rgba(97, 206, 112, 0) 70%);
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
  pointer-events: none;
}

.timeline__steps {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
}

.timeline__step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
  /* Grid items stretch to the row's height by default, so all three
     steps already match — the card below is what needs to fill that
     stretched height instead of just sizing to its own (1- vs 2-line)
     text, otherwise the shorter-copy card reads visibly smaller. */
  height: 100%;
}

.timeline__node {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  color: var(--text-tertiary);
  transition: border-color var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

.timeline__node-index {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
}

.timeline__step.is-active .timeline__node {
  border-color: var(--accent);
  color: var(--accent);
  /* Very restrained glow — a soft ring plus a short-radius bloom, not a
     neon halo. */
  box-shadow: 0 0 0 4px var(--accent-dim), 0 0 14px rgba(97, 206, 112, 0.3);
}

.timeline__card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  width: 100%;
  padding: var(--space-md);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  max-width: 22rem;
  opacity: 0;
  transform: translateY(20px) scale(0.98);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: 0.12s;
}

/* Minimal directional nudge per step, per spec — step 1 drifts in
   slightly from the left, step 3 slightly from the right, step 2
   (already vertical-only) stays a plain rise. Kept subtle on purpose:
   this is an offset, not a fly-in. */
.timeline__step[data-dir="left"] .timeline__card {
  transform: translate(-14px, 20px) scale(0.98);
}

.timeline__step[data-dir="right"] .timeline__card {
  transform: translate(14px, 20px) scale(0.98);
}

.timeline__step.is-active .timeline__card {
  opacity: 1;
  transform: translate(0, 0) scale(1);
}

.timeline__card h3 {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-xs);
}

.timeline__card p {
  font-size: var(--fs-small);
  color: var(--text-secondary);
}

@media (prefers-reduced-motion: reduce) {
  .timeline__card {
    transition: opacity 0.4s linear;
    transform: none !important;
  }
}

@media (max-width: 780px) {
  .timeline__steps {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }

  .timeline__step {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-md);
    text-align: left;
    /* Fixed regardless of how many lines the card's text wraps to, so
       all three nodes land at exactly even intervals — same trick the
       line-height math below relies on. */
    min-height: 5.5rem;
  }

  .timeline__card {
    max-width: none;
  }

  /* Runs exactly from node 1's centre to node 3's — height derived from
     the fixed step min-height + gap above, so it never dangles past
     step 3 into the empty space underneath. */
  .timeline__line-track {
    top: 1.375rem;
    left: 1.375rem;
    right: auto;
    height: calc(2 * (5.5rem + var(--space-xl)));
    width: 1px;
  }

  .timeline__line-fill {
    transform-origin: top center;
    transform: scaleY(var(--timeline-progress));
  }

  .timeline__line-glow {
    top: calc(var(--timeline-progress) * 100%);
    left: 50%;
  }

  /* No horizontal drift on the stacked mobile layout — every card just
     rises in, matching the vertical charge direction of the line. */
  .timeline__step[data-dir="left"] .timeline__card,
  .timeline__step[data-dir="right"] .timeline__card {
    transform: translateY(16px) scale(0.98);
  }

  .timeline__step.is-active .timeline__card {
    transform: translate(0, 0) scale(1);
  }
}

/* ---- Gallery (Drink & Paint) ---- */
.gallery {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: 9rem;
  gap: var(--space-2xs);
}

.gallery__item {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-sm);
}

.gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-slow) var(--ease-out);
  filter: grayscale(0.35) contrast(1.05);
}

.gallery__item:hover img {
  transform: scale(1.05);
  filter: grayscale(0) contrast(1.05);
}

.gallery__item--a {
  grid-column: span 3;
  grid-row: span 3;
}
.gallery__item--b {
  grid-column: span 3;
  grid-row: span 2;
}
.gallery__item--c {
  grid-column: span 2;
  grid-row: span 2;
}
.gallery__item--d {
  grid-column: span 2;
  grid-row: span 2;
}
.gallery__item--e {
  grid-column: span 2;
  grid-row: span 2;
}
.gallery__item--f {
  grid-column: span 3;
  grid-row: span 2;
}
.gallery__item--g {
  grid-column: span 3;
  grid-row: span 2;
}

@media (max-width: 860px) {
  .gallery {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: 11rem;
  }
  .gallery__item,
  .gallery__item--a,
  .gallery__item--b,
  .gallery__item--c,
  .gallery__item--d,
  .gallery__item--e,
  .gallery__item--f,
  .gallery__item--g {
    grid-column: span 1;
    grid-row: span 1;
  }
}

/* ---- Forms ---- */
.form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
}

.form__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.form__field--full {
  grid-column: 1 / -1;
}

.form__field label {
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.form__field input,
.form__field textarea,
.form__field select {
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.9em 1em;
  color: var(--text);
  transition: border-color var(--dur-fast) var(--ease-out);
}

.form__field textarea {
  resize: vertical;
  min-height: 8rem;
}

.form__field input:focus,
.form__field textarea:focus,
.form__field select:focus {
  border-color: var(--accent);
}

.form__field input::placeholder,
.form__field textarea::placeholder {
  color: var(--text-tertiary);
}

.form__hint {
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
}

.form__actions {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
}

.form__status {
  grid-column: 1 / -1;
  font-size: var(--fs-small);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  display: none;
}

.form__status.is-visible {
  display: block;
}

.form__status--success {
  border-color: var(--accent-line);
  color: var(--accent);
  background: var(--accent-dim);
}

.form__status--error {
  border-color: rgba(255, 90, 90, 0.4);
  color: #ff8a8a;
  background: rgba(255, 90, 90, 0.08);
}

.form__field--hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
}

/* ---- Privacy consent checkbox ---- */
/* Specificity bumped via .form__field--consent (beats the generic
   ".form__field label" eyebrow styling — this is a full sentence, not a
   field label, so it shouldn't render uppercase/letter-spaced). */
.form__field--consent .form__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: var(--fw-regular);
  letter-spacing: normal;
  text-transform: none;
  color: var(--text-secondary);
  cursor: pointer;
}

.form__consent input[type="checkbox"] {
  width: 1.1em;
  height: 1.1em;
  margin-top: 0.2em;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.form__consent span {
  line-height: 1.5;
}

.form__consent a {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  transition: color var(--dur-fast) var(--ease-out);
}

.form__consent a:hover {
  color: var(--accent);
}

@media (max-width: 720px) {
  .form {
    grid-template-columns: 1fr;
  }
}

/* ---- Footer ---- */
.footer {
  position: relative;
  border-top: 1px solid var(--border);
  padding-block: var(--space-2xl) var(--space-lg);
  overflow: hidden;
}

.footer__main {
  position: relative;
  z-index: 1;
}

.footer__grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-xl);
  margin-bottom: var(--space-xl);
}

/* Neon centre divider — sits exactly at the midpoint of the 4-column
   grid (i.e. between columns 2 and 3) regardless of content width,
   since it's positioned independently at 50%, not tied to a column. */
.footer__divider {
  position: absolute;
  left: 50%;
  top: -0.25rem;
  bottom: -0.25rem;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(
    to bottom,
    transparent 0%,
    var(--accent-line) 15%,
    var(--accent-line) 85%,
    transparent 100%
  );
  pointer-events: none;
}

.footer__divider::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 10px 2px var(--accent), 0 0 30px 9px rgba(97, 206, 112, 0.55);
  transform: translate(-50%, -50%);
}

.footer__col {
  min-width: 0;
}

.footer__logo {
  width: 140px;
  margin-bottom: var(--space-md);
}

.footer__social {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
  margin-top: var(--space-md);
}

.footer__col h4 {
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: var(--space-sm);
}

.footer__col p {
  font-size: var(--fs-small);
}

.footer__col ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.footer__col a:not(.btn) {
  color: var(--text-secondary);
  transition: color var(--dur-fast) var(--ease-out);
}

.footer__col a:not(.btn):hover {
  color: var(--accent);
}

.footer__col--booking .btn {
  margin-top: var(--space-md);
}

/* Nudges the Navigation column's content away from the centre divider,
   so it sits balanced in the free space between the divider and the
   Rechtliches column instead of hugging the divider's left edge. Only
   an inset within the column itself — the grid/column widths, divider
   position and Rechtliches column are untouched. */
.footer__col--nav {
  padding-left: clamp(1.5rem, 4vw, 4rem);
}

.footer__bottom {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  margin-top: 18px;
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
}

/* The Brickweb credit: wordmark replaced by the agency logo. Sits on the
   text baseline next to "Design & Umsetzung:". */
.footer__credit {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
}

.footer__credit-link {
  display: inline-flex;
  align-items: center;
  /* Dimmed to sit at the same visual weight as the tertiary text beside it;
     comes up to full strength on hover. */
  opacity: 0.75;
  transition: opacity 250ms ease, filter 250ms ease;
}

.footer__credit-logo {
  display: block;
  /* Scaled to the cap height of the surrounding line rather than a fixed px
     size, so it tracks the footer's type. */
  height: 1.55em;
  width: auto;
}

.footer__credit-link:hover,
.footer__credit-link:focus-visible {
  opacity: 1;
  filter: drop-shadow(0 0 8px rgba(127, 0, 255, 0.45));
}

@media (max-width: 900px) {
  .footer__grid {
    grid-template-columns: repeat(2, 1fr);
    row-gap: var(--space-2xl);
  }
  .footer__divider {
    display: none;
  }
  /* The divider this inset was balancing against is hidden at this
     breakpoint (columns reflow to 2-up), so the inset no longer applies. */
  .footer__col--nav {
    padding-left: 0;
  }
}

@media (max-width: 560px) {
  /* Brand + Booking each keep a full-width row; Navigation and
     Rechtliches pair up side by side underneath instead of stacking
     as four full-width rows. */
  .footer__grid {
    grid-template-columns: repeat(2, 1fr);
    row-gap: var(--space-xl);
  }
  .footer__col--brand,
  .footer__col--booking {
    grid-column: 1 / -1;
  }

}

/* ---- Marquee band ---- */
.marquee {
  overflow: hidden;
  white-space: nowrap;
  border-block: 1px solid var(--border);
  /* Tight band thickness — text hugs its own border lines, like the
     original. Vertical position within the black gap after the hero is
     controlled by margin (below), not padding, so the band itself
     doesn't grow: margin-top gives the rotated corners clearance so
     they don't bleed up into the hero video, margin-bottom keeps it off
     the About section (which already adds its own top padding). */
  padding-block: var(--space-sm);
  /* Bottom value trimmed ~30% (paired with .about's reduced padding-top
     below) to tighten the banner-to-About transition specifically —
     margin-top (clearance from the hero above) is untouched. */
  margin-block: clamp(3rem, 2rem + 4vw, 6rem) clamp(1.05rem, 0.7rem + 1.4vw, 2.1rem);
  transform: rotate(-1.5deg) scale(1.03);
}

.marquee__track {
  display: inline-flex;
  animation: marquee 42s linear infinite;
}

.marquee__track span {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: clamp(1.1rem, 0.9rem + 1vw, 1.8rem);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-tertiary);
  padding-inline: var(--space-md);
}

.marquee__track span.is-accent {
  color: var(--accent);
}

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

@media (prefers-reduced-motion: reduce) {
  .marquee__track {
    animation: none;
  }
}

/* ---- Click-to-load embed facade ---- */
.embed-facade {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated) center / cover no-repeat;
  border: 1px solid var(--border);
}

.embed-facade__btn {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: rgba(0, 0, 0, 0.45);
  color: var(--text);
  text-align: center;
  padding: var(--space-md);
}

.embed-facade__play {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.embed-facade__note {
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
  max-width: 22rem;
}

/* ---- Legal pages ---- */
.legal h2 {
  /* 12% smaller than the default h2 — the main "Impressum"/
     "Datenschutzerklärung" h1 above is untouched, only these section
     subheadlines are scaled down. */
  font-size: calc(var(--fs-h2) * 0.88);
  margin-top: var(--space-xl);
  margin-bottom: var(--space-sm);
}

.legal h2:first-child {
  margin-top: 0;
}

.legal p,
.legal li {
  color: var(--text-secondary);
  margin-bottom: var(--space-sm);
}

.legal ul {
  list-style: disc;
  padding-left: 1.4rem;
}

.legal a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.legal__notice {
  margin-top: var(--space-2xl);
  padding: var(--space-md);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  font-size: var(--fs-small);
}

/* ---- Click-to-load video embed ----
   Stays a poster + button until pressed; main.js swaps the whole box for the
   iframe on click, so nothing is requested from YouTube before that. */
.video-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}

.video-embed__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out),
    filter var(--dur-base) var(--ease-out);
}

.video-embed:hover .video-embed__poster {
  transform: scale(1.03);
  filter: brightness(0.82);
}

.video-embed__scrim {
  position: absolute;
  inset: 0;
  background: radial-gradient(
      ellipse at 50% 45%,
      rgba(0, 0, 0, 0.15) 0%,
      rgba(0, 0, 0, 0.55) 70%
    ),
    linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.75) 100%);
  pointer-events: none;
}

.video-embed__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  color: var(--text);
  background: transparent;
  cursor: pointer;
}

.video-embed__play-icon {
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  border: 1px solid var(--accent-line);
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--accent);
  transition: background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}

.video-embed__play-icon svg {
  width: 1.9rem;
  height: 1.9rem;
  /* Nudge the triangle so it reads as centred inside the circle. */
  margin-left: 0.15rem;
}

.video-embed__play:hover .video-embed__play-icon,
.video-embed__play:focus-visible .video-embed__play-icon {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  transform: scale(1.06);
}

.video-embed__play-label {
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media (max-width: 720px) {
  .video-embed__play-icon {
    width: 3.6rem;
    height: 3.6rem;
  }

  .video-embed__play-icon svg {
    width: 1.5rem;
    height: 1.5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .video-embed__poster,
  .video-embed__play-icon {
    transition: none;
  }

  .video-embed:hover .video-embed__poster {
    transform: none;
  }
}
