:root{
  --bg-cream:#FFFDF7;--bg-warm:#F9F5EE;--gold:#D1B46D;--gold-dark:#b8994f;
  --text-dark:#333333;--accent-brown:#7D6246;
  --font-serif:"Playfair Display",Georgia,serif;
  --font-sans:"Montserrat",system-ui,sans-serif;
  /* Height the mobile bottom tab bar occupies — 0 on desktop, where it isn't rendered.
     Anything else pinned to the bottom of the viewport (the PDP buy bar, the WhatsApp
     float) offsets by this instead of hardcoding a number, so they stay stacked correctly
     if the bar's height ever changes. Includes the iOS safe-area inset. */
  --bottom-nav-h:0px;
}
/* 59px, not 58: .bn-item is 58px tall and .bottom-nav adds a 1px top border, so the bar really
   occupies 59px. Understating it by that pixel let the buy bar sit over the nav's top border. */
@media(max-width:900px){:root{--bottom-nav-h:calc(59px + env(safe-area-inset-bottom))}}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
/* Guard against any stray element pushing the page wider than the screen (which on
   mobile pushes the navbar icons off-screen and creates a right-side gap). `clip`
   (not `hidden`) so it doesn't create a scroll container and break the sticky header. */
html{overflow-x:clip}
body{max-width:100%;overflow-x:clip}
body{background:var(--bg-cream);color:var(--text-dark);font-family:var(--font-sans);line-height:1.5;-webkit-font-smoothing:antialiased}
/* Keep the end of the page (footer, copyright) reachable above the fixed tab bar. */
@media(max-width:900px){body{padding-bottom:var(--bottom-nav-h)}}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%;height:auto}
button{font-family:inherit;background:none;border:0;cursor:pointer;color:inherit}
ul{list-style:none}
.serif{font-family:emogi}
.container{max-width:1200px;margin:0 auto;padding:0 24px}
/* Same gutter as .container, but no max-width — content spans the full viewport width. */
.container-fluid{width:100%;padding:0 24px}
/* Visually hidden but still read by screen readers and crawlers — used for the homepage
   <h1> when the event banner replaces the hero (that banner's copy is a rotating slider,
   so it can't itself carry the page's single heading). */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

