/* ==========================================================================
   Oh! Gift — MOTION LAYER
   --------------------------------------------------------------------------
   Everything animated lives here so it can be tuned (or deleted wholesale)
   without touching the base design in styles.css.

   Two rules govern this file:
     1. Only `transform` and `opacity` are animated. Nothing that triggers
        layout or paint on every frame.
     2. Every single effect has a calm fallback under `prefers-reduced-motion`,
        collected at the bottom of this file.

    1. Scroll progress      6. Card tilt / sheen    11. Form focus
    2. Preloader            7. Filter transitions   12. Sticky how-it-works
    3. Hero atmosphere      8. Buttons              13. Trust icon draw
    4. Split headline       9. WhatsApp float       14. Mobile menu
    5. Reveal + parallax   10. Divider shimmer      15. Image blur-up
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(.22, .8, .3, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);
}

/* ------------------------- 1. SCROLL PROGRESS BAR ----------------------- */
.scroll-progress {
  position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 300;
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand-red) 55%, var(--gold) 100%);
  transform: scaleX(0); transform-origin: 0 50%;
  will-change: transform;
  pointer-events: none;
}

/* ----------------------------- 2. PRELOADER ----------------------------- */
/* Shown immediately, then removed. The CSS animation self-dismisses even if
   JS never runs, so a script failure can never trap the visitor. */
.preloader {
  position: fixed; inset: 0; z-index: 400;
  display: grid; place-items: center;
  background: var(--cream);
  animation: preloader-out .5s var(--ease-out) 1.5s forwards;
}
.preloader.is-done { animation: preloader-out .45s var(--ease-out) forwards; }
@keyframes preloader-out {
  to { opacity: 0; visibility: hidden; transform: scale(1.015); }
}
.preloader__logo {
  width: min(230px, 56vw); position: relative;
  animation: pre-rise .8s var(--ease-out) both;
}
@keyframes pre-rise { from { opacity: 0; transform: translateY(14px); } }
/* metallic sweep travelling across the logo */
.preloader__sheen {
  position: absolute; inset: -8% -30%;
  background: linear-gradient(105deg, transparent 38%,
              rgba(255,255,255,.85) 50%, transparent 62%);
  transform: translateX(-100%);
  animation: pre-sheen 1.5s var(--ease-soft) .25s infinite;
  mix-blend-mode: overlay;
}
@keyframes pre-sheen { to { transform: translateX(100%); } }

/* --------------------------- 3. HERO ATMOSPHERE ------------------------- */
/* Slow-drifting mesh of warm blooms. Two layers on independent cycles so the
   loop never reads as a loop. Both animate transform only. */
.hero__mesh { position: absolute; inset: -25%; z-index: 0; pointer-events: none; overflow: hidden; }
.hero__mesh span {
  position: absolute; display: block; border-radius: 50%;
  filter: blur(56px); opacity: .5; will-change: transform;
}
.hero__mesh span:nth-child(1) {
  width: 46%; height: 62%; left: 4%;  top: 6%;
  background: radial-gradient(circle, rgba(216,0,0,.20), transparent 68%);
  animation: mesh-a 23s var(--ease-soft) infinite alternate;
}
.hero__mesh span:nth-child(2) {
  width: 52%; height: 58%; left: 42%; top: 24%;
  background: radial-gradient(circle, rgba(219,183,137,.34), transparent 68%);
  animation: mesh-b 29s var(--ease-soft) infinite alternate;
}
.hero__mesh span:nth-child(3) {
  width: 40%; height: 50%; left: 22%; top: 44%;
  background: radial-gradient(circle, rgba(140,17,22,.20), transparent 68%);
  animation: mesh-c 34s var(--ease-soft) infinite alternate;
}
@keyframes mesh-a { to { transform: translate3d(14%, 10%, 0) scale(1.22); } }
@keyframes mesh-b { to { transform: translate3d(-16%, 8%, 0) scale(1.16); } }
@keyframes mesh-c { to { transform: translate3d(10%, -12%, 0) scale(1.26); } }

/* tactile grain over the whole hero */
.hero__grain {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: .32; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
  animation: grain 900ms steps(4) infinite;
}
@keyframes grain {
  0%   { transform: translate3d(0,0,0); }
  25%  { transform: translate3d(-2%, 1%, 0); }
  50%  { transform: translate3d(1%, -2%, 0); }
  75%  { transform: translate3d(-1%, -1%, 0); }
}

