/* ===== CUSTOM FONTS ===== */
@font-face {
  font-family: 'Amsterdam Signature';
  src: url('Fonts/amsterdam_signature/Amsterdam Signature.woff2') format('woff2'),
       url('Fonts/amsterdam_signature/Amsterdam Signature.woff') format('woff'),
       url('Fonts/amsterdam_signature/Amsterdam Signature.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* ===== PRELOADER ===== */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg-primary);
  transition: opacity 0.5s ease, visibility 0.5s ease;
}

.preloader-logo {
  width: 130px;
  height: auto;
  animation: preloader-pulse 1.6s ease-in-out infinite;
}

.preloader-bar {
  width: 180px;
  height: 3px;
  background: var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.preloader-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  border-radius: var(--radius-md);
  transition: width 0.25s ease;
}

.preloader-percent {
  font-family: var(--font-heading);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 2px;
  color: var(--text-secondary);
}

.preloader.preloader-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

body.preloader-active {
  overflow: hidden;
}

@keyframes preloader-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.06); opacity: 0.8; }
}


/* ===== CSS RESET & VARIABLES ===== */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  /* ====================================================================
     BRAND PALETTE — single source of truth for the site's colors.
     To re-theme the whole site, edit ONLY these 4 values; every
     background, border, and text token below derives from them.
     ==================================================================== */
  --brand-black: #0A0A09;   /* deep dark ground — the hard ink that the whole page is drawn on in dark mode */
  --brand-maroon: #FF4C24;  /* "maroon" is just this slot's historical name — now carries the portfolio accent orange */
  --brand-tan: #AAAAAA;     /* likewise: the neutral mid-tone that drives secondary/muted text */
  --brand-cream: #EFEDE8;   /* the warm ink in dark mode / the paper in light — portfolio --ink / --ground */

  /* RGB triplets kept in sync with the hex values above — required
     wherever a color needs alpha transparency, e.g. rgba(var(--accent-rgb), .2) */
  --accent-rgb: 255, 76, 36;
  --sale-red-rgb: 229, 72, 77;
  --success-rgb: 47, 107, 70;

  /* A light, theme-INVARIANT blend of cream+tan for text that sits on a
     fixed dark photo scrim (hero, category cards, CTA banner) — those
     never follow the page theme, so they can't use --text-secondary,
     which flips per theme. See the elements using it below. */
  --on-photo-secondary: color-mix(in srgb, var(--brand-cream) 70%, var(--brand-tan) 30%);

  /* Semantics follows: this base :root is LIGHT (the default, no
     attribute). The dark-mode overrides live in the [data-theme="dark"]
     block below, which wins whenever theme.js stamps that attribute.
     Components reference the semantic tokens, never the raw palette. */

  /* ===== Semantic tokens — LIGHT is the default (no attribute), so
     these live here on the base :root. Components reference these
     tokens, never the raw palette above, so a re-theme never touches
     component CSS. The [data-theme="dark"] block below redeclares them
     and wins whenever theme.js stamps the dark attribute. ===== */
  --bg-primary: var(--brand-cream);          /* portfolio --ground (#EBE9E4) */
  --bg-primary-rgb: 235, 233, 228;
  --bg-secondary: color-mix(in srgb, var(--brand-cream) 90%, var(--brand-tan));
  --bg-card: color-mix(in srgb, var(--brand-cream) 82%, white);
  --bg-card-hover: color-mix(in srgb, var(--brand-cream) 92%, white);
  /* Light mode deepens the brand orange so text on it (white on buttons,
     badges) and text in it (labels, links on cream) meets WCAG AA:
     white 5.7:1, cream 4.9:1, secondary surface 4.6:1. Dark mode keeps
     the vivid #FF4C24 (--brand-maroon, below), which reads 6:1 on black.
     --accent-rgb stays vivid in both: it only feeds translucent glows and
     tints, which carry no text. */
  --accent: #C0320E;
  --accent-rgb: 255, 76, 36;
  --accent-hover: color-mix(in srgb, var(--accent) 85%, black);
  --on-accent: #FFFFFF;
  --text-primary: #111111;                   /* portfolio --ink */
  --text-secondary: #4a4a45;
  --text-muted: #666560;               /* ≥4.5:1 on every light surface (WCAG AA) */
  --border: rgba(17, 17, 17, 0.16);          /* hairline ink rule — the brutalist 1px borders */
  --border-light: rgba(17, 17, 17, 0.09);
  --border-color: var(--border-light); /* alias — modal/form markup references this name */
  --sale-red: #c62828;
  --sale-red-rgb: 198, 40, 40;
  --sale-bg: #d6303a;
  --success: #2f6b46;
  --success-rgb: 47, 107, 70;
  --overlay: rgba(0, 0, 0, 0.5);

  /* Typography */
  --font-heading: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  /* Typographic Scale (Neo-Grotesque) */
  --text-huge: clamp(3rem, 6vw, 4.5rem);
  --text-h1: clamp(2.2rem, 4vw, 3.2rem);
  --text-h2: clamp(1.8rem, 3vw, 2.4rem);
  --text-h3: clamp(1.4rem, 2.5vw, 1.8rem);
  --text-large: 1.15rem;
  --text-body: 1rem;
  --text-small: 0.85rem;
  --text-micro: 0.75rem;
  
  --tracking-tight: -0.03em;
  --tracking-tighter: -0.04em;
  --tracking-normal: 0;
  --tracking-wide: 0.05em;
  --tracking-widest: 0.1em;
  

  /* Spacing */
  --section-padding: 80px 0;
  --container-width: 1280px;
  --container-padding: 0 24px;

  /* Transitions */
  --transition-fast: 0.2s ease;
  --transition-med: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  --transition-slow: 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  /* The "premium" ease-out-with-a-touch-of-overshoot curve already used
     ad-hoc (as a repeated literal) by several reveal/hover effects
     throughout this file — formalized here as the signature curve for
     every overlay's entrance/exit (modals, drawer, search) in Phase 10,
     so they all share one motion language instead of each having picked
     up a slightly different curve over time. */
  --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);

  /* Radius */
  --radius-sm: 0px;  /* brutalist sharp edges — near-zero radii keep every */
  --radius-md: 2px; /* card, button and modal crisp instead of soft-curved */
  --radius-lg: 3px;
  --radius-xl: 4px;

  /* Mockup Coordinates (assets/mockup_2.jpg, 2193x3348) - the poster's box
     within the frame photo's picture window. Re-measured: the previous
     values undersized the box (matched the frame's true top/left inner
     edge but fell short of its actual bottom/right edge), so the poster
     sat flush against the frame's top border with a large, uneven gap at
     the bottom instead of an even margin on all sides. */
  --mockup-top: 22.30%;
  --mockup-left: 25.60%;
  --mockup-width: 48.80%;
  --mockup-height: 44.00%;

  /* Ambient background-layer glow opacity (see .bg-layered below).
     Tokenized rather than hardcoded in the gradient itself because dark
     and light mode need different values for the same visual weight:
     adding a light accent onto a near-black background raises luminance
     (reads as a glow), but the same math in reverse - a darkened accent
     over cream - lowers luminance instead, which reads as a faint dirty
     patch, not a glow, at the same opacity. Light (the base) pushes these
     up; the dark block below drops them back down. */
  --glow-opacity-1: 0.18;
  --glow-opacity-2: 0.13;
}

/* ====================================================================
   DARK MODE — the historical default, now the explicit override.
   Base :root above is light (no attribute — what every fresh visit
   opens in); theme.js sets <html data-theme="dark"> when the visitor
   toggles (or has a saved dark preference), which applies this block.
   Placed AFTER the base :root so its redeclarations win in source order
   whenever the attribute is present.
   ==================================================================== */
:root[data-theme="dark"] {
  --bg-primary: var(--brand-black);
  --bg-primary-rgb: 10, 10, 9;
  --bg-secondary: color-mix(in srgb, var(--brand-black) 92%, var(--brand-maroon));
  --bg-card: color-mix(in srgb, var(--brand-black) 86%, var(--brand-maroon));
  --bg-card-hover: color-mix(in srgb, var(--brand-black) 78%, var(--brand-maroon));
  --accent: var(--brand-maroon);
  --accent-rgb: 255, 76, 36;
  --accent-hover: color-mix(in srgb, var(--accent) 82%, white);
  --on-accent: #FFFFFF;
  --text-primary: var(--brand-cream);
  --text-secondary: color-mix(in srgb, var(--brand-cream) 70%, var(--brand-tan) 30%);
  --text-muted: color-mix(in srgb, var(--brand-cream) 38%, var(--brand-tan) 62%);
  --border: rgba(235, 233, 228, 0.16);
  --border-light: rgba(235, 233, 228, 0.09);
  --border-color: var(--border-light); /* alias — modal/form markup references this name */
  --sale-red: #e5484d;
  --sale-bg: #d6303a;
  --success: #2f6b46;
  --overlay: rgba(0, 0, 0, 0.6);
  /* Bumped DOWN from the light-mode default - see the --glow-opacity-1/2
     comment in the :root block for the luminance math. */
  --glow-opacity-1: 0.10;
  --glow-opacity-2: 0.07;
}

/* The "Brush" wordmark PNG (navbar, footer, preloader - every page uses
   the same asset) is solid white artwork on a transparent background.
   It sits against a LIGHT ground now (light is the default, no attribute),
   so it needs the invert+hue-rotate treatment wherever the ground is light —
   and only stops needing it in dark mode. Attribute selector rather than a
   class, so this covers every current usage (and any future one) without
   editing markup in each of the ~7 pages that reference this file. */
:root img[src*="Brush Text Arial.png"]:not(.hero-animated-logo),
:root img[src*="brush-logo"]:not(.hero-animated-logo) {
  filter: invert(1) hue-rotate(180deg);
}
:root[data-theme="dark"] img[src*="Brush Text Arial.png"]:not(.hero-animated-logo),
:root[data-theme="dark"] img[src*="brush-logo"]:not(.hero-animated-logo) {
  filter: none;
}

html {
  /* No CSS scroll-behavior: smooth here on purpose — Lenis (scroll.js) owns
     smooth scrolling when motion is allowed; when prefers-reduced-motion is
     set, Lenis doesn't init at all and this should fall back to instant
     native scroll rather than fight Lenis for control. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* body already declares overflow-x: hidden, but that only reliably
     becomes the viewport's own scroll behavior when html has no overflow
     of its own — with html left at the default (visible), some elements
     that overflow their container (the marquee tracks, mainly) were still
     reachable via a real ~100px horizontal scroll/swipe on phones despite
     body's rule, confirmed with window.scrollTo in a live check. Setting
     it here too removes the ambiguity instead of relying on propagation. */
  overflow-x: hidden;
}

body {
  font-family: var(--font-body);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  overflow-x: hidden;
}

/* Grain texture — fixed, non-interactive, sits above everything (including
   modals) since at this opacity it reads as film grain, not a visible layer.
   A static SVG turbulence tile blended with mix-blend-mode, so it's a single
   cheap composited layer rather than anything that repaints per frame. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 99999;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 120px 120px;
}

/* ====================================================================
   AMBIENT BACKGROUND LAYERS
   Most full-bleed sections (.features-strip, .categories-section,
   .testimonials-section, .faq-section, etc.) were a single flat
   background-color and nothing else - the grain above sits on EVERY
   section already, but grain alone doesn't give a section depth, just
   texture. This adds one reusable layer for that: soft, asymmetric,
   accent-tinted radial-gradient glows behind a section's content.

   Deliberately one hue (--accent) across every use, not a different
   color per section - variety comes from position/size instead, so
   this reads as one considered lighting system across the site rather
   than a different accent color arguing for attention in every section.

   Implementation notes:
   - Lives on ::before, not the section itself, so it never has to touch
     background-color (still owned by whichever section applies this).
   - z-index: -1 + isolation: isolate on the section: the glow stays
     behind that section's own content without needing to bump every
     child's z-index to compensate (no existing markup changes needed
     wherever this class gets added).
   - Plain radial-gradient, no filter: blur - the soft falloff is baked
     into the gradient stops, so this is one cheap composited paint, not
     a per-frame blur repaint.
   - --glow-pos-1/2 let each section place its two glows without
     redeclaring the whole background; sections that don't override them
     get the default top-left / bottom-right placement below. */
.bg-layered {
  position: relative;
  isolation: isolate;
}

.bg-layered::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  --glow-pos-1: 15% 20%;
  --glow-pos-2: 85% 80%;
  background:
    radial-gradient(600px circle at var(--glow-pos-1), rgba(var(--accent-rgb), var(--glow-opacity-1)), transparent 60%),
    radial-gradient(520px circle at var(--glow-pos-2), rgba(var(--accent-rgb), var(--glow-opacity-2)), transparent 55%);
}

/* Same system, viewport-fixed variant for long, section-less scrolling
   pages (All Products' 170-item list, checkout's form) where there's no
   natural per-section boundary to hang .bg-layered off of. One ambient
   pair of glows anchored to the viewport instead of the page, so it
   stays put as a soft frame around the edges while content scrolls past
   underneath - same technique the sitewide grain layer already uses
   (position: fixed), so this is proven cheap on these exact pages. */
body.page-layered {
  isolation: isolate;
}

body.page-layered::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(700px circle at 6% 10%, rgba(var(--accent-rgb), calc(var(--glow-opacity-1) * 0.75)), transparent 55%),
    radial-gradient(600px circle at 96% 90%, rgba(var(--accent-rgb), calc(var(--glow-opacity-2) * 0.7)), transparent 50%);
}

a {
  text-decoration: none;
  color: inherit;
  transition: color var(--transition-fast);
}

