/* ============================================================================
   overlays.css — Video backdrop, invisible chapters, overlay base layer.
   Per-overlay visual styles (beach/bar/transition/dj) added in Phase 4.
   ============================================================================ */

/* --- Frame-sequence canvas backdrop (z-index 0) --------------------------- */
/* The <canvas> is drawn by js/scroll-video.js using a 209-image JPEG
   sequence. The poster acts as the fallback painted under the canvas —
   shown while frames are loading, and kept for reduced-motion mode.      */

body {
  background-color: var(--ink-deep);
  background-image: url('../assets/video/playa-poster.jpg');
  background-size: cover;
  background-position: center;
  /* NOTE: background-attachment deliberately defaults to `scroll` (not
     `fixed`). With `fixed`, the poster was pinned to the viewport and
     bled through anywhere the canvas didn't cover (top/bottom strips
     on iOS when URL-bar state and canvas sizing were out of sync) —
     making the beach look like it "stayed underneath" during bar/DJ
     chapters. With `scroll`, the poster scrolls off with the document
     and any gap behind the canvas falls back to #000 (invisible
     against the overlays). */
}

#backdrop {
  position: fixed;
  inset: 0;
  /* `inset: 0` already fills the viewport; explicit width: 100vw was
     causing 15–17px horizontal scroll on Windows where the scrollbar
     reserves physical space. Removing it. */
  /* iOS Safari viewport strategy revised 2026-04-20 (v=19):
     - Use 100vh (= 100lvh "large viewport", URL-bar hidden) so the
       canvas is ALWAYS at least as tall as any visible viewport state.
       When the URL bar is showing, the bottom extra is occluded by the
       browser chrome (position:fixed clips cleanly) — no visible strip.
     - 100svh would be too short: when URL bar hides, a gap appears.
     - The previous 100dvh approach was still racy because the canvas
       element gets its final size from JS (style.height), and JS +
       CSS + layout could disagree by one frame when the URL bar
       animates. Using the maximum viewport eliminates the race. */
  height: 100vh;
  height: 100lvh;
  z-index: 0;
  display: block;
  pointer-events: none;
}

/* Reduced-motion: hide the canvas and show the poster backdrop only */
body.reduced-motion #backdrop {
  display: none;
}

/* --- Fireflies layer (z-index 5) ------------------------------------------ */
/* Ambient golden particles drifting between backdrop and overlays. Drawn
   by js/fireflies.js. `pointer-events: none` so it never steals clicks
   from the overlay buttons above. */
#fireflies {
  position: fixed;
  inset: 0;
  /* width: 100vw removed — see #backdrop note. inset: 0 fills viewport. */
  height: 100vh;
  height: 100lvh;
  z-index: 5;
  display: block;
  pointer-events: none;
  /* Additive-ish blend: the yellow cores "pop" over the warm beach tones
     without looking like flat stickers. `screen` is broadly supported. */
  mix-blend-mode: screen;
}

/* Reduced-motion: no fireflies at all (movement is the whole point). */
body.reduced-motion #fireflies {
  display: none;
}

/* --- Chapters (invisible triggers, z-index 1) ------------------------------ */

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

.chapter {
  position: relative;
  width: 100%;
  /* height is set inline per chapter to give ScrollTrigger exact boundaries */
  pointer-events: none; /* chapters never intercept clicks */
}

/* --- Overlay base layer (z-index 10) --------------------------------------- */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
  opacity: 0;                  /* GSAP flips via ScrollTrigger */
  pointer-events: none;        /* JS enables per overlay when visible */
  will-change: opacity;
}

.overlay.is-active {
  pointer-events: auto;
}

/* --- DJ scrim (covers the 6.5s → 8.4s video jump) ------------------------- */

.dj-scrim {
  position: absolute;
  inset: 0;
  background: var(--night-deep, #2A0E1A);
  opacity: 0;
  pointer-events: none;
}

/* --- Responsive guard: overlay vertical stacking on small screens --------- */

@media (max-width: 600px) {
  .overlay {
    padding: 12px;
  }
}

/* --- Beach overlay -------------------------------------------------------- */

.overlay--beach {
  flex-direction: column;
  justify-content: center;          /* logo+claim truly centered vertically */
  align-items: center;
  padding: clamp(40px, 8vh, 100px) clamp(16px, 4vw, 48px);
}

/* Soft initial readability scrim behind the logo/claim.
   Fully opaque at scroll=0, faded out by js/overlays.js once the user
   starts scrolling, so the photography takes over. */
.beach-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;   /* behind .beach-center (which is implicit z-auto) */
  background:
    radial-gradient(
      ellipse at 50% 42%,
      rgba(0, 0, 0, 0.55) 0%,
      rgba(0, 0, 0, 0.25) 55%,
      rgba(0, 0, 0, 0) 85%
    );
  opacity: 1;
  transition: opacity 0.35s ease;
  will-change: opacity;
}

.beach-center {
  position: relative;
  z-index: 1; /* above .beach-scrim */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(18px, 3vh, 32px);
}

.beach-logo {
  /* Transparent SVG — keep natural aspect (≈2.1:1), drop the old circular
     mask + shadow that were there for the JPG version. A soft drop-shadow
     filter replaces box-shadow so it follows the logo's actual outline. */
  width: clamp(240px, 44vw, 380px);
  height: auto;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.45));
}