/* drifting ribbons & sparkles behind the copy (parallax depth) */
.hero__floaters { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.hero__floaters i {
  position: absolute; display: block; opacity: 0;
  animation: float-in 1.1s var(--ease-out) forwards, drift 18s var(--ease-soft) infinite alternate;
  will-change: transform;
}
.hero__floaters i::before {
  content: ""; display: block; width: 100%; height: 100%;
  border: 1.5px solid var(--brand-light); border-radius: 50%; opacity: .5;
}
.hero__floaters i.spark::before {
  border: 0; border-radius: 0; opacity: .75;
  background: conic-gradient(from 45deg, transparent 0 42%, var(--gold) 50%, transparent 58% 100%);
}
.hero__floaters i.box::before { border-radius: 5px; transform: rotate(14deg); }
@keyframes float-in { to { opacity: 1; } }
@keyframes drift {
  to { transform: translate3d(var(--dx, 18px), var(--dy, -26px), 0) rotate(var(--dr, 12deg)); }
}

/* cursor-follow glow — desktop pointers only, switched on by JS */
.hero__spotlight {
  position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: 0;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%),
              rgba(216,0,0,.11), rgba(219,183,137,.10) 42%, transparent 72%);
  transition: opacity .45s var(--ease-soft);
}
.hero.has-spotlight .hero__spotlight { opacity: 1; }

/* hero copy sits above mesh / floaters / grain / spotlight */
.hero__inner { z-index: 5; }

/* --------------------------- 4. SPLIT HEADLINE -------------------------- */
.split-word { display: inline-block; overflow: hidden; vertical-align: bottom; }
.split-word > span {
  display: inline-block;
  transform: translateY(105%) rotate(2deg);
  opacity: 0;
}
.split-ready .split-word > span {
  animation: word-rise .82s var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 65ms + var(--base, 0ms));
}
@keyframes word-rise { to { transform: none; opacity: 1; } }

/* --------------------------- 5. REVEAL + PARALLAX ----------------------- */
/* richer than the base reveal: adds a touch of scale */
.reveal { opacity: 0; transform: translateY(26px) scale(.985); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity .75s var(--ease-out), transform .75s var(--ease-out);
}
/* background media drifts slower than the copy in front of it */
[data-parallax] { will-change: transform; }

/* --------------------------- 6. CARD TILT & SHEEN ----------------------- */
@media (hover: hover) and (pointer: fine) {
  .gift-card { transform-style: preserve-3d; }
  .gift-card.is-tilting {
    transition: transform .12s linear, box-shadow .3s ease;
    transform: perspective(900px)
               rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
               translateY(-6px) scale(1.012);
  }
  /* rose-gold glare tracking the pointer */
  .gift-card__media::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2;
    background: radial-gradient(420px circle at var(--gx, 50%) var(--gy, 50%),
                rgba(255,255,255,.42), rgba(219,183,137,.20) 34%, transparent 62%);
    opacity: 0; transition: opacity .35s var(--ease-soft);
  }
  .gift-card:hover .gift-card__media::after { opacity: 1; }

  /* price + CTA lift into view on hover */
  .gift-card__price, .gift-card__actions {
    transition: transform .42s var(--ease-out), opacity .42s var(--ease-out);
  }
  .gift-card:hover .gift-card__price   { transform: translateY(-3px); }
  .gift-card:hover .gift-card__actions { transform: translateY(-3px); }
}

/* ------------------------ 7. FILTER TRANSITIONS ------------------------- */
/* FLIP: JS measures before/after, sets --fx/--fy, then releases. */
.gift-card.flip-start {
  transform: translate3d(var(--fx, 0), var(--fy, 0), 0) scale(var(--fs, 1));
  transition: none;
}
.gift-card.flip-play {
  transform: none;
  transition: transform .58s var(--ease-out), opacity .38s var(--ease-soft);
}
.gift-card.is-leaving { opacity: 0; transform: scale(.94); transition: all .26s var(--ease-soft); }
.gift-card.is-entering { animation: card-in .5s var(--ease-out) both; }
@keyframes card-in { from { opacity: 0; transform: translateY(16px) scale(.96); } }

/* ------------------------------ 8. BUTTONS ------------------------------ */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn--primary::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(135deg, var(--brand-red) 0%, var(--brand-mid) 55%, var(--brand) 100%);
  opacity: 0; transition: opacity .4s var(--ease-soft);
}
.btn--primary:hover::before { opacity: 1; }
.btn:active { transform: translateY(1px) scale(.985); }

