/* ==========================================================================
   Joms & Nikki 2026 — enhancement layer
   Animated entry gate, synced audio/video start, music widget, scroll progress.
   Everything here is additive: it never touches the exported page's own DOM.
   ========================================================================== */

/* --- Site typefaces, re-declared under readable names ---------------------
   Same .woff files the exported page already ships, so the gate matches the
   site exactly and costs no extra download.                                */
@font-face { font-family: "JN Display"; font-style: normal; font-weight: 400;
  src: url("../_assets/fonts/2a90c4d9a267db6b8afa3a2cdcc91ae3.woff") format("woff"); font-display: swap; }
@font-face { font-family: "JN Display"; font-style: normal; font-weight: 700;
  src: url("../_assets/fonts/00983e96235aff1cbb9ec54694208b49.woff") format("woff"); font-display: swap; }
@font-face { font-family: "JN Caps"; font-style: normal; font-weight: 400;
  src: url("../_assets/fonts/6f5eea03a3c8870185ad90dfba29cd4a.woff") format("woff"); font-display: swap; }
@font-face { font-family: "JN Caps"; font-style: normal; font-weight: 700;
  src: url("../_assets/fonts/6f5eea03a3c8870185ad90dfba29cd4a.woff") format("woff"); font-display: swap; }
@font-face { font-family: "JN Script"; font-style: normal; font-weight: 400;
  src: url("../_assets/fonts/1ab468fc2817f36ee188c45f4f2bff7b.woff") format("woff"); font-display: swap; }

:root {
  --jn-ink:        #2a1108;
  --jn-ink-deep:   #1a0a04;
  --jn-cream:      #ebdeb9;
  --jn-gold:       #d9b071;
  --jn-gold-lt:    #f4e2b4;
  --jn-ember:      #b15928;
  --jn-ease:       cubic-bezier(.22, .61, .36, 1);
  --jn-ease-out:   cubic-bezier(.16, 1, .3, 1);
}

/* ==========================================================================
   1. The gate
   ========================================================================== */

/* Locked while the gate is up; released the moment it opens. */
html.jn-locked, html.jn-locked body { overflow: hidden !important; }

.jn-gate {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--jn-ink-deep);
  /* Tap anywhere. */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  contain: strict;
}

/* Ambient video bed ------------------------------------------------------- */
.jn-gate__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.12);
  filter: saturate(.86) contrast(1.04);
  animation: jn-bed-in 2.2s var(--jn-ease-out) .15s forwards,
             jn-bed-drift 26s ease-in-out 2s infinite alternate;
}
@keyframes jn-bed-in   { to { opacity: .46; } }
@keyframes jn-bed-drift { to { transform: scale(1.2) translate3d(-1.4%, -1%, 0); } }

/* Warm veil so the type always reads over the footage. */
.jn-gate__veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 82% at 50% 42%, rgba(42,17,8,.14) 0%, rgba(26,10,4,.72) 58%, rgba(16,6,2,.94) 100%),
    linear-gradient(180deg, rgba(26,10,4,.86) 0%, rgba(26,10,4,.16) 26%, rgba(26,10,4,.28) 62%, rgba(16,6,2,.92) 100%);
}

/* Drifting embers (canvas, painted by jn-enhance.js). */
.jn-gate__embers {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  animation: jn-fade-in 3s ease 1s forwards;
}
@keyframes jn-fade-in { to { opacity: 1; } }

/* Content ----------------------------------------------------------------- */
.jn-gate__inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(20px, 5vw, 48px);
  width: min(100%, 760px);
  will-change: transform, opacity;
}

/* Every child rises in on its own beat. */
.jn-gate__inner > * {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  animation: jn-rise .95s var(--jn-ease-out) forwards;
}
@keyframes jn-rise { to { opacity: 1; transform: none; } }

.jn-gate__rule {
  width: min(320px, 62vw);
  height: 1px;
  border: 0;
  margin: 0;
  background: linear-gradient(90deg, transparent, var(--jn-gold) 22%, var(--jn-gold-lt) 50%, var(--jn-gold) 78%, transparent);
  transform-origin: center;
  animation: jn-rule .9s var(--jn-ease-out) forwards;
}
@keyframes jn-rule { from { opacity: 0; transform: scaleX(.15); } to { opacity: .85; transform: scaleX(1); } }

.jn-gate__eyebrow {
  margin: 18px 0 0;
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-size: clamp(9px, 1.5vw, 12px);
  font-weight: 700;
  letter-spacing: .42em;
  text-indent: .42em;
  text-transform: uppercase;
  color: rgba(235, 222, 185, .72);
  animation-delay: .12s;
}