.beach-claim {
  color: #fff;
  text-align: center;
  font-family: var(--font-hero, 'Playfair Display', serif);
  font-style: italic;          /* editorial, "dolce vita" feel */
  font-weight: 700;
  font-size: clamp(1.9rem, 5vw, 3.2rem);
  line-height: 1.2;
  letter-spacing: 0.005em;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
  max-width: min(92vw, 640px);
  margin: 0;
  /* Avoid orphaned single words on the last line. Modern browsers honor
     this; older ones safely ignore it. */
  text-wrap: balance;
  /* Fraunces variable axis hook — JS animates --fraunces-opsz on scroll
     to morph display-grade glyphs into more "intimate" text-grade ones. */
  font-variation-settings: 'opsz' var(--fraunces-opsz, 144), 'SOFT' 30;
}

/* --- Quick nav (global, fixed top-center, liquid glass pill) -------------- */
/* Lets the user jump directly between the three big moments of the site.
   Visible from first paint. Each button acts as a scroll target; the
   active button tracks the current chapter (class toggled in JS). */
.quick-nav {
  position: fixed;
  top: clamp(14px, 2.5vh, 24px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 12;
  display: flex;
  gap: 4px;
  padding: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(22px) saturate(1.6);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  box-shadow:
    inset 0 1px 1.2px rgba(255, 255, 255, 0.5),
    inset 0 -1px 0 rgba(0, 0, 0, 0.2),
    0 10px 30px rgba(0, 0, 0, 0.35);
  transition: opacity 0.35s ease;
  will-change: opacity;
}

.qn-btn {
  border: 0;
  background: transparent;
  color: #fff;
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.72rem, 1.8vw, 0.85rem);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: clamp(8px, 1.4vh, 12px) clamp(14px, 3vw, 22px);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.25s ease,
              color 0.25s ease,
              transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.3s ease;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}

.qn-btn:hover,
.qn-btn:focus-visible {
  background: rgba(255, 255, 255, 0.16);
  transform: translateY(-1px);
  outline: none;
}

.qn-btn:active {
  transform: translateY(0) scale(0.96);
  transition-duration: 0.1s;
}

.qn-btn.is-active {
  /* Solid pill that matches the sunset palette so the user sees where
     they are at a glance. Sunset-tinted shadow for warmth. */
  background: linear-gradient(
    165deg,
    rgba(245, 166, 35, 0.95) 0%,
    rgba(193, 74, 74, 0.9) 100%
  );
  color: #fff;
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.5),
    0 4px 12px rgba(193, 74, 74, 0.42),
    0 2px 6px rgba(245, 166, 35, 0.22);
}

/* Home button: circular icon pill (svg centered, no text). */
.qn-btn--icon {
  padding: 0;
  width: clamp(34px, 8vw, 42px);
  height: clamp(34px, 8vw, 42px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.qn-btn--icon svg {
  display: block;
  width: 60%;
  height: 60%;
}

@media (max-width: 420px) {
  .qn-btn {
    padding: 8px 12px;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
  }
}

/* --- Scroll hint (global, fixed, continuous) ------------------------------ */
/* Lives outside the overlay system so it persists through the entire
   scroll journey. Sits above overlays (z-index 11) and is horizontally
   centered via left:50%/translateX(-50%).
   The bounce animation runs ONLY on the arrow child — applying it to the
   container would overwrite translateX(-50%) and push the hint off-center. */
.scroll-hint {
  position: fixed;
  bottom: clamp(20px, 4vh, 48px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 11;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(8px, 1.2vh, 14px);
  color: #fff;
  opacity: 0.85;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  transition: opacity 0.4s ease;
  will-change: opacity;
}

/* When the DJ overlay is the dominant view, fade out the hint so it
   doesn't fight the social buttons / countdown at the end of scroll.
   Toggled by js/overlays.js via .is-hidden. */
.scroll-hint.is-hidden {
  opacity: 0;
}

/* Override the global .label baseline (uppercase + wide tracking from base.css)
   — for a whole sentence we need tighter tracking so it reads as a phrase,
   not three words mashed into paragraph width. */
.scroll-hint .label {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.68rem, 1.3vw, 0.8rem);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  max-width: 82vw;
  line-height: 1.35;
}

/* Swipe-down gesture: phone-screen frame + touchpoint dot that
   travels from top to bottom, fades, resets. The dot uses
   transform-box: fill-box so translateY is relative to its own
   geometry (not the SVG root), which gives us a pixel-exact swipe. */
.scroll-hint .swipe-icon {
  width: clamp(26px, 3.6vw, 34px);
  height: auto;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}

.scroll-hint .swipe-dot {
  transform-box: fill-box;
  transform-origin: center;
  animation: swipe-scroll 1.9s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes swipe-scroll {
  0%   { transform: translateY(0);    opacity: 0; }
  15%  { transform: translateY(0);    opacity: 1; }
  65%  { transform: translateY(20px); opacity: 1; }
  85%  { transform: translateY(20px); opacity: 0; }
  100% { transform: translateY(0);    opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-hint .swipe-dot { animation: none; }
}

/* --- Bar overlay ---------------------------------------------------------- */

.overlay--bar {
  background: linear-gradient(180deg, rgba(42, 14, 26, 0.15), rgba(42, 14, 26, 0.55));
}

.bar-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(24px, 5vh, 48px);
  width: 100%;
  max-width: 900px;
}

.bar-title {
  color: var(--sand-cream, #FFF3E0);
  font-family: 'Fraunces', serif;
  font-weight: 900;
  font-size: clamp(2rem, 6vw, 4rem);
  text-align: center;
  text-wrap: balance;
  margin: 0;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.5);
}

.bar-cards {
  display: flex;
  gap: clamp(14px, 3vw, 24px);
  width: 100%;
  max-width: clamp(340px, 78vw, 620px);   /* aligned to the title's optical width */
  margin-inline: auto;
  justify-content: stretch;
  align-items: stretch;
  flex-wrap: wrap;                         /* third card wraps to a second row */
  row-gap: clamp(12px, 2.4vw, 20px);
}

/* The third .card (CAFFÈ E FRUTTA) sits below DRINK + CIBI as a wider
   "secondary" CTA spanning the full row. flex-basis: 100% combined with
   flex-wrap on the parent forces the wrap. */
.bar-cards > .card:nth-child(3) {
  flex-basis: 100%;
}

/* Horizontal pill CTAs — each one opens its own menu on click. Liquid
   glass treatment: tinted translucent fill, strong backdrop blur +
   saturation boost (so the bar behind bleeds through), crisp top specular
   highlight, subtle bottom shading, soft ambient drop shadow. ::before
   adds a radial gleam that sells the curved-glass read. The two cards
   share the row equally and span up to the title's optical width, height
   stays tight (~80–100px) so the bar background reads through and the
   cards feel like buttons rather than panels. */
.card {
  flex: 1 1 0;
  min-width: 0;
  min-height: clamp(78px, 10vh, 100px);
  padding: clamp(14px, 2vh, 18px) clamp(18px, 3vw, 28px);
  border: 1px solid rgba(255, 255, 255, 0.32);
  border-radius: 22px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;     /* label + hint clustered in the middle of the card */
  gap: clamp(6px, 1.2vh, 12px);
  text-align: center;
  font-family: 'Fraunces', serif;
  color: #fff;
  backdrop-filter: blur(22px) saturate(1.6);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.55),   /* top specular line */
    inset 0 -1px 0 rgba(0, 0, 0, 0.22),            /* bottom edge shade */
    0 14px 36px rgba(193, 74, 74, 0.34),           /* ambient drop, sunset-tinted */
    0 4px 12px rgba(245, 166, 35, 0.18);           /* contact shadow, orange-warm */
  /* Spring easing on transform for a "weighted" hover lift; box-shadow + blur
     keep linear easing so they don't overshoot. */
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.35s ease,
              backdrop-filter 0.3s ease;
  pointer-events: auto;
  position: relative;
  overflow: hidden;
  isolation: isolate;       /* keep ::before composited cleanly on top */
}

/* Radial gleam at the top — mimics light catching the curve of glass. */
.card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 55%;
  background: radial-gradient(
    ellipse at 50% -15%,
    rgba(255, 255, 255, 0.38) 0%,
    rgba(255, 255, 255, 0.06) 55%,
    rgba(255, 255, 255, 0) 80%
  );
  pointer-events: none;
  z-index: 1;
}

/* Cursor-tracked spotlight: a soft warm halo that follows the pointer
   inside the card. CSS custom props --mx/--my are updated by js/main.js
   on mousemove. Skipped on touch and reduced-motion. */
.card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 209, 102, 0.22) 0%,    /* gold-glow core */
    rgba(245, 166, 35, 0.10) 35%,    /* orange falloff */
    transparent 65%
  );
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: screen;
}

