/* =========================================================
   RELIVE — four years with Elfrida
   Black ground, words in the centre, photos everywhere else.
   Type is Century Book, the same cut as the R.F.W. Moedjiono site
   (embedded in fonts/century-book.css). Only the Book weight exists,
   so font-synthesis stays off.

   Smoothness rule for this file: anything that moves only ever
   animates transform or opacity. Those run on the GPU, so phones
   keep up; blur, masks and shadow changes do not, so they're out.
   ========================================================= */

:root{
  --bg:        #000000;
  --ink:       #F4F1EA;                 /* warm white, easier on black than #FFF */
  --ink-soft:  rgba(244,241,234,.62);

  --ph-a:      #FCFCFC;                 /* placeholder photo, top-left */
  --ph-b:      #DADADA;                 /* placeholder photo, bottom-right */
  --ph-tag:    rgba(0,0,0,.38);

  --gold-ink:  #FFE1A1;

  --serif: "Century Book", Georgia, "Times New Roman", serif;
  --out:   cubic-bezier(.16,1,.3,1);
  --inout: cubic-bezier(.65,0,.35,1);
  --ease:  cubic-bezier(.5,.05,.35,1);   /* the RFW card's hover ease */
  --pop:   1.045;                         /* …and its hover zoom */
  --gutter: 20px;

  color-scheme:dark;
}

*,*::before,*::after{ box-sizing:border-box; margin:0; padding:0; }

html,body{
  height:100%;
  background:var(--bg); color:var(--ink);
  overflow:hidden;
  overscroll-behavior:none;              /* no pull-to-refresh or rubber-band bounce on phones */
}
html{ -webkit-text-size-adjust:100%; text-size-adjust:100%; }

body{
  font-family:var(--serif);
  font-weight:400;
  font-synthesis:none;
  font-kerning:normal;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  -webkit-user-select:none; user-select:none;
  -webkit-touch-callout:none;            /* no "save image" pop-up on a long press */
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;             /* taps respond instantly, no double-tap zoom */
}

button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }
button:focus-visible{ outline:1px solid var(--ink-soft); outline-offset:6px; }

#stage{ position:fixed; inset:0; overflow:hidden; cursor:pointer; }
body.is-final #stage{ cursor:default; }


/* =========================================================
   SCENES — one visible at a time; the outgoing one keeps
   .is-leaving for a moment so it can fade while the next arrives.
   ========================================================= */
.scene{
  position:absolute; inset:0;
  display:grid; place-items:center;
  padding:0 var(--gutter);
  visibility:hidden;
  pointer-events:none;
}
.scene.is-active,
.scene.is-leaving{ visibility:visible; }

.photos{ position:absolute; inset:0; pointer-events:none; }


/* ---------- words ---------- */
.copy{
  position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center;
  width:fit-content;
  max-width:var(--copy-w, min(40vw, 680px));
  text-align:center;
}
.scene.is-active .copy{ pointer-events:auto; }

.words{
  font-weight:400; letter-spacing:-.015em; text-wrap:balance;
  transition:transform .32s var(--ease);
}
.words .line{ display:block; }

.xl{ font-size:clamp(40px, min(6.6vw, 11vh), 108px); line-height:1.04; }
.lg{ font-size:clamp(30px, min(3.4vw, 6.6vh), 60px); line-height:1.1; }
.lede{
  font-size:clamp(17px, min(1.65vw, 2.9vh), 23px);
  line-height:1.55; letter-spacing:0;
  max-width:31em;
}
.lede .line + .line{ margin-top:.9em; }

/* each word rises and fades in, one after another (delays set in script.js) */
.w{
  display:inline-block;
  opacity:0; transform:translateY(.32em);
  transition:opacity 1s var(--out), transform 1.2s var(--out);
  transition-delay:calc(var(--wd, 0) * 1ms);
}
.scene.is-active .w{ opacity:1; transform:none; }
.scene.is-leaving .w{
  opacity:0; transform:translateY(-.1em);
  transition-duration:.45s; transition-delay:0ms;
}

.ch{ display:inline-block; will-change:transform; }   /* the letters of "mess", knocked askew */

.gold{ color:var(--gold-ink); text-shadow:0 0 .4em rgba(255,190,90,.45); }

/* a smaller sign-off line under the main words ("Happy 4 years") */
.words .sub{ font-size:clamp(18px, .42em, 34px); line-height:1.3; margin-top:.8em; letter-spacing:0; }