.jn-gate__monogram {
  display: block;
  width: clamp(128px, 25vw, 216px);
  height: auto;
  margin: clamp(10px, 2.4vw, 22px) auto 0;
  /* The shimmer lives on ::after of the frame, not the image itself. */
  filter: drop-shadow(0 8px 30px rgba(0, 0, 0, .55));
  animation: jn-monogram 1.5s var(--jn-ease-out) .2s forwards;
}
@keyframes jn-monogram {
  from { opacity: 0; transform: translate3d(0, 24px, 0) scale(.9); }
  to   { opacity: 1; transform: none; }
}

/* Gold sweep across the monogram, on a loop. */
.jn-gate__shine {
  position: relative;
  animation-delay: .2s;
}
.jn-gate__shine::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 244, 214, .5) 48%, rgba(255, 255, 255, .78) 51%, rgba(255, 244, 214, .5) 54%, transparent 64%);
  background-size: 260% 100%;
  background-position: 190% 0;
  mix-blend-mode: screen;
  animation: jn-sweep 5.2s ease-in-out 2.1s infinite;
  border-radius: 6px;
}
@keyframes jn-sweep {
  0%        { background-position: 190% 0; opacity: 0; }
  12%       { opacity: 1; }
  46%, 100% { background-position: -90% 0; opacity: 0; }
}

.jn-gate__names {
  margin: clamp(12px, 2.6vw, 26px) 0 0;
  font-family: "JN Display", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: clamp(23px, 5.6vw, 50px);
  line-height: 1.06;
  color: var(--jn-cream);
  letter-spacing: .2em;
  text-indent: .2em;
  white-space: nowrap;
  animation: none;          /* letters animate individually */
  opacity: 1;
  transform: none;
}
.jn-gate__names span {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 26px, 0) rotate(4deg);
  animation: jn-letter .8s var(--jn-ease-out) forwards;
  animation-delay: calc(.55s + var(--i) * .045s);
  text-shadow: 0 2px 22px rgba(0, 0, 0, .5);
}
.jn-gate__names span.is-space { width: .34em; }
@keyframes jn-letter { to { opacity: 1; transform: none; } }

.jn-gate__meta {
  margin: clamp(14px, 2.4vw, 22px) 0 0;
  display: flex;
  align-items: center;
  gap: clamp(10px, 2vw, 18px);
  animation-delay: 1.15s;
}
.jn-gate__meta .jn-dash {
  width: clamp(18px, 5vw, 46px);
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(217, 176, 113, .9), transparent);
}
.jn-gate__date {
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: clamp(13px, 2.4vw, 22px);
  letter-spacing: .3em;
  text-indent: .3em;
  color: var(--jn-cream);
  white-space: nowrap;
}

.jn-gate__venue {
  margin: clamp(10px, 1.8vw, 16px) 0 0;
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-size: clamp(8.5px, 1.4vw, 12px);
  font-weight: 700;
  letter-spacing: .22em;
  text-indent: .22em;
  text-transform: uppercase;
  line-height: 2;
  color: rgba(235, 222, 185, .6);
  animation-delay: 1.28s;
}

/* Enter control ----------------------------------------------------------- */
.jn-gate__enter {
  --pad: clamp(12px, 2vw, 16px);
  margin: clamp(26px, 4.5vw, 46px) 0 0;
  display: inline-flex;
  align-items: center;
  gap: clamp(11px, 2vw, 16px);
  padding: var(--pad) clamp(20px, 3.4vw, 30px) var(--pad) var(--pad);
  font: inherit;
  color: var(--jn-cream);
  background: rgba(42, 17, 8, .42);
  border: 1px solid rgba(217, 176, 113, .42);
  border-radius: 999px;
  cursor: pointer;
  backdrop-filter: blur(9px) saturate(1.1);
  -webkit-backdrop-filter: blur(9px) saturate(1.1);
  transition: border-color .45s var(--jn-ease), background .45s var(--jn-ease),
              transform .45s var(--jn-ease), box-shadow .45s var(--jn-ease);
  animation-delay: 1.45s;
  box-shadow: 0 10px 40px rgba(0, 0, 0, .35);
}
.jn-gate__enter:hover,
.jn-gate__enter:focus-visible {
  border-color: rgba(244, 226, 180, .95);
  background: rgba(76, 34, 14, .58);
  transform: translateY(-2px);
  box-shadow: 0 16px 52px rgba(0, 0, 0, .48), 0 0 0 6px rgba(217, 176, 113, .08);
  outline: none;
}
.jn-gate__enter:active { transform: translateY(0) scale(.985); }

/* The disc wrapper carries the pulse rings, so they stay centred on the vinyl
   no matter how the button lays itself out (left-aligned on desktop, centred
   on phones). */
