/* Floating collage hero — pahari.vercel.app-style drifting photo gallery.
   hero-float.js scatters the conference photos (assets/img/collage/c01–c19)
   across a slowly turning 3D cloud; each card also wanders on its own, so
   the field reads as photos floating around at random. Deep navy ground,
   cool blue tint on every photo, text overlaid via .hero-float-scrim.
   Replaces the old reel collage on the home hero only — the countdown
   section further down still uses .home-hero-collage / intro.css reels. */

/* Host sections: the home hero (#main-content) plus any page hero carrying
   .hero-float-section (About, Registration, …). */
#main-content.section-hero,
.hero-float-section {
  position: relative;
  overflow: hidden;
  background-color: #041231; /* paints the frame before JS builds the cloud */
  background-image: none !important;
}

#main-content .grid-halves-section,
.hero-float-section .grid-halves-section {
  position: relative;
  z-index: 3;
}

.hero-float {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  background:
    radial-gradient(120% 95% at 18% 8%, rgba(23, 78, 196, 0.4), transparent 58%),
    radial-gradient(95% 85% at 84% 90%, rgba(3, 86, 240, 0.32), transparent 55%),
    radial-gradient(60% 55% at 55% 45%, rgba(35, 96, 220, 0.16), transparent 70%),
    linear-gradient(158deg, #082052 0%, #051540 46%, #020b26 100%);
  opacity: 0;
  transition: opacity 1.1s ease;
}

.hero-float.is-live {
  opacity: 1;
}

/* Two very soft light blobs breathing behind the photos, for depth. */
.hero-float::before,
.hero-float::after {
  content: "";
  position: absolute;
  width: 46vmax;
  height: 46vmax;
  border-radius: 50%;
  filter: blur(70px);
  pointer-events: none;
}

.hero-float::before {
  left: -12vmax;
  top: -14vmax;
  background: radial-gradient(circle, rgba(43, 108, 235, 0.34), transparent 65%);
  animation: hero-float-blob-a 26s ease-in-out infinite alternate;
}

.hero-float::after {
  right: -14vmax;
  bottom: -16vmax;
  background: radial-gradient(circle, rgba(2, 62, 180, 0.38), transparent 65%);
  animation: hero-float-blob-b 32s ease-in-out infinite alternate;
}

@keyframes hero-float-blob-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(9vmax, 7vmax, 0) scale(1.18); }
}

@keyframes hero-float-blob-b {
  from { transform: translate3d(0, 0, 0) scale(1.12); }
  to   { transform: translate3d(-8vmax, -6vmax, 0) scale(0.95); }
}

.hero-float-card {
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 0;
  overflow: hidden;
  border-radius: 5px;
  /* one light shadow — with 100+ tiles, stacked heavy shadows are the
     single biggest paint cost and visually just mud at this size */
  box-shadow: 0 6px 18px rgba(1, 7, 24, 0.35);
  will-change: transform;
  backface-visibility: hidden;
  contain: layout style paint;
}

/* Depth fade: cards stay fully opaque (translucent cards ghosted whatever
   sat behind them); distance is faded by veiling far cards toward the navy
   ground with this solid overlay, opacity driven per-frame by hero-float.js. */
.hero-float-fog {
  position: absolute;
  inset: 0;
  background: #0a1c48;
  pointer-events: none;
  /* composited — its opacity changes every frame and must not repaint the card */
  will-change: opacity;
}

.hero-float-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* slightly darker than before — compensates for dropping the multiply tint */
  filter: saturate(0.78) contrast(1.06) brightness(0.92);
}

/* The slight blue tint — a plain translucent navy film plus a faint top
   sheen. Deliberately NOT mix-blend-mode: a blend mode composites against
   whatever card happens to be underneath, so overlapping photos shift
   color and pop as they cross; normal alpha keeps every card stable. */
.hero-float-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(120, 165, 255, 0.1), rgba(120, 165, 255, 0) 40%),
    linear-gradient(200deg, rgba(23, 62, 156, 0.34), rgba(4, 16, 52, 0.48));
  pointer-events: none;
}

