/* ------------------------------------------------------------------
   Yo Fu Yan Wo — custom styles that sit on top of Tailwind (CDN).
   WHY a small hand-written sheet: gradients, gold "metallic" text and
   scroll-reveal can't be expressed as Tailwind utilities cleanly. The
   brand colour tokens themselves live in the Tailwind config (header.php).
   ------------------------------------------------------------------ */

html { scroll-behavior: smooth; }
body { font-family: Inter, "Noto Sans SC", system-ui, sans-serif; }

/* Metallic gold gradient text — section eyebrows & accents on dark grounds */
.text-gold-grad{
  background:linear-gradient(92deg,#8A6A2E 0%,#C6A15B 30%,#F0E2BF 52%,#C6A15B 74%,#8A6A2E 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}

/* Festival-themed grounds (three depths reused across sections) — driven by
   CSS custom properties set per active color theme in header.php (see
   app/data/themes.php). Fallback values are the Chinese New Year palette, in
   case this stylesheet is ever loaded somewhere the vars aren't set. */
.bg-imperial-radial{ background:radial-gradient(120% 120% at 50% 0%,var(--grad-radial-1,#8B0000) 0%,var(--grad-radial-2,#5C0000) 45%,var(--grad-radial-3,#3D0000) 100%); }
.bg-imperial-deep{ background:radial-gradient(140% 100% at 50% -10%,var(--grad-deep-1,#A30000) 0%,var(--grad-deep-2,#5C0000) 55%,var(--grad-deep-3,#3D0000) 100%); }

/* Decorative hairline + gold inset ring */
.hairline-gold{ height:1px; background:linear-gradient(90deg,transparent,#C6A15B 50%,transparent); }
.ring-gold{ box-shadow:0 0 0 1px rgba(198,161,91,.5) inset; }

/* Branded product / gallery image placeholder ground (no photos yet). A soft
   second radial "spotlight" sits behind the gold line-art icon (see
   nest_placeholder() in helpers.php) so the motif reads as a deliberate
   brand moment rather than an empty box. */
.nest-ph{
  background:
    radial-gradient(38% 38% at 50% 46%,rgba(216,188,126,.16) 0%,transparent 72%),
    radial-gradient(90% 90% at 30% 20%,var(--grad-nest-1,#A30000) 0%,var(--grad-nest-2,#5C0000) 60%,var(--grad-nest-3,#3D0000) 100%);
}

/* Scroll-reveal (progressive enhancement; JS adds .in). Starts mostly
   visible (not fully hidden) so a slow script load, a heavy page, or an
   observer that hasn't fired yet never reads as a blank/broken page, only
   a subtle settle-in as content scrolls into view. */
.reveal{ opacity:.6; transform:translateY(8px); transition:opacity .5s ease, transform .5s ease; }
.reveal.in{ opacity:1; transform:none; }
/* No-JS / reduced-motion safety: never leave content invisible */
@media (prefers-reduced-motion: reduce){ .reveal{ opacity:1; transform:none; transition:none; } }
.no-js .reveal{ opacity:1; transform:none; }

/* FAQ accordion (native <details>) */
details.faq > summary{ list-style:none; cursor:pointer; }
details.faq > summary::-webkit-details-marker{ display:none; }
details.faq[open] .faq-plus{ transform:rotate(45deg); }

/* Animated gold underline for text links */
.link-underline{ background-image:linear-gradient(#C6A15B,#C6A15B); background-size:0% 1px; background-repeat:no-repeat; background-position:0 100%; transition:background-size .3s; }
.link-underline:hover{ background-size:100% 1px; }

/* "Fly to cart" add-to-cart animation (assets/js/shop.js flyToCart()) — a
   small gold dot travels from the clicked button to the header cart icon.
   Fixed + top/left set inline per-call; transform/opacity animate via this
   transition so JS only ever touches those two properties. */
.fly-to-cart-dot{
  position:fixed; z-index:60; width:14px; height:14px; border-radius:9999px;
  background:#C6A15B; box-shadow:0 2px 8px rgba(0,0,0,.25);
  pointer-events:none; opacity:1;
  transition:transform .55s cubic-bezier(.3,.1,.3,1), opacity .55s ease;
  will-change:transform, opacity;
}
@media (prefers-reduced-motion: reduce){ .fly-to-cart-dot{ display:none; } }

/* Cart badge "pop" whenever an item is added (assets/js/shop.js refreshCartCount()) */
@keyframes cartBadgePop{ 0%{ transform:scale(1); } 35%{ transform:scale(1.45); } 100%{ transform:scale(1); } }
.cart-badge-pop{ animation:cartBadgePop .4s cubic-bezier(.3,.1,.3,1); }
@media (prefers-reduced-motion: reduce){ .cart-badge-pop{ animation:none; } }

/* ============================================================
   SITE-WIDE MODAL ARCHITECTURE (2026-07-15)
   ------------------------------------------------------------
   Every modal on this site - current and future, storefront or admin -
   must be a fixed-header / scrollable-body / fixed-footer sandwich: only
   .yf-modal-body scrolls, so the title+close row and the action buttons
   are ALWAYS reachable without hunting for them, no matter how tall the
   content or how short the viewport is. This was already the pattern for
   auth_modals.php/feedback_modals.php (defined locally there); moved here
   so it's defined exactly once, on every page (via site.css, loaded
   site-wide), instead of only existing on pages that happen to also
   render the auth/feedback modals. Any new modal should reuse these
   classes rather than inventing its own scroll handling.

   Required structure:
     <div class="yf-modal-panel ...">          (flex column, capped height)
       <div class="yf-modal-header ...">...</div>   (shrink-0)
       <div class="yf-modal-body ...">...</div>     (flex:1, scrolls)
       <div class="yf-modal-footer ...">...</div>   (shrink-0, optional)
     </div>
   Panel needs its own visual classes (rounded corners, background, max-
   width) added by the caller - this only owns the scroll mechanics.
   ============================================================ */
.yf-modal-panel{ display:flex; flex-direction:column; max-height:92vh; overflow:hidden; }
.yf-modal-header{ display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-shrink:0; }
.yf-modal-body{ flex:1 1 auto; overflow-y:auto; min-height:0; }
.yf-modal-footer{ display:flex; align-items:center; justify-content:space-between; gap:.75rem; flex-shrink:0; border-top:1px solid #EAE4DA; }
