/* effects.css — photo-forward design utilities (Apple-Invites + film looks).
   Pure CSS, no build. Used by the event hero, gallery, and landing page.
   Techniques per research/modern-design.md + research/aesthetic-trends.md. */

/* ============ Full-bleed photo surface (the photo IS the design) ============ */
.surface {
  position: relative;
  border-radius: var(--r-surface);
  overflow: clip;
  background: var(--ink-strong);
  isolation: isolate;
}
.surface__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* Scrim derived from the per-event accent (colorthief writes --accent-photo).
   Guarantees legibility AND ties the card into one colour story. */
.surface__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to top,
      color-mix(in oklab, var(--accent-photo) 88%, var(--ink-strong)) 0%,
      color-mix(in oklab, var(--accent-photo) 55%, transparent) 30%,
      transparent 58%),
    linear-gradient(to top, color-mix(in oklab, var(--ink-strong) 55%, transparent), transparent 50%);
}
.surface__content {
  position: relative;
  z-index: 2;
  color: var(--accent-photo-ink);
}

/* ============ Glass material (kills flat buttons) ============ */
.glass {
  background: color-mix(in srgb, var(--accent-photo) 22%, rgba(255, 255, 255, 0.14));
  -webkit-backdrop-filter: blur(18px) saturate(1.6);
  backdrop-filter: blur(18px) saturate(1.6);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--r-pill);
  color: #fff;
  box-shadow: none;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: color-mix(in oklab, var(--accent-photo) 70%, black); }
}
.glass-chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4); min-height: var(--sp-10);
  font: 600 var(--fs-sm)/1 var(--font-ui);
}

/* ============ Film grain overlay (toggle with .has-grain on a root) ============ */
.has-grain { position: relative; }
.has-grain::after {
  content: ""; position: fixed; inset: 0; z-index: var(--z-toast);
  pointer-events: none; opacity: 0.06; mix-blend-mode: soft-light;
  background-size: 180px 180px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============ Film-stock colour grades (apply to a hero <img>) ============ */
.grade-portra    { filter: saturate(1.06) contrast(0.90) brightness(1.03) sepia(0.14) hue-rotate(-8deg); }
.grade-cinestill { filter: saturate(1.12) contrast(1.04) brightness(0.96) hue-rotate(8deg); }
.grade-airy      { filter: saturate(0.82) contrast(0.88) brightness(1.07); }

/* ============ Depth helpers ============ */
.elev-1 { box-shadow: var(--elev-1); }
.elev-2 { box-shadow: var(--elev-2); }
.elev-3 { box-shadow: var(--elev-3); }

/* ============ Blur-up image load ============ */
.blurup { background: var(--surface-warm); }
.blurup img { opacity: 0; transition: opacity 420ms var(--ease-out); }
.blurup img.is-loaded { opacity: 1; }

/* ============ Per-event effect layer (hero-scoped, static/lib/effects.mjs) ============
   Independent of style_mood. `none`/absent renders nothing. Confetti is a one-shot
   canvas burst (lib/confetti.mjs, already reduced-motion aware). Sparkle and
   grain-shimmer are pure CSS, capped low-opacity, and fully disabled below. */
.hero-effect { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }

.hero-effect--sparkle .sparkle {
  position: absolute;
  border-radius: 50%;
  background: #fff;
  opacity: 0;
  animation: sparkle-twinkle 3.4s ease-in-out infinite;
}
@keyframes sparkle-twinkle {
  0%, 100% { opacity: 0; transform: scale(0.5); }
  50% { opacity: 0.5; transform: scale(1); }
}

.hero-effect--grain-shimmer {
  opacity: 0.06;
  mix-blend-mode: soft-light;
  background-size: 160px 160px;
  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.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain-shift 6.4s steps(8) infinite;
}
@keyframes grain-shift {
  from { background-position: 0 0; }
  to   { background-position: 160px 160px; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-effect--sparkle .sparkle { animation: none; opacity: 0; }
  .hero-effect--grain-shimmer { animation: none; }
}

/* ============ Reveal-on-scroll (zero-JS where supported) ============ */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-up linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
  }
}
@keyframes reveal-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ============ Slot-machine wordmark (landing hero) ============ */
.slotword {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  letter-spacing: 0;
}
.slotword__ch {
  display: inline-block;
  width: 0.72em;
  min-width: 0.72em;
  line-height: 0.9;
  text-align: center;
  vertical-align: baseline;
  overflow: hidden;
  font-family: var(--slot-font, var(--font-grotesque));
  will-change: transform, font-family;
  transition: font-family 0s;
}
.slotword__ch.is-settling { transition: transform 360ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  .slotword__ch {
    transition: none;
    transform: none;
  }
}
