﻿/* =========================================================================
   ZAYNA COSMETIQUE — stylesheet (v3 — premium liquid-glass system)
   -------------------------------------------------------------------------
   Table of contents
   1.  Fonts
   2.  Design tokens (CSS variables) — EDIT COLORS / FONTS / SPACING HERE
   3.  Reset & base
   4.  Layout helpers
   5.  Buttons & form controls
   6.  Announcement bar + Marquee ticker
   7.  Header & navigation
   8.  Mobile navigation
   9.  Hero
   10. Media slot / placeholder illustrations
   11. Benefit strip
   12. Product showcase
   13. Ritual
   14. Ingredients
   15. Offers
   16. Testimonials
   17. FAQ
   18. Checkout
   19. Footer + floating WhatsApp
   20. Scroll reveal & motion
   21. Responsive
   ========================================================================= */

/* 1. Fonts loaded from index.html <head>. */

/* 2. Design tokens ------------------------------------------------------------
   Soft liquid-glass surfaces, glow accents, gentle 3D. Royal gold + warm
   ivory/espresso palette; corners are soft, borders are hairline, shadows
   are blurred (never hard/offset).
--------------------------------------------------------------------------*/
:root{
  /* ZAYNA palette: warm ivory + royal gold + espresso black (dark mode flips the mix) */
  --c-black:#170B10;
  --c-ivory:#F6EEDC;
  --c-pink:#C9962F;
  --c-blush:#EFE1C2;
  --c-berry:#6B4718;
  /* the wine accent already used by the checkout band ornaments */
  --c-wine:#6B0F2A;
  --c-rosegray:#8A7A63;
  --c-gold:#E8C468;
  --c-error:#C0524A;
  --c-white:#FBF6EA;

  /* light theme (default) */
  --bg:var(--c-ivory);
  --bg-soft:var(--c-blush);
  --text-strong:#1E1509;
  --text-body:#3D3226;
  --text-muted:#8A7A63;
  --accent:var(--c-pink);
  --accent-on:#241505;
  --glow:var(--c-gold);
  --gold:var(--c-gold);
  --ring:rgba(201,150,47,0.3);

  --surface:rgba(255,252,242,0.6);
  --surface-solid:var(--c-white);
  --border:rgba(23,11,16,0.1);

  /* always-dark editorial block (Product showcase / Checkout / Footer) */
  --inv-bg:var(--c-black);
  --inv-text:var(--c-ivory);
  --inv-muted:rgba(246,238,220,0.66);
  --inv-border:rgba(246,238,220,0.14);
  --inv-surface:rgba(255,255,255,0.055);

  --blur:22px;
  --sat:150%;

  --radius-lg:28px;
  --radius-md:18px;
  --radius-sm:12px;
  --radius-pill:999px;

  --shadow-soft:0 24px 60px -24px rgba(23,11,16,0.35);
  --shadow-soft-inv:0 24px 60px -20px rgba(0,0,0,0.6);
  --glow-pink:0 0 0 rgba(201,150,47,0);
  --glow-pink-lit:0 10px 40px -6px rgba(201,150,47,0.5);
  --glow-gold-lit:0 10px 34px -6px rgba(232,196,104,0.5);

  --font-heading:'Alexandria','Noto Kufi Arabic','Segoe UI',Tahoma,sans-serif;
  --font-body:'Tajawal','IBM Plex Sans Arabic','Segoe UI',Tahoma,sans-serif;

  --fs-hero:clamp(2.5rem, 1.5rem + 4vw, 4.6rem);
  --fs-h2:clamp(1.8rem, 1.35rem + 1.9vw, 3rem);
  --fs-h3:clamp(1.2rem, 1.05rem + 0.6vw, 1.55rem);
  --fs-lead:clamp(1.05rem, 1rem + 0.35vw, 1.2rem);
  --fs-body:1rem;
  --fs-small:0.875rem;
  --fs-micro:0.75rem;

  --space-section:clamp(64px, 8vw, 116px);
  --container-w:1240px;
  --container-pad:clamp(20px, 5vw, 64px);

  --ease:cubic-bezier(.22,.8,.32,1);
  --dur-fast:180ms;
  --dur:340ms;
  --dur-slow:600ms;

  --header-h:80px;
}

:root[data-theme="dark"]{
  --bg:var(--c-black);
  --bg-soft:#241708;
  --text-strong:var(--c-ivory);
  --text-body:rgba(246,238,220,0.85);
  --text-muted:rgba(196,178,140,0.75);
  --accent:var(--c-gold);
  --accent-on:#241505;
  --glow:var(--c-gold);
  --gold:var(--c-gold);
  --ring:rgba(232,196,104,0.32);

  --surface:rgba(255,255,255,0.055);
  --surface-solid:#241708;
  --border:rgba(246,238,220,0.12);

  --inv-bg:#0D060A;
  --inv-surface:rgba(255,255,255,0.045);

  --shadow-soft:0 24px 60px -20px rgba(0,0,0,0.6);
  --glow-pink-lit:0 10px 44px -6px rgba(232,196,104,0.4);
}


/* 3. Reset & base ---------------------------------------------------------*/
*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}
@media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto;} }
body{
  margin:0;
  background:var(--bg);
  color:var(--text-body);
  font-family:var(--font-body);
  font-size:var(--fs-body);
  line-height:1.8;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  transition:background-color var(--dur) var(--ease), color var(--dur) var(--ease);
  overflow-x:hidden;
}
img{max-width:100%;display:block;}
svg{display:block;}
a{color:inherit;text-decoration:none;}
ul{list-style:none;margin:0;padding:0;}
h1,h2,h3,h4{
  font-family:var(--font-heading);
  color:var(--text-strong);
  margin:0;
  font-weight:700;
  line-height:1.16;
  letter-spacing:-0.01em;
}
p{margin:0;}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;padding:0;}
input,textarea{font:inherit;color:inherit;}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}

.skip-link{
  position:fixed;
  inset-inline-start:12px;
  top:-60px;
  background:var(--c-black);
  color:var(--c-ivory);
  padding:.75rem 1.25rem;
  border-radius:var(--radius-sm);
  z-index:999;
  transition:top var(--dur) var(--ease);
  font-family:var(--font-heading);
  font-size:var(--fs-small);
}
.skip-link:focus{top:12px;}

/* glow text used on accent words inside headlines — a slow breathing glow */
.glow-text{
  color:var(--accent);
  animation:glowTextPulse 3.5s ease-in-out infinite;
}
@keyframes glowTextPulse{
  0%,100%{text-shadow:0 0 30px var(--glow), 0 0 68px color-mix(in srgb, var(--glow) 60%, transparent);}
  50%{text-shadow:0 0 42px var(--glow), 0 0 92px color-mix(in srgb, var(--glow) 72%, transparent);}
}
@media (prefers-reduced-motion: reduce){ .glow-text{animation:none;text-shadow:0 0 30px var(--glow), 0 0 68px color-mix(in srgb, var(--glow) 60%, transparent);} }

/* Site background ---------------------------------------------------------
   The reference: radial-gradient(125% 125% at 50% 10%, #000 40%, #63e 100%)
   — a solid colour across the top and centre that blooms into a vivid
   accent toward the edges and the bottom. In ZAYNA's palette:
     light → ivory blooming into royal gold
     dark  → espresso blooming into the brand's wine
   It sits on one fixed, viewport-sized layer, so every screen gets the same
   glow while the content scrolls over it — and since it never changes, the
   browser paints it once and only ever composites it after that. (Not
   background-attachment:fixed on body: that repaints on every scroll frame
   on phones.) Theme switching is just the two variables below. */
:root{
  --bg-g1:var(--c-ivory);   /* the calm centre */
  --bg-g2:var(--c-gold);    /* the bloom */
}
:root[data-theme="dark"]{
  --bg-g1:#120A0D;          /* espresso */
  --bg-g2:var(--c-wine);    /* wine */
}
.site-bg{
  position:fixed;top:0;left:0;z-index:-1;
  width:100%;height:100vh;height:100lvh;   /* lvh: no gap when a phone's address bar hides */
  pointer-events:none;
  background:radial-gradient(125% 125% at 50% 10%, var(--bg-g1) 40%, var(--bg-g2) 100%);
}
#ritual > .container, #ingredients > .container, #testimonials > .container, #faq > .container{
  position:relative;z-index:1;
}

/* 4. Layout helpers --------------------------------------------------------*/
.container{width:100%;max-width:var(--container-w);margin-inline:auto;padding-inline:var(--container-pad);}
.section{padding-block:var(--space-section);position:relative;}
section[id]{scroll-margin-top:calc(var(--header-h) + 16px);}
.section-head{max-width:660px;margin-block-end:clamp(32px,5vw,56px);position:relative;z-index:1;}
.section-head--center{margin-inline:auto;text-align:center;}
.eyebrow{
  display:inline-flex;align-items:center;gap:.6em;
  font-family:var(--font-heading);
  font-size:var(--fs-micro);
  letter-spacing:.16em;
  color:var(--accent);
  font-weight:700;
  margin-block-end:.9em;
}
.eyebrow::before{content:"";width:0;height:1px;background:currentColor;display:inline-block;transition:width 700ms var(--ease) 250ms;}
.is-visible .eyebrow::before,.eyebrow.is-visible::before{width:22px;}
.section-head--center .eyebrow{justify-content:center;}
.section-head--center .eyebrow::before{display:none;}
@media (prefers-reduced-motion: reduce){ .eyebrow::before{width:22px;transition:none;} }
.section-title{font-size:var(--fs-h2);}
.section-title::after{
  content:"";display:block;margin-block-start:16px;
  width:0;height:3px;border-radius:2px;
  background:linear-gradient(90deg,var(--c-pink),var(--c-gold));
  transition:width 900ms var(--ease) 300ms;
}
.is-visible .section-title::after{width:64px;}
.section-head--center .section-title::after{margin-inline:auto;}
@media (prefers-reduced-motion: reduce){ .section-title::after{width:64px;transition:none;} }
.section-lead{margin-block-start:14px;color:var(--text-muted);font-size:var(--fs-lead);max-width:52ch;}
.section-head--center .section-lead{margin-inline:auto;}
.visually-hidden{position:absolute !important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:-1px;padding:0;border:0;}

/* glass panel utility — soft blur, hairline border, blurred shadow */
.glass{
  background:var(--surface);
  backdrop-filter:blur(var(--blur)) saturate(var(--sat));
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--sat));
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-soft);
}

/* 5. Buttons & inputs -------------------------------------------------------*/
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.6em;
  padding:1.05rem 2.1rem;
  font-family:var(--font-heading);
  font-weight:700;
  font-size:.96rem;
  border:1px solid transparent;
  border-radius:var(--radius-pill);
  cursor:pointer;
  transition:transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  white-space:nowrap;
}
/* an icon inside a button must never be the thing that gives way: .btn is
   a nowrap flex row, so on a narrow card a long label used to squeeze the
   icon's SVG down to 0px wide and it silently vanished */
.btn > svg{flex-shrink:0;}
.btn__icon{width:18px;height:18px;}
.btn:active{transform:scale(.97);}
.btn__arrow{width:16px;height:16px;flex:none;animation:btnArrowNudge 2.2s ease-in-out infinite;}
@keyframes btnArrowNudge{0%,100%{transform:translateX(0);}50%{transform:translateX(-4px);}}
@media (prefers-reduced-motion: reduce){ .btn__arrow{animation:none;} }
/* "Liquid glass" CTA — adapted from a community shadcn glass-button (a
   translucent blurred pill with a light-catching top edge and a soft
   shadow floating beneath it, instead of an opaque fill). Reuses the
   site's own --blur/--sat glass tokens — the exact ones .glass and the
   header already blur with, and the ones the mobile media query further
   down already turns down — so it never costs more than any other glass
   surface already on the page. Unlike the old shiny rotating rim,
   NOTHING here loops forever: the only motion is a one-off light sweep
   that plays once per hover/focus, not an infinite animation. */
.btn-primary{
  position:relative;isolation:isolate;overflow:hidden;
  border:1px solid color-mix(in srgb, var(--c-ivory) 55%, transparent);
  background:linear-gradient(165deg,
    color-mix(in srgb, var(--c-gold) 62%, transparent),
    color-mix(in srgb, var(--c-berry) 48%, transparent) 130%);
  backdrop-filter:blur(var(--blur)) saturate(calc(var(--sat) + 40%));
  -webkit-backdrop-filter:blur(var(--blur)) saturate(calc(var(--sat) + 40%));
  color:#fff;
  text-shadow:0 1px 3px rgba(0,0,0,.35);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -10px 14px -10px rgba(23,11,16,.35),
    0 16px 34px -16px color-mix(in srgb, var(--c-gold) 60%, transparent),
    0 10px 22px -12px rgba(0,0,0,.4);
  transition:transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.btn-primary:hover,.btn-primary:focus-visible{
  transform:translateY(-3px);
  background:linear-gradient(165deg,
    color-mix(in srgb, var(--c-gold) 78%, transparent),
    color-mix(in srgb, var(--c-berry) 60%, transparent) 130%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.7),
    inset 0 -10px 14px -10px rgba(23,11,16,.3),
    0 22px 46px -16px color-mix(in srgb, var(--c-gold) 70%, transparent),
    0 14px 28px -12px rgba(0,0,0,.45);
}
.btn-primary > *{position:relative;z-index:1;}
/* the light sweep itself — static until hovered, so it never runs when
   nobody's looking */
.btn-primary::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(120deg, transparent 40%, rgba(255,255,255,.55) 50%, transparent 60%);
  transform:translateX(-130%);
}
.btn-primary:hover::after,.btn-primary:focus-visible::after{animation:btnGlassSweep .9s var(--ease);}
@keyframes btnGlassSweep{ to{ transform:translateX(130%); } }
@media (prefers-reduced-motion: reduce){ .btn-primary:hover::after,.btn-primary:focus-visible::after{animation:none;} }
.btn-outline{background:transparent;border-color:var(--border);color:var(--text-strong);}
.btn-outline:hover{background:var(--ring);transform:translateY(-2px);border-color:transparent;}
.btn-ghost-inverse{background:transparent;border-color:var(--inv-border);color:var(--inv-text);}
.btn-ghost-inverse:hover{background:rgba(255,255,255,0.08);transform:translateY(-2px);}
.btn-block{width:100%;}
.btn-sm{padding:.65rem 1.35rem;font-size:.85rem;}
.btn[disabled]{opacity:.55;cursor:not-allowed;transform:none !important;}