/* ripple */
.btn .ripple, .filter .ripple {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: rgba(255,255,255,.4); transform: scale(0); opacity: .75;
  animation: ripple .62s var(--ease-out) forwards;
}
.btn--ghost .ripple { background: rgba(122,28,39,.18); }
.filter .ripple { background: rgba(140,17,22,.14); }
.filter { position: relative; overflow: hidden; isolation: isolate; }
@keyframes ripple { to { transform: scale(2.6); opacity: 0; } }

/* magnetic pull (desktop only, applied by JS) */
@media (hover: hover) and (pointer: fine) {
  .is-magnetic { transition: transform .35s var(--ease-out); }
  .is-magnetic.is-pulling { transition: transform .12s linear; }
}

/* --------------------------- 9. WHATSAPP FLOAT -------------------------- */
.wa-float::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  border: 2px solid var(--wa-green); opacity: 0;
  animation: wa-pulse 2.8s var(--ease-soft) 1.2s infinite;
  pointer-events: none;
}
@keyframes wa-pulse {
  0%   { transform: scale(1);    opacity: .55; }
  70%  { transform: scale(1.22); opacity: 0; }
  100% { transform: scale(1.22); opacity: 0; }
}
.wa-float__tip {
  position: absolute; right: calc(100% + 12px); top: 50%;
  transform: translate(6px, -50%) scale(.96); transform-origin: right center;
  white-space: nowrap; background: var(--ink); color: var(--cream);
  font-size: .8rem; font-weight: 500; padding: .5rem .8rem; border-radius: 8px;
  opacity: 0; pointer-events: none;
  transition: opacity .3s var(--ease-out), transform .3s var(--ease-out);
  box-shadow: var(--shadow-md);
}
.wa-float:hover .wa-float__tip, .wa-float:focus-visible .wa-float__tip {
  opacity: 1; transform: translate(0, -50%) scale(1);
}
@media (max-width: 559px) { .wa-float__tip { display: none; } }

/* ------------------------- 10. DIVIDER SHIMMER -------------------------- */
.divider { position: relative; overflow: hidden; }
.divider.is-in::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.95), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.5s var(--ease-soft) .25s;
}
@keyframes shimmer { to { transform: translateX(100%); } }

/* ------------------------------ 11. FORMS ------------------------------- */
.field { position: relative; }
.field label {
  transform-origin: left center;
  transition: color .28s var(--ease-out), transform .28s var(--ease-out);
}
.field.is-focused label { color: var(--brand); transform: translateY(-2px) scale(1.02); }
/* underline that grows from the centre on focus */
.field .underline {
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--brand); border-radius: 2px;
  transform: scaleX(0); transform-origin: 50% 50%;
  transition: transform .38s var(--ease-out);
  pointer-events: none;
}
.field.is-focused .underline { transform: scaleX(1); }
.field input, .field select, .field textarea { transition: border-color .25s, box-shadow .25s, transform .25s; }
.field.is-focused input, .field.is-focused select, .field.is-focused textarea {
  transform: translateY(-1px);
}

/* ---------------------- 12. STICKY "HOW IT WORKS" ----------------------- */
.how { display: grid; gap: 2rem; }
.how__aside .how__rail { list-style: none; margin: 2rem 0 0; padding: 0; display: none; }
.how__rail li {
  display: flex; align-items: center; gap: .85rem;
  padding: .7rem 0; font-size: .95rem; color: var(--muted);
  opacity: .5; transition: opacity .4s var(--ease-out), color .4s var(--ease-out);
}
.how__rail li b {
  font-family: var(--font-serif); font-size: 1.05rem; color: var(--brand-light);
  width: 2ch; transition: color .4s var(--ease-out);
}
.how__rail li::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
  transform: scaleX(0); transform-origin: left; transition: transform .5s var(--ease-out);
}
.how__rail li.is-active { opacity: 1; color: var(--ink); }
.how__rail li.is-active b { color: var(--brand); }
.how__rail li.is-active::after { transform: scaleX(1); background: var(--brand-pale); }

.how__steps { display: grid; gap: 1.6rem; }
.step { transition: transform .5s var(--ease-out), box-shadow .5s var(--ease-out), border-color .5s; }