ul, ol {
  list-style: none;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Orphan control: keeps headings from leaving a single word stranded on
   the last line. Unsupported browsers just ignore the property, so this
   is a pure enhancement. Component-specific heading classes below set
   their own text-wrap where they need something more specific (pretty
   for body copy); this is just the site-wide floor for h1-h3. */
h1, h2, h3 {
  text-wrap: balance;
}

button {
  cursor: pointer;
  border: none;
  background: none;
  font-family: inherit;
  font-size: inherit;
  transition: transform 0.15s ease;
}

/* Press feedback — no button anywhere had a :active state, so every click
   landed with zero physical acknowledgement. A scale-down on press reads
   as "the click registered" the way a hover-only button never can. Buttons
   that already animate a magnet pull (see micro-interactions.js) get their
   own rule below so pressing them doesn't blow away the --magnet-x/-y
   translate this scale would otherwise replace. */
button:active {
  transform: scale(0.97);
}

.hero-cta:active,
.modal-add-to-cart:active,
.cart-checkout-btn:active {
  transform: translate(var(--magnet-x, 0px), var(--magnet-y, 0px)) scale(0.96);
}


/* ===== FORM CONTROLS — brand-styled checkbox/radio/select baseline =====
   Unscoped element selectors, so anywhere a plain <input type="checkbox">,
   <input type="radio">, or <select> shows up without its own bespoke
   styling (filter sidebars, review forms, checkout address fields), it
   still gets the accent-colored, dark-surface treatment instead of the OS
   default control — those default controls are the one place native chrome
   was still leaking through an otherwise fully custom-styled site. More
   specific rules (e.g. .payment-option input[type="radio"]) still win on
   the properties they redeclare; this only fills the gap. */
input[type="checkbox"],
input[type="radio"] {
  appearance: none;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 2px solid var(--border-light);
  background: var(--bg-card);
  cursor: pointer;
  position: relative;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

input[type="checkbox"] {
  border-radius: var(--radius-md);
}

input[type="radio"] {
  border-radius: 50%;
}

input[type="checkbox"]:hover,
input[type="radio"]:hover {
  border-color: var(--accent);
}

input[type="checkbox"]:checked {
  border-color: var(--accent);
  background: var(--accent);
}

input[type="radio"]:checked {
  border-color: var(--accent);
}

input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: solid var(--on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Ring + dot (not a solid fill) so this matches the checkout payment-option
   radio style already shipped elsewhere — one radio convention site-wide. */
input[type="radio"]:checked::after {
  content: '';
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: var(--accent);
}

select {
  appearance: none;
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 0.65rem 2.2rem 0.65rem 0.9rem;
  font-family: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23968f85' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
  transition: border-color var(--transition-fast);
}

select:hover {
  border-color: var(--border-light);
}

/* Accessible focus ring — a border-color swap alone (as several forms had)
   isn't enough contrast for keyboard users; this adds a visible ring on
   every focusable control site-wide without disturbing the box model. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: var(--container-padding);
}


/* ===== ANNOUNCEMENT BAR ===== */
.announcement-bar {
  background: var(--accent);
  color: var(--on-accent);
  text-align: center;
  padding: 8px 16px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  position: relative;
  z-index: 1001;
}

.announcement-bar a {
  color: var(--on-accent);
  text-decoration: underline;
  font-weight: 700;
}

.announcement-bar a:hover {
  opacity: 0.8;
}


/* ===== NAVBAR ===== */
/* Custom-element host is display:inline by default, which would collapse
   around the fixed pill and break first-paint layout on inner pages. */
global-navbar {
  display: contents;
}

.navbar {
  position: fixed;
  top: var(--nav-top, 16px);          /* floating gap; navbar-scroll.js tucks it under the announcement bar at page top */
  left: 0;
  right: 0;
  margin-inline: auto;
  width: 90%;
  max-width: 1200px;
  z-index: 1000;
  padding: 0 32px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  isolation: isolate;
  border-radius: 999px; /* Pill shape */
  transition: box-shadow var(--transition-med);
}

/* The frosted pill lives on a pseudo-element: backdrop-filter / transform on
   .navbar itself would become the containing block for the position:fixed
   mobile menu sheet and trap it inside the 60px pill. */
.navbar::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: color-mix(in srgb, var(--bg-primary) 78%, transparent);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--border);
  transition: background var(--transition-med);
}

.navbar.scrolled {
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
}

.navbar.scrolled::before {
  background: color-mix(in srgb, var(--bg-primary) 92%, transparent);
}

.announcement-bar.nav-hidden {
  transform: translateY(-100%);
}
.navbar.nav-hidden {
  transform: translateY(var(--nav-hidden-offset, -100%));
}

/* Always fixed at the true top of the viewport, independent of the navbar's
   own position/hide state — z-index above the navbar so it stays visible
   as a reading-progress cue even while the navbar itself is hidden. */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  will-change: transform;
  height: 3px;
  background: var(--accent);
  z-index: 1001;
  pointer-events: none;
}

.nav-brand {
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0; /* 48px tap target around the 32px logo */
}

.nav-brand img {
  height: 32px;
  width: auto;
}

.nav-brand span {
  color: var(--accent);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
}

.nav-links a {
  position: relative;
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--text-secondary);
  transition: color var(--transition-fast);
  letter-spacing: -0.01em;
}

.nav-links a::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width var(--transition-med);
}

.nav-links a:hover {
  color: var(--text-primary);
}

.nav-links a:hover::after {
  width: 100%;
}

/* Skip link — off-screen until focused by keyboard, then pinned top-left
   above the navbar. */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 10000;
  padding: 10px 18px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
  font-size: var(--text-small);
  border-radius: var(--radius-md);
  transform: translateY(-200%);
  transition: transform var(--transition-fast);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

main:focus {
  outline: none;
}

/* Current page — same underline as hover, held on, so visitors always
   know where they are (global-navbar.js stamps aria-current). */
.nav-links a[aria-current="page"],
.nav-dd-toggle.is-current {
  color: var(--text-primary);
}

.nav-links a[aria-current="page"]::after {
  width: 100%;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 20px;
}

.nav-action-btn {
  color: var(--text-secondary);
  font-size: 1.15rem;
  transition: color var(--transition-fast), transform var(--transition-fast);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
}

.nav-action-btn:hover {
  color: var(--text-primary);
  transform: scale(1.1);
}

/* Landing pop when the fly-to-cart clone (see .fly-to-cart-clone below)
   arrives — triggered by adding/removing this class in script.js. */
@keyframes cartIconPop {
  0% { transform: scale(1); }
  35% { transform: scale(1.25); }
  65% { transform: scale(0.9); }
  100% { transform: scale(1); }
}

.nav-action-btn.cart-pop {
  animation: cartIconPop 0.4s ease;
}

/* ===== FLY TO CART (Phase 12 micro-interaction) =====
   A cloned poster image, created and animated entirely from script.js
   (flyToCart()): appended at the source image's exact on-screen rect,
   then given a transform/opacity transition toward the cart icon on the
   very next frame. Scaling is done via transform, not by animating
   width/height, so it shrinks around its own center instead of collapsing
   toward a corner. */
.fly-to-cart-clone {
  position: fixed;
  margin: 0;
  z-index: 9999;
  pointer-events: none;
  border-radius: var(--radius-md);
  object-fit: cover;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.7s cubic-bezier(0.55, 0, 0.85, 0.35), opacity 0.7s ease-in;
  will-change: transform, opacity;
}

/* Theme toggle — a .nav-action-btn with a sun/moon pair; CSS shows
   whichever icon matches the *current* mode, JS just flips the attribute. */
.theme-toggle-icon-light {
  display: none;
}

:root[data-theme="dark"] .theme-toggle-icon-light {
  display: inline-block;
}

:root[data-theme="dark"] .theme-toggle-icon-dark {
  display: none;
}

.cart-count {
  position: absolute;
  top: 2px;
  right: 2px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 0.6rem;
  font-weight: 700;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Mobile menu toggle */
.menu-toggle {
  display: none;
  position: relative;
  flex-direction: column;
  gap: 5px;
  padding: 8px;
  z-index: 1002;
}

.menu-toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--text-primary);
  transition: transform var(--transition-med), opacity var(--transition-fast);
}

.menu-toggle.active span:nth-child(1) {
  transform: rotate(45deg) translate(5px, 5px);
}
.menu-toggle.active span:nth-child(2) {
  opacity: 0;
}
.menu-toggle.active span:nth-child(3) {
  transform: rotate(-45deg) translate(5px, -5px);
}


/* ===== HERO SECTION ===== */
.hero {
  position: relative;
  width: 100%;
  /* min-height (not height) + a flex column with top padding that clears
     the announcement bar and floating navbar: on short screens the hero
     grows instead of pushing its content up underneath the navbar. svh
     keeps it to the visible screen on mobile browsers with a URL bar. */
  min-height: max(600px, 100vh);
  min-height: max(600px, 100svh);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 150px 0 12vh;
  overflow: hidden;
}

.hero-slider {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.2s ease-in-out;
}

.hero-slide.active {
  opacity: 1;
}

.hero-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.05);
  transition: transform 8s ease-out;
}

.hero-slide.active img {
  transform: scale(1);
}

.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.3) 0%,
    rgba(0, 0, 0, 0.1) 40%,
    rgba(0, 0, 0, 0.6) 100%
  );
  z-index: 1;
}

.hero-content {
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  z-index: 2;
  width: 90%;
  max-width: 800px;
}

.hero-tag {
  display: inline-block;
  background: rgba(var(--accent-rgb), 0.15);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  color: var(--brand-cream); /* sits on the hero photo's fixed dark scrim, not the page bg — stays light in both themes */
  padding: 6px 18px;
  border-radius: 50px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-bottom: 20px;
  backdrop-filter: blur(10px);
}

.hero-title {
  font-family: var(--font-heading);
  font-size: var(--text-huge);
  font-weight: 800;
  line-height: 1.05;
  margin-bottom: 16px;
  letter-spacing: var(--tracking-tighter);
  color: var(--brand-cream); 
}

.hero-subtitle {
  font-size: clamp(1rem, 2vw, 1.25rem);
  color: var(--on-photo-secondary); /* same reasoning as .hero-title */
  margin-bottom: 32px;
  max-width: 550px;
  margin-left: auto;
  margin-right: auto;
  text-wrap: pretty;
}

.hero-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--accent);
  color: var(--on-accent);
  padding: 12px 28px;
  border-radius: 50px;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  transform: translate(var(--magnet-x, 0px), var(--magnet-y, 0px));
  transition: transform var(--transition-med), box-shadow var(--transition-med), background var(--transition-fast);
}

.hero-cta:hover {
  transform: translate(var(--magnet-x, 0px), calc(var(--magnet-y, 0px) - 2px));
  box-shadow: 0 8px 30px rgba(var(--accent-rgb), 0.3);
  background: var(--accent-hover);
}

.hero-cta svg {
  width: 16px;
  height: 16px;
  transition: transform var(--transition-fast);
}

.hero-cta:hover svg {
  transform: translateX(4px);
}

.hero-trust-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 22px;
}

.hero-trust-badge {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--brand-cream); /* hero photo's fixed dark scrim, not the page bg — stays light in both themes */
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(4px);
  padding: 7px 16px;
  border-radius: 50px;
}

/* Hero pagination dots */
.hero-dots {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: 14px;
}

.hero-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  border: none;
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

/* 10px dot, 24px tap target (WCAG 2.5.8) via a transparent ring. */
.hero-dot {
  position: relative;
}

.hero-dot::after {
  content: '';
  position: absolute;
  inset: -7px;
}

.hero-dot.active {
  background: var(--accent);
  transform: scale(1.3);
}

/* Staggered on-load entrance — above the fold, so this plays automatically
   on load rather than waiting for the .fade-in scroll-observer. Scoped to
   .hero-content specifically because .hero-cta is reused by non-hero
   buttons elsewhere on the page that must NOT replay this entrance.
   The entrance animation targets .hero-cta-reveal (a plain inline-block
   wrapper around .hero-cta), not .hero-cta itself: animation-fill-mode:both
   holds its keyframe's `transform` forever at the CSS Animation cascade
   layer, which outranks normal rules regardless of specificity — including
   :hover — so animating .hero-cta directly would permanently pin its
   transform to translateY(0) and silently swallow the magnetic-pull effect
   from micro-interactions.js. Keeping the two concerns on separate elements
   leaves .hero-cta's own transform free for hover/magnet use. */
.hero-content .hero-tag { animation: fadeInUp 0.7s ease both; animation-delay: 0.1s; }
.hero-content .hero-title { animation: fadeInUp 0.7s ease both; animation-delay: 0.3s; }
.hero-content .hero-cta-reveal { display: inline-block; animation: fadeInUp 0.7s ease both; animation-delay: 0.5s; }
.hero-content .hero-trust-badges { animation: fadeInUp 0.7s ease both; animation-delay: 0.7s; }

/* Scroll cue — bounces to hint "more below", fades out via JS once the
   visitor actually scrolls (see script.js's hero parallax block). */
.scroll-cue {
  position: absolute;
  bottom: 88px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  opacity: 0.85;
  transition: opacity 0.4s ease;
}

.scroll-cue.is-hidden {
  opacity: 0;
  pointer-events: none;
}

.scroll-cue-mouse {
  display: block;
  width: 24px;
  height: 38px;
  border: 2px solid color-mix(in srgb, var(--brand-cream) 65%, transparent);
  border-radius: 14px;
  position: relative;
}

.scroll-cue-wheel {
  position: absolute;
  top: 6px;
  left: 50%;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  background: var(--brand-cream);
  border-radius: 50%;
  animation: scrollCueBounce 1.6s ease-in-out infinite;
}

@keyframes scrollCueBounce {
  0% { transform: translateY(0); opacity: 1; }
  60% { transform: translateY(14px); opacity: 0; }
  61% { transform: translateY(0); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}


/* ===== MARQUEE / SCROLLING TICKER ===== */
.marquee-section {
  background: var(--bg-secondary);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 14px 0;
  overflow: hidden;
}

.marquee-track {
  display: flex;
  animation: marquee 30s linear infinite;
  white-space: nowrap;
}

.marquee-item {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 0 40px;
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 2px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.marquee-item .dot-sep {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

@keyframes marquee {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}


/* ===== FEATURES STRIP ===== */
.features-strip {
  padding: 50px 0;
  background: var(--bg-primary);
}

.features-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}

.feature-item {
  text-align: center;
  padding: 30px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-med), transform var(--transition-med), background var(--transition-med);
}

.feature-item:hover {
  border-color: var(--accent);
  transform: translateY(-4px);
  background: var(--bg-card);
}

.feature-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--bg-card);
  border: 1px solid var(--border-light);
  color: var(--accent);
  font-size: 1.3rem;
  transition: background var(--transition-med), border-color var(--transition-med);
}

.feature-item:hover .feature-icon {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

.feature-item h3,
.feature-item h4 {
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 6px;
}

.feature-item p {
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.4;
}


/* ===== SECTION HEADERS ===== */
.section-header {
  text-align: center;
  margin-bottom: 50px;
}

.section-tag {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 12px;
}

.section-title {
  font-family: var(--font-heading);
  font-size: var(--text-h2);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: var(--tracking-tight);
}

.section-subtitle {
  font-size: var(--text-large);
  color: var(--text-secondary);
  margin-top: 12px;
  max-width: 500px;
  margin-left: auto;
  margin-right: auto;
  text-wrap: balance;
  letter-spacing: var(--tracking-normal);
}

/* ===== PAGE HEADER (inner pages) =====
   One intro band for every secondary page (About, Policies, B2B, Style
   Options...) — they each used to carry their own copy with drifting
   padding, font and size. Reuses .section-tag / heading scale tokens so
   an inner page reads as part of the same system as the homepage. */
.page-header {
  position: relative;
  isolation: isolate;
  background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
  padding: 140px 24px 64px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

.page-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(520px circle at 50% 0%, rgba(var(--accent-rgb), calc(var(--glow-opacity-2) * 0.8)), transparent 60%);
}

.page-header .container {
  padding: 0;
}

.page-header h1 {
  font-family: var(--font-heading);
  font-size: var(--text-h1);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
  margin-bottom: 14px;
  text-wrap: balance;
}

.page-header p {
  color: var(--text-secondary);
  font-size: var(--text-large);
  line-height: 1.6;
  max-width: 600px;
  margin: 0 auto;
  text-wrap: pretty;
}

.page-header p + .hero-cta,
.page-header p + div {
  margin-top: 2rem;
}

@media (max-width: 768px) {
  .page-header {
    padding: 112px 20px 44px;
  }
}

/* ===== SECONDARY BUTTON =====
   Outline companion to .hero-cta — same height, weight and radius so a
   primary/secondary pair lines up wherever they sit side by side. */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 27px; /* hero-cta's 12px/28px minus the 1px border */
  border: 1px solid var(--border);
  border-radius: 50px;
  color: var(--text-primary);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}

