/* Slideshow display -- built for a TV across a room, so everything is large,
   high contrast, and free of anything that looks like a web page. */

:root {
  --accent: #e8b4bc;
  --bg: #08080b;
  --slide-ms: 8000ms;
  /* Ibiza sunset-over-sea: coral up top, gold at the horizon, turquoise sea
     below. Lives mainly in the chrome (title, badges, buttons, glows)
     rather than over the photos themselves -- they stay the show. */
  --ibiza-sea: #2fd9c4;
  --ibiza-gold: #ffd98a;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: #fff;
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  cursor: none;
}

body {
  background:
    radial-gradient(72% 48% at 15% -4%, color-mix(in srgb, var(--accent) 24%, transparent), transparent 62%),
    radial-gradient(50% 34% at 62% 0%, color-mix(in srgb, var(--ibiza-gold) 16%, transparent), transparent 60%),
    radial-gradient(64% 44% at 100% 100%, color-mix(in srgb, var(--ibiza-sea) 18%, transparent), transparent 66%),
    var(--bg);
}

body.show-cursor { cursor: default; }

#stage {
  position: fixed;
  inset: 0;
}

/* --- slides ------------------------------------------------------------- */

.slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1400ms ease-in-out;
  will-change: opacity;
}

.slide.visible { opacity: 1; }

/* A soft wash behind collages so the gaps between photos aren't dead black. */
.slide-wash {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 20% 15%, rgba(255,255,255,0.08), transparent 60%),
    radial-gradient(100% 70% at 78% 10%, color-mix(in srgb, var(--ibiza-gold) 20%, transparent), transparent 58%),
    radial-gradient(110% 80% at 85% 80%, color-mix(in srgb, var(--accent) 30%, transparent), transparent 65%),
    radial-gradient(90% 70% at 8% 92%, color-mix(in srgb, var(--ibiza-sea) 20%, transparent), transparent 60%),
    var(--bg);
}