@media (hover: hover) {
  .card:hover::after { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .card::after { display: none; }
}

/* Keep label + hint above the gleam and spotlight. */
.card-label,
.card-hint { position: relative; z-index: 2; }

/* Alpha bumped (0.68/0.48 → 0.9/0.78 and 0.66/0.48 → 0.9/0.78) so the
   labels stay legible against busy backgrounds; still translucent enough
   to read as "liquid glass" rather than a solid card. */
.card--drink {
  background: linear-gradient(
    165deg,
    rgba(245, 166, 35, 0.90) 0%,
    rgba(193, 74, 74, 0.78) 100%
  );
}

.card--food {
  background: linear-gradient(
    165deg,
    rgba(232, 201, 155, 0.92) 0%,
    rgba(245, 166, 35, 0.82) 100%
  );
}

/* Caffè e Frutta — espresso-meets-caramel gradient, distinct from the
   warmer drink/food cards but still in the same warm-earth brand family. */
.card--cafe {
  background: linear-gradient(
    165deg,
    rgba(96, 64, 42, 0.88) 0%,        /* dark espresso */
    rgba(180, 132, 90, 0.82) 100%     /* caramel latte */
  );
}

.card:hover,
.card:focus-visible {
  transform: translateY(-6px) scale(1.025);
  backdrop-filter: blur(26px) saturate(1.8);
  -webkit-backdrop-filter: blur(26px) saturate(1.8);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.22),
    0 22px 54px rgba(193, 74, 74, 0.45),           /* lift, deeper sunset */
    0 8px 20px rgba(245, 166, 35, 0.28);           /* warm halo */
  outline: none;
}

.card:active {
  transform: translateY(-1px) scale(0.985);
  transition-duration: 0.12s;
}

.card-label {
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  font-weight: 900;
  letter-spacing: 0.06em;
  line-height: 1;
}

.card-hint {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.72rem, 1.3vw, 0.85rem);
  font-weight: 500;
  opacity: 0.92;
  letter-spacing: 0.06em;
  line-height: 1.4;
  text-transform: lowercase;
}

@media (max-width: 420px) {
  .bar-cards {
    gap: 14px;
    max-width: 100%;
  }
  .card {
    min-height: clamp(76px, 22vw, 92px);
    padding: 14px 18px;
  }
}

/* --- Transition overlay --------------------------------------------------- */

.overlay--transition {
  /* no background overlay — keep video luminance intact */
}

.intertitle {
  font-family: 'Fraunces', serif;
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.5rem, 4vw, 2.8rem);
  color: var(--sand-cream, #FFF3E0);
  text-align: center;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.6);
  margin: 0;
  max-width: 22ch;
}