.btn-ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.06);
}

/* Animated Logo — Infinite Blur Pulse */
.hero-logo-container {
  margin: 0 0 1.1rem 0;
  display: block;
  line-height: 0;
  position: relative;
}

/* Soft animated glow behind the wordmark — a local z-index of 0 vs. the
   logo's 1 keeps this confined to the container's own stacking, so it can
   never leak behind .hero-overlay (no negative z-index needed). */
.hero-logo-container::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 280px;
  height: 280px;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(var(--accent-rgb), 0.55) 0%, rgba(var(--accent-rgb), 0) 70%);
  filter: blur(30px);
  z-index: 0;
  animation: logoGlowPulse 4.5s ease-in-out infinite;
  pointer-events: none;
}

@keyframes logoGlowPulse {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); opacity: 0.6; }
  50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
}

.hero-animated-logo {
  display: inline-block;
  position: relative;
  z-index: 1;
  height: clamp(56px, 8vw, 92px);
  width: auto;
  opacity: 1;
  filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.25));
  animation: fadeInUp 0.7s ease both;
}


/* The preloader can take anywhere from ~200ms to a few seconds depending on
   image/font load time. Keep these paused while it's on screen so the
   counter's entrance always plays where the user can see it, and the logo's
   loop always starts fresh from a clean frame instead of mid-cycle. Same
   reasoning extends to every other hero entrance animation added since. */
body.preloader-active .hero-animated-logo,
body.preloader-active .hero-logo-container::before,
body.preloader-active .hero-counter,
body.preloader-active .hero-content .hero-tag,
body.preloader-active .hero-content .hero-title,
body.preloader-active .hero-content .hero-cta-reveal,
body.preloader-active .hero-content .hero-trust-badges {
  animation-play-state: paused;
}

/* Dynamic Counter */
.hero-counter {
  margin-top: 1.5rem;
  margin-bottom: 2rem;
  font-family: var(--font-heading);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--brand-cream); /* hero photo's fixed dark scrim, not the page bg — stays light in both themes */
  background: rgba(255,255,255,0.05);
  padding: 7px 16px;
  border-radius: 50px;
  display: table;
  margin-left: auto;
  margin-right: auto;
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 4px 15px rgba(0,0,0,0.2);
  backdrop-filter: blur(10px);
  animation: fadeInUp 0.7s ease both;
  animation-delay: 1.1s;
}

.hero-counter span {
  color: var(--accent);
  font-size: 1.05rem;
  font-weight: 800;
}

@keyframes fadeInUp {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}


/* ===== PRODUCT GRID ===== */
.products-section {
  padding: var(--section-padding);
}

.products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

.product-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: transform var(--transition-med), border-color var(--transition-med), box-shadow var(--transition-med);
  position: relative;
}

.product-card:hover {
  transform: translateY(-6px);
  border-color: var(--border-light);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), 0 0 40px rgba(var(--accent-rgb), 0.15);
}

@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

.product-card-image, .plain-product-image, .mockup-wrapper {
  background-color: var(--bg-secondary);
}

.shimmer-skeleton, .mockup-frame, .mockup-poster, .mockup-hover, .plain-product-image {
  opacity: 0;
  transition: opacity 0.4s ease-out;
}

.mockup-frame.loaded, .mockup-poster.loaded, .mockup-hover.loaded, .plain-product-image.loaded, .modal-plain-image.loaded {
  opacity: 1;
}

/* Add shimmer effect to the empty wrappers before images paint */
.mockup-wrapper::before, .product-card-image::before, .modal-plain-image-wrapper::before {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.04) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  animation: shimmer 1.5s infinite;
  z-index: 0;
}

:root[data-theme="dark"] .mockup-wrapper::before,
:root[data-theme="dark"] .product-card-image::before {
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.04) 50%,
    rgba(255, 255, 255, 0) 100%
  );
}

.product-card-image {
  position: relative;
  aspect-ratio: 2193 / 3348;
  overflow: hidden;
  background: var(--bg-secondary);
}

/* Mockup Layout */
.mockup-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 2193 / 3348; /* matches assets/mockup_2.jpg exactly so the frame is never cropped/zoomed */
  overflow: hidden;
  transition: transform var(--transition-slow);
}

/* Scoped to .product-card specifically — .mockup-wrapper is shared markup
   with .category-card, which has its own (unrelated) cursor-tilt hover. */
.product-card:hover .mockup-wrapper {
  transform: scale(1.05);
}

.mockup-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 1;
}

.mockup-poster {
  position: absolute;
  top: var(--mockup-top);
  left: var(--mockup-left);
  width: var(--mockup-width);
  height: var(--mockup-height);
  object-fit: cover;
  z-index: 2;
  transition: opacity var(--transition-fast);
  box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}

.mockup-hover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #fff;
  z-index: 3;
  opacity: 0;
  transition: opacity var(--transition-med);
}

.mockup-wrapper:hover .mockup-hover {
  opacity: 1;
}

.mockup-wrapper:hover .mockup-poster {
  opacity: 0;
}

/* Plain product photo for non-poster types (plate, wallpaper) — no
   picture-frame mockup, since that would misrepresent the product. */
.plain-product-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-slow);
}

.product-card:hover .plain-product-image {
  transform: scale(1.05);
  filter: grayscale(100%);
}

.product-badge {
  position: absolute;
  top: 16px;
  left: 16px;
  background: var(--text-primary);
  color: var(--bg-primary);
  padding: 4px 10px;
  font-size: var(--text-micro);
  font-weight: 700;
  border-radius: var(--radius-sm);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  z-index: 2;
}

.product-quick-actions {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 32px 12px 12px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.55), transparent);
  z-index: 4;
  transform: translateY(20px);
  opacity: 0;
  transition: transform var(--transition-med), opacity var(--transition-med);
}

.product-card:hover .product-quick-actions {
  transform: translateY(0);
  opacity: 1;
}

/* The second information layer Dessine Art's card hover surfaces (spec
   copy, not just a CTA) — shown above the Add to Cart button so hover
   answers "why buy" before the click, not just "this is clickable". */
.product-card-specs {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}

.product-card-specs span {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.7rem;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

.product-card-specs i {
  color: var(--accent);
  font-size: 0.68rem;
}

.quick-add-btn {
  background: var(--text-primary);
  color: var(--bg-primary);
  padding: 10px 28px;
  border-radius: 50px;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.quick-add-btn:hover {
  background: var(--accent);
  color: var(--on-accent);
  transform: scale(1.05);
}

.product-card-info {
  padding: 18px;
}

.product-card-info h3 {
  font-family: var(--font-heading);
  font-size: 0.95rem;
  font-weight: 600;
  margin-bottom: 8px;
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-pricing {
  display: flex;
  align-items: center;
  gap: 10px;
}

.price-current {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.price-original {
  font-size: 0.85rem;
  color: var(--text-muted);
  text-decoration: line-through;
}

.price-discount {
  font-size: 0.75rem;
  color: var(--success);
  font-weight: 600;
}


/* ===== CATEGORY SECTION ===== */
.categories-section {
  padding: var(--section-padding);
  background: var(--bg-secondary);
}

.categories-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.category-card {
  position: relative;
  border: 1px solid var(--border-color);
  border-radius: 0;
  background: var(--bg-card);
  overflow: hidden;
  cursor: pointer;
  isolation: isolate; /* scopes z-index of mockup layers/title so the title always wins, hover state included */
  container-type: inline-size; /* lets the title scale off the card's own width via cqw */
  transition: box-shadow var(--transition-med);
}

/* No `transform` on hover here, deliberately — this card has
   container-type: inline-size (needed above for the title's cqw sizing),
   and animating `transform` via CSS transition on an element that also has
   container-type reliably broke overflow:hidden clipping on this card's
   .mockup-wrapper descendant in Chromium (poster rendered unclipped, frame
   graphic invisible) on every normal hover — not an edge case, and not
   about which transform function was used: a JS-driven 3D
   perspective()/rotateX/rotateY tilt, a plain 2D scale(), and a CSS-only
   translateY+scale hover all reproduced it identically once animated
   (setting the same transform statically, no transition, was always fine).
   Confirmed via isolation that removing container-type — not isolation,
   not the specific transform function — was what fixed it. Since the title
   sizing needs container-type to stay, the fix is the other side: don't
   animate `transform` on this element at all. The zoom-on-hover instead
   targets .mockup-wrapper below, a plain descendant with no
   container-type of its own. */
.category-card:hover {
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(var(--accent-rgb), 0.15);
}

.category-card:hover .mockup-wrapper {
  transform: scale(1.06);
}

.category-card-title {
  position: relative;
  z-index: 2;
  padding: 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--bg-primary);
  border-top: 1px solid var(--border-color);
  font-family: var(--font-heading);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.category-card-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(0,0,0,0.85) 100%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 24px;
  transition: background var(--transition-med);
}

.category-card:hover .category-card-overlay {
  background: linear-gradient(180deg, transparent 20%, rgba(0,0,0,0.9) 100%);
}

.category-card-overlay p {
  font-size: 0.8rem;
  color: var(--on-photo-secondary); /* sits on a fixed dark gradient over the poster photo, not the page bg — stays light in both themes */
}

/* Plates/Wallpaper have no real product photography yet — an icon tile
   in the same card shell (same size, same title/overlay treatment) reads
   as "new category, coming soon" rather than a broken or faked photo. */
.category-card-icon-bg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, var(--bg-secondary), var(--bg-primary));
}

.category-card-icon-bg i {
  font-size: 4rem;
  color: var(--accent);
  opacity: 0.8;
  transition: transform var(--transition-med);
}

.category-card-icon:hover .category-card-icon-bg i {
  transform: scale(1.08);
}

.category-card-title-icon {
  color: var(--accent);
  text-shadow: none;
}

.category-card-overlay .cat-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 1px;
  transition: gap var(--transition-fast);
}

.category-card:hover .cat-arrow {
  gap: 12px;
}


/* ===== HORIZONTAL SCROLL COLLECTION ===== */
.scroll-collection {
  padding: var(--section-padding);
}

.scroll-wrapper {
  position: relative;
}

.scroll-track {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 20px;
}

.scroll-track::-webkit-scrollbar {
  display: none;
}

.scroll-track .product-card {
  flex-shrink: 0;
  width: 280px;
  scroll-snap-align: start;
}

.scroll-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%) translateZ(0); /* Force GPU compositing to prevent scroll-track from intercepting hits */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-card);
  border: 1px solid var(--border-light);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  z-index: 99;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.scroll-nav i {
  pointer-events: none;
}

.scroll-nav:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.scroll-nav.prev {
  left: -22px;
}

.scroll-nav.next {
  right: -22px;
}

.scroll-nav:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.scroll-nav:disabled:hover {
  background: var(--bg-card);
  border-color: var(--border-light);
  color: var(--text-primary);
}

.carousel-counter {
  text-align: center;
  margin-top: 18px;
  font-family: var(--font-heading);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--text-secondary);
}


/* ===== BANNER / CTA SECTION ===== */
.cta-banner {
  position: relative;
  padding: 100px 0;
  text-align: center;
  overflow: hidden;
}

.cta-banner-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.cta-banner-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.3);
}

/* Animated gradient "mood" wash — built entirely from the same palette
   tokens as everything else, so it re-themes automatically with a light/dark
   toggle or a palette swap. mix-blend-mode: screen (not overlay) is
   deliberate: over a photo this dark, overlay would mostly darken further,
   while screen always adds light/color regardless of how dark the base is —
   what makes these blobs actually glow instead of just muddying the photo. */
.cta-banner::after {
  content: '';
  position: absolute;
  inset: -25%;
  z-index: 1;
  background:
    radial-gradient(circle at 25% 30%, rgba(var(--accent-rgb), 0.6) 0%, transparent 55%),
    radial-gradient(circle at 75% 70%, color-mix(in srgb, var(--brand-tan) 65%, transparent) 0%, transparent 55%),
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--brand-cream) 40%, transparent) 0%, transparent 60%);
  mix-blend-mode: screen;
  filter: blur(50px);
  animation: ctaGradientDrift 18s ease-in-out infinite alternate;
  pointer-events: none;
}

@keyframes ctaGradientDrift {
  0% { transform: translate(0%, 0%) scale(1); }
  50% { transform: translate(-5%, 4%) scale(1.1); }
  100% { transform: translate(4%, -4%) scale(1.02); }
}

.cta-banner-content {
  position: relative;
  z-index: 2; /* above .cta-banner::after (z-index 1) so the gradient wash never dims the text */
  max-width: 700px;
  margin: 0 auto;
  padding: 0 24px;
}

.cta-banner-content h2 {
  font-family: var(--font-heading);
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 800;
  margin-bottom: 16px;
  line-height: 1.2;
  color: var(--brand-cream); /* sits on a fixed-dark photo (brightness(0.3)), not the page bg — stays light in both themes */
}

.cta-banner-content p {
  font-size: 1.05rem;
  color: var(--on-photo-secondary); /* same reasoning as h2 above */
  margin-bottom: 32px;
}


/* ===== TESTIMONIALS ===== */
.testimonials-section {
  padding: var(--section-padding);
  background: var(--bg-secondary);
}

.testimonials-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  /* Needed for the bento offset below to actually show — grid items
     stretch to fill the row height by default, which would hide any
     margin-top difference between cards. */
  align-items: start;
}

.testimonial-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 32px;
  position: relative;
  overflow: hidden; /* clips the oversized decorative quote mark below to the card's rounded corners */
  transition: border-color var(--transition-med), transform var(--transition-med);
}

/* Bento wave — desktop-only (reset at both breakpoints below, where the
   grid drops to 2 then 1 column and a mid-row offset stops making sense). */
.testimonial-card:nth-child(2) {
  margin-top: 36px;
}

.testimonial-card:hover {
  border-color: var(--accent);
  transform: translateY(-4px);
}

.testimonial-card::before {
  content: '\201C';
  position: absolute;
  top: -0.35em;
  right: 0.15em;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 7rem;
  line-height: 1;
  color: rgba(var(--accent-rgb), 0.12);
  pointer-events: none;
}

.testimonial-stars {
  color: var(--accent);
  font-size: 0.9rem;
  margin-bottom: 16px;
  letter-spacing: 2px;
}

.testimonial-text {
  font-size: 0.95rem;
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: 20px;
  font-style: italic;
  position: relative; /* sits above ::before's decorative quote mark */
}

.testimonial-author {
  display: flex;
  align-items: center;
  gap: 12px;
}