.frame {
  position: absolute;
  overflow: hidden;
  border-radius: 10px;
  background: #16161c;
  box-shadow:
    0 30px 60px -12px rgba(0, 0, 0, 0.75),
    0 0 0 1px rgba(255, 255, 255, 0.06),
    0 0 46px -20px color-mix(in srgb, var(--accent) 60%, transparent);
  animation: frame-in 1200ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.frame img {
  width: 100%;
  height: 100%;
  /* contain, not cover -- the whole photo is always visible. Faces sit in
     different places in different photos, so no fixed crop bias can protect
     all of them; showing everything is the only crop that's never wrong.
     Any letterbox gap this leaves is covered by the frame's blurred
     backdrop (see buildSlide in slideshow.js) or, for polaroids, its own
     cream border. */
  object-fit: contain;
  object-position: center;
  display: block;
  position: relative;
}

/* Polaroid treatment used by the scatter layout. */
.frame.polaroid {
  background: #f6f3ee;
  padding: 1.1% 1.1% 4.2% 1.1%;
  border-radius: 4px;
}

/* The photo window inside the cream border. A real polaroid's picture
   always fills its window edge to edge, so this gets the same blurred
   backdrop as every other frame -- just scoped to sit inside the padding
   instead of under it, so the border still reads as an actual paper mat
   rather than a stray gap. */
.polaroid-window {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 2px;
}

@keyframes frame-in {
  from { opacity: 0; transform: translateY(26px) scale(0.965) rotate(var(--rot, 0deg)); }
  to   { opacity: 1; transform: translateY(0)    scale(1)     rotate(var(--rot, 0deg)); }
}

/* Full-bleed single photo. */
.frame.full {
  inset: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}

/* A blurred copy of the photo fills whatever letterbox gap contain-fit
   leaves, on any frame size -- full-bleed solo slides and collage cells
   alike. */
.backdrop {
  position: absolute;
  inset: -6%;
  background-size: cover;
  background-position: center;
  filter: blur(46px) saturate(140%) brightness(0.42);
  transform: scale(1.12);
}

/* --- Ken Burns ---------------------------------------------------------- */

.kb {
  animation-name: var(--kb, kb-in);
  animation-duration: var(--kb-ms, 9000ms);
  animation-timing-function: linear;
  animation-fill-mode: both;
}

@keyframes kb-in    { from { transform: scale(1.00) translate(0,0); }        to { transform: scale(1.13) translate(-1.2%, 0.8%); } }
@keyframes kb-out   { from { transform: scale(1.13) translate(1.0%, -0.9%); } to { transform: scale(1.00) translate(0,0); } }
@keyframes kb-left  { from { transform: scale(1.10) translate(2.4%, 0); }     to { transform: scale(1.10) translate(-2.4%, 0); } }
@keyframes kb-right { from { transform: scale(1.10) translate(-2.4%, 0); }    to { transform: scale(1.10) translate(2.4%, 0); } }
@keyframes kb-up    { from { transform: scale(1.11) translate(0, 2.2%); }     to { transform: scale(1.11) translate(0, -2.2%); } }

/* --- empty state -------------------------------------------------------- */

.empty {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background:
    radial-gradient(70% 50% at 20% 0%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 62%),
    radial-gradient(55% 40% at 80% 100%, color-mix(in srgb, var(--ibiza-sea) 16%, transparent), transparent 65%),
    var(--bg);
  z-index: 40;
}

.empty-card { text-align: center; }

.empty h1 {
  font-size: clamp(2rem, 5vw, 4rem);
  font-weight: 300;
  letter-spacing: -0.02em;
  margin: 0 0 0.4em;
}

.empty p {
  font-size: clamp(1rem, 1.8vw, 1.6rem);
  color: rgba(255, 255, 255, 0.6);
  margin: 0 0 2em;
  font-weight: 300;
}

.empty-qr {
  width: clamp(220px, 26vw, 380px);
  height: auto;
  border-radius: 16px;
  padding: 18px;
  background: #fff;
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.6),
    0 0 60px -14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.empty-url {
  margin-top: 1.4em;
  font-size: clamp(0.9rem, 1.4vw, 1.3rem);
  color: rgba(255, 255, 255, 0.45);
  font-variant-numeric: tabular-nums;
}

/* --- event title -----------------------------------------------------
   A proper banner, not a watermark -- gold-accented shimmer text with a
   pair of twinkling sparkles either side. Still restrained: no motion on
   the photos themselves, just a slow shine on the words. */

.event-title {
  position: fixed;
  left: 50%;
  top: 2.6vw;
  transform: translateX(-50%);
  z-index: 25;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 26px;
  border-radius: 999px;
  background: linear-gradient(
    100deg,
    color-mix(in srgb, var(--accent) 22%, rgba(12, 12, 16, 0.7)),
    color-mix(in srgb, var(--ibiza-sea) 16%, rgba(12, 12, 16, 0.7))
  );
  backdrop-filter: blur(14px);
  box-shadow:
    0 10px 34px rgba(0, 0, 0, 0.5),
    0 0 0 1px color-mix(in srgb, var(--ibiza-gold) 30%, rgba(255, 255, 255, 0.1)),
    0 0 40px -14px color-mix(in srgb, var(--accent) 65%, transparent);
}

.event-title-text {
  font-size: clamp(1.15rem, 2.15vw, 2.15rem);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  background: linear-gradient(
    100deg,
    #fff 0%,
    var(--accent) 30%,
    var(--ibiza-gold) 50%,
    var(--accent) 70%,
    #fff 100%
  );
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: title-shine 9s ease-in-out infinite;
}

.event-title-icon {
  flex: none;
  color: var(--ibiza-gold);
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--ibiza-gold) 70%, transparent));
  animation: title-twinkle 2.8s ease-in-out infinite;
}

.event-title-icon:last-of-type { animation-delay: 1.4s; }

