/* ---- Ghost City — base ---- */
:root{
  --cream:#f4ead0;
  --cream-soft:#e9dfc2;
  --fog:#a8bfc8;
  --fog-deep:#8aa3ad;
  --bone:#d8cfb8;
  --grass-shadow:#2a3a18;
  --ink:#1b2228;
  --serif:'IM Fell English', 'Cormorant Garamond', Georgia, serif;
  --body:'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --max:1100px;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
/* Horizontal containment: `clip` is preferred (doesn't create a scroll
   container, plays nicely with position:sticky); older iOS Safari falls
   back to `hidden`. Declared on BOTH html and body because iOS sometimes
   honors only the one it sees first. */
html{
  scroll-behavior:smooth;
  overflow-x:hidden;
  overflow-x:clip;
}
body{
  font-family:var(--body);
  color:var(--cream);
  background:#5d7c89;
  min-height:100vh;
  overflow-x:hidden;
  overflow-x:clip;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

img{max-width:100%;display:block}
a{color:inherit}

.visually-hidden{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

/* ---- Fixed layered sky gradient (no image) ---- */
.backdrop{
  position:fixed;inset:0;z-index:-30;
  background:
    /* warm golden-hour haze, upper right */
    radial-gradient(ellipse 70% 50% at 78% 18%, rgba(244,234,208,.34), transparent 62%),
    /* lavender wash, mid left */
    radial-gradient(ellipse 60% 70% at 12% 58%, rgba(178,168,200,.22), transparent 65%),
    /* dusty rose horizon glow, low center */
    radial-gradient(ellipse 110% 38% at 50% 102%, rgba(214,182,168,.28), transparent 70%),
    /* base sky: dusky top -> foggy mid -> warmer bottom — pitched a couple
       stops darker than a hazy SF morning so the cream serif type reads
       crisply against it. */
    linear-gradient(178deg, #44606e 0%, #557484 22%, #6e8b97 48%, #7c97a3 72%, #708893 100%);
}

/* ---- Sunset overlay: organically fades in as you scroll toward the bottom ---- */
/* JS writes a 0..1 number into --day. 0 = blue noon sky; 1 = full golden hour.
   --flare additionally damps the sun + lens-flare burst once the band photos
   have scrolled above the viewport, so the bright glow doesn't keep blasting
   against the empty footer / pyramid scene at the very bottom of the page. */
:root{ --day:0; --flare:1; }

.sunset{
  position:fixed;inset:0;z-index:-29;pointer-events:none;
  opacity:var(--day);
  transition:opacity .25s linear;
  background:
    /* glow rising off the horizon (sun's atmospheric scatter) */
    radial-gradient(ellipse 130% 55% at 50% 102%, rgba(255,196,118,.85), rgba(255,150,90,.45) 28%, rgba(220,90,90,.18) 55%, transparent 78%),
    /* warm haze lifting through the mid-sky */
    radial-gradient(ellipse 110% 50% at 50% 70%, rgba(255,176,118,.55), transparent 72%),
    /* high-altitude pinks and lavenders */
    radial-gradient(ellipse 90% 55% at 30% 22%, rgba(204,140,180,.45), transparent 70%),
    radial-gradient(ellipse 80% 45% at 78% 12%, rgba(255,170,150,.35), transparent 70%),
    /* base sunset: deep dusk top → magenta mid → blazing horizon bottom */
    linear-gradient(180deg,
      #2c3a5d 0%,
      #4f3f6b 16%,
      #8a4f6e 34%,
      #c46358 56%,
      #e6905a 76%,
      #f5b86c 92%,
      #fbd482 100%);
}

/* The sun: a fat warm disk that rises from below the horizon as --day grows. */
.sun{
  position:fixed;
  left:50%;
  bottom:calc(-32vh + var(--day) * 28vh);
  width:min(70vw, 760px);
  aspect-ratio:1 / 1;
  transform:translateX(-50%) scale(calc(.7 + var(--day) * .55));
  border-radius:50%;
  z-index:-28;
  pointer-events:none;
  opacity:calc(var(--day) * 1.05 * var(--flare, 1));
  background:
    radial-gradient(circle at 50% 50%,
      rgba(255,255,232,1) 0%,
      rgba(255,232,170,.95) 5%,
      rgba(255,196,128,.78) 14%,
      rgba(255,150,100,.4) 30%,
      rgba(255,120,90,.14) 48%,
      transparent 66%);
  filter:blur(2px);
  transition:opacity .25s linear, bottom .25s linear;
  mix-blend-mode:screen;
}

/* Lens flare: a horizontal streak across the horizon + a tall vertical column.
   Becomes visible alongside the sun and adds the cinematic glow. */
.sun-flare{
  position:fixed;
  inset:auto 0 -10vh 0;
  height:140vh;
  z-index:-28;
  pointer-events:none;
  opacity:calc(var(--day) * .9 * var(--flare, 1));
  transition:opacity .25s linear;
  background:
    /* horizontal streak across the horizon */
    linear-gradient(90deg,
      transparent 0%,
      rgba(255,210,160,0) 22%,
      rgba(255,225,180,.55) 50%,
      rgba(255,210,160,0) 78%,
      transparent 100%),
    /* vertical glow column rising through the page */
    linear-gradient(0deg,
      rgba(255,200,130,.55) 0%,
      rgba(255,200,130,.18) 30%,
      rgba(255,200,130,.05) 55%,
      transparent 80%);
  background-size:100% 18vh, 100% 100%;
  background-position:50% 70vh, 50% 100%;
  background-repeat:no-repeat;
  filter:blur(18px);
  mix-blend-mode:screen;
}

.vignette{
  position:fixed;inset:0;z-index:-20;pointer-events:none;
  background:
    radial-gradient(ellipse at 50% 30%, transparent 40%, rgba(20,30,40,.35) 100%),
    linear-gradient(180deg, rgba(0,0,0,.05) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,.25) 100%);
}

/* ---- Film grain ---- */
.grain{
  position:fixed;inset:-50%;z-index:60;pointer-events:none;
  opacity:.18;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.96  0 0 0 0 0.92  0 0 0 0 0.81  0 0 0 0.55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size:240px 240px;
  animation:grain 1.6s steps(6) infinite;
}
@keyframes grain{
  0%  { transform:translate(0,0) }
  20% { transform:translate(-3%,1%) }
  40% { transform:translate(2%,-2%) }
  60% { transform:translate(-1%,3%) }
  80% { transform:translate(3%,2%) }
  100%{ transform:translate(-2%,-1%) }
}

/* ---- Nav ---- */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:50;
  display:flex;align-items:center;justify-content:space-between;
  padding:18px 28px;
  font-family:var(--serif);
  letter-spacing:.04em;
  background:linear-gradient(180deg, rgba(0,0,0,.18), rgba(0,0,0,0));
  backdrop-filter:blur(0px);
}
.nav .brand{
  text-decoration:none;color:var(--cream);
  font-size:1.05rem;letter-spacing:.18em;text-transform:uppercase;
  opacity:.9;
}
.nav nav{display:flex;gap:22px}
.nav nav a{
  text-decoration:none;color:var(--cream);
  font-size:.95rem;letter-spacing:.16em;text-transform:uppercase;
  opacity:.78;transition:opacity .25s ease, transform .25s ease;
}
.nav nav a:hover{opacity:1;transform:translateY(-1px)}

@media (max-width:640px){
  .nav{padding:12px 16px}
  .nav .brand{font-size:.85rem}
  .nav nav{gap:14px}
  .nav nav a{font-size:.78rem;letter-spacing:.12em}
}

/* ---- Sections ---- */
main{position:relative;z-index:1}
section{
  position:relative;
  padding:120px 24px;
  max-width:var(--max);
  margin:0 auto;
}

/* ---- Section dividers ----
   A slim white horizontal rule placed between sections. Sections in this
   page each carry their own padding-top / padding-bottom (sometimes
   asymmetric), so a divider dropped at the boundary would naturally be
   off-center within the gap. We compensate per-pair with a small
   negative-top / positive-bottom (or vice versa) margin so the line
   lands at the visual midpoint of the gap — the distance from the
   divider to the previous section's last content equals the distance
   to the next section's first content. The net contribution to the
   document flow is just the divider's 1 px height, so existing layout
   isn't shifted. */
.section-divider{
  display:block;
  border:0;
  height:1px;
  width:clamp(180px, 50%, 480px);
  background:rgba(255, 255, 255, .42);
  margin:0 auto;
  position:relative;
  z-index:1;
}

/* music (pad-bot 120) → contact (pad-top 120): already symmetric */
.section-divider--music-contact{ margin:  0   auto   0;   }
/* contact (pad-bot 120) → photos (pad-top 40): center at 80 / 80 (shift -40) */
.section-divider--contact-photos{margin:-40px auto 40px; }

.section-title{
  /* Same Cormorant Upright treatment as the hero wordmark, just smaller —
     keeps the LISTEN / CONTACT headers in the same register. Non-italic. */
  font-family:'Cormorant Upright', var(--serif);
  font-weight:500;
  font-style:normal;
  text-align:center;
  font-size:clamp(2rem,2.4vw,4rem);
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--cream);
  opacity:.85;
  margin:0 0 48px;
}

/* ---- Hero ---- */
.hero{
  min-height:100vh;
  padding:14vh 24px 80px;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  text-align:center;
  position:relative;
}
/* Hero wordmark — Cormorant Upright: a quirky display cut with vertical
   italic-like forms, very "expensive and a little eccentric". */
.hero .logo-text{
  margin:0;
  position:relative;
  /* Sits above .eagle so the bird passes behind the wordmark. */
  z-index:2;
  font-family:'Cormorant Upright', var(--serif);
  font-weight:500;
  font-style:normal;
  color:var(--cream);
  text-transform:uppercase;
  letter-spacing:.22em;
  font-size:clamp(3rem, 10vw, 5rem);
  line-height:1;
  /* Pull the first character's left side-bearing back so the tracked
     title stays optically centered on the page. */
  text-indent:.22em;
  text-shadow:0 6px 24px rgba(0,0,0,.35);
  animation:logoIn 1.6s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes logoIn{
  from{opacity:0;transform:translateY(18px) scale(.985);filter:blur(6px)}
  to  {opacity:1;transform:translateY(0)    scale(1);   filter:blur(0)}
}
.hero .tag{
  margin-top:20px;
  font-family:var(--serif);font-style:italic;
  font-size:clamp(2rem, 1.6vw, 2.5rem);
  letter-spacing:.32em;
  text-transform:lowercase;
  color:var(--cream);
  opacity:0;
  animation:fadeUp 1.2s ease 1s forwards;
}
@keyframes fadeUp{
  from{opacity:0;transform:translateY(10px)}
  to  {opacity:.85;transform:translateY(0)}
}

/* Centering frame for the hero polaroid. Sits as the last flex child of
   .hero with flex-grow:1 so it eats every remaining pixel between the
   subtitle (.tag) and the hero's bottom-padding edge, then vertically
   centers the polaroid in that space — which puts the photo at the
   visual midpoint between the subtitle and the bottom of the hero
   (which now flows directly into the bio's first ornament dot, since
   the bio is no longer bracketed by section dividers). */
.hero-stage{
  flex:1 1 auto;
  display:flex;
  align-items:center;
  justify-content:center;
  width:100%;
}

/* Hero polaroid: large band photo in the same frame as the gallery.
   Width is capped at 600 px on very wide viewports so the photo doesn't
   balloon out on large monitors. Phones and tablets stay on the 86vw
   side of the min(): the cap only kicks in once the viewport is wider
   than ~700 px, so smaller-screen sizing is unchanged. */
.hero-polaroid{
  margin:0 auto;
  width:min(86vw, 600px);
  padding:6px;
  background:#fdf8ec;
  border-radius:8px;
  box-shadow:
    0 1px 0 rgba(255,255,255,.6) inset,
    0 24px 60px rgba(0,0,0,.5),
    0 6px 14px rgba(0,0,0,.3);
  transform:rotate(-1.4deg);
  opacity:0;
  animation:heroPolaroidIn 1.4s cubic-bezier(.2,.8,.2,1) 1.3s forwards;
  transition:transform .5s cubic-bezier(.2,.8,.2,1), box-shadow .35s ease;
  will-change:transform,opacity;
}
.hero-polaroid img{
  width:100%;
  height:auto;
  display:block;
  background:#222;
  border-radius:4px;
  filter:saturate(.95) contrast(1.02);
}
.hero-polaroid:hover{
  transform:rotate(-.4deg) translateY(-4px);
  box-shadow:
    0 1px 0 rgba(255,255,255,.6) inset,
    0 32px 72px rgba(0,0,0,.55),
    0 8px 18px rgba(0,0,0,.35);
}
@keyframes heroPolaroidIn{
  from{ opacity:0; transform:rotate(-3deg) translateY(30px) scale(.97) }
  to  { opacity:1; transform:rotate(-1.4deg) translateY(0) scale(1) }
}

/* Eagle: a small distant bird that darts across the sky every ~10s. */
.eagle{
  position:absolute;
  top:calc(35vh);
  left:-12%;
  width:min(34px, 4vw);
  opacity:0;
  filter:drop-shadow(0 3px 8px rgba(0,0,0,.3));
  animation:soar 15s linear infinite, flap .32s ease-in-out infinite;
  transform-origin:center;
  pointer-events:none;
  z-index:0;
}
/* Total cycle = 15s. Eagle is visible roughly the first 5s (fast fly-across),
   then sits offscreen for ~10s before reappearing. */
@keyframes soar{
  /* Same starting point, but the bird now glides on a ~30° downward
     trajectory instead of a near-horizontal pass. Body is rotated ~30°
     clockwise throughout so the eagle visibly *points* into its dive. */
  0%   { transform:translate(0vw, 0vh)   rotate(30deg); opacity:0 }
  2%   { opacity:.9 }
  10%  { transform:translate(35vw, 18vh) rotate(30deg) }
  22%  { transform:translate(75vw, 39vh) rotate(30deg) }
  33%  { transform:translate(125vw, 65vh) rotate(30deg); opacity:.9 }
  36%  { opacity:0 }
  100% { transform:translate(125vw, 65vh);               opacity:0 }
}
@keyframes flap{
  0%,100% { filter:drop-shadow(0 3px 8px rgba(0,0,0,.3)) }
  50%     { filter:drop-shadow(0 2px 4px rgba(0,0,0,.18)) }
}

/* ---- Bio ---- */
.bio{
  max-width:770px;
  text-align:center;
  padding-top:60px;padding-bottom:80px;
}
.ornament{
  font-family:var(--serif);
  color:var(--cream);
  opacity:.6;
  font-size:1.4rem;
  margin:8px 0 20px;
  letter-spacing:.2em;
}
/* Nudge the bio's two decorator dots outward from the copy: the top one
   sits 10px higher, the bottom one 20px lower. Uses transform so the
   surrounding flow (and every other section's spacing) is untouched. */
.bio .ornament:first-of-type{ transform:translateY(-10px); }
.bio .ornament:last-of-type{  transform:translateY(20px);  }
.bio-copy{
  font-family:var(--serif);
  font-style:normal;
  font-size:clamp(1.5rem, 4vw, 2.4rem);
  line-height:1.35;
  color:var(--cream);
  margin:0 auto;
  text-shadow:0 2px 18px rgba(0,0,0,.25);
}
/* Drop-cap "A" stays italic for that flourishy opening — everything
   after it reads upright like printed liner notes. */
.bio-copy::first-letter{
  font-style:italic;
  font-size:1.35em;
  line-height:1;
}

/* ---- Music + socials ---- */
.music{
  max-width:720px;
}
.player{
  border-radius:14px;
  overflow:hidden;
  box-shadow:0 18px 60px rgba(0,0,0,.35);
  background:rgba(0,0,0,.35);
}
.player iframe{display:block}

.socials{
  list-style:none;padding:0;margin:44px 0 0;
  display:flex;justify-content:center;gap:48px;flex-wrap:wrap;
}
.socials a{
  display:inline-flex;align-items:center;gap:14px;
  text-decoration:none;color:#fff;
  font-family:var(--serif);font-style:normal;
  letter-spacing:.12em;font-size:1.45rem;
  padding:10px 6px;
  opacity:1;
  /* Layered shadows: a soft dark glow under the glyphs to lift them off
     the variable sky behind, plus a subtle bright lift so they don't go
     muddy against darker sections. */
  text-shadow:
    0 1px 2px rgba(0,0,0,.55),
    0 0 18px rgba(0,0,0,.35);
  transition:opacity .25s ease, transform .25s ease;
}
.socials a:hover{opacity:1;transform:translateY(-2px)}
.socials svg{
  width:38px;height:38px;
  fill:#fff;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.55)) drop-shadow(0 0 8px rgba(0,0,0,.35));
}

.socials.small{gap:27px;margin:0}
.socials.small svg{width:33px;height:33px}
.socials.small a span{display:none}

/* ---- Scene: TransAmerica pyramid behind a curved SF hill ----
   Layout strategy:
   - Fixed-height stage so the entire pyramid is always visible inside it.
   - Pyramid is absolutely positioned, planted with just its very base
     sunk a touch below the crest of the hill (z-index 1, BEHIND grass).
   - Grass sits at the bottom of the stage (z-index 2, IN FRONT) at a
     deterministic height; we share that height via --grass-h so the
     pyramid's base is always a fixed offset below the crest.
   - Grass bottom edge is mask-faded so it dissolves into the sky. */
.scene{
  --grass-h:clamp(120px, 12vw, 180px);
  max-width:none;
  /* 100% (not 100vw) so mobile Safari can't render this wider than the
     true visible viewport — 100vw includes scrollbar gutter in some
     rendering paths and was contributing to right-side scroll overflow. */
  width:100%;
  margin:30px 0 0;
  padding:0;
  position:relative;
  pointer-events:none;
  overflow:hidden;
  /* Headroom expanded so the taller pyramid (50% bigger) clears the hill. */
  height:clamp(490px, 46vw, 620px);
}
.scene .pyramid{
  position:absolute;
  left:50%;
  /* Base sits 18px below the crest of the hill — just a kiss of overlap. */
  bottom:calc(var(--grass-h) - 18px);
  transform:translateX(-50%);
  /* Width drives height (image is ~4:1); +50% on the previous footprint. */
  width:clamp(75px, 7.5vw, 113px);
  height:auto;
  z-index:1;
  filter:drop-shadow(0 14px 22px rgba(0,0,0,.4));
}
.scene .grass{
  position:absolute;
  left:50%;
  bottom:0;
  transform:translateX(-50%);
  /* Fix the grass HEIGHT (not width) so the crest position is predictable
     across every viewport size; let the very wide image overspill horizontally. */
  height:var(--grass-h);
  width:auto;
  max-width:none;
  z-index:2;
  /* Sharp at the crest, fizzles into the sky toward the bottom. */
  -webkit-mask-image:linear-gradient(180deg, #000 0%, #000 35%, transparent 100%);
          mask-image:linear-gradient(180deg, #000 0%, #000 35%, transparent 100%);
}

/* Ghosts perched on the left slope of the curved hill. They sit ABOVE the
   grass (z-index 3) so they don't get mask-faded, but below the nav. The
   `bottom` values place each ghost's feet roughly on the left slope of the
   grass; the sitting one lounges low on the slope, the walking one stands
   a little further up the hill. */
.scene .ghost{
  position:absolute;
  z-index:3;
  pointer-events:none;
  filter:drop-shadow(0 10px 14px rgba(0,0,0,.3));
  opacity:.95;
}
.scene .ghost-walking{
  display: none; /* This was a failed experiment... removing unless we change our minds later */
  left:10vw;
  bottom:calc(var(--grass-h) * .22);
  width:clamp(102px, 12.75vw, 200px);
  height:auto;
}
@media (max-width:640px){
  .scene .ghost-walking{left:18vw}
}

/* ---- Polaroid gallery ----
   Layout principle: scatter is expressed in viewport units (vw), so the
   composition feels equally relaxed on a 13" laptop and a 27" monitor.
   Card sizes use clamp() to keep them legible on small screens without
   blowing up unreasonably on huge ones. The .gallery box is allowed to
   stretch wider than the rest of the page (max-width 1500px) since the
   scatter wants horizontal room to breathe. */
.gallery{
  padding-top:40px;
  padding-bottom:160px;
  max-width:1500px;
}
.polaroids{
  position:relative;
  /* Height tracks the viewport so cards never bunch up vertically as the
     scatter widens. */
  height:clamp(580px, 52vw, 760px);
  margin:0 auto;
  perspective:1200px;
}
/* Inner canvas the figures anchor to. On desktop it's a no-op 100%/100%
   block; on mobile (see @media below) it becomes wider than the viewport
   so the scatter stays relaxed and the outer .polaroids handles the
   horizontal scroll. */
.polaroids-track{
  position:relative;
  width:100%;
  height:100%;
}
.polaroids figure{
  /* JS-driven push offset (only set on hover-capable devices) */
  --px:0px; --py:0px;
  position:absolute;
  top:50%;left:50%;
  width:clamp(220px, 19vw, 310px);
  margin:0;
  padding:14px 14px 56px;
  background:#fdf8ec;
  box-shadow:
    0 1px 0 rgba(255,255,255,.6) inset,
    0 18px 40px rgba(0,0,0,.45),
    0 4px 10px rgba(0,0,0,.3);
  transform:
    translate(-50%,-50%)
    translate(calc(var(--x) + var(--px)), calc(var(--y) + var(--py)))
    rotate(var(--r));
  /* default (resting) transition: long, gentle settle. The 1.5s+ duration lets
     polaroids drift back into place rather than snap. z-drop waits for the
     transform to mostly complete so the lifted card stays on top until it lands. */
  transition:
    transform 1.6s cubic-bezier(.22, 1, .32, 1),
    box-shadow 1.4s ease,
    z-index 0s linear 1.4s;
  will-change:transform;
}

/* Default scatter: tablet/desktop. Two staggered rows of four cards, fanned
   out to ~±32vw which fits comfortably inside the 1500px gallery on
   anything from ~1200px upward and stays interesting on smaller viewports
   (the @media block below tightens it for phones). */
.polaroids figure:nth-child(1){ --x:-30vw; --y:-40px }
.polaroids figure:nth-child(2){ --x:-12vw; --y:-70px }
.polaroids figure:nth-child(3){ --x:8vw;   --y:-30px }
.polaroids figure:nth-child(4){ --x:28vw;  --y:-60px }
.polaroids figure:nth-child(5){ --x:-32vw; --y:200px }
.polaroids figure:nth-child(6){ --x:-10vw; --y:230px }
.polaroids figure:nth-child(7){ --x:14vw;  --y:240px }
.polaroids figure:nth-child(8){ --x:32vw;  --y:200px }
.polaroids figure img{
  width:100%;
  aspect-ratio:1/1;
  object-fit:cover;
  background:#222;
  filter:saturate(.9) contrast(1.02);
}

/* Hover effects only on devices with a real pointer (desktop/laptop). */
@media (hover: hover) and (pointer: fine){
  .polaroids figure:hover{
    transform:
      translate(-50%,-50%)
      translate(var(--x), calc(var(--y) - 18px))
      rotate(calc(var(--r) * .25))
      scale(1.05);
    box-shadow:
      0 1px 0 rgba(255,255,255,.6) inset,
      0 32px 70px rgba(0,0,0,.55),
      0 8px 18px rgba(0,0,0,.35);
    z-index:30;
    /* matched 1.5s slow lift on hover-in. z-pop is immediate so the card
       comes to the top right away while the rest of the motion eases in. */
    transition:
      transform 1.5s cubic-bezier(.22, 1, .32, 1),
      box-shadow 1.2s ease,
      z-index 0s;
  }
}

@media (max-width:780px){
  /* Phone: cards stay chunky (40vw) but the scatter is sized so even the
     edge-most card lands fully inside the visible window — no clipping
     and no horizontal scrolling needed. The container is roughly 88vw
     wide on a 390 px phone after the section's 24 px side padding;
     half = 44vw, so edge cards at ±21vw + half-card 20vw = ±41vw fit
     comfortably (works down to ~320 px screens too). The .polaroids-track
     wrapper drops back to 100 % so it has no horizontal-scroll role. */
  .polaroids{ height:580px; }
  .polaroids-track{ width:100%; }
  .polaroids figure{ width:40vw; }

  .polaroids figure:nth-child(1){ --x:-21vw; --y:-50px }
  .polaroids figure:nth-child(2){ --x:-2vw;  --y:-70px }
  .polaroids figure:nth-child(3){ --x:21vw;  --y:-40px }
  .polaroids figure:nth-child(4){ --x:-16vw; --y:70px }
  .polaroids figure:nth-child(5){ --x:14vw;  --y:90px }
  .polaroids figure:nth-child(6){ --x:-21vw; --y:200px }
  .polaroids figure:nth-child(7){ --x:0;     --y:220px }
  .polaroids figure:nth-child(8){ --x:21vw;  --y:200px }
}

/* ---- Contact ---- */
/* Layout mirror of the Music section: the section-title (CONTACT) sits
   above a self-contained dark card (.contact-card), exactly the way
   LISTEN sits above the Spotify .player box.

   The dark "card" lives on a ::before layer so we can fade just the
   panel (background, border, shadow, blur) in/out without touching the
   text. JS writes a 0..1 --shine variable on .contact; the value
   cascades to .contact-card and its ::before so the panel materialises
   as the sun passes behind it, then dissolves away again. */
.contact{
  text-align:center;
  max-width:640px;
  margin-bottom:140px;
  --shine:0;
}
.contact-card{
  position:relative;
  isolation:isolate;
  padding:48px 44px 56px;
}
.contact-card::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  border-radius:6px;
  background:rgba(22, 28, 36, .55);
  border:10px solid rgba(244, 234, 208, .14);
  backdrop-filter:blur(10px) saturate(115%);
  -webkit-backdrop-filter:blur(10px) saturate(115%);
  box-shadow:
    0 18px 50px rgba(0, 0, 0, .35),
    0 1px 0 rgba(255, 255, 255, .04) inset;
  opacity:var(--shine, 0);
  transition:opacity .25s ease-out;
  pointer-events:none;
  will-change:opacity;
}

@media (max-width: 600px){
  .contact-card{
    padding:32px 22px 38px;
  }
  .contact-card::before{
    border-width:6px;
  }
}
/* The "CONTACT" heading keeps its italic flourish (matches the rest of
   the section titles), but the body copy below is upright so the booking
   pitch reads plainly, like printed placard copy. */
.contact-copy{
  font-family:var(--serif);
  font-style:normal;
  font-size:clamp(1.15rem, 2vw, 1.5rem);
  line-height:1.55;
  color:var(--cream);
  opacity:.92;
  margin:0 0 22px;
}
.contact-email{
  /* Lets long email strings break inside the dark card on narrow phones
     instead of pushing past the right edge of the panel. */
  overflow-wrap:anywhere;
  word-break:break-word;
  margin:0;
}
.contact-email a{
  font-family:var(--body);
  /* Scales the address down on narrow screens (4.2vw on a 390 px phone
     ≈ 16 px) while keeping the original ~28 px size on tablet/desktop. */
  font-size:clamp(1rem, 4.2vw, calc(1.5rem + 4px));
  color:var(--cream);
  text-decoration:none;
  border-bottom:1px solid rgba(244,234,208,.4);
  padding-bottom:2px;
  letter-spacing:.04em;
  transition:border-color .25s ease, color .25s ease;
}
.contact-email a:hover{
  color:#fff;
  border-color:rgba(255,255,255,.9);
}

/* ---- Footer ---- */
.footer{
  position:relative;z-index:2;
  padding:45px 24px 75px;
  display:flex;flex-direction:column;align-items:center;gap:21px;
  text-align:center;
}
.footer .copy{
  font-family:var(--serif);font-style:normal;
  font-size:1.275rem;letter-spacing:.18em;text-transform:uppercase;
  opacity:.65;margin:0;
}

/* ---- Lightbox (full-screen photo viewer) ---- */
body.lightbox-open{ overflow:hidden; }

.lightbox{
  position:fixed;
  inset:0;
  z-index:100;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:clamp(20px, 5vw, 60px);
  background:rgba(14, 22, 28, .92);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  opacity:0;
  pointer-events:none;
  transition:opacity .3s ease;
  cursor:zoom-out;
}
.lightbox.open{
  opacity:1;
  pointer-events:auto;
}

.lightbox-frame{
  margin:0;
  padding:18px 18px 64px;
  background:#fdf8ec;
  box-shadow:
    0 1px 0 rgba(255,255,255,.6) inset,
    0 30px 80px rgba(0,0,0,.6),
    0 8px 18px rgba(0,0,0,.4);
  max-width:min(92vw, 1100px);
  max-height:90vh;
  display:flex;
  cursor:default;
  transform:scale(.94) rotate(-.6deg);
  transition:transform .4s cubic-bezier(.18, 1.05, .25, 1.15);
}
.lightbox.open .lightbox-frame{
  transform:scale(1) rotate(0);
}
.lightbox-frame img{
  display:block;
  max-width:100%;
  max-height:calc(90vh - 82px);
  width:auto;
  height:auto;
  object-fit:contain;
  background:#222;
}

.lightbox-close{
  position:absolute;
  top:18px;
  right:22px;
  width:46px;
  height:46px;
  border-radius:50%;
  background:rgba(244, 234, 208, .12);
  border:1px solid rgba(244, 234, 208, .35);
  color:var(--cream);
  font:300 28px/1 var(--body);
  cursor:pointer;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:0 0 4px;
  transition:background .2s ease, transform .2s ease, border-color .2s ease;
}
.lightbox-close:hover,
.lightbox-close:focus-visible{
  background:rgba(244, 234, 208, .22);
  border-color:rgba(244, 234, 208, .7);
  transform:scale(1.06);
  outline:none;
}

@media (max-width:600px){
  .lightbox-frame{ padding:12px 12px 40px; }
  .lightbox-close{ top:12px; right:14px; width:42px; height:42px; }
}

/* ---- Scroll reveal ---- */
.reveal{
  opacity:0;
  transform:translateY(24px);
  transition:opacity .9s cubic-bezier(.2,.8,.2,1), transform .9s cubic-bezier(.2,.8,.2,1);
}
.reveal.visible{
  opacity:1;
  transform:translateY(0);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce){
  *{ animation:none !important; transition:none !important }
  .reveal{opacity:1;transform:none}
  .grain{display:none}
}
