/* ── Home page ambient effects ────────────────────────────────────────────────
   Loaded only by /index.html, on top of /components/fx.css (which provides the
   drifting background, the @property registrations and the fx-glow / fx-sheen
   keyframes used below).
   Everything here is deliberately faint and slow: drifting colour glows behind
   the page, translucent "glass" panels that let them through, and an occasional
   soft shine sweeping across the panels. All motion stops under
   prefers-reduced-motion. */

/* ── Sidebar: frosted instead of solid, with a light travelling down its edge ── */
.sidebar {
  background: rgba(9,10,13,0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-right-color: rgba(255,255,255,0.05);
}
.sidebar::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 1px;
  height: 28%;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, rgba(0,255,204,0.45), transparent);
  animation: fx-edge 16s ease-in-out infinite;
}
@keyframes fx-edge {
  0%   { transform: translateY(-100%); opacity: 0; }
  10%  { opacity: 1; }
  55%  { opacity: 1; }
  65%  { transform: translateY(360%); opacity: 0; }
  100% { transform: translateY(360%); opacity: 0; }
}

/* ── Panels: translucent glass ──────────────────────────────────────────────── */
.desc-section,
.gig-section,
.contact-section {
  position: relative;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.desc-section {
  background: rgba(10,12,16,0.68);
  border: 1px solid rgba(255,255,255,0.05);
}
/* The coloured glow in the corner of each panel slowly wanders. */
.gig-section {
  background:
    radial-gradient(620px circle at var(--fx-gx) var(--fx-gy), rgba(0,255,204,0.11), transparent 56%),
    radial-gradient(520px circle at calc(100% - var(--fx-gx)) calc(100% - var(--fx-gy)), rgba(56,139,253,0.11), transparent 52%),
    linear-gradient(to bottom, rgba(17,17,17,0.66), rgba(12,12,12,0.74));
  animation: fx-glow 38s ease-in-out infinite alternate;
}
.contact-section {
  background:
    radial-gradient(620px circle at calc(100% - var(--fx-gx)) var(--fx-gy), rgba(56,139,253,0.13), transparent 56%),
    radial-gradient(520px circle at var(--fx-gx) calc(var(--fx-gy) + 6%), rgba(0,255,204,0.09), transparent 52%),
    linear-gradient(to bottom, rgba(17,17,17,0.66), rgba(12,12,12,0.74)),
    radial-gradient(rgba(125,140,158,0.2) 1px, transparent 1px);
  background-size: auto, auto, 100% 100%, 20px 20px;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat;
  animation: fx-glow 44s ease-in-out -12s infinite alternate;
}

/* Soft diagonal shine that sweeps across each panel now and then. */
.desc-section::after,
.gig-section::after,
.contact-section::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(115deg,
    transparent calc(var(--fx-sheen) - 14%),
    rgba(255,255,255,0.035) var(--fx-sheen),
    transparent calc(var(--fx-sheen) + 14%));
  animation: fx-sheen 18s ease-in-out infinite;
}
.gig-section::after     { animation-delay: -6s; }
.contact-section::after { animation-delay: -12s; }

/* ── Song carousel cards ─────────────────────────────────────────────────────
   No backdrop blur here: the carousel has many moving cards, so the shine is a
   transform-only sweep that stays cheap to animate. */
.album-card {
  position: relative;
  background: rgba(18,20,26,0.62);
  border-color: rgba(255,255,255,0.07);
  transition: border-color 0.2s, box-shadow 0.3s;
}
.album-card::after {
  content: '';
  position: absolute;
  inset: -20% auto -20% 0;
  width: 60%;
  pointer-events: none;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,0.07) 50%, transparent);
  transform: translateX(-120%) skewX(-12deg);
  animation: fx-card-sheen 14s ease-in-out infinite;
}
/* Staggered so the shine ripples along the row instead of flashing all at once. */
.album-card:nth-child(4n+2)::after { animation-delay: -3.5s; }
.album-card:nth-child(4n+3)::after { animation-delay: -7s; }
.album-card:nth-child(4n+4)::after { animation-delay: -10.5s; }
@keyframes fx-card-sheen {
  0%        { transform: translateX(-120%) skewX(-12deg); }
  22%, 100% { transform: translateX(260%) skewX(-12deg); }
}
.album-info {
  background: linear-gradient(to bottom, rgba(0,255,204,0.035), transparent 70%);
}
.album-card.active {
  animation: fx-card-breathe 5s ease-in-out infinite;
}
@keyframes fx-card-breathe {
  0%, 100% { box-shadow: 0 0 24px rgba(0,255,204,0.38); }
  50%      { box-shadow: 0 0 36px rgba(0,255,204,0.58); }
}