/* An extra ambient pulse for the handful of especially-important CTAs
   (checkout submit, hero, buy-bar) — layered on top of .btn-primary's own
   glass, paused on hover so the box-shadow settles instead of fighting
   the hover state's own shadow change. */
.btn-glow{position:relative;animation:btnGlowPulse 2.6s ease-in-out infinite;}
.btn-glow:hover{animation-play-state:paused;}
/* keeps .btn-primary's own inset glass highlights constant and only
   pulses the outer glow layer, so a glowing CTA doesn't go flat between
   beats */
@keyframes btnGlowPulse{
  0%,100%{box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -10px 14px -10px rgba(23,11,16,.35),
    var(--glow-pink-lit);
  }
  50%{box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -10px 14px -10px rgba(23,11,16,.35),
    0 14px 54px -6px var(--glow);
  }
}
@media (prefers-reduced-motion: reduce){ .btn-glow{animation:none;} }

/* order-confirmation CTAs (checkout submit + mobile bar) — pulsing white
   text glow in light mode, on top of .btn-primary's own white label color. */
:root:not([data-theme="dark"]) .btn-confirm-glow span{animation:submitBtnTextGlow 2.6s ease-in-out infinite;}
:root:not([data-theme="dark"]) .btn-confirm-glow:hover span{animation-play-state:paused;}
@keyframes submitBtnTextGlow{
  0%,100%{text-shadow:0 0 0 rgba(255,255,255,0);}
  50%{text-shadow:0 0 16px rgba(255,255,255,0.95), 0 0 32px rgba(255,255,255,0.55);}
}
@media (prefers-reduced-motion: reduce){ .btn-confirm-glow span{animation:none;} }

.field{display:flex;flex-direction:column;gap:.5rem;margin-block-end:1.2rem;}
.field label{font-family:var(--font-heading);font-size:var(--fs-small);font-weight:700;color:var(--text-strong);}
.field .optional{color:var(--text-muted);font-weight:400;}
.field__control{position:relative;display:flex;align-items:center;}
.field__control--textarea{align-items:flex-start;}
.field__icon{position:absolute;inset-inline-start:16px;top:1.05rem;width:18px;height:28px;color:var(--accent);opacity:.85;pointer-events:none;}
.field__control input,.field__control textarea{padding-inline-start:46px;width:100%;}
.field input,.field textarea{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius-md);
  padding:.95rem 2.5rem;
  font-size:1rem;
  color:var(--text-strong);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  transition:border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field textarea{resize:vertical;min-height:90px;}
.field input::placeholder,.field textarea::placeholder{color:var(--text-muted);opacity:.8;}
.field input:focus,.field textarea:focus{border-color:var(--accent);box-shadow:0 0 0 4px var(--ring);}
.field.has-error input,.field.has-error textarea{border-color:var(--c-error);}
.field-error{font-size:var(--fs-small);color:var(--c-error);font-weight:600;display:none;align-items:center;gap:.4em;}
.field.has-error .field-error{display:flex;}

/* pill badge — trust badges, rating, package badges */
.badge{
  display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--font-heading);font-weight:700;font-size:var(--fs-small);
  color:var(--text-strong);
  background:var(--surface);
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  border:1px solid var(--border);
  border-radius:var(--radius-pill);
  padding:.55em 1.1em;
}
.badge svg{width:15px;height:15px;color:var(--accent);}

/* 6. Announcement bar + marquee ticker --------------------------------------*/
.announcement-bar{background:var(--c-black);color:var(--c-ivory);}
:root[data-theme="dark"] .announcement-bar{background:var(--c-blush);color:var(--c-black);}
.announcement-bar p{text-align:center;font-size:var(--fs-micro);letter-spacing:.06em;padding-block:.6rem;padding-inline:var(--container-pad);}

/* dark backdrop in light mode, matching the announcement bar above it —
   inverted to a beige backdrop in dark mode, same as that bar. */
.marquee{overflow:hidden;background:var(--c-black);direction:ltr;}
:root[data-theme="dark"] .marquee{background:var(--c-blush);}
.marquee__track{display:inline-flex;width:max-content;gap:2.2rem;padding-block:11px;animation:marqueeScroll 60s linear infinite;}
.marquee__track span{display:inline-flex;align-items:center;gap:2.2rem;font-family:var(--font-heading);font-weight:700;font-size:1rem;color:var(--c-ivory);white-space:nowrap;}
:root[data-theme="dark"] .marquee__track span{color:var(--c-black);}
.marquee__track span::after{content:"✦";opacity:.65;margin-inline-start:2.2rem;color:var(--gold);display:inline-block;animation:starSpin 6s linear infinite;}
:root[data-theme="dark"] .marquee__track span::after{color:var(--c-pink);}
@keyframes starSpin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion: reduce){ .marquee__track span::after{animation:none;} }
@keyframes marqueeScroll{from{transform:translateX(0);}to{transform:translateX(-50%);}}
@media (prefers-reduced-motion: reduce){ .marquee__track{animation:none;} }

/* 7. Header -----------------------------------------------------------------*/
.site-header{
  position:sticky;top:0;z-index:60;
  background:color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  border-bottom:1px solid transparent;
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.site-header.is-scrolled{border-color:var(--border);box-shadow:0 16px 40px -28px rgba(34,0,17,0.5);}
.site-header__inner{display:flex;align-items:center;justify-content:space-between;gap:clamp(16px,3vw,40px);block-size:var(--header-h);}
.brand{display:inline-flex;align-items:center;}
.brand__logo{height:60px;width:auto;animation:logoBreathe 4s ease-in-out infinite;}
@keyframes logoBreathe{0%,100%{filter:drop-shadow(0 0 4px color-mix(in srgb, var(--c-gold) 30%, transparent));}50%{filter:drop-shadow(0 0 10px color-mix(in srgb, var(--c-gold) 60%, transparent));}}
@media (prefers-reduced-motion: reduce){ .brand__logo{animation:none;} }
.brand__logo--light{display:none;}
:root[data-theme="dark"] .brand__logo--dark{display:none;}
:root[data-theme="dark"] .brand__logo--light{display:block;}

.main-nav ul{display:flex;align-items:center;gap:clamp(18px,2.4vw,34px);}
.main-nav a{font-family:var(--font-heading);font-size:.92rem;font-weight:600;color:var(--text-body);position:relative;padding-block:6px;transition:color var(--dur-fast) var(--ease);}
.main-nav a::after{content:"";position:absolute;inset-inline-start:0;bottom:0;width:0;height:2px;background:var(--accent);transition:width var(--dur) var(--ease);}
.main-nav a:hover{color:var(--accent);}
.main-nav a:hover::after{width:100%;}

.site-header__actions{display:flex;align-items:center;gap:14px;}
/* Turns the always-sticky header CTA into a live purchase affordance —
   the price stays in sync with whatever offer is currently selected
   below, so "sticky purchase action" means something concrete on desktop
   without needing a second fixed bar competing with the page content. */
.site-header__cta-price{
  display:inline-flex;align-items:center;margin-inline-start:8px;padding-inline-start:8px;
  border-inline-start:1px solid rgba(255,255,255,.35);
  font-size:.78rem;font-weight:600;opacity:.92;
}
.theme-toggle{
  width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--border);border-radius:50%;color:var(--text-strong);
  background:var(--surface);
  transition:border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.theme-toggle:hover{border-color:var(--accent);transform:rotate(-10deg);}
.theme-toggle svg{width:18px;height:18px;}
.theme-toggle .icon-moon{display:none;}
:root[data-theme="dark"] .theme-toggle .icon-sun{display:none;}
:root[data-theme="dark"] .theme-toggle .icon-moon{display:block;}

.nav-toggle{display:none;width:42px;height:42px;border:1px solid var(--border);border-radius:50%;position:relative;background:var(--surface);}
.nav-toggle span{position:absolute;inset-inline-start:11px;width:18px;height:1.5px;background:var(--text-strong);transition:transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease), top var(--dur-fast) var(--ease);}
.nav-toggle span:nth-child(1){top:15px;}
.nav-toggle span:nth-child(2){top:20px;}
.nav-toggle span:nth-child(3){top:25px;}
.nav-toggle[aria-expanded="true"] span:nth-child(1){top:20px;transform:rotate(45deg);}
.nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0;}
.nav-toggle[aria-expanded="true"] span:nth-child(3){top:20px;transform:rotate(-45deg);}

/* 8. Mobile navigation --------------------------------------------------------*/
/* visibility:hidden while closed, not just opacity:0 — an invisible
   full-screen fixed layer still gets composited on every frame. The
   visibility flip is delayed by the fade's duration on close so the
   fade-out still plays, and is immediate on open. Same for the panel. */
.mobile-nav-backdrop{position:fixed;inset:0;background:rgba(34,0,17,0.5);opacity:0;pointer-events:none;visibility:hidden;transition:opacity var(--dur) var(--ease), visibility 0s linear var(--dur);z-index:70;}
.mobile-nav-backdrop.is-open{opacity:1;pointer-events:auto;visibility:visible;transition:opacity var(--dur) var(--ease), visibility 0s;}
.mobile-nav{
  position:fixed;inset-block:0;inset-inline-end:0;width:min(86vw,380px);
  background:color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter:blur(24px) saturate(160%);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
  border-inline-start:1px solid var(--border);
  z-index:80;transform:translateX(100%);visibility:hidden;transition:transform var(--dur-slow) var(--ease), visibility 0s linear var(--dur-slow);
  display:flex;flex-direction:column;padding:22px clamp(20px,6vw,32px) 28px;
}
:dir(rtl) .mobile-nav{transform:translateX(-100%);}
.mobile-nav.is-open{transform:translateX(0);visibility:visible;transition:transform var(--dur-slow) var(--ease), visibility 0s;}
.mobile-nav__top{display:flex;justify-content:space-between;align-items:center;margin-block-end:36px;}
.mobile-nav__close{width:38px;height:38px;border:1px solid var(--border);border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--text-strong);}
.mobile-nav__close svg{width:16px;height:16px;}
.mobile-nav ul{display:flex;flex-direction:column;gap:6px;margin-block-end:auto;}
.mobile-nav a{font-family:var(--font-heading);font-size:1.25rem;font-weight:700;padding-block:14px;border-block-end:1px solid var(--border);display:block;color:var(--text-strong);}
.mobile-nav a.btn-primary{color:#fff;}
.mobile-nav__foot{display:flex;flex-direction:column;gap:16px;padding-block-start:24px;}
.mobile-nav__theme{display:flex;align-items:center;gap:10px;font-family:var(--font-heading);font-size:.95rem;}
body.nav-open{overflow:hidden;}

/* 9. Hero ---------------------------------------------------------------------*/
.hero{position:relative;overflow:clip;padding-block:clamp(40px,6vw,60px) clamp(52px,7vw,84px);}
.hero__wordmark{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  font-family:var(--font-heading);font-weight:800;font-size:clamp(6rem,26vw,17rem);
  color:var(--text-strong);opacity:.055;white-space:nowrap;user-select:none;z-index:0;
}
/* Desktop: initScrollEffects writes its transform + opacity on every scroll
   frame through the hero; as its own layer that's a free compositor update
   instead of a repaint. NOT on phones: there, a layer under the hero copy
   forces the copy above it onto two more tall layers ('overlaps composited
   content'), and the drift is switched off on touch anyway. */
@media (min-width:901px) and (pointer:fine){ .hero__wordmark{will-change:transform,opacity;} }
:root:not([data-theme="dark"]) .hero__wordmark{color:var(--c-black);opacity:.07;}
.hero__inner{position:relative;z-index:1;display:grid;grid-template-columns:1.05fr .95fr;align-items:center;gap:clamp(28px,5vw,64px);}
.hero__copy{max-width:580px;}
.hero__title{font-size:var(--fs-hero);margin-block:.32em .48em;}
.hero__subtitle{font-size:var(--fs-lead);color:var(--text-muted);max-width:48ch;}
.hero__actions{display:flex;flex-wrap:wrap;gap:14px;margin-block-start:32px;}
/* slim stat strip — plain icon+label pairs with hairline dividers, instead
   of four boxed pill badges competing for attention under the CTAs. */
.hero__stats{display:flex;flex-wrap:wrap;gap:16px;margin-block-start:28px;}
.hero__stat{
  display:inline-flex;align-items:center;gap:.55em;
  font-size:.86rem;font-weight:600;color:var(--text-muted);
  padding-inline-end:16px;border-inline-end:1px solid var(--border);
  opacity:0;transform:translateX(-8px);
}
:dir(rtl) .hero__stat{transform:translateX(8px);}
.hero__stat:last-child{border-inline-end:none;padding-inline-end:0;}
.hero__stat svg{width:16px;height:16px;color:var(--accent);flex:none;}
.hero__stats.is-visible .hero__stat{animation:statFadeIn 500ms var(--ease) forwards;}
.hero__stats.is-visible .hero__stat:nth-child(1){animation-delay:.05s;}
.hero__stats.is-visible .hero__stat:nth-child(2){animation-delay:.15s;}
.hero__stats.is-visible .hero__stat:nth-child(3){animation-delay:.25s;}
@keyframes statFadeIn{to{opacity:1;transform:translateX(0);}}
@media (prefers-reduced-motion: reduce){
  .hero__stat,
  .hero__stats.is-visible .hero__stat{opacity:1;transform:none;animation:none;}
}

/* floating rating badge overlapping the product photo's corner */
.hero__rating{
  position:absolute;z-index:3;bottom:-16px;inset-inline-start:-16px;
  display:flex;align-items:center;gap:9px;
  background:var(--surface-solid);border:1px solid var(--border);
  border-radius:var(--radius-pill);padding:9px 16px 9px 12px;
  box-shadow:var(--shadow-soft);
  opacity:0;transform:scale(.7);
}
.hero__media.is-visible .hero__rating{animation:ratingPop 550ms var(--ease) .5s forwards;}
@keyframes ratingPop{60%{opacity:1;transform:scale(1.08);}100%{opacity:1;transform:scale(1);}}
@media (prefers-reduced-motion: reduce){
  .hero__rating,
  .hero__media.is-visible .hero__rating{opacity:1;transform:none;animation:none;}
}
.hero__rating svg{width:20px;height:20px;color:var(--accent);flex:none;}
.hero__rating-text{display:flex;flex-direction:column;line-height:1.2;}
.hero__rating-text strong{font-family:var(--font-heading);font-size:.92rem;font-weight:800;color:var(--text-strong);}
.hero__rating-text span{font-size:.68rem;color:var(--text-muted);}
@media (max-width:480px){
  .hero__rating{padding:7px 12px 7px 10px;gap:7px;}
  .hero__rating svg{width:17px;height:17px;}
  .hero__rating-text strong{font-size:.8rem;}
  .hero__rating-text span{font-size:.6rem;}
}

/* offset bordered card peeking out behind the product photo, for depth —
   matches the marquee ticker's own background exactly, per theme:
   near-black in light mode, beige in dark mode (see .marquee further
   down) — same color, same light/dark swap, not just one fixed hex. */
.hero__float-backdrop{
  position:absolute;z-index:-1;inset:8% -10% -10% 8%;
  border:1.5px solid color-mix(in srgb, var(--c-black) 45%, transparent);
  border-radius:var(--radius-lg);
  background:color-mix(in srgb, var(--c-black) 6%, transparent);
  transform:rotate(-4deg);
}
:root[data-theme="dark"] .hero__float-backdrop{
  border-color:color-mix(in srgb, var(--c-blush) 55%, transparent);
  background:color-mix(in srgb, var(--c-blush) 8%, transparent);
}

.hero__media{position:relative;perspective:1600px;display:flex;justify-content:center;}

.hero__float{position:relative;max-width:300px;margin-inline:auto;}

.hero__float::before{
  content:"";
  position:absolute;
  inset:-14%;
  z-index:-1;
  border-radius:50%;
  background:radial-gradient(circle, var(--c-black) 0%, rgba(23,11,16,0.35) 45%, transparent 72%);
  filter:blur(30px);
  opacity:.75;
}
:root[data-theme="dark"] .hero__float::before{
  background:radial-gradient(circle, var(--c-blush) 0%, rgba(239,225,194,0.35) 45%, transparent 72%);
}
/* slowly rotating conic light-ring behind the product — an ambient "halo",
   same per-theme color as the marquee ticker's background. */
.hero__float::after{
  content:"";
  position:absolute;
  inset:-22%;
  z-index:-2;
  border-radius:50%;
  background:conic-gradient(from 0deg, transparent 0%, var(--c-black) 18%, transparent 38%, var(--c-black) 55%, transparent 75%, var(--c-black) 92%, transparent 100%);
  filter:blur(26px);
  opacity:.4;
  animation:heroHaloSpin 16s linear infinite;
}
:root[data-theme="dark"] .hero__float::after{
  background:conic-gradient(from 0deg, transparent 0%, var(--c-blush) 18%, transparent 38%, var(--c-blush) 55%, transparent 75%, var(--c-blush) 92%, transparent 100%);
}
@keyframes heroHaloSpin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion: reduce){ .hero__float::after{animation:none;} }