/* --- DJ overlay ----------------------------------------------------------- */

.overlay--dj {
  background: linear-gradient(180deg, rgba(26, 10, 21, 0.15), rgba(26, 10, 21, 0.7));
  flex-direction: column;
  /* Anchor stack from the top so the intertitle never slides under the
     fixed quick-nav pill (which occupies ~70-80px at the very top). */
  justify-content: flex-start;
  align-items: center;
  padding-top: clamp(80px, 10vh, 110px);
}

/* Mobile-only compaction: moved to END of file (line ~1045) so that
   source-order wins over the default rules declared below. See comment
   block there for rationale. */

.dj-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.2vh, 22px);
  width: 100%;
  max-width: 720px;
  color: #fff;
  text-align: center;
  padding: clamp(16px, 3vh, 28px);
  position: relative;
  z-index: 2; /* above dj-scrim */
}

/* --- DJ lineup (polaroid placeholders) ----------------------------------
   Three cream-framed cards arranged in a row with slight alternating
   rotation, like photos pinned on a board. Photo area is a styled
   placeholder until the client drops in the real DJ images.             */
.dj-lineup {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(6px, 1.2vw, 14px);
  width: 100%;
  padding: 8px 0 4px;
}

.dj-card {
  flex: 0 0 auto;
  /* Bumped from 88–124 → 130–180 so the DJ photos dominate the section. */
  width: clamp(130px, 21vw, 180px);
  background: var(--sand-cream, #FFF3E0);
  border-radius: 8px;
  padding: 10px 10px 16px;
  /* Sunset-tinted "Polaroid drop" shadow instead of plain black. */
  box-shadow:
    0 14px 34px rgba(193, 74, 74, 0.42),
    0 6px 14px rgba(245, 166, 35, 0.18);
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Spring overshoot on transform so the tilt feels physical. */
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.35s ease;
}

/* Alternating tilt — left card leans left, right card leans right.
   Tilts persist on hover; we ADD scale + lift on top via per-card rules. */
.dj-card:nth-child(1) { transform: rotate(-5deg) translateY(4px); }
.dj-card:nth-child(2) { transform: rotate(1.5deg);     z-index: 2; }
.dj-card:nth-child(3) { transform: rotate(5deg)  translateY(2px); }

/* Hover: keep the per-child rotation, add scale 1.05 + a small lift, and
   bump the shadow so the card feels picked up off the table. */
.dj-card:nth-child(1):hover,
.dj-card:nth-child(1):focus-visible {
  transform: rotate(-5deg) translateY(-2px) scale(1.05);
  z-index: 3;
}
.dj-card:nth-child(2):hover,
.dj-card:nth-child(2):focus-visible {
  transform: rotate(1.5deg) translateY(-6px) scale(1.05);
  z-index: 4;
}
.dj-card:nth-child(3):hover,
.dj-card:nth-child(3):focus-visible {
  transform: rotate(5deg) translateY(-4px) scale(1.05);
  z-index: 3;
}
.dj-card:hover,
.dj-card:focus-visible {
  box-shadow:
    0 22px 50px rgba(193, 74, 74, 0.55),
    0 10px 22px rgba(245, 166, 35, 0.28);
  outline: none;
}

/* Active press feedback (preserves rotation, scales down). */
.dj-card:nth-child(1):active { transform: rotate(-5deg) translateY(2px) scale(0.985); }
.dj-card:nth-child(2):active { transform: rotate(1.5deg) translateY(-2px) scale(0.985); }
.dj-card:nth-child(3):active { transform: rotate(5deg)  translateY(0)    scale(0.985); }
.dj-card:active { transition-duration: 0.12s; }

.dj-card-photo {
  aspect-ratio: 3 / 4;
  border-radius: 4px;
  background:
    linear-gradient(135deg, rgba(255, 107, 138, 0.35), rgba(193, 74, 74, 0.5)),
    #2A0E1A;
  position: relative;
  overflow: hidden;
}

/* Subtle dashed "photo" hint so empty cards don't look broken. */
.dj-card-photo::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1px dashed rgba(255, 255, 255, 0.35);
  border-radius: 3px;
  pointer-events: none;
}

/* When a real image is supplied (--filled modifier), hide the dashed
   placeholder and stretch the <img> to fill the polaroid frame edge-to-
   edge with cover scaling. Aspect-ratio on the parent guarantees both
   polaroids render at identical pixel dimensions regardless of the
   intrinsic size of each source image. */
.dj-card-photo--filled {
  aspect-ratio: 3 / 4;
}
.dj-card-photo--filled::before { display: none; }
.dj-card-photo--filled img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.dj-card-name {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.72rem, 1.3vw, 0.88rem);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-deep, #1A0A15);
  text-align: center;
  margin: 0;
}

/* When the lineup carries the --pair modifier (two polaroids only), pin the
   meta line to a uniform two-line box so a single-line caption (BAND →
   "Ogni sabato") and a wrapped one (DJSET → "Ogni domenica" + "17:00 →
   22:00") produce visually equal-height cards. white-space: normal so
   the longer DJSET caption wraps instead of overflowing. */
/* Match polaroid pair heights by stretching the flex children. The default
   .dj-lineup uses align-items: center, which makes both cards size to
   their own content — so DJSET (2-line meta) and BAND (1-line meta) end
   up unequal. Stretch fixes that without overriding individual heights. */