.testimonial-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--on-photo-secondary)); /* brand-tan alone is too dark now — no single fixed text color would read on both gradient ends */
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--brand-black); /* fixed gradient (accent→tan), so keep text dark in both themes */
  flex-shrink: 0;
}

.testimonial-author-info h3,
.testimonial-author-info h5 {
  font-size: 0.9rem;
  font-weight: 600;
}

.testimonial-author-info p {
  font-size: 0.75rem;
  color: var(--text-muted);
}


/* ===== APP DOWNLOAD / SECONDARY CTA ===== */
.app-section {
  padding: var(--section-padding);
}

.app-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}

.app-content h2 {
  font-family: var(--font-heading);
  font-size: var(--text-h1);
  font-weight: 800;
  line-height: 1.15;
  margin-bottom: 20px;
  letter-spacing: var(--tracking-tight);
}

.app-content p {
  color: var(--text-secondary);
  margin-bottom: 32px;
  font-size: 1rem;
  line-height: 1.7;
}

.app-buttons {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.app-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-card);
  border: 1px solid var(--border-light);
  color: var(--text-primary);
  padding: 14px 28px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 0.9rem;
  transition: border-color var(--transition-fast), background var(--transition-fast), transform var(--transition-fast);
}

.app-btn:hover {
  border-color: var(--accent);
  background: var(--bg-card-hover);
  transform: translateY(-2px);
}

.app-btn i {
  font-size: 1.4rem;
}

.app-image {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.app-image img {
  width: 100%;
  border-radius: var(--radius-lg);
}


/* ===== FOOTER ===== */
/* Rendered by global-footer.js; the host is a plain block wrapper. */
global-footer {
  display: block;
}

.site-footer {
  background: var(--bg-secondary);
  border-top: 1px solid var(--border);
  padding: 80px 0 30px;
  position: relative;
  isolation: isolate;
}

/* Footer gets its own glow rather than reusing .bg-layered's default
   two-glow placement: this section is dense (4 link columns), so both
   glows are pulled up to the top edge instead of into the content area
   - just enough warmth right under the border to feel like a
   continuation of the section above, not another spotlight competing
   with the link columns. */
.site-footer::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(560px circle at 10% 0%, rgba(var(--accent-rgb), calc(var(--glow-opacity-1) * 0.8)), transparent 55%),
    radial-gradient(480px circle at 90% 0%, rgba(var(--accent-rgb), calc(var(--glow-opacity-2) * 0.7)), transparent 50%);
}

.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1.5fr;
  gap: 50px;
  margin-bottom: 50px;
}

.footer-brand h3 {
  font-family: var(--font-heading);
  font-size: 1.6rem;
  font-weight: 800;
  margin-bottom: 14px;
}

.footer-brand h3 span {
  color: var(--accent);
}

.footer-brand p {
  color: var(--text-muted);
  font-size: 0.88rem;
  line-height: 1.7;
  margin-bottom: 20px;
  max-width: 320px;
}

.footer-social {
  display: flex;
  gap: 12px;
}

.footer-social a {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--border-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  font-size: 0.95rem;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}

.footer-social a:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
}

.footer-column h2,
.footer-column h4 {
  font-family: var(--font-heading);
  font-size: 0.95rem;
  font-weight: 700;
  margin-bottom: 20px;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.footer-column ul li {
  margin-bottom: 10px;
}

.footer-column ul li a {
  color: var(--text-muted);
  font-size: 0.88rem;
  transition: color var(--transition-fast), padding-left var(--transition-fast);
}

.footer-column ul li a:hover {
  color: var(--accent);
  padding-left: 6px;
}

.footer-newsletter p {
  color: var(--text-muted);
  font-size: 0.88rem;
  margin-bottom: 16px;
  line-height: 1.6;
}

.newsletter-form {
  display: flex;
  gap: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--border-light);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.newsletter-form:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.25);
}

.newsletter-form input {
  flex: 1;
  background: var(--bg-card);
  border: none;
  padding: 12px 16px;
  color: var(--text-primary);
  font-size: 0.85rem;
  outline: none;
}

.newsletter-form input::placeholder {
  color: var(--text-muted);
}

.newsletter-form button {
  background: var(--accent);
  color: var(--on-accent);
  padding: 12px 20px;
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  transition: background var(--transition-fast);
}

.newsletter-form button:hover {
  background: var(--accent-hover);
}

.footer-bottom {
  border-top: 1px solid var(--border);
  padding-top: 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

.footer-bottom p {
  color: var(--text-muted);
  font-size: 0.8rem;
}

.footer-bottom-links {
  display: flex;
  gap: 24px;
}

.footer-bottom-links a {
  color: var(--text-muted);
  font-size: 0.8rem;
}

.footer-bottom-links a:hover {
  color: var(--accent);
}

/* Brand block details (moved out of inline styles when the footer became
   the shared <global-footer> component). */
.footer-logo {
  height: 36px;
  width: auto;
  margin-bottom: 0.5rem;
}

.footer-parent {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 1rem;
}

.footer-parent-label {
  font-size: var(--text-micro);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.footer-parent-name {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1rem;
  color: var(--accent);
}

.newsletter-status {
  min-height: 1.2em;
  margin: 8px 0 12px !important;
  font-size: var(--text-micro) !important;
  color: var(--success) !important;
}

.newsletter-status.is-error {
  color: var(--sale-red) !important;
}

.footer-contact li {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  color: var(--text-muted);
  font-size: 0.88rem;
}

.footer-contact i {
  width: 16px;
  text-align: center;
  color: var(--accent);
}

.footer-contact a {
  color: var(--text-muted);
  transition: color var(--transition-fast);
}

.footer-contact a:hover {
  color: var(--accent);
}

.footer-disclaimer {
  display: inline-block;
  max-width: 800px;
  margin-top: 8px;
  font-size: 0.85em;
  line-height: 1.4;
}

/* ===== VIEW ALL BUTTON ===== */
.view-all-wrap {
  text-align: center;
  margin-top: 40px;
}

.view-all-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 2px solid var(--border-light);
  color: var(--text-primary);
  padding: 14px 36px;
  border-radius: 50px;
  font-size: 0.9rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}

.view-all-btn:hover {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}


/* ===== SCROLL TO TOP ===== */
.scroll-top {
  position: fixed;
  bottom: 30px;
  right: 30px;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  z-index: 999;
  opacity: 0;
  visibility: hidden;
  transform: translateY(20px);
  transition: opacity var(--transition-med), visibility var(--transition-med), transform var(--transition-med);
  box-shadow: 0 4px 20px rgba(var(--accent-rgb), 0.3);
}

.scroll-top.visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.scroll-top:hover {
  transform: translateY(-4px);
}


/* ===== FADE-IN ANIMATIONS ===== */
.fade-in {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.7s ease-out, transform 0.7s ease-out;
}

.fade-in.visible {
  opacity: 1;
  transform: translateY(0);
}

.fade-in-delay-1 { transition-delay: 0.1s; }
.fade-in-delay-2 { transition-delay: 0.2s; }
.fade-in-delay-3 { transition-delay: 0.3s; }
.fade-in-delay-4 { transition-delay: 0.4s; }

/* Two more reveal variants, same .visible-toggle contract as .fade-in above
   (observed/added by the same IntersectionObserver in script.js) — pick
   whichever suits the element instead of defaulting to fade-in everywhere. */
.scale-in {
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 0.7s ease-out, transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.scale-in.visible {
  opacity: 1;
  transform: scale(1);
}

/* Not clip-path on this element itself, deliberately — that was the
   original design and it never actually worked: IntersectionObserver
   computes intersection against the target's own clipped/rendered area, so
   an element clipped to zero visible height (inset(0 0 100% 0)) always
   reports isIntersecting:false, even while it's squarely in the viewport.
   That's a real deadlock, not an edge case — the element can never be
   detected as visible precisely because it's clipped, which is the same
   clip the detection is supposed to lift. Confirmed via an isolated
   reproduction outside this codebase before rewriting this. Fix: put the
   clip on the PARENT via overflow:hidden (which does not shrink the
   parent's own layout box — the parent's geometry, and thus what
   IntersectionObserver sees, is unaffected by its own overflow), and
   animate a translateY reveal on the child instead. */
.clip-reveal {
  overflow: hidden;
}

.clip-reveal > * {
  transform: translateY(100%);
  transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}

.clip-reveal.visible > * {
  transform: translateY(0);
}

/* ===== CUSTOM CURSOR (Phase 11 micro-interactions) =====
   Only mounted by micro-interactions.js when the visitor has a fine
   pointer (mouse/trackpad) and hasn't asked for reduced motion — see the
   JS gate there. body.custom-cursor-active is added by that same script,
   so a page with this script missing/broken just keeps the native
   cursor rather than going invisible. */
.custom-cursor-dot {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  border-radius: 50%;
  z-index: 10001;
  opacity: 0;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  background: var(--accent);
  transition: opacity 0.2s ease, width 0.2s ease, height 0.2s ease, margin 0.2s ease;
}

.custom-cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  border-radius: 50%;
  z-index: 10000;
  opacity: 0;
  width: 36px;
  height: 36px;
  margin: -18px 0 0 -18px;
  border: 1.5px solid var(--accent);
  transition: opacity 0.2s ease, width 0.2s ease, height 0.2s ease, margin 0.2s ease, background 0.2s ease;
}

.custom-cursor-ring.hovering {
  width: 50px;
  height: 50px;
  margin: -25px 0 0 -25px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.custom-cursor-dot.hovering {
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
}
}
/* Hide default cursor on interactive element hover */
body.custom-cursor-active,
body.custom-cursor-active * {
  cursor: none !important;
}

@media (pointer: coarse) {
  .custom-cursor-dot, .custom-cursor-ring {
    display: none !important;
  }
}
}
/* Anyone who's asked their OS for reduced motion gets content in its final
   state immediately — no fade/scale/clip, no transition. Applies regardless
   of whether .visible has been toggled yet, so there's no dependency on the
   IntersectionObserver having fired first. */
@media (prefers-reduced-motion: reduce) {
  .fade-in,
  .scale-in,
  .clip-reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* .clip-reveal's own hide/reveal transform now lives on its direct
     child (see .clip-reveal > * above), not on .clip-reveal itself. */
  .clip-reveal > * {
    transform: none !important;
    transition: none !important;
  }

  /* Hero: kill the infinite logo pulse/glow (which would otherwise loop
     forever — including whatever mid-cycle opacity it happened to be at,
     since browsers don't auto-pause author animations for reduced motion)
     and the one-shot entrance animations. No need to touch .hero-content's
     own transform (used for centering, not motion) — the JS parallax that
     would otherwise override it never runs here, since scroll.js refuses
     to init Lenis under reduced motion and script.js's parallax is gated
     on window.lenis. */
  .hero-animated-logo,
  .hero-logo-container::before,
  .hero-counter,
  .hero-content .hero-tag,
  .hero-content .hero-title,
  .hero-content .hero-cta-reveal,
  .hero-content .hero-trust-badges,
  .scroll-cue-wheel {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  .scroll-cue {
    display: none;
  }

  /* Safety net: micro-interactions.js already refuses to mount the cursor
     or bind magnetic buttons under reduced motion, but in case that class
     is ever left on the body (e.g. motion preference changes mid-session
     without a reload) don't leave visitors without a real cursor. */
  .custom-cursor-dot, .custom-cursor-ring {
    display: none !important;
  }

  body.custom-cursor-active,
  body.custom-cursor-active * {
    cursor: auto !important;
  }

  /* flyToCart() already refuses to create a clone or pop the cart icon
     under reduced motion — this is a safety net in case either class
     is ever applied some other way. */
  .fly-to-cart-clone {
    display: none !important;
  }

  .nav-action-btn.cart-pop {
    animation: none !important;
  }

  /* Freeze the CTA banner's gradient drift at its resting position — but
     NOT via the shared rule above, which forces filter:none. That would
     strip this element's blur(50px), which softens the gradient blobs and
     has nothing to do with motion; killing it would leave hard-edged circles. */
  .cta-banner::after {
    animation: none !important;
    transform: none !important;
  }

  /* The ticker is an infinite auto-scrolling loop with no user control to
     stop it — exactly the kind of motion reduced-motion exists to opt out of. */
  .marquee-track {
    animation: none !important;
  }
}


/* ===== CART DRAWER ===== */
.cart-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 2000;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s var(--ease-premium), visibility 0.35s var(--ease-premium);
  backdrop-filter: blur(4px);
}

.cart-overlay.open {
  opacity: 1;
  visibility: visible;
}

.cart-drawer {
  position: fixed;
  top: 0;
  right: 0;
  width: 420px;
  max-width: 92vw;
  height: 100vh;
  background: var(--bg-secondary);
  border-left: 1px solid var(--border);
  z-index: 2001;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.4s var(--ease-premium);
  box-shadow: -8px 0 30px rgba(0, 0, 0, 0.4);
}

.cart-drawer.open {
  transform: translateX(0);
}

.cart-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.cart-drawer-header h3 {
  font-family: var(--font-heading);
  font-size: 1.15rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 10px;
}

.cart-drawer-count {
  font-weight: 500;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.cart-close-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--border-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  font-size: 1rem;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}

.cart-close-btn:hover {
  border-color: var(--sale-red);
  color: var(--sale-red);
  background: rgba(var(--sale-red-rgb), 0.1);
}

.cart-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 24px;
}

.cart-drawer-body::-webkit-scrollbar {
  width: 5px;
}
.cart-drawer-body::-webkit-scrollbar-track {
  background: transparent;
}
.cart-drawer-body::-webkit-scrollbar-thumb {
  background: var(--border-light);
  border-radius: var(--radius-md);
}

/* Empty cart state */
.cart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
  padding: 40px 20px;
}

.cart-empty i {
  font-size: 3rem;
  color: var(--text-muted);
  margin-bottom: 16px;
}

.cart-empty h4 {
  font-family: var(--font-heading);
  font-size: 1.1rem;
  margin-bottom: 6px;
}