.hero__media .media-slot{
  border-radius:var(--radius-lg);
  border:1px solid rgba(23,11,16,0.35);
  box-shadow:0 0 50px -6px rgba(23,11,16,0.45), var(--shadow-soft);
  transition:box-shadow var(--dur-slow) var(--ease);
}
:root[data-theme="dark"] .hero__media .media-slot{
  border-color:rgba(239,225,194,0.5);
  box-shadow:0 0 50px -6px rgba(239,225,194,0.6), var(--shadow-soft);
}
/* A glow-only hover response (no transform) — the product itself never
   moves for a hover, only ever for a scroll. */
.hero__media:hover .media-slot{box-shadow:0 0 64px -4px rgba(23,11,16,0.55), 0 30px 70px -20px var(--ring);}
:root[data-theme="dark"] .hero__media:hover .media-slot{box-shadow:0 0 64px -4px rgba(239,225,194,0.75), 0 30px 70px -20px var(--ring);}
/* liquid-glass light sweep gliding across the product photo. Animated
   with transform, NOT background-position: background-position repaints
   the whole photo-sized layer on every frame, forever — the most expensive
   thing in the hero on a phone. A transform on the pseudo-element itself
   composes with .hero__float's 3D transform on the ancestor rather than
   clashing with it, and costs the compositor nothing. */
.hero__media .media-slot::after{
  content:"";
  position:absolute;
  top:0;bottom:0;left:0;width:60%;
  z-index:2;
  /* a horizontal gradient that is transparent at BOTH of the band's edges,
     tilted with skewX — a diagonal (115deg) gradient in this tall, narrow
     band still had colour at the band's right edge and drew a hard line */
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.4) 50%, transparent);
  transform:translateX(-140%) skewX(-18deg);
  animation:heroGlassSheen 6.5s ease-in-out infinite;
  pointer-events:none;
}
@keyframes heroGlassSheen{
  0%,42%{transform:translateX(-140%) skewX(-18deg);}
  68%,100%{transform:translateX(300%) skewX(-18deg);}
}
@media (prefers-reduced-motion: reduce){ .hero__media .media-slot::after{animation:none;display:none;} }
.hero__media .media-slot img,.hero__media .media-slot video{object-position:center 74%;}

/* 10. Media slot / illustrated placeholders ------------------------------------*/
.media-slot{position:relative;border-radius:var(--radius-lg);overflow:hidden;background:linear-gradient(160deg,var(--bg-soft),var(--bg) 60%);border:1px solid var(--border);}
.media-slot img,.media-slot video{width:100%;height:100%;object-fit:cover;display:block;}
.media-slot__placeholder{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:14px;padding:10%;text-align:center;}
.media-slot:not(:has(img)):not(:has(video)) .media-slot__placeholder{display:flex;}
.media-slot.is-empty .media-slot__placeholder{display:flex;}
.media-slot.is-empty img,.media-slot.is-empty video{display:none;}
.media-slot__placeholder svg{width:46%;max-width:220px;height:auto;}
.media-slot__caption{font-family:var(--font-heading);font-size:var(--fs-micro);color:var(--text-muted);}
.media-slot--square{aspect-ratio:1/1;}
.media-slot--portrait{aspect-ratio:3/4;}
.media-slot--wide{aspect-ratio:16/10;}
.media-slot--proof .media-slot__caption{color:var(--accent);font-weight:600;max-width:24ch;line-height:1.6;}

/* 11. Benefit strip -------------------------------------------------------------*/
.benefit-strip{position:relative;background:var(--bg-soft);border-block:1px solid var(--border);}
:root[data-theme="dark"] .benefit-strip{background:color-mix(in srgb, var(--c-gold) 7%, var(--c-black));}
.benefit-strip__row{position:relative;z-index:1;display:grid;grid-template-columns:repeat(4,1fr);}
.benefit-strip__item{display:flex;align-items:center;gap:14px;padding:clamp(20px,3vw,30px) clamp(16px,2.4vw,28px);border-inline-end:1px solid var(--border);}
.benefit-strip__item:last-child{border-inline-end:none;}
.benefit-strip__icon{flex:none;width:40px;height:40px;border-radius:50%;background:var(--surface-solid);border:1px solid var(--border);color:var(--accent);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--shadow-soft);}
.benefit-strip__icon svg{width:17px;height:17px;}
.benefit-strip__icon{opacity:0;transform:scale(.3);}
.is-visible .benefit-strip__icon{animation:iconPop 500ms var(--ease) forwards;}
.benefit-strip__item:nth-child(1).is-visible .benefit-strip__icon{animation-delay:.05s;}
.benefit-strip__item:nth-child(2).is-visible .benefit-strip__icon{animation-delay:.15s;}
.benefit-strip__item:nth-child(3).is-visible .benefit-strip__icon{animation-delay:.25s;}
.benefit-strip__item:nth-child(4).is-visible .benefit-strip__icon{animation-delay:.35s;}
@media (prefers-reduced-motion: reduce){
  .benefit-strip__icon,
  .is-visible .benefit-strip__icon{opacity:1;transform:none;animation:none;}
}
.benefit-strip__item p{font-family:var(--font-heading);font-size:.86rem;font-weight:700;color:var(--text-strong);}

/* 12. Product showcase --------------------------------------------------------*/
.showcase{background:var(--inv-bg);color:var(--inv-text);position:relative;overflow:clip;}
.showcase .eyebrow{background:var(--c-gold);color:#241505;}
.showcase .section-title{
  color:var(--inv-text);
  text-shadow:0 0 24px rgba(255,248,250,0.5), 0 0 60px rgba(255,248,250,0.25);
}
.showcase .section-title .glow-text{color:var(--c-gold);text-shadow:0 0 26px var(--c-gold), 0 0 60px rgba(232,196,104,0.5);}
.showcase .section-lead{color:var(--inv-muted);}
/* ---- Endless "wheel" carousel ------------------------------------------
   Only three real products, but initShowcaseCarousel() in main.js clones
   the set into a long strip and, whenever the scroll position nears
   either end, silently jumps it back by exactly one set-width. The strip
   repeats every set-width, so the jump can't be seen: you can flick in
   EITHER direction forever and the same three products keep coming round,
   like a spinning wheel. A slow autoplay nudges it one card at a time and
   pauses on any touch / drag / hover (resuming after a few idle seconds).
   Same behaviour desktop + mobile — no separate layout.

   direction:ltr on the track (the page is RTL) so DOM order == visual
   left-to-right order AND scrollLeft counts up normally left→right — the
   loop maths needs both. Card TEXT is set back to rtl. Per set, DOM and
   visual order is:  hydrolat  ·  shampoo (centred on load)  ·  oil. */
.showcase__grid{
  position:relative;z-index:1;
  display:flex;flex-wrap:nowrap;
  justify-content:flex-start;align-items:center;
  direction:ltr;
  gap:clamp(16px,3.4vw,40px);
  overflow-x:auto;overflow-y:visible;
  overflow-anchor:none;
  scroll-behavior:auto;
  padding-block:clamp(28px,6vw,60px);
  padding-inline:0;
  min-height:clamp(440px,54vw,580px);
  /* No CSS scroll-snap: both mandatory and proximity fight the smooth
     scrollTo()s that drive autoplay / drag-release / the initial centre
     (the animation kept ending short of its target). initShowcaseCarousel
     settles every rest position on an exact card centre itself, including
     after a free momentum flick. */
  scroll-snap-type:none;
  -webkit-overflow-scrolling:touch;
  /* pan-x pan-y — NOT pan-x alone. pan-x told the browser a finger on
     the cards may only ever move sideways, so a vertical swipe starting on
     a card did nothing at all: on a phone, where the wheel is ~450px tall,
     half the screen stopped scrolling the page. With both axes allowed the
     browser picks the direction from the gesture itself: sideways spins
     the wheel, up/down scrolls the page. overscroll-behavior-x keeps a hard
     flick at either end inside the carousel instead of chaining into a
     page/back gesture. */
  touch-action:pan-x pan-y;
  overscroll-behavior-x:contain;
  scrollbar-width:none;
  perspective:1600px;
  cursor:grab;
}
.showcase__grid::-webkit-scrollbar{display:none;}
.showcase__grid.is-grabbing{cursor:grabbing;scroll-snap-type:none;user-select:none;}

/* [data-reveal] stays in the selector so it out-specifies the generic
   ".product-card[data-reveal].is-visible{transform:translateY(0)}" reveal
   rule later in this file — the per-frame coverflow transform is written
   as an inline style by initShowcaseCarousel() and must win. Only opacity
   transitions; transform is left transition-less so it tracks the scroll
   position exactly instead of lagging behind it. */
.showcase__grid > .product-card[data-reveal]{
  flex:0 0 clamp(238px,30vw,330px);
  scroll-snap-align:center;
  direction:rtl;
  transform-origin:50% 50%;
  transition:opacity .4s var(--ease);
  backface-visibility:hidden;
}
/* no-JS fallback: a plain finite swipe row, still usable */
.showcase__grid:not(.is-carousel) > .product-card[data-reveal]:first-child{margin-inline-start:12%;}
.showcase__grid:not(.is-carousel) > .product-card[data-reveal]:last-child{margin-inline-end:12%;}

@media (max-width:860px){
  .showcase__grid{
    gap:12px;
    min-height:clamp(400px,116vw,520px);
    perspective:900px;
  }
  .showcase__grid > .product-card[data-reveal]{flex-basis:72%;}
}

@media (prefers-reduced-motion: reduce){
  .showcase__grid{scroll-snap-type:x proximity;}
  .showcase__grid > .product-card[data-reveal]{transition:none;}
}

/* Showcase card CTAs on phones. Each card is only ~200px wide there, and
   "اطلبي الآن — 150 درهم" + icon needed ~200px at the normal button size
   against ~140px of room inside the default 2.1rem side padding: the
   label spilled into the padding at 390px and was cut off outright by
   .btn-primary's overflow:hidden on 360px and 320px phones. Tighter
   padding, a smaller icon and a slightly smaller label keep it on ONE line
   on 375px+ phones; narrower than that it wraps onto two lines instead of
   being clipped. */
@media (max-width:860px){
  .showcase__grid .product-card__body .btn{
    padding-inline:.75rem;
    font-size:.84rem;
    gap:.4em;
    white-space:normal;
    line-height:1.35;
    text-wrap:balance;
  }
  .showcase__grid .product-card__body .btn__icon{width:15px;height:15px;}
}

/* ---- Carousel performance -------------------------------------------------
   The wheel puts many product cards in one horizontal scroller. Every
   GPU-heavy trick that is fine on a SINGLE static card — a backdrop-filter
   blur, an infinitely animating conic-gradient button rim, a looping
   shimmer sweep, an ambient glow layer — turns into a per-frame tax paid
   N times while the strip moves, and that is the single biggest cause of
   jank on a phone here. Inside the carousel each one is swapped for a flat
   equivalent that looks the same but costs nothing to keep on screen. */
.showcase__grid.is-carousel > .product-card[data-reveal]{
  backdrop-filter:none;-webkit-backdrop-filter:none;
  background:linear-gradient(165deg,
    color-mix(in srgb, var(--c-gold) 13%, var(--inv-bg)),
    color-mix(in srgb, var(--c-gold) 4%, var(--inv-bg)));
  transition:none;                 /* transform + opacity are written live by JS every scroll frame */
  /* no will-change: it kept a GPU layer for ALL 15 cards (3 real + 12
     clones), including the ~10 parked off-screen at visibility:hidden.
     The cards on screen are already composited by the translate3d() the
     wheel writes into them; parked ones carry transform:none and cost
     nothing. */
  contain:layout paint style;
}
.showcase__grid.is-carousel .product-card::before{display:none;}          /* ambient spotlight glow layer */
.showcase__grid.is-carousel .product-card__media::before{display:none;}   /* hover shine sweep */
.showcase__grid.is-carousel .product-card__index{
  backdrop-filter:none;-webkit-backdrop-filter:none;
  background:linear-gradient(160deg,#241206,#140a0e);
}
.showcase__grid.is-carousel .product-card__index::after{display:none;animation:none;}
/* card CTAs keep the gold look but drop the backdrop-filter glass (see
   .btn-primary below) — translucent blur on ~15 continuously-transforming
   cloned cards is exactly the per-frame cost the wheel can't afford, the
   same call already made for the medallion and the ribbon shimmer above. */
.showcase__grid.is-carousel .btn-primary{
  backdrop-filter:none;-webkit-backdrop-filter:none;
  background:linear-gradient(135deg, var(--c-gold), var(--c-berry) 120%);
  box-shadow:0 10px 24px -12px color-mix(in srgb, var(--c-gold) 55%, transparent);
}
@media (max-width:860px){
  .showcase__grid{perspective:none;}   /* JS drops to 2D transforms below this width */
}

.product-card{
  position:relative;
  /* a clearly gold-tinted glass surface instead of near-invisible 5.5%
     white — the old surface barely separated from the section's own dark
     background, so the card never read as a distinct object. */
  background:linear-gradient(165deg, color-mix(in srgb, var(--c-gold) 10%, transparent), color-mix(in srgb, var(--c-gold) 3%, transparent));
  backdrop-filter:blur(var(--blur)) saturate(var(--sat));
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--sat));
  border:1px solid color-mix(in srgb, var(--c-gold) 30%, var(--inv-border));
  border-radius:var(--radius-lg);
  overflow:hidden;
  display:flex;flex-direction:column;
  box-shadow:0 20px 50px -30px rgba(0,0,0,.6);
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* --tiltX/--tiltY are written by initCardTilt() on mousemove — a real 3D
   tilt (perspective + rotateX/rotateY) layered onto the existing lift,
   sharing this same transition so it settles with a soft, weighted feel
   rather than snapping instantly. Falls back to 0deg (flat) with no JS. */
.product-card:hover{transform:translateY(-10px) scale(1.015) perspective(900px) rotateX(var(--tiltX,0deg)) rotateY(var(--tiltY,0deg));box-shadow:var(--shadow-soft-inv);border-color:var(--c-gold);}
/* --spotlight is written continuously by initCardSpotlight() while
   scrolling — a soft ambient glow that brightens as the card nears the
   center of the viewport and fades as it drifts away. Opacity only, on
   its own layer, so it can never fight the hover-tilt or reveal
   transform already on the same element. */
.product-card::before{
  content:"";position:absolute;inset:0;z-index:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--c-gold) 45%, transparent), transparent 70%);
  opacity:var(--spotlight,0);
}
.product-card__media{border:none;border-radius:0;margin:0;}
.product-card__media img{transition:transform 900ms var(--ease);}
.product-card:hover .product-card__media img{transform:scale(1.08);}
.product-card__media::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,transparent 55%,rgba(0,0,0,.55));
  pointer-events:none;
}
/* hover shine sweep across the product photo — background-position only,
   so it can never fight the card's own hover transform (see the hero
   glass-sheen fix earlier in this file for why that pairing is unsafe). */