/* ── First gig card ───────────────────────────────────────────────────────────
   Driven by /home-gig-fx.js: a black-hole entrance, the photos as stickers
   drifting in the wind, and the focused video (.is-gig-focus) as the card's
   focal point — the other photos and videos dim with its distance from it (--gig-far,
   0..1, set per element) and particles (canvas.gig-particles) get pulled into
   it. Motion is transform/opacity only. */
@property --gig-sx { syntax: '<length-percentage>'; inherits: true; initial-value: 50%; }
@property --gig-sy { syntax: '<length-percentage>'; inherits: true; initial-value: 60%; }
@property --gig-sr { syntax: '<length>'; inherits: true; initial-value: 180px; }
@property --gig-sd { syntax: '<length>'; inherits: true; initial-value: 320px; }

.gig-stage { position: relative; }
.gig-section {
  isolation: isolate;
  /* The spotlight glides when another video takes the focus. */
  transition: --gig-sx 0.8s ease, --gig-sy 0.8s ease, --gig-sr 0.8s ease;
}
/* Spotlight: clear around the focused video, darkening further out. Behind the content. */
.gig-section::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(circle at var(--gig-sx) var(--gig-sy), rgba(0,255,204,0.07), transparent calc(var(--gig-sr) + 90px)),
    radial-gradient(circle at var(--gig-sx) var(--gig-sy),
      transparent var(--gig-sr),
      rgba(0,0,0,0.2) calc(var(--gig-sr) + var(--gig-sd) * 0.45),
      rgba(0,0,0,0.45) calc(var(--gig-sr) + var(--gig-sd)));
}
.gig-particles {
  position: absolute;
  z-index: 1;
  pointer-events: none;
}
/* Above the particle canvas, so the particles slip underneath it. */
.gig-section .is-gig-focus {
  z-index: 2;
  border-color: rgba(0,255,204,0.35);
  box-shadow: 0 0 34px rgba(0,255,204,0.22), 0 18px 40px rgba(0,0,0,0.5);
}
.gig-section .is-gig-focus:hover {
  border-color: rgba(0,255,204,0.7);
  box-shadow: 0 0 40px rgba(0,255,204,0.38), 0 18px 40px rgba(0,0,0,0.5);
}

/* Dimming by distance from the focus; hovering or focusing an item lights it back up.
   Only the photos and videos — the header and text always stay fully readable. */
.gig-photo-frame,
.gig-video-main,
.gig-short {
  --gig-dim: 0.6;
  filter: brightness(calc(1 - var(--gig-far, 0) * var(--gig-dim)))
          saturate(calc(1 - var(--gig-far, 0) * var(--gig-dim) * 0.7));
  transition: border-color 0.2s, box-shadow 0.25s, filter 0.6s ease, scale 0.35s ease;
}
.gig-photo-frame:hover, .gig-photo-frame:focus-visible,
.gig-video-main:hover, .gig-video-main:focus-visible,
.gig-short:hover, .gig-short:focus-visible {
  --gig-dim: 0;
}
/* Photos as stickers: off-white die-cut edge, a glossy sheen, a slight tilt, drifting
   in the wind (the tilt is `rotate`, the wind `transform`, so the two compose). */