.cart-empty p {
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* Cart item */
.cart-item {
  display: flex;
  gap: 14px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
  animation: fadeSlideIn 0.3s ease-out;
}

@keyframes fadeSlideIn {
  0% { opacity: 0; transform: translateX(20px); }
  100% { opacity: 1; transform: translateX(0); }
}

.cart-item-image {
  aspect-ratio: 4 / 5;
  width: 72px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
  background: var(--bg-card);
}

.cart-item-details {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cart-item-details h4 {
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.3;
}

.cart-item-details .cart-item-price {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.cart-item-details .cart-item-price strong {
  color: var(--text-primary);
}

.cart-item-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.qty-control {
  display: flex;
  align-items: center;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.qty-control button {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  font-size: 0.85rem;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.qty-control button:hover {
  background: var(--accent);
  color: var(--on-accent);
}

.qty-control .qty-value {
  width: 32px;
  text-align: center;
  font-size: 0.85rem;
  font-weight: 600;
  background: var(--bg-card);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  line-height: 30px;
}

.cart-item-remove {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 4px;
  transition: color var(--transition-fast);
}

.cart-item-remove:hover {
  color: var(--sale-red);
}

/* Cart footer */
.cart-drawer-footer {
  padding: 20px 24px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.cart-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  font-size: 0.88rem;
  color: var(--text-secondary);
}

.cart-summary-row .cart-subtotal,
.cart-summary-row #cart-shipping {
  font-weight: 600;
  color: var(--text-primary);
}

.cart-total-row {
  padding-top: 12px;
  margin-top: 6px;
  border-top: 1px solid var(--border-light);
  font-size: 1.05rem;
  color: var(--text-primary) !important;
  font-weight: 700;
}

.cart-total-row .cart-total {
  color: var(--accent);
  font-weight: 800;
  font-size: 1.15rem;
}

.cart-checkout-btn {
  display: block;
  width: 100%;
  text-align: center;
  background: var(--accent);
  color: var(--on-accent);
  padding: 14px;
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-top: 16px;
  transform: translate(var(--magnet-x, 0px), var(--magnet-y, 0px));
  transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}

.cart-checkout-btn:hover {
  background: var(--accent-hover);
  transform: translate(var(--magnet-x, 0px), calc(var(--magnet-y, 0px) - 2px));
  box-shadow: 0 4px 16px rgba(var(--accent-rgb), 0.3);
}

.cart-continue-btn {
  display: block;
  width: 100%;
  text-align: center;
  color: var(--text-secondary);
  padding: 10px;
  font-size: 0.82rem;
  margin-top: 8px;
  transition: color var(--transition-fast);
}

.cart-continue-btn:hover {
  color: var(--text-primary);
}

/* ===== TOAST NOTIFICATION ===== */
.toast {
  position: fixed;
  bottom: 30px;
  right: 30px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  padding: 1rem 1.5rem;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
  border-left: 4px solid var(--accent);
  transform: translateY(100px);
  opacity: 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 10000;
}

.toast.visible {
  transform: translateY(0);
  opacity: 1;
}

.toast i {
  color: var(--accent);
  font-size: 1.2rem;
}

/* ========================================
   PRODUCT DETAIL MODAL
   ======================================== */
.product-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: var(--bg-primary);
  z-index: 2000;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease-premium), visibility 0.4s var(--ease-premium);
}

.product-modal-overlay.open {
  opacity: 1;
  visibility: visible;
}

.product-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: var(--bg-primary);
  z-index: 2001;
  opacity: 0;
  visibility: hidden;
  transform: translateY(20px);
  transition: opacity 0.4s var(--ease-premium), visibility 0.4s var(--ease-premium), transform 0.4s var(--ease-premium);
  overflow-y: auto;
  border-radius: 0;
  border: none;
}

.product-modal.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.modal-close-btn {
  position: fixed;
  top: 20px;
  right: 20px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  color: var(--text-primary);
  width: 44px;
  height: 44px;
  border-radius: 0;
  cursor: pointer;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.modal-close-btn:hover {
  background: var(--text-primary);
  color: var(--bg-primary);
}

.modal-content-wrapper {
  display: flex;
  flex-direction: row;
  min-height: 100vh;
  width: 100%;
  padding: 0;
}

.modal-image-col {
  width: 68%;
  position: sticky;
  top: 0;
  height: 100vh;
  background: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid var(--border-color);
  padding: 0;
}

.modal-info-col {
  width: 32%;
  padding: 50px 30px;
  background: var(--bg-primary);
}

.modal-image-col .mockup-wrapper {
  width: 100%;
  max-width: 60vh;
  margin: 0 auto;
  border-radius: 0;
}

/* Non-poster product types (plate, wallpaper) skip the picture-frame
   mockup — just the plain photo, same treatment (radius/shadow) as the
   poster mockup wrapper so the modal layout doesn't shift between types. */
.modal-plain-image-wrapper {
  position: relative;
  border-radius: 0;
  overflow: hidden;
  width: 100%;
  max-width: 70vh;
  margin: 0 auto;
}

.modal-plain-image {
  display: block;
  width: 100%;
  aspect-ratio: 297 / 420;
  border-radius: var(--radius-md);
  object-fit: contain;
}

/* Lets a shopper browse straight to the next poster without closing the
   modal and re-opening one from the grid — scoped to whichever product
   cards are actually on screen (a carousel section, or the current
   filtered/paginated page), not the full catalog. */
.modal-next-btn {
  position: absolute;
  bottom: 14px;
  right: 14px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.6rem 1.1rem;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 50px;
  font-size: 0.85rem;
  font-weight: 600;
  backdrop-filter: blur(4px);
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.modal-next-btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  transform: translateX(3px);
}

.modal-info-col {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

#modal-title {
  font-family: var(--font-heading);
  font-size: var(--text-h2);
  margin: 0;
  font-weight: 800;
  letter-spacing: var(--tracking-tight);
  line-height: 1.1;
  color: var(--text-primary);
}

.modal-price-wrap {
  display: flex;
  align-items: center;
  gap: 1rem;
}

#modal-price {
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

#modal-original-price {
  text-decoration: line-through;
  color: var(--text-secondary);
}

/* Tabular figures wherever a price renders — proportional digits make a
   struck-through original price and the discounted price beside it drift
   out of alignment purely because "1" is narrower than "8". Listed by
   class/id across every page that shows a ₹ amount (product cards, modal,
   cart drawer, checkout summary, wall-setup packs). */
#modal-price,
#modal-original-price,
.item-price,
.list-item-price,
.price-breakdown,
.price-row,
.ws-old-price,
.ws-new-price,
#cart-subtotal,
#cart-total,
#cart-shipping {
  font-variant-numeric: tabular-nums;
}

.modal-description {
  color: var(--text-secondary);
  line-height: 1.6;
}

.variant-selectors {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  background: rgba(255,255,255,0.03);
  padding: 1.5rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.selector-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.selector-group label {
  font-size: 0.9rem;
  color: var(--text-secondary);
  font-weight: 500;
}

.selector-group select {
  padding: 0.75rem 2.2rem 0.75rem 0.75rem;
  /* background-color, not the background shorthand — the shorthand resets
     background-image too, which silently deleted the custom chevron the
     global `select` rule sets (arrow just vanished, no error anywhere). */
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  font-family: 'Inter', sans-serif;
  cursor: pointer;
}

.selector-group select:focus {
  border-color: var(--accent);
}

/* Swatch-style variant pickers — a tappable pill row reads faster than a
   dropdown and matches the custom checkbox/radio controls already shipped
   elsewhere in the form-control system. */
.swatch-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.swatch-btn {
  padding: 0.6rem 1rem;
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}

.swatch-btn small {
  font-weight: 500;
  opacity: 0.7;
  margin-left: 3px;
}

.swatch-btn:hover {
  border-color: var(--border-light);
}

.swatch-btn.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
}

.swatch-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.modal-add-to-cart {
  padding: 1rem;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: var(--radius-md);
  font-size: 1.1rem;
  font-weight: 600;
  cursor: pointer;
  transform: translate(var(--magnet-x, 0px), var(--magnet-y, 0px));
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.modal-add-to-cart:hover {
  transform: translate(var(--magnet-x, 0px), calc(var(--magnet-y, 0px) - 2px));
  box-shadow: 0 4px 15px rgba(var(--accent-rgb), 0.4);
}

/* Reviews */
.reviews-section {
  margin-top: 1rem;
  border-top: 1px solid var(--border-color);
  padding-top: 1.5rem;
}

.reviews-section h3 {
  font-size: 1.2rem;
  margin-bottom: 1rem;
}

.reviews-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-height: 300px;
  overflow-y: auto;
  margin-bottom: 1.5rem;
}

.review-item {
  background: rgba(255,255,255,0.03);
  padding: 1rem;
  border-radius: var(--radius-md);
}

.review-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.review-author {
  font-weight: 600;
  font-size: 0.95rem;
}

.review-stars {
  color: #fbbf24;
}

.review-date {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.review-text {
  font-size: 0.95rem;
  color: var(--text-secondary);
  margin: 0;
}

.review-photo {
  display: block;
  margin-top: 0.75rem;
  max-width: 140px;
  max-height: 140px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.review-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  background: rgba(255,255,255,0.02);
  padding: 1.5rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.review-form h4 {
  margin: 0;
}

.review-form input, .review-form select, .review-form textarea {
  padding: 0.75rem;
  background: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  font-family: inherit;
}

.review-form textarea {
  resize: vertical;
  min-height: 80px;
}

.review-form button {
  padding: 0.75rem;
  background: var(--text-primary);
  color: var(--bg-primary);
  border: none;
  border-radius: var(--radius-md);
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s;
}

.review-form button:hover {
  opacity: 0.9;
}

.review-photo-label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.7rem 0.9rem;
  background: var(--bg-primary);
  color: var(--text-secondary);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-md);
  font-size: 0.85rem;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.review-photo-label:hover {
  border-color: var(--accent);
  color: var(--text-primary);
}

.review-photo-preview {
  max-width: 100px;
  max-height: 100px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

/* The site-wide `img { display: block }` rule outranks the UA [hidden]
   stylesheet (author styles always beat UA styles), so the attribute
   alone doesn't hide this element without an explicit override. */
.review-photo-preview[hidden] {
  display: none;
}

@media (max-width: 768px) {
  .modal-content-wrapper {
    flex-direction: column;
    padding: 0;
  }
  .modal-image-col {
    width: 100%;
    height: auto;
    position: relative;
    padding: 20px;
    border-right: none;
    border-bottom: 1px solid var(--border-color);
    display: block;
  }
  .modal-info-col {
    width: 100%;
    padding: 30px 20px;
  }
  .product-modal {
    width: 100vw;
  }
  /* Keep the image to ~55% of the screen so the title, price, size and
     Add button are visible without scrolling on a phone. */
  .modal-plain-image-wrapper { max-width: min(100%, 44dvh); }
  .modal-image-col .mockup-wrapper { max-width: min(100%, 36dvh); margin-inline: auto; }
  .modal-info-col { padding: 22px 18px 30px; }
  /* Add button stays reachable while reading the details below it. */
  .modal-add-to-cart {
    position: sticky;
    bottom: calc(12px + env(safe-area-inset-bottom));
    z-index: 3;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  }
}

/* ===== ADD TO CART BUTTON FEEDBACK ===== */
.quick-add-btn.added {
  background: var(--success) !important;
  color: white !important;
  pointer-events: none;
}



/* ===== RESPONSIVE ===== */
@media (max-width: 1024px) {
  .navbar {
    padding: 0 24px;
  }

  .nav-links {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--bg-primary);
    flex-direction: column;
    justify-content: flex-start;
    gap: 28px;
    z-index: 1001;
    padding:  110px 40px 60px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  }

  .nav-links.open {
    display: flex;
  }

  .nav-links a {
    font-size: 1.4rem;
    color: var(--text-primary);
  }

  .menu-toggle {
    display: flex;
  }

  .features-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .categories-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .testimonials-grid {
    grid-template-columns: 1fr 1fr;
  }

  .testimonial-card:nth-child(2) {
    margin-top: 0; /* the desktop bento offset assumes a single row of 3 — doesn't apply once it wraps to 2 columns */
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 40px;
  }

  .app-grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .products-grid {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  }
}

@media (max-width: 640px) {
  .features-grid {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  .feature-item {
    padding: 20px 14px;
  }

  .categories-grid {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  .category-card-title {
    font-size: 1.7rem;
  }

  .testimonials-grid {
    grid-template-columns: 1fr;
  }

  .products-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }

  .product-card-info {
    padding: 12px;
  }

  .product-card-info h3 {
    font-size: 0.82rem;
  }

  .footer-grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .footer-bottom {
    flex-direction: column;
    text-align: center;
  }

  .hero {
    padding: 140px 0 16vh;
  }

  .scroll-nav {
    display: none;
  }
}

@media (max-width: 480px) {
  .announcement-bar {
    font-size: 0.7rem;
  }

  .products-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }

  .product-quick-actions {
    display: none;
  }

  /* Nav-actions never had a phone-width rule: 5 icon buttons (40px + 20px
     gap each) plus the hamburger toggle add up to ~300px on top of the
     brand logo and navbar padding — wider than the viewport itself on
     every real phone (iPhone SE at 375px up through most Android devices),
     so the cart button was pushed off-screen and unreachable. Shrinking
     the buttons and gap here, rather than hiding any of them, keeps every
     action reachable instead of trading functionality for fit. */
  .navbar {
    padding: 0 16px;
  }

  .nav-actions {
    gap: 2px;
  }

  .nav-action-btn,
  .menu-toggle {
    width: 32px;
    height: 32px;
  }

  .nav-action-btn {
    font-size: 1rem;
  }

  .menu-toggle {
    padding: 6px;
  }
}

/* ===== AUTH & PROFILE MODALS ===== */
.auth-modal-overlay, .profile-modal-overlay {
  position: fixed;
  top: 0; left: 0; width: 100%; height: 100%;
  background: rgba(0,0,0,0.8);
  backdrop-filter: blur(5px);
  z-index: 2000;
  opacity: 0; visibility: hidden;
  transition: opacity 0.3s var(--ease-premium), visibility 0.3s var(--ease-premium);
}

.auth-modal-overlay.open, .profile-modal-overlay.open {
  opacity: 1; visibility: visible;
}

.auth-modal, .profile-modal {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -47%) scale(0.95);
  width: 90%; max-width: 450px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  z-index: 2001;
  opacity: 0; visibility: hidden;
  transition: opacity 0.35s var(--ease-premium), visibility 0.35s var(--ease-premium), transform 0.35s var(--ease-premium);
  padding: 2rem;
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.7);
}
.profile-modal {
  max-width: 600px;
  max-height: 90vh;
  overflow-y: auto;
}

.auth-modal.open, .profile-modal.open {
  opacity: 1; visibility: visible;
  transform: translate(-50%, -50%) scale(1);
}

.auth-close-btn, .profile-close-btn {
  position: absolute; top: 15px; right: 15px;
  background: transparent; border: none; color: var(--text-primary);
  font-size: 1.2rem; cursor: pointer;
}

.auth-tabs {
  display: flex; gap: 1rem; margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border-color);
}
.auth-tab {
  background: none; border: none; padding: 0.5rem 1rem;
  color: var(--text-secondary); cursor: pointer;
  font-weight: 600; font-size: 1rem; border-bottom: 2px solid transparent;
}
.auth-tab.active {
  color: var(--text-primary); border-bottom-color: var(--accent);
}

.auth-form {
  display: none; flex-direction: column; gap: 1rem;
}
.auth-form.active {
  display: flex;
}

.auth-form h3, .profile-modal h2 { margin: 0 0 1rem 0; }
.form-group { display: flex; flex-direction: column; gap: 0.5rem; }
.form-group label { font-size: 0.9rem; color: var(--text-secondary); }
.form-group input, .form-group textarea {
  padding: 0.75rem; background: var(--bg-primary);
  border: 1px solid var(--border-color); color: var(--text-primary);
  border-radius: var(--radius-md); font-family: inherit;
}
.auth-submit-btn {
  padding: 0.75rem; background: var(--accent); color: var(--on-accent);
  border: none; border-radius: var(--radius-md); font-weight: 700; cursor: pointer;
  margin-top: 1rem;
}
.auth-error { color: var(--sale-red); font-size: 0.85rem; text-align: center; }