.product-card__media::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(115deg, transparent 35%, rgba(255,255,255,.35) 50%, transparent 65%);
  background-size:260% 260%;background-position:220% 50%;background-repeat:no-repeat;
  transition:background-position 900ms var(--ease);
  pointer-events:none;
}
.product-card:hover .product-card__media::before{background-position:-120% 50%;}
/* Floating glass medallion — a squircle chip (not a circle, not a flat
   flag) that sits pinned onto the photo with real depth: frosted-glass
   body (same blur/saturate recipe every card surface on this site
   already uses, so it belongs here), a thin gold ring + soft ambient
   glow halo (both via box-shadow, which paints OUTSIDE the element and
   is never clipped by its own overflow:hidden — that's reserved purely
   for the shimmer sweep below), and an embossed number (light catches
   the lower edge, shadow sits in the upper edge — the same emboss
   recipe used on the checkout band's own headline). Dark glass reads
   consistently on any photo behind it, unlike the old translucent
   gradient-text numeral it replaced. */
.product-card__index{
  position:absolute;top:16px;inset-inline-start:16px;z-index:2;
  width:50px;height:50px;border-radius:16px;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-heading);font-weight:800;font-size:1.3rem;line-height:1;
  color:var(--c-ivory);
  background:linear-gradient(160deg, color-mix(in srgb, var(--c-black) 80%, transparent), color-mix(in srgb, var(--c-black) 55%, transparent));
  backdrop-filter:blur(14px) saturate(180%);
  -webkit-backdrop-filter:blur(14px) saturate(180%);
  text-shadow:0 1px 0 rgba(255,255,255,.35), 0 -1px 1px rgba(0,0,0,.45);
  box-shadow:
    0 14px 28px -8px rgba(0,0,0,.65),
    0 0 0 1.5px color-mix(in srgb, var(--c-gold) 75%, transparent),
    0 0 26px 2px color-mix(in srgb, var(--c-gold) 45%, transparent),
    inset 0 1px 0 rgba(255,255,255,.3),
    inset 0 -8px 12px -8px rgba(0,0,0,.5);
  overflow:hidden;
  transition:box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.product-card:hover .product-card__index{
  transform:scale(1.08) rotate(-3deg);
  box-shadow:
    0 16px 34px -8px rgba(0,0,0,.7),
    0 0 0 1.5px var(--c-gold),
    0 0 36px 4px color-mix(in srgb, var(--c-gold) 65%, transparent),
    inset 0 1px 0 rgba(255,255,255,.35),
    inset 0 -8px 12px -8px rgba(0,0,0,.5);
}
/* Diagonal glass shine sweeping across the chip — transform only,
   matching every other shimmer on this site (checkout band, "soon"
   sheen, ribbon banner) instead of a one-off animation of its own. */
.product-card__index::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(115deg, transparent 30%, rgba(255,255,255,.5) 50%, transparent 70%);
  transform:translateX(-140%);
  animation:indexShimmer 4.5s ease-in-out infinite;
}
@keyframes indexShimmer{0%,40%{transform:translateX(-140%);}75%,100%{transform:translateX(140%);}}
@media (prefers-reduced-motion: reduce){
  .product-card__index::after{animation:none;display:none;}
  .product-card:hover .product-card__index{transform:none;}
}
@media (max-width:560px){ .product-card__index{width:42px;height:42px;border-radius:13px;font-size:1.1rem;top:12px;} }
/* Cut way down on request — media does almost all the talking now, the
   body is just enough text to name the product before the button. The
   detailed benefits/ingredients copy that used to live here didn't
   disappear from the site, only from this section: it still lives in
   the dedicated ingredients section further down the page. */
.product-card__body{padding:18px 20px 20px;display:flex;flex-direction:column;gap:12px;position:relative;z-index:1;}
.product-card__name{font-size:1.25rem;color:var(--inv-text);text-align:center;}

.showcase__cta{position:relative;z-index:1;text-align:center;margin-block-start:clamp(32px,5vw,48px);}

/* 13. Ritual -----------------------------------------------------------------------*/
.ritual__grid{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,5vw,64px);align-items:start;}
/* Signature pinned product storytelling: the photo stays in view (the
   same sticky convention already used for .checkout__summary) while the
   four ritual steps scroll past beside it, instead of the image just
   scrolling away like everything else on the page. */
.ritual__media{position:sticky;top:calc(var(--header-h) + 32px);}
.ritual__media .media-slot{aspect-ratio:4/5;box-shadow:var(--shadow-soft);}
.ritual__list{display:flex;flex-direction:column;}
.ritual__step{
  position:relative;
  display:grid;grid-template-columns:76px 1fr;gap:clamp(16px,3vw,32px);align-items:start;
  padding-block:clamp(22px,3.2vw,32px);border-block-end:1px solid var(--border);
}
.ritual__step:first-child{border-block-start:1px solid var(--border);}
/* A thin accent rule that fills in beside whichever step is currently
   centered in view — initRitualSteps() toggles .is-active via
   IntersectionObserver, no scroll listener involved. */
.ritual__step::before{
  content:"";position:absolute;inset-inline-start:-1px;top:0;bottom:0;width:2px;
  background:var(--accent);transform:scaleY(0);transform-origin:top;
  transition:transform var(--dur-slow) var(--ease);
}
.ritual__step.is-active::before{transform:scaleY(1);}
.ritual__num{
  display:inline-flex;align-items:center;justify-content:center;
  width:52px;height:52px;border-radius:50%;
  background:var(--surface);backdrop-filter:blur(14px);
  border:1px solid var(--border);
  font-family:var(--font-heading);font-weight:700;font-size:1.2rem;color:var(--accent);
  transition:transform var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ritual__step.is-active .ritual__num{background:var(--accent);color:var(--accent-on);border-color:var(--accent);transform:scale(1.08);}
.ritual__body h3{font-size:var(--fs-h3);margin-block-end:8px;}
.ritual__body p{color:var(--text-muted);max-width:56ch;}
@media (prefers-reduced-motion: reduce){
  .ritual__step::before,.ritual__num{transition:none;}
}

/* 14. Ingredients ------------------------------------------------------------------*/
.ingredients__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2.4vw,24px);}
.ingredient-card{position:relative;display:flex;flex-direction:column;gap:16px;transition:transform var(--dur) var(--ease);}
.ingredient-card:hover{transform:perspective(900px) rotateX(var(--tiltX,0deg)) rotateY(var(--tiltY,0deg));}
.ingredient-card .media-slot{
  position:relative;
  transition:transform var(--dur-slow) var(--ease), box-shadow var(--dur-slow) var(--ease);
  box-shadow:var(--shadow-soft);
  border-color:color-mix(in srgb, var(--c-gold) 26%, var(--border));
}
/* lift + tilt into a gold ring on hover (the ring rides on box-shadow, so
   it can't shift layout or fight the tilt transform) */
.ingredient-card:hover .media-slot{
  transform:translateY(-10px) rotate(-1.5deg);
  box-shadow:
    0 26px 54px -20px rgba(23,11,16,.42),
    0 0 0 1.5px color-mix(in srgb, var(--c-gold) 70%, transparent),
    0 0 34px -6px color-mix(in srgb, var(--c-gold) 45%, transparent);
}
/* the photo sits very slightly pulled back and cooled, then blooms to
   full colour as it zooms in — "comes alive when you touch it" */
.ingredient-card .media-slot img{
  transform:scale(1.02);
  filter:saturate(.88) contrast(1.02);
  transition:transform 900ms var(--ease), filter 700ms var(--ease);
}
.ingredient-card:hover .media-slot img{transform:scale(1.12);filter:saturate(1.14) contrast(1.05);}
/* a warm gold wash that keeps four unrelated photos looking like one set;
   lifts on hover so the real photo reads clean. Only while an actual
   photo is there — never over the illustrated fallback. */
.ingredient-card .media-slot:not(.is-empty)::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg, transparent 52%, color-mix(in srgb, var(--c-gold) 34%, transparent));
  opacity:.55;transition:opacity var(--dur) var(--ease);
}
.ingredient-card:hover .media-slot:not(.is-empty)::after{opacity:0;}
/* one-shot light sweep on hover — same move as the glass CTA, never a loop */
.ingredient-card .media-slot::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(115deg, transparent 38%, rgba(255,255,255,.5) 50%, transparent 62%);
  transform:translateX(-140%);
}
.ingredient-card:hover .media-slot::before{animation:ingredientSweep 1s var(--ease);}
@keyframes ingredientSweep{to{transform:translateX(140%);}}
/* Reveal: the card rises (shared card-grid rule further down) WHILE its
   photo resolves out of a blur — staggered across the four by the
   .ingredients__grid nth-child delays. Deliberately no transform here, so
   it can never collide with the hover lift above. */