.dj-lineup--pair {
  align-items: stretch;
}
.dj-lineup--pair .dj-card-meta {
  white-space: normal;
  font-size: clamp(0.55rem, 1vw, 0.66rem);
  line-height: 1.25;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* DJ intertitle living at the top of .dj-stack. */
.dj-intertitle {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.2rem, 3.2vw, 1.8rem);
  color: var(--sand-cream, #FFF3E0);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
  margin: 0 0 clamp(6px, 1.2vh, 14px) 0;
}

@media (max-width: 420px) {
  .dj-lineup { gap: 6px; }
  .dj-card   { width: 30vw; max-width: 150px; }
}

.dj-kicker {
  color: var(--gold-glow, #FFD166);
  font-size: 0.75rem;
  letter-spacing: 0.28em;
  margin: 0;
}

.dj-event-date {
  font-family: 'Fraunces', serif;
  font-weight: 700;
  font-size: clamp(1rem, 2.4vw, 1.3rem);
  letter-spacing: 0.03em;
  margin: 0;
  font-variant-numeric: tabular-nums;
  text-wrap: balance;
}

.dj-countdown {
  display: flex;
  gap: clamp(6px, 1.4vw, 14px);
  justify-content: center;
  width: 100%;
  max-width: clamp(280px, 60vw, 420px);
  margin-inline: auto;
}

.cd-block {
  flex: 1 1 0;             /* equal-share columns regardless of label width */
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: clamp(10px, 1.8vh, 16px) clamp(8px, 1.4vw, 14px);
  border: 1px solid var(--gold-glow, #FFD166);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 209, 102, 0.08), rgba(193, 74, 74, 0.18));
  backdrop-filter: blur(6px);
}

.cd-value {
  font-family: 'Fraunces', serif;
  font-weight: 900;
  font-size: clamp(1.6rem, 5vw, 2.4rem);
  color: var(--gold-glow, #FFD166);
  line-height: 1;
  /* Lock digit widths so the countdown doesn't shimmy as values change. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.cd-value--pulse {
  animation: pulse-glow 1s ease-in-out infinite;
}

.cd-label {
  font-family: 'Inter', sans-serif;
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}

.dj-event-card {
  width: 100%;
  max-width: clamp(280px, 60vw, 420px);
  margin-inline: auto;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 209, 102, 0.3);
  border-radius: 14px;
  padding: clamp(12px, 2vh, 20px) clamp(16px, 3vw, 28px);
  backdrop-filter: blur(10px);
  box-sizing: border-box;
}

.event-title {
  font-family: 'Fraunces', serif;
  font-weight: 700;
  font-size: clamp(1.1rem, 3vw, 1.6rem);
  margin: 0 0 4px 0;
}

.event-placeholder {
  opacity: 0.6;
  font-style: italic;
}

.event-sub {
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  margin: 0;
  color: rgba(255, 255, 255, 0.75);
}

.dj-upcoming ul {
  list-style: none;
  padding: 0;
  margin: 6px 0 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.dj-upcoming li {
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.04em;
}

.dj-footer {
  display: flex;
  gap: 18px;
  margin-top: clamp(10px, 2vh, 20px);
}

/* Liquid-glass social buttons — translucent circles with specular top
   highlight, strong backdrop blur, and a subtle cyan/white gleam. */
.social {
  color: #fff;
  opacity: 0.92;
  transition: opacity 0.2s ease,
              transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
              backdrop-filter 0.25s ease,
              box-shadow 0.3s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px rgba(0, 0, 0, 0.18),
    0 8px 20px rgba(193, 74, 74, 0.36),
    0 3px 8px rgba(245, 166, 35, 0.18);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.social::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 55%;
  background: radial-gradient(
    ellipse at 50% -20%,
    rgba(255, 255, 255, 0.35) 0%,
    rgba(255, 255, 255, 0) 70%
  );
  pointer-events: none;
  border-radius: 50%;
}

.social svg { position: relative; z-index: 1; }

.social:hover,
.social:focus-visible {
  opacity: 1;
  transform: translateY(-3px) scale(1.06);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.65),
    inset 0 -1px 1px rgba(0, 0, 0, 0.18),
    0 14px 32px rgba(193, 74, 74, 0.5),
    0 5px 12px rgba(245, 166, 35, 0.28);
  outline: none;
}

.social:active {
  transform: translateY(-1px) scale(0.96);
  transition-duration: 0.1s;
}

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

@media (max-width: 480px) {
  .cd-block {
    min-width: 54px;
    padding: 8px 6px;
  }
}

/* ============================================================================
   NEW (2026-04-20 polish pass):
   - .dj-card-meta           sottotitolo categoria (RESIDENT/GUEST/SPECIAL)
   - .cta-primary            bottone WhatsApp "Prenota" (liquid glass + sunset)
   - .venue-info             indirizzo + telefono cliccabili (Maps + tel:)
   - .beach-subclaim         micro-descrittore sotto il claim principale
   - .scroll-hint .label     micro-label "SCORRI"
   - safe-area iOS           notch / home indicator
   - touch target 44px       quick-nav icon + social
   - landscape iPhone        fallback per orientation landscape short
   - .noscript-fallback      fallback statico senza JS
   - :focus-visible          ring custom su tutti gli elementi interattivi
   ============================================================================ */

/* DJ card secondary label (sotto al nome categoria). */
.dj-card-meta {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.6rem, 1.1vw, 0.72rem);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: none;
  color: rgba(26, 10, 21, 0.65);
  text-align: center;
  margin: -4px 0 0 0;
}

/* Primary CTA (WhatsApp prenota). Più prominente delle social icons.
   Translation hook for magnetic cursor: --magx/--magy are set by JS on
   pointermove and reset on pointerleave. We compose the magnetic offset
   with the hover lift via CSS variables so the two transforms don't
   fight each other. */
.cta-primary {
  --magx: 0px;
  --magy: 0px;
  --lift: 0px;
  --press: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: clamp(12px, 2vh, 16px) clamp(20px, 4vw, 32px);
  border-radius: 999px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.85rem, 2vw, 1rem);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  text-decoration: none;
  background: linear-gradient(
    165deg,
    rgba(37, 211, 102, 0.95) 0%,   /* WhatsApp green */
    rgba(18, 140, 70, 0.95) 100%
  );
  border: 1px solid rgba(255, 255, 255, 0.28);
  /* Layered shadow: deep green for "weight" + sunset orange for ambient
     context (so the green button doesn't look pasted on top of a warm
     scene). */
  box-shadow:
    inset 0 1px 1.2px rgba(255, 255, 255, 0.5),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 12px 30px rgba(18, 140, 70, 0.45),
    0 4px 12px rgba(245, 166, 35, 0.22);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transform: translate3d(var(--magx), calc(var(--magy) + var(--lift)), 0) scale(var(--press));
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.3s ease;
  margin-top: clamp(8px, 1.5vh, 14px);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.cta-primary:hover,
.cta-primary:focus-visible {
  --lift: -3px;
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.65),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 18px 42px rgba(18, 140, 70, 0.55),
    0 6px 16px rgba(245, 166, 35, 0.32);
  outline: none;
}

.cta-primary:active {
  --press: 0.97;
  transition-duration: 0.12s;
}

/* Cursor-tracked highlight on the WhatsApp button — a soft white sheen
   that follows the pointer to reinforce the "tactile" feel. */
.cta-primary::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    180px circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 255, 255, 0.18) 0%,
    rgba(255, 255, 255, 0) 60%
  );
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: 1;
}