.hero-float-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(75% 65% at 50% 52%, rgba(2, 9, 30, 0.14), transparent 70%),
    linear-gradient(180deg, rgba(2, 9, 30, 0.58) 0%, rgba(2, 9, 30, 0.3) 42%, rgba(2, 9, 30, 0.66) 100%);
}

@media (prefers-reduced-motion: reduce) {
  .hero-float::before,
  .hero-float::after {
    animation: none;
  }
}

/* ==================== pro variant (homepage hero) ====================
   A calmer, more editorial treatment of the same helix: richer ink-navy
   ground with an axis glow behind the strands, hairline-bordered tiles
   with a single soft shadow, a staggered fade-in cascade on load, film
   grain, and a directional scrim that protects the text zones. Scoped to
   .hero-float--pro so the other pages' collages are untouched. */

.hero-float--pro {
  background:
    radial-gradient(85% 120% at 68% 26%, rgba(30, 88, 210, 0.38), transparent 58%),
    radial-gradient(130% 100% at 10% 92%, rgba(2, 44, 126, 0.34), transparent 55%),
    linear-gradient(168deg, #0a2158 0%, #051336 55%, #02081f 100%);
}

/* axis glow — a tall soft beam of light behind the helix column.
   No blur filter: the radial gradients are already soft, and a blurred
   26vmax layer costs real GPU memory every frame. */
.hero-float--pro::before {
  left: auto;
  top: -15%;
  right: 22%;
  width: 26vmax;
  height: 130%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(56, 118, 240, 0.26), rgba(56, 118, 240, 0.1) 45%, transparent 72%);
  filter: none;
}

.hero-float--pro::after {
  left: -12vmax;
  right: auto;
  bottom: -16vmax;
  background: radial-gradient(circle, rgba(2, 52, 156, 0.28), rgba(2, 52, 156, 0.1) 42%, transparent 68%);
  filter: none;
}

/* film grain — keeps the large gradient fields from banding. Plain alpha,
   no blend mode: a full-screen blended layer over animated content forces
   a re-blend of the whole hero every frame. */
.hero-float-grain {
  position: absolute;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

.hero-float--pro .hero-float-card {
  /* flat, crisp ribbon segments like the logo's — near-square corners,
     hairline edge, no shadow (also the single biggest paint saving) */
  border-radius: 2px;
  border: 1px solid rgba(175, 205, 255, 0.22);
  box-shadow: none;
  /* staggered entrance — delay set per tile by hero-float.js */
  animation: hero-float-card-in 0.9s cubic-bezier(0.22, 0.8, 0.3, 1) both;
}

@keyframes hero-float-card-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.hero-float--pro .hero-float-card img {
  filter: saturate(0.85) contrast(1.05) brightness(0.95);
}

.hero-float--pro .hero-float-card::after {
  background:
    linear-gradient(180deg, rgba(150, 185, 255, 0.14), rgba(150, 185, 255, 0) 38%),
    linear-gradient(205deg, rgba(20, 56, 148, 0.26), rgba(3, 12, 40, 0.4));
}

/* directional scrim: densest over the left text column and the very top
   and bottom edges, nearly clear where the helix lives, plus a vignette */
#main-content .hero-float-scrim {
  background:
    radial-gradient(115% 90% at 50% 42%, transparent 52%, rgba(1, 5, 18, 0.5) 100%),
    linear-gradient(102deg, rgba(2, 8, 26, 0.62) 0%, rgba(2, 8, 26, 0.34) 38%, rgba(2, 8, 26, 0.08) 64%, rgba(2, 8, 26, 0.3) 100%),
    linear-gradient(180deg, rgba(2, 8, 26, 0.5) 0%, transparent 28%, transparent 62%, rgba(2, 8, 26, 0.62) 100%);
}

@media (prefers-reduced-motion: reduce) {
  .hero-float--pro .hero-float-card {
    animation: none;
  }
}