.order-history-section { margin-top: 2rem; border-top: 1px solid var(--border-color); padding-top: 1.5rem; }
#order-history-list { display: flex; flex-direction: column; gap: 1rem; max-height: 200px; overflow-y: auto; }
.order-item { background: var(--bg-primary); padding: 1rem; border-radius: var(--radius-md); border: 1px solid var(--border-color); }
.logout-btn {
  margin-top: 2rem; width: 100%; padding: 0.75rem;
  background: transparent; border: 1px solid var(--sale-red); color: var(--sale-red);
  border-radius: var(--radius-md); cursor: pointer; font-weight: 600;
}

/* Classes for what used to be inline styles in the modal markup (now the
   shared <site-overlays> component, site-overlays.js). */
site-overlays { display: contents; }
/* Homepage "Are you an organisation?" band */
.b2b-cta-section { border-top: 1px solid var(--border); }
.app-content .b2b-cta-title {
  font-size: var(--text-h2);
  margin-bottom: 1rem;
  overflow-wrap: break-word;
  hyphens: auto;
}
.b2b-cta-text { font-size: var(--text-large); margin-bottom: 2rem; }
/* The image carries a drop shadow; the shared .app-image clip cut it off. */
.b2b-cta-media { overflow: visible; }
.institutional-cta-img {
  width: 100%;
  height: auto;
  max-width: 400px;
  margin: 0 auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
}
.auth-success { color: var(--success); }
.auth-link-row { text-align: center; margin-top: 15px; }
.auth-link-row--end { text-align: right; margin: 0 0 15px; }
.auth-link {
  background: none;
  border: 0;
  padding: 4px 0;
  font: inherit;
  font-size: 0.9rem;
  color: var(--accent);
  cursor: pointer;
}
.auth-link:hover { text-decoration: underline; }
.auth-link--muted { color: var(--text-secondary); }
.auth-submit-btn--secondary {
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
}
.auth-submit-btn--secondary:hover { border-color: var(--accent); }
.profile-subform {
  margin-top: 2rem;
  border-top: 1px solid var(--border-color);
  padding-top: 1.5rem;
}
.orders-modal-title { font-family: var(--font-heading); margin-top: 0; }
.orders-modal-title + .order-history-section { margin-top: 1.5rem; }
.modal-stock-status { margin-top: 5px; font-weight: 600; font-size: 0.9rem; }
.accordion-list { padding-left: 20px; text-align: left; margin: 10px 0; }
/* --- Global Search Overlay --- */
.search-overlay {
  position: fixed;
  top: 70px;
  left: 0;
  width: 100%;
  height: auto;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  z-index: 10000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s var(--ease-premium);
}

.search-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.search-container {
  width: 100%;
  max-width: 450px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-xl);
  box-shadow: 0 20px 40px rgba(0,0,0,0.8);
  padding: 10px;
  position: relative;
  transform: translateY(-20px);
  transition: transform 0.35s var(--ease-premium);
}

.search-overlay.open .search-container {
  transform: translateY(0);
}

.search-close-btn {
  display: none; /* Hide close button as they can click outside */
}

.global-search-form {
  display: flex;
  align-items: center;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: 50px;
  overflow: hidden;
  padding: 4px 6px;
}

.search-suggestions {
  margin-top: 10px;
  max-height: 300px;
  overflow-y: auto;
  border-radius: var(--radius-md);
  display: none;
}
.search-suggestions.active {
  display: block;
}
.suggestion-item {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 10px 15px;
  cursor: pointer;
  border-radius: var(--radius-md);
  transition: background 0.2s;
  color: var(--text-primary);
  text-decoration: none;
}
.suggestion-item:hover {
  background: var(--bg-secondary);
}
.suggestion-item .mockup-wrapper {
  width: 40px;
  border-radius: var(--radius-md);
}
.suggestion-item-details {
  display: flex;
  flex-direction: column;
}
.suggestion-title {
  font-weight: 600;
  font-size: 0.95rem;
}
.suggestion-cat {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.global-search-form:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.2);
}

.global-search-form input {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--text-primary);
  font-size: 1.1rem;
  padding: 10px 15px;
  outline: none;
}

.global-search-form button {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  cursor: pointer;
  transition: transform 0.2s;
}

.global-search-form button:hover {
  transform: scale(1.05);
}

/* FAQ Section */
.faq-section {
  padding: var(--section-padding);
  background-color: var(--bg-secondary);
  border-top: 1px solid var(--border);
}

.faq-section .container {
  max-width: 1100px;
  margin: 0 auto;
}

.faq-title {
  text-align: center;
  font-family: var(--font-heading);
  font-size: 4rem;
  font-weight: 900;
  margin-bottom: 2rem;
  position: relative;
  display: inline-block;
  left: 50%;
  transform: translateX(-50%);
  color: var(--text-primary);
}

.faq-qmark {
  color: var(--accent);
  position: relative;
  z-index: 1;
}

.faq-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  align-items: center;
}

.faq-accordion-col {
  display: flex;
  flex-direction: column;
}

.faq-item {
  border-bottom: 1px solid var(--border);
  transition: background var(--transition-fast);
}

.faq-item:hover {
  background: rgba(var(--accent-rgb), 0.04);
}

.faq-question {
  width: 100%;
  background: none;
  border: none;
  padding: 1.5rem 0;
  padding-left: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-heading);
  font-size: 1.1rem;
  font-weight: 500;
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
  transition: color var(--transition-fast), padding-left var(--transition-fast);
}

.faq-question:hover {
  color: var(--accent);
  padding-left: 8px;
}

.faq-q-text {
  display: flex;
  align-items: center;
  gap: 12px;
}

.faq-q-text i {
  color: var(--accent);
  width: 20px;
  text-align: center;
}

.faq-toggle-icon {
  transition: transform 0.3s ease;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.faq-item.active .faq-toggle-icon {
  transform: rotate(180deg);
  color: var(--accent);
}

/* grid-template-rows 0fr->1fr, not the old max-height:0->500px hack — that
   guessed a large fixed max-height, so the transition duration applied
   across the full 500px regardless of how short the actual answer was
   (harmless for these short answers, but imprecise and not reusable if a
   longer answer is ever added). This animates to the exact natural content
   height instead, for every answer length. Needs the .faq-answer-inner
   wrapper in the markup — the row-track animates the grid container itself,
   while the inner div's own overflow:hidden clips its content during that. */
.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.faq-item.active .faq-answer {
  grid-template-rows: 1fr;
}

.faq-answer-inner {
  overflow: hidden;
  min-height: 0;
}

.faq-answer p {
  color: var(--text-secondary);
  line-height: 1.6;
  /* margin-bottom, not padding on the wrapper — padding doesn't collapse
     via min-height:0 (min-height constrains the content box, padding is
     added on top of it regardless), so at grid-template-rows: 0fr the
     collapsed row was stuck at 24px instead of 0. A margin on this
     innermost element does actually disappear once its clipped,
     zero-height ancestor stops rendering it. */
  margin: 0 0 1.5rem 0;
  padding-left: 32px;
}

.faq-image-col {
  display: flex;
  justify-content: center;
  align-items: center;
}

.faq-image-col img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-card);
  padding: 1.5rem;
  /* The source JPG is a flat illustration on a solid white canvas (no
     transparency), which in dark mode reads as a stray light panel dropped
     into an otherwise dark, photographic page. multiply blends that white
     canvas into --bg-card (white is the multiply identity, so it
     disappears into whatever's behind it) while the illustration's dark
     linework and color accents stay put — no new asset needed. In light
     mode --bg-card is already a near-white cream, so multiply is a no-op
     there and nothing changes. */
  mix-blend-mode: multiply;
}

@media (max-width: 900px) {
  .faq-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  
  .faq-image-col {
    order: -1;
  }
  
  .faq-image-col img {
    max-width: 80%;
  }
}

/* Custom Prints Section */
.custom-prints-section {
  padding: 6rem 0;
  background-color: var(--bg-primary);
}

.custom-prints-header {
  text-align: center;
  margin-bottom: 4rem;
  position: relative;
}

.custom-prints-title {
  font-family: var(--font-heading);
  font-size: 3rem;
  font-weight: 800;
  letter-spacing: -1px;
  margin: 0;
  line-height: 1.1;
  color: var(--text-primary);
}

.custom-prints-subtitle {
  font-size: 1.2rem;
  letter-spacing: 12px;
  font-weight: 400;
  color: var(--accent);
  display: block;
  margin-top: 10px;
}

.custom-prints-header .coming-soon-tag {
  position: absolute;
  top: -30px;
  right: 10%;
  background: var(--accent);
  color: var(--on-accent);
  padding: 6px 14px;
  border-radius: var(--radius-xl);
  font-size: 0.85rem;
  font-weight: 600;
}

.custom-prints-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  padding: 0 1rem;
}

.custom-print-card {
  position: relative;
  flex: 1 1 220px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0,0,0,0.3);
  transition: transform var(--transition-med), border-color var(--transition-med), box-shadow var(--transition-med);
  cursor: pointer;
  height: 400px;
}

.custom-print-card:hover {
  transform: translateY(-10px);
  border-color: var(--accent);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(var(--accent-rgb), 0.15);
}

.custom-print-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  transition: transform var(--transition-slow);
}

.custom-print-card:hover img {
  transform: scale(1.08);
}

.custom-print-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  padding: 1.5rem 1rem;
  z-index: 2;
  text-align: center;
  /* Always a dark scrim for legibility over the poster photo underneath —
     intentionally not theme-linked, unlike --bg-primary which flips in light mode. */
  background: linear-gradient(to bottom, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0) 100%);
  height: 150px;
}

.cursive-text {
  font-family: 'Brush Script MT', 'Dancing Script', cursive, var(--font-heading);
  font-size: 1.8rem;
  font-weight: 400;
  margin: 0 0 -5px 0;
  color: var(--accent);
}

.custom-print-overlay h2 {
  font-family: var(--font-heading);
  font-size: 1.2rem;
  font-weight: 800;
  margin: 0 0 10px 0;
  letter-spacing: -0.5px;
  color: var(--brand-cream); /* sits on a permanent dark scrim over a photo — stays light in both themes */
}

.custom-print-btn {
  background: var(--bg-secondary);
  color: var(--text-muted);
  border: 1px solid var(--border-light);
  padding: 6px 16px;
  font-size: 0.75rem;
  border-radius: var(--radius-xl);
  cursor: not-allowed;
  opacity: 0.9;
}

@media (max-width: 1200px) {
  .custom-prints-grid {
    gap: 1.25rem;
  }
  .custom-prints-header .coming-soon-tag {
    right: 5%;
  }
}

@media (max-width: 768px) {
  .custom-prints-grid {
    gap: 1rem;
  }
  .custom-print-card {
    flex-basis: calc(50% - 0.5rem);
    height: 320px;
  }
  .custom-prints-header .coming-soon-tag {
    position: relative;
    top: auto;
    right: auto;
    display: inline-block;
    margin-bottom: 15px;
  }
}

@media (max-width: 480px) {
  .custom-print-card {
    flex-basis: 100%;
    height: 300px;
  }
}

/* Content Protection Styles */
body {
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

input, textarea {
  -webkit-user-select: auto;
  user-select: auto;
}

img {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  -webkit-touch-callout: none;
}

/* Wall Setup Packs */
.wall-setup-section {
  padding: 5rem 0;
  background-color: var(--bg-primary);
  border-top: 1px solid var(--border);
}

.ws-header {
  text-align: center;
  margin-bottom: 3rem;
}

.ws-title-main {
  font-family: var(--font-heading);
  font-size: 2.5rem;
  font-weight: 800;
  letter-spacing: 2px;
  margin: 0;
  color: var(--text-primary);
}

.ws-subtitle {
  font-size: 0.75rem;
  letter-spacing: 8px;
  color: var(--text-secondary);
  text-transform: uppercase;
  margin-top: 10px;
}

.ws-track .wall-setup-card {
  flex-shrink: 0;
  width: 280px;
  scroll-snap-align: start;
}

.wall-setup-card {
  text-align: center;
  transition: transform var(--transition-med);
  cursor: pointer;
}

.wall-setup-card:hover {
  transform: translateY(-5px);
}

/* The glow goes on .ws-img-container, not .wall-setup-card itself — the
   card is just a text-align wrapper with no background/border of its own,
   so a shadow on it wouldn't read as anything (no visible edge to glow
   from). .ws-img-container is the actual bordered box. */
.wall-setup-card:hover .ws-img-container {
  border-color: var(--accent);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35), 0 0 30px rgba(var(--accent-rgb), 0.15);
}

.ws-img-container {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  margin-bottom: 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  transition: border-color var(--transition-med), box-shadow var(--transition-med);
}

.ws-img-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-slow);
  /* --ws-parallax-x is set via JS (script.js's updateCardParallax, extended
     in Phase 8 to cover this carousel too) as the track scrolls — composed
     here via a custom property, not by JS writing .style.transform
     directly, so it doesn't clobber the :hover scale below (inline styles
     would win over the class rule and silently kill the zoom on hover). */
  transform: translateX(var(--ws-parallax-x, 0px));
}

.wall-setup-card:hover .ws-img-container img {
  transform: translateX(var(--ws-parallax-x, 0px)) scale(1.05);
}

.ws-sale-badge {
  position: absolute;
  bottom: 10px;
  left: 10px;
  background: var(--sale-bg);
  color: #fff;
  padding: 4px 12px;
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: var(--radius-lg);
}

.ws-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 5px 0;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ws-brand {
  font-size: 0.7rem;
  color: var(--accent);
  letter-spacing: 1px;
  font-weight: 600;
  margin: 0 0 10px 0;
}

.ws-pricing {
  font-size: 0.9rem;
}

.ws-old-price {
  text-decoration: line-through;
  color: var(--text-muted);
  margin-right: 8px;
  font-size: 0.8rem;
}

.ws-new-price {
  font-weight: 700;
  color: var(--text-primary);
}

@media (max-width: 768px) {
  .ws-track .wall-setup-card {
    width: 240px;
  }
}

/* =========================================
   Reach Out Section & Modals
========================================= */
.reachout-section {
  padding: 80px 20px;
  background: var(--bg-primary);
}

.reachout-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 32px;
  margin-top: 40px;
}

.reachout-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 40px 32px;
  text-align: center;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}

.reachout-card:hover {
  transform: translateY(-5px);
  border-color: var(--accent);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3), 0 0 24px rgba(var(--accent-rgb), 0.12);
}

.reachout-icon {
  font-size: 2.5rem;
  color: var(--accent);
  margin-bottom: 24px;
  display: inline-block;
  transition: transform var(--transition-med);
}

.reachout-card:hover .reachout-icon {
  transform: scale(1.15) rotate(-4deg);
}

.reachout-card h3 {
  font-family: var(--font-heading);
  font-size: 1.4rem;
  margin-bottom: 12px;
}