@media (min-width: 960px) {
  .how { grid-template-columns: .85fr 1.15fr; gap: 4rem; align-items: start; }
  .how__aside { position: sticky; top: calc(var(--header-h) + 3.5rem); }
  .how__aside .how__rail { display: block; }
  .how__steps { gap: 2.5rem; }
  /* each step gets room to own the viewport as you scroll past it */
  .how__steps .step {
    min-height: 36vh; padding: 2.6rem 2.4rem;
    display: flex; flex-direction: column; justify-content: center;
  }
  .how__steps .step.is-active {
    transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale);
  }
}

/* --------------------------- 13. TRUST ICON DRAW ------------------------ */
.trust__icon svg path, .trust__icon svg circle {
  stroke-dasharray: var(--len, 120); stroke-dashoffset: var(--len, 120);
}
.trust__item.is-in .trust__icon svg path,
.trust__item.is-in .trust__icon svg circle {
  animation: draw .9s var(--ease-out) forwards;
  animation-delay: calc(var(--d, 0) * 90ms + 180ms);
}
@keyframes draw { to { stroke-dashoffset: 0; } }

/* count-up numerals shouldn't reflow as digits change */
.stats div strong, .corp__badge strong { font-variant-numeric: tabular-nums; }

/* ---------------------------- 14. MOBILE MENU --------------------------- */
.mobile-nav li, .mobile-nav .btn { opacity: 0; transform: translateY(14px); }
.mobile-nav.is-open li, .mobile-nav.is-open .btn {
  animation: menu-in .5s var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 55ms + 80ms);
}
@keyframes menu-in { to { opacity: 1; transform: none; } }

/* --------------------------- 15. IMAGE BLUR-UP -------------------------- */
/* Images fade up from a warm blur instead of popping in. Works with whatever
   photo you drop in — there's no baked-in thumbnail to go stale. */
.gift-card__media, .corp__media, .personal__media, .about__media {
  background: linear-gradient(135deg, var(--champagne-l), var(--brand-tint));
}
img[data-blurup] {
  opacity: 0; filter: blur(14px); transform: scale(1.04);
  transition: opacity .7s var(--ease-out), filter .7s var(--ease-out), transform .7s var(--ease-out);
}
img[data-blurup].is-loaded { opacity: 1; filter: none; transform: none; }

/* ======================================================================== */
/*  REDUCED MOTION — a calm, near-static version of every effect above.     */
/*  Nothing disappears; it simply stops moving.                             */
/* ======================================================================== */
@media (prefers-reduced-motion: reduce) {
  .preloader { display: none; }
  .scroll-progress { display: none; }

  .hero__mesh span,
  .hero__grain,
  .hero__floaters i { animation: none !important; }
  .hero__floaters i { opacity: 1; }
  .hero__spotlight { display: none; }

  .split-word > span { transform: none !important; opacity: 1 !important; animation: none !important; }

  .reveal { opacity: 1; transform: none; }
  [data-parallax] { transform: none !important; }

  .gift-card.is-tilting { transform: none; }
  .gift-card__media::after { display: none; }
  .gift-card.flip-start, .gift-card.flip-play,
  .gift-card.is-entering, .gift-card.is-leaving {
    transform: none !important; opacity: 1 !important; animation: none !important; transition: none !important;
  }

  .btn .ripple { display: none; }
  .is-magnetic { transform: none !important; }

  .wa-float::after { animation: none; opacity: 0; }
  .wa-float__tip { transition: none; }

  .divider.is-in::after { animation: none; display: none; }

  .field.is-focused label { transform: none; }
  .field .underline { transition: none; }

  .how__steps .step { min-height: 0; }
  .how__rail li::after { transform: scaleX(1); }

  .trust__icon svg path, .trust__icon svg circle {
    stroke-dasharray: none; stroke-dashoffset: 0; animation: none !important;
  }

  .mobile-nav li, .mobile-nav .btn { opacity: 1; transform: none; animation: none !important; }

  img[data-blurup] { opacity: 1; filter: none; transform: none; transition: none; }
}

/* ==========================================================================
   17. INTERACTIVITY UPGRADE
   --------------------------------------------------------------------------
   Hero depth collage (cursor-parallax gift photos), Card A shine sweep,
   magnetic filter chips, hide-on-scroll header, "Oh!" shimmer.
   All decorative — the page is complete without this section.
   ========================================================================== */

/* ------------------- Hero II: depth collage ------------------ */
/* Framed gift photos that float on separate parallax depths.
   The pointer writes --mx/--my (0-100) on the hero in motion.js;
   each layer multiplies by its own --depth, so near layers move
   more than far ones. No JS? The photos still entrance — animating
   from the same offset keyframe — they just don't track the cursor. */