/* ==================== masked spiral (homepage hero) ====================
   The logo mark itself, cut out of a drifting photo mosaic: logo-mask.png's
   alpha channel masks a grid of conference photos, so the helix shape is
   literally drawn in photos. hero-spiral.js builds the tiles and drives the
   mouse tilt/parallax. Shares the pro backdrop, grain and scrim. */

.hero-spiral {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  background:
    radial-gradient(85% 120% at 68% 26%, rgba(30, 88, 210, 0.38), transparent 58%),
    radial-gradient(130% 100% at 10% 92%, rgba(2, 44, 126, 0.34), transparent 55%),
    linear-gradient(168deg, #0a2158 0%, #051336 55%, #02081f 100%);
  opacity: 0;
  transition: opacity 1.1s ease;
}

.hero-spiral.is-live {
  opacity: 1;
}

/* soft beam of light directly behind the mark — tracks .hero-spiral-pos */
.hero-spiral::before {
  content: "";
  position: absolute;
  top: 16%;
  right: -9%;
  width: min(120vh, 72vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(56, 118, 240, 0.36), rgba(56, 118, 240, 0.13) 48%, transparent 72%);
  pointer-events: none;
}

/* outer positioner — owns placement so the tilt transform stays separate */
.hero-spiral-pos {
  position: absolute;
  top: 4%;
  right: -8%;
  width: min(150vh, 88vw);
  aspect-ratio: 1;
  /* big and leaning hard left, the lower half running off-screen — the
     fill inside is counter-rotated so the photos stay upright */
  transform: rotate(-60deg);
  perspective: 1200px;
}

.hero-spiral-mask {
  position: absolute;
  inset: 0;
  /* the intro backdrop's exact ground, so the fill's tint context matches */
  background: radial-gradient(120% 120% at 50% 0%, #12296b 0%, #0a1f4d 55%, #060f28 100%);
  -webkit-mask-image: url(../img/logo-mask.png);
  mask-image: url(../img/logo-mask.png);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  will-change: transform;
  animation: hero-spiral-in 1.4s cubic-bezier(0.22, 0.8, 0.3, 1) both;
}

@keyframes hero-spiral-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* parallax wrapper — oversized enough that the counter-rotated fill still
   covers the mask's corners, plus room for the mouse slide */
.hero-spiral-par {
  position: absolute;
  inset: -25%;
  will-change: transform;
}

/* the intro overlay's collage, verbatim (see .intro-collage in intro.css):
   vertical reels of 190px tiles at low opacity, alternating roll direction.
   Only the motion driver differs — a slow time loop instead of the intro's
   scroll progress. */
.hero-spiral-reels {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  gap: 2px;
  /* a notch brighter than the intro's 0.3 so the mark reads clearly here */
  opacity: 0.42;
  /* undoes the mark's -60deg lean so the photos inside stay upright */
  transform: rotate(60deg);
}

.hero-spiral-reel {
  position: relative;
  flex: 1 1 0%;
  display: flex;
  flex-direction: column;
  gap: 2px;
  will-change: transform;
  animation: hero-spiral-roll 58s ease-in-out infinite alternate;
}

@keyframes hero-spiral-roll {
  from { transform: translate3d(0, var(--roll-from, 0px), 0); }
  to { transform: translate3d(0, var(--roll-to, 0px), 0); }
}

.hero-spiral-reel img {
  width: 100%;
  height: 88px; /* keep in sync with TILE_H in hero-spiral.js */
  flex: none;
  object-fit: cover;
  display: block;
  filter: saturate(0.85) contrast(1.05);
  transform: scale(var(--tile-scale, 1));
}

@media (max-width: 900px) {
  .hero-spiral-pos {
    top: 12%;
    right: 50%;
    transform: translateX(50%) rotate(-60deg);
    width: min(115vw, 95vh);
  }

  .hero-spiral::before {
    right: 50%;
    transform: translate(50%, -50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-spiral-mask,
  .hero-spiral-reel {
    animation: none;
  }
}