@media (hover: hover) {
  .cta-primary:hover::after { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .cta-primary::after { display: none; }
  .cta-primary {
    transform: translate3d(0, var(--lift), 0) scale(var(--press));
  }
}

/* Legal links (privacy + cookie). Lives between venue-info and the social
   footer. Visually quiet — small, low-contrast, low letter-spacing — so it
   doesn't compete with the brand block but stays reachable. */
.legal-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 6px;
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.55);
}

.legal-links__item {
  color: inherit;
  text-decoration: none;
  padding: 2px 4px;
  border-radius: 4px;
  transition: color 0.2s ease, background 0.2s ease;
}

.legal-links__item:hover,
.legal-links__item:focus-visible {
  color: rgba(255, 255, 255, 0.92);
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}

.legal-links__sep {
  opacity: 0.5;
  user-select: none;
}

/* Indirizzo + telefono: blocco informativo essenziale. */
.venue-info {
  font-style: normal;  /* <address> is italic by default */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: clamp(10px, 2vh, 18px);
  width: 100%;
  max-width: 420px;
}

.venue-info__row {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.88);
  text-decoration: none;
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.78rem, 1.6vw, 0.92rem);
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 4px 8px;
  border-radius: 6px;
  transition: color 0.2s ease, background 0.2s ease;
  text-align: center;
  line-height: 1.4;
  /* Phone numbers + addresses look better with tabular digits. */
  font-variant-numeric: tabular-nums;
}

.venue-info__row:hover,
.venue-info__row:focus-visible {
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}

.venue-info__row svg {
  flex: 0 0 auto;
  opacity: 0.85;
}

/* Micro-subclaim sotto l'H1 beach-claim. Anticipa cosa troverà l'utente. */
.beach-subclaim {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.7rem, 2vw, 0.85rem);
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #fff;
  opacity: 0.8;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
  margin: clamp(10px, 2vh, 16px) 0 0 0;
  text-align: center;
}

/* Scroll-hint label ("SCORRI") sotto l'icona swipe. */
.scroll-hint .label {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.62rem, 1.3vw, 0.72rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.78;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  line-height: 1;
}

/* ---- Safe-area iOS (notch + home indicator) ----------------------------- */
.quick-nav {
  top: max(clamp(14px, 2.5vh, 24px), env(safe-area-inset-top));
}

.scroll-hint {
  bottom: max(clamp(20px, 4vh, 48px), calc(env(safe-area-inset-bottom) + 16px));
}

.overlay--dj {
  padding-bottom: max(clamp(20px, 4vh, 40px), env(safe-area-inset-bottom));
}

/* ---- Touch target minimum 44x44 (Apple HIG + WCAG 2.5.5) --------------- */
.qn-btn--icon {
  width: clamp(44px, 9vw, 48px);
  height: clamp(44px, 9vw, 48px);
  /* Subtle always-on indicator so the icon doesn't disappear visually next
     to the MENÙ / EVENTI text buttons when the pill is idle. When a text
     button becomes .is-active the home stays readable but clearly
     non-active. */
  background: rgba(255, 255, 255, 0.08);
}

/* Bumped icon 55% → 64% so the home glyph reads clearly on 375-430px
   iPhone widths where the text buttons dominate the pill. */
.qn-btn--icon svg { width: 64%; height: 64%; }

.social {
  width: 44px;
  height: 44px;
}