/* ---------- the Relive button (page 1) ---------- */
.relive{
  position:relative;
  font-size:clamp(28px, min(3.3vw, 6vh), 46px);
  letter-spacing:.01em;
  padding:.46em 1.9em .54em;
  margin-bottom:clamp(26px, 5vh, 54px);
  border:1px solid rgba(244,241,234,.85);
  opacity:0; transform:translateY(10px);
  transition:opacity .6s var(--out), transform .6s var(--out), background-color .45s var(--out), color .45s var(--out);
}
.scene.is-active .relive{
  opacity:1; transform:none;
  transition:opacity 1.2s var(--out) .25s, transform 1.4s var(--out) .25s, background-color .45s var(--out), color .45s var(--out);
}
/* a ring that keeps breathing out of the box — "press me" */
.relive::after{
  content:""; position:absolute; inset:-1px;
  border:1px solid var(--ink);
  opacity:0; pointer-events:none;
  animation:breathe 2.6s var(--out) infinite 1.6s;
}
@keyframes breathe{
  0%  { opacity:.6; transform:scale(1); }
  100%{ opacity:0;  transform:scale(1.12, 1.45); }
}
.relive:hover, .relive:focus-visible{ background:var(--ink); color:#000; outline:none; }


/* =========================================================
   PHOTOS — .ph is moved every frame by script.js,
   .ph-in handles arriving and leaving, .ph-pop handles hover.
   ========================================================= */
.ph{ position:absolute; left:0; top:0; }
/* only the page on screen gets GPU layers, so phones don't hold six pages' worth */
.scene.is-active .ph,
.scene.is-leaving .ph{ will-change:transform; }

.ph-in{
  position:relative; width:100%; height:100%;
  opacity:0;
  transform:translate(var(--ex, 0px), var(--ey, 0px)) rotate(var(--er, 0deg)) scale(.84);
  transition:opacity 1s var(--out), transform 1.5s var(--out);
  transition-delay:calc(var(--d, 0) * 1ms);
}
.scene.is-active .ph-in{ opacity:1; transform:none; }
.scene.is-leaving .ph-in{
  opacity:0; transform:scale(.93);
  transition-duration:.7s, .9s;
  transition-delay:0ms;
}

.ph-pop{
  position:absolute; inset:0;
  transition:transform .32s var(--ease);
}
/* the hover glow sits ready and only fades in, so nothing repaints mid-hover */
.ph-pop::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  box-shadow:0 0 24px 0 rgba(150,150,150,.28), 0 0 55px 6px rgba(150,150,150,.13);
  opacity:0;
  transition:opacity .32s var(--ease);
}