.announce{background:var(--gold);color:#fff;text-align:center;font-size:13px;padding:8px 12px;letter-spacing:.08em}

.header{position:sticky;top:0;z-index:40;background:var(--bg-cream);border-bottom:1px solid rgba(0,0,0,.06);transition:background .3s,box-shadow .3s}
.header.scrolled{background:rgba(255,253,247,.95);backdrop-filter:blur(8px);box-shadow:0 4px 20px rgba(0,0,0,.05)}
/* Only vertical padding here — the `.container` class on the same element supplies the
   horizontal padding. (Using the `padding` shorthand would zero that out, pushing the
   nav icons hard against the screen edge and clipping the cart badge on mobile.) */
.nav{display:flex;align-items:center;justify-content:space-between;padding-top:18px;padding-bottom:18px}
.nav-left{display:flex;align-items:center;gap:16px}
.logo{display:flex;flex-direction:column;align-items:center;line-height:1}
/* Logo images need explicit height + width:auto to beat the global `img{height:auto}`
   reset above (which otherwise ignores the height attribute and blows the logo up). */
.logo img{display:block;width:auto;max-width:none}
.header .logo img{height:42px}
.drawer-head .logo img{height:40px}
footer .logo img{height:54px}
@media(min-width:768px){.header .logo img{height:46px}}
.nav-links{display:none;gap:28px;font-size:16px;letter-spacing:.12em;font-weight:500}
.nav-links a{position:relative;padding:4px 0;color:var(--text-dark);transition:color .3s}
.nav-links a::after{content:"";position:absolute;left:0;bottom:-6px;width:0;height:1px;background:var(--gold);transition:width .35s}
.nav-links a:hover{color:var(--gold)}
.nav-links a:hover::after,.nav-links a.active::after{width:100%}
.nav-links a.active{color:var(--accent-brown)}
.icons{display:flex;align-items:center;gap:20px}
.icons button,.icons a{transition:color .3s;position:relative;display:inline-flex}
.icons button:hover,.icons a:hover{color:var(--gold)}
.bag-count{position:absolute;top:-8px;right:-8px;background:var(--gold);color:#fff;font-size:10px;border-radius:50%;width:16px;height:16px;display:flex;align-items:center;justify-content:center}
.menu-btn{display:inline-flex;padding:4px;transition:color .3s}
.menu-btn:hover{color:var(--gold)}
@media(min-width:1024px){.nav-links{display:flex}.menu-btn{display:none}}

.drawer{position:fixed;inset:0;z-index:50;visibility:hidden;pointer-events:none}
.drawer.open{visibility:visible;pointer-events:auto}
.drawer-back{position:absolute;inset:0;background:rgba(0,0,0,.5);opacity:0;transition:opacity .4s}
.drawer.open .drawer-back{opacity:1}
.drawer-panel{position:absolute;left:0;top:0;height:100%;width:320px;max-width:85%;background:var(--bg-cream);box-shadow:0 20px 50px rgba(0,0,0,.3);padding:32px;transform:translateX(-100%);transition:transform .5s cubic-bezier(.2,.8,.2,1)}
.drawer.open .drawer-panel{transform:translateX(0)}
.drawer-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:40px}
.drawer-close{color:var(--text-dark);transition:color .3s}
.drawer-close:hover{color:var(--gold)}
.drawer ul li{opacity:0;transform:translateX(-16px);transition:all .5s}
.drawer.open ul li{opacity:1;transform:translateX(0)}
.drawer.open ul li:nth-child(1){transition-delay:60ms}
.drawer.open ul li:nth-child(2){transition-delay:120ms}
.drawer.open ul li:nth-child(3){transition-delay:180ms}
.drawer.open ul li:nth-child(4){transition-delay:240ms}
.drawer.open ul li:nth-child(5){transition-delay:300ms}
.drawer.open ul li:nth-child(6){transition-delay:360ms}
.drawer ul li a{display:block;padding:16px 0;border-bottom:1px solid rgba(209,180,109,.2);font-family:var(--font-serif);letter-spacing:.25em;font-size:14px;transition:all .3s}
.drawer ul li a:hover{color:var(--gold);padding-left:8px}
/* When drawer-anim.js takes over, GSAP writes transform/opacity every frame. The CSS
   transitions above would re-animate each of those writes and visibly trail the tween, so they
   are switched off here. The rules themselves stay in place as the no-JS / reduced-motion
   fallback — this class is only added once GSAP is confirmed present. */
.drawer.js-drawer .drawer-back,
.drawer.js-drawer .drawer-panel,
.drawer.js-drawer .drawer-head,
.drawer.js-drawer ul li,
.drawer.js-drawer .drawer-social{transition:none}
/* Promote the panel to its own layer so the slide is composited rather than repainted. */
.drawer.js-drawer .drawer-panel{will-change:transform}
.drawer-social{display:flex;gap:20px;margin-top:40px;color:rgba(51,51,51,.7)}
.drawer-social a:hover{color:var(--gold)}

.hero{background:radial-gradient(600px circle at 20% 30%,rgba(209,180,109,.1),transparent 60%),radial-gradient(500px circle at 80% 70%,rgba(125,98,70,.08),transparent 60%);padding:80px 0}
.hero-grid{display:grid;grid-template-columns:1fr;gap:40px;align-items:center}
@media(min-width:768px){.hero{padding:100px 0}.hero-grid{grid-template-columns:1fr 1fr}}
.tag{display:flex;align-items:center;gap:12px;margin-bottom:24px}
.gold-line{width:40px;height:1px;background:var(--gold);display:inline-block}
.tag span{font-size:12px;letter-spacing:.35em;font-weight:500;color:var(--accent-brown)}
.hero-logo{display:block;width:100%;max-width:360px;height:auto}
@media(min-width:768px){.hero-logo{max-width:460px}}
/* The tagline is the homepage's <h1> (an SEO audit flagged the page as having none — the
   brand name itself is the logo image above, so the tagline is the real page heading).
   It keeps the smaller tagline sizing it has always had; the old 64px/96px `.hero h1`
   rule was left over from a pre-logo design where the brand name was live text. */
.hero h1{font-size:22px;font-weight:400;margin-top:8px;color:var(--accent-brown);letter-spacing:.03em}
/* Each half of the tagline on its own line, per the client. display:block guarantees the split
   at every width — relying on natural wrapping would rejoin them on a wide screen. line-height
   is set here because the h1 inherits a body value tuned for single-line headings, which leaves
   the two lines looking loose once stacked. */
.hero h1 span{display:block;line-height:1.35}
@media(min-width:768px){.hero h1{font-size:32px}}
.hero p{margin-top:24px;max-width:440px;color:rgba(51,51,51,.7);font-size:15px}
.btn-dark{display:inline-block;margin-top:32px;background:var(--text-dark);color:#fff;font-family:var(--font-serif);letter-spacing:.25em;font-size:14px;padding:16px 40px;transition:background .3s}
.btn-dark:hover{background:#000}
.btn-gold{display:inline-block;background:var(--gold);color:#fff;font-family:var(--font-serif);letter-spacing:.25em;font-size:12px;padding:12px 32px;transition:background .3s,letter-spacing .3s}
.btn-gold:hover{background:var(--gold-dark);letter-spacing:.3em}
.btn-outline{display:inline-block;margin-top:32px;background:transparent;color:var(--text-dark);border:1px solid var(--text-dark);border-radius:999px;font-family:var(--font-serif);letter-spacing:.25em;font-size:14px;padding:14px 36px;transition:background .3s,color .3s}
.btn-outline:hover{background:var(--text-dark);color:#fff}
.btn-outline-gold{display:inline-block;text-align: center; background:transparent;color:var(--accent-brown);border:1px solid var(--gold);border-radius:999px;font-family:var(--font-serif);letter-spacing:.25em;font-size:12px;padding: 10px 26px;transition:background .3s,color .3s}
.btn-outline-gold:hover{background:var(--gold);color:#fff}
.hero-img{display:flex;flex-direction:column;align-items:center;gap:22px}
.hero-img > img{max-width:420px;width:100%;filter:drop-shadow(0 25px 40px rgba(0,0,0,.25));animation:floatY 6s ease-in-out infinite}
@keyframes floatY{0%,100%{transform:translateY(0)}50%{transform:translateY(-12px)}}

.hero-slider{position:relative;width:100%;max-width:420px;aspect-ratio:1/1;animation:floatY 6s ease-in-out infinite}
.hero-slider-glow{position:absolute;inset:8%;border-radius:50%;background:radial-gradient(circle,rgba(209,180,109,.35),rgba(209,180,109,0) 70%);filter:blur(14px);z-index:0}
.hero-slide{display:block;position:absolute;inset:0;opacity:0;transform:scale(.96);transition:opacity 1s cubic-bezier(.2,.8,.2,1),transform 1.1s cubic-bezier(.2,.8,.2,1);filter:drop-shadow(0 25px 40px rgba(0,0,0,.25));pointer-events:none;cursor:pointer;z-index:1}
.hero-slide.active{opacity:1;transform:scale(1);pointer-events:auto;z-index:2}
.hero-slide img{width:100%;height:100%;object-fit:contain}
.hero-slide-caption{position:absolute;left:50%;bottom:6px;transform:translateX(-50%);text-align:center;pointer-events:none;background:rgba(255,253,247,.88);backdrop-filter:blur(4px);padding:8px 20px;border-radius:999px;box-shadow:0 8px 20px rgba(0,0,0,.08);white-space:nowrap}
.hero-slide-caption strong{display:block;font-family:var(--font-serif);font-size:14px;letter-spacing:.06em;color:var(--text-dark)}
.hero-slide-caption span{display:block;font-size:11px;color:var(--accent-brown);margin-top:1px}

/* Prev/next arrows */
.hero-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:38px;height:38px;border-radius:50%;background:rgba(255,253,247,.92);backdrop-filter:blur(4px);box-shadow:0 6px 16px rgba(0,0,0,.14);display:flex;align-items:center;justify-content:center;color:var(--text-dark);opacity:0;transition:opacity .3s,background .3s,color .3s}
.hero-slider:hover .hero-arrow,.hero-slider:focus-within .hero-arrow{opacity:1}
.hero-arrow:hover{background:var(--gold);color:#fff}
.hero-arrow.prev{left:-6px}
.hero-arrow.next{right:-6px}
@media(max-width:767px){.hero-arrow{opacity:1;width:32px;height:32px}.hero-arrow.prev{left:-2px}.hero-arrow.next{right:-2px}}

/* Tabs — segmented progress bars under the slider (client's requested "tabs") */
.hero-tabs{display:flex;justify-content:center;gap:8px}
.hero-tab{width:34px;height:5px;border-radius:999px;background:rgba(125,98,70,.18);overflow:hidden;position:relative;padding:0;border:0;cursor:pointer;transition:background .3s,width .3s}
.hero-tab-fill{position:absolute;inset:0;width:0;background:var(--gold);border-radius:999px}
.hero-tab.active{width:44px}
.hero-tab.active .hero-tab-fill{animation:heroTabFill var(--hero-duration,5s) linear forwards}
.hero-tab:not(.active):hover{background:rgba(125,98,70,.32)}
@keyframes heroTabFill{from{width:0}to{width:100%}}
@media(prefers-reduced-motion:reduce){.hero-slider,.hero-img>img{animation:none}.hero-tab.active .hero-tab-fill{animation:none;width:100%}.event-countdown,.pdp-countdown{animation:none}.event-countdown::after,.pdp-countdown::after{display:none}}

/* ---- Mobile hero: product first ----
   On a phone the two-column grid stacks copy-then-image, which pushed the watches below the
   fold — the client only ever saw the wordmark and a paragraph. Here the slider leads, edge to
   edge, and the copy + SHOP NOW sit directly under it. Desktop (>=768px) is untouched. */
@media(max-width:767px){
  /* No top padding: the product should meet the header, not float 80px below it. */
  .hero{padding:0 0 40px}
  .hero-grid{gap:0}
  /* z-index, not just order: flex/grid items paint in order-modified order, so .hero-copy
     (order:2) would otherwise paint over the tabs' enlarged tap area and swallow taps aimed
     just below the bars. */
  .hero .hero-img{order:1;position:relative;z-index:1}
  .hero .hero-copy{order:2;display:flex;flex-direction:column;align-items:center;text-align:center}

  /* Full-bleed out of the container's 24px gutters. Negative margins rather than 100vw, which
     would overflow by the scrollbar width wherever one is actually rendered. */
  .hero .hero-img{margin-left:-24px;margin-right:-24px;padding-top:0;gap:8px}

  /* No float here. On desktop the bob reads as a product hovering on a backdrop; edge to edge
     under a sticky header it just opens and closes an 8px gap at the top and drags the caption
     with it. The image is the hero on mobile, so it holds still. */
  .hero-slider,.hero-img>img{animation:none}

  /* Square, sized by whichever runs out first — the screen's width or 52% of its height. On a
     modern phone the width wins and the image runs edge to edge; on a short one the vh cap
     shrinks it instead of pushing SHOP NOW down behind the fixed bottom nav. */
  .hero-slider,.hero-img>img{width:min(100%,52vh);max-width:none;margin-left:auto;margin-right:auto}

  /* The photo's own backdrop is a different tone from the page, so at full bleed it ends in a
     hard horizontal line. Fading the last few percent lets the product settle onto the page
     instead of sitting in a visible box. Transparent PNGs are unaffected. */
  .hero-slide img,.hero-img>img{
    -webkit-mask-image:linear-gradient(to bottom,#000 90%,transparent 100%);
    mask-image:linear-gradient(to bottom,#000 90%,transparent 100%);
  }

  /* Swipe, autoplay and the tap-through tabs all already move the slider here, so the two
     white discs were only covering the watch. Touch devices get the product back. */
  .hero-arrow{display:none}

  /* Caption moves off the product into a reserved band under it: the pill used to sit across
     the bracelet, hiding the thing it was captioning. The band is held open by margin so the
     tabs can't ride up into it on a slide that has no caption. */
  .hero-slider{margin-bottom:46px}
  .hero-slide-caption{
    left:0;right:0;bottom:-46px;height:46px;transform:none;max-width:none;
    display:flex;flex-direction:column;justify-content:center;
    background:none;box-shadow:none;backdrop-filter:none;padding:0 20px;white-space:normal;
  }
  .hero-slide-caption strong{font-size:15px}
  .hero-slide-caption span{font-size:11.5px;margin-top:2px}

  /* The bars stay slim, but the tappable area around them grows to a thumb-sized target.
     overflow has to be released for that to escape the 5px-tall bar — the fill it was clipping
     carries its own border-radius, so the pill shape survives without it. */
  .hero-tab{overflow:visible}
  .hero-tab::before{content:"";position:absolute;left:-5px;right:-5px;top:-20px;bottom:-20px}

  /* The header carries the wordmark a few pixels above this, so the hero logo drops to a
     supporting size — that, and the paragraph below, is the space the watches gained. */
  .hero-logo{max-width:140px;margin:10px auto 0}
  .hero h1{font-size:18px;margin-top:4px}
  /* Generic marketing filler that was costing ~50px of fold on a phone. The product photo and
     the SHOP NOW button say the same thing better, so it stays desktop-only. */
  .hero p{display:none}
  /* Wider and taller than the desktop pill: the only call to action on the screen, and a
     comfortable thumb target rather than a thin outline. */
  .hero .btn-outline{margin-top:16px;min-width:230px;padding:15px 36px;text-align:center}
}

/* ================= Event hero banner =================
   Replaces the section above while an event is active AND has slides (see
   PageController::home() + pages/home.blade.php). Reuses .hero-arrow/.hero-tabs/
   .hero-tab/.hero-tab-fill as-is (already generic).

   No text, no background gradient — just the photo, full-bleed, with rounded corners
   clipped by .event-hero's own overflow:hidden. Desktop and mobile can use two
   independently-composed images (see the <picture>/<source> markup in the partial + the
   image_mobile column), so each is already framed/cropped correctly for its own screen. */
.event-hero{position:relative;width:100%;overflow:hidden;border-radius:16px;aspect-ratio:16/8}
@media(max-width:767px){.event-hero{aspect-ratio:3/4;border-radius:10px}}
.eh-slide{position:absolute;inset:0;opacity:0;transform:scale(1.03);transition:opacity 1s cubic-bezier(.2,.8,.2,1),transform 1.3s cubic-bezier(.2,.8,.2,1);pointer-events:none}
.eh-slide.active{opacity:1;transform:scale(1);pointer-events:auto;z-index:2}
.eh-slide img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

.event-hero .hero-arrow.prev{left:12px}
.event-hero .hero-arrow.next{right:12px}
.event-hero .hero-tabs{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);z-index:3}
.event-hero .hero-tab{background:rgba(255,255,255,.3)}
.event-hero .hero-tab:not(.active):hover{background:rgba(255,255,255,.5)}
/* Arrows used to be desktop-only here because they collided with the on-image headline —
   now that the photo carries no text, that no longer applies, so mobile keeps them too
   (same always-visible treatment .hero-arrow already gets on the default hero). */
@media(max-width:767px){.event-hero .hero-tabs{bottom:12px}}

.trust{border-top:1px solid rgba(209,180,109,.2);border-bottom:1px solid rgba(209,180,109,.2);padding:40px 0}
.trust-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:32px}
@media(min-width:768px){.trust-grid{grid-template-columns:repeat(4,1fr)}}
.trust-item{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px}
.trust-item svg{color:var(--gold)}
.trust-item .t{font-family:var(--font-serif);letter-spacing:.2em;font-size:14px;margin-top:8px}
.trust-item .d{font-size:12px;color:rgba(51,51,51,.6)}

section.block{padding:80px 0}
.section-title{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:48px}
.section-title span.l{height:1px;width:64px;background:var(--gold)}
.section-title h2{font-size:28px;letter-spacing:.25em;color:var(--text-dark)}
@media(min-width:768px){.section-title h2{font-size:36px}}

.card-img{width:100%;aspect-ratio:1/1;overflow:hidden}
.card-img img{width:100%;height:100%;object-fit:cover;transition:transform .8s cubic-bezier(.2,.8,.2,1)}

/* ================= Shop-by-category cards (modern, full-bleed) =================
   Entrance (fade + rise, staggered) and the hover lift are driven by GSAP/ScrollTrigger
   (see the script at the bottom of pages/home.blade.php) — this file only handles the
   image zoom, gradient overlay and CTA reveal, which are cheap enough as plain CSS
   transitions and don't need a JS timeline. Cards render at full opacity by default
   (GSAP sets the hidden starting state from JS, not CSS) so a script failure or
   prefers-reduced-motion never leaves them stuck invisible. */
.cat-grid-modern{display:grid;grid-template-columns:repeat(1,1fr);gap:16px}
@media(min-width:640px){.cat-grid-modern{gap:20px}}
@media(min-width:1024px){.cat-grid-modern{grid-template-columns:repeat(3,1fr);gap:24px}}

.cat-card-modern{position:relative;display:block;aspect-ratio:3/4;border-radius:16px;overflow:hidden;box-shadow:0 16px 40px -20px rgba(125,98,70,.4)}
.cat-card-img{position:absolute;inset:0}
.cat-card-img img{width:100%;height:100%;object-fit:cover;transition:transform .8s cubic-bezier(.2,.8,.2,1)}
.cat-card-modern:hover .cat-card-img img{transform:scale(1.09)}
.cat-card-overlay{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 35%,rgba(0,0,0,.8) 100%);transition:opacity .4s ease}
.cat-card-modern:hover .cat-card-overlay{opacity:.85}
.cat-card-content{position:absolute;left:0;right:0;bottom:0;padding:18px}
.cat-card-content h3{font-family:var(--font-serif);font-size:16px;letter-spacing:.15em;color:#fff}
@media(min-width:768px){.cat-card-content h3{font-size:21px;letter-spacing:.2em}}
.cat-card-cta{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-family:var(--font-sans);font-size:11px;font-weight:600;letter-spacing:.12em;color:var(--gold);opacity:0;transform:translateY(8px);transition:opacity .4s ease,transform .4s ease}
.cat-card-modern:hover .cat-card-cta{opacity:1;transform:translateY(0)}
.cat-card-cta svg{transition:transform .3s ease}
.cat-card-modern:hover .cat-card-cta svg{transform:translateX(4px)}
@media(max-width:767px){.cat-card-content{padding:14px}.cat-card-cta{font-size:10px}}

.prod-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
@media(min-width:1024px){.prod-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
/* Flex column + `margin-top:auto` on the add-to-cart form pins every CTA to the bottom of its
   card, so buttons stay on one line across a grid row no matter how the content above them
   differs (a product name wrapping to two lines, a missing rating, fewer swatches). Grid
   already stretches cards in a row to equal height, so this just distributes that height. */
.prod{position:relative;display:flex;flex-direction:column;background:var(--bg-warm);padding:20px;border-radius:16px;box-shadow:0 10px 28px -16px rgba(125,98,70,.45),0 2px 6px -3px rgba(0,0,0,.06);transition:transform .5s cubic-bezier(.2,.8,.2,1),box-shadow .5s}
/* The square image must never be squeezed by flex when a card is short on space. */
.prod .card-img{flex:none}
.prod .add-cart-form{margin-top:auto}
.prod:hover{transform:translateY(-8px);box-shadow:0 28px 55px -18px rgba(125,98,70,.5),0 8px 20px -10px rgba(0,0,0,.12)}
.prod .card-img{border-radius:12px}
.prod .badge{z-index:20}
.btn-add-cart{display:block;width:100%;margin-top:14px;padding:10px 12px;border:1px solid var(--text-dark);background:transparent;color:var(--text-dark);border-radius:999px;font-family:var(--font-sans);letter-spacing:.08em;font-weight:600;font-size:11.5px;cursor:pointer;transition:background .3s,color .3s;white-space:nowrap;
  /* The fill is clipped by the button's own rounded box, which is what keeps its corners
     identical to the border's at every frame. isolation:isolate gives the button its own
     stacking context so the fill can never rise above the card's other layers. */
  position:relative;overflow:hidden;isolation:isolate}
/* Plain-CSS fallback: only while JS has NOT taken over (no GSAP, or reduced motion), so the
   two treatments can never both fill the button at once. add-to-cart-fx.js adds .fx-ready. */
.btn-add-cart:not(.fx-ready):hover{background:var(--text-dark);color:#fff}
/* Once JS owns it, kill the CSS transition — otherwise it would re-animate every colour value
   GSAP writes per frame and visibly lag behind the wipe. */
.btn-add-cart.fx-ready{transition:none}
.btn-add-cart .btn-fill{position:absolute;inset:0;background:var(--text-dark);z-index:0;pointer-events:none;will-change:transform}
/* Above the fill, and inline-block so the label can be transformed if ever needed. */
.btn-add-cart .btn-label{position:relative;z-index:1;display:inline-block}
.prod .meta{font-size:12px;color:rgba(51,51,51,.7);letter-spacing:.03em;margin-top:16px}
/* Name and colour on their own lines, each locked to one line so every card in a grid row is
   the same height whatever the name's length. The name is shrunk to fit by the auto-fit pass in
   script.js; nowrap + ellipsis is the floor for a name too long even at the smallest size, and
   is also what a JS-less browser gets. */
.prod .prod-name{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.prod .prod-variant{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:3px;font-size:11px;color:rgba(51,51,51,.5)}
/* min-height keeps the zero-review placeholder (.card-rating--empty, rendered by
   partials/product-card.blade.php) exactly as tall as a real star row, so price/swatches/CTA
   line up between reviewed and unreviewed products in the same grid row. */
.card-rating{display:flex;align-items:center;gap:1px;margin-top:6px;min-height:18px}
.card-rating .star{color:rgba(0,0,0,.18);font-size:12px}
.card-rating .star.on{color:var(--gold)}
.card-rating-count{margin-left:5px;font-size:11px;color:rgba(51,51,51,.55)}
/* Colour-swap stability. Swatch clicks rewrite the price text, and this font renders digits at
   different widths (measured: "111111" 38.9px vs "444444" 69.3px). With the row needing ~224px
   of the 230px a 4-column card allows, simply switching colour could change the text width
   enough to wrap "-10%" onto a second line — which shoved the swatches down 25px and made the
   card visibly jump. tabular-nums forces every digit to one fixed advance width, so a price
   with the same number of digits always occupies exactly the same space no matter its value.
   flex + gap (instead of inline children with margins) then keeps the spacing exact, and the
   min-height reserves the row so nothing below can move even if it ever does wrap. */
.prod .price{font-family:var(--font-sans);font-size:17px;font-weight:600;margin-top:8px;color:var(--accent-brown);
  display:flex;flex-wrap:wrap;align-items:baseline;column-gap:7px;row-gap:2px;min-height:26px;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
/* gap owns the spacing now — clear the inline margins so they don't double up (these beat the
   narrow-screen overrides further down thanks to the extra class in the selector). */
.prod .price .price-old{margin-right:0}
.prod .price .price-discount{margin-left:0;align-self:center}
/* At 4 columns each card gives the price row only ~230px, and the full "was / now / -10%"
   trio needed ~241px — just enough to wrap the badge onto its own line. Shaving a little off
   the supporting elements (the old price and the badge, not the headline price) buys back the
   difference so the whole row fits on one line at this width. Narrower breakpoints keep the
   larger type and simply wrap, which is fine there because it wraps consistently. */
@media(min-width:1024px){
  .prod .price{font-size:16px;column-gap:6px}
  .prod .price .price-old{font-size:12px}
  .prod .price .price-discount{font-size:9.5px;padding:2px 5px}
}
.prod .card-img img{transition:transform .8s cubic-bezier(.2,.8,.2,1)}
.prod:hover .card-img img{transform:scale(1.06)}
.view-all{display:flex;justify-content:center;margin-top:48px}
.view-all .btn-gold{padding:16px 40px;font-size:14px;letter-spacing:.3em}

footer{background:var(--bg-warm);margin-top:40px}
.foot-grid{display:grid;grid-template-columns:1fr;gap:40px;padding-top:64px;padding-bottom:64px}
@media(min-width:768px){.foot-grid{grid-template-columns:repeat(4,1fr)}}
.foot h4{font-family:var(--font-serif);letter-spacing:.2em;font-size:14px;margin-bottom:16px}
.foot ul li{margin-bottom:8px;font-size:14px;color:rgba(51,51,51,.75)}
.foot ul li a{transition:color .3s}
.foot ul li a:hover{color:var(--gold)}
.foot .intro{font-size:14px;color:rgba(51,51,51,.7);max-width:280px;margin-top:16px}
/* Base look for the shared partials/social-links.blade.php icon row — used in the footer,
   the mobile drawer and the contact page's "Follow Us" card. */
.socials{display:flex;gap:16px;color:rgba(51,51,51,.7)}
.socials a{transition:color .3s}
.socials a:hover{color:var(--gold)}
.foot .socials{margin-bottom:32px}
.newsletter{display:flex;background:#fff;margin-top:12px}
.newsletter input{flex:1;padding:12px;border:0;font:inherit;outline:none;font-size:14px}
.newsletter button{padding:0 16px;background:var(--gold);color:#fff;display:inline-flex;align-items:center;justify-content:center;transition:background .3s}
.newsletter button:hover{background:var(--gold-dark)}
.newsletter button:disabled{opacity:.6;cursor:progress}
/* Answer to the signup, shown in place. Reserves no space until it has something to say. */
.newsletter-msg{margin-top:8px;font-size:13px;line-height:1.5;color:var(--accent-brown)}
.newsletter-msg.err{color:#c0392b}
.newsletter-msg[hidden]{display:none}
.copy{background:#fff;text-align:center;padding:16px;font-size:12px;color:rgba(51,51,51,.7)}

@keyframes floatUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}
.floatUp{animation:floatUp .7s ease-out both}
.reveal{opacity:0;transform:translateY(24px);transition:opacity .8s ease,transform .8s ease}
.reveal.on{opacity:1;transform:translateY(0)}

.shop-hero{padding:60px 0 30px;text-align:center}
.shop-hero h1{font-family:var(--font-serif);font-size:44px;letter-spacing:.15em}
.shop-hero p{margin-top:12px;color:rgba(51,51,51,.7)}
.crumbs{padding:16px 0;font-size:12px;letter-spacing:.15em;color:rgba(51,51,51,.6)}
.crumbs a{transition:color .3s}
.crumbs a:hover{color:var(--gold)}
.shop-layout{display:grid;grid-template-columns:1fr;gap:32px;padding-bottom:80px}
.filters{background:var(--bg-warm);padding:24px}
.filters h3{font-family:var(--font-serif);letter-spacing:.2em;font-size:14px;margin-bottom:16px;padding-bottom:8px;border-bottom:1px solid rgba(209,180,109,.3)}
.filter-group{margin-bottom:24px}
.filter-group label{display:flex;align-items:center;gap:8px;padding:6px 0;font-size:14px;cursor:pointer}
.filter-group input[type=range]{width:100%;accent-color:var(--gold)}
.price-out{font-size:13px;color:var(--accent-brown);margin-top:4px}
.shop-toolbar{display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;align-items:center;margin-bottom:24px}
.search{position:relative;flex:1;max-width:320px;min-width:200px}
.search input{width:100%;padding:10px 12px 10px 36px;border:1px solid rgba(0,0,0,.1);background:#fff;font:inherit;font-size:14px;outline:none}
.search input:focus{border-color:var(--gold)}
.search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:rgba(51,51,51,.5)}
.sort{display:flex;gap:8px;align-items:center;font-size:14px}
.sort select{padding:8px 10px;border:1px solid rgba(0,0,0,.1);background:#fff;font:inherit;font-size:14px;outline:none}
.filter-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border:1px solid var(--gold);color:var(--accent-brown);font-size:13px;letter-spacing:.1em;background:#fff}
@media(min-width:1024px){.filter-btn{display:none}}
.filters.desktop{display:none}
@media(min-width:1024px){.filters.desktop{display:block}}
.drawer-filters{position:fixed;inset:0;z-index:60;visibility:hidden;pointer-events:none}
.drawer-filters.open{visibility:visible;pointer-events:auto}
.drawer-filters .back{position:absolute;inset:0;background:rgba(0,0,0,.5);opacity:0;transition:opacity .3s}
.drawer-filters.open .back{opacity:1}
.drawer-filters .panel{position:absolute;right:0;top:0;height:100%;width:320px;max-width:85%;background:var(--bg-cream);padding:24px;overflow-y:auto;transform:translateX(100%);transition:transform .4s}
.drawer-filters.open .panel{transform:translateX(0)}
.count{font-size:13px;color:rgba(51,51,51,.6)}
.badge{position:absolute;top:12px;left:12px;background:var(--gold);color:#fff;font-size:10px;letter-spacing:.15em;padding:4px 8px;z-index:2}
.badge.hot{background:#c0392b}
.badge.sale{background:var(--text-dark)}
.empty{padding:60px 20px;text-align:center;color:rgba(51,51,51,.6);grid-column:1/-1}

/* Discounted pricing (product card) */
.price-old{color:rgba(51,51,51,.5);text-decoration:line-through;font-size:13px;font-weight:400;margin-right:8px;white-space:nowrap}
.price-current{white-space:nowrap}
/* Event-driven discount chip — themed by the running sale's colour (--ec-accent on <body>),
   falling back to the original red when no sale is live. */
.price-discount{display:inline-block;margin-left:8px;background:var(--ec-accent,#c0392b);color:#fff;font-size:10px;letter-spacing:.05em;padding:2px 6px;border-radius:2px;vertical-align:middle;white-space:nowrap}

/* Site-wide event countdown bar — sits above the "Free Delivery" announcement.
   position:relative + overflow:hidden here isn't decorative — the ::after shimmer sweep
   below is absolutely positioned and needs this bar to clip it, or it'd bleed into the
   header underneath. */
/* --ec-accent / --ec-edge come from the active event's admin-picked colour (set inline in
   partials/countdown-bar.blade.php); the fallbacks are the original hardcoded red. */
.event-countdown{position:relative;overflow:hidden;background:linear-gradient(90deg, var(--ec-edge,#211213), var(--ec-accent,#d11805), var(--ec-edge,#1e1314));color:#fff;animation:ecSlideIn .6s cubic-bezier(.2,.8,.2,1) both}
@keyframes ecSlideIn{from{transform:translateY(-100%)}to{transform:translateY(0)}}
/* A soft light sweep drifting across the bar every few seconds — purely ambient, "feels
   alive" rather than static, matching the smooth, low-key motion of the Sveston reference. */
.event-countdown::after{content:"";position:absolute;inset:0;width:35%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.16),transparent);animation:ecShimmer 3.4s ease-in-out infinite;animation-delay:1s;pointer-events:none}
@keyframes ecShimmer{0%{transform:translateX(-120%)}55%,100%{transform:translateX(340%)}}
.event-countdown .ec-inner{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:12px;padding:8px 24px;font-size:13px}
.event-countdown .ec-label{font-weight:700;letter-spacing:.12em}
.event-countdown .ec-timer{display:flex;align-items:center;gap:6px}
.event-countdown .ec-unit{display:inline-flex;flex-direction:column;align-items:center;line-height:1;background:rgba(255,255,255,.14);border-radius:4px;padding:4px 7px;min-width:34px}
.event-countdown .ec-unit b{font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
.event-countdown .ec-unit i{font-style:normal;font-size:8px;letter-spacing:.1em;opacity:.85;margin-top:2px}
.event-countdown .ec-sep{opacity:.6;font-weight:700}
.event-countdown .ec-live{font-size:11px;font-weight:700;letter-spacing:.1em;background:rgba(0,0,0,.25);padding:3px 8px;border-radius:3px}
.event-countdown .ec-off{background:#fff;color:var(--ec-accent,#c0392b);font-weight:700;font-size:12px;letter-spacing:.04em;padding:4px 12px;border-radius:3px}
@media(max-width:560px){
  .event-countdown .ec-inner{gap:6px;padding:7px 10px;font-size:11px}
  .event-countdown .ec-label,.event-countdown .ec-live{display:none}
  .event-countdown .ec-timer{gap:3px}
  .event-countdown .ec-unit{min-width:26px;padding:3px 4px}
  .event-countdown .ec-unit b{font-size:12px}
  .event-countdown .ec-unit i{font-size:7px}
  .event-countdown .ec-off{font-size:11px;padding:3px 8px}
}

/* PDP discount badge next to the price */
.pdp-discount{display:inline-block;margin-left:12px;background:var(--ec-accent,#c0392b);color:#fff;font-size:12px;font-weight:700;letter-spacing:.04em;padding:3px 10px;border-radius:3px;vertical-align:middle;white-space:nowrap}

/* Sale countdown inside the purchase area (see partials/event-timer.blade.php) — a solid
   bar filled with the running sale's colour (--ec-accent on <body>), white text throughout.
   Carries the same motion as the site-wide bar: a smooth entrance plus the drifting light
   sweep. The entrance uses the site's standard rise rather than the top bar's slide-down —
   that one starts off-screen above, which only reads correctly for a bar docked to the very
   top of the page, not one sitting mid-column between the price and the description.
   position:relative + overflow:hidden are load-bearing: they clip the ::after sweep. */
.pdp-countdown{position:relative;overflow:hidden;display:flex;align-items:center;flex-wrap:wrap;gap:6px 16px;margin-top:16px;padding:13px 18px;border-radius:6px;background:var(--ec-accent,#c0392b);color:#fff;animation:floatUp .7s cubic-bezier(.2,.8,.2,1) both}
.pdp-countdown::after{content:"";position:absolute;inset:0;width:35%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.22),transparent);animation:ecShimmer 3.4s ease-in-out infinite;animation-delay:1.2s;pointer-events:none}
.pdp-countdown .pc-off{font-size:17px;font-weight:800;white-space:nowrap}
.pdp-countdown .pc-label{font-size:14px;font-weight:500;opacity:.95;white-space:nowrap}
.pdp-countdown .pc-timer{display:inline-flex;align-items:baseline;gap:2px;font-variant-numeric:tabular-nums}
.pdp-countdown .pc-timer b{font-size:20px;font-weight:700;line-height:1}
.pdp-countdown .pc-timer i{font-style:normal;font-size:12px;font-weight:600;opacity:.85;margin-right:12px}
.pdp-countdown .pc-timer i:last-child{margin-right:0}
@media(max-width:560px){
  .pdp-countdown{padding:11px 14px;gap:4px 10px}
  .pdp-countdown .pc-off{font-size:15px}
  .pdp-countdown .pc-label{font-size:12.5px}
  .pdp-countdown .pc-timer b{font-size:18px}
  .pdp-countdown .pc-timer i{font-size:11px;margin-right:9px}
}
/* Two instances render (see partials/event-timer.blade.php) — old position (after price)
   for desktop, new position (right after the gallery) for mobile. 900px matches .pdp-grid's
   own breakpoint for when the gallery/info columns stack into one. */
@media(max-width:899px){.pdp-countdown--desktop{display:none}}
@media(min-width:900px){.pdp-countdown--mobile{display:none}}

/* Colour swatches — always a single row, never wrapping and never scrolling.
   Wrapping made cards with more colours taller than their grid neighbours (misaligning the
   "ADD TO CART" row); a scroll container was worse — the clipped half-circle plus scrollbar
   read as a broken layout, and a horizontal scroller nested in a vertically-scrolling grid
   is awkward to hit on touch. Instead the card shows the first few colours and collapses
   the remainder into a "+N" chip linking to the PDP (see product-card.blade.php). */
.swatches{display:flex;align-items:center;gap:8px;margin-top:12px;flex-wrap:nowrap}
.swatch{width:20px;height:20px;flex:none;border-radius:50%;background:var(--sw,#ccc);border:0;padding:0;position:relative;cursor:pointer;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.14),0 1px 2px rgba(0,0,0,.07);
  transition:transform .3s cubic-bezier(.2,.8,.2,1),box-shadow .3s}
/* Invisible hit area — widens the tap target to the full gap without shifting layout.
   Sized to the centre-to-centre distance so neighbouring targets never overlap. */
.swatch::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:28px;height:28px;border-radius:50%}
.swatch:hover{transform:translateY(-2px) scale(1.12);box-shadow:inset 0 0 0 1px rgba(0,0,0,.14),0 5px 12px -2px rgba(125,98,70,.45)}
.swatch:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.swatch.active{transform:scale(1.05);box-shadow:inset 0 0 0 1px rgba(0,0,0,.14),0 0 0 2px var(--bg-warm),0 0 0 3px var(--gold)}
/* "+N more colours" chip */
.swatch-more{flex:none;display:inline-flex;align-items:center;justify-content:center;height:20px;min-width:20px;padding:0 7px;border-radius:999px;
  background:rgba(125,98,70,.1);color:var(--accent-brown);font-size:10.5px;font-weight:600;letter-spacing:.02em;line-height:1;white-space:nowrap;
  transition:background .3s,color .3s,transform .3s}
.swatch-more:hover{background:var(--gold);color:#fff;transform:translateY(-2px)}
.swatch-more:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.prod-img{transition:opacity .35s ease}
.prod-img.fading{opacity:0}

/* Tighter product cards on narrow (2-column) mobile widths */
@media(max-width:640px){
  .prod-grid{gap:14px}
  .prod{padding:14px;border-radius:12px}
  .prod .card-img{border-radius:8px}
  .badge{font-size:9px;padding:3px 7px;top:8px;left:8px}
  .prod .meta{font-size:11px;margin-top:12px;line-height:1.4}
  .prod .prod-variant{font-size:10px;margin-top:2px}
  .prod .price{font-size:14.5px;margin-top:6px}
  .prod .price-old{font-size:11px;margin-right:5px}
  .prod .price-discount{font-size:9px;padding:2px 5px;margin-left:5px}
  .swatches{gap:7px;margin-top:10px}
  .swatch{width:18px;height:18px}
  .swatch::after{width:25px;height:25px} /* stays equal to swatch + gap, so targets don't overlap */
  .swatch-more{height:18px;min-width:18px;padding:0 6px;font-size:9.5px}
  .btn-add-cart{margin-top:10px;padding:9px 8px;font-size:10.5px}
}

/* Filter color chips */
.color-filter{display:flex;flex-wrap:wrap;gap:8px}
.color-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px 6px 6px;border:1px solid rgba(0,0,0,.1);background:#fff;border-radius:999px;cursor:pointer;font-size:12px;letter-spacing:.05em;transition:border-color .25s,box-shadow .25s}
.color-chip:hover{border-color:var(--gold)}
.color-chip input{display:none}
.color-chip .chip-sw{width:16px;height:16px;border-radius:50%;border:1px solid rgba(0,0,0,.15);display:inline-block}
.color-chip:has(input:checked){border-color:var(--gold);box-shadow:0 0 0 2px rgba(209,180,109,.25);background:#fff}
.clear-filters{display:block;width:100%;margin-top:8px;padding:10px 14px;border:1px solid var(--gold);color:var(--accent-brown);background:#fff;font-family:var(--font-serif);letter-spacing:.2em;font-size:12px;transition:background .3s,color .3s}
.clear-filters:hover{background:var(--gold);color:#fff}

/* ================= Product Detail Page ================= */
.crumbs{font-size:11px;letter-spacing:.2em;color:var(--accent-brown);padding:20px 0;text-transform:uppercase}
.crumbs a{transition:color .3s}.crumbs a:hover{color:var(--gold)}
.crumbs span{color:var(--text-dark);opacity:.7}

.pdp{padding:20px 24px 80px;max-width:1200px;margin:0 auto}
/* minmax(0,…) + min-width:0 on the items: a bare `1fr` track floors at the item's
   min-content width, so the thumbnail strip (7 × 72px + gaps = 564px) was forcing the
   whole gallery column to 564px on phones. It didn't *look* broken only because
   html{overflow-x:clip} silently cropped it — half the page was simply unreachable. */
.pdp-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:48px}
.pdp-gallery,.pdp-info{min-width:0}
@media(min-width:900px){.pdp-grid{grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:64px}}

/* Slider */
.pdp-slider{position:relative;overflow:hidden;background:var(--bg-warm);border-radius:6px;aspect-ratio:1/1}
.pdp-track{position:relative;width:100%;height:100%}
.pdp-slide{position:absolute;inset:0;opacity:0;transform:scale(1.04);transition:opacity .8s ease,transform 1.2s ease;pointer-events:none}
.pdp-slide.active{opacity:1;transform:scale(1);pointer-events:auto}
.pdp-slide img{width:100%;height:100%;object-fit:cover}
.pdp-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(255,253,247,.85);backdrop-filter:blur(4px);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(0,0,0,.1);transition:all .3s;opacity:0}
.pdp-slider:hover .pdp-nav,.pdp-slider:focus-within .pdp-nav{opacity:1}
/* Touch devices never fire :hover, which left the arrows permanently invisible on phones
   and tablets — show them by default wherever hover isn't available. */
@media(hover:none){.pdp-nav{opacity:1}}
.pdp-nav:hover{background:var(--gold);color:#fff}
.pdp-nav:focus-visible{outline:2px solid var(--gold);outline-offset:2px;opacity:1}
.pdp-nav.prev{left:16px}.pdp-nav.next{right:16px}
.pdp-dots{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:8px}
.pdp-dot{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.6);border:1px solid rgba(0,0,0,.1);transition:all .3s;position:relative}
/* Invisible 24px hit area around each 8px dot so they're tappable without looking heavy. */
.pdp-dot::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:24px;height:24px;border-radius:50%}
.pdp-dot.active{background:var(--gold);width:24px;border-radius:4px}
.pdp-dot:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.pdp-thumbs{display:flex;gap:10px;margin-top:14px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:rgba(209,180,109,.55) transparent}
.pdp-thumbs::-webkit-scrollbar{height:4px}
.pdp-thumbs::-webkit-scrollbar-track{background:transparent}
.pdp-thumbs::-webkit-scrollbar-thumb{background:rgba(209,180,109,.55);border-radius:999px}
.pdp-thumb{flex:0 0 72px;height:72px;border-radius:4px;overflow:hidden;border:2px solid transparent;transition:border-color .3s;background:var(--bg-warm);scroll-snap-align:start;cursor:pointer}
.pdp-thumb.active{border-color:var(--gold)}
.pdp-thumb img{width:100%;height:100%;object-fit:cover}

/* Info */
.pdp-info{display:flex;flex-direction:column;gap:18px}
.pdp-badge{display:inline-block;background:var(--gold);color:#fff;font-size:10px;letter-spacing:.25em;padding:5px 12px;border-radius:2px;align-self:flex-start}
.pdp-title{font-size:34px;line-height:1.15;font-weight:600;color:var(--text-dark)}
@media(min-width:900px){.pdp-title{font-size:42px}}
.pdp-variant{font-size:13px;letter-spacing:.15em;color:var(--accent-brown);text-transform:uppercase}
.pdp-rating{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--accent-brown);text-decoration:none}
.pdp-rating .star{color:rgba(0,0,0,.18);font-size:16px}
.pdp-rating .star.on{color:var(--gold)}
.pdp-price .base-price{font-family:var(--font-sans);font-size:28px;color:var(--text-dark);font-weight:600;white-space:nowrap}
.pdp-price .base-price-old{color:rgba(51,51,51,.5);text-decoration:line-through;font-size:16px;margin-right:10px;white-space:nowrap}
.pdp-desc{font-size:14px;line-height:1.7;color:#555;max-width:520px}
.pdp-label{font-size:11px;letter-spacing:.22em;color:var(--text-dark);text-transform:uppercase;margin-bottom:10px;font-weight:600}
.pdp-block{padding-top:6px}
.pdp-swatches{display:flex;gap:10px;flex-wrap:wrap}
.pdp-swatch{width:34px;height:34px;border-radius:50%;background:var(--sw);border:2px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.15);transition:all .25s;cursor:pointer}
.pdp-swatch:hover{transform:scale(1.1)}
.pdp-swatch.active{box-shadow:0 0 0 2px var(--gold);transform:scale(1.08)}

.qty{display:inline-flex;align-items:center;border:1px solid rgba(0,0,0,.15);border-radius:2px;overflow:hidden}
.qty-btn{width:38px;height:40px;font-size:18px;color:var(--text-dark);transition:background .2s}
.qty-btn:hover{background:var(--bg-warm)}
.qty input{width:52px;height:40px;text-align:center;border:0;border-left:1px solid rgba(0,0,0,.1);border-right:1px solid rgba(0,0,0,.1);font-family:inherit;font-size:14px;background:transparent;-moz-appearance:textfield}
.qty input::-webkit-outer-spin-button,.qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* Add-ons */
.pdp-addons{display:flex;flex-direction:column;gap:10px;margin-top:8px}
.addon{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;padding:14px 16px;border:1px solid rgba(0,0,0,.1);border-radius:4px;cursor:pointer;transition:all .3s;background:#fff}
.addon:hover{border-color:var(--gold);box-shadow:0 4px 14px rgba(209,180,109,.12)}
.addon input{width:18px;height:18px;accent-color:var(--gold);cursor:pointer}
.addon input:checked ~ .addon-body .addon-title{color:var(--gold)}
.addon:has(input:checked){border-color:var(--gold);background:linear-gradient(0deg,rgba(209,180,109,.05),rgba(209,180,109,.05))}
.addon-body{display:flex;flex-direction:column;gap:2px}
.addon-title{font-size:14px;font-weight:600;letter-spacing:.05em;transition:color .3s}
.addon-desc{font-size:12px;color:#777}
.addon-price{font-size:13px;font-weight:600;color:var(--accent-brown);white-space:nowrap}
/* Marks the price as per item, so "+ PKR 200" can't be read as a flat order charge. */
.addon-each{font-size:10.5px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;opacity:.7}

.greeting-panel{padding:16px;background:var(--bg-warm);border-radius:4px;border-left:3px solid var(--gold);animation:slideDown .35s ease}
@keyframes slideDown{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}
.greeting-select,.greeting-msg{width:100%;padding:10px 12px;border:1px solid rgba(0,0,0,.15);border-radius:2px;font-family:inherit;font-size:13px;background:#fff;color:var(--text-dark);transition:border-color .25s}
.greeting-select:focus,.greeting-msg:focus{outline:none;border-color:var(--gold)}
.greeting-msg{min-height:80px;resize:vertical}

/* Total */
.pdp-total{margin-top:8px;padding:18px 20px;background:var(--bg-warm);border-radius:4px}
.pdp-total .row{display:flex;justify-content:space-between;align-items:center;font-size:13px;color:#555;padding:4px 0}
.pdp-total .row.delivery-free span:last-child{color:#1a8a4a;font-weight:600;letter-spacing:.06em}
.pdp-total .row.total{border-top:1px solid rgba(0,0,0,.1);margin-top:8px;padding-top:12px;font-family:var(--font-sans);font-size:20px;color:var(--text-dark);font-weight:600}

/* CTA */
.pdp-cta{display:flex;gap:10px;margin-top:8px}
.btn-primary{flex:1;background:var(--text-dark);color:#fff;padding:16px 28px;font-size:12px;letter-spacing:.25em;font-weight:600;border-radius:2px;transition:all .3s;position:relative;overflow:hidden}
/* GSAP drives transform frame-by-frame on the magnetic CTAs (public/js/magnetic-buttons.js).
   A CSS `transition` covering `transform` would re-animate every one of those writes, smearing
   the pull and fighting the tween — so transitions here are narrowed to the paint-only
   properties, and the :hover/:active transform nudges are dropped (GSAP owns transform). */
[data-magnetic]{transition:background .3s,color .3s,box-shadow .3s,border-color .3s}
[data-magnetic]:hover,[data-magnetic]:active{transform:none}
/* The label is animated separately from its button so the text leads the magnetic pull.
   `transform` has no effect on a plain inline box, hence inline-block; `will-change` promotes
   it to its own layer so the two nested transforms composite instead of repainting. */
[data-magnetic] .btn-label{display:inline-block;will-change:transform}
.btn-primary:hover{background:var(--gold);transform:translateY(-2px);box-shadow:0 10px 24px rgba(209,180,109,.35)}
.btn-secondary{flex:1;background:transparent;color:var(--text-dark);border:1px solid var(--text-dark);padding:16px 28px;font-size:12px;letter-spacing:.25em;font-weight:600;border-radius:2px;transition:all .3s}
.btn-secondary:hover{background:var(--text-dark);color:#fff}

.pdp-trust{display:flex;flex-direction:column;gap:6px;font-size:12px;color:#666;margin-top:8px}

.pdp-related{margin-top:80px}
.pdp-related .section-title{font-size:24px;letter-spacing:.15em;text-align:center;margin-bottom:32px;color:var(--text-dark)}

.pdp-reviews{margin-top:88px}
.pdp-reviews .section-title{font-size:24px;letter-spacing:.15em;text-align:center;margin-bottom:16px;color:var(--text-dark)}

.reviews-summary{display:flex;flex-direction:column;align-items:center;gap:8px;margin:0 auto 44px}
.reviews-summary .avg{font-size:44px;font-weight:700;line-height:1;color:var(--text-dark)}
.reviews-summary .stars .star{color:rgba(0,0,0,.18);font-size:20px}
.reviews-summary .stars .star.on{color:var(--gold)}
.reviews-summary .count{font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--accent-brown)}

/* ---- Customer reviews slider ----
   The viewport clips, the track slides. GSAP animates the track's transform only
   (public/js/reviews-slider.js), so movement stays on the compositor.
   The arrows sit outside the viewport's clip, hence position:relative on the slider itself.
   `--rev-gap` is read back by the JS to work out how far one card-step is, so the gap is
   defined in exactly one place and the two never drift apart. */
.reviews-slider{position:relative;--rev-gap:22px}
.reviews-viewport{overflow:hidden}
/* overflow-x:auto is the no-JS fallback: if the script never runs, this is simply a
   horizontally scrollable row rather than a clipped one with unreachable cards. */
.reviews-track{display:flex;gap:var(--rev-gap);overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.reviews-track::-webkit-scrollbar{display:none}
/* Once JS takes over, the track is transformed instead of scrolled. */
.reviews-slider.is-ready .reviews-track{overflow-x:visible;will-change:transform}
.reviews-track > .review-card{flex:0 0 100%}
@media(min-width:640px){.reviews-track > .review-card{flex-basis:calc((100% - var(--rev-gap)) / 2)}}
@media(min-width:1000px){.reviews-track > .review-card{flex-basis:calc((100% - 2 * var(--rev-gap)) / 3)}}

.rev-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:3;display:none;
  width:42px;height:42px;border-radius:50%;background:var(--bg-cream);color:var(--text-dark);
  border:1px solid rgba(209,180,109,.5);cursor:pointer;align-items:center;justify-content:center;
  box-shadow:0 8px 22px -10px rgba(125,98,70,.55);transition:background .25s,color .25s,opacity .25s}
.reviews-slider.is-ready .rev-arrow{display:flex}
.rev-arrow:hover{background:var(--gold);color:#fff}
.rev-arrow:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.rev-arrow[disabled]{opacity:.32;cursor:default}
.rev-arrow[disabled]:hover{background:var(--bg-cream);color:var(--text-dark)}
.rev-arrow.prev{left:-8px}
.rev-arrow.next{right:-8px}
@media(min-width:1100px){.rev-arrow.prev{left:-22px}.rev-arrow.next{right:-22px}}

.rev-dots{display:none;justify-content:center;gap:8px;margin-top:22px}
.reviews-slider.is-ready .rev-dots{display:flex}
.rev-dot{width:8px;height:8px;padding:0;border:0;border-radius:50%;background:rgba(125,98,70,.28);cursor:pointer;transition:background .3s,width .3s}
.rev-dot.active{background:var(--gold);width:22px;border-radius:999px}
.rev-dot:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

.review-card{background:var(--bg-warm);border-radius:16px;padding:24px;display:flex;flex-direction:column;gap:14px;box-shadow:0 10px 28px -18px rgba(125,98,70,.4);transition:transform .4s cubic-bezier(.2,.8,.2,1),box-shadow .4s}
.review-card:hover{transform:translateY(-5px);box-shadow:0 22px 40px -18px rgba(125,98,70,.45)}
.review-head{display:flex;align-items:center;gap:12px}
.review-avatar{flex-shrink:0;width:40px;height:40px;border-radius:50%;background:var(--gold);color:#fff;display:flex;align-items:center;justify-content:center;font-family:var(--font-serif);font-size:14px;font-weight:700}
.review-head-text{min-width:0;display:flex;flex-direction:column}
.review-name{font-family:var(--font-serif);font-size:15px;letter-spacing:.02em;color:var(--text-dark)}
.review-date{font-size:11.5px;color:rgba(51,51,51,.5);margin-top:2px}
.review-stars .star{color:rgba(0,0,0,.18);font-size:14px}
.review-stars .star.on{color:var(--gold)}
.review-photo-btn{display:block;width:100%;height:170px;border-radius:10px;overflow:hidden;border:0;padding:0;cursor:zoom-in}
.review-photo-btn img{width:100%;height:100%;object-fit:cover;transition:transform .4s}
.review-photo-btn:hover img{transform:scale(1.06)}
.review-body{flex:1;font-size:13.5px;line-height:1.7;color:rgba(51,51,51,.85);margin:0}
.pdp-no-reviews{color:rgba(51,51,51,.6);font-size:14px;text-align:center}

/* Review photo lightbox */
/* ---- Product gallery lightbox ----
   Sits above every fixed thing on the page (bottom nav 44, buy bar 46, header) so the photo
   is the only thing in view. The scrim is a translucent brand brown rather than flat black,
   with the page itself blurred behind it — the surroundings stay recognisable, which is what
   stops a full-screen photo feeling like a page change. */
.pdp-lightbox{position:fixed;inset:0;z-index:210;display:none;align-items:center;justify-content:center;padding:24px;
  /* backdrop-filter has fewer samples to work with right at the element's edge, so page text
     near the viewport bottom stays noticeably crisper than the rest. A slightly heavier scrim
     covers that seam — there is no CSS-side fix for the sampling itself. */
  background:rgba(51,44,34,.64);
  -webkit-backdrop-filter:blur(22px) saturate(115%);backdrop-filter:blur(22px) saturate(115%)}
.pdp-lightbox.open{display:flex}
#pdpLightboxImg{max-width:min(92vw,720px);max-height:82vh;width:auto;border-radius:12px;
  background:var(--bg-cream);box-shadow:0 30px 80px -18px rgba(0,0,0,.55);
  animation:pdpLbIn .32s cubic-bezier(.2,.8,.2,1);
  /* The script owns every gesture on this image (pinch, pan, double-tap), so the browser
     must not also try to scroll or zoom the page from the same fingers. */
  touch-action:none;transform-origin:center center;will-change:transform;
  cursor:zoom-in;-webkit-user-select:none;user-select:none}
.pdp-lightbox.zoomed #pdpLightboxImg{cursor:zoom-out;border-radius:0}
/* Swiping to the next photo is off while zoomed, so the arrows and the counter would only
   get in the way of a close-up. */
.pdp-lightbox.zoomed .pdp-lb-nav,
.pdp-lightbox.zoomed .pdp-lb-count{opacity:0;pointer-events:none;transition:opacity .2s}
@keyframes pdpLbIn{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:scale(1)}}
/* Cream-on-brown controls, so they read as part of the shop rather than a browser chrome. */
.pdp-lb-close,.pdp-lb-nav{position:absolute;display:flex;align-items:center;justify-content:center;
  background:rgba(255,253,247,.9);color:var(--accent-brown);border-radius:50%;
  box-shadow:0 8px 22px -6px rgba(0,0,0,.4);transition:background .25s,color .25s,transform .25s}
.pdp-lb-close:hover,.pdp-lb-nav:hover{background:var(--gold);color:#fff}
.pdp-lb-close{top:20px;right:20px;width:42px;height:42px}
.pdp-lb-nav{top:50%;transform:translateY(-50%);width:46px;height:46px}
.pdp-lb-nav:hover{transform:translateY(-50%) scale(1.06)}
.pdp-lb-nav.prev{left:16px}
.pdp-lb-nav.next{right:16px}
/* Tells a first-time shopper the photo does more than sit there. Touch devices only —
   a mouse gets the same thing from the zoom-in cursor. */
.pdp-lb-hint{position:absolute;top:20px;left:50%;transform:translateX(-50%);
  background:rgba(255,253,247,.9);color:var(--accent-brown);font-size:11.5px;font-weight:600;
  letter-spacing:.06em;padding:6px 14px;border-radius:999px;pointer-events:none;
  white-space:nowrap;max-width:calc(100% - 32px);
  animation:pdpHintFade 3.4s ease forwards}
@keyframes pdpHintFade{0%,70%{opacity:1}100%{opacity:0}}
@media(hover:hover) and (pointer:fine){.pdp-lb-hint{display:none}}
/* animation:none is doing the work — a filled animation outranks a plain opacity
   declaration in the cascade, so without cancelling it the hint stays put while zoomed. */
.pdp-lightbox.zoomed .pdp-lb-hint{animation:none;opacity:0}
.pdp-lb-count{position:absolute;bottom:26px;left:50%;transform:translateX(-50%);
  background:rgba(255,253,247,.9);color:var(--accent-brown);font-size:12.5px;font-weight:600;
  letter-spacing:.08em;padding:7px 16px;border-radius:999px}
/* The gallery image is the thing you tap, so say so. */
.pdp-slide img{cursor:zoom-in}
@media(max-width:640px){
  .pdp-lightbox{padding:16px}
  .pdp-lb-nav{width:40px;height:40px}
  .pdp-lb-nav.prev{left:8px}
  .pdp-lb-nav.next{right:8px}
  .pdp-lb-close{top:14px;right:14px}
}
/* The shop chrome steps aside while the viewer is open. Not only for focus: .bottom-nav sets
   its own backdrop-filter, which makes it a backdrop root of its own — so the lightbox's blur
   never reached it and the tab labels stayed razor sharp over a blurred page, which read as a
   rendering fault rather than a design. */
body.pdp-lightbox-on .bottom-nav,
body.pdp-lightbox-on .buy-bar,
body.pdp-lightbox-on .whatsapp-float{opacity:0;pointer-events:none;transition:opacity .2s}
@media(prefers-reduced-motion:reduce){#pdpLightboxImg{animation:none}}

.lightbox{position:fixed;inset:0;background:rgba(0,0,0,.88);z-index:200;display:none;align-items:center;justify-content:center;padding:24px}
.lightbox.open{display:flex}
.lightbox img{max-width:90vw;max-height:85vh;border-radius:8px;box-shadow:0 20px 60px rgba(0,0,0,.5)}
.lightbox-close{position:absolute;top:20px;right:24px;color:#fff;font-size:20px;background:rgba(255,255,255,.12);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:background .2s}
.lightbox-close:hover{background:rgba(255,255,255,.24)}

/* ---- Sticky mobile "Buy it now" bar (product detail page) ----
   Hidden by default and on desktop; script.js reveals it once the shopper reaches the
   inline CTA. Stacks directly on top of the bottom tab bar (hence the --bottom-nav-h
   offset rather than bottom:0) so the two never overlap; the tab bar owns the safe-area
   inset, so this one doesn't add it again. */
.buy-bar{position:fixed;left:0;right:0;bottom:var(--bottom-nav-h);z-index:46;display:none;
  padding:0 12px 12px;
  /* Only the pill inside takes taps — the transparent gutter around it must not swallow
     clicks meant for the page behind. */
  pointer-events:none;
  /* To hide, the bar must travel its own height AND clear the --bottom-nav-h offset it sits
     on — otherwise it stops short and leaves a strip parked over the tab bar. translateY(110%)
     only moved it 110% of its own height, so ~50px stayed on screen: that strip both looked
     like a half-drawn buy bar and, at z-index 46 over the nav's 44, hid the tab bar entirely.
     Adding the offset makes the hidden position exactly the bottom edge of the viewport. */
  transform:translateY(calc(100% + var(--bottom-nav-h)));transition:transform .35s cubic-bezier(.2,.8,.2,1)}
.buy-bar.show{transform:translateY(0)}
/* One dark pill holding both halves, rather than a light tray with two separate controls:
   price on the left in gold, the action filling the rest. Product name is deliberately absent
   — the shopper scrolled past it to get here. */
.buy-bar-inner{display:flex;align-items:center;pointer-events:auto;
  background:#0000008c;border:1px solid rgba(209,180,109,.45);border-radius:999px;
  /* The body is translucent, so whatever is scrolling underneath would otherwise read straight
     through the bar. Blurring the backdrop keeps the price legible over any product photo. */
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  /* Asymmetric on purpose. The bar's right end is a semicircle (radius = half its height), so a
     square-cornered button flush at 5px would push its corners straight through that arc. The
     corner sits 22.5px off the vertical centre, where the arc is only ~15.8px wide, so the
     button has to stop ~12px short of the edge to stay inside it. The left end needs no such
     clearance — the price is plain text, not a box. */
  padding:5px 13px 5px 5px;box-shadow:0 14px 34px -10px rgba(0,0,0,.5)}
/* Price sits on the bar itself — no pill of its own. Giving it a filled background made it
   compete with the action beside it, and the thing that should look pressable is the button. */
.buy-bar-price{flex:none;background:none;color:#fff;
  font-family:var(--font-sans);font-size:15px;font-weight:700;white-space:nowrap;
  /* Prices change with the colour swatch, so the bar must not resize as digits swap. */
  font-variant-numeric:tabular-nums;
  padding:0 14px 0 18px}
/* The one thing to press: a solid square-cornered block filling the rest of the bar. */
.buy-bar-btn{flex:1;background:#0c0d0b;color:#fff;border:0;border-radius:0;
  padding:14px 16px;font-family:var(--font-sans);font-size:12.5px;font-weight:700;letter-spacing:.14em;
  white-space:nowrap;cursor:pointer;transition:background .3s,color .3s,transform .3s}
/* The bar is mobile-only, so hover barely applies — but focus still needs to be visible, and
   gold is the theme's focus colour everywhere else. */
.buy-bar-btn:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.buy-bar-btn:active{transform:scale(.97)}
.buy-bar-btn:disabled{opacity:.65}
@media(max-width:900px){.buy-bar{display:block}}
@media(max-width:360px){
  .buy-bar-price{font-size:13.5px;padding:0 10px 0 14px}
  .buy-bar-btn{font-size:11.5px;letter-spacing:.1em;padding:13px 10px}
}
/* Keep the floating WhatsApp button clear of the bar while it's on screen. */
body.buy-bar-on .whatsapp-float{transform:translateY(-64px)}

/* ---- Product detail page: phone tuning ----
   Reclaims horizontal room (narrower gutters, smaller thumbs) and stops the two CTA
   buttons wrapping their labels onto a second line inside a ~130px column. */
@media(max-width:640px){
  .pdp{padding:12px 16px 56px}
  .pdp-grid{gap:32px}
  .pdp-title{font-size:26px}
  .pdp-info{gap:14px}
  .pdp-price .base-price{font-size:24px}
  .pdp-price .base-price-old{font-size:14px;margin-right:7px}
  .pdp-discount{font-size:11px;padding:2px 8px;margin-left:8px}
  .pdp-thumbs{gap:8px;margin-top:10px}
  .pdp-thumb{flex:0 0 56px;height:56px}
  .pdp-nav{width:34px;height:34px}
  .pdp-nav.prev{left:10px}.pdp-nav.next{right:10px}
  .pdp-swatch{width:30px;height:30px}
  .pdp-total{padding:14px 16px}
  .pdp-total .row.total{font-size:18px}
  .addon{padding:12px 14px;gap:10px}
  .addon-title{font-size:13px}
  .addon-desc{font-size:11.5px}
  /* Tighter type/padding so both labels stay on one line side by side. */
  .pdp-cta{gap:8px}
  .pdp-cta .btn-primary,.pdp-cta .btn-secondary{padding:15px 10px;font-size:11px;letter-spacing:.1em;white-space:nowrap}
  .pdp-related,.pdp-reviews{margin-top:56px}
  .pdp-related .section-title,.pdp-reviews .section-title{font-size:19px;letter-spacing:.1em}
  .reviews-summary{margin-bottom:28px}
  .reviews-summary .avg{font-size:36px}
  .review-card{padding:18px;border-radius:12px;gap:12px}
  .review-photo-btn{height:150px}
}

/* Product card link */
.prod{position:relative}
.prod-link{position:absolute;inset:0;z-index:1}
/* z-index only takes effect on a positioned element — without `position:relative` here,
   this rule was a no-op and .prod-link (position:absolute, z-index:1) silently won the
   stacking fight, swallowing every click on the swatches/add-to-cart controls underneath
   it and sending the shopper to the PDP instead (the colour-swap bug).
   .badge is deliberately NOT in this list: it's already position:absolute (top/left 12px,
   overlaying the image corner) with z-index:20, so it clears .prod-link on its own. Adding
   it here overrode that absolute positioning with relative — dropping the badge into normal
   flow above the image and shoving the rest of the card down. */
.prod .swatches,.prod .add-cart-form{position:relative;z-index:2}

/* Add-to-bag toast */
.cart-toast{position:fixed;right:20px;bottom:20px;z-index:200;background:var(--text-dark);color:#fff;padding:14px 20px;font-size:14px;letter-spacing:.03em;border-radius:4px;box-shadow:0 12px 30px rgba(0,0,0,.25);opacity:0;transform:translateY(16px);transition:opacity .3s,transform .3s;pointer-events:none;max-width:320px}
.cart-toast.show{opacity:1;transform:translateY(0)}
.cart-toast::before{content:"✓ ";color:var(--gold);font-weight:700}
.prod .meta a{transition:color .3s}
.prod .meta a:hover{color:var(--gold)}

/* ============ Video Showcase ============ */
.video-showcase{padding:80px 0;background:var(--bg-cream)}
.vs-head{display:flex;flex-direction:column;align-items:center;text-align:center;margin-bottom:40px}
.vs-head h2{font-size:clamp(24px,3vw,36px);letter-spacing:.25em;color:var(--text-dark)}
.vs-line{display:block;width:96px;height:1px;background:var(--gold);margin:16px 0}
.vs-head p{max-width:440px;font-size:14px;color:rgba(51,51,51,.6)}
.reels-row{display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;padding-bottom:12px}
.reel-card{position:relative;flex:0 0 70vw;aspect-ratio:9/16;border-radius:12px;overflow:hidden;background:#000;scroll-snap-align:start;transition:transform .3s ease,box-shadow .3s ease,outline-color .3s ease;outline:1px solid transparent}
.reel-card:hover{transform:scale(1.03);box-shadow:0 10px 40px -10px rgba(209,180,109,.55);outline-color:var(--gold)}
.reel-card video{width:100%;height:100%;object-fit:cover;display:block}
.reel-mute{position:absolute;top:12px;right:12px;width:36px;height:36px;display:grid;place-items:center;border-radius:999px;border:1px solid rgba(255,255,255,.7);background:rgba(0,0,0,.25);backdrop-filter:blur(4px);color:#fff;transition:color .3s,border-color .3s}
.reel-mute:hover{color:var(--gold);border-color:var(--gold)}
.reel-mute .mute-x{display:block}
.reel-mute.on .mute-x{display:none}
.reel-tag{position:absolute;left:12px;right:12px;bottom:12px;text-align:center;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#fff;background:rgba(0,0,0,.45);backdrop-filter:blur(4px);border:1px solid rgba(209,180,109,.6);border-radius:999px;padding:8px 12px}
@media(min-width:640px){.reel-card{flex-basis:42vw}}
@media(min-width:768px){.reel-card{flex-basis:28vw}.reels-row{overflow:visible}}
@media(min-width:1024px){.reel-card{flex-basis:19%}}

/* ---- Static content / trust pages (about, contact, faq, legal) ---- */
.content-page{max-width:820px;padding-top:20px;padding-bottom:72px}
.content-hero{text-align:center;margin-bottom:36px;padding-bottom:24px;border-bottom:1px solid rgba(209,180,109,.3)}
.content-hero h1{font-size:34px;letter-spacing:.08em;color:var(--text-dark)}
@media(min-width:768px){.content-hero h1{font-size:44px}}
.content-hero .lead{margin-top:12px;color:var(--accent-brown);font-size:15px;letter-spacing:.03em}
/* "3bLegacy" colour-split to match the logo (gold 3B, dark Legacy) instead of flat text */
.brand-name{white-space:nowrap}
.brand-name .bn-3b{color:var(--gold-dark)}
.brand-name .bn-legacy{color:var(--text-dark)}
.content-page h2{font-size:22px;letter-spacing:.02em;margin:32px 0 12px;color:var(--text-dark)}
.content-page p{color:rgba(51,51,51,.82);font-size:15.5px;line-height:1.8;margin-bottom:14px}
.content-page a{color:var(--accent-brown);}
.content-list{margin:8px 0 18px;padding-left:22px}
.content-list li{color:rgba(51,51,51,.82);font-size:15px;line-height:1.9;margin-bottom:6px}
.promise-list{list-style:none;margin:8px 0 18px;padding:0;display:flex;flex-direction:column;gap:10px}
.promise-list li{display:flex;align-items:center;gap:12px;color:rgba(51,51,51,.85);font-size:15px;font-weight:500}
.promise-list li::before{content:"✓";flex:none;width:22px;height:22px;border-radius:50%;background:rgba(209,180,109,.15);color:var(--gold-dark);font-weight:700;font-size:12px;display:flex;align-items:center;justify-content:center}
.content-cta{display:flex;flex-wrap:wrap;gap:14px;margin-top:40px;padding-top:28px;border-top:1px solid rgba(0,0,0,.08)}
.content-cta .btn-outline,.content-cta .btn-outline-gold{margin-top:0}

/* Shop supporting copy (below the grid) */
.shop-copy{margin-top:56px;padding-top:32px;border-top:1px solid rgba(0,0,0,.08)}
.shop-copy h2{font-size:20px;letter-spacing:.04em;margin-bottom:12px}
.shop-copy p{color:rgba(51,51,51,.7);font-size:14.5px;line-height:1.8;max-width:820px}

/* FAQ accordion */
.faq-list{display:flex;flex-direction:column;gap:12px}
.faq-item{border:1px solid rgba(0,0,0,.1);border-radius:10px;padding:4px 20px;background:#fff}
.faq-item summary{cursor:pointer;font-family:var(--font-serif);font-size:16px;padding:16px 0;list-style:none;position:relative;color:var(--text-dark)}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:"+";position:absolute;right:0;top:14px;font-size:22px;color:var(--gold);transition:transform .25s}
.faq-item[open] summary::after{transform:rotate(45deg)}
.faq-item p{padding:0 0 16px;margin:0;color:rgba(51,51,51,.78);font-size:15px;line-height:1.75}

/* Contact */
.contact-grid{display:grid;grid-template-columns:1fr;gap:20px;margin:8px 0 20px}
@media(min-width:640px){.contact-grid{grid-template-columns:1fr 1fr}}
.contact-card{background:var(--bg-warm);border:1px solid rgba(209,180,109,.25);border-radius:10px;padding:24px}
.contact-card h2{margin-top:0;font-size:18px}
.contact-form{max-width:560px;margin-top:8px}
.cf-row{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}
.cf-row label{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--accent-brown);font-weight:600}
.cf-row input,.cf-row textarea{padding:12px 14px;border:1px solid rgba(0,0,0,.15);border-radius:6px;font:inherit;font-size:15px;outline:none;transition:border-color .2s}
.cf-row input:focus,.cf-row textarea:focus{border-color:var(--gold)}
.contact-form .btn-primary{padding:14px 30px;font-size:12px;letter-spacing:.2em}
.contact-flash{padding:14px 18px;border-radius:8px;font-size:14.5px;margin-bottom:20px;max-width:560px}
.contact-flash.ok{background:rgba(26,138,74,.1);border:1px solid rgba(26,138,74,.35);color:#1a8a4a}
.cf-err{font-size:12.5px;color:#c0392b;margin-top:2px}

/* Site search — header overlay */
.search-overlay{position:fixed;inset:0;z-index:70;visibility:hidden;pointer-events:none}
.search-overlay.open{visibility:visible;pointer-events:auto}
.search-overlay-back{position:absolute;inset:0;background:rgba(51,41,20,.55);opacity:0;transition:opacity .35s}
.search-overlay.open .search-overlay-back{opacity:1}
.search-overlay-panel{position:absolute;left:0;right:0;top:0;background:var(--bg-cream);padding:80px 20px 30px;box-shadow:0 20px 50px rgba(0,0,0,.25);transform:translateY(-100%);transition:transform .45s cubic-bezier(.2,.8,.2,1)}
.search-overlay.open .search-overlay-panel{transform:translateY(0)}
.search-overlay-form{max-width:720px;margin:0 auto;display:flex;align-items:center;gap:14px;border-bottom:2px solid var(--gold);padding-bottom:14px}
.search-overlay-form svg{flex:none;color:var(--accent-brown)}
.search-overlay-form input{flex:1;min-width:0;border:0;background:transparent;font:inherit;font-size:16px;font-family:var(--font-serif);color:var(--text-dark);outline:none}
.search-overlay-submit{flex:none;background:var(--text-dark);color:#fff;border:0;padding:12px 16px;font-family:var(--font-sans);letter-spacing:.1em;font-weight:600;font-size:11px;white-space:nowrap;cursor:pointer;transition:background .3s}
.search-overlay-submit:hover{background:var(--gold)}
.search-overlay-close{position:absolute;top:28px;right:24px;color:var(--text-dark);transition:color .3s}
.search-overlay-close:hover{color:var(--gold)}

/* ---- Type-ahead suggestions ----
   Sits in the panel's flow under the input rather than floating over the page: the panel is
   already an overlay that slides down, so a second layer on top of it would need its own
   z-index and stacking rules for no gain. */
.search-suggest{max-width:720px;margin:0 auto;padding:8px 0 0}
.search-suggest[hidden]{display:none}
.ss-item{display:flex;align-items:center;gap:14px;width:100%;padding:10px 10px;border-radius:10px;
  text-align:left;color:inherit;transition:background .18s}
.ss-item + .ss-item{margin-top:2px}
/* One highlight class for both hover and keyboard, so arrowing through the list looks
   identical to running the mouse down it. */
.ss-item:hover,.ss-item.is-active{background:rgba(209,180,109,.16)}
.ss-item img{flex:none;width:48px;height:48px;object-fit:cover;border-radius:8px;background:var(--bg-warm)}
.ss-body{flex:1;min-width:0}
/* display:block on both: they are spans (an <a> can't hold block-level children in valid
   HTML5 flow, but inline-by-default meant the name and the meta line ran together as one
   string), and text-overflow:ellipsis needs a block box to clip against anyway. */
.ss-name{display:block;font-family:var(--font-serif);font-size:14.5px;color:var(--text-dark);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The matched run of characters, so it is obvious why a row is being offered. */
.ss-name mark{background:none;color:var(--gold-dark);font-weight:700;padding:0}
.ss-meta{display:block;font-size:11.5px;color:rgba(51,51,51,.55);letter-spacing:.03em;margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-price{flex:none;font-size:13.5px;font-weight:700;color:var(--accent-brown);white-space:nowrap;
  font-variant-numeric:tabular-nums}
.ss-price .ss-old{display:block;font-size:11px;font-weight:500;color:rgba(51,51,51,.4);text-decoration:line-through}
/* Last row: hand the raw term to the full results page. */
.ss-all{display:block;width:100%;text-align:center;padding:12px 10px;margin-top:6px;
  border-top:1px solid rgba(209,180,109,.3);
  font-size:12px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--accent-brown);transition:color .2s,background .18s;border-radius:0 0 10px 10px}
.ss-all:hover,.ss-all.is-active{background:rgba(209,180,109,.16);color:var(--gold-dark)}
.ss-empty{padding:18px 10px;text-align:center;font-size:13.5px;color:rgba(51,51,51,.55)}
/* Same row as the empty state, gently pulsing so a slow reply still reads as "working". */
.ss-busy{animation:ssPulse 1.1s ease-in-out infinite}
@keyframes ssPulse{0%,100%{opacity:.45}50%{opacity:.9}}
@media(prefers-reduced-motion:reduce){.ss-busy{animation:none}}
@media(max-width:640px){
  .search-suggest{max-height:52vh;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .ss-item img{width:42px;height:42px}
  .ss-name{font-size:13.5px}
  .ss-price{font-size:12.5px}
}

/* Site search — results page */
.search-results-page{padding-bottom:80px}
.search-page-form{display:flex;gap:12px;max-width:560px;margin:0 auto 40px}
.search-page-form input{flex:1;padding:14px 18px;border:1px solid rgba(0,0,0,.15);border-radius:6px;font:inherit;font-size:15px;outline:none;transition:border-color .2s}
.search-page-form input:focus{border-color:var(--gold)}
.search-empty{text-align:center;padding:40px 20px}
.search-empty p{color:rgba(51,51,51,.7);margin-bottom:20px}
.search-empty .btn-primary{display:inline-block}
.prod-availability{display:block;margin-top:4px;font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.prod-availability.in-stock{color:#1a8a4a}
mark{background:rgba(209,180,109,.4);color:inherit;padding:0 2px;border-radius:2px}

/* Pagination */
.pager{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:48px;flex-wrap:wrap}
.pager-num,.pager-arrow{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:0 8px;border:1px solid rgba(0,0,0,.1);border-radius:6px;color:var(--text-dark);font-size:13px;transition:all .25s}
.pager-num:hover,.pager-arrow:hover{border-color:var(--gold);color:var(--gold-dark)}
.pager-num.active{background:var(--text-dark);color:#fff;border-color:var(--text-dark)}
.pager-arrow.disabled{opacity:.35;pointer-events:none}
.pager-dots{color:rgba(51,51,51,.5);padding:0 4px}

@media(min-width:640px){
  .search-overlay-panel{padding-top:140px}
  .search-overlay-form input{font-size:28px}
}

/* Floating WhatsApp button — sits below the drawer/search-overlay z-index so it's
   naturally hidden behind them while open, rather than floating on top of a modal. */
.whatsapp-float{position:fixed;right:22px;bottom:calc(22px + var(--bottom-nav-h));z-index:45;width:56px;height:56px;border-radius:50%;background:#25D366;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(37,211,102,.45);transition:transform .3s,box-shadow .3s}
.whatsapp-float:hover{transform:scale(1.08);box-shadow:0 12px 30px rgba(37,211,102,.55)}
@media(max-width:640px){.whatsapp-float{width:50px;height:50px;right:16px;bottom:calc(16px + var(--bottom-nav-h))}.whatsapp-float svg{width:26px;height:26px}}

/* ================= Mobile bottom tab bar =================
   Rendered on every storefront page (partials/bottom-nav.blade.php) but only shown at
   mobile widths — above 900px the sticky header already offers the same destinations.
   Sits below the drawer/search-overlay z-index for the same reason .whatsapp-float does. */
.bottom-nav{position:fixed;left:0;right:0;bottom:0;z-index:44;display:none;
  grid-template-columns:repeat(4,1fr);
  background:rgba(255,253,247,.98);backdrop-filter:blur(10px);
  border-top:1px solid rgba(209,180,109,.35);
  box-shadow:0 -4px 18px -10px rgba(125,98,70,.4);
  padding-bottom:env(safe-area-inset-bottom)}
@media(max-width:900px){.bottom-nav{display:grid}}
.bn-item{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  height:58px;background:none;border:0;padding:0;cursor:pointer;
  color:rgba(51,51,51,.6);font-family:var(--font-sans);font-size:10px;letter-spacing:.05em;
  transition:color .25s}
.bn-item:hover,.bn-item.active{color:var(--gold-dark)}
.bn-item.active .bn-label{font-weight:600}
/* Anchors the .bag-count badge, which is position:absolute and shared with the header. */
.bn-icon{position:relative;display:inline-flex}
.bn-label{line-height:1}