.jn-gate__disc {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.jn-gate__disc::before,
.jn-gate__disc::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(38px, 6.4vw, 48px);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  border: 1px solid rgba(217, 176, 113, .55);
  pointer-events: none;
  animation: jn-pulse 2.8s var(--jn-ease-out) infinite;
}
.jn-gate__disc::after { animation-delay: 1.4s; }

/* Vinyl, drawn in CSS — no extra asset, and it spins forever. */
.jn-gate__vinyl {
  position: relative;
  flex: 0 0 auto;
  width: clamp(34px, 6vw, 44px);
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, var(--jn-ember) 0 17%, #1a0a04 17.5% 21%, transparent 21.5%),
    repeating-radial-gradient(circle at 50% 50%, #241009 0 2px, #140702 2px 3.4px),
    #140702;
  box-shadow: inset 0 0 0 1px rgba(217, 176, 113, .5), 0 4px 16px rgba(0, 0, 0, .5);
  animation: jn-spin 3.6s linear infinite;
}
/* Sheen that rotates opposite the disc, so it reads as light on vinyl. */
.jn-gate__vinyl::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 18%, rgba(244, 226, 180, .26) 26%, transparent 34% 68%, rgba(244, 226, 180, .18) 76%, transparent 84%);
  animation: jn-spin 3.6s linear infinite reverse;
}
@keyframes jn-spin { to { transform: rotate(360deg); } }

@keyframes jn-pulse {
  0%        { opacity: .7;  transform: scale(.82); }
  70%, 100% { opacity: 0;   transform: scale(2.1); }
}

.jn-gate__enter-text { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.jn-gate__enter-label {
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: clamp(10px, 1.7vw, 13px);
  letter-spacing: .3em;
  text-indent: .3em;
  text-transform: uppercase;
  line-height: 1;
}
.jn-gate__enter-sub {
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-size: clamp(7.5px, 1.2vw, 9.5px);
  letter-spacing: .17em;
  text-indent: .17em;
  text-transform: uppercase;
  line-height: 1;
  color: rgba(235, 222, 185, .58);
}

/* Waiting -----------------------------------------------------------------
   Shown only when the tap lands before the page behind the gate has finished
   laying out. The disc speeds up and a light travels the border, so the pause
   reads as the site working rather than as the tap having missed. */
.jn-gate.is-waiting .jn-gate__enter {
  cursor: progress;
  border-color: rgba(244, 226, 180, .8);
}
.jn-gate.is-waiting .jn-gate__vinyl,
.jn-gate.is-waiting .jn-gate__vinyl::after { animation-duration: .9s; }
.jn-gate.is-waiting .jn-gate__disc::before,
.jn-gate.is-waiting .jn-gate__disc::after { animation-duration: 1.2s; }

.jn-gate.is-waiting .jn-gate__enter::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 999px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 40%, rgba(244, 226, 180, .5) 50%, transparent 60%);
  background-size: 220% 100%;
  animation: jn-wait-sweep 1.4s linear infinite;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  padding: 1px;
}
@keyframes jn-wait-sweep {
  from { background-position: 160% 0; }
  to   { background-position: -60% 0; }
}

/* Exit -------------------------------------------------------------------- */
/* Gold bloom that expands from the centre as the gate lets go. */
.jn-gate__bloom {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40px;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 246, 224, .95) 0%, rgba(217, 176, 113, .5) 40%, transparent 70%);
  opacity: 0;
  pointer-events: none;
  z-index: 3;
}
.jn-gate.is-opening { pointer-events: none; }
.jn-gate.is-opening .jn-gate__bloom { animation: jn-bloom 1.05s var(--jn-ease-out) forwards; }
@keyframes jn-bloom {
  0%   { opacity: .85; transform: scale(1); }
  100% { opacity: 0;   transform: scale(70); }
}
.jn-gate.is-opening .jn-gate__inner {
  animation: jn-content-out .85s var(--jn-ease) forwards;
}
@keyframes jn-content-out {
  to { opacity: 0; transform: translate3d(0, -30px, 0) scale(1.04); filter: blur(6px); }
}
.jn-gate.is-opening {
  animation: jn-gate-out 1.05s var(--jn-ease) forwards;
}
@keyframes jn-gate-out {
  0%   { opacity: 1; transform: scale(1); }
  55%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.09); visibility: hidden; }
}

/* ==========================================================================
   2. Music widget (persists after the gate opens)
   ========================================================================== */