.ph-img{
  position:absolute; inset:0; overflow:hidden;
  background:linear-gradient(155deg, var(--ph-a), var(--ph-b));
  outline:1px solid transparent;          /* smooth edges when a photo is tilted */
}
.has-img .ph-img{ background:#111; }
.ph-photo{
  position:absolute; inset:0;
  display:block; width:100%; height:100%;
  object-fit:cover;
}

.ph-tag{
  position:absolute; left:9px; bottom:7px; z-index:1;
  font-style:normal; font-size:10px; letter-spacing:.16em;
  color:var(--ph-tag);
}


/* =========================================================
   HOVER — words and photos lift a touch, like the card on the
   RFW site (same zoom, same timing). Mouse only: on a phone a tap
   just moves to the next page.
   ========================================================= */
@media (hover:hover){
  .scene.is-active .words:hover{ transform:scale(var(--pop)); }

  .scene.is-active .ph{ pointer-events:auto; }
  .ph:hover{ z-index:1; }                     /* above the other photos, still under the words */
  .ph:hover .ph-pop{ transform:scale(var(--pop)); }
  .ph:hover .ph-pop::before{ opacity:1; }
}


/* ---------- 1 · intro ---------- */
.scene--intro{ --copy-w:min(44vw, 580px); }


/* ---------- 2 · mess — grey, dim, crooked ---------- */
.scene--mess{ --ph-a:#A3A3A3; --ph-b:#5E5E5E; --ph-tag:rgba(0,0,0,.45); }
.scene--mess .ph-photo{ filter:grayscale(1) brightness(.72) contrast(.95); }


/* ---------- 3 · light — sunlight pours in from both sides ---------- */
.scene--light{ --ph-a:#FFFDF7; --ph-b:#FFE6B3; --ph-tag:rgba(120,70,0,.45); }

.light{
  position:absolute; inset:0; pointer-events:none;
  opacity:0; transition:opacity .9s var(--out);
}
.scene--light.is-active .light{ opacity:1; transition-duration:2.4s; }

.glow{
  position:absolute; top:-10%; bottom:-10%; width:64vw;
  transition:transform 3.2s var(--out);
  animation:flicker 6s var(--inout) infinite alternate;
}
.glow--a{
  left:0; transform-origin:0 50%; transform:scaleX(.15);
  background:radial-gradient(ellipse 60% 64% at 0% 50%,
    rgba(255,238,196,.92) 0%, rgba(255,206,112,.62) 14%, rgba(255,172,70,.28) 38%, rgba(255,140,40,.08) 62%, transparent 82%);
}
.glow--b{
  right:0; transform-origin:100% 50%; transform:scaleX(.15);
  background:radial-gradient(ellipse 60% 64% at 100% 50%,
    rgba(255,238,196,.92) 0%, rgba(255,206,112,.62) 14%, rgba(255,172,70,.28) 38%, rgba(255,140,40,.08) 62%, transparent 82%);
  animation-delay:-3s;
}
.scene--light.is-active .glow{ transform:none; }
@keyframes flicker{ from{ opacity:.82; } to{ opacity:1; } }

/* the ray fans are small canvases placed by script.js; they only sway and shimmer */
.rays{ position:absolute; inset:0; overflow:hidden; }
.fan{
  position:absolute;
  will-change:transform, opacity;
  animation:sway 12s var(--inout) infinite alternate, shimmer 3.8s ease-in-out infinite alternate;
}
.fan + .fan{ animation-direction:alternate-reverse; animation-delay:0s, -1.9s; }
@keyframes sway{ from{ transform:rotate(-2.4deg); } to{ transform:rotate(2.4deg); } }
@keyframes shimmer{ from{ opacity:.65; } to{ opacity:1; } }

.dust{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; opacity:0; transition:opacity 1s var(--out); }
.scene--light.is-active .dust{ opacity:1; transition-duration:3s; }

/* photos in the light glow warm, and a glint slides across each now and then */
.scene--light .ph-pop::before{
  box-shadow:0 0 30px 2px rgba(255,200,110,.5), 0 0 80px 12px rgba(255,170,60,.24);
}
.scene--light .ph-pop::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  box-shadow:
    0 0 0 1px rgba(255,226,160,.7),
    0 0 34px 4px rgba(255,196,97,.42),
    0 0 110px 22px rgba(255,170,60,.2);
  will-change:opacity;
  animation:halo 4.4s var(--inout) infinite alternate;
  animation-delay:calc(var(--i, 0) * -.9s);
}
@keyframes halo{ from{ opacity:.5; } to{ opacity:1; } }
.scene--light .ph-img::after{
  content:""; position:absolute; inset:-30%; z-index:1;
  background:linear-gradient(112deg, transparent 42%, rgba(255,255,255,.95) 50%, transparent 58%);
  transform:translateX(-110%);
  will-change:transform;
  animation:glint 7s var(--inout) infinite;
  animation-delay:calc(var(--i, 0) * .7s + 1.5s);
}
@keyframes glint{ 0%{ transform:translateX(-110%); } 30%,100%{ transform:translateX(110%); } }
.scene--light .ph-photo{ filter:sepia(.22) saturate(1.1) brightness(1.06); }


/* ---------- 4 · years — columns fade into black at the top and bottom edges.
   A black gradient laid over the photos looks the same as masking them,
   but costs the GPU almost nothing. ---------- */
.scene--years{ --copy-w:min(34vw, 600px); }
.scene--years::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to bottom, #000 0%, rgba(0,0,0,0) 14%, rgba(0,0,0,0) 86%, #000 100%);
}


/* ---------- 5 · orbit ---------- */
.scene--orbit{ --copy-w:min(34vw, 600px); }


/* ---------- 6 · heart ---------- */
.scene--heart{ --copy-w:min(40vw, 640px); }
.scene--heart .xl{ font-size:clamp(34px, min(5.2vw, 8.4vh), 88px); }
.scene--heart .copy{ will-change:transform; }   /* the heartbeat (script.js) */


/* =========================================================
   PHONES & TALL SCREENS — side bands become top and bottom bands
   whenever the screen is taller than wide. script.js uses the same threshold.
   ========================================================= */
@media (max-aspect-ratio: 1/1){
  .scene{ --copy-w:calc(100vw - 2 * var(--gutter)); }
  .scene--intro{ --copy-w:calc(100vw - 48px); }

  .glow{ top:auto; bottom:auto; left:-10%; right:-10%; width:auto; height:58vh; }
  .glow--a{
    top:0; transform-origin:50% 0; transform:scaleY(.15);
    background:radial-gradient(ellipse 70% 60% at 50% 0%,
      rgba(255,238,196,.92) 0%, rgba(255,206,112,.62) 14%, rgba(255,172,70,.28) 38%, rgba(255,140,40,.08) 62%, transparent 82%);
  }
  .glow--b{
    bottom:0; transform-origin:50% 100%; transform:scaleY(.15);
    background:radial-gradient(ellipse 70% 60% at 50% 100%,
      rgba(255,238,196,.92) 0%, rgba(255,206,112,.62) 14%, rgba(255,172,70,.28) 38%, rgba(255,140,40,.08) 62%, transparent 82%);
  }

  .scene--years::after{
    background:linear-gradient(to right, #000 0%, rgba(0,0,0,0) 13%, rgba(0,0,0,0) 87%, #000 100%);
  }
}

@media (prefers-reduced-motion: reduce){
  .relive::after, .fan, .glow{ animation:none; }
}