.gig-photo-frame {
  box-sizing: border-box;
  border: 5px solid #f3f0e7;
  border-radius: 14px;
  box-shadow: 0 12px 22px rgba(0,0,0,0.5), 0 2px 3px rgba(0,0,0,0.3);
  rotate: -2.2deg;
  transform-origin: 50% 20%;
  animation: gig-wind 7s ease-in-out var(--gig-wind-delay, 0s) infinite;
}
.gig-photo-frame--secondary {
  rotate: 2.6deg;
  --gig-wind-delay: -3.4s;
  animation-duration: 8.4s;
}
.gig-photo-frame::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(125deg,
    rgba(255,255,255,0.26) 0%, rgba(255,255,255,0.06) 26%, transparent 42%,
    transparent 78%, rgba(255,255,255,0.08) 100%);
}
.gig-photo-frame .gig-video-caption { z-index: 2; }
.gig-photo-frame:hover {
  scale: 1.035;
  border-color: #fff;
  box-shadow: 0 18px 30px rgba(0,0,0,0.55), 0 0 26px rgba(0,255,204,0.3);
}
.gig-photo-frame:focus-visible {
  border-color: #fff;
  outline: 3px solid rgba(0,255,204,0.6);
  outline-offset: 3px;
}
.gig-section.fx-offscreen .gig-photo-frame { animation-play-state: paused; }
@keyframes gig-wind {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg) skewX(0deg); }
  18%      { transform: translate3d(3px, -4px, 0) rotate(1.4deg) skewX(-0.8deg); }
  34%      { transform: translate3d(1px, -2px, 0) rotate(0.5deg) skewX(0.3deg); }
  52%      { transform: translate3d(4px, -6px, 0) rotate(2deg) skewX(-1.2deg); }
  70%      { transform: translate3d(-1px, -1px, 0) rotate(-0.6deg) skewX(0.5deg); }
  86%      { transform: translate3d(1px, -3px, 0) rotate(0.8deg) skewX(-0.2deg); }
}

/* Entrance. .gig-wait hides the card until it scrolls into view; .gig-emerge plays it
   (items fly out from the hole: --gig-from-x/y and --gig-delay are set per element);
   .gig-emerging only lasts while the hole and shockwave exist. Keyframes give only the
   start, so each animation ends on the element's own tilt/dim/scale. */
.gig-stage.gig-wait .gig-section { opacity: 0; }
.gig-stage.gig-emerging { overflow-x: clip; } /* the shockwave outgrows a phone screen */
.gig-stage.gig-emerge .gig-section {
  animation: gig-panel-in 0.95s cubic-bezier(0.16, 0.92, 0.24, 1.04) 0.28s backwards,
             fx-glow 38s ease-in-out infinite alternate;
}
.gig-stage.gig-emerge :is(.gig-header, .gig-blurb, .gig-video-main, .gig-short) {
  animation: gig-item-in 0.85s cubic-bezier(0.2, 0.85, 0.25, 1.05) var(--gig-delay, 0.5s) backwards;
}
.gig-stage.gig-emerge .gig-photo-frame {
  animation: gig-item-in 0.85s cubic-bezier(0.2, 0.85, 0.25, 1.05) var(--gig-delay, 0.5s) backwards,
             gig-wind 7s ease-in-out var(--gig-wind-delay, 0s) infinite;
}
.gig-stage.gig-emerge .gig-photo-frame--secondary {
  animation-duration: 0.85s, 8.4s;
}
@keyframes gig-panel-in {
  from { scale: 0.12; rotate: -14deg; opacity: 0; }
}
@keyframes gig-item-in {
  from { translate: var(--gig-from-x, 0) var(--gig-from-y, 0); scale: 0.06; rotate: -55deg; opacity: 0; }
  40%  { opacity: 1; }
}