.ingredient-card[data-reveal] .media-slot{
  filter:blur(12px);opacity:0;
  transition:filter 900ms var(--ease), opacity 900ms var(--ease),
             transform var(--dur-slow) var(--ease), box-shadow var(--dur-slow) var(--ease);
}
.ingredient-card[data-reveal].is-visible .media-slot{filter:blur(0);opacity:1;}
.ingredient-card .media-slot__placeholder svg{animation:ingredientGlow 4s ease-in-out infinite;}
.ingredient-card:nth-child(2) .media-slot__placeholder svg{animation-delay:.5s;}
.ingredient-card:nth-child(3) .media-slot__placeholder svg{animation-delay:1s;}
.ingredient-card:nth-child(4) .media-slot__placeholder svg{animation-delay:1.5s;}
@keyframes ingredientGlow{
  0%,100%{filter:drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 35%, transparent));transform:rotate(0deg);}
  50%{filter:drop-shadow(0 0 12px var(--accent));transform:rotate(3deg);}
}
@media (prefers-reduced-motion: reduce){
  .ingredient-card .media-slot__placeholder svg{animation:none;}
  .ingredient-card:hover .media-slot::before{animation:none;}
  .ingredient-card[data-reveal] .media-slot{filter:none;opacity:1;transition:none;}
}
/* name gets a gold rule that draws itself out under the word on hover */
.ingredient-card h3{font-size:1.05rem;position:relative;align-self:flex-start;}
.ingredient-card h3::after{
  content:"";position:absolute;inset-inline-start:0;bottom:-6px;
  height:2px;width:0;border-radius:2px;
  background:linear-gradient(90deg,var(--c-pink),var(--c-gold));
  transition:width var(--dur) var(--ease);
}
.ingredient-card:hover h3::after{width:100%;}
.ingredient-card p{color:var(--text-muted);font-size:var(--fs-small);}

/* keep this section on the light-mode palette even when the site is in
   dark mode — re-pins every theme-flipping token back to its :root (light)
   value, scoped to #ingredients only. */
:root[data-theme="dark"] #ingredients{
  --bg:#F6EEDC;
  --bg-soft:#EFE1C2;
  --text-strong:#1E1509;
  --text-body:#3D3226;
  --text-muted:#8A7A63;
  --accent:#C9962F;
  --accent-on:#241505;
  --border:rgba(23,11,16,0.1);
  --surface:rgba(255,252,242,0.6);
  --surface-solid:#FBF6EA;
  --shadow-soft:0 24px 60px -24px rgba(23,11,16,0.35);
  --ring:rgba(201,150,47,0.3);
}

/* 15. Offers — the poster presented as a lit 3D object on a stage --------------*/
/* The section itself is the stage: it owns `perspective`, so every
   transform on the card below is a real 3D projection rather than a fake
   skew, and it owns the ambient light. No second blurred copy of the
   artwork as wallpaper any more — the background is pure gradients built
   from the theme tokens, so it follows light/dark automatically and costs
   nothing to paint. */
.offers.section{
  /* One source of truth for the card width, because three other things are
     derived from it: the card itself, the height of the floor reflection,
     and the section's bottom padding. The reflection is position:absolute,
     so it contributes NO height of its own — without the padding below it
     gets sliced in half by this section's own overflow:hidden. */
  --poster-w:min(620px,88vw);
  --refl-h:calc(var(--poster-w) * .40);
  --stage-pad:clamp(56px,10vw,120px);

  position:relative;
  overflow:hidden;
  isolation:isolate;
  perspective:1500px;
  perspective-origin:50% 42%;
  padding-block:var(--stage-pad) calc(var(--stage-pad) + var(--refl-h) + 8px);
  /* The exact cream #ingredients ends on, so the top fade starts from that
     colour instead of briefly revealing the lighter page background as a
     pale stripe. It is --c-blush, NOT --bg-soft: #ingredients is pinned to
     the light palette even in dark mode (see the
     `:root[data-theme="dark"] #ingredients` block above), so --bg-soft
     would flip to #241708 here in dark mode and put a hard step right back
     on the seam. --c-blush is a fixed brand token and matches in both. */
  /* cream only in the top half (the only part ever seen is the top fade,
     matched to #ingredients above); transparent in the bottom half, so the
     bottom fade shows the same page background the testimonials sit on.
     The hard stop in the middle is hidden under the opaque stage. */
  background:linear-gradient(180deg, var(--c-blush) 0 50%, transparent 50% 100%);
}
/* the light itself: a warm gold pool up where the card's top edge is, and
   a deeper berry wash down at the "floor" under the reflection */
/* A deep, warm room with one light in it. Two layers:
     1. a dark berry/black base — the room. Its own mask fades it out to
        nothing at the section's top and bottom edges, so it never ends on
        a hard seam against the cream sections above and below; it reads as
        the page dimming around the offer, not as a pasted dark box.
     2. a gold pool right where the card sits — the light.
   Gold on cream had almost no contrast, which is why the first attempt
   looked like a flat plate; on this base the same gold finally glows.
   Both are token-derived, so dark mode picks them up unchanged. */
.offers::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(54% 40% at 50% 44%, color-mix(in srgb, var(--c-gold) 42%, transparent), transparent 72%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--c-black) 90%, var(--c-berry)),
      color-mix(in srgb, var(--c-black) 74%, var(--c-berry)) 58%,
      var(--inv-bg));
  /* fades in at the top AND out at the bottom: the checkout used to sit
     right below and the stage ran straight into it; now the testimonials
     follow, so it has to dissolve into the page again */
  -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 120px, #000 calc(100% - 130px), transparent 100%);
  mask-image:linear-gradient(180deg, transparent 0, #000 120px, #000 calc(100% - 130px), transparent 100%);
}
/* corner vignette, so the light falls off toward the sides too */
.offers::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(74% 58% at 50% 46%, transparent 46%, rgba(23,11,16,.42));
  -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 120px, #000 calc(100% - 160px), transparent 100%);
  mask-image:linear-gradient(180deg, transparent 0, #000 120px, #000 calc(100% - 160px), transparent 100%);
}

/* ---- the object that tilts ------------------------------------------
   .media-slot is kept ONLY so the existing broken-image → illustrated-
   placeholder fallback (initMediaFallback matches .closest('.media-slot'))
   still applies; everything it adds visually is cancelled here, and
   overflow must be visible so the glow and the floor reflection can spill
   outside the card's own box.
   transform-style:preserve-3d is the important one — it lets the glow sit
   genuinely behind the card and the CTA/sheen genuinely in front of it, so
   the layers slide against each other as it turns. That inter-layer
   parallax is what reads as "3D"; the rotation on its own just looks like
   a squashed rectangle.
   The idle float uses the standalone `translate` property, NOT `transform`,
   precisely so the keyframes and the cursor tilt can coexist on one element
   without overwriting each other. */
.offer-poster.media-slot{
  position:relative;z-index:1;
  width:var(--poster-w);
  margin-inline:auto;
  border:none;border-radius:0;background:none;
  overflow:visible;
  transform-style:preserve-3d;
  transform:rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) scale(var(--pscale,1));
  transition:transform 400ms var(--ease);
  animation:posterFloat 7.5s ease-in-out infinite;
  will-change:transform;
}
/* while the cursor is actually on the card, drop the easing to near-live
   so the tilt tracks the pointer instead of lagging behind it; the 400ms
   above is what makes the *release* glide back smoothly */
.offer-poster.media-slot.is-tilting{transition:transform 90ms linear;}
@keyframes posterFloat{
  0%,100%{translate:0 0;}
  50%{translate:0 -14px;}
}

/* coloured halo, pushed genuinely behind the card in Z */
.offer-poster__glow{
  position:absolute;left:-16%;top:-13%;width:132%;height:126%;
  transform:translateZ(-90px);
  border-radius:50%;
  /* the colour stops fade out early (closest-side, gone by 72%) and the
     blur is wide — that is the difference between a halo and a plate. The
     first version stopped at 78% with only a 40px blur, which left a
     visible hard-ish disc sitting behind the card. */
  background:radial-gradient(closest-side,
    color-mix(in srgb, var(--c-gold) 72%, transparent),
    color-mix(in srgb, var(--c-berry) 34%, transparent) 55%,
    transparent 72%);
  filter:blur(58px);
  opacity:.8;
  transition:opacity var(--dur-slow) var(--ease);
  pointer-events:none;
}
@media (hover: hover) and (pointer: fine){
  .offer-poster:hover .offer-poster__glow{opacity:1;}
}

/* the card body */
.offer-poster__frame{
  position:relative;
  aspect-ratio:1/1;
  border-radius:clamp(20px,3.2vw,34px);
  overflow:hidden;
  border:1px solid color-mix(in srgb, var(--c-gold) 55%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.4),
    0 44px 86px -38px rgba(23,11,16,.6),
    0 20px 44px -28px color-mix(in srgb, var(--c-gold) 65%, transparent);
  transition:box-shadow var(--dur-slow) var(--ease);
}
@media (hover: hover) and (pointer: fine){
.offer-poster:hover .offer-poster__frame{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.5),
    0 58px 100px -40px rgba(23,11,16,.66),
    0 26px 56px -26px color-mix(in srgb, var(--c-gold) 80%, transparent);
}
}
.offer-poster .offer-poster__img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
}

/* spotlight that follows the cursor across the artwork (--mx/--my are
   written by initPosterTilt as percentages) */
.offer-poster__glare{
  position:absolute;inset:0;z-index:3;pointer-events:none;
  background:radial-gradient(30% 30% at var(--mx,50%) var(--my,50%),
    rgba(255,255,255,.30), rgba(255,255,255,.08) 45%, transparent 70%);
  mix-blend-mode:screen;
  opacity:0;
  transition:opacity 320ms var(--ease);
}
@media (hover: hover) and (pointer: fine){
  .offer-poster:hover .offer-poster__glare{opacity:1;}
}

/* a fixed diagonal streak of light that slides the *opposite* way to the
   cursor — the cheap trick that makes flat artwork read as being behind
   glass. --mxn/--myn are the same pointer position as unitless -1..1, so
   they can be multiplied by a px distance here. */
.offer-poster__sheen{
  position:absolute;inset:-30%;z-index:4;pointer-events:none;
  background:linear-gradient(115deg,
    transparent 42%, rgba(255,255,255,.30) 50%, transparent 58%);
  transform:translate3d(calc(var(--mxn,0) * -80px), calc(var(--myn,0) * -80px), 30px);
  opacity:0;
  transition:opacity 320ms var(--ease);
}
@media (hover: hover) and (pointer: fine){
  .offer-poster:hover .offer-poster__sheen{opacity:1;}
}

/* Invisible hit target over the "اطلبيها الآن" button already drawn into
   the poster. Measured, not guessed: a pixel scan of offer-poster.jpg
   (1254×1254) found the solid maroon pill at x=53..460, y=943..1026 —
   i.e. left 4.23%, top 75.2%, width 32.46%, height 6.62%. The values below
   pad that a little so the tap target is forgiving on a phone without
   reaching the icon row above or the delivery line below.
   left/top are deliberately PHYSICAL, not logical (inset-inline-start) —
   the page is RTL but the button is fixed pixels baked into the image, so
   a logical property flips it to the wrong side.
   translateZ lifts it in front of the glare/sheen so it stays clickable,
   and because it rides inside the tilting card the browser maps the
   pointer through the same 3D matrix — it stays glued to the printed
   button at every angle. */
.offer-poster__cta{
  position:absolute;z-index:5;
  left:3.6%;
  top:74.2%;
  width:34%;
  height:8.4%;
  border-radius:999px;
  transform:translateZ(40px);
}
/* a ring that only appears on hover, so the buyer can see the printed
   button is genuinely clickable — never a permanent background animation */
.offer-poster__cta::after{
  content:"";position:absolute;inset:-7px;border-radius:999px;
  border:2px solid color-mix(in srgb, var(--c-gold) 90%, transparent);
  box-shadow:0 0 22px -4px color-mix(in srgb, var(--c-gold) 80%, transparent);
  opacity:0;
  transition:opacity var(--dur) var(--ease);
}
/* Gated behind a real pointer on purpose. A tap on a phone can leave
   :hover stuck on the element, and this rule starts an INFINITE animation —
   on a touch device that would mean a permanently running keyframe nobody
   asked for, which is exactly the class of always-on animation the mobile
   performance pass removed everywhere else. */
@media (hover: hover) and (pointer: fine){
  .offer-poster:hover .offer-poster__cta::after{opacity:1;animation:posterCtaPulse 1.9s ease-out infinite;}
}
@keyframes posterCtaPulse{
  0%{transform:scale(1);opacity:1;}
  70%{transform:scale(1.14);opacity:0;}
  100%{transform:scale(1.14);opacity:0;}
}
.offer-poster__cta:focus-visible{outline:3px solid var(--c-gold);outline-offset:4px;}

/* the floor: the poster mirrored below itself, blurred and faded out.
   scaleY(-1) flips the element in place (its box stays below the card) and
   object-position:50% 100% makes it show the poster's BOTTOM band, so the
   edge touching the card matches the card's real bottom edge. The mask is
   written in local space — "to bottom, opaque at the bottom" — because the
   flip happens after masking, landing the solid end up against the card. */
/* NOTE the doubled-up selector: the base rule `.media-slot img{height:100%}`
   is specificity (0,1,1) and was silently beating a bare `.offer-poster__
   reflection{height:40%}` (0,1,0) — the reflection rendered at the card's
   full 620px instead of a 248px band. */
