/* animations.css — motion pre-states, animated components, and micro-interactions.
   Loaded last so it can override section styles. */

/* ---------- FOUC GATE ----------
   These pre-states apply ONLY while <html class="js-anim"> is set, which happens in a
   synchronous inline script before first paint. If JavaScript is off the class is never
   added, if GSAP fails to load it is removed immediately, and if init never completes a
   watchdog removes it — so content can never be permanently stuck at opacity:0. */
html.js-anim .hero .stars,
html.js-anim .hero .skyline,
html.js-anim .hero .castle,
html.js-anim .hero .castle-glow,
html.js-anim .hero .eyebrow,
html.js-anim .hero h1 .line-inner,
html.js-anim .hero p.lead,
html.js-anim .hero-ctas .btn,
html.js-anim .hero .badge,
html.js-anim .scroll-indicator,
html.js-anim .section-head .tag,
html.js-anim .section-head h2,
html.js-anim .section-head p,
html.js-anim .value-card,
html.js-anim .dest-card,
html.js-anim .dest-rule,
html.js-anim .faq-item,
html.js-anim .news-item,
html.js-anim .test-card,
html.js-anim .about-photo,
html.js-anim .about-copy > *,
html.js-anim .sparkle-divider .line,
html.js-anim .sparkle-divider svg,
html.js-anim .quote-wrap{
  opacity:0;
}

/* Reduced motion wins over the gate no matter what, so the page is readable immediately. */
@media (prefers-reduced-motion: reduce){
  html.js-anim .hero .stars,
  html.js-anim .hero .skyline,
  html.js-anim .hero .castle,
  html.js-anim .hero .castle-glow,
  html.js-anim .hero .eyebrow,
  html.js-anim .hero h1 .line-inner,
  html.js-anim .hero p.lead,
  html.js-anim .hero-ctas .btn,
  html.js-anim .hero .badge,
  html.js-anim .scroll-indicator,
  html.js-anim .section-head .tag,
  html.js-anim .section-head h2,
  html.js-anim .section-head p,
  html.js-anim .value-card,
  html.js-anim .dest-card,
  html.js-anim .dest-rule,
  html.js-anim .faq-item,
  html.js-anim .news-item,
  html.js-anim .test-card,
  html.js-anim .about-photo,
  html.js-anim .about-copy > *,
  html.js-anim .sparkle-divider .line,
  html.js-anim .sparkle-divider svg,
  html.js-anim .quote-wrap{
    opacity:1 !important;
  }
}

/* ---------- HERO HEADLINE MASK ----------
   Each line is its own overflow-hidden window; the inner span wipes up from behind it.
   Padding/negative-margin pair keeps descenders from being clipped by the mask. */
.hero h1 .line{
  display:block;
  overflow:hidden;
  padding-bottom:.12em;
  margin-bottom:-.12em;
}
.hero h1 .line-inner{display:block;}

/* ---------- PARTICLE LAYERS ---------- */
.particle-layer{
  position:absolute;
  inset:0;
  pointer-events:none;
  overflow:hidden;
  z-index:1;
}
.sparkle{
  position:absolute;
  top:0; left:0;
  pointer-events:none;
  will-change:transform, opacity;
}

/* The rare shooting star (see particles.js initShootingStar) — a single streak, at most
   three per visit, never a running show. */
.shooting-star{
  position:absolute;
  top:0; left:0;
  width:70px; height:2px;
  border-radius:2px;
  background:linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.85));
  transform:rotate(20deg);
  pointer-events:none;
}

/* ---------- CASTLE WINDOWS ----------
   Ambient only — a slow, staggered glow, not a strobe. Neutralized automatically by the
   global prefers-reduced-motion rule in base.css (it zeros every animation-duration). */
.castle-window rect{
  fill:var(--fairy-gold-soft);
  filter:drop-shadow(0 0 3px rgba(232,185,74,.9));
  animation:window-glow 5s ease-in-out infinite;
}
.castle-window rect:nth-child(2n){ animation-delay:1.1s; }
.castle-window rect:nth-child(3n){ animation-delay:2.3s; }
@keyframes window-glow{
  0%, 100%{ opacity:.55; }
  50%{ opacity:1; }
}

/* ---------- SCROLL INDICATOR ----------
   The one intentional loop on the page: it is wayfinding, and it retires once the
   visitor has started scrolling. */
.scroll-indicator{
  position:relative;
  z-index:2;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:8px;
  padding-bottom:34px;
  color:rgba(255,255,255,.55);
  font-size:.68rem;
  letter-spacing:.22em;
  text-transform:uppercase;
  font-weight:500;
}
.scroll-arrow{color:var(--fairy-gold-soft);}

/* ---------- DESTINATIONS ---------- */
.dest-rule{
  height:1px;
  width:100%;
  max-width:1140px;
  margin:0 auto 44px;
  background:linear-gradient(90deg, transparent, var(--fairy-gold), transparent);
  transform-origin:left center;
}

.dest-grid-wrap{position:relative;}

/* The journey line sits behind the cards; its path is measured and injected at runtime. */
#journeyLine{
  position:absolute;
  top:0; left:0;
  width:100%; height:100%;
  pointer-events:none;
  z-index:0;
  overflow:visible;
}
#journeyLine path{
  fill:none;
  stroke:var(--fairy-gold);
  stroke-width:1.25;
  stroke-linecap:round;
  stroke-linejoin:round;
  opacity:0;
  /* Delicate on purpose: it should read as a route pencilled across a map, not as a rule. */
  stroke-opacity:.45;
}
#journeyLine circle{
  fill:var(--fairy-gold);
  fill-opacity:.9;
}
.dest-card{z-index:1;}

