/* ------------------------------------------------------------------
   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; }
/* FONT STACK (fixed 2026-08-03). This sheet loads AFTER the inline <style> in
   layout/header.php, so whatever body font-family is declared HERE wins the
   cascade. It still said `Inter`, but Inter is not one of the families the
   page actually loads, so every line of Latin body copy was silently falling
   back to "Noto Sans SC" and rendering in a CJK face's Latin glyphs. That is
   what read as "the font is not attractive". Keep this stack identical to
   fontFamily.sans in header.php's tailwind.config or the bug comes back. */
body { font-family: "Plus Jakarta Sans", "Noto Sans SC", system-ui, sans-serif; }

/* Metallic gold gradient text - section eyebrows & accents on dark grounds */
.text-gold-grad{
  background:linear-gradient(92deg,var(--yfx-metal-1) 0%,var(--yfx-metal-2) 30%,var(--yfx-metal-3) 52%,var(--yfx-metal-2) 74%,var(--yfx-metal-1) 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 track the live China-red ramp
   (2026-08-03) so an unset-var render never falls back to the old near-black
   maroon these used to carry. */
.bg-imperial-radial{ background:radial-gradient(120% 120% at 50% 0%,var(--grad-radial-1,var(--yfx-imperial-800)) 0%,var(--grad-radial-2,var(--yfx-imperial-900)) 45%,var(--grad-radial-3,var(--yfx-imperial-950)) 100%); }
.bg-imperial-deep{ background:radial-gradient(140% 100% at 50% -10%,var(--grad-deep-1,var(--yfx-imperial-700)) 0%,var(--grad-deep-2,var(--yfx-imperial-900)) 55%,var(--grad-deep-3,var(--yfx-imperial-950)) 100%); }

/* Decorative hairline + gold inset ring */
.hairline-gold{ height:1px; background:linear-gradient(90deg,transparent,var(--yfx-gold-500) 50%,transparent); }
.ring-gold{ box-shadow:0 0 0 1px rgb(var(--yf-gold-500) / .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%,rgb(var(--yf-gold-400) / .16) 0%,transparent 72%),
    radial-gradient(90% 90% at 30% 20%,var(--grad-nest-1,var(--yfx-imperial-700)) 0%,var(--grad-nest-2,var(--yfx-imperial-900)) 60%,var(--grad-nest-3,var(--yfx-imperial-950)) 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(var(--yfx-gold-500),var(--yfx-gold-500)); 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:var(--yfx-gold-500); 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 var(--yfx-ivory-200); }