.reachout-card p {
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
  margin-bottom: 24px;
  min-height: 44px;
}

.reachout-btn {
  width: 100%;
  background: transparent;
  border: 2px solid var(--accent);
  color: var(--accent);
  padding: 12px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition-fast);
}

.reachout-btn:hover {
  background: var(--accent);
  color: var(--on-accent);
}

/* Modals */
.reachout-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(5px);
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast);
}

.reachout-modal-overlay.active {
  opacity: 1;
  pointer-events: auto;
}

.reachout-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -45%);
  width: 90%;
  max-width: 500px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 40px;
  z-index: 1001;
  opacity: 0;
  pointer-events: none;
  transition: all var(--transition-med);
  box-shadow: 0 20px 40px rgba(0,0,0,0.5);
}

.reachout-modal.active {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%);
}

.reachout-close-btn {
  position: absolute;
  top: 20px;
  right: 20px;
  background: transparent;
  border: none;
  color: var(--text-secondary);
  font-size: 1.2rem;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.reachout-close-btn:hover {
  color: var(--accent);
}

.reachout-modal h3 {
  font-family: var(--font-heading);
  font-size: 1.6rem;
  margin-bottom: 24px;
  text-align: center;
}

.reachout-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.reachout-form .hero-cta {
  margin-top: 10px;
  width: 100%;
  border: none;
  cursor: pointer;
}

/* ===== PRODUCT ACCORDIONS ===== */
.product-accordions {
  margin-top: 2rem;
  border-top: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
}

.product-accordion {
  border-bottom: 1px solid var(--border-color);
}

.product-accordion summary {
  padding: 1.2rem 0;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.1rem;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.product-accordion summary::-webkit-details-marker {
  display: none;
}

.product-accordion summary::after {
  content: '+';
  font-size: 1.5rem;
  font-weight: 400;
  transition: transform 0.3s ease;
}

.product-accordion[open] summary::after {
  content: '-';
  transform: rotate(180deg);
}

.product-accordion .accordion-content {
  padding-bottom: 1.2rem;
  font-size: 0.95rem;
  color: var(--text-secondary);
  line-height: 1.5;
}

/* ===== SKELETON LOADER ===== */
.shimmer-bg {
  background: var(--bg-secondary);
  background-image: linear-gradient(
    90deg,
    rgba(0,0,0, 0) 0,
    rgba(0,0,0, 0.05) 20%,
    rgba(0,0,0, 0.1) 60%,
    rgba(0,0,0, 0)
  );
  background-size: 200% 100%;
  animation: flipkartShimmer 1.5s infinite linear;
}
:root[data-theme="dark"] .shimmer-bg {
  background-image: linear-gradient(
    90deg,
    rgba(255,255,255, 0) 0,
    rgba(255,255,255, 0.08) 20%,
    rgba(255,255,255, 0.15) 60%,
    rgba(255,255,255, 0)
  );
}
@keyframes flipkartShimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.skeleton-card { pointer-events: none; }
.skeleton-card .product-image-container { aspect-ratio: 4/5; width: 100%; }
.skeleton-text { border-radius: 2px; }

/* ===== TRUSTED BY SECTION ===== */
.trusted-by-section {
  padding: 60px 0;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-primary);
  text-align: center;
  overflow: hidden;
}

.trusted-title {
  font-family: var(--font-heading);
  font-size: var(--text-small);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-muted);
  margin-bottom: 40px;
  font-weight: 700;
}

.trusted-logos {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(40px, 8vw, 100px);
  flex-wrap: wrap;
}

.trusted-logo {
  font-family: var(--font-heading);
  font-size: clamp(1.2rem, 3vw, 1.8rem);
  font-weight: 900;
  letter-spacing: var(--tracking-tighter);
  color: var(--text-primary);
  opacity: 0.3;
  transition: opacity var(--transition-fast), transform var(--transition-fast);
  cursor: default;
}

.trusted-logo:hover {
  opacity: 1;
  transform: scale(1.05);
}

.category-card:hover .plain-product-image { transform: scale(1.05); filter: grayscale(100%); transition: all var(--transition-med); }

.list-item:hover .plain-product-image {
  transform: scale(1.05);
  filter: grayscale(100%);
  transition: all var(--transition-med);
}


/* =====================================================================
   FIXES — layout stability & category cards (Sep 2026 debugging pass)
   ===================================================================== */

/* Category cards: every card gets the same 4:5 media box, whatever the
   source image's shape, so the four tiles line up in one clean row. */
.category-card {
  display: flex;
  flex-direction: column;
  text-decoration: none;
}
.category-card-media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bg-secondary);
}
.category-card-media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--transition-slow), filter var(--transition-med);
}
.category-card:hover .category-card-media > img {
  transform: scale(1.05);
  filter: none;
}
.category-card-overlay { z-index: 1; }
.category-card-title {
  font-size: clamp(0.95rem, 1.6vw, 1.15rem);
}

/* Product imagery: never collapse, never letterbox. */
.product-card-image > img,
.list-item-img-wrapper > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.product-card-image > img { position: absolute; inset: 0; }
.product-card-image .product-badge,
.product-card-image .product-quick-actions { z-index: 2; }

/* Skeletons in the carousels share the real card's footprint so nothing
   jumps when products arrive. */
.scroll-track .skeleton-card .product-image-container {
  aspect-ratio: 2193 / 3348;
}

.products-error {
  padding: 2rem 1rem;
  color: var(--text-secondary);
  text-align: center;
  width: 100%;
}

/* width/height attributes are there for layout stability only. */
.faq-image-col img,
.app-image img { height: auto; }

/* Reveal safety net: if JS never runs, nothing stays invisible. */
.no-js .fade-in,
.no-js .scale-in { opacity: 1; transform: none; }

/* Mobile navbar sheet sits below the pill's own controls. */
@media (max-width: 1024px) {
  .nav-links { z-index: -1; padding-top: 110px; }
  .nav-links.open { z-index: 1; }
  .nav-actions { position: relative; z-index: 2; }
  .nav-brand { position: relative; z-index: 2; }
}

@media (max-width: 640px) {
  .category-card-title { font-size: 0.95rem; padding: 12px; }
  .category-card-overlay { padding: 14px; }
  .category-card-overlay p { font-size: 0.72rem; }
}

@media (max-width: 480px) {
  .navbar { width: calc(100% - 20px); }
}

/* Signed-in greeting next to the account icon — first name only, never wraps. */
.nav-action-btn.has-greeting {
  width: auto;
  padding: 0 10px 0 8px;
  border-radius: 999px;
  gap: 6px;
}
.nav-action-btn.has-greeting svg { flex-shrink: 0; width: 22px !important; height: 22px !important; }
.nav-user-greeting {
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 640px) {
  .nav-user-greeting { display: none; }
  .nav-action-btn.has-greeting { width: 40px; padding: 0; }
}
@media (max-width: 480px) {
  .nav-action-btn.has-greeting { width: 32px; }
  .nav-brand img { height: 26px !important; }
}

/* Hide shimmer once image loads to prevent it showing through transparent PNGs forever */
.product-card-image:has(img.loaded)::before,
.mockup-wrapper:has(img.loaded)::before,
.modal-plain-image-wrapper:has(img.loaded)::before {
  display: none !important;
}

/* Custom crop for apparel cards to show the design clearly while keeping it fully visible */
.plain-product-image.apparel-card-img {
  object-fit: cover;
  object-position: center 25%;
}

/* ===== APPAREL GALLERY (product modal) =====
   Back / Front / Design layout / Size chart. Zoom scales the active image
   in place around the cursor (transform-origin follows the pointer), so
   there is no separate lens to misalign. */
.apparel-gallery {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  outline: none;
}
.ag-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: var(--bg-secondary);
  cursor: default;
}
.ag-stage.in-zoom-zone { cursor: zoom-in; }
.apparel-gallery.ag-no-zoom .ag-hint { display: none; }
.ag-slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s ease, visibility 0.35s;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ag-slide.is-active { opacity: 1; visibility: visible; }
.ag-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1);
  transition: transform 0.25s ease-out;
  user-select: none;
  -webkit-user-drag: none;
}
.ag-slide[data-fit="contain"] { padding: 3%; background: #f7f5f1; }
.ag-slide[data-fit="contain"] img { object-fit: contain; }
/* Hoodie print art: transparent PNGs in dark ink, and the resized webp the
   image pipeline serves is flattened onto white — so this fit is pure white
   rather than the warm card, or the flattened edge would show as a rectangle. */
.ag-slide[data-fit="print"] { padding: 4%; background: #fff; }
.ag-slide[data-fit="print"] img { object-fit: contain; }
.ag-slide.is-zoomed img { transform: scale(var(--ag-zoom, 2.4)); transition: transform 0.2s ease-out; }
.ag-slide.is-locked { cursor: zoom-out; }
.ag-stage.in-zoom-zone:has(.ag-slide.is-active.is-locked) { cursor: zoom-out; }

.ag-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--bg-primary) 88%, transparent);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease;
}
.ag-nav:hover { transform: translateY(-50%) scale(1.08); }
.ag-prev { left: 18px; }
.ag-next { right: 18px; }
.ag-hint {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 3;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.ag-stage:has(.is-zoomed) .ag-hint { opacity: 0; }

.ag-thumbs {
  display: flex;
  gap: 10px;
  padding: 12px 16px;
  overflow-x: auto;
  scrollbar-width: none;
  background: var(--bg-primary);
  border-top: 1px solid var(--border-color);
  justify-content: center;
}
.ag-thumbs::-webkit-scrollbar { display: none; }
.ag-thumb {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 4px;
  border-radius: var(--radius-lg);
  border: 1px solid transparent;
  background: none;
  color: var(--text-secondary);
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.ag-thumb img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  opacity: 0.7;
  transition: opacity 0.2s ease;
}
/* Contain-fit slides (hoodie prints, size chart) are transparent artwork in
   dark ink — they need the same light card in the thumb strip that they get
   on the stage, or they read as empty squares on the dark modal. */
.ag-thumb[data-fit="print"] img,
.ag-thumb[data-fit="contain"] img {
  object-fit: contain;
  background: #fff;
  padding: 4px;
}
.ag-thumb:hover img,
.ag-thumb.is-active img { opacity: 1; }
.ag-thumb.is-active { border-color: var(--accent); color: var(--text-primary); }

.modal-image-col:has(.apparel-gallery) { align-items: stretch; }

@media (max-width: 768px) {
  .modal-image-col:has(.apparel-gallery) { padding: 0; }
  .apparel-gallery { height: auto; display: block; }
  .ag-stage { flex: none; aspect-ratio: 4 / 5; }
  .ag-nav { width: 38px; height: 38px; }
  .ag-prev { left: 10px; }
  .ag-next { right: 10px; }
  .ag-thumb img { width: 52px; height: 52px; }
}
.modal-image-col:has(.apparel-gallery) .modal-next-btn { bottom: 108px; }

/* ===== NAV: CATEGORIES DROPDOWN ===== */
.nav-dropdown { position: relative; }
.nav-dd-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition-fast);
}
.nav-dd-toggle:hover,
.nav-dropdown.open .nav-dd-toggle { color: var(--text-primary); }
.nav-dd-caret { font-size: 0.65em; transition: transform 0.25s ease; }
.nav-dropdown.open .nav-dd-caret { transform: rotate(180deg); }

.nav-dd-panel {
  position: absolute;
  top: calc(100% + 22px);
  left: 50%;
  width: 520px;
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 8px 22px;
  padding: 20px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.18);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 8px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
  z-index: 5;
}
.nav-links .nav-dd-item.nav-dd-item--feature {
  margin-top: 6px;
  border-top: 1px solid var(--border-light);
  padding-top: 12px;
  color: var(--accent);
}

/* invisible bridge so the pointer can travel from toggle to panel */
.nav-dd-panel::before { content: ''; position: absolute; left: 0; right: 0; top: -24px; height: 24px; }
.nav-dropdown.open .nav-dd-panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.nav-dd-heading {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted, var(--text-secondary));
  margin: 0 0 8px;
}
.nav-links .nav-dd-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  margin: 0 -10px;
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-weight: 600;
  transition: background 0.15s ease;
}
.nav-links .nav-dd-item i {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
  font-size: 0.85rem;
}
.nav-links .nav-dd-item:hover { background: var(--bg-secondary); }
.nav-dd-genres { display: flex; flex-wrap: wrap; gap: 8px; }
/* Sub-categories under a product type (Apparel -> T-Shirts / Hoodies) */
.nav-dd-subs { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 8px 40px; }
.nav-links .nav-dd-genre {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.nav-links .nav-dd-genre:hover { border-color: var(--accent); color: var(--accent); }
.nav-links .nav-dd-all {
  display: inline-block;
  margin-top: 16px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--accent);
}
.nav-dropdown .nav-dd-panel a::after { display: none; }

@media (max-width: 1024px) {
  .nav-dropdown { width: 100%; max-width: 420px; text-align: center; }
  .nav-dd-toggle { font-size: 1.4rem; color: var(--text-primary); }
  .nav-dd-panel {
    position: static;
    width: 100%;
    display: none;
    grid-template-columns: 1fr;
    transform: none;
    opacity: 1;
    visibility: visible;
    margin-top: 14px;
    padding: 14px;
    box-shadow: none;
    text-align: left;
  }
  .nav-dropdown.open .nav-dd-panel { display: grid; transform: none; }
  .nav-dd-panel::before { display: none; }
  .nav-links .nav-dd-item { font-size: 1rem; }
  .nav-links .nav-dd-genre { font-size: 0.8rem; }
  .nav-links .nav-dd-all { font-size: 0.9rem; }
  
}

/* Five product categories: one row on wide screens, balanced wrap below. */
.categories-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1100px) { .categories-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .categories-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .categories-grid > .category-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .categories-grid > .category-card:last-child:nth-child(odd) .category-card-media { aspect-ratio: 16 / 9; }
}