.hero__collage { position: absolute; inset: 0; z-index: 1; pointer-events: none; display: none; }
@media (min-width: 1100px) { .hero__collage { display: block; } }

.hero__photo {
  position: absolute; display: block; overflow: hidden;
  aspect-ratio: 4 / 5; border-radius: 14px;
  border: 5px solid var(--white);
  box-shadow: var(--shadow-lg);
  will-change: transform;
  transform:
    translate3d(calc((var(--mx, 50) - 50) * var(--depth, 6px)),
                calc((var(--my, 50) - 50) * calc(var(--depth, 6px) * .7)), 0)
    rotate(var(--rot, 0deg));
  animation: collage-in .9s var(--ease-out) both;
  animation-delay: var(--enter, .5s);
}
@keyframes collage-in {
  from { opacity: 0; transform: translate3d(48px, 34px, 0) rotate(var(--rot, 0deg)) scale(.94); }
  to   { opacity: 1; transform:
    translate3d(calc((var(--mx, 50) - 50) * var(--depth, 6px)),
                calc((var(--my, 50) - 50) * calc(var(--depth, 6px) * .7)), 0)
    rotate(var(--rot, 0deg)); }
}
.hero__photo img { width: 100%; height: 100%; object-fit: cover; }

/* three frames, staggered entrance, near-to-far depths */
.hero__photo--1 { right: 7%;  top: 9%;    width: 225px; --depth: 6px;  --rot: 3deg;  --enter: .55s; }
.hero__photo--2 { right: 25%; bottom: 5%; width: 180px; --depth: 11px; --rot: -5deg; --enter: .72s; }
.hero__photo--3 { right: 2%;  bottom: 26%; width: 138px; --depth: 16px; --rot: 6deg;  --enter: .9s; }

/* gold sparks drift deepest */
.hero__spark {
  position: absolute; width: 9px; height: 9px; border-radius: 50%;
  background: radial-gradient(circle, var(--gold) 0%, rgba(195,156,99,.55) 60%, transparent 75%);
  box-shadow: 0 0 12px rgba(195, 156, 99, .5);
  transform: translate3d(calc((var(--mx, 50) - 50) * 1.9px), calc((var(--my, 50) - 50) * 1.5px), 0);
}
.hero__spark--sm { width: 6px; height: 6px; opacity: .8; }

/* ------------------- Card A: shine sweep + underline --------- */
/* Injected by motion.js (cardSweep). Decorative only. */
.gift-card__sweep {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(105deg, transparent 38%,
              rgba(255, 244, 230, .34) 47%, rgba(255, 248, 240, .62) 50%,
              rgba(255, 244, 230, .34) 53%, transparent 62%);
  transform: translateX(-130%);
}
.gift-card:hover .gift-card__sweep,
.gift-card.is-tilting .gift-card__sweep {
  opacity: 1; transform: translateX(130%);
  transition: transform .75s cubic-bezier(.3, .6, .2, 1);
}

/* hairline brand underline draws under the gift name on hover */
.gift-card__body h3 { position: relative; width: fit-content; }
.gift-card__body h3::after {
  content: ""; position: absolute; left: 0; bottom: -5px;
  width: 100%; height: 2px; border-radius: 2px;
  background: var(--brand-grad);
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s var(--ease-out);
}
.gift-card:hover .gift-card__body h3::after { transform: scaleX(1); }

/* ------------------- "Oh!" gold shimmer ---------------------- */
.hero h1 .oh {
  background-image: linear-gradient(110deg, #D80000 0%, #C39C63 30%, #D80000 60%);
  background-size: 220% auto;
  animation: oh-shimmer 6.5s ease-in-out infinite;
}
@keyframes oh-shimmer {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

/* ------------------- Hide-on-scroll header ------------------- */
.header { transition-property: background-color, box-shadow, border-color, transform; }
.header.is-hidden { transform: translateY(-102%); }
body.nav-open .header { transform: none !important; }

/* ------------------- Reduced motion fallbacks ---------------- */
@media (prefers-reduced-motion: reduce) {
  .hero__photo { animation: none !important; opacity: 1;
    transform: rotate(var(--rot, 0deg)); }
  .hero__spark { display: none; }
  .hero h1 .oh { animation: none; background-image: var(--brand-grad); background-size: auto; }
  .gift-card__sweep { display: none; }
  .gift-card__body h3::after { transition: none; }
  .header, .header.is-hidden { transition: none; transform: none; }
}