.gig-hole,
.gig-hole-wave {
  --s: clamp(120px, 30vw, 220px);
  position: absolute;
  left: var(--gig-hole-x, 50%);
  top: var(--gig-hole-y, 50%);
  width: var(--s);
  height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  z-index: 3;
  pointer-events: none;
}
.gig-hole {
  animation: gig-hole 1.55s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
/* Accretion disk: a spinning colour ring around the dark core. */
.gig-hole-disk {
  position: absolute;
  inset: -18%;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    rgba(0,255,204,0), rgba(0,255,204,0.9), rgba(56,139,253,0.8),
    rgba(179,107,255,0.7), rgba(255,0,102,0.5), rgba(0,255,204,0) 72%, rgba(0,255,204,0.6));
  -webkit-mask: radial-gradient(closest-side, transparent 48%, #000 56%, #000 64%, transparent 100%);
  mask: radial-gradient(closest-side, transparent 48%, #000 56%, #000 64%, transparent 100%);
  animation: gig-spin 0.9s linear infinite;
}
.gig-hole-core {
  position: absolute;
  inset: 14%;
  border-radius: 50%;
  background: radial-gradient(closest-side, #000 72%, rgba(0,0,0,0.85) 86%, rgba(0,0,0,0) 100%);
  box-shadow: 0 0 0 1.5px rgba(200,255,245,0.5), 0 0 26px 6px rgba(0,255,204,0.3);
}
.gig-hole-wave {
  border-radius: 50%;
  border: 2px solid rgba(0,255,204,0.75);
  box-shadow: 0 0 18px rgba(0,255,204,0.45), inset 0 0 18px rgba(0,255,204,0.3);
  opacity: 0;
  animation: gig-wave 0.85s cubic-bezier(0.2, 0.7, 0.3, 1) 1.05s forwards;
}
@keyframes gig-hole {
  0%   { scale: 0;    opacity: 0; }
  22%  { scale: 1;    opacity: 1; }
  50%  { scale: 1.12; opacity: 1; }
  78%  { scale: 0.2;  opacity: 1; }
  100% { scale: 0;    opacity: 0; }
}
@keyframes gig-spin { to { rotate: 360deg; } }
@keyframes gig-wave {
  from { scale: 0.25; opacity: 0.95; }
  to   { scale: 5;    opacity: 0; }
}

/* ── Mobile: the sidebar is display:contents, so frost its visible parts ────── */
@media (max-width: 700px) {
  .sidebar::after { display: none; }
  .sidebar-top,
  .site-nav {
    background: rgba(9,10,13,0.88);
  }
}

/* ── Phones: drop the effects that cost a full re-render every frame ───────────
   - No backdrop blur. The 3D background (bg-3d.js) redraws every frame, so every blurred
     panel on screen was re-blurred every frame too, and on a phone the panels cover almost
     the whole screen. The panels are a little more opaque instead, so the lattice behind
     stays as faint as it looked through the frost.
   - No wandering corner glows or panel shines. They animate custom properties inside
     gradients, which can't run on the compositor: each frame repainted the whole panel
     on the main thread. On a small screen the drift (38s+) and the shine (3.5% white)
     are next to invisible anyway.
   - The page's two drifting colour layers (fx.css body::before/::after, each 1.5× the
     screen) stay put: the drift is a few percent over a minute, and the lattice moving in
     front of them already keeps the background alive.
   Transform/opacity-only motion (carousel, sticker wind, logo glow, entrance) stays. */
@media (max-width: 767px) {
  body::before, body::after { animation: none; }
  .sidebar-top, .site-nav,
  .desc-section, .gig-section, .contact-section,
  rk-footer, .site-footer {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .desc-section { background: rgba(10,12,16,0.8); }
  .gig-section {
    background:
      radial-gradient(620px circle at var(--fx-gx) var(--fx-gy), rgba(0,255,204,0.11), transparent 56%),
      radial-gradient(520px circle at calc(100% - var(--fx-gx)) calc(100% - var(--fx-gy)), rgba(56,139,253,0.11), transparent 52%),
      linear-gradient(to bottom, rgba(17,17,17,0.78), rgba(12,12,12,0.84));
  }
  .contact-section {
    background:
      radial-gradient(620px circle at calc(100% - var(--fx-gx)) var(--fx-gy), rgba(56,139,253,0.13), transparent 56%),
      radial-gradient(520px circle at var(--fx-gx) calc(var(--fx-gy) + 6%), rgba(0,255,204,0.09), transparent 52%),
      linear-gradient(to bottom, rgba(17,17,17,0.78), rgba(12,12,12,0.84)),
      radial-gradient(rgba(125,140,158,0.2) 1px, transparent 1px);
    background-size: auto, auto, 100% 100%, 20px 20px;
    background-repeat: no-repeat, no-repeat, no-repeat, repeat;
  }
  .gig-section, .contact-section { animation: none; }
  .gig-stage.gig-emerge .gig-section { animation: gig-panel-in 0.95s cubic-bezier(0.16, 0.92, 0.24, 1.04) 0.28s backwards; }
  .desc-section::after, .gig-section::after, .contact-section::after { display: none; }
  /* The carousel's song card (mp3-tracks/styles.css, loaded later; the id outranks it).
     It's on screen for the whole song, under a waveform that redraws as it plays. */
  #activeAlbumEmbed .pc-card[data-track-id] {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background:
      radial-gradient(420px circle at var(--fx-gx) var(--fx-gy), rgba(0,255,204,0.10), transparent 60%),
      radial-gradient(360px circle at calc(100% - var(--fx-gx)) calc(100% - var(--fx-gy)), rgba(56,139,253,0.10), transparent 58%),
      rgba(16,18,24,0.78);
    animation: none;
  }
  #activeAlbumEmbed .pc-card[data-track-id]::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar::after,
  .gig-section, .contact-section,
  .desc-section::after, .gig-section::after, .contact-section::after,
  .album-card::after, .album-card.active,
  .gig-photo-frame {
    animation: none;
  }
  .gig-section { transition: none; }
}
