/* ==========================================================================
   DESIGN TOKENS
   ========================================================================== */
:root{
  --notte:        #0E1526;
  --carta:        #F4ECD8;
  --inchiostro:   #2A2016;
  --oro:          #C6952F;
  --oro-chiaro:   #E8C878;
  --rosso:        #9B3B3B;
  --cioccolato:   #4A2C1D;

  --font-display: 'Cormorant Garamond', serif;
  --font-body:    'EB Garamond', serif;
  --font-script:  'Petit Formal Script', cursive;
  --font-stamp:   'Special Elite', monospace;

  --radius: 3px;
  --ease: cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box;}
/* Several elements below set their own `display` (flex, etc.) at the same
   specificity as the browser's default [hidden]{display:none}, which lets
   author styles win the tie and silently defeats the `hidden` attribute.
   This restores it globally. */
[hidden]{ display:none !important; }
html,body{margin:0;padding:0;height:100%;}
body{
  font-family: var(--font-body);
  color: var(--inchiostro);
  background: var(--notte);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
button{ font-family: inherit; }

@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important; transition-duration:.001ms !important;}
}

/* ==========================================================================
   STAGE / SCENES
   ========================================================================== */
#stage{position:relative; width:100vw; height:100vh; height:100dvh;}

.scene{
  position:absolute; inset:0; z-index:1;
  opacity:0; pointer-events:none;
  transition: opacity .9s var(--ease);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding: 4vh 4vw;
  overflow-y:auto;
  background: var(--notte);
}
.scene.is-active{opacity:1; pointer-events:auto;}
.scene-illustration{ background: var(--notte); }
.scene-finale{ background: #0A0705; }

/* ==========================================================================
   FLAT MAP (replaces the old WebGL globe entirely)
   ========================================================================== */
.map-frame{
  position:relative; z-index:1;
  width: min(92vw, 178vh);
  aspect-ratio: 2;
  max-height: 66vh;
  border: 8px solid var(--carta);
  box-shadow: 0 30px 70px -20px rgba(0,0,0,.65), 0 0 0 1px rgba(198,149,47,.35);
  background: var(--notte);
  overflow: hidden;
}
.flight-overlay{ position:absolute; inset:0; width:100%; height:100%; }

.map-pin-dot{ fill: var(--oro-chiaro); }
.map-pin-label{
  text-anchor: middle; font-family: var(--font-stamp); font-size: 22px;
  fill: #F4ECD8; letter-spacing: 1px;
  paint-order: stroke; stroke: #0E1526; stroke-width: 5px;
}
.map-pin-heart .map-pin-dot{ fill: var(--rosso); }
.map-pin-pulse{
  fill: none; stroke: var(--rosso); stroke-width: 3;
  transform-origin: center; transform-box: fill-box;
  animation: mapHeartbeat 1.3s infinite;
}
@keyframes mapHeartbeat{
  0%   { transform: scale(1); opacity: .8; }
  70%  { transform: scale(3.2); opacity: 0; }
  100% { transform: scale(3.2); opacity: 0; }
}
.map-route-ghost{ fill:none; stroke: var(--oro); stroke-width: 3; stroke-dasharray: 2 12; opacity: .35; }
.map-route-trail{ fill:none; stroke: var(--oro-chiaro); stroke-width: 4; stroke-linecap: round; filter: drop-shadow(0 0 4px rgba(232,200,120,.7)); }
.map-route-final{ fill:none; stroke: var(--oro); stroke-width: 2.4; opacity: .6; }
.map-plane{ font-size: 34px; text-anchor: middle; dominant-baseline: middle; fill: #FDF6E3; filter: drop-shadow(0 0 4px rgba(0,0,0,.6)); }
.map-burst{
  fill: var(--oro-chiaro); opacity: 1;
  animation: mapBurst .8s var(--ease) forwards;
}
@keyframes mapBurst{
  to{ transform: translate(var(--bx,0px), var(--by,0px)) scale(0.3); opacity: 0; }
}

/* ==========================================================================
   LANDING (map background + gate card overlaid)
   ========================================================================== */
#scene-landing{ position:absolute; }
.map-frame-bg{ position:absolute; inset:0; margin:auto; }
.card-overlay{ position:relative; z-index:2; }

/* ==========================================================================
   FLIGHT SCENE TEXT (below the map, never overlapping it)
   ========================================================================== */
.eyebrow-floating{ position:relative; z-index:2; color: var(--oro-chiaro); margin:0 0 1rem; text-align:center; }
.flight-story{
  position:relative; z-index:2; max-width:600px; text-align:center;
  color:#D8CBA8; font-size:1.05rem; line-height:1.6; margin: 1rem 0 0;
}
.btn-continue-floating{ position:relative; z-index:2; margin-top:1.2rem; }

/* ==========================================================================
   JOURNAL / LANDING CARD
   ========================================================================== */
.journal-card{
  background: var(--carta);
  border: 1px solid rgba(42,32,22,.15);
  box-shadow: 0 30px 60px -20px rgba(0,0,0,.55);
  padding: 2.4rem 2.6rem;
  max-width: 480px;
  animation: rise .8s var(--ease) both;
}
.journal-card::before{
  content:""; position:absolute; inset:9px;
  border: 1px solid rgba(198,149,47,.35);
  pointer-events:none;
}
@keyframes rise{ from{opacity:0; transform:translateY(18px);} to{opacity:1; transform:translateY(0);} }
.card-center{ margin: 0 auto; text-align:center; position:relative; }
.card-compact{ padding: 2rem 2.2rem; }

.eyebrow{
  font-family: var(--font-stamp); font-size:.72rem; letter-spacing:.16em;
  text-transform:uppercase; color: var(--rosso); margin:0 0 .5rem;
}
.journal-card h1{ font-family: var(--font-display); margin:0 0 .7rem; }
h1.script{ font-family: var(--font-script); font-size: clamp(2.6rem, 6vw, 3.8rem); font-weight:400; color: var(--rosso); }
.lede{ color:#4a3f2e; font-size:1rem; margin:0 0 1.2rem; }

/* ==========================================================================
   POSTCARD FRAME — aspect-ratio locked so hotspot %-coords stay accurate
   ========================================================================== */
.frame-wrap{
  position:relative; z-index:2;
  width: min(94vw, 152vh);
  aspect-ratio: 1.6;
  max-height: 60vh;
}
.postcard-frame{
  position:relative; width:100%; height:100%; overflow:hidden;
  border: 10px solid var(--carta);
  border-radius:2px;
  box-shadow: 0 30px 70px -20px rgba(0,0,0,.65), 0 0 0 1px rgba(198,149,47,.4);
}
.postcard-dark{ border-color:#1B1420; }
/* Farm's photo carries more detail (couple, horses, house all at once) —
   given more room than the other illustration frames. aspect-ratio stays
   locked at the shared 1.6, so hotspot %-coords are unaffected. */
#scene-farm .frame-wrap{ width: min(97vw, 168vh); max-height: 70vh; }
.illu-svg{ position:absolute; inset:0; width:100%; height:100%; display:block; object-fit:cover; }

.hotspots{ position:absolute; inset:0; }
.hotspot{
  position:absolute; transform:translate(-50%,-50%);
  width:36px; height:36px; border-radius:50%;
  border:2px solid var(--oro-chiaro);
  background: rgba(198,149,47,.34);
  color: var(--oro-chiaro); font-size:1.05rem; line-height:1;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  /* box-shadow drives the expanding ripple, filter drives a separate
     pulsing glow — neither touches `transform`, so the hover scale-up
     below still works untouched by these two looping animations. */
  animation: tapring 1.6s infinite, hotspotGlow 1.6s ease-in-out infinite;
  transition: opacity .4s var(--ease), transform .25s var(--ease), background .25s;
  opacity:0; pointer-events:none;
}
@keyframes tapring{
  0%   { box-shadow: 0 0 0 0 rgba(232,200,120,.9); }
  70%  { box-shadow: 0 0 0 40px rgba(232,200,120,0); }
  100% { box-shadow: 0 0 0 0 rgba(232,200,120,0); }
}
@keyframes hotspotGlow{
  0%,100%{ filter: drop-shadow(0 0 6px rgba(232,200,120,.75)); }
  50%{ filter: drop-shadow(0 0 22px rgba(255,221,140,1)) drop-shadow(0 0 38px rgba(232,200,120,.65)); }
}
.hotspot.is-active{ opacity:1; }
.hotspot:hover{ transform:translate(-50%,-50%) scale(1.12); }
.hotspot.is-found{ background: var(--oro); color:#2A1E08; border-color: var(--oro); animation:none; opacity:1; }
/* All scenes' hotspots are wired up front at page load, so an inactive
   scene's hotspot can still carry pointer-events:auto from is-active/
   is-found — opacity:0 alone doesn't stop hit-testing, and a
   descendant's explicit pointer-events:auto overrides the ancestor
   .scene's pointer-events:none. Scoping it to only the active scene
   stops an off-screen scene's hotspot from ever intercepting a click
   meant for the one actually on screen. */
.scene.is-active .hotspot.is-active,
.scene.is-active .hotspot.is-found{ pointer-events:auto; }
.hotspot-heart{ color: var(--rosso); border-color: var(--rosso); background: rgba(155,59,59,.18); }
.hotspot-heart.is-found{ background: var(--rosso); color:#FBEAEA; border-color:var(--rosso); }
.hotspot-sparkle{
  position:absolute; width:6px; height:6px; border-radius:50%; background: var(--oro-chiaro);
  left:0; top:0; animation: sparkleOut .7s var(--ease) forwards;
}
@keyframes sparkleOut{
  0%{ opacity:1; transform:translate(-50%,-50%) scale(.5); }
  100%{ opacity:0; transform:translate(calc(-50% + var(--sx,0px)), calc(-50% + var(--sy,0px))) scale(1); }
}

/* ==========================================================================
   SCENE HINT + CAPTION STRIP
   ========================================================================== */
.scene-hint{
  position:relative; z-index:2; margin: .9rem 0 0; text-align:center;
  font-family: var(--font-stamp); font-size:.78rem; letter-spacing:.03em;
  color: var(--oro-chiaro);
}
.scene-hint.is-complete{ color:#8fae8f; }
.hint-count{ color:#F4ECD8; }

.caption-strip{
  position:relative; z-index:2; margin-top:.7rem;
  max-width: min(94vw,152vh);
  background: var(--carta); border-left:4px solid var(--rosso);
  padding: .8rem 1.2rem; font-size:1rem; line-height:1.5; color: var(--inchiostro);
  box-shadow: 0 12px 30px -14px rgba(0,0,0,.5);
  animation: rise .5s var(--ease) both;
}

/* ==========================================================================
   FINAL LETTER SCENE
   ========================================================================== */
.scene-letter-scene{ background: #120D1B; }
/* The card + perimeter photos are pinned to the exact center of the
   viewport (not just centered within the eyebrow/button flex stack),
   so the eyebrow and restart button are pulled out of flow too and
   pinned to the top/bottom edges instead. */
.scene-letter-scene .eyebrow-floating{
  position:absolute; top:64px; left:50%; transform:translateX(-50%);
  margin:0; z-index:3;
}
.scene-letter-scene .btn{
  position:absolute; left:50%; bottom:4vh; transform:translateX(-50%);
  z-index:3; margin:0;
}
.letter-layout{
  position:absolute; inset:0; margin:auto; z-index:2;
  width: min(94vw, 920px); height: min(74vh, 640px);
}
.letter-photos-perimeter{ position:absolute; inset:0; z-index:1; pointer-events:none; }
.letter-photos-perimeter .polaroid{
  position:absolute; box-shadow: 0 16px 34px -10px rgba(0,0,0,.65);
  animation: none; opacity: 1;
  /* Bigger than the .polaroid stack-pile default (82x96), and each one's
     aspect-ratio is set inline per-photo in animateLetterGallery() to match
     its own real shape, so nothing is cropped however tall/narrow or wide
     the source photo is. aspect-ratio here is just the pre-JS fallback. */
  width:128px; height:auto; aspect-ratio:.855; max-height:190px;
  padding:7px 7px 20px;
}
.letter-photos-perimeter .polaroid img{ object-fit:contain; }
/* .letter-card also carries .journal-card's `rise` keyframe animation,
   which animates `transform` — a running/filled CSS animation always wins
   over a plain `transform` declaration on the same element, so the
   centering translate has to be baked into its own keyframes instead of
   set statically, or .journal-card's animation silently cancels it. */
@keyframes letterRise{
  from{ opacity:0; transform:translate(-50%, calc(-50% + 18px)); }
  to{ opacity:1; transform:translate(-50%,-50%); }
}
.letter-card{
  position:absolute; left:50%; top:50%;
  animation: letterRise .8s var(--ease) both;
  width: min(90vw, 440px); z-index:5; text-align:left; padding-top:2.2rem;
}
.wax-seal{
  position:absolute; top:-22px; left:50%; transform:translateX(-50%);
  width:44px; height:44px; border-radius:50%; background: var(--rosso);
  color:#F4ECD8; display:flex; align-items:center; justify-content:center;
  font-size:1.3rem; box-shadow: 0 6px 14px rgba(0,0,0,.5), inset 0 0 0 2px rgba(255,255,255,.15);
}
.letter-textarea{
  width:100%; min-height:190px; background:transparent; border:none; resize:vertical;
  font-family: var(--font-body); font-size:1.05rem; line-height:1.65; color: var(--inchiostro);
  outline:none; padding:0;
}
.letter-textarea.is-typing{ cursor:default; resize:none; }
.letter-hint{
  font-family: var(--font-stamp); font-size:.68rem; color:#8a7a5c; margin:.6rem 0 0;
}
.letter-hint.is-typing{ opacity:0; }

/* ==========================================================================
   PHOTO FLIGHT — big centered reveal on upload, and stack-to-perimeter travel
   ========================================================================== */
.photo-reveal{
  /* Anchored near the top (not viewport-center) so the story caption
     below the illustration stays visible/readable while the photo is
     showing, instead of being covered by it. */
  position:fixed; left:50%; top:6vh; z-index:500;
  /* Sized to fit within these bounds while matching the photo's own
     aspect-ratio (set inline per-photo by revealWithFlight in main.js,
     once its natural size is known) — so tall/narrow or wide photos
     show completely instead of being cropped to a fixed portrait shape. */
  width:auto; height:auto;
  max-width:min(66vw, 440px); max-height:46vh; aspect-ratio:.855;
  opacity:0; pointer-events:none;
  background:#FBF8EF; border:1px solid rgba(0,0,0,.15);
  padding:10px 10px 30px; box-shadow: 0 40px 90px -16px rgba(0,0,0,.75);
}
.photo-reveal img{ width:100%; height:100%; object-fit:contain; display:block; }
.photo-reveal.is-flying{
  transition: transform 1.1s var(--ease), opacity .9s var(--ease) .2s, filter .4s var(--ease);
  opacity:0; filter:blur(0);
}

/* entrance variants — cycled through so consecutive reveals don't repeat.
   Only translateX(-50%) is used for horizontal centering; the vertical
   position comes from `top` above, not a translateY(-50%), since the
   anchor is the top edge now rather than viewport-center. */
.photo-reveal.fx-fade{
  transform:translateX(-50%) scale(.4) rotate(-3deg);
  transition: transform .7s var(--ease), opacity .5s var(--ease);
}
.photo-reveal.fx-fade.is-in{ opacity:1; transform:translateX(-50%) scale(1) rotate(-1.5deg); }

.photo-reveal.fx-slide{
  transform:translateX(-50%) translateY(-140%) scale(.94);
  transition: transform .8s var(--ease), opacity .6s var(--ease);
}
.photo-reveal.fx-slide.is-in{ opacity:1; transform:translateX(-50%) scale(1); }

.photo-reveal.fx-spin{
  transform:translateX(-50%) scale(.3) rotate(-32deg);
  transition: transform .8s var(--ease), opacity .5s var(--ease);
}
.photo-reveal.fx-spin.is-in{ opacity:1; transform:translateX(-50%) scale(1) rotate(0deg); }

.photo-reveal.fx-blur{
  transform:translateX(-50%) scale(1.18); filter:blur(24px);
  transition: transform .9s var(--ease), opacity .5s var(--ease), filter .9s var(--ease);
}
.photo-reveal.fx-blur.is-in{ opacity:1; transform:translateX(-50%) scale(1); filter:blur(0); }
/* Compound selector (not just .letter-photo-flying) so this outranks the
   later, equal-specificity `.polaroid{ transition: transform .2s, ... }`
   rule below — otherwise that rule silently wins the cascade and the
   left/top flight never transitions, so `transitionend` never fires and
   the photo is stuck mid-flight forever instead of landing in its slot. */
.polaroid.letter-photo-flying{
  position:fixed; z-index:500; box-shadow: 0 20px 44px -10px rgba(0,0,0,.65);
  transition: left 1s var(--ease), top 1s var(--ease), transform 1s var(--ease);
}

/* ==========================================================================
   STACKING PHOTO ALBUM (persistent, grows as the story is discovered)
   ========================================================================== */
.photo-album{
  position:fixed; left:16px; bottom:16px; z-index:38;
  display:flex; flex-direction:column; align-items:flex-start; gap:.4rem;
}
.album-label{
  font-family: var(--font-stamp); font-size:.65rem; letter-spacing:.03em;
  color:#EFE6C8; background: rgba(14,21,38,.5); padding:.25rem .6rem;
  border-radius:999px; border:1px solid rgba(198,149,47,.3); margin:0;
}
.album-stack{ position:relative; width:92px; height:104px; }
.polaroid{
  position:absolute; left:0; top:0; width:82px; height:96px;
  background:#FBF8EF; border:1px solid rgba(0,0,0,.15);
  padding:5px 5px 16px; box-shadow: 0 6px 16px -4px rgba(0,0,0,.55);
  cursor:pointer; transition: transform .2s var(--ease), box-shadow .2s;
  animation: dealIn .4s var(--ease) both;
}
.polaroid:hover{ transform: translateY(-6px) rotate(0deg) !important; z-index:999 !important; box-shadow: 0 14px 24px -6px rgba(0,0,0,.6); }
.polaroid-inner{
  width:100%; height:100%; background: rgba(198,149,47,.14);
  display:flex; align-items:center; justify-content:center;
  font-size:1.1rem; color: var(--oro);
}
.polaroid.has-photo .polaroid-inner{ background:none; }
.polaroid img{ width:100%; height:100%; object-fit:cover; display:block; }
@keyframes dealIn{ from{ opacity:0; transform: translateY(14px) scale(.85); } to{ opacity:1; } }

/* ==========================================================================
   BUTTONS
   ========================================================================== */
.btn{
  font-family: var(--font-stamp);
  font-size:.85rem; letter-spacing:.06em;
  padding: .85rem 1.6rem;
  border: 1px solid var(--inchiostro);
  background: transparent;
  color: var(--inchiostro);
  cursor:pointer;
  border-radius: var(--radius);
  transition: transform .25s var(--ease), background .25s, color .25s, box-shadow .25s;
}
.btn:hover{ transform: translateY(-2px); }
.btn:active{ transform: translateY(0); }
.btn:focus-visible{ outline: 2px solid var(--rosso); outline-offset:3px; }
.btn-gold{
  background: var(--oro); border-color: var(--oro); color: #2A1E08;
  box-shadow: 0 8px 20px -8px rgba(198,149,47,.7);
}
.btn-gold:hover{ background: var(--oro-chiaro); }

/* ==========================================================================
   PASSWORD FORM
   ========================================================================== */
.password-form{ display:flex; flex-direction:column; align-items:center; gap:.9rem; margin-top:1.2rem; }
.password-field{
  position:relative; display:flex; align-items:center;
  background:#fff; border:1px solid rgba(42,32,22,.25); border-radius: 999px;
  padding:.3rem .3rem .3rem 1rem; width: min(300px, 78vw);
}
.password-icon{ color: var(--rosso); margin-right:.5rem; font-size:1rem; }
.password-field input{
  border:none; outline:none; flex:1; font-family:var(--font-body); font-size:1rem;
  padding:.6rem .4rem; background:transparent; color:var(--inchiostro);
}
.password-field:focus-within{ border-color: var(--rosso); box-shadow: 0 0 0 3px rgba(155,59,59,.12); }
.password-hint{ font-family: var(--font-stamp); font-size:.78rem; color: var(--rosso); min-height:1.1em; margin:0; }
.password-hint.ok{ color:#3f6b3f; }
.shake{ animation: shake .5s var(--ease); }
@keyframes shake{
  10%,90%{transform:translateX(-1px);} 20%,80%{transform:translateX(2px);}
  30%,50%,70%{transform:translateX(-5px);} 40%,60%{transform:translateX(5px);}
}

/* ==========================================================================
   STAMP THREAD
   ========================================================================== */
.stamp-thread{
  position:fixed; top:18px; left:50%; transform:translateX(-50%);
  display:flex; gap:12px; z-index:40;
  padding:.5rem .9rem; background: rgba(14,21,38,.4);
  border:1px solid rgba(198,149,47,.25); border-radius:999px;
  backdrop-filter: blur(6px);
}
.stamp{
  width:30px; height:30px; border-radius:50%;
  border:1.5px solid rgba(232,200,120,.4);
  display:flex; align-items:center; justify-content:center;
  font-family: var(--font-stamp); font-size:.5rem; letter-spacing:.05em;
  color: rgba(232,200,120,.55);
  transition: all .4s var(--ease);
}
.stamp.is-visited{ border-color: var(--oro); color: var(--notte); background: var(--oro); box-shadow:0 0 10px rgba(198,149,47,.6); }
.stamp.is-current{ transform: scale(1.18); box-shadow: 0 0 0 3px rgba(198,149,47,.3); }

/* ==========================================================================
   AUDIO HUD
   ========================================================================== */
.audio-hud{
  position:fixed; right:18px; bottom:18px; z-index:40;
  display:flex; align-items:center; gap:.6rem;
  background: rgba(14,21,38,.55); border:1px solid rgba(198,149,47,.3);
  padding:.5rem .9rem; border-radius:999px; backdrop-filter: blur(6px);
}
.audio-toggle{
  width:32px; height:32px; border-radius:50%; border:1px solid var(--oro);
  background: rgba(198,149,47,.12); cursor:pointer; display:flex; align-items:center; justify-content:center;
}
.audio-bars{ display:flex; gap:2px; align-items:flex-end; height:14px; }
.audio-bars i{ width:2.5px; background: var(--oro-chiaro); display:block; animation: bar 1s ease-in-out infinite; }
.audio-bars i:nth-child(1){height:40%; animation-delay:0s;}
.audio-bars i:nth-child(2){height:100%; animation-delay:.15s;}
.audio-bars i:nth-child(3){height:65%; animation-delay:.3s;}
.audio-bars i:nth-child(4){height:85%; animation-delay:.45s;}
.audio-hud.is-paused .audio-bars i{ animation-play-state: paused; height:20% !important; }
@keyframes bar{ 0%,100%{height:30%;} 50%{height:100%;} }
.audio-label{ font-family: var(--font-stamp); font-size:.7rem; color:#EFE6C8; letter-spacing:.04em; white-space:nowrap; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 720px){
  .frame-wrap, .map-frame{ width:94vw; max-height:42vh; }
  #scene-farm .frame-wrap{ max-height:50vh; }
  .flight-story{ max-width:90vw; font-size:.95rem; }
  .stamp-thread{ gap:7px; padding:.4rem .6rem; top:8px; }
  .stamp{ width:24px; height:24px; font-size:.42rem; }
  .hotspot{ width:30px; height:30px; font-size:.9rem; }
  .caption-strip{ font-size:.9rem; padding:.7rem 1rem; }
  .photo-album{ left:8px; bottom:8px; transform:scale(.85); transform-origin:bottom left; }
  .letter-layout{ width:96vw; height:min(80vh, 560px); }
  .letter-photos-perimeter .polaroid{ width:84px; height:auto; max-height:124px; padding:4px 4px 12px; }
}