/* ---- Focus-visible ring custom (WCAG 2.4.7) ---------------------------- */
.qn-btn:focus-visible,
.card:focus-visible,
.social:focus-visible,
.cta-primary:focus-visible,
.venue-info__row:focus-visible,
.dj-lineup .dj-card:focus-visible {
  outline: 2px solid var(--gold-glow, #FFD166);
  outline-offset: 3px;
}

/* ---- Landscape iPhone short-height fallback ---------------------------- */
@media (orientation: landscape) and (max-height: 500px) {
  .overlay--dj { padding-top: clamp(40px, 6vh, 60px); }
  .dj-stack    { gap: clamp(8px, 1.4vh, 14px); padding: clamp(8px, 2vh, 16px); }
  .dj-lineup   { gap: 6px; }
  .dj-card     { width: clamp(90px, 12vw, 120px); }
  .dj-countdown{ gap: 6px; }
  .cd-block    { min-width: 52px; padding: 6px 4px; }
  .cd-value    { font-size: clamp(1.1rem, 3vw, 1.6rem); }
  .beach-claim { font-size: clamp(1.4rem, 4vw, 2rem); }
  .beach-logo  { width: clamp(160px, 30vw, 240px); }
}

/* ---- Desktop short (≤900px tall) — tight packing of the DJ overlay ------
   Fix 2026-04-20: on 1080p/900p monitors the CTA "Prenota via WhatsApp" was
   pushed below the fold. Shrink vertical padding and stack gap so the whole
   section fits the viewport and the CTA stays above the fold.            */
@media (min-width: 768px) and (max-height: 900px) {
  .overlay--dj { padding-top: clamp(56px, 7vh, 84px); }
  .dj-stack    { gap: clamp(10px, 1.6vh, 18px); padding: clamp(10px, 2vh, 20px); }
  .dj-lineup   { padding: 2px 0; }
  .dj-card     { width: clamp(110px, 15vw, 150px); }
  .dj-intertitle.display { font-size: clamp(1.3rem, 2.4vw, 1.9rem); margin: 0; }
}

/* ---- Noscript fallback (se JS fallisce o è disattivato) ---------------- */
.noscript-fallback {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 40px 20px;
  background: linear-gradient(180deg, rgba(26, 10, 21, 0.72), rgba(42, 14, 26, 0.88));
  color: #fff;
  text-align: center;
  font-family: 'Inter', sans-serif;
}

.noscript-fallback h1 {
  font-family: 'Fraunces', serif;
  font-size: clamp(2rem, 6vw, 3.2rem);
  font-weight: 900;
  margin: 0;
}

.noscript-fallback p {
  font-size: clamp(0.9rem, 2vw, 1rem);
  margin: 0;
  max-width: 560px;
  line-height: 1.5;
}

.noscript-fallback a {
  color: var(--gold-glow, #FFD166);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ============================================================================
   Mobile overrides (placed LAST so source order wins over defaults above).
   ----------------------------------------------------------------------------
   Original placement was between .overlay--dj (line 500ish) and the default
   .dj-stack / .dj-card rules, which meant the defaults defined AFTER the
   media block were overriding the mobile values (same specificity → later
   rule wins). Moving the entire block here, past every default, makes the
   compaction actually apply on phones.

   Design target: DJ chapter content fits a 375×812 iPhone viewport
   (URL bar visible → ~724 usable) without needing internal scroll.
   Prior attempts with `overflow-y: auto` on the overlay trapped the scroll
   chain and a fade gradient looked like a canvas cut — avoid both.
   ============================================================================ */
@media (max-width: 767px) {
  .overlay--dj {
    /* Nav pill = env(safe-area-inset-top ~47) + ~56px height ≈ 103px.
       Padding-top = 95–115 px gives ~15-25px breathing from the nav pill. */
    padding-top: clamp(95px, 12vh, 115px);
  }
  .dj-stack {
    gap: clamp(6px, 1.2vh, 12px);
    padding: clamp(6px, 1.4vh, 12px);
    max-width: 520px;
  }
  .dj-intertitle {
    font-size: clamp(0.95rem, 4vw, 1.3rem);
    margin: 0;
  }
  .dj-lineup   { gap: 4px; padding: 0; }
  /* Shrink cards so intertitle → lineup → countdown → event → CTA →
     upcoming → venue fits one phone viewport with the footer hidden. */
  .dj-card     { width: clamp(72px, 21vw, 92px); padding: 5px 5px 8px; gap: 5px; }
  .dj-card-name{ font-size: 0.6rem; letter-spacing: 0.12em; }
  .dj-card-meta{ font-size: 0.54rem; }
  .dj-kicker   { font-size: 0.65rem; letter-spacing: 0.22em; }
  .dj-event-date { font-size: clamp(0.9rem, 3.2vw, 1.05rem); }
  .dj-event-card { padding: 8px 14px; }
  .event-title   { font-size: clamp(0.95rem, 3.6vw, 1.15rem); }
  .event-sub     { font-size: 0.78rem; }
  .dj-countdown  { gap: 6px; }
  .cd-block      { min-width: 52px; padding: 8px 4px; }
  .cd-value      { font-size: clamp(1.2rem, 5.5vw, 1.7rem); }
  .cta-primary   { margin-top: 4px; min-height: 44px; padding: 10px 20px; font-size: 0.85rem; }
  .dj-upcoming   { margin-top: 2px; }
  .dj-upcoming ul { flex-direction: row; gap: 12px; justify-content: center; flex-wrap: wrap; }
  .dj-upcoming li { font-size: 0.78rem; }
  .venue-info    { margin-top: 4px; gap: 2px; }
  .venue-info__row { font-size: 0.78rem; padding: 2px 6px; }
  /* Compact the social footer on phones rather than hiding it — IG/FB
     links are useful brand discovery points that the user explicitly
     asked to keep visible. */
  .dj-footer    { margin-top: 6px; gap: 12px; }
  .dj-footer .social { width: 36px; height: 36px; }
  .dj-footer .social svg { width: 20px; height: 20px; }
}

/* Desktop short (≤1080px tall): compact the DJ stack so intertitle →
   polaroids → countdown → 2 event cards → CTA → venue → legal → social
   footer all fit one viewport. Earlier version hid the footer entirely;
   user explicitly wants IG/FB visible, so we trim padding/gaps instead. */
@media (min-width: 768px) and (max-height: 1080px) {
  .dj-stack       { gap: clamp(8px, 1.4vh, 16px); padding: clamp(8px, 1.4vh, 16px); }
  .dj-intertitle  { font-size: clamp(1rem, 2.6vw, 1.4rem); margin: 0; }
  .dj-lineup      { padding: 0; }
  .dj-event-card  { padding: 8px clamp(16px, 3vw, 24px); }
  .event-title    { font-size: clamp(1rem, 2.4vw, 1.3rem); }
  .event-sub      { font-size: 0.8rem; }
  .cd-block       { padding: clamp(6px, 1.2vh, 10px) clamp(6px, 1vw, 12px); }
  .cd-value       { font-size: clamp(1.4rem, 3.6vw, 1.9rem); }
  .cta-primary    { min-height: 44px; padding: 10px 22px; font-size: 0.9rem; }
  .venue-info     { gap: 2px; }
  .venue-info__row { padding: 2px 6px; }
  .dj-footer      { margin-top: 6px; gap: 14px; }
  .dj-footer .social { width: 38px; height: 38px; }
  .dj-footer .social svg { width: 20px; height: 20px; }
}

/* ============================================================================
   Liquid-glass FAB stack — Floating action buttons anchored to bottom-right.

   Two buttons today: ⛱️ "Prenota il tuo ombrellone" (WhatsApp) and ⭐ "Lascia
   una recensione" (Google reviews). The stack handles positioning so each
   .fab is purely concerned with its own visual state.

   Behaviour
   ---------
   Default state: 56px circular glass disc with the icon. On :hover /
   :focus-visible / .is-expanded (set by js/umbrella-fab.js on tap), the
   disc widens into a pill, revealing the label. Click → opens the target
   URL in a new tab.

   Z-index 80 sits above page content / overlays (≤12) but below modal
   (100) and cookie banner (150), so neither is occluded by the stack.
============================================================================ */
.fab-stack {
  /* In-flow above the .beach-logo inside .beach-center — the parent flex
     column centers vertically inside the hero overlay, so the FAB pair +
     logo + claim are always treated as one block. This avoids the desktop
     bug where viewport-anchored FABs (top: 25vh) could collide with the
     vertically-centered logo on shorter monitors. */
  display: flex;
  flex-direction: row;             /* horizontal pair: ⭐ review · ⛱️ umbrella */
  gap: clamp(14px, 2vw, 22px);
  align-items: center;
  justify-content: center;
  /* Small breathing room below the FAB pair before the logo — added on
     top of the .beach-center gap so the logo doesn't feel crowded by the
     glass discs above. */
  margin-bottom: clamp(4px, 1vh, 12px);
}

/* When the beach overlay is faded out (i.e. the user has scrolled past
   the hero chapter), disable FAB clicks so they don't act as invisible
   hit targets sitting on top of the bar/DJ overlays. Opacity inheritance
   from the parent overlay already hides them visually. */
.overlay:not(.is-active) .fab {
  pointer-events: none;
}

.fab {
  /* Scaled +70% from the original 56px disc (now ~95px) so the pair reads
     as a hero-prominence CTA shelf, not a discrete bottom-right utility. */
  --fab-size: clamp(76px, 9vw, 95px);

  display: inline-flex;
  align-items: center;
  height: var(--fab-size);
  width: var(--fab-size);
  padding: 0;
  border-radius: 999px;
  overflow: hidden;

  /* Liquid glass: blurred translucent body + inset highlight + soft drop */
  background: rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(22px) saturate(180%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.30);
  box-shadow:
    0 14px 38px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.50),
    inset 0 -1px 0 rgba(0, 0, 0, 0.08);

  color: #fff;
  text-decoration: none;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: clamp(0.88rem, 1.4vw, 1.02rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  cursor: pointer;

  transition:
    background 0.3s ease,
    box-shadow 0.3s ease,
    transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.fab__icon {
  flex: 0 0 var(--fab-size);
  width: var(--fab-size);
  height: var(--fab-size);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(2rem, 4.2vw, 2.6rem);
  line-height: 1;
}

/* Umbrella icon "bobs" gently to draw the eye to the primary booking CTA.
   The review star sits still — two animated icons next to each other read
   as fidgety. */
.fab--umbrella .fab__icon {
  animation: fab-bob 4.2s ease-in-out infinite;
}

/* Labels are present in the DOM for screen readers (aria-label on the
   anchor already covers the same need, but keeping the span lets us
   re-enable expansion later without DOM changes) but hidden visually so
   both FABs read as identical liquid-glass discs at all times. */
.fab__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Light hover lift only — no width expansion. Both FABs stay the same
   size always so the pair reads as a balanced shelf. */
.fab:hover,
.fab:focus-visible {
  background: rgba(255, 255, 255, 0.26);
  box-shadow:
    0 18px 44px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.60),
    inset 0 -1px 0 rgba(0, 0, 0, 0.10);
  transform: translateY(-2px);
}

.fab:active {
  transform: translateY(0) scale(0.96);
}

.fab:focus-visible {
  outline: 2px solid var(--sunset-orange, #F5A623);
  outline-offset: 3px;
}

@keyframes fab-bob {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-2px) rotate(3deg); }
}

@media (prefers-reduced-motion: reduce) {
  .fab,
  .fab__label              { transition: none; }
  .fab--umbrella .fab__icon { animation: none; }
}

/* Mobile compaction — tighter gap between the two glass discs on phones. */
@media (max-width: 480px) {
  .fab-stack {
    gap: 10px;
  }
}