/* Per-destination personality. The motion stays identical across all six — only the
   accent changes — so each place feels distinct without becoming six different websites. */
.dest-card[data-dest="wdw"]{        --accent:#8E6BD8; }  /* castle at night */
.dest-card[data-dest="disneyland"]{ --accent:#E8B94A; }  /* classic, nostalgic gold */
.dest-card[data-dest="cruise"]{     --accent:#4FB8C9; }  /* ocean */
.dest-card[data-dest="aulani"]{     --accent:#F0A05A; }  /* tropical warmth */
.dest-card[data-dest="universal"]{  --accent:#D8629E; }  /* adventure, energy */
.dest-card[data-dest="abd"]{        --accent:#6FBF8B; }  /* exploration, worldwide */

.dest-card{
  background:linear-gradient(160deg,
    color-mix(in srgb, var(--accent, var(--amethyst)) 30%, transparent),
    rgba(31,18,53,.2));
  border-color:color-mix(in srgb, var(--accent, var(--fairy-gold)) 26%, transparent);
}
.dest-card:hover{
  border-color:var(--accent, var(--fairy-gold));
  transform:translateY(-4px);
}
.dest-card .num{color:var(--accent, var(--fairy-gold));}

/* Pointer glow — desktop only (see destinations.js). --mx/--my are written on pointermove;
   the gradient itself is CSS-only and free until the card is actually hovered. Six cards
   with no photography still get a tactile, per-destination touch out of the accent colour
   that already exists. */
.dest-card::before{
  content:'';
  position:absolute; inset:0; z-index:0;
  border-radius:inherit;
  background:radial-gradient(260px circle at var(--mx,50%) var(--my,50%),
    color-mix(in srgb, var(--accent, var(--fairy-gold)) 35%, transparent), transparent 70%);
  opacity:0;
  transition:opacity .3s ease;
  pointer-events:none;
}
.dest-card:hover::before{opacity:1;}

/* First real destination photography on the page (see docs/seo-and-motion-plan.md Section
   7.2 item 7). Only Walt Disney World has a photo so far; the other five stay on the flat
   accent-colour treatment until more photos exist — a card can carry either look without
   the section feeling inconsistent, since the accent-colour system was designed to make
   six cards feel distinct without needing six sets of imagery. */
.dest-card--photo{overflow:hidden;}
.dest-photo{position:absolute; inset:0; z-index:0;}
.dest-photo img{width:100%; height:100%; object-fit:cover; display:block;}
.dest-card--photo::after{
  content:'';
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg, rgba(31,18,53,.1) 0%, rgba(15,8,26,.5) 55%, rgba(10,5,18,.86) 100%);
  pointer-events:none;
}
.dest-card--photo .dest-content{position:relative; z-index:2;}
.dest-card--photo .num{color:var(--fairy-gold-soft);}
.dest-card--photo h3{color:var(--white);}
.dest-card--photo p{color:rgba(255,255,255,.85);}

/* ---------- ABOUT MICRO-INTERACTIONS ---------- */
.about-photo{
  transition:box-shadow .3s ease;
}
.about-photo:hover{
  box-shadow:0 24px 60px -24px rgba(75,46,131,.55);
}
/* A slow light sweep across the portrait on hover. */
.about-photo::after{
  content:'';
  position:absolute;
  inset:0;
  z-index:3;
  pointer-events:none;
  background:linear-gradient(115deg,
    transparent 35%,
    rgba(255,255,255,.22) 50%,
    transparent 65%);
  transform:translateX(-120%);
  opacity:0;
}
.about-photo.sweep::after{
  opacity:1;
  transform:translateX(120%);
  transition:transform 1.1s ease, opacity .2s ease;
}
.about-contact a svg{will-change:transform;}

/* ---------- MAGIC CTA ----------
   Positions and motion are driven by GSAP; CSS only describes appearance. */
.magic-glow-el{
  position:fixed;
  top:0; left:0;
  width:10px; height:10px;
  border-radius:50%;
  background:radial-gradient(circle,
    rgba(255,246,214,.9) 0%,
    rgba(232,185,74,.55) 35%,
    rgba(124,79,191,0) 70%);
  pointer-events:none;
  z-index:9998;
}
.magic-wish-el{
  position:fixed;
  top:0; left:0;
  pointer-events:none;
  z-index:9999;
  white-space:nowrap;
  font-family:'Parisienne',cursive;
  font-size:1.25rem;
  color:var(--fairy-gold-soft);
  text-shadow:0 2px 14px rgba(232,185,74,.55);
}

/* ---------- MOBILE NAV ----------
   `.mobile-open` was toggled by the burger but never defined, so the menu could not open. */
@media (max-width: 880px){
  nav.links.mobile-open{
    display:flex;
    flex-direction:column;
    align-items:stretch;
    gap:0;
    position:absolute;
    top:100%; left:0; right:0;
    padding:10px 28px 18px;
    background:rgba(31,18,53,.97);
    backdrop-filter:blur(8px);
    box-shadow:0 12px 28px rgba(0,0,0,.28);
  }
  nav.links.mobile-open a{
    padding:13px 0;
    border-bottom:1px solid rgba(255,255,255,.08);
  }
  nav.links.mobile-open a:last-child{border-bottom:0;}
  nav.links.mobile-open .nav-cta{
    margin-top:14px;
    text-align:center;
  }
}