.offer-poster .offer-poster__reflection{
  position:absolute;left:0;top:calc(100% + 8px);
  width:100%;height:var(--refl-h);
  object-fit:cover;object-position:50% 100%;
  transform:scaleY(-1);
  border-radius:clamp(20px,3.2vw,34px);
  opacity:.22;
  filter:blur(3px);
  -webkit-mask-image:linear-gradient(to bottom, transparent 6%, #000 96%);
  mask-image:linear-gradient(to bottom, transparent 6%, #000 96%);
  pointer-events:none;
}

/* "coming into focus" reveal. These two selectors must out-specify the
   global [data-reveal] / [data-reveal].is-visible translateY rules, which
   would otherwise wipe out the tilt transform above. */
.offer-poster[data-reveal]{
  opacity:0;
  transform:rotateX(9deg) scale(.94);
  transition:opacity 900ms var(--ease), transform 900ms var(--ease);
}
.offer-poster[data-reveal].is-visible{
  opacity:1;
  transform:rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) scale(var(--pscale,1));
}
.offer-poster[data-reveal] .offer-poster__img{
  transform:scale(1.06);filter:blur(16px);
  transition:transform 1100ms var(--ease), filter 1100ms var(--ease);
}
.offer-poster[data-reveal].is-visible .offer-poster__img{transform:scale(1);filter:blur(0);}

/* Touch / small screens: no cursor, so no tilt and no spotlight. The card
   keeps the depth that costs nothing to composite (glow, rim, shadow,
   reflection, float) and drops the blur on the reflection, which is the
   only per-pixel filter in the whole section. */
@media (max-width:860px){
  .offers.section{
    --poster-w:min(620px,92vw);
    --refl-h:calc(var(--poster-w) * .30);
    --stage-pad:clamp(40px,8vw,72px);
    perspective:none;
  }
  .offer-poster.media-slot{animation-duration:9s;}
  .offer-poster__glow{filter:blur(28px);opacity:.62;}
  /* a light 2px blur is kept on phones after all: it is a STATIC filter on
     a 359x108 layer, rasterised once and then only composited (the float
     animates `translate`, which never re-rasterises), and without it the
     mirrored Arabic stays legible enough to read as a glitch rather than a
     reflection. */
  .offer-poster .offer-poster__reflection{filter:blur(2px);opacity:.15;}
}
@media (prefers-reduced-motion: reduce){
  .offer-poster.media-slot{animation:none;transition:none;transform:none;}
  .offer-poster[data-reveal]{opacity:1;transform:none;transition:none;}
  .offer-poster[data-reveal] .offer-poster__img{transform:none;filter:none;transition:none;}
  .offer-poster .offer-poster__cta::after{animation:none;}
}

/* 16. Testimonials — stacked, large video cards (one under another) -----------------*/
.testimonials__grid{display:flex;flex-direction:column;gap:clamp(20px,3vw,28px);max-width:420px;margin-inline:auto;}
.video-testimonial__frame{
  position:relative;aspect-ratio:9/14;border-radius:var(--radius-lg);overflow:hidden;
  background:radial-gradient(120% 90% at 50% 12%, rgba(232,196,104,0.18), transparent 60%), linear-gradient(165deg,var(--bg-soft),var(--bg) 75%);
  border:1px solid var(--border);
  display:flex;align-items:center;justify-content:center;
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.video-testimonial__frame:hover{transform:translateY(-5px);box-shadow:var(--shadow-soft);}
.video-testimonial__media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:1;display:none;background:#000;}
.video-testimonial__frame.is-playing .video-testimonial__media{display:block;}
.video-testimonial__thumb{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;}
.video-testimonial__frame:has(.video-testimonial__thumb)::before{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0.12),rgba(0,0,0,0.5) 75%);z-index:1;}
.video-testimonial__play{position:relative;z-index:2;width:64px;height:64px;border-radius:50%;border:none;padding:0;cursor:pointer;background:var(--accent);color:var(--accent-on);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--glow-pink-lit);transition:transform var(--dur-fast) var(--ease);}
.video-testimonial__play:hover{transform:scale(1.07);}
/* pulsing ring animated via transform+opacity only (compositor-only,
   GPU-cheap) instead of animating box-shadow spread every frame — same
   look, far lighter on mobile. */
.video-testimonial__play::before{
  content:"";position:absolute;inset:0;border-radius:50%;contain:paint;
  border:2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  animation:playPulseRing 2.4s ease-out infinite;
  pointer-events:none;
}
@keyframes playPulseRing{
  0%{transform:scale(1);opacity:.8;}
  70%{transform:scale(1.45);opacity:0;}
  100%{transform:scale(1.45);opacity:0;}
}
@media (prefers-reduced-motion: reduce){ .video-testimonial__play::before{animation:none;opacity:0;} }
.video-testimonial__play:focus-visible{outline:2px solid var(--c-gold);outline-offset:3px;}
.video-testimonial__play svg{width:20px;height:20px;margin-inline-start:3px;}
.video-testimonial__caption{position:absolute;z-index:2;inset-inline:0;bottom:0;padding:28px 16px 18px;text-align:center;font-family:var(--font-heading);font-size:var(--fs-small);color:var(--text-muted);background:linear-gradient(180deg,transparent,rgba(0,0,0,0.06));}
:root[data-theme="dark"] .video-testimonial__caption{background:linear-gradient(180deg,transparent,rgba(0,0,0,0.5));}
.video-testimonial__frame:has(.video-testimonial__thumb) .video-testimonial__caption{color:var(--c-ivory);background:none;}
.video-testimonial__frame.is-playing::before,
.video-testimonial__frame.is-playing .video-testimonial__thumb,
.video-testimonial__frame.is-playing .video-testimonial__play,
.video-testimonial__frame.is-playing .video-testimonial__caption{display:none;}
.testimonial-note{margin-block-start:32px;text-align:center;font-size:var(--fs-small);color:var(--text-muted);border:1px dashed var(--border);border-radius:var(--radius-md);padding:16px;}

/* 17. FAQ -------------------------------------------------------------------------------*/
.faq__list{max-width:800px;margin-inline:auto;}
.faq-item{border-block-end:1px solid var(--border);}
.faq-item:first-child{border-block-start:1px solid var(--border);}
.faq-item__q{width:100%;display:flex;align-items:center;justify-content:space-between;gap:20px;padding-block:22px;text-align:start;font-family:var(--font-heading);font-size:1.02rem;font-weight:700;color:var(--text-strong);}
.faq-item__icon{flex:none;width:28px;height:28px;border-radius:50%;border:1px solid var(--border);display:inline-flex;align-items:center;justify-content:center;color:var(--accent);transition:transform var(--dur) var(--ease);}
.faq-item__icon svg{width:13px;height:13px;}
.faq-item[data-open="true"] .faq-item__icon{transform:rotate(180deg);background:var(--accent);color:var(--accent-on);border-color:var(--accent);}
.faq-item__a{overflow:hidden;max-height:0;transition:max-height var(--dur-slow) var(--ease);}
.faq-item__a-inner{padding-block-end:22px;color:var(--text-muted);max-width:64ch;opacity:0;transform:translateY(-8px);transition:opacity var(--dur) var(--ease), transform var(--dur) var(--ease);}
.faq-item[data-open="true"] .faq-item__a-inner{opacity:1;transform:translateY(0);transition-delay:150ms;}
@media (prefers-reduced-motion: reduce){ .faq-item__a-inner{opacity:1;transform:none;transition:none;} }
.faq-item__a-inner a{color:var(--accent);text-decoration:underline;text-underline-offset:3px;}

/* 18. Checkout -----------------------------------------------------------------------------*/
.checkout{position:relative;overflow:clip;background:var(--inv-bg);color:var(--inv-text);}
.checkout .eyebrow{color:var(--c-pink);}
.checkout .section-title{color:var(--inv-text);}
.checkout .section-lead{color:var(--inv-muted);}

.checkout__panel{
  position:relative;z-index:1;
  overflow:hidden;
  background:rgba(255,249,248,0.08);
  backdrop-filter:blur(30px) saturate(160%);
  -webkit-backdrop-filter:blur(30px) saturate(160%);
  color:var(--inv-text);
  border:1px solid var(--inv-border);
  border-radius:var(--radius-lg);
  padding:clamp(22px,3.4vw,40px);
  box-shadow:var(--shadow-soft-inv);
}

/* A warm gold "golden ticket" band, not the old flat brown-to-black one —
   this sits directly above pack selection, right where a visitor decides
   to order, so it's the one spot on the page allowed to feel genuinely
   festive/inviting rather than moody-luxury. Glossy radial highlight +
   a slow diagonal sheen (::before, dedicated layer so text stays crisp)
   read as foil/metal instead of a flat sticker. */
.checkout__band{
  position:relative;
  overflow:hidden;
  background:
    radial-gradient(130% 180% at 20% -40%, rgba(255,255,255,.4), transparent 55%),
    linear-gradient(135deg, var(--c-gold) 0%, var(--c-pink) 60%, color-mix(in srgb, var(--c-berry) 65%, black) 100%);
  color:#241505;
  text-align:center;
  padding:22px 20px;
  margin:calc(-1 * clamp(22px,3.4vw,40px)) calc(-1 * clamp(22px,3.4vw,40px)) 26px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35), 0 12px 30px -12px color-mix(in srgb, var(--c-gold) 55%, transparent);
}
.checkout__band::before{
  content:"";
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(115deg, transparent 32%, rgba(255,255,255,.55) 50%, transparent 68%);
  transform:translateX(-140%);
  animation:bandSheen 4.5s ease-in-out infinite;
}
@keyframes bandSheen{0%,30%{transform:translateX(-140%);}65%,100%{transform:translateX(140%);}}
@media (prefers-reduced-motion: reduce){ .checkout__band::before{animation:none;display:none;} }
/* The offer, stated as an equation on the gold foil:
     [الزيت الملكي] + [الهيدرولا الطبيعي] = [🎁 شامبو زينة مجاناً]
   The two products you pay for are frosted-white chips; the free one is
   the only DARK chip on the band, so the eye lands on the gift. The band
   is gold in both themes, so none of this changes with dark mode. On a
   phone the "= gift" half drops to its own line as one unit (it is its
   own flex group), never splitting "=" from what it equals. */