@keyframes title-shine {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

@keyframes title-twinkle {
  0%, 100% { opacity: 0.5; transform: scale(0.8) rotate(0deg); }
  50% { opacity: 1; transform: scale(1.05) rotate(8deg); }
}

/* --- corner prompt ------------------------------------------------------ */

/* Sized so a phone can actually scan this off a TV from a few metres away --
   a small tasteful badge is useless if nobody can read the code. */
.corner {
  position: fixed;
  right: 2.2vw;
  bottom: 2.2vw;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 16px 24px 16px 16px;
  border-radius: 18px;
  background:
    linear-gradient(120deg, color-mix(in srgb, var(--accent) 14%, transparent), transparent 55%),
    rgba(12, 12, 16, 0.68);
  backdrop-filter: blur(14px);
  box-shadow:
    0 10px 34px rgba(0, 0, 0, 0.5),
    0 0 0 1px color-mix(in srgb, var(--accent) 28%, rgba(255, 255, 255, 0.1)),
    0 0 34px -16px color-mix(in srgb, var(--ibiza-sea) 55%, transparent);
  transition: opacity 600ms ease;
}

.corner-qr {
  width: clamp(112px, 10.5vw, 186px);
  height: auto;
  border-radius: 10px;
  background: #fff;
  padding: 9px;
  display: block;
}

.corner-text {
  display: flex;
  flex-direction: column;
  gap: 5px;
  line-height: 1.25;
}

.corner-text strong {
  font-size: clamp(1.15rem, 1.8vw, 1.8rem);
  font-weight: 600;
  letter-spacing: 0.01em;
}

.corner-text span {
  font-size: clamp(0.85rem, 1.15vw, 1.15rem);
  color: rgba(255, 255, 255, 0.55);
}

/* --- badges and toasts -------------------------------------------------- */

.badge {
  position: fixed;
  left: 2.2vw;
  bottom: 2.2vw;
  z-index: 30;
  padding: 10px 22px;
  border-radius: 999px;
  font-size: clamp(0.9rem, 1.2vw, 1.2rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #1a1013;
  background: linear-gradient(120deg, var(--accent), var(--ibiza-gold));
  box-shadow: 0 0 54px color-mix(in srgb, var(--accent) 65%, transparent);
  animation: pop 500ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes pop {
  from { opacity: 0; transform: translateY(14px) scale(0.94); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.toast {
  position: fixed;
  top: 2.2vw;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  padding: 10px 20px;
  border-radius: 10px;
  background: rgba(200, 60, 60, 0.9);
  font-size: 0.95rem;
}

/* --- tap/click controls -------------------------------------------------- */

.controls {
  position: fixed;
  left: 50%;
  bottom: 2.2vw;
  transform: translateX(-50%);
  z-index: 35;
  display: flex;
  gap: 6px;
  padding: 8px;
  border-radius: 999px;
  background: rgba(12, 12, 16, 0.68);
  backdrop-filter: blur(14px);
  box-shadow:
    0 10px 34px rgba(0, 0, 0, 0.5),
    0 0 0 1px color-mix(in srgb, var(--accent) 26%, rgba(255, 255, 255, 0.1)),
    0 0 30px -14px color-mix(in srgb, var(--accent) 55%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease;
}

body.show-cursor .controls { opacity: 1; pointer-events: auto; }

.ctrl-btn {
  width: clamp(44px, 4.4vw, 56px);
  height: clamp(44px, 4.4vw, 56px);
  border-radius: 50%;
  border: none;
  background: transparent;
  color: rgba(255, 255, 255, 0.85);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}

.ctrl-btn:active {
  background: linear-gradient(135deg, var(--accent), var(--ibiza-gold));
  color: #1a1013;
}
.ctrl-btn.off { color: rgba(255, 255, 255, 0.35); }

.hidden { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  .slide { transition-duration: 300ms; }
  .kb, .frame { animation: none !important; }
  .event-title-text, .event-title-icon { animation: none !important; }
}