/* ===== STAR RATINGS ===== */
:root { --star-on: #f5a623; --star-off: color-mix(in srgb, var(--text-secondary) 28%, transparent); }
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Read-only strip: a 5-star mask filled to --rating/5 of its width. */
.stars {
  --size: 16px;
  display: inline-block;
  vertical-align: middle;
  width: calc(var(--size) * 5);
  height: var(--size);
  flex-shrink: 0;
  background: linear-gradient(90deg, var(--star-on) calc(var(--rating, 0) / 5 * 100%), var(--star-off) 0);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z'/%3E%3C/svg%3E") left center / var(--size) var(--size) repeat-x;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z'/%3E%3C/svg%3E") left center / var(--size) var(--size) repeat-x;
}
.stars.stars-sm { --size: 12px; }
.testimonial-stars .stars { --size: 17px; }
.review-stars { margin-bottom: 6px; }

.card-rating {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 2px 0 6px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.modal-rating {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 14px;
  padding: 4px 0;
  background: none;
  border: none;
  font: inherit;
  font-size: 0.85rem;
  color: var(--text-secondary);
  cursor: pointer;
}
.modal-rating .stars { --size: 18px; }
.modal-rating-value { font-weight: 700; color: var(--text-primary); }
.modal-rating:hover .modal-rating-count { text-decoration: underline; }

/* Interactive picker. Radios run 5→1 in the DOM with row-reverse so
   "this star and every star before it" is just `:hover ~ label`. */
.star-input { display: flex; flex-direction: column; gap: 6px; }
.star-input-stars {
  display: inline-flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: 4px;
}
.star-input input[type="radio"] { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.star-input label {
  width: 34px;
  height: 34px;
  cursor: pointer;
  background: var(--star-off);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: background 0.15s ease, transform 0.15s ease;
}
.star-input input:checked ~ label,
.star-input-stars:not(:hover) input:checked ~ label { background: var(--star-on); }
.star-input-stars:hover label { background: var(--star-off); }
.star-input-stars label:hover,
.star-input-stars label:hover ~ label { background: var(--star-on); transform: scale(1.12); }
.star-input input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-md); }
.star-input label.pop { animation: starPop 0.35s ease; }
@keyframes starPop { 0% { transform: scale(1); } 45% { transform: scale(1.35); } 100% { transform: scale(1); } }
.star-input-caption { font-size: 0.8rem; font-weight: 600; color: var(--text-secondary); }
.star-input-caption.is-preview { color: var(--star-on); }
.star-input.needs-rating .star-input-caption { color: var(--sale-red, #e5484d); }
.star-input.shake { animation: starShake 0.4s ease; }
@keyframes starShake { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
@media (prefers-reduced-motion: reduce) {
  .star-input label.pop, .star-input.shake { animation: none; }
}
@media (max-width: 768px) {
  .ag-hint { left: 12px; transform: none; bottom: 12px; }
  .modal-image-col:has(.apparel-gallery) .modal-next-btn { bottom: 96px; right: 12px; }
}

/* ===== VARIANT SWATCHES ===== */
.swatch-btn[hidden] { display: none !important; }
.swatch-group--size .swatch-btn { min-width: 58px; padding: 0.55rem 0.8rem; }
.swatch-group--style { display: grid; grid-template-columns: 1fr; gap: 0.5rem; }
.swatch-group--style .swatch-btn {
  display: flex;
  justify-content: space-between;
  align-items: center;
  text-align: left;
}
.swatch-group.is-single .swatch-btn { cursor: default; }
.variant-note {
  margin: 0.25rem 0 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

.cart-total-note { display: block; font-size: 0.68rem; font-weight: 500; color: var(--text-secondary); margin-top: 2px; }

/* Design-layout slide: same 10:7 frame as the tee photos — show it whole,
   as large as the stage allows, on a neutral backdrop. */
.ag-slide[data-fit="sheet"] { background: var(--bg-secondary); }
.ag-slide[data-fit="sheet"] img { object-fit: contain; }




/* ===== COLLECTIBLE MODAL LAYOUT ===== */
.modal-content-wrapper[data-product-type="collectibles" i] .modal-image-col {
  /* Width now comes from --media-col like every other type — this block used
     to pin it to 40-60%, which left a fifth of the column empty beside a tall
     figure. Only the transparent ground is collectible-specific. */
  background: var(--bg-primary);
}
.modal-content-wrapper[data-product-type="collectibles" i] .modal-info-col {
  flex: 1;
  width: auto;
}
.modal-content-wrapper[data-product-type="collectibles" i] .ag-stage {
  aspect-ratio: 2 / 3;
  margin: auto;
  max-height: calc(100vh - 120px);
  background: transparent;
}
.ag-slide[data-fit="collectible"] { padding: 0; background: transparent; }
.ag-slide[data-fit="collectible"] img { object-fit: contain; }

/* Collectible Mobile Overrides */
@media (max-width: 768px) {
  .modal-content-wrapper[data-product-type="collectibles" i] .modal-image-col {
    width: 100%;
    max-width: 100%;
    height: auto;
    border-bottom: 1px solid var(--border-color);
    padding: 0;
    display: block;
  }
  .modal-content-wrapper[data-product-type="collectibles" i] .ag-stage {
    aspect-ratio: 2 / 3;
    max-height: 70vh;
  }
}

/* Prevent cropping constraint on cards */
.product-card[data-product-type="collectibles" i] .product-card-image,
.product-card[data-product-type="collectibles" i] .list-item-img-wrapper,
.product-card[data-product-type="collectibles" i] .mockup-wrapper {
  aspect-ratio: 2 / 3 !important;
  background: transparent;
}
.product-card[data-product-type="collectibles" i] .product-card-image > img,
.product-card[data-product-type="collectibles" i] .list-item-img-wrapper > img {
  object-fit: contain !important;
}

/* Ensure category card for collectibles uses a smart crop to keep the figurine's face in view */
.category-card[href="all_products.html?type=Collectibles"] .category-card-media > img {
  object-fit: cover;
  object-position: center 25%;
}

/* ===== FIX: aspect-ratio collapse & overlap on iOS Safari ===== */
@media (max-width: 992px) {
  /* Give the wrapper a deterministic height to break the auto/100% cyclical dependency on Safari */
  .list-item-img-wrapper {
    aspect-ratio: 4 / 5;
    min-height: 0; /* Bypass flex item minimum height calc bug */
  }
  
  /* Collectibles have a taller photo frame */
  .product-card[data-product-type="collectibles" i] .list-item-img-wrapper {
    aspect-ratio: 2 / 3;
  }
  
  /* Apparel photos are variable, but fallback to 4/5 logic is fine or auto if we want */
  .product-card[data-product-type="apparel" i] .list-item-img-wrapper,
  .product-card[data-product-type="hoodie" i] .list-item-img-wrapper {
    /* Apparel can just use 4/5 ratio container in list view for uniformity */
    aspect-ratio: 4 / 5;
  }

  /* Make sure the image inside fills the deterministic wrapper */
  .list-item-img-wrapper > img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100% !important;
    object-fit: cover;
  }
}

/* =====================================================================
   TOUCH TARGETS (phones & tablets)
   Text links that read fine with a mouse were 15-24px tall on touch
   screens. Padding (not font size) brings them to ~40px, compensating
   margins keep the visual rhythm the same.
   ===================================================================== */
@media (max-width: 900px) {
  .footer-column ul li { margin-bottom: 0; }
  .footer-column ul li a,
  .footer-bottom-links a,
  .footer-contact a {
    display: inline-block;
    padding: 10px 0;
  }
  .footer-contact li { margin-bottom: 0; }
  .footer-disclaimer { font-size: 0.75rem; }

  .announcement-bar a {
    display: inline-block;
    padding: 6px 0;
  }
}

/* ===== OVERLAY CLICK-BLOCKING =====
   Every overlay above hides itself with `visibility: hidden` and TRANSITIONS
   that property. A transition only reaches its end value when the document's
   animation timeline advances — and the timeline stops dead whenever the tab
   is backgrounded. Close a product and switch app or tab inside the 0.4s fade
   and the transition freezes at time zero: the modal stays `visibility:
   visible`, full-viewport, z-index 2001, and every click on the page lands on
   it instead of the page. It looks like the whole site has died.

   `pointer-events` is never transitioned, so it flips the instant the `.open`
   class comes off, however the fade is doing. Making it — not visibility —
   the thing that decides whether an overlay swallows clicks removes the whole
   failure mode, and also stops the closing overlay eating a click during the
   fade. The visual fade is untouched.

   Ordered after the rules it corrects so it wins on equal specificity. */
.product-modal,
.product-modal-overlay,
.cart-drawer,
.cart-overlay,
.auth-modal,
.profile-modal,
.auth-modal-overlay,
.profile-modal-overlay,
.search-overlay,
.nav-dd-panel,
.scroll-top {
  pointer-events: none;
}

.product-modal.open,
.product-modal-overlay.open,
.cart-drawer.open,
.cart-overlay.open,
.auth-modal.open,
.profile-modal.open,
.auth-modal-overlay.open,
.profile-modal-overlay.open,
.search-overlay.open,
.scroll-top.visible,
.scroll-top.show,
.scroll-top.is-visible {
  pointer-events: auto;
}

/* The categories dropdown is revealed by a class on its parent. */
.nav-dropdown.open .nav-dd-panel {
  pointer-events: auto;
}

/* ===== CAROUSEL ARROW HIT AREA =====
   The arrows are 44px circles sitting half over the first/last card. Because
   `border-radius: 50%` clips hit-testing too, the four corners of the button's
   box are NOT the button — a click a few pixels off-centre falls through to
   the product card behind and opens that product instead of scrolling the
   row. The arrow reads as only working on part of itself.

   This pseudo-element gives each arrow a forgiving rounded-square target a
   little larger than the circle. It is transparent, so nothing changes
   visually, and it inherits the button's z-index, so it sits above the cards.
   `.scroll-nav i` is already pointer-events:none, so the icon never steals
   the click from it. */
.scroll-nav::after {
  content: '';
  position: absolute;
  inset: -11px;
  border-radius: 16px;
}

/* A disabled arrow must not keep swallowing clicks meant for the card. */
.scroll-nav:disabled::after {
  content: none;
}

/* ===== PRODUCT MODAL: MEDIA COLUMN FOLLOWS THE ARTWORK =====
   The image column used to be a fixed 68% of the modal whatever the product,
   and the artwork inside was capped at 70vh. A portrait poster is height-
   bound, so it rendered ~585px wide inside a ~1010px column: 42% of the
   image side was empty grey. Stickers had the same shape and the same gap;
   collectibles wasted 20%.

   Now `--media-col` is set per product by fitModalMedia() in script.js from
   the artwork's real aspect ratio, so the column is only as wide as the art
   it holds plus a gutter, and the info column takes everything that is left.
   The fallback value keeps the old proportions if the script hasn't measured
   yet (or the image never loads), so nothing collapses. */
@media (min-width: 769px) {
  .modal-image-col {
    width: var(--media-col, 68%);
    flex: 0 0 var(--media-col, 68%);
  }

  .modal-info-col {
    width: auto;
    flex: 1 1 0;
    min-width: 0;            /* let it shrink; the default min-content floor overflows */
    padding-inline: clamp(28px, 4vw, 64px);
  }

  /* The info column is now wider on portrait products. Capping and centring
     the content stack keeps the text at a readable measure and makes the
     slack read as deliberate margin.
     (Percentage padding was tried first and is wrong here: percentages in
     padding resolve against the CONTAINING BLOCK's width, not the element's,
     so it inflated the column's min-content width and overflowed the modal.) */
  .modal-info-col > * {
    width: 100%;
    max-width: 620px;
    margin-inline: auto;
  }

  /* With the column cut to the artwork's shape there is nothing left to letterbox
     against, so the art fills it and the old 70vh cap is redundant. */
  .modal-plain-image-wrapper {
    max-width: none;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(18px, 3vh, 40px);
  }

  .modal-image-col .mockup-wrapper { max-width: none; }

  /* The forced A4 box was letterboxing every non-A4 product (stickers, plates,
     wallpapers) a second time inside an already-oversized column. The image
     now keeps its own proportions. */
  .modal-plain-image {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    aspect-ratio: auto;
    object-fit: contain;
  }
}

/* ==========================================================================
   PRODUCT SPEC COPY  (product-copy.js)
   The modal accordions are rendered per product type, so a hoodie shows
   fabric, GSM, a size chart and print areas where a poster shows paper
   stock. These styles cover the shared pieces those blocks are built from.
   ========================================================================== */
.product-accordion summary i {
  font-size: 0.85em;
  width: 1.15em;
  margin-right: 8px;
  color: var(--text-secondary);
}
.product-accordion .spec-list {
  list-style: none;
  padding: 0;
  margin: 0;
  text-align: left;
}
.product-accordion .spec-list li {
  position: relative;
  padding-left: 16px;
  margin: 0 0 7px;
  line-height: 1.55;
}
.product-accordion .spec-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-secondary);
  opacity: 0.55;
}
.product-accordion .spec-list li + li { margin-top: 0; }
.product-accordion .accordion-content p + p,
.product-accordion .accordion-content .spec-list + p,
.product-accordion .accordion-content p + .spec-list { margin-top: 10px; }
.product-accordion .spec-note {
  font-size: 0.86em;
  opacity: 0.72;
  margin-top: 10px;
}

/* Size chart. Scrolls sideways on a phone instead of squeezing the columns
   into unreadable widths. */
.spec-table-wrap {
  margin: 12px 0 2px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.spec-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 320px;
  font-size: 0.9em;
  text-align: center;
}
.spec-table th,
.spec-table td {
  border: 1px solid var(--border-color, rgba(128, 128, 128, 0.25));
  padding: 6px 10px;
  white-space: nowrap;
}
.spec-table tr:first-child th {
  font-weight: 600;
  background: rgba(128, 128, 128, 0.08);
}
.spec-table tr th:first-child {
  text-align: left;
  font-weight: 500;
}

/* Colour swatches on the variant selector — a dot ahead of the name, so
   "Bottle Green" is a colour and not just a word. */
.swatch-btn .swatch-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 7px;
  vertical-align: -1px;
  background: var(--dot);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.28);
}

/* ==========================================================================
   SCROLL LOCK  (script.js lockPageScroll / global-navbar.js lockScroll)
   `body { overflow: hidden }` does not lock this page: `html` above carries
   `overflow-x: hidden`, which per spec computes the other axis to `auto`,
   making <html> the scroll container — body's rule then propagates nowhere.
   On desktop lenis.stop() hid the problem; on touch, where Lenis does not
   handle scroll at all, the catalogue scrolled behind an open product modal.
   Pinning the body is what actually stops it. The inline `top: -<scrollY>px`
   that script.js sets keeps the page visually where it was.
   ========================================================================== */
html.scroll-locked {
  overflow: hidden;
}
html.scroll-locked body {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
  /* `top` is set inline by the lock, so it must not be declared here. */
}

/* ==========================================================================
   FULL-SCREEN OVERLAYS ON MOBILE
   100vh on iOS Safari is the *large* viewport — the height the page would
   have with the browser toolbars hidden — so a 100vh overlay runs underneath
   the address bar and the bottom bar, taking the sticky Add-to-Cart button
   with it. 100dvh tracks the area actually on screen. Declared after the
   vh rule so browsers without dvh keep the old value.
   overscroll-behavior stops a scroll that reaches the end of the overlay
   from chaining into the page behind it.
   ========================================================================== */
.product-modal,
.product-modal-overlay,
.cart-drawer,
.cart-overlay,
.search-overlay {
  height: 100dvh;
}
.product-modal,
.cart-drawer,
.cart-body,
.reviews-list,
.search-suggestions,
.store-facets-panel,
.store-sort-sheet {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ===== CART DRAWER: savings rows and the free-delivery nudge ===== */
.cart-summary-row.is-saving span { color: #10b981; font-weight: 600; }
.cart-summary-row[hidden] { display: none; }
.cart-free-nudge {
  margin: 8px 0 0;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--accent);
  text-align: center;
}
.cart-free-nudge[hidden] { display: none; }