.checkout__band-kicker{
  position:relative;z-index:1;
  display:inline-flex;align-items:center;gap:.6em;
  margin-block-end:12px;
  font-family:var(--font-heading);font-weight:800;font-size:.82rem;letter-spacing:.04em;
  color:#3A2208;
}
.checkout__band-orn{font-size:.85em;color:#6B0F2A;}
.checkout__offer{
  position:relative;z-index:1;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:10px;margin:0;
}
.checkout__offer-paid,
.checkout__offer-free{display:inline-flex;align-items:center;gap:10px;}
.checkout__chip{
  display:inline-flex;align-items:center;gap:.4em;
  padding:.5em 1.05em;border-radius:999px;
  font-family:var(--font-heading);font-weight:800;font-size:1.02rem;line-height:1.2;
  white-space:nowrap;
  color:#2A1606;
  background:rgba(255,255,255,.42);
  border:1px solid rgba(255,255,255,.72);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6), 0 6px 16px -10px rgba(60,30,5,.55);
}
.checkout__chip--gift{
  color:#F7E7B4;
  background:linear-gradient(160deg, #7A1631, #4E0A1D);
  border-color:rgba(247,231,180,.45);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18), 0 10px 22px -10px rgba(78,10,29,.75);
}
.checkout__op{
  font-family:var(--font-heading);font-weight:800;font-size:1.5rem;line-height:1;
  color:#3A2208;
}
.checkout__band-price{
  position:relative;z-index:1;
  margin-block-start:12px;
  font-size:var(--fs-small);color:#3A2208;
}
.checkout__band-price s{opacity:.62;margin-inline:.15em;}
.checkout__band-price strong{font-family:var(--font-heading);font-weight:800;font-size:1.15em;color:#2A1606;}
@media (max-width:560px){
  .checkout__chip{font-size:.88rem;padding:.48em .9em;}
  .checkout__op{font-size:1.25rem;}
  .checkout__offer, .checkout__offer-paid, .checkout__offer-free{gap:8px;}
}
/* Brand mark pressed into the gold foil, not sitting on top of it — a
   faint, oversized logo watermark behind the headline. mix-blend-mode
   (not plain opacity alone) is what sells "stuck into the surface": it
   lets the ink darken the gold underneath instead of floating as a flat
   grey layer. The two drop-shadows are a light-catches-the-recessed-edge
   / dark-catches-the-lip trick — the exact same recipe as the title's own
   text-shadow just above, so the mark and the headline read as one
   consistent engraved surface instead of two different treatments. */
.checkout__band-mark{
  position:absolute;top:50%;left:50%;z-index:0;
  width:min(280px,72%);height:auto;
  transform:translate(-50%,-50%) rotate(-5deg);
  opacity:.22;
  mix-blend-mode:overlay;
  filter:drop-shadow(0 1.5px 0 rgba(255,255,255,.5)) drop-shadow(0 -1.5px 1px rgba(0,0,0,.4));
  pointer-events:none;
  user-select:none;
}


/* "توصيل في جميع أنحاء المغرب – الدفع عند الاستلام" — moved down from the
   gold band to close the checkout panel: a full-bleed footer row (the same
   negative-margin trick the band uses at the top), so the reassurance is
   the last thing read right under the order button and the summary. */
.checkout__assure{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px 14px;
  margin:26px calc(-1 * clamp(22px,3.4vw,40px)) calc(-1 * clamp(22px,3.4vw,40px));
  padding:16px 20px;
  border-top:1px solid var(--inv-border);
  background:color-mix(in srgb, var(--c-gold) 6%, transparent);
  font-size:var(--fs-small);
  text-align:center;
}
.checkout__assure-item{display:inline-flex;align-items:center;gap:8px;color:var(--inv-text);font-weight:600;}
.checkout__assure-item svg{width:18px;height:18px;flex:none;color:var(--c-gold);}
.checkout__assure-sep{color:var(--inv-muted);}
@media (max-width:420px){ .checkout__assure-sep{display:none;} }

.checkout__grid{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(24px,4vw,48px);align-items:start;}
.checkout__form h3, .checkout__summary h3{font-size:1.15rem;margin-block-end:18px;color:inherit;display:flex;align-items:center;gap:.6em;}
.checkout__form-icon{width:20px;height:20px;color:var(--c-pink);}
.checkout__form label{color:var(--inv-text);}
.checkout__panel .field input,
.checkout__panel .field textarea{
  background:rgba(255,255,255,0.07);
  border-color:var(--inv-border);
  color:var(--inv-text);
}
.checkout__panel .field input::placeholder,
.checkout__panel .field textarea::placeholder{color:var(--inv-muted);}
.checkout__panel .field input:focus,
.checkout__panel .field textarea:focus{border-color:var(--c-gold);box-shadow:0 0 0 4px rgba(232,196,104,0.25);}
.checkout__panel .field__icon{color:var(--c-pink);}
.checkout__row2{display:grid;grid-template-columns:1fr 1fr;gap:16px;}

.checkout__summary{
  position:sticky;top:calc(var(--header-h) + 20px);
  background:rgba(255,255,255,0.05);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  border-radius:var(--radius-lg);
  padding:clamp(20px,2.6vw,28px);
  border:1px solid var(--inv-border);
}
.summary__product{display:flex;gap:14px;align-items:center;margin-block-end:18px;}
.summary__product .media-slot{width:76px;height:76px;flex:none;border-radius:var(--radius-sm);border-color:var(--inv-border);}
.summary__product-name{font-family:var(--font-heading);font-weight:700;font-size:.98rem;}
.summary__product-offer{font-size:var(--fs-small);color:var(--inv-muted);margin-block-start:4px;}
.summary__qty-row{display:flex;align-items:center;justify-content:space-between;margin-block-end:18px;}
.summary__lines{display:flex;flex-direction:column;gap:10px;padding-block:14px;border-block:1px solid var(--inv-border);}
.summary__line{display:flex;justify-content:space-between;gap:16px;font-size:.92rem;color:var(--inv-muted);}
/* the label never shrinks; a long value (the delivery note) wraps on its own
   side instead of running into the label — it used to read "التوصيلمجاني" */
.summary__line > :first-child{flex:none;}
.summary__line > :last-child{text-align:end;}
.summary__line--total{font-family:var(--font-heading);font-weight:700;font-size:1.15rem;color:var(--inv-text);border-block-start:1px solid var(--inv-border);padding-block-start:14px;margin-block-start:4px;}

.qty-selector{display:inline-flex;align-items:center;border:1px solid var(--inv-border);border-radius:var(--radius-pill);overflow:hidden;}
.qty-btn{width:40px;height:44px;display:inline-flex;align-items:center;justify-content:center;color:var(--inv-text);font-size:1.1rem;transition:background-color var(--dur-fast) var(--ease);}
.qty-btn:hover{background:rgba(255,255,255,0.1);}
.qty-value{min-width:44px;text-align:center;font-family:var(--font-heading);font-weight:700;color:var(--inv-text);}

.cod-badge{display:inline-flex;align-items:center;gap:8px;margin-block-start:18px;padding:.6em 1.1em;border:1px solid var(--c-pink);color:var(--c-pink);border-radius:var(--radius-pill);font-size:var(--fs-small);font-weight:700;}
.cod-note{margin-block-start:10px;font-size:var(--fs-small);color:var(--inv-muted);}

/* Order submit → Telegram: sending state, failure message, honeypot */
#submitOrderBtn .btn-spinner{
  display:none;width:18px;height:18px;border-radius:50%;
  border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  animation:btnSpin .7s linear infinite;
}
#submitOrderBtn.is-loading .btn-spinner{display:inline-block;}
#submitOrderBtn.is-loading .btn-submit-icon{display:none;}
/* while sending: no glow pulse, no hover lift, and the cursor says wait */
#submitOrderBtn.is-loading,
#submitOrderBtn:disabled{cursor:progress;animation:none;transform:none;opacity:.85;}
@keyframes btnSpin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion: reduce){ #submitOrderBtn .btn-spinner{animation-duration:2s;} }

.checkout__send-error{
  margin-block-start:14px;padding:12px 14px;border-radius:14px;
  font-size:var(--fs-small);font-weight:600;line-height:1.7;
  color:var(--c-error);
  background:color-mix(in srgb, var(--c-error) 10%, transparent);
  border:1px solid color-mix(in srgb, var(--c-error) 35%, transparent);
}
.checkout__send-error[hidden]{display:none;}

/* off-screen, NOT display:none — plenty of spam bots skip display:none
   fields on purpose, but still fill one that is merely out of view */
.hp-field{position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden;}

.checkout__success{display:none;text-align:center;padding-block:40px;}
.checkout__success.is-visible{display:block;}
.checkout__success-icon{width:64px;height:64px;margin-inline:auto;border-radius:50%;border:1px solid var(--c-pink);color:var(--c-pink);display:flex;align-items:center;justify-content:center;margin-block-end:20px;box-shadow:var(--glow-pink-lit);}
.checkout__success-icon svg{width:26px;height:26px;}
.checkout__success-check{stroke-dasharray:26;stroke-dashoffset:26;}
.checkout__success.is-visible .checkout__success-icon{animation:successPop .5s var(--ease) both;}
.checkout__success.is-visible .checkout__success-check{animation:successDraw .5s var(--ease) .25s forwards;}
@keyframes successPop{from{transform:scale(.6);opacity:0;}to{transform:scale(1);opacity:1;}}
@keyframes successDraw{to{stroke-dashoffset:0;}}
@media (prefers-reduced-motion: reduce){
  .checkout__success-check{stroke-dashoffset:0;}
  .checkout__success.is-visible .checkout__success-icon,
  .checkout__success.is-visible .checkout__success-check{animation:none;}
}
/* The checkout section is INVERTED (dark in light mode), but h3 and
   .btn-outline both default to the page's normal dark-on-light colours —
   which left the "order received" title and the button nearly invisible,
   dark on dark. Pinned to the inverted palette here. */
.checkout__success h3{font-size:1.4rem;margin-block-end:10px;color:var(--inv-text);}
.checkout__success .btn-outline{
  color:var(--inv-text);
  border-color:color-mix(in srgb, var(--inv-text) 32%, transparent);
}
.checkout__success .btn-outline:hover{background:color-mix(in srgb, var(--c-gold) 18%, transparent);border-color:var(--c-gold);}
.checkout__success-ref{font-family:var(--font-heading);color:var(--c-pink);font-weight:700;letter-spacing:.05em;}
.checkout__success p{color:var(--inv-muted);max-width:48ch;margin-inline:auto;margin-block-start:10px;}
.checkout__success .btn{margin-block-start:24px;}
.checkout__grid.is-hidden{display:none;}

.checkout__mobile-bar{
  display:none;position:fixed;inset-inline:0;bottom:0;z-index:65;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  border-block-start:1px solid var(--border);
  padding:12px var(--container-pad);align-items:center;justify-content:space-between;gap:14px;
  box-shadow:0 -14px 30px -20px rgba(0,0,0,0.35);
  transform:translateY(100%);opacity:0;pointer-events:none;
  transition:transform 420ms var(--ease), opacity 420ms var(--ease);
}
body.checkout-visible .checkout__mobile-bar{transform:translateY(0);opacity:1;pointer-events:auto;}
@media (prefers-reduced-motion: reduce){ .checkout__mobile-bar{transition:none;} }
.checkout__mobile-bar-total{display:flex;flex-direction:column;}
.checkout__mobile-bar-total span:first-child{font-size:var(--fs-micro);color:var(--text-muted);}
.checkout__mobile-bar-total span:last-child{font-family:var(--font-heading);font-weight:700;font-size:1.05rem;color:var(--text-strong);}

/* Same visual language as .checkout__mobile-bar above, one z-index lower
   so the two never compete — body.buybar-visible / .checkout-visible are
   mutually exclusive (see initStickyBars in main.js). Animates in/out via
   transform+opacity (never display, which can't transition) — slides up
   from below and fades in when shown, and slides back down/fades out
   when hidden, instead of snapping on/off instantly. */
.buy-bar{
  display:none;position:fixed;inset-inline:0;bottom:0;z-index:64;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  border-block-start:1px solid var(--border);
  padding:12px var(--container-pad);align-items:center;justify-content:space-between;gap:14px;
  box-shadow:0 -14px 30px -20px rgba(0,0,0,0.35);
  transform:translateY(100%);opacity:0;pointer-events:none;
  transition:transform 420ms var(--ease), opacity 420ms var(--ease);
}
body.buybar-visible .buy-bar{transform:translateY(0);opacity:1;pointer-events:auto;}
@media (prefers-reduced-motion: reduce){ .buy-bar{transition:none;} }
.buy-bar__info{display:flex;flex-direction:column;}
.buy-bar__label{font-size:var(--fs-micro);color:var(--text-muted);}
.buy-bar__price{font-family:var(--font-heading);font-weight:700;font-size:1.05rem;color:var(--text-strong);}

/* 19. Footer + floating WhatsApp ------------------------------------------------------------*/
.site-footer{position:relative;overflow:clip;background:var(--inv-bg);color:var(--inv-text);padding-block:clamp(40px,5vw,60px) 26px;}
.site-footer > .container{position:relative;z-index:1;}
.footer__top{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:clamp(24px,4vw,40px);padding-block-end:34px;border-block-end:1px solid var(--inv-border);}
.footer__brand .brand__logo{height:56px;margin-block-end:16px;}
.footer__brand p{color:var(--inv-muted);max-width:34ch;font-size:var(--fs-small);}
.footer__col h4{font-family:var(--font-heading);font-size:.85rem;letter-spacing:.06em;color:var(--inv-muted);margin-block-end:16px;}
.footer__col ul{display:flex;flex-direction:column;gap:10px;}
.footer__col a, .footer__col span{font-size:.92rem;color:var(--inv-text);}
.footer__social{display:flex;gap:12px;margin-block-start:6px;}
.footer__social a{width:38px;height:38px;border:1px solid var(--inv-border);border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--inv-text);transition:border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);}
.footer__social a:hover{border-color:var(--c-pink);color:var(--c-pink);transform:translateY(-2px);}
.footer__social svg{width:16px;height:16px;}
.footer__bottom{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-block-start:22px;flex-wrap:wrap;}
.footer__bottom p{font-size:var(--fs-micro);color:var(--inv-muted);}

.footer__bottom{justify-content:center;text-align:center;}