.jn-music {
  position: fixed;
  left: clamp(12px, 2.2vw, 24px);
  bottom: clamp(12px, 2.2vw, 24px);
  z-index: 2147482000;
  display: none;                    /* shown by JS once a track is confirmed */
  align-items: center;
  gap: 10px;
  padding: 7px 15px 7px 7px;
  border-radius: 999px;
  border: 1px solid rgba(217, 176, 113, .34);
  background: rgba(26, 10, 4, .62);
  backdrop-filter: blur(12px) saturate(1.15);
  -webkit-backdrop-filter: blur(12px) saturate(1.15);
  cursor: pointer;
  color: var(--jn-cream);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .38);
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity .7s var(--jn-ease-out), transform .7s var(--jn-ease-out),
              border-color .35s var(--jn-ease), background .35s var(--jn-ease);
}
.jn-music.is-ready { display: inline-flex; }
.jn-music.is-visible { opacity: 1; transform: none; }
.jn-music:hover, .jn-music:focus-visible {
  border-color: rgba(244, 226, 180, .85);
  background: rgba(60, 26, 11, .74);
  outline: none;
}

.jn-music__disc {
  width: 28px;
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, var(--jn-ember) 0 18%, #1a0a04 18.5% 23%, transparent 23.5%),
    repeating-radial-gradient(circle at 50% 50%, #241009 0 1.6px, #140702 1.6px 2.7px),
    #140702;
  box-shadow: inset 0 0 0 1px rgba(217, 176, 113, .45);
  animation: jn-spin 3.2s linear infinite;
  animation-play-state: paused;
}
.jn-music.is-playing .jn-music__disc { animation-play-state: running; }

/* Four bars that bounce only while the track is actually playing. */
.jn-music__eq { display: flex; align-items: flex-end; gap: 2.5px; height: 14px; }
.jn-music__eq i {
  display: block;
  width: 2.5px;
  height: 4px;
  border-radius: 1px;
  background: var(--jn-gold);
  transform-origin: bottom;
}
.jn-music.is-playing .jn-music__eq i { animation: jn-eq .9s ease-in-out infinite; }
.jn-music__eq i:nth-child(2) { animation-delay: .18s; }
.jn-music__eq i:nth-child(3) { animation-delay: .36s; }
.jn-music__eq i:nth-child(4) { animation-delay: .12s; }
@keyframes jn-eq { 0%, 100% { height: 4px; } 50% { height: 14px; } }

.jn-music__label {
  font-family: "JN Caps", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: .22em;
  text-indent: .22em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ==========================================================================
   2b. Hidden YouTube player
   Invisible but genuinely rendered and full-size. A player scaled down to a
   few pixels, moved off-screen, or set to display:none gets its playback
   throttled or refused outright, so it stays in the viewport at 320x180 with
   an opacity the eye cannot pick up.
   ========================================================================== */
.jn-yt-host {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 320px;
  height: 180px;
  opacity: .0001;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  border: 0;
}
.jn-yt-host iframe { width: 100%; height: 100%; border: 0; }

/* ==========================================================================
   3. Scroll progress
   ========================================================================== */
.jn-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 2147482000;
  background: transparent;
  pointer-events: none;
  opacity: 0;
  transition: opacity .6s var(--jn-ease);
}
.jn-progress.is-visible { opacity: 1; }
.jn-progress i {
  display: block;
  height: 100%;
  width: var(--p, 0%);
  background: linear-gradient(90deg, var(--jn-ember), var(--jn-gold), var(--jn-gold-lt));
  box-shadow: 0 0 12px rgba(217, 176, 113, .65);
  transition: width .12s linear;
}

/* ==========================================================================
   4. Small screens
   ========================================================================== */
@media (max-width: 560px) {
  .jn-gate__names { letter-spacing: .13em; text-indent: .13em; }
  .jn-gate__enter { width: min(88vw, 340px); justify-content: center; }
  .jn-music__label { display: none; }
  .jn-music { padding: 7px; gap: 8px; }
}

/* Very short landscape phones: shrink the stack so the button stays on screen. */
@media (max-height: 520px) {
  .jn-gate__monogram { width: clamp(84px, 15vh, 130px); }
  .jn-gate__enter { margin-top: 16px; }
  .jn-gate__venue { display: none; }
}

/* ==========================================================================
   5. Reduced motion — keep the gate, drop the movement
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .jn-gate__video { animation: jn-bed-in .4s linear forwards; }
  .jn-gate__inner > *,
  .jn-gate__names span,
  .jn-gate__monogram,
  .jn-gate__embers { animation-duration: .4s !important; animation-delay: 0s !important; }
  .jn-gate__shine::after,
  .jn-gate__disc::before,
  .jn-gate__disc::after { animation: none; opacity: 0; }
  .jn-gate.is-waiting .jn-gate__enter::after { animation: none; opacity: .5; }
  .jn-gate__vinyl,
  .jn-gate__vinyl::after,
  .jn-music__disc { animation: none; }
  .jn-music.is-playing .jn-music__eq i { animation: none; height: 9px; }
  .jn-gate.is-opening { animation: jn-gate-out .3s linear forwards; }
  .jn-gate.is-opening .jn-gate__inner,
  .jn-gate.is-opening .jn-gate__bloom { animation-duration: .3s; }
}