.whatsapp-float{
  position:fixed;bottom:24px;right:24px;z-index:90;
  width:58px;height:58px;border-radius:50%;
  background:#25D366;color:#fff;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 14px 34px -10px rgba(37,211,102,0.65);
  transition:transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.whatsapp-float svg{width:28px;height:28px;}
.whatsapp-float:hover{transform:scale(1.08);box-shadow:0 18px 42px -8px rgba(37,211,102,0.75);}
.whatsapp-float:hover::before{animation-play-state:paused;}
/* pulsing ring animated via transform+opacity only (compositor-only) —
   this button never leaves the screen, so its old box-shadow animation
   was repainting every frame for the entire visit; this variant is free. */
.whatsapp-float::before{
  content:"";position:absolute;inset:0;border-radius:50%;contain:paint;
  border:2px solid rgba(37,211,102,0.55);
  animation:waPulse 2.6s ease-in-out infinite;
  pointer-events:none;
}
@keyframes waPulse{
  0%,100%{transform:scale(1);opacity:.7;}
  50%{transform:scale(1.28);opacity:0;}
}
@media (prefers-reduced-motion: reduce){ .whatsapp-float::before{animation:none;opacity:0;} }

/* 20. Scroll reveal & motion --------------------------------------------------------------*/
/* Every [data-reveal] variant below animates ONLY transform + opacity —
   compositor-only properties that never trigger layout or paint — so
   scrolling stays smooth no matter how many elements are revealing at
   once. will-change is applied only while an element is still waiting to
   reveal, then the browser is free to drop that layer once .is-visible
   lands, instead of holding every revealed element on its own layer for
   the rest of the page's life. Four content types get their own restrained
   entrance instead of one generic template effect: headings settle up
   slightly slower and further, body content is a quick understated
   lift, media/product imagery arrives by settling down into its natural
   size, and card grids get a single plain lift with no scale or rotate. */
[data-reveal]{opacity:0;transform:translateY(20px);transition:opacity 750ms var(--ease), transform 750ms var(--ease);}
/* (no will-change here: it held a separate GPU layer for every block still
   waiting below the fold — 25 on the home page. The browser promotes an
   element on its own for the 750ms its transition actually runs.) */
[data-reveal].is-visible{opacity:1;transform:translateY(0);}

/* This page has ~20 different infinitely-looping CSS animations (shiny
   button rims, glow pulses, shimmer sweeps, the marquee, the dev
   signature's aurora ring…) — each cheap on its own, but ALL of them run
   forever, all the time, whether the element is on screen or three
   sections away, permanently competing for the same frame budget as
   whatever the visitor is actually scrolling/swiping (the showcase wheel,
   most of all). initOffscreenAnimationPause() in main.js adds .is-offscreen
   to each owning element the instant it leaves the viewport; this rule
   freezes that element's own animation AND every animation on its
   descendants/pseudo-elements in one shot, and un-freezes the moment it's
   back — same holding pattern [data-reveal] already uses for will-change. */
.is-offscreen,
.is-offscreen::before, .is-offscreen::after,
.is-offscreen *, .is-offscreen *::before, .is-offscreen *::after{
  animation-play-state:paused !important;
}

/* Headings — a touch slower and further than body text, so titles read
   as leading the section in rather than arriving with everything else. */
.section-head[data-reveal]{
  transform:translateY(34px);
  transition:opacity 1000ms var(--ease), transform 1000ms var(--ease);
}
.section-head[data-reveal].is-visible{transform:translateY(0);}

/* The hero title carries its own motion at the word level (see
   .word-reveal below, applied by initWordReveal()) — the container itself
   just fades in quickly rather than also translating, so the two motions
   don't stack into something busier than intended. */
.hero__title[data-reveal]{transform:none;transition:opacity 500ms var(--ease);}
.hero__title[data-reveal].is-visible{transform:none;}
/* Editorial word-by-word reveal — each word sits in a masked box and
   rises into place with a short per-word stagger (set inline by
   initWordReveal()), instead of the headline moving as one solid block.
   Pure transform inside an overflow:hidden mask; scoped to a single,
   tightly-controlled element rather than every heading. */
/* padding-bottom + matching negative margin-bottom: the overflow:hidden
   mask box was clipped exactly tight to the line box, which cut off
   anything sitting below the baseline (e.g. the two dots under ي) — this
   gives the clip region a bit of slack for descenders without pushing
   the title's own line spacing down (the negative margin cancels the
   added height back out). */
.word-reveal{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.5em;margin-bottom:-.5em;}
.word-reveal__inner{display:inline-block;transform:translateY(115%);transition:transform 700ms var(--ease);}
.hero__title.is-visible .word-reveal__inner{transform:translateY(0);}
/* masks released once the words have landed, so the glow isn't boxed in */
.hero__title.words-done .word-reveal{overflow:visible;}
@media (prefers-reduced-motion: reduce){
  .word-reveal{overflow:visible;}
  .word-reveal__inner{transform:none;transition:none;}
}

/* Product imagery — settles into its frame from slightly oversized rather
   than sliding up, reading as "coming into focus" instead of "flying in". */
.hero__media[data-reveal],.ritual__media[data-reveal]{
  transform:scale(1.045);
  transition:opacity 1050ms var(--ease), transform 1050ms var(--ease);
}
.hero__media[data-reveal].is-visible,.ritual__media[data-reveal].is-visible{transform:scale(1);}

/* Card grids — one plain lift-and-fade, no scale, no rotate, no bounce. */
.product-card[data-reveal],.ingredient-card[data-reveal],.video-testimonial[data-reveal]{
  transform:translateY(38px);
  transition:opacity 850ms var(--ease), transform 850ms var(--ease);
}
.product-card[data-reveal].is-visible,.ingredient-card[data-reveal].is-visible,.video-testimonial[data-reveal].is-visible{transform:translateY(0);}

.hero__copy > [data-reveal]:nth-child(1){transition-delay:.05s;}
.hero__copy > [data-reveal]:nth-child(2){transition-delay:.14s;}
.hero__copy > [data-reveal]:nth-child(3){transition-delay:.22s;}
.hero__copy > [data-reveal]:nth-child(4){transition-delay:.30s;}
.hero__copy > [data-reveal]:nth-child(5){transition-delay:.38s;}
.hero__media[data-reveal]{transition-delay:.2s;}
.showcase__grid > [data-reveal]:nth-child(2){transition-delay:.1s;}
.ingredients__grid > [data-reveal]:nth-child(2){transition-delay:.08s;}
.ingredients__grid > [data-reveal]:nth-child(3){transition-delay:.16s;}
.ingredients__grid > [data-reveal]:nth-child(4){transition-delay:.24s;}
.testimonials__grid > [data-reveal]:nth-child(2){transition-delay:.1s;}
.testimonials__grid > [data-reveal]:nth-child(3){transition-delay:.2s;}
.ritual__list > [data-reveal]:nth-child(1){transition-delay:0s;}
.ritual__list > [data-reveal]:nth-child(2){transition-delay:.09s;}
.ritual__list > [data-reveal]:nth-child(3){transition-delay:.18s;}
.ritual__list > [data-reveal]:nth-child(4){transition-delay:.27s;}

/* thin fixed bar at the very top showing scroll progress down the page */
.scroll-progress{
  position:fixed;top:0;inset-inline:0;height:2px;z-index:1000;
  background:var(--accent);
  transform-origin:right;transform:scaleX(0);
  pointer-events:none;
}
@media (prefers-reduced-motion: reduce){ .scroll-progress{display:none;} }

/* Matched selector-for-selector against the rules above (same classes,
   same specificity) so this override actually wins for every reveal
   variant instead of only the generic base rule. */
@media (prefers-reduced-motion: reduce){
  [data-reveal],
  .hero__title[data-reveal],.section-head[data-reveal],
  .hero__media[data-reveal],.ritual__media[data-reveal],
  .product-card[data-reveal],.ingredient-card[data-reveal],.video-testimonial[data-reveal]{
    opacity:1;transform:none;transition:none;
  }
  *{scroll-behavior:auto !important;}
}

/* 21. Responsive ---------------------------------------------------------------------------*/
@media (max-width:1080px){
  .showcase__grid{grid-template-columns:1fr;}
  .ritual__grid{grid-template-columns:1fr;}
  /* Pinning only makes sense in a side-by-side layout; stacked on a
     smaller screen, the photo just scrolls normally — "simplified
     elegantly on mobile" per the brief, not the same effect at a smaller size. */
  .ritual__media{position:static;top:auto;max-width:360px;margin-inline:auto;width:100%;}
  .checkout__grid{grid-template-columns:1fr;}
  .checkout__summary{position:static;}
  .footer__top{grid-template-columns:1fr 1fr;}
  .footer__brand{grid-column:1/-1;}
}

@media (max-width:900px){
  .main-nav{display:none;}
  .site-header__actions .btn.site-header__cta{display:none;}
  .nav-toggle{display:inline-flex;}
  .hero__inner{grid-template-columns:1fr;}
  .hero__copy{max-width:none;order:1;}
  .hero__media{order:0;max-width:340px;margin-inline:auto;width:100%;}
  .hero__float{max-width:240px;}
  .hero__actions{justify-content:flex-start;}
  .benefit-strip__row{grid-template-columns:1fr 1fr;}
  .benefit-strip__item{border-inline-end:none;border-block-end:1px solid var(--border);}
  .benefit-strip__item:nth-child(2n){border-inline-start:1px solid var(--border);}
  .ingredients__grid{grid-template-columns:1fr 1fr;}
  .checkout__row2{grid-template-columns:1fr;}
  /* Always display:flex at this breakpoint now for both bars —
     body.checkout-visible / body.buybar-visible toggle transform/opacity
     (above) to animate each in and out instead of snapping display. */
  .checkout__mobile-bar,.buy-bar{display:flex;}
  .checkout{padding-block-end:112px;}
  .section{padding-block:clamp(48px,10vw,72px);}
  .whatsapp-float{width:52px;height:52px;bottom:calc(18px + env(safe-area-inset-bottom));}
  .whatsapp-float svg{width:25px;height:25px;}

  /* backdrop-filter blur is one of the heaviest things a mobile GPU can be
     asked to do every frame, especially on elements that stay on screen
     while the page scrolls behind them (sticky header, the checkout mobile
     bar). Cut every blur radius down here — same frosted-glass look, far
     less work per frame. */
  :root{--blur:12px;--sat:130%;}
  .site-header{backdrop-filter:blur(12px) saturate(130%);-webkit-backdrop-filter:blur(12px) saturate(130%);}
  .mobile-nav{backdrop-filter:blur(14px) saturate(130%);-webkit-backdrop-filter:blur(14px) saturate(130%);}
  .badge{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);}
  .field input,.field textarea{backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);}
  .ritual__num{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);}
  .checkout__panel{backdrop-filter:blur(14px) saturate(130%);-webkit-backdrop-filter:blur(14px) saturate(130%);}
  .checkout__summary{backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);}
  .checkout__mobile-bar{backdrop-filter:blur(12px) saturate(130%);-webkit-backdrop-filter:blur(12px) saturate(130%);}
  .buy-bar{backdrop-filter:blur(12px) saturate(130%);-webkit-backdrop-filter:blur(12px) saturate(130%);}
}
body.checkout-visible .whatsapp-float,
body.buybar-visible .whatsapp-float{display:none;}

@media (max-width:560px){
  .hero__title{font-size:clamp(2rem,8vw,2.6rem);}
  .ingredients__grid{grid-template-columns:1fr 1fr;gap:12px;}
  .ritual__step{grid-template-columns:56px 1fr;}
  .footer__top{grid-template-columns:1fr;}
  /* bottom room so the copyright line, the last thing on the page, clears
     the fixed WhatsApp float button in the corner when scrolled to the end */
  .footer__bottom{flex-direction:column;align-items:center;padding-block-end:84px;}
}

/* =========================================================================
   PHONES — performance pass
   -------------------------------------------------------------------------
   Measured on a 390px phone viewport (CDP audit) before this block:
     · ~288 MB of GPU texture across 98 composited layers
     · 22 live backdrop-filter blurs — 4 of them on fixed/sticky bars,
       re-blurred on EVERY scroll frame
     · 10 never-ending animations that repaint every frame (text-shadow,
       box-shadow, filter, background-position)
     · blurred layers inside elements that animate forever, so the GPU
       re-ran the blur every frame
   On a weak phone that is the difference between smooth and "the order
   button doesn't respond". Everything below keeps the same LOOK, just
   still / pre-baked. The !importants are deliberate: this is a kill-
   switch that must beat every more-specific rule above it.
   ========================================================================= */
@media (max-width:900px), (pointer:coarse){

  /* 1. No live blur anywhere. Surfaces that relied on the blur for
        readability get a near-opaque background instead. */
  *, *::before, *::after{
    backdrop-filter:none !important;
    -webkit-backdrop-filter:none !important;
  }
  .site-header{background:color-mix(in srgb, var(--bg) 96%, transparent);}
  .mobile-nav{background:var(--bg);}
  .buy-bar, .checkout__mobile-bar{background:color-mix(in srgb, var(--bg) 97%, transparent);}
  .btn-primary{background:linear-gradient(135deg, var(--c-gold), var(--c-berry) 120%);}

  /* 2. Animations that repaint every frame → their resting look */
  .brand__logo{animation:none !important;filter:drop-shadow(0 0 6px color-mix(in srgb, var(--c-gold) 40%, transparent));}
  .glow-text{animation:none !important;text-shadow:0 0 26px var(--glow), 0 0 56px color-mix(in srgb, var(--glow) 55%, transparent);}
  .btn-glow{animation:none !important;box-shadow:inset 0 1px 0 rgba(255,255,255,.55), inset 0 -10px 14px -10px rgba(23,11,16,.35), var(--glow-pink-lit);}
  .btn-confirm-glow span{animation:none !important;}

  /* 3. Blurred layers inside forever-moving elements → plain soft
        gradients (they already fade to transparent, so no hard edge) */
  /* The hero halo leaned on its blur to hide its own edge: the shadow's
     gradient was sized farthest-corner, so it was still visible where
     border-radius cut it off — without the blur that showed as a hard grey
     oval. closest-side makes it reach fully transparent inside the box.
     The conic ring has no soft equivalent, and it can't rotate here anyway,
     so on phones it goes. */
  .hero__float::before{
    filter:none;
    background:radial-gradient(closest-side, var(--c-black) 0%, rgba(23,11,16,0.32) 50%, transparent 100%);
  }
  :root[data-theme="dark"] .hero__float::before{
    background:radial-gradient(closest-side, var(--c-blush) 0%, rgba(239,225,194,0.3) 50%, transparent 100%);
  }
  .hero__float::after{display:none;}
  .offer-poster__glow{
    filter:none !important;
    background:radial-gradient(closest-side,
      color-mix(in srgb, var(--c-gold) 46%, transparent),
      color-mix(in srgb, var(--c-berry) 22%, transparent) 55%,
      transparent 100%);
  }
  .offer-poster .offer-poster__reflection{filter:none;opacity:.1;}

  /* 4. Scroll-in reveals: keep the fade/slide, drop the blur-to-sharp —
        animating filter:blur repaints the whole image every frame */
  .ingredient-card[data-reveal] .media-slot{filter:none;}
  .offer-poster[data-reveal] .offer-poster__img{filter:none;}
}

/* =========================================================================
   Dark mode CTA — light, solid champagne gold
   -------------------------------------------------------------------------
   The glass CTA (.btn-primary, top of this file) is semi-transparent by
   design. On the cream light theme that reads as bright gold; on the dark
   theme the black page showed straight through it and it went muddy
   bronze — with a white label at ~1.6:1 contrast on the gold.
   So dark mode does what dark UIs (and Material's dark-theme guidance) do
   with an accent: the fill goes LIGHTER and OPAQUE and the label goes dark.
   Espresso on champagne gold is ~8–13:1 across the gradient. Opaque also
   means no backdrop blur to pay for. Light mode is untouched.
   ========================================================================= */
:root[data-theme="dark"] .btn-primary,
:root[data-theme="dark"] .showcase__grid.is-carousel .btn-primary{
  color:#1F1206;
  text-shadow:0 1px 0 rgba(255,255,255,.35);
  border:1px solid rgba(255,236,190,.7);
  background:linear-gradient(180deg, #F7E2A4 0%, #E8C468 52%, #D4A84E 100%);
  backdrop-filter:none;-webkit-backdrop-filter:none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.7),
    inset 0 -2px 0 rgba(110,72,18,.22),
    0 12px 30px -12px rgba(232,196,104,.6),
    0 3px 8px -2px rgba(0,0,0,.45);
}
:root[data-theme="dark"] .btn-primary:hover,
:root[data-theme="dark"] .btn-primary:focus-visible{
  background:linear-gradient(180deg, #FBEBBD 0%, #EFCF7C 52%, #DDB45C 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.8),
    inset 0 -2px 0 rgba(110,72,18,.2),
    0 18px 40px -12px rgba(232,196,104,.75),
    0 4px 10px -2px rgba(0,0,0,.5);
}
/* keyboard focus: a visible ring, not just the hover colour */
:root[data-theme="dark"] .btn-primary:focus-visible{outline:2px solid #F7E2A4;outline-offset:3px;}

/* pieces inside the CTAs that were drawn in white for the white label */
:root[data-theme="dark"] .site-header__cta-price{border-inline-start-color:rgba(31,18,6,.3);}
:root[data-theme="dark"] .mobile-nav a.btn-primary{color:#1F1206;}
:root[data-theme="dark"] #submitOrderBtn .btn-spinner{border-color:rgba(31,18,6,.25);border-top-color:#1F1206;}

/* the ambient pulse on the key CTAs (desktop only — phones keep it still)
   keeps these new inset edges instead of the light-mode ones */
:root[data-theme="dark"] .btn-glow{animation-name:btnGlowPulseDark;}
@keyframes btnGlowPulseDark{
  0%,100%{box-shadow:inset 0 1px 0 rgba(255,255,255,.7), inset 0 -2px 0 rgba(110,72,18,.22), 0 12px 30px -12px rgba(232,196,104,.6), 0 3px 8px -2px rgba(0,0,0,.45);}
  50%{box-shadow:inset 0 1px 0 rgba(255,255,255,.7), inset 0 -2px 0 rgba(110,72,18,.22), 0 14px 48px -8px rgba(232,196,104,.85), 0 3px 8px -2px rgba(0,0,0,.45);}
}
