:root {
  /* Restrained gold accent system — gold marks VALUE + AUTHENTICITY only, never chrome. */
  --gold-leaf: 198, 166, 103;      /* structural hairlines/rims — cooler, recedes */
  --gold-parchment: 232, 224, 204; /* glyph/ink (COA, value line) — warmer */

  /* Stable full-viewport height for FIXED background layers.
     100vh == the LARGE viewport on mobile and stays constant while scrolling,
     so fixed backgrounds never reflow/jump when the browser URL bar shows or
     hides. NEVER swap this for dvh — dvh tracks the dynamic viewport and would
     reintroduce the jitter this variable exists to prevent. */
  --rv-bg-h: 100vh;
}

/* Upgrade to the explicit large-viewport unit where supported (same constant
   value, clearer intent). Still constant during scroll — no jump. */
@supports (height: 100lvh) {
  :root { --rv-bg-h: 100lvh; }
}

/**
 * SHOWROOM VISUAL PRIMITIVES
 * Comment 4: Dedicated stylesheet for premium Apple-level visual layers
 * Extracted from inline styles in index.html for maintainability
 */

/* ============================================ */
/* MOBILE SKY FALLBACK — pure CSS, compositor-only */
/* Replaces Vanta WebGL on coarse-pointer devices  */
/* Two layers of blurred radial blobs simulate     */
/* drifting clouds matching the Vanta colour mood. */
/* ============================================ */
@keyframes cloudDrift1 {
  0%   { transform: translateX(-4%) translateY(0px);   opacity: 0.85; }
  50%  { transform: translateX(3%)  translateY(-10px); opacity: 1;    }
  100% { transform: translateX(-4%) translateY(0px);   opacity: 0.85; }
}
@keyframes cloudDrift2 {
  0%   { transform: translateX(3%)  translateY(-5px); opacity: 0.9;  }
  50%  { transform: translateX(-3%) translateY(8px);  opacity: 0.72; }
  100% { transform: translateX(3%)  translateY(-5px); opacity: 0.9;  }
}

/* Base sky layer — warm amber sun glow at bottom, dark navy sky */
.vanta-mobile-sky {
  background:
    radial-gradient(ellipse at 48% 94%, rgba(230, 95, 20, 0.45)  0%, rgba(150, 50, 8, 0.18) 38%, transparent 58%),
    radial-gradient(ellipse at 82% 82%, rgba(190, 75, 15, 0.22)  0%, transparent 42%),
    radial-gradient(ellipse at 12% 88%, rgba(160, 55, 10, 0.15)  0%, transparent 38%),
    linear-gradient(175deg, #08111c 0%, #0d1925 32%, #111420 65%, #090909 100%);
}

/* Cloud layer 1 — brighter warm-grey blobs, slow lateral drift */
.vanta-mobile-sky::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 75% 42% at 32% 48%, rgba(90, 88, 105, 0.80) 0%, transparent 68%),
    radial-gradient(ellipse 56% 32% at 74% 38%, rgba(80, 78, 98, 0.72) 0%, transparent 63%),
    radial-gradient(ellipse 84% 36% at 55% 24%, rgba(70, 76, 100, 0.62) 0%, transparent 68%),
    radial-gradient(ellipse 52% 30% at 18% 62%, rgba(88, 78, 96, 0.58) 0%, transparent 60%);
  filter: blur(18px);
  animation: cloudDrift1 52s ease-in-out infinite;
}

/* Cloud layer 2 — slightly lighter, different timing for depth */
.vanta-mobile-sky::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 62% 34% at 64% 52%, rgba(100, 92, 115, 0.65) 0%, transparent 64%),
    radial-gradient(ellipse 54% 30% at 24% 38%, rgba(82, 88, 115, 0.60) 0%, transparent 61%),
    radial-gradient(ellipse 70% 40% at 44% 68%, rgba(75, 68, 90, 0.55) 0%, transparent 66%),
    radial-gradient(ellipse 46% 26% at 85% 62%, rgba(88, 76, 96, 0.50) 0%, transparent 56%);
  filter: blur(22px);
  animation: cloudDrift2 68s ease-in-out infinite;
}

/* ============================================================ */
/* NIGHT SKY BACKGROUND — NightSkyBackground.tsx              */
/* Purple night sky + box-shadow star fields + mountains      */
/* All animations are CSS-only, GPU-composited, 0 JS per frame */
/* ============================================================ */

/* ── Sky gradient ─────────────────────────────────────────── */
.ns-sky {
  position: fixed;
  /* Stable large-viewport height (see --rv-bg-h) so the night sky never jumps
     when the mobile URL bar toggles. Anchored top; bottom intentionally auto. */
  top: 0;
  left: 0;
  right: 0;
  bottom: auto;
  height: var(--rv-bg-h, 100vh);
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* Force own GPU compositing layer — eliminates paint on toggle */
  transform: translateZ(0);
  /* Smooth fade-in when mounted (day→night switch) */
  animation: nsFadeIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
  /* Deep purple night sky matching the reference palette */
  background: linear-gradient(
    to bottom,
    #060010 0%,   #060010 6%,  #090016 11%, #070016 20%,
    #0a0121 48%,  #0a0127 55%, #0c012b 62%, #0e0131 68%,
    #18023c 78%,  #1c0242 81%, #22034b 85%,
    #2e045a 92%,  #370569 100%
  );
}

@keyframes nsFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── Star layers (box-shadow technique) ───────────────────── */
/* One 1-3px div per depth layer.                             */
/* All star positions are CSS box-shadow offsets — the GPU    */
/* composites them; no per-star DOM element or JS animation.  */
.ns-stars {
  position: absolute;
  top: 0;
  left: 0;
  background: transparent;
  border-radius: 50%;
  will-change: opacity;
}
.ns-stars-s { width: 1px; height: 1px; animation: nsT1  4s       ease-in-out infinite alternate; }
.ns-stars-m { width: 2px; height: 2px; animation: nsT2  6s 1.5s  ease-in-out infinite alternate; }
.ns-stars-l { width: 3px; height: 3px; animation: nsT3  9s 3s    ease-in-out infinite alternate; }

@keyframes nsT1 { from { opacity: 0.60; } to { opacity: 1.00; } }
@keyframes nsT2 { from { opacity: 0.45; } 50% { opacity: 1.00; } to { opacity: 0.65; } }
@keyframes nsT3 { from { opacity: 0.50; } to { opacity: 1.00; } }

/* ── Milky Way nebula band ─────────────────────────────────── */
.ns-milkyway {
  position: absolute;
  top: -30%;
  left: -20%;
  width: 140%;
  height: 80%;
  transform: rotate(-25deg);
  transform-origin: center;
  background:
    radial-gradient(ellipse 50% 100% at 50% 50%, rgba(120, 50, 200, 0.10) 0%, transparent 70%),
    radial-gradient(ellipse 70%  60% at 35% 40%, rgba(80,  30, 150, 0.07) 0%, transparent 65%);
  filter: blur(18px);
  pointer-events: none;
}

/* ── Horizon aurora / light base ─────────────────────────── */
.ns-light-base {
  position: absolute;
  bottom: -80px;
  left: 10%;
  width: 80%;
  height: 100px;
  border-radius: 50%;
  background-color: #ffc1a0;
  box-shadow:
    0px -10px  30px  10px #ffc1a0,
    0px -20px  40px  20px #fe9c7f,
    0px -30px  60px  30px #be6590,
    0px -50px 150px  75px #632b6c;
  z-index: 1;
}

/* ── Mountain silhouettes ─────────────────────────────────── */
.ns-mountains {
  position: absolute;
  height: 80px;
  width: 100%;
  bottom: 0;
  left: 0;
  z-index: 2;
}
.ns-mountains > div {
  background: #110124;
  box-shadow: 0px 0px 50px 5px rgba(255, 255, 255, 0.20);
  position: absolute;
  bottom: 0;
}
.ns-mountain-1 {
  width: 100px; height: 100px;
  bottom: -40px !important;
  left: 10px;
  transform: rotate(45deg);
  border-top-left-radius: 10px;
}
.ns-mountain-2 {
  width: 60px; height: 60px;
  bottom: -20px !important;
  left: -10px;
  transform: rotate(45deg);
  border-top-left-radius: 10px;
}
.ns-land-1 { width: 30%; height: 20px; border-top-right-radius: 100%; }
.ns-land-2 { width: 60%; height: 15px; left: 30%; border-top-left-radius: 200%; border-top-right-radius: 200%; }
.ns-land-3 { width: 20%; height: 20px; left: 80%; border-top-left-radius: 100%; }

/* ── Mountain gradient fade-to-ground ─────────────────────── */
.ns-mountains-base {
  position: absolute;
  bottom: -10px;
  left: 0;
  width: 100%;
  height: 100px;
  z-index: 3;
  background: linear-gradient(to bottom, rgba(55, 5, 105, 0) 0%, rgba(9, 0, 22, 1) 100%);
}

/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .ns-sky    { animation: none !important; }
  .ns-stars  { animation: none !important; }
}

/* ── Mobile-specific overrides ───────────────────────────── */
/* Larger mountains + stronger aurora on narrow screens       */
@media (max-width: 640px) {
  .ns-mountains {
    height: 120px;
  }
  .ns-mountain-1 {
    width: 140px; height: 140px;
    bottom: -55px !important;
    left: 8px;
  }
  .ns-mountain-2 {
    width: 90px; height: 90px;
    bottom: -35px !important;
    left: -12px;
  }
  .ns-land-1 { height: 28px; }
  .ns-land-2 { height: 22px; }
  .ns-land-3 { height: 28px; }
  .ns-light-base {
    width: 100%;
    left: 0;
    box-shadow:
      0px -10px  40px  14px #ffc1a0,
      0px -22px  55px  25px #fe9c7f,
      0px -35px  80px  40px #be6590,
      0px -55px 180px  90px #632b6c;
  }
  .ns-mountains-base {
    height: 130px;
  }
}

/* Night toggle icon animation */
.night-toggle {
  transition: background 0.2s ease, border-color 0.2s ease;
}
.night-toggle-icon {
  display: inline-block;
  font-size: 14px;
  line-height: 1;
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease;
  transform-origin: center;
}
.night-toggle:hover .night-toggle-icon {
  transform: rotate(20deg) scale(1.15);
}

/* ============================================ */
/* VANTA CANVAS — block all pointer/touch events */
/* so the cloud scene is purely decorative and   */
/* never responds to swipes or taps on mobile.   */
/* ============================================ */
canvas.vanta-canvas {
  touch-action:   none !important;
  pointer-events: none !important;
}

/* ============================================ */
/* GRID & BACKGROUND LAYERS */
/* ============================================ */

/* 90s Grid Background */
.bg-grid {
  background-size: 40px 40px;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.13) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.13) 1px, transparent 1px);
  background-position: center top;
}

/* Anchored Background Layers */
.anchored-bg-layer-1,
.parallax-bg-layer-1 {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rv-bg-h, 100vh); /* stable large-viewport height — no mobile URL-bar jump */
  background: radial-gradient(ellipse at 50% 30%, rgba(20, 20, 40, 0.4) 0%, transparent 60%);
  pointer-events: none;
  z-index: 0;
  will-change: auto;
}

.anchored-bg-layer-2,
.parallax-bg-layer-2 {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rv-bg-h, 100vh); /* stable large-viewport height — no mobile URL-bar jump */
  background: radial-gradient(ellipse at 50% 70%, rgba(40, 20, 20, 0.3) 0%, transparent 60%);
  pointer-events: none;
  z-index: 0;
  will-change: auto;
}

/* ============================================ */
/* GLASS & GLOW EFFECTS */
/* ============================================ */

/* Radial ambient glow for hero sections */
.radial-glow {
  background: radial-gradient(ellipse at 50% 50%,
    rgba(255, 255, 255, 0.07) 0%,
    transparent 65%
  );
}
/* HERO LEGIBILITY — NO background box. Readability comes purely from a soft shadow
   HALO on the text itself, so the light wordmark/eyebrow/subline/scroll-cue read
   over ANY atmosphere (bright day clouds, sunset) with zero visible box behind them.
   Gated off the white theme (there the hero text is dark ink on a light wall, where
   a dark halo would be wrong — app.css handles that theme). */
html:not([data-lum="light"]) .radial-glow h1 .kinetic-line {
  text-shadow: 0 1px 2px rgba(0,0,0,0.60), 0 2px 16px rgba(0,0,0,0.50), 0 0 46px rgba(0,0,0,0.34);
}
html:not([data-lum="light"]) .hero-eyebrow,
html:not([data-lum="light"]) .hero-subline {
  text-shadow: 0 1px 2px rgba(0,0,0,0.65), 0 1px 12px rgba(0,0,0,0.55);
}
/* Scroll cue ("Discover archive") was the faintest line (text-zinc-400) — brighten
   + halo it so it always reads, still no box. */
html:not([data-lum="light"]) .radial-glow button[class*="text-zinc-400"] {
  color: #e4e4de;
  text-shadow: 0 1px 2px rgba(0,0,0,0.65), 0 1px 12px rgba(0,0,0,0.55);
}

/* ============================================ */
/* LIQUID GLASS CARDS                          */
/* CSS-first (all browsers) + Chrome SVG       */
/* refraction enhancement via @supports        */
/* ============================================ */

/* Premium glass card effect — liquid glass tier */
/* NOTE: This element is ALSO the 3D-tilt element (cardRef in ProductCard).
   overflow:hidden here clips in LOCAL space BEFORE the perspective transform,
   so rounded corners stay perfectly clean during tilt — no "box" artifact. */
.glass-card-2d {
  position: relative;
  background: transparent;
  /* Apple squircle radius */
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-top-color: rgba(255, 255, 255, 0.20);
  /* overflow clips to border-radius in LOCAL space (before perspective tilt) */
  overflow: hidden;
  isolation: isolate;
  /* Multi-layer shadow: far ambient + mid lift + near contact */
  box-shadow:
    0 0 0 0.5px rgba(255,255,255,0.04),
    0 2px 6px  rgba(0,0,0,0.35),
    0 8px 28px rgba(0,0,0,0.55),
    0 20px 60px rgba(0,0,0,0.30),
    0 1px 0 rgba(255,255,255,0.14) inset,
    0 -1px 0 rgba(0,0,0,0.45) inset;
  transition:
    border-color 0.65s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow   0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Specular rim highlight — top edge brightens like a glass edge catching light */
.glass-card-2d::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 10;
  /* Radial gradient from top-left simulates a convex glass surface catching light */
  background:
    linear-gradient(
      145deg,
      rgba(255,255,255,0.13) 0%,
      rgba(224,200,150,0.05) 22%,
      transparent 45%
    ),
    linear-gradient(
      to bottom,
      rgba(255,255,255,0.09) 0%,
      transparent 18%
    );
  opacity: 0;
  transition: opacity 0.35s ease;
  mix-blend-mode: screen;
}

/* Fresnel-like rim: faint outline glow that intensifies on hover */
.glass-card-2d::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  z-index: 11;
  background: transparent;
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.06),
    0 0 12px rgba(255,255,255,0.04) inset;
  opacity: 0;
  transition: opacity 0.35s ease;
}

.glass-card-2d:hover {
  border-color: rgba(255, 255, 255, 0.22);
  border-top-color: rgba(255, 255, 255, 0.42);
  box-shadow:
    0 0 0 0.5px rgba(255,255,255,0.10),
    0 4px 12px  rgba(0,0,0,0.40),
    0 16px 48px rgba(0,0,0,0.65),
    0 40px 80px rgba(0,0,0,0.35),
    0 1px 0 rgba(255,255,255,0.22) inset,
    0 -1px 0 rgba(0,0,0,0.50) inset,
    0 0 40px rgba(255,255,255,0.04),
    0 56px 120px rgba(0,0,0,0.28); /* ← ADDED: deeper, softer ground-shadow at peak lift */
  /* hover-IN crisp; hover-OUT inherits the base 0.65s settle so tilt + shadow land together */
  transition:
    border-color 0.30s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow   0.30s cubic-bezier(0.4, 0, 0.2, 1);
}

.glass-card-2d:hover::before {
  opacity: 1;
}

.glass-card-2d:hover::after {
  opacity: 1;
}

/* E1 — FOCUS RING (focus-ring). Off-white outline that rides the 3D tilt,
   immune to overflow:hidden; no ring flash on mouse click. */
.glass-card-2d:focus { outline: none; }               /* suppress UA default; focus-visible owns it */
.glass-card-2d:focus-visible {
  outline: 2px solid rgba(242, 240, 239, 0.92);        /* off-white #F2F0EF */
  outline-offset: 3px;
  border-radius: 20px;
}

/* E2 — PREMIUM PHOTO PUSH-IN (image-zoom). Own GPU layer so it never jitters
   against the parent card's rotateX/Y tilt. opacity stays owned by the pixel
   reveal — these transitions only touch transform + filter. */
.rv-photo-zoom {
  transform-origin: center center;
  transition:
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1),
    filter    700ms cubic-bezier(0.22, 1, 0.36, 1);
  transform: translateZ(0) scale(1);
  backface-visibility: hidden;
}
.group:hover .rv-photo-zoom {
  transform: translateZ(0) scale(1.045);
  filter: brightness(1.05);
}
.group:not(:hover) .rv-photo-zoom {
  transition:
    transform 450ms cubic-bezier(0.4, 0, 0.2, 1),
    filter    450ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (pointer: coarse) {
  .rv-photo-zoom, .group:hover .rv-photo-zoom { transform: none; filter: none; transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rv-photo-zoom, .group:hover .rv-photo-zoom { transform: none; filter: none; transition: none; }
}

/* E3 — LIGHT (DAY) THEME shadow re-tune (theme-light). DESKTOP-ONLY by the
   min-width guard — REQUIRED so these (0,2,1) selectors never outrank the
   mobile @media(max-width:639px) .glass-card-2d shadow-stripping (0,1,0). */
@media (min-width: 640px) {
  html[data-lum="light"] .glass-card-2d {
    border-color: rgba(30, 26, 20, 0.16);
    border-top-color: rgba(255, 255, 255, 0.14);
    box-shadow:
      0 1px 2px   rgba(30, 26, 20, 0.14),
      0 6px 16px  rgba(30, 26, 20, 0.16),
      0 14px 34px rgba(30, 26, 20, 0.12),
      0 1px 0 rgba(255, 255, 255, 0.10) inset,
      0 -1px 0 rgba(0, 0, 0, 0.40) inset;
  }
  html[data-lum="light"] .glass-card-2d:hover {
    border-color: rgba(30, 26, 20, 0.24);
    border-top-color: rgba(255, 255, 255, 0.20);
    box-shadow:
      0 2px 4px   rgba(30, 26, 20, 0.16),
      0 12px 28px rgba(30, 26, 20, 0.22),
      0 26px 52px rgba(30, 26, 20, 0.16),
      0 1px 0 rgba(255, 255, 255, 0.14) inset,
      0 -1px 0 rgba(0, 0, 0, 0.45) inset;
  }
}
/* ── END BLOCK E ──────────────────────────────────────────────────────────── */

/* Chrome-only: SVG feDisplacementMap refraction on the card backdrop */
@supports (backdrop-filter: url("#lg-card")) {
  .glass-card-2d .card-meta {
    backdrop-filter: blur(6px) saturate(160%) url("#lg-card") !important;
    -webkit-backdrop-filter: blur(6px) saturate(160%) url("#lg-card") !important;
  }
}

/* Heavy glass layer (for modals/overlays) */
.liquid-glass-heavy {
  background: rgba(8, 8, 8, 0.85);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.8);
}

/* Light glass layer — liquid glass treatment */
.liquid-glass {
  position: relative;
  background: rgba(255, 255, 255, 0.055);
  backdrop-filter: blur(20px) saturate(180%) brightness(1.08);
  -webkit-backdrop-filter: blur(20px) saturate(180%) brightness(1.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-top-color: rgba(255, 255, 255, 0.28); /* bright top edge = lit glass rim */
  border-radius: 10px;
  box-shadow:
    0 2px 16px rgba(0,0,0,0.40),
    0 1px 0   rgba(255,255,255,0.14) inset,
    0 -1px 0  rgba(0,0,0,0.28) inset;
  transition: all 0.3s ease;
  isolation: isolate;
  overflow: hidden;
}

/* Specular sheen: top-left light source */
.liquid-glass::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(
      135deg,
      rgba(255,255,255,0.14) 0%,
      rgba(255,255,255,0.04) 30%,
      transparent 55%
    );
  mix-blend-mode: screen;
  transition: opacity 0.3s ease;
}

.liquid-glass:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.22);
  border-top-color: rgba(255, 255, 255, 0.38);
  box-shadow:
    0 6px 28px rgba(0,0,0,0.50),
    0 1px 0 rgba(255,255,255,0.22) inset,
    0 -1px 0 rgba(0,0,0,0.35) inset;
}

/* Chrome SVG refraction on liquid-glass buttons */
@supports (backdrop-filter: url("#lg-btn")) {
  .liquid-glass {
    backdrop-filter: blur(20px) saturate(180%) brightness(1.08) url("#lg-btn");
    -webkit-backdrop-filter: blur(20px) saturate(180%) brightness(1.08) url("#lg-btn");
  }
}

/* Story section glass card */
.liquid-glass-story {
  background: rgba(255, 255, 255, 0.028);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow:
    0 2px 0 rgba(255,255,255,0.06) inset,
    0 32px 64px rgba(0,0,0,0.55),
    0 0 0 0.5px rgba(255,255,255,0.04);
  border-radius: 2rem;
  transition: border-color 0.4s ease, box-shadow 0.4s ease;
}

@supports not (backdrop-filter: blur(1px)) {
  .liquid-glass-story {
    background: rgba(8, 8, 8, 0.88);
  }
}

/* ============================================ */
/* TEXT EFFECTS */
/* ============================================ */

/* Subtle text glow */
.text-glow {
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
}

/* Gold shimmer animation (for premium branding) */
.text-gold-shimmer {
  background: linear-gradient(to right, 
    rgb(var(--gold-leaf)) 0%, rgb(var(--gold-parchment)) 42%, #faf6ea 50%, rgb(var(--gold-parchment)) 58%, rgb(var(--gold-leaf)) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Resting state = rich gold (leaf→parchment band). The bright #faf6ea glint
     lives at the gradient's 50% stop, so the value must NOT park at 50% —
     that read as plain white. One sheen pass sweeps through, then settles
     back on solid gold. */
  background-size: 220% auto; background-position: 0% center;
  animation: shineOnce 1.6s cubic-bezier(0.22, 1, 0.36, 1) 0.4s 1 both;
}

@keyframes shine {
  to {
    background-position: 175% center;
  }
}

/* One struck pass for the market value: the sheen enters from the right,
   sweeps across the numerals once, and settles on the golden resting band. */
@keyframes shineOnce {
  from { background-position: 200% center; }
  to   { background-position: 0% center; }
}

/* ============================================ */
/* SCROLLBAR STYLING */
/* ============================================ */

::-webkit-scrollbar {
  width: 4px;
}

::-webkit-scrollbar-track {
  background: #000;
  border-left: 1px solid #222;
}

::-webkit-scrollbar-thumb {
  background: #555;
  border: 1px solid #000;
}

::-webkit-scrollbar-thumb:hover {
  background: #777;
}

/* Firefox scrollbar */
* {
  scrollbar-width: thin;
  scrollbar-color: #555 #000;
}

/* ============================================ */
/* RETRO/MINIMALIST EFFECTS */
/* ============================================ */

.retro-glass {
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow: none;
}

.retro-border {
  border: 1px solid rgba(255, 255, 255, 0.15);
}

.retro-hover:hover {
  background: #fff;
  color: #000;
  transition: all 0.2s ease;
}

/* ============================================ */
/* ANIMATIONS */
/* ============================================ */

/* Marquee effect for ticker text — slow, editorial drift (not an LED board) */
.animate-marquee {
  animation: marquee 104s linear infinite;
  will-change: transform;
}

@keyframes marquee {
  0% { transform: translateX(0); }
  100% { transform: translateX(-33.333%); }
}

/* Scanline effect (optional retro CRT look) */
.scanline {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rv-bg-h, 100vh); /* stable large-viewport height — no mobile URL-bar jump */
  background: linear-gradient(to bottom,
    rgba(255,255,255,0), 
    rgba(255,255,255,0) 50%, 
    rgba(0,0,0,0.1) 50%, 
    rgba(0,0,0,0.1)
  );
  background-size: 100% 4px;
  pointer-events: none;
  z-index: 1;
  opacity: 0.15;
}

/* Apple-style scroll animations */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeInScale {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* Modal slide-in animation */
@keyframes modalSlideIn {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.modal-slide-in {
  /* No fill-mode: the keyframes end at the natural state (opacity 1,
     translateY 0), and a `forwards` fill would pin a transform on the card
     forever — keeping it composited and risking lost border-radius clipping
     of composited children (film strip, backdrop-filter footer) in Safari. */
  animation: modalSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Modal slide-out (close) — mirrors entry, settles downward. Must follow
   .modal-slide-in so it wins the cascade while both classes are present.
   260ms exit < 320ms unmount timer; forwards fill holds opacity 0 for the
   remaining ~60ms until unmount. Compositor-only. */
@keyframes modalSlideOut {
  to {
    opacity: 0;
    transform: translateY(16px) scale(0.98);
  }
}

.modal-slide-out {
  animation: modalSlideOut 0.26s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .modal-slide-in,
  .modal-slide-out {
    animation-duration: 1ms;
  }
}

/* ── LOT PAGE — product modal chapter stack (Apple-grade staging) ──────────
   The right panel reads as a catalogue lot page: stages separated by air,
   gold hairline kickers, catalogue plates between chapters. Reveals reuse the
   global [data-reveal]/.reveal-visible mechanics (observer is panel-scoped). */
.rv-lot-stage { padding-block: clamp(2.5rem, 6vh, 4rem); }
.rv-lot-kicker {
  display: flex; align-items: center; gap: 0.8rem;
  font-family: 'Space Mono', monospace; font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.38em; color: #71717a;
  margin-bottom: 1.25rem;
}
.rv-lot-kicker::before {
  content: ''; width: 40px; height: 1px; flex-shrink: 0;
  background: linear-gradient(to right, #c6a667, rgba(198, 166, 103, 0));
}
.rv-lot-hero-bg {
  /* Full panel width, anchored to the panel top — no hard column edges. The
     mask (inline, per-product fade) dissolves it downward into the panel. */
  position: absolute; inset: 0 0 auto 0; height: clamp(240px, 46vh, 440px); z-index: 0;
  -webkit-mask-image: linear-gradient(180deg, black 55%, transparent 100%);
  mask-image: linear-gradient(180deg, black 55%, transparent 100%);
}
.rv-lot-hero-bg img { width: 100%; height: 100%; object-fit: cover; opacity: 0.35; }
/* Everything in the lot flow paints above the mood image. */
.rv-lot > :not(.rv-lot-hero-bg) { position: relative; z-index: 1; }
.rv-lot-value {
  font-weight: 300;
  font-size: clamp(3rem, 2.2rem + 2.5vw, 4.25rem);
  letter-spacing: -0.04em; line-height: 1.05;
  font-variant-numeric: tabular-nums lining-nums;
  /* Safety net: a pathological price wraps instead of clipping off-panel. */
  max-width: 100%; overflow-wrap: anywhere;
}
/* Price scales with the LOT PANEL's own width, not the viewport — the panel
   is only 40% of the card on md+, so vw-based sizing clipped "$22,500" to
   "$22,50C" at 768–900px viewports (iPad portrait). cqw keys the size to the
   real column; the vw rule above stays as the no-container-query fallback. */
@supports (font-size: 1cqw) {
  .rv-lot { container-type: inline-size; }
  .rv-lot-value { font-size: clamp(2rem, 1rem + 11cqw, 4.25rem); }
}
.rv-lot-essay p {
  font-family: 'Cormorant Garamond', serif; font-style: italic; font-weight: 500;
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.3rem); line-height: 1.75;
  color: rgba(232, 224, 204, 0.92); max-width: 34rem;
}
.rv-lot-essay p + p { margin-top: 1.25em; }
.rv-lot-essay p:first-child { font-size: 1.35rem; line-height: 1.65; }
.rv-lot-essay--drop p:first-child::first-letter {
  float: left; font-size: 3em; line-height: 0.82;
  padding: 0.04em 0.1em 0 0; font-style: normal; font-weight: 600;
  color: rgb(var(--gold-parchment));
}
@media (max-width: 639px) {
  .rv-lot-essay--drop p:first-child::first-letter { font-size: 2.5em; }
}
.rv-lot-endrule {
  width: 40px; height: 1px; margin: 2.5rem auto 0;
  background: linear-gradient(to right, transparent, #c6a667, transparent);
}
.rv-lot-plate {
  background: #0d0d0f; border: 1px solid rgba(255, 255, 255, 0.10);
  padding: 0.5rem; cursor: pointer; transition: border-color 0.25s;
  width: 100%; display: block;
  position: relative; overflow: hidden;
}
.rv-lot-plate:hover { border-color: rgba(255, 255, 255, 0.3); }
/* Blurred cover fill — occupies the letterbox zones the contained photo leaves */
.rv-lot-plate-bg {
  position: absolute; inset: 0.5rem;
  width: calc(100% - 1rem); height: calc(100% - 1rem);
  object-fit: cover;
  filter: blur(24px) brightness(0.5) saturate(0.85);
  transform: scale(1.15);
}
.rv-lot-plate-photo {
  position: relative; display: block; width: 100%;
  max-height: 40vh; object-fit: contain;
}
.rv-lot-plate-caption {
  font-family: 'Space Mono', monospace; font-size: 8px; letter-spacing: 0.3em;
  text-transform: uppercase; color: #52525b; text-align: center; margin-top: 0.5rem;
}
.rv-lot-spec-val {
  font-weight: 300; font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2rem);
  letter-spacing: -0.02em; color: #fff; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere; /* long values wrap instead of painting into the next cell */
}
/* reveal cascade delays — same shared [data-reveal] transition as rv-story */
.rv-lot-d0[data-reveal] { transition-delay: 0ms; }
.rv-lot-d1[data-reveal] { transition-delay: 80ms; }
.rv-lot-d2[data-reveal] { transition-delay: 160ms; }
.rv-lot-d3[data-reveal] { transition-delay: 240ms; }
/* Sheen gate: the one-pass gold sheen fires when the value stage reveals,
   not invisibly at mount — the sheen becomes the reveal's finishing flourish. */
.rv-lot [data-reveal]:not(.reveal-visible) .text-gold-shimmer,
.rv-lot [data-reveal].text-gold-shimmer:not(.reveal-visible) {
  animation-play-state: paused;
}

/* Kinetic typography for hero */
@keyframes kineticLineIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.kinetic-line {
  opacity: 0;
  transform: translateY(16px);
  will-change: transform, opacity;
  animation: kineticLineIn 0.9s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* Construction line animation */
@keyframes lineGrow {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

/* Scroll indicator line */
@keyframes scrollLineGrow {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

/* Animation utility classes */
.animate-in {
  animation-fill-mode: both;
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}

.fade-in {
  animation-name: fadeIn;
}

.fade-out {
  animation-name: fadeOut;
}

/* Overlay-safe fades — opacity ONLY. The generic fadeIn keyframes animate
   transform too, and with fill-mode both the element retains an identity
   transform forever, turning it into a containing block for position:fixed
   descendants (the modal's close button + dim/blur layer would then scroll
   away with the content). Used by the product modal overlay root. */
@keyframes rvOverlayFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes rvOverlayFadeOut { from { opacity: 1; } to { opacity: 0; } }
.rv-overlay-fade-in  { animation: rvOverlayFadeIn 0.32s cubic-bezier(0.16, 1, 0.3, 1) both; }
.rv-overlay-fade-out { animation: rvOverlayFadeOut 0.32s cubic-bezier(0.4, 0, 0.2, 1) both; }
@media (prefers-reduced-motion: reduce) {
  .rv-overlay-fade-in, .rv-overlay-fade-out { animation-duration: 1ms; }
}

/* ============================================ */
/* PAGE-FLIP PHOTO GALLERY ANIMATION            */
/* ============================================ */

@keyframes pageFoldOut {
  0%   { transform: rotateY(0deg);     filter: brightness(1) drop-shadow(0 4px 12px rgba(0,0,0,0.2)); }
  45%  { filter: brightness(0.55) drop-shadow(0 20px 50px rgba(0,0,0,0.95)); }
  100% { transform: rotateY(-180deg);  filter: brightness(0.85); }
}
@keyframes pageFoldOutRev {
  0%   { transform: rotateY(0deg);     filter: brightness(1) drop-shadow(0 4px 12px rgba(0,0,0,0.2)); }
  45%  { filter: brightness(0.55) drop-shadow(0 20px 50px rgba(0,0,0,0.95)); }
  100% { transform: rotateY(180deg);   filter: brightness(0.85); }
}
@keyframes pageUnfoldIn {
  0%   { transform: rotateY(180deg);   filter: brightness(0.85); }
  55%  { filter: brightness(0.55) drop-shadow(0 20px 50px rgba(0,0,0,0.95)); }
  100% { transform: rotateY(0deg);     filter: brightness(1) drop-shadow(0 4px 12px rgba(0,0,0,0.15)); }
}
@keyframes pageUnfoldInRev {
  0%   { transform: rotateY(-180deg);  filter: brightness(0.85); }
  55%  { filter: brightness(0.55) drop-shadow(0 20px 50px rgba(0,0,0,0.95)); }
  100% { transform: rotateY(0deg);     filter: brightness(1) drop-shadow(0 4px 12px rgba(0,0,0,0.15)); }
}

.page-fold-out {
  animation: pageFoldOut 0.38s cubic-bezier(0.4, 0, 0.8, 0.6) forwards;
  transform-origin: left center;
}
.page-fold-out-rev {
  animation: pageFoldOutRev 0.38s cubic-bezier(0.4, 0, 0.8, 0.6) forwards;
  transform-origin: right center;
}
.page-unfold-in {
  animation: pageUnfoldIn 0.38s cubic-bezier(0.2, 0.4, 0.2, 1) forwards;
  transform-origin: left center;
}
.page-unfold-in-rev {
  animation: pageUnfoldInRev 0.38s cubic-bezier(0.2, 0.4, 0.2, 1) forwards;
  transform-origin: right center;
}

.slide-in-from-bottom-4,
.slide-in-from-bottom-8 {
  animation-name: fadeInUp;
}

/* Hero mouse-tracking glow */
.hero-mouse-glow {
  --mx: 50%;
  --my: 50%;
  background: radial-gradient(
    ellipse at var(--mx) var(--my),
    rgba(255, 255, 255, 0.03) 0%,
    transparent 55%
  );
  transition: background 0.1s ease;
}

/* Hero subline — fourth kinetic reveal */
.hero-subline {
  opacity: 0;
  will-change: opacity;
  animation: fadeIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.6s forwards;
}

/* Scroll indicator — compositor-only opacity pulse (replaces bounce which causes layout) */
@keyframes scrollPulse {
  0%, 100% { opacity: 0.35; }
  50%       { opacity: 0.90; }
}
.scroll-pulse {
  animation: scrollPulse 2.4s ease-in-out infinite;
  will-change: opacity;
}

/* Hero masthead eyebrow — soft fade-in on load */
.hero-eyebrow {
  opacity: 0;
  animation: fadeIn 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.3s forwards;
}

/* Apple-style scroll cue — a thin rail with a dot that travels down and fades.
   Pure transform/opacity on the dot (compositor-only); rail is static. */
.scroll-cue {
  position: relative;
  display: block;
  width: 1px;
  height: 3rem;
  background: linear-gradient(to bottom, rgba(255,255,255,0.30), rgba(255,255,255,0.06));
  overflow: hidden;
  border-radius: 1px;
}
.scroll-cue-dot {
  position: absolute;
  top: 0;
  left: 50%;
  width: 3px;
  height: 8px;
  margin-left: -1.5px;
  border-radius: 2px;
  background: rgba(255,255,255,0.7);
  will-change: transform, opacity;
  animation: scrollCueTravel 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes scrollCueTravel {
  0%   { transform: translateY(-8px); opacity: 0; }
  25%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { transform: translateY(3rem); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-cue-dot { animation: none; top: 40%; opacity: 0.8; }
  .hero-eyebrow { animation: none; opacity: 1; }
}

/* ============================================ */
/* CUSTOM FILTER DROPDOWN                       */
/* ============================================ */

@keyframes filterDropIn {
  from { opacity: 0; transform: translateY(-6px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}

.filter-dropdown {
  background: rgba(12, 12, 14, 0.97);
  backdrop-filter: blur(24px) saturate(160%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-top-color: rgba(255, 255, 255, 0.18);
  border-radius: 12px;
  box-shadow:
    0 8px 32px rgba(0,0,0,0.65),
    0 1px 0 rgba(255,255,255,0.08) inset;
  overflow: hidden;
  animation: filterDropIn 0.18s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.filter-dropdown-item {
  transition: background 0.15s ease, color 0.15s ease;
}
.filter-dropdown-item:hover {
  background: rgba(255,255,255,0.06) !important;
  color: #ffffff !important;
}

/* ============================================ */
/* COMPACT FILTER BAR                           */
/* ============================================ */
.filter-bar-compact {
  background: transparent;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* Shared glass control: search input, sort, year, type selects */
.filter-control {
  position: relative;
  background: rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(16px) saturate(180%) brightness(1.05);
  -webkit-backdrop-filter: blur(16px) saturate(180%) brightness(1.05);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-top-color: rgba(255, 255, 255, 0.13);
  border-radius: 8px;
  color: #ffffff;
  font-family: 'Space Mono', monospace;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.08) inset,
    0 -1px 0 rgba(0,0,0,0.20) inset,
    0 2px 8px rgba(0,0,0,0.20);
  transition: all 0.2s ease;
}

/* Custom arrow for select dropdowns — hides native OS chrome, adds SVG chevron */
select.filter-control {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='rgba(255,255,255,0.5)' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 28px !important;
  cursor: pointer;
}

.filter-control:hover {
  background: rgba(255, 255, 255, 0.085);
  border-color: rgba(255, 255, 255, 0.22);
  border-top-color: rgba(255, 255, 255, 0.35);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.18) inset,
    0 -1px 0 rgba(0,0,0,0.30) inset,
    0 4px 14px rgba(0,0,0,0.40);
}

.filter-control:focus {
  outline: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
  border-color: rgba(255, 255, 255, 0.35);
}

.filter-control::placeholder {
  color: rgba(113, 113, 122, 0.8);
}

/* Active filter pill — liquid glass capsule */
.filter-pill-active {
  position: relative;
  background: rgba(255, 255, 255, 0.10);
  backdrop-filter: blur(16px) saturate(180%) brightness(1.12);
  -webkit-backdrop-filter: blur(16px) saturate(180%) brightness(1.12);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-top-color: rgba(255, 255, 255, 0.40);
  border-radius: 999px;
  box-shadow:
    0 0 14px rgba(255,255,255,0.07),
    0 1px 0  rgba(255,255,255,0.22) inset,
    0 -1px 0 rgba(0,0,0,0.30) inset;
  color: #ffffff;
  isolation: isolate;
  overflow: hidden;
}

/* Specular sheen on active pill */
.filter-pill-active::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    rgba(255,255,255,0.18) 0%,
    rgba(255,255,255,0.04) 40%,
    transparent 65%
  );
  mix-blend-mode: screen;
}

/* Inactive filter pill */
.filter-pill-inactive {
  position: relative;
  background: rgba(255,255,255,0.04);
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border: 1px solid rgba(255,255,255,0.18);
  border-top-color: rgba(255,255,255,0.28);
  border-radius: 999px;
  box-shadow: none;
  transition: all 0.25s ease;
  isolation: isolate;
  overflow: hidden;
}

.filter-pill-inactive::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    rgba(255,255,255,0.07) 0%,
    transparent 50%
  );
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.filter-pill-inactive:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.16);
  border-top-color: rgba(255, 255, 255, 0.28);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.14) inset,
    0 3px 12px rgba(0,0,0,0.30);
}

.filter-pill-inactive:hover::before {
  opacity: 1;
}

.animate-fade-in {
  animation: fadeIn 1s ease-out forwards;
}

.animate-fade-in-delay {
  animation: fadeIn 1s ease-out 0.2s forwards;
  opacity: 0;
}

.animate-fade-in-delay-2 {
  animation: fadeIn 1s ease-out 0.4s forwards;
  opacity: 0;
}

/* ============================================ */
/* CARD INTERACTION EFFECTS */
/* ============================================ */

/* Card metadata strip — liquid glass bottom panel */
.card-meta {
  background: rgba(7, 7, 9, 0.82);
  backdrop-filter: blur(12px) saturate(160%) brightness(0.95);
  -webkit-backdrop-filter: blur(12px) saturate(160%) brightness(0.95);
  border-top: 1px solid rgba(255,255,255,0.08);
  border-radius: 0 0 19px 19px;                 /* concentric with the 19px child clip */
  position: relative;
  isolation: isolate;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);  /* lit inner-top bevel */
}

/* Subtle specular sheen on the metadata strip top edge */
.card-meta::before {
  content: '';
  position: absolute;
  top: 0; left: 8%; right: 8%;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,255,255,0.04) 18%,
    rgba(255,255,255,0.20) 50%,
    rgba(255,255,255,0.04) 82%,
    transparent 100%);
  pointer-events: none;
}

/* F1 — VALUE LINE (gold-system): the ONE promoted gold accent — a struck
   gradient hairline that warms on hover, replacing the old white border. */
.card-value-line {
  border-bottom-color: transparent !important;   /* border-image overrides; neutralise currentColor fallback */
  border-image: linear-gradient(
      90deg,
      transparent 0%,
      rgba(var(--gold-leaf), 0.22) 18%,
      rgba(var(--gold-leaf), 0.22) 82%,
      transparent 100%
    ) 1;
  transition: border-image 0.2s ease, filter 0.2s ease;
}
.group:hover .card-value-line {
  border-image: linear-gradient(
      90deg,
      transparent 0%,
      rgba(var(--gold-leaf), 0.40) 15%,
      rgba(var(--gold-parchment), 0.34) 50%,
      rgba(var(--gold-leaf), 0.40) 85%,
      transparent 100%
    ) 1;
  filter: drop-shadow(0 0 2px rgba(var(--gold-leaf), 0.14));
}

/* F2 — PRODUCT NAME (name-type): controlled 2-line clamp, fixed 2-line slot so
   card heights stay even across the grid; long SKUs still wrap, never overflow. */
.card-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  line-height: 1.15;
  min-height: 2.3em;             /* 2 × 1.15 → single- and two-line names share a footprint */
  overflow-wrap: anywhere;
  word-break: normal;
}

/* F3 — PRICE (price-type): tabular figures so prices align on a shared digit
   grid across the whole 2–5-col grid; warms a touch on hover. */
.card-price {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  letter-spacing: -0.01em;
  transition: color 0.2s ease;
}
.group:hover .card-price { color: #FFFDF8; }

/* F3b — ARCHIVED LEDGER (unavailable-treat): realized lots lower their voice.
   SOLD/GONE/NFS cards mute the price to a settled warm-neutral and freeze the
   gold value hairline at its resting weight — no hover warm-up on settled
   pieces. Static colors, zero new transitions; cards are dark-glass in both
   themes, so no light-mode override is needed. */
.glass-card-2d.is-archived .card-price,
.glass-card-2d.is-archived:hover .card-price {
  color: rgba(196, 192, 188, 0.58);
  text-shadow: none;
}
.glass-card-2d.is-archived:hover .card-value-line {
  border-image: linear-gradient(
      90deg,
      transparent 0%,
      rgba(var(--gold-leaf), 0.22) 18%,
      rgba(var(--gold-leaf), 0.22) 82%,
      transparent 100%
    ) 1;
  filter: none;
}

/* F4 — SPEC ROWS (meta-rhythm): specimen-label two-column layout, one shared
   right edge across both rows, tabular digits; left truncates, right is intrinsic. */
.card-meta .spec-block {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.card-meta .spec-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: 10px;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.card-meta .spec-row > .spec-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.card-meta .spec-row > .spec-value {
  text-align: right;
  white-space: nowrap;
  color: rgba(210, 205, 198, 0.92);   /* faint warm-neutral lift = the "data" column */
}

/* F5 — ARCHIVAL № ID BADGE (id-badge): faint at rest, blooms on desktop hover;
   pinned to a quiet legible opacity on touch (no hover to reveal it). */
.product-id-badge { opacity: 0.3; }
.group:hover .product-id-badge { opacity: 1; }
@media (hover: none) {
  .product-id-badge { opacity: 0.5; }
  .group:hover .product-id-badge { opacity: 0.5; } /* neutralise desktop hover where hover isn't real */
}
@media (prefers-reduced-motion: reduce) {
  .product-id-badge { transition: none; }
}

/* F6 — COA SEAL (coa-seal): restrained struck-gold authenticity mark. Sharp
   corners to match the sibling ID badge; overrides the removed bg/border. */
.coa-seal {
  background:
    linear-gradient(180deg, rgba(198,166,103,0.10) 0%, rgba(0,0,0,0) 55%),
    rgba(8, 7, 5, 0.78) !important;
  border: 1px solid rgba(198,166,103,0.32) !important;
  border-top-color: rgba(232,224,204,0.55) !important;
  box-shadow:
    0 0 0 0.5px rgba(0,0,0,0.55),
    inset 0 1px 0 rgba(232,224,204,0.14),
    inset 0 0 6px rgba(198,166,103,0.10);
}
.coa-seal::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(ellipse 80% 120% at 12% 0%, rgba(232,224,204,0.16) 0%, transparent 60%);
}

/* F7 — BOTTOM PHOTO SCRIM (image-scrim): melts the photo into the meta panel
   and lifts badge contrast. Static gradient, no JS. z-4 = above image, below
   badges (z-10) + glare (z-20). */
.card-photo-scrim {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 34%;
  pointer-events: none;
  z-index: 4;
  background: linear-gradient(
    to bottom,
    rgba(6,6,6,0)    0%,
    rgba(6,6,6,0)    40%,
    rgba(6,6,6,0.20) 72%,
    rgba(6,6,6,0.52) 100%
  );
}

/* F8 — ARCHIVED / SOLD TREATMENT (unavailable-treat): desaturate non-Available
   pieces to a warm museum grey. GPU-only filter+opacity; the reveal fade is
   preserved (img keeps its base transition-opacity, animating 0 → 0.62). */
.archived-photo {
  opacity: 0.62;
  filter: grayscale(0.85) sepia(0.16) hue-rotate(-8deg) contrast(1.04) brightness(0.82);
}
.archived-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 9;                 /* above image, below stamp (z-10) + glare (z-20) */
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(120% 100% at 50% 42%,
              transparent 46%,
              rgba(6,6,8,0.28) 82%,
              rgba(4,4,6,0.5) 100%);
}

/* F9 — SKELETON SHIMMER (skeleton): near-black graphite base + one slow diagonal
   sweep with a faint gold crest. Sits UNDER the <img>; the opaque object-cover
   image (or canvas / error plate) covers it once content paints — no JS to remove. */
.img-skeleton {
  background-color: #08080a;
  background-image: linear-gradient(
    115deg,
    #08080a 0%,
    #101013 32%,
    #17171b 46%,
    rgba(198,166,103,0.10) 50%,
    #17171b 54%,
    #101013 68%,
    #08080a 100%
  );
  background-size: 260% 100%;
  background-position: 130% 0;
  background-repeat: no-repeat;
  animation: imgSkeletonSweep 2.6s ease-in-out infinite;
}
@keyframes imgSkeletonSweep { to { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) {
  .img-skeleton { animation: none; background-image: none; background-color: #0a0a0c; }
}

/* F10 — ARCHIVAL PLATE (error-fallback): elegant image-error mount card. */
.archival-plate {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background:
    repeating-linear-gradient(45deg,  rgba(198,166,103,0.045) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(-45deg, rgba(198,166,103,0.035) 0 1px, transparent 1px 11px),
    radial-gradient(120% 90% at 50% 42%, rgba(20,18,16,0.0) 0%, rgba(0,0,0,0.55) 100%),
    linear-gradient(180deg, #111010 0%, #0a0908 100%);
}
.archival-plate__monogram {
  position: absolute;
  z-index: 0;
  top: 50%; left: 50%;
  transform: translate(-50%, -58%);
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 600;
  font-size: clamp(48px, 8vw, 120px);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(198,166,103,0.14);
  user-select: none;
  pointer-events: none;
}
.archival-plate__tick {
  position: absolute;
  width: 9px; height: 9px;
  pointer-events: none;
  border-color: rgba(198,166,103,0.30);
  border-style: solid;
  border-width: 0;
}
.archival-plate__tick--tl { top: 7px;    left: 7px;  border-top-width: 1px;    border-left-width: 1px;  }
.archival-plate__tick--tr { top: 7px;    right: 7px; border-top-width: 1px;    border-right-width: 1px; }
.archival-plate__tick--bl { bottom: 7px; left: 7px;  border-bottom-width: 1px; border-left-width: 1px;  }
.archival-plate__tick--br { bottom: 7px; right: 7px; border-bottom-width: 1px; border-right-width: 1px; }

/* F11 — SELECT / PRESS MICRO-INTERACTION (select-press + mobile-press merged).
   The SINGLE press system. Desktop: dip only the inner .card-meta (never the
   card transform → never fights the inline mousemove tilt). Coarse pointer:
   whole-card scale dip. Keyboard: a one-shot .card-meta pulse via data-pressed. */
.glass-card-2d:active .card-meta,
.glass-card-2d[data-pressed='1'] .card-meta {
  filter: brightness(0.94);
  transition: filter 0.12s ease;
}
@media (pointer: coarse) {
  .glass-card-2d:active,
  .glass-card-2d[data-pressed='1'] {
    transform: scale(0.972);
    transition: transform 0.13s cubic-bezier(0.4, 0, 0.2, 1), filter 0.13s ease;
    filter: brightness(0.97);
  }
}
@keyframes cardPressPulse {
  0%   { transform: translateZ(0) scale(1);     filter: brightness(1);    }
  35%  { transform: translateZ(0) scale(0.978); filter: brightness(0.95); }
  100% { transform: translateZ(0) scale(1);     filter: brightness(1);    }
}
.glass-card-2d[data-pressed='1'] .card-meta {
  animation: cardPressPulse 0.22s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .glass-card-2d:active,
  .glass-card-2d[data-pressed='1'] {
    animation: none !important;
    transform: none !important;
    transition: filter 0.1s ease !important;
    filter: brightness(0.97) !important;
  }
  .glass-card-2d:active .card-meta,
  .glass-card-2d[data-pressed='1'] .card-meta {
    animation: none !important;
    transform: none !important;
    filter: brightness(0.96) !important;
    transition: filter 0.1s ease !important;
  }
}
/* ── END BLOCK F ──────────────────────────────────────────────────────────── */

/* ============================================ */
/* UTILITY: HIDE SCROLLBAR (keep scrollability) */
/* Used on horizontally-scrollable filter rows  */
/* on mobile to avoid visible scrollbar chrome. */
/* ============================================ */
.no-scrollbar {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.no-scrollbar::-webkit-scrollbar {
  display: none;
}

/* ============================================ */
/* MOBILE-FIRST OVERRIDES (max-width: 639px)    */
/* All changes here apply ONLY on screens       */
/* narrower than sm: (640px) breakpoint.        */
/* ============================================ */
@media (max-width: 639px) {

  /* ── Header BUTTONS: minimum 44 × 44 px touch target ───
     Only applies to <button> elements with .liquid-glass.
     Deliberately excludes the logo <span class="liquid-glass">
     so the logo stays compact and doesn't balloon in size.   */
  button.liquid-glass {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-left: 12px;
    padding-right: 12px;
  }

  /* ── Filter controls: bigger tap area ─────────────────── */
  .filter-control {
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
    font-size: 11px;
  }

  /* ── Filter pills: bigger tap area on mobile ───────────── */
  .filter-pill-active,
  .filter-pill-inactive {
    padding-top: 10px;
    padding-bottom: 10px;
    white-space: nowrap; /* prevent line-break inside pill */
  }

  /* ── Card meta strip: slightly more readable text ─────── */
  .card-meta {
    padding: 10px 12px;
  }

  /* H1 — museum-placard type ramp for ~180px 2-col cards (mobile-density). */
  .card-meta h3 {          /* name */
    font-size: 12.5px;
    line-height: 1.15;
  }
  .card-meta h3 + span {   /* price (immediate sibling span after the h3) */
    font-size: 13.5px;
    line-height: 1.15;
  }
  /* H2 — spec-row density on small cards (meta-rhythm mobile override). */
  .card-meta .spec-row  { column-gap: 6px; }
  .card-meta .spec-block { gap: 1px; }
  .card-meta .spec-row > .spec-label,
  .card-meta .spec-row > .spec-value {
    font-size: 9.5px;
    letter-spacing: 0.14em;
  }
  /* H3 — archival plate: smaller ticks + tighter monogram on 2-col cards. */
  .archival-plate__tick { width: 6px; height: 6px; }
  .archival-plate__tick--tl, .archival-plate__tick--tr { top: 5px; }
  .archival-plate__tick--bl, .archival-plate__tick--br { bottom: 5px; }
  .archival-plate__tick--tl, .archival-plate__tick--bl { left: 5px; }
  .archival-plate__tick--tr, .archival-plate__tick--br { right: 5px; }
  .archival-plate__monogram { font-size: clamp(40px, 14vw, 72px); }

  /* ── Liquid-glass-story: no outward shadow on mobile.
     The desktop 0 32px 64px shadow bleeds upward because
     blur(64) > y-offset(32), appearing as a dark band above
     the box. Removing outward shadow entirely on mobile;
     the border and inset highlight are enough definition.     */
  .liquid-glass-story {
    padding-left: 20px;
    padding-right: 20px;
    box-shadow:
      0 2px 0 rgba(255,255,255,0.06) inset,
      0 0 0 0.5px rgba(255,255,255,0.06);
  }

  /* ── Product cards: no outward shadow, no stacking context on mobile.
     - Shadows removed: any blur > y-offset bleeds above card onto neighbours.
     - isolation:auto: ::before (mix-blend-mode) is already display:none on
       mobile so the stacking context is waste — removing it reduces the
       number of compositor layers the browser has to manage during scroll.
     - transition:none: box-shadow/border transitions force repaint on every
       hover/tap; removed since hover effects don't fire on touch anyway.
     - contain:content: scopes the browser's layout/paint recalculation to
       each card individually — repainting one card doesn’t re-check others. */
  .glass-card-2d {
    isolation: auto;
    transition: none;
    contain: content;
    box-shadow:
      0 0 0 0.5px rgba(255,255,255,0.06),
      0 1px 0 rgba(255,255,255,0.12) inset,
      0 -1px 0 rgba(0,0,0,0.35) inset;
  }

  /* Remove stacking context from card meta strip — ::before is display:none
     on mobile so isolation:isolate just wastes a compositor stacking context */
  .card-meta {
    isolation: auto;
  }

  /* liquid-glass: swap transition:all for only the two properties that
     actually change on interaction (bg + border). transition:all would
     transition every CSS property including paint-heavy ones like box-shadow,
     padding, font-size etc — hugely expensive on a mid-tier GPU. */
  .liquid-glass {
    transition: background-color 0.2s ease, border-color 0.2s ease;
  }

}

/* Card lift — perspective parent wrapper (glass-card-2d does the actual tilt) */
.card-lift {
  transition: box-shadow 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

.card-lift:hover {
  position: relative;
  z-index: 2;
}

/* ─────────────────────────────────────────────────────────────────────────
   BLOCK G — WISHLIST CHIP (wishlist-btn).
   ───────────────────────────────────────────────────────────────────────── */
.wishlist-btn {
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
              border-color 0.25s ease,
              background-color 0.25s ease;
}
.group:hover .wishlist-btn:not(:hover) { border-color: rgba(255,255,255,0.30); }
.wishlist-btn:hover {
  transform: translateY(-1px);
  border-color: rgba(198,166,103,0.75);   /* brand gold rim, sparingly */
  background-color: rgba(24,24,27,0.60);
}
.wishlist-btn:not([data-wishlisted="true"]):hover .wishlist-heart {
  stroke: rgba(232,224,204,0.95);
}
.wishlist-btn[data-wishlisted="true"] .wishlist-heart {
  stroke: rgba(232,224,204,0.95);
  fill:   url(#wl-fill);
  transform-box: fill-box;
  transform-origin: center;
  animation: wishlistPop 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes wishlistPop {
  0%   { transform: scale(0.7); }
  45%  { transform: scale(1.28); }
  70%  { transform: scale(0.94); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .wishlist-btn[data-wishlisted="true"] .wishlist-heart { animation: none !important; }
}
@media (pointer: coarse) {
  .wishlist-btn::before {                  /* true 44×44 tap target without enlarging the chip */
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }
}
/* ── END BLOCK G ──────────────────────────────────────────────────────────── */

/* ============================================ */
/* CART BADGE — springy pop when the count or   */
/* discount sticker changes                     */
/* ============================================ */
@keyframes cartBadgePop {
  0%   { transform: scale(0.4) rotate(-12deg); }
  55%  { transform: scale(1.35) rotate(-12deg); }
  100% { transform: scale(1) rotate(-12deg); }
}
.cart-badge-pop {
  animation: cartBadgePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes cartCountPop {
  0%   { transform: scale(0.4); }
  55%  { transform: scale(1.5); }
  100% { transform: scale(1); }
}
.cart-count-pop {
  display: inline-block;
  animation: cartCountPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@media (prefers-reduced-motion: reduce) {
  .cart-badge-pop, .cart-count-pop { animation: none; }
}

/* ============================================ */
/* SCROLL REVEAL — one-shot rise+fade on enter  */
/* Driven by IntersectionObserver in Showroom;  */
/* compositor-only properties, no layout work.  */
/* ============================================ */
[data-reveal] {
  opacity: 0;
  transform: translateY(30px) scale(0.985);
  transition:
    opacity   0.9s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
}
[data-reveal].reveal-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}
/* Drop the compositor hint once settled so idle sections don't hold GPU layers */
[data-reveal].reveal-visible {
  will-change: auto;
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ============================================ */
/* INVESTMENT-THESIS EDITORIAL CHAPTERS (Hero → Grid) */
/* Scoped under .rv-story only — never touches product cards. */
/* ============================================ */
/* Transparent, full-width carrier — the atmosphere (Vanta clouds/night sky) shows through. */
/* --- Hero manifesto ---------------------------------------------------------
   Five plain statements in the archive's voice, directly under the hero.
   Museum register: quiet serif, generous air, no motion. */
.rv-manifesto {
  position: relative;
  z-index: 10;
  padding: 5.5rem 1.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.rv-manifesto__inner {
  max-width: 44rem;
  margin: 0 auto;
  text-align: center;
}
.rv-manifesto__line {
  font-family: 'Cormorant Garamond', serif;
  font-weight: 300;
  font-style: italic;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  line-height: 1.45;
  color: #e7e7e1;
  margin: 0;
}
.rv-manifesto__line + .rv-manifesto__line { margin-top: 0.4rem; }

.rv-story {
  position: relative;
  z-index: 10;                          /* above the fixed backdrop (z-index:0), below Collector-Sets z-20 */
  width: 100%;
  /* Centered band: without this the left/right cards pin to the section edges and
     the centre gutter grows with the viewport (≈900px+ on a wide monitor), so the
     chapters read as flung apart. Capping the carrier keeps a constant, tight gutter
     at any width. Below this width it simply doesn't bind (mobile stays full-width). */
  max-width: 68rem;
  margin-inline: auto;
  background: transparent;
  padding: clamp(1.4rem, 3.2vw, 2.4rem) clamp(1rem, 4vw, 2rem);
  scroll-margin-top: 5rem;
}
/* The inset, floating liquid-glass card (story-grade opacities — quiet, museum/bank). */
.rv-story__inner {
  position: relative;
  overflow: hidden;
  max-width: 44rem;
  margin: 0 auto;
  padding: clamp(1.5rem, 3.2vw, 2.4rem) clamp(1.4rem, 3.2vw, 2.3rem);
  border-radius: 1.5rem;
  /* Dark "smoked glass": the near-transparent white (0.03) washed the light text out
     over BRIGHT atmospheres (day clouds, sunset). A dark translucent tint darkens
     whatever's behind the text enough to stay readable on EVERY theme, while the
     blur still lets the atmosphere glow through, just dimmed. White theme overrides
     this via html[data-lum="light"] .rv-story__inner, so it is unaffected. */
  background: rgba(10, 12, 20, 0.62);
  backdrop-filter: blur(26px) saturate(165%);
  -webkit-backdrop-filter: blur(26px) saturate(165%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-top-color: rgba(255, 255, 255, 0.18);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.06) inset,
    0 30px 60px rgba(0, 0, 0, 0.42);
}
/* Faint specular highlight (matches .liquid-glass::before) — harmless over the text. */
.rv-story__inner::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, transparent 58%);
}
/* Staggered / offset glass cards on wide screens — chapters alternate left & right
   so they read as a composed editorial spread, not one centered "flowing" column. */
@media (min-width: 900px) {
  /* narrower cards → alternating left/right sit in opposite columns with a clear
     centre gutter, so they can overlap in height without ever touching. */
  .rv-story__inner { max-width: min(29rem, 42vw); }
  .rv-story__inner--left  { margin-left: 0;    margin-right: auto; }
  .rv-story__inner--right { margin-left: auto; margin-right: 0;    }
  /* pull every card AFTER the first up into the previous one's band so they
     interlock vertically (opposite columns + constant gutter → they never touch).
     Deep negative margin = strong shingle overlap, so you see two chapters
     interlocking at once instead of one-per-screen. */
  .rv-story__inner--stack { margin-top: -13rem; }
}
.rv-story__no {
  display: block;
  font-family: 'Cormorant Garamond', serif;
  font-weight: 300;
  font-style: italic;
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  line-height: 1;
  color: rgba(255, 255, 255, 0.13);      /* neutral — the one gold accent is the hairline */
  margin-bottom: 0.55rem;
  user-select: none;
  pointer-events: none;
}
.rv-story__kicker {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.38em;
  color: #93938b;
  margin-bottom: 1.05rem;
}
.rv-story__hairline {
  flex: none;
  width: 40px;
  height: 1px;
  background: linear-gradient(to right, #c6a667, rgba(198, 166, 103, 0));
}
.rv-story__title {
  font-family: 'Cormorant Garamond', serif;
  font-weight: 300;
  font-style: italic;
  font-size: clamp(1.35rem, 2.5vw, 1.95rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: #fafaf7;
  max-width: 20ch;
  margin: 0 0 0.85rem;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6), 0 0 16px rgba(0, 0, 0, 0.4);
}
.rv-story__body {
  font-weight: 300;
  font-size: clamp(0.9rem, 0.8vw, 1rem);
  line-height: 1.56;
  color: #e7e7e1;
  max-width: 46ch;
  margin: 0;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55), 0 0 14px rgba(0, 0, 0, 0.35);
}
.rv-story__micro {
  margin-top: 1.5rem;
  font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.24em;
  color: #86867e;
  line-height: 1.9;
}
/* Gentle inner cascade (shared [data-reveal] transition) */
.rv-story__no[data-reveal]     { transition-delay: 0ms; }
.rv-story__kicker[data-reveal] { transition-delay: 60ms; }
.rv-story__title[data-reveal]  { transition-delay: 140ms; }
.rv-story__body[data-reveal]   { transition-delay: 240ms; }
.rv-story__micro[data-reveal]  { transition-delay: 360ms; }
/* Typewriter caret on the manifest micro line — the one gold spark, well visible on glass */
.rv-story__manifest { display: inline; }
.rv-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 0.14em;
  transform: translateY(0.16em);
  background: #c6a667;
  vertical-align: baseline;
  opacity: 0;               /* hidden until typing starts */
  will-change: opacity;
}
[data-typing] .rv-caret { opacity: 1; }
[data-done] .rv-caret  { animation: rvCaretBlink 1.1s steps(1) infinite; }
@keyframes rvCaretBlink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .rv-caret { display: none; } }
/* Mobile: lighter blur for performance + a touch more fill for readability; real card offset */
@media (max-width: 767px) {
  .rv-story { padding: 2.25rem 0; scroll-margin-top: 6.75rem; }
  .rv-story__inner {
    margin: 0 1rem;
    padding: 1.6rem 1.35rem 1.75rem;
    border-radius: 1.15rem;
    background: rgba(14, 14, 16, 0.44);
    backdrop-filter: blur(8px) saturate(150%);
    -webkit-backdrop-filter: blur(8px) saturate(150%);
  }
  .rv-story__no { font-size: 2.3rem; margin-bottom: 0.7rem; }
  .rv-story__title { font-size: 1.7rem; line-height: 1.12; max-width: 18ch; margin-bottom: 1rem; }
  .rv-story__body { font-size: 1rem; line-height: 1.62; max-width: 38ch; }
  .rv-story__kicker { font-size: 9px; letter-spacing: 0.3em; }
  .rv-story__micro { font-size: 9px; letter-spacing: 0.2em; }
}
/* No backdrop-filter support → readable solid fill */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .rv-story__inner { background: rgba(10, 10, 12, 0.9); }
}

/* ============================================ */
/* RESPONSIVE UTILITIES */
/* ============================================ */

/* Smooth scroll behavior — html only. Never apply to `*`: that would force
   smooth animation onto programmatic scrollTop writes inside scroll containers
   (e.g. chat autoscroll during streaming), causing lag and rubber-banding. */
html {
  scroll-behavior: smooth;
}

/* Disable animations for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   BLOCK I — REDUCED-MOTION GUARDRAIL (reduced-motion).
   The blanket above only zeroes DURATIONS; this cancels transform TARGETS so
   hover/press/entrance FX are truly static.
   ───────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .glass-card-2d img            { transform: none !important; } /* kill any img hover zoom */
  .glass-card-2d.card-lift      { transform: none !important; } /* neutralise stale inline tilt */
  .glass-card-2d > .pointer-events-none.z-20 {                  /* glare overlay stays hidden */
    opacity: 0 !important;
    background: none !important;
  }
  .glass-card-2d .card-fx       { transform: none !important; animation: none !important; }
}
/* ── END BLOCK I ──────────────────────────────────────────────────────────── */

/* ============================================ */
/* MOBILE PERFORMANCE — backdrop-filter removed */
/* All glass classes fall back to opaque solid  */
/* colours that match what the blur shows over  */
/* the dark #09090b body. Desktop unaffected.   */
/* ============================================ */
@media (max-width: 767px) {
  .liquid-glass,
  .liquid-glass-heavy,
  .liquid-glass-story,
  .retro-glass,
  .filter-bar-compact,
  .filter-control,
  .filter-pill-active,
  .filter-pill-inactive,
  .card-meta {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  /* Disable pseudo-element specular sheens on mobile (compositor cost) */
  .liquid-glass::before,
  .glass-card-2d::before,
  .glass-card-2d::after,
  .filter-pill-active::before,
  .filter-pill-inactive::before,
  .card-meta::before {
    display: none !important;
  }
  /* Tailwind backdrop-blur utilities (modal overlay, badges, toasts) — same
     rationale: live blur behind scrolling content is the single most
     expensive compositor effect on mid-range phones. The elements carry
     near-opaque backgrounds, so the visual difference is negligible. */
  .backdrop-blur-sm,
  .backdrop-blur,
  .backdrop-blur-md,
  .backdrop-blur-lg,
  .backdrop-blur-xl {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }

  .liquid-glass        { background: rgba(8, 8, 8, 0.78); border-top-color: rgba(255,255,255,0.14); }
  .liquid-glass-heavy  { background: rgba(6, 6, 6, 0.88); }
  .liquid-glass-story  {
    background: rgba(8, 8, 8, 0.80);
    box-shadow: none;
  }
  .card-meta {
    background:
      linear-gradient(180deg,
        rgba(255,255,255,0.14) 0px,
        rgba(255,255,255,0) 1px,
        rgba(255,255,255,0.015) 2px,
        transparent 14px),
      rgba(6, 6, 6, 0.88);
  }
  .filter-bar-compact  { background: transparent; }
  .filter-control      { background: rgba(255, 255, 255, 0.06); }
  .scanline            { display: none; }

  /* Reduce cloud blur to save GPU compositing on mid-range phones */
  .vanta-mobile-sky::before { filter: blur(8px); }
  .vanta-mobile-sky::after  { filter: blur(10px); }

  /* content-visibility: off-screen below-fold panels skip paint until visible */
  .content-below-fold {
    content-visibility: auto;
    contain-intrinsic-size: 0 600px;
  }
}

/* Very old / low-power phones (≤ 430px) — strip all animations from the sky */
@media (max-width: 430px) {
  .vanta-mobile-sky::before,
  .vanta-mobile-sky::after {
    animation: none;
    filter: none;
  }
  /* Also stop kinetic hero lines from animating so first paint is instant */
  .kinetic-line {
    animation-duration: 0.4s;
    will-change: auto;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   RSC LANDING — full-screen hero + parallax feature slides
   ══════════════════════════════════════════════════════════════════════════ */

/* Hero */
.rsc-hero {
  height: 100%;
  min-height: 600px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  position: relative;
  overflow: hidden;
}

.rsc-hero__sub {
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.55em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.22);
  margin-bottom: 1.5rem;
  animation: rsc-fade-up 1.1s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.rsc-hero__title {
  font-size: clamp(2.6rem, 7vw, 6.5rem);
  font-weight: 100;
  letter-spacing: -0.03em;
  color: #fff;
  line-height: 1;
  margin: 0 0 2rem;
  animation: rsc-fade-up 1.3s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both;
}

.rsc-hero__tagline {
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.62rem;
  color: rgba(255, 255, 255, 0.22);
  letter-spacing: 0.08em;
  line-height: 2;
  text-align: center;
  max-width: 42ch;
  animation: rsc-fade-up 1.3s cubic-bezier(0.16, 1, 0.3, 1) 0.18s both;
}

.rsc-hero__scroll {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  animation: rsc-fade-in 1.8s ease 1s both;
}

.rsc-hero__scroll-text {
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.55em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.16);
}

.rsc-hero__scroll-line {
  width: 1px;
  height: 2.5rem;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.28), transparent);
  animation: rsc-scroll-pulse 2.4s ease-in-out 1.5s infinite;
}

@keyframes rsc-fade-up {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes rsc-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes rsc-scroll-pulse {
  0%, 100% { opacity: 0.25; transform: scaleY(0.85); }
  50%       { opacity: 0.7;  transform: scaleY(1.15) translateY(4px); }
}

/* Feature slides */
.rsc-slide {
  position: relative;
  height: 100vh;
  min-height: 600px;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  flex-shrink: 0;
}

.rsc-slide__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
  background-size: 64px 64px;
  pointer-events: none;
  z-index: 1;
}

.rsc-slide__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.97) 0%,
    rgba(0, 0, 0, 0.52) 45%,
    rgba(0, 0, 0, 0.18) 100%
  );
  z-index: 2;
}

.rsc-slide__content {
  position: relative;
  z-index: 10;
  padding: 0 8vw 11vh;
  width: 100%;
}

.rsc-slide__label {
  display: block;
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.55em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.2);
  margin-bottom: 1.4rem;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.8s ease 0.1s, transform 0.8s ease 0.1s;
}

.rsc-slide.is-visible .rsc-slide__label {
  opacity: 1;
  transform: translateY(0);
}

.rsc-slide__title-block {
  overflow: hidden;
}

.rsc-title-line {
  display: block;
  overflow: hidden;
  line-height: 1.04;
}

.rsc-title-line span {
  display: block;
  transform: translateY(115%);
  transition: transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
  font-size: clamp(2.4rem, 6.5vw, 5.8rem);
  font-weight: 200;
  letter-spacing: -0.025em;
  color: #ffffff;
}

.rsc-slide.is-visible .rsc-title-line span {
  transform: translateY(0);
}

.rsc-title-line:nth-child(2) span {
  transition-delay: 0.1s;
}

.rsc-slide__desc {
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.26);
  letter-spacing: 0.05em;
  line-height: 2;
  margin-top: 1.8rem;
  max-width: 48ch;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.9s ease 0.4s, transform 0.9s ease 0.4s;
}

.rsc-slide.is-visible .rsc-slide__desc {
  opacity: 1;
  transform: translateY(0);
}

.rsc-slide__counter {
  position: absolute;
  right: 8vw;
  bottom: 11vh;
  font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
  font-size: 0.45rem;
  letter-spacing: 0.5em;
  color: rgba(255, 255, 255, 0.08);
  z-index: 10;
  opacity: 0;
  transition: opacity 0.8s ease 0.5s;
}

.rsc-slide.is-visible .rsc-slide__counter {
  opacity: 1;
}

/* Login section at end of landing */
.rsc-login-section {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5rem 1rem;
  position: relative;
  flex-shrink: 0;
}

/* Mobile */
@media (max-width: 640px) {
  .rsc-hero__title { font-size: clamp(2rem, 11vw, 3.2rem); }
  .rsc-title-line span { font-size: clamp(1.8rem, 10vw, 2.8rem); }
  .rsc-slide__content { padding: 0 6vw 8vh; }
  .rsc-slide__counter { right: 6vw; bottom: 8vh; }
}

/* ==========================================================================
   SELECTABLE BACKGROUNDS + STORM LIGHTNING
   Appended block — consumed by BackgroundLayer / StormBackground components.
   Everything is scoped to .rv-* so it never touches product cards or any
   existing .rsc-* classes. Nothing above this line is modified.
   ========================================================================== */

/* --- Base fill layer --------------------------------------------------------
   Static, full-viewport, behind everything. The transition gives a soft
   cross-fade when the active theme background is swapped. */
.rv-bg {
  position: fixed;
  /* Stable large-viewport height (see --rv-bg-h) so the themed fill never jumps
     when the mobile URL bar toggles. Anchored top; bottom intentionally auto. */
  top: 0;
  left: 0;
  right: 0;
  bottom: auto;
  height: var(--rv-bg-h, 100vh);
  z-index: 0;
  pointer-events: none;
  transition: background 0.8s ease;
  /* Own compositor layer — avoids repaint on scroll (iOS) */
  transform: translateZ(0);
}

/* --- Theme: BLACK -----------------------------------------------------------
   Edel near-black with a subtle radial lift toward the top so it reads as
   depth rather than a flat #000 wall. */
.rv-bg--black {
  background: radial-gradient(120% 120% at 50% 0%, #101012 0%, #060607 60%, #000000 100%);
}

/* --- Theme: WHITE -----------------------------------------------------------
   Soft, warm archival paper / museum-wall tone. Never a hard #fff. A very
   faint radial vignette keeps the edges from looking clinical. */
.rv-bg--white {
  background:
    radial-gradient(140% 110% at 50% 0%, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0) 55%),
    linear-gradient(180deg, #f6f4ee 0%, #ece8df 55%, #e4dfd4 100%);
}

/* --- Theme: SUNSET ----------------------------------------------------------
   Rich, color-graded dusk gradient. Dark and cool up top (keeps light text
   legible), warm and glowing toward the bottom. A very slow, tiny-amplitude
   drift keeps it alive without ever reading as motion. */
.rv-bg--sunset {
  background: linear-gradient(
    180deg,
    #1a1030 0%,
    #4a1f4d 32%,
    #a83a54 60%,
    #e8794a 82%,
    #f2a65a 100%
  );
  background-size: 100% 130%;
  background-position: 50% 0%;
  animation: rvSunsetDrift 52s ease-in-out infinite;
}

@keyframes rvSunsetDrift {
  0%   { background-position: 50% 0%;   filter: hue-rotate(0deg); }
  50%  { background-position: 50% 8%;   filter: hue-rotate(-4deg); }
  100% { background-position: 50% 0%;   filter: hue-rotate(0deg); }
}

/* --- Theme-Presets (Registry: services/backgroundRegistry.ts) ---------------
   Ein Gradient-Preset = genau eine Klasse hier + ein Registry-Eintrag +
   ein EN-Label in i18n.ts. Die Basis-Klasse .rv-bg (Position/Cross-Fade oben)
   wird unverändert wiederverwendet. Kompositor-freundlich: keine animierten
   background-positions (statische Fills). */
.rv-bg--ocean {
  background:
    radial-gradient(120% 90% at 50% 100%, rgba(28, 96, 110, 0.45), rgba(28, 96, 110, 0) 60%),
    linear-gradient(180deg, #020a12 0%, #06283a 55%, #0a3d4a 100%);
}
.rv-bg--forest {
  background:
    radial-gradient(130% 100% at 50% 0%, rgba(52, 92, 58, 0.35), rgba(52, 92, 58, 0) 55%),
    linear-gradient(180deg, #06130a 0%, #0c2414 60%, #071008 100%);
}
/* lum:'light' im Registry-Eintrag → bekommt automatisch die data-lum="light"-Overrides */
.rv-bg--paper {
  background:
    radial-gradient(140% 110% at 50% 0%, rgba(255, 252, 244, 0.5), rgba(255, 252, 244, 0) 55%),
    linear-gradient(180deg, #f2ead8 0%, #e8dcc4 60%, #ddcfb4 100%);
}

/* --- Storm sky fallback -----------------------------------------------------
   Dark, cool storm base used behind the lightning layers (and as a standalone
   fallback if the flash layers are absent). */
.rv-storm__sky {
  background: linear-gradient(180deg, #0a0e14 0%, #12161d 50%, #0a0d12 100%);
}

/* --- Lightning flash layer --------------------------------------------------
   Screen-blended glow that stays invisible almost the entire cycle, then
   fires a brief, gentle double-flash. Duration overridable per-instance via
   the --rv-flash-dur custom property (default 11s). */
.rv-lightning {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
  background: radial-gradient(
    ellipse at 50% 20%,
    rgba(200, 220, 255, 0.9) 0%,
    rgba(150, 180, 255, 0.3) 30%,
    transparent 65%
  );
  animation: rvLightningFlash var(--rv-flash-dur, 11s) linear infinite;
}

@keyframes rvLightningFlash {
  0%,
  88% { opacity: 0; }
  89% { opacity: 0; }
  90% { opacity: 0.55; }
  91% { opacity: 0.1; }
  92% { opacity: 0.7; }
  94% { opacity: 0; }
  100% { opacity: 0; }
}

/* Second, staggered layer. Give it a different --rv-flash-dur and/or
   animation-delay inline (from StormBackground.tsx) so the two layers never
   flash in lock-step — subtle depth, never a strobe. */
.rv-lightning--b {
  background: radial-gradient(
    ellipse at 42% 28%,
    rgba(210, 225, 255, 0.85) 0%,
    rgba(140, 170, 255, 0.28) 32%,
    transparent 68%
  );
}

/* --- Reduced motion ---------------------------------------------------------
   Respect the user's preference: no flashing, no sunset drift. */
@media (prefers-reduced-motion: reduce) {
  .rv-lightning {
    animation: none;
    opacity: 0;
  }
  .rv-bg--sunset {
    animation: none;
  }
}

/* Mobile: the sunset drift animates background-position + filter, which forces a
   full repaint of the fixed, viewport-sized layer every frame — the only
   background that isn't compositor-only. Freeze it on phones so scrolling stays
   perfectly smooth (the static dusk gradient still looks rich). Desktop keeps
   the gentle drift. */
@media (max-width: 767px) {
  .rv-bg--sunset {
    animation: none;
  }
}

/* ============================================================================
   Sourcing page — light (white / day) theme overrides
   ----------------------------------------------------------------------------
   The Sourcing page hard-codes a light-on-dark Tailwind palette (text-white,
   text-zinc-400..700 on near-transparent glass). On the user-selectable white
   theme (html[data-lum="light"], bg ~#ece8df) that renders near-invisible.
   Scoped under .rv-sourcing only, we remap the neutral ink to dark tones and
   make the glass fills opaque light so everything is legible on #ece8df.
   Mirrors the pattern used by .rv-community / .rv-explainer / .rv-story.
   Emerald / amber / red accent tokens are left intact — they read on light. */
html[data-lum="light"] .rv-sourcing .text-white { color: #1a1a18; }
html[data-lum="light"] .rv-sourcing .text-zinc-300 { color: #3a3a34; }
html[data-lum="light"] .rv-sourcing .text-zinc-400 { color: #4a4a44; }
html[data-lum="light"] .rv-sourcing .text-zinc-500 { color: #5a5a52; }
html[data-lum="light"] .rv-sourcing .text-zinc-600 { color: #6a6a62; }
html[data-lum="light"] .rv-sourcing .text-zinc-700 { color: #7a7a70; }

/* Serif italic accent line in the hero (uses text-zinc-700) — keep it soft. */
html[data-lum="light"] .rv-sourcing h1 .text-zinc-700 { color: #8a8a80; }

/* Opaque light glass so text sits on a readable surface, not on beige. */
html[data-lum="light"] .rv-sourcing .liquid-glass,
html[data-lum="light"] .rv-sourcing .liquid-glass-heavy {
  background: rgba(255, 255, 255, 0.9);
  border-color: rgba(0, 0, 0, 0.08);
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.08);
}
html[data-lum="light"] .rv-sourcing .liquid-glass:hover {
  background: rgba(255, 255, 255, 0.96);
  border-color: rgba(0, 0, 0, 0.14);
}
/* Kill the dark specular sheen overlay on light glass. */
html[data-lum="light"] .rv-sourcing .liquid-glass::before { opacity: 0; }

/* Hairline dividers / white-tinted borders → dark hairlines on light. */
html[data-lum="light"] .rv-sourcing .border-white\/5 { border-color: rgba(0, 0, 0, 0.06); }
html[data-lum="light"] .rv-sourcing .border-white\/10 { border-color: rgba(0, 0, 0, 0.12); }
html[data-lum="light"] .rv-sourcing .border-white\/20 { border-color: rgba(0, 0, 0, 0.18); }
html[data-lum="light"] .rv-sourcing .border-white\/30 { border-color: rgba(0, 0, 0, 0.28); }

/* White-tinted fills (hero badge, selected card, textarea/inputs) → light ink fills. */
html[data-lum="light"] .rv-sourcing .bg-white\/5 { background-color: rgba(0, 0, 0, 0.03); }
html[data-lum="light"] .rv-sourcing .bg-white\/10 { background-color: rgba(0, 0, 0, 0.06); }

/* Calculator number inputs use bg-black/40 + text-white; on light theme make
   them a light field with dark ink so the typed value is legible. */
html[data-lum="light"] .rv-sourcing .bg-black\/30 { background-color: rgba(0, 0, 0, 0.04); }
html[data-lum="light"] .rv-sourcing .bg-black\/40 { background-color: rgba(0, 0, 0, 0.05); }
html[data-lum="light"] .rv-sourcing input.bg-black\/40 { color: #1a1a18; }

/* The urgency <select> uses solid bg-black; invert to a light field on light. */
html[data-lum="light"] .rv-sourcing select.bg-black {
  background-color: #f4f1e9;
  color: #1a1a18;
}

/* Selected-tier radio fill flips to white on dark; on light use dark ink so the
   check mark (text-black) stays visible against it. */
html[data-lum="light"] .rv-sourcing .border-white.bg-white { background-color: #1a1a18; border-color: #1a1a18; }

/* Submit button is bg-white/text-black on dark — that already reads on light,
   but darken it for contrast against the near-white page. */
html[data-lum="light"] .rv-sourcing button.bg-white { background-color: #1a1a18; color: #f4f1e9; }
html[data-lum="light"] .rv-sourcing button.bg-white:hover { background-color: #33332e; }


/* ── card-perfection: Registry serial integrity — one artifact, one serial + Retir ── */
/* Gold shimmer — reduced motion: no sweep, rest on the warm mid-gradient */
@media (prefers-reduced-motion: reduce) {
  .text-gold-shimmer {
    animation: none;
    background-position: 50% center;
  }
}

/* ── card-perfection: Cap the lot title at 2–3 balanced lines with a fluid, length ── */
/* Modal lot title — balance the rag on 2–3 line titles.
   Compositor-neutral; graceful no-op in browsers without text-wrap support. */
#product-detail-title {
  text-wrap: balance;
}

/* In-cart confirmation — house gold instead of checkout-emerald.
   Uses --gold-leaf / --gold-parchment from :root in showroom-visuals.css;
   append these rules to public/styles/showroom-visuals.css. The product
   modal renders dark in both themes, so no light-theme variant is needed. */
.rv-incart-gold {
  border-color: rgba(var(--gold-leaf), 0.5);
  background: rgba(var(--gold-leaf), 0.08);
  color: rgb(var(--gold-parchment));
}
.rv-incart-gold:hover {
  border-color: rgba(var(--gold-leaf), 0.75);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ANIMATIONS MASTER SWITCH (Baukasten) — html.rv-anim-off
   App.tsx sets this class while siteConfig.animationsEnabled === false. It
   MIRRORS the prefers-reduced-motion rules above as plain class rules, so
   "animations off" behaves exactly like an OS reduced-motion request. The media
   queries stay untouched — the user's own preference keeps working on its own;
   this block only adds a second trigger. Only target-state rules are mirrored
   individually; pure duration kills come from the blanket below.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Blanket duration kill (mirror of the prefers-reduced-motion blanket) */
html.rv-anim-off *,
html.rv-anim-off *::before,
html.rv-anim-off *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
}
html.rv-anim-off { scroll-behavior: auto; } /* html itself isn't matched by the * above */

/* Scroll reveal → instantly visible */
html.rv-anim-off [data-reveal] {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* Card tilt/glare — cancel transform TARGETS. Beats the inline mousemove tilt
   (!important), so already-mounted cards go static the moment the class lands. */
html.rv-anim-off .glass-card-2d img            { transform: none !important; }
html.rv-anim-off .glass-card-2d.card-lift      { transform: none !important; }
html.rv-anim-off .glass-card-2d > .pointer-events-none.z-20 {
  opacity: 0 !important;
  background: none !important;
}
html.rv-anim-off .glass-card-2d .card-fx       { transform: none !important; animation: none !important; }

/* Photo push-in (BOTH selectors, or the hover rule would outrank a lone mirror) */
html.rv-anim-off .rv-photo-zoom,
html.rv-anim-off .group:hover .rv-photo-zoom { transform: none; filter: none; transition: none; }

/* Hero statics */
html.rv-anim-off .scroll-cue-dot { animation: none; top: 40%; opacity: 0.8; }
html.rv-anim-off .hero-eyebrow   { animation: none; opacity: 1; }

/* Typewriter caret (the typing itself is gated in Showroom) */
html.rv-anim-off .rv-caret { display: none; }

/* Gold sheen rests on the warm mid-gradient */
html.rv-anim-off .text-gold-shimmer { animation: none; background-position: 50% center; }

/* Storm / sunset — CSS backstop even if the React layer hasn't re-rendered yet */
html.rv-anim-off .rv-lightning  { animation: none; opacity: 0; }
html.rv-anim-off .rv-bg--sunset { animation: none; }

/* Night sky */
html.rv-anim-off .ns-sky   { animation: none !important; }
html.rv-anim-off .ns-stars { animation: none !important; }

/* Skeleton sweep → flat graphite plate */
html.rv-anim-off .img-skeleton { animation: none; background-image: none; background-color: #0a0a0c; }

/* Press micro-interaction → static dim */
html.rv-anim-off .glass-card-2d:active,
html.rv-anim-off .glass-card-2d[data-pressed='1'] {
  animation: none !important;
  transform: none !important;
  transition: filter 0.1s ease !important;
  filter: brightness(0.97) !important;
}
html.rv-anim-off .glass-card-2d:active .card-meta,
html.rv-anim-off .glass-card-2d[data-pressed='1'] .card-meta {
  animation: none !important;
  transform: none !important;
  filter: brightness(0.96) !important;
  transition: filter 0.1s ease !important;
}

/* ============================================================ */
/* RARITY TIERS — Seltenheits-Rahmen + Editions-Plakette         */
/* Registry: services/rarityPresets.ts (bronze/silver/legendary) */
/*                                                               */
/* Der Rahmen ist ein EIGENES Div direkt im Karten-Root          */
/* (.glass-card-2d) — dessen ::before/::after sind vom Specular/ */
/* Fresnel-Effekt belegt. border-radius:inherit erbt so die      */
/* echten 20px Karten-Radius. z-12: über Specular(10)/Fresnel(11)*/
/* und COA/ID(10), unter Glare/Wishlist(20); pointer-events:none */
/* hält №/Wishlist/COA klickbar.                                 */
/* Ring-Technik: Gradient füllt die Border-Box, mask-composite   */
/* stanzt die Padding-Box heraus → nur der 1.5px-Ring bleibt     */
/* sichtbar, das Produktfoto darunter bleibt unangetastet. Die   */
/* Maske clippt auch die ::after-Sweeps: der Glanz läuft NUR     */
/* über den Ring und niemals über das Foto. Browser ohne         */
/* mask-composite bekommen einen soliden inset-box-shadow-Ring   */
/* (statisch, ohne Sweep).                                       */
/* GPU-Regeln: Sweeps sind transform-only (translateX), KEIN     */
/* filter-/box-shadow-Anim, KEIN backdrop-filter (mobile-sicher).*/
/* ============================================================ */

.rv-rarity-frame {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 12;
}

/* Fallback-Ringe (immer aktiv; im @supports-Block darunter ersetzt) */
.rv-rarity--bronze    { box-shadow: inset 0 0 0 1.5px rgba(180, 120, 60, 0.60); }
.rv-rarity--silver    { box-shadow: inset 0 0 0 1.5px rgba(176, 188, 210, 0.55); }
.rv-rarity--legendary { box-shadow: inset 0 0 0 1.5px rgba(var(--gold-leaf), 0.75); }

@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .rv-rarity--bronze,
  .rv-rarity--silver,
  .rv-rarity--legendary {
    box-shadow: none;
    border: 1.5px solid transparent;
    -webkit-mask:
      linear-gradient(#000 0 0) padding-box,
      linear-gradient(#000 0 0) border-box;
    -webkit-mask-composite: xor;
    mask:
      linear-gradient(#000 0 0) padding-box,
      linear-gradient(#000 0 0) border-box;
    mask-composite: exclude;
  }

  /* BRONZE — statischer Ring, warme Bronzetöne. Kein Sweep. */
  .rv-rarity--bronze {
    background: linear-gradient(160deg,
      rgba(180, 120, 60, 0.85) 0%,
      rgba(126, 78, 38, 0.45) 45%,
      rgba(196, 138, 78, 0.70) 100%) border-box;
  }

  /* SILVER — kühler Ring … */
  .rv-rarity--silver {
    background: linear-gradient(160deg,
      rgba(200, 210, 228, 0.85) 0%,
      rgba(112, 122, 142, 0.40) 45%,
      rgba(176, 188, 210, 0.75) 100%) border-box;
  }

  /* … + EIN Sheen-Durchlauf on-hover. transform-only; 'both' hält den
     Sweep nach dem Durchlauf off-canvas, erneutes Hovern startet neu.
     WICHTIG: inset -2px, damit der Sweep die Border-Zone (den Ring)
     überdeckt — inset:0 würde nur die Padding-Box abdecken und der
     maskierte Ring bliebe ohne Glanz. */
  .rv-rarity--silver::after {
    content: '';
    position: absolute;
    inset: -2px;
    background: linear-gradient(60deg,
      transparent 32%,
      rgba(226, 233, 244, 0.40) 50%,
      transparent 68%);
    transform: translateX(-150%);
  }
  .group:hover .rv-rarity--silver::after {
    animation: rvRaritySheenOnce 1.2s ease both;
  }

  /* LEGENDARY — Gold-Gradient-Ring aus den bestehenden Gold-Variablen. */
  .rv-rarity--legendary {
    background: linear-gradient(160deg,
      rgba(var(--gold-leaf), 0.95) 0%,
      rgba(var(--gold-parchment), 0.55) 35%,
      rgba(var(--gold-leaf), 0.50) 65%,
      rgba(var(--gold-parchment), 0.85) 100%) border-box;
  }
  .rv-rarity--legendary::after {
    content: '';
    position: absolute;
    inset: -2px;
    background: linear-gradient(60deg,
      transparent 32%,
      rgba(250, 246, 234, 0.35) 50%,
      transparent 68%);
    transform: translateX(-150%);
  }
  /* Glanz-Sweep NUR mit .rv-rarity-fx: ProductCard hängt die Klasse ab
     pixelPhase==='done' an das FRAME-ELEMENT SELBST (compound-Selektor);
     der descendant-Selektor deckt zusätzlich den Fall "Klasse auf der
     Karte" ab. 6s-Zyklus, davon 1.2s sichtbar (0→20%), dann Ruhe. */
  .rv-rarity-fx.rv-rarity--legendary::after,
  .rv-rarity-fx .rv-rarity--legendary::after {
    animation: rvRarityGoldSweep 6s ease-in-out infinite;
  }
}

@keyframes rvRaritySheenOnce {
  from { transform: translateX(-150%); }
  to   { transform: translateX(150%); }
}
@keyframes rvRarityGoldSweep {
  0%   { transform: translateX(-150%); }
  20%  { transform: translateX(150%); }
  100% { transform: translateX(150%); }
}

/* Editions-Plakette — kleine Mono-Kapsel unten rechts im Bild-Frame.
   Unten rechts ist auf der Karte frei (ID-Badge oben links, COA-Seal
   unten links, Wishlist oben rechts). Dunkler Grund OHNE backdrop-filter. */
.rv-edition-plaque {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 13;
  pointer-events: none;
  padding: 2px 8px 3px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(9, 9, 11, 0.78);
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 0.14em;
  line-height: 1.5;
  text-transform: uppercase;
  color: rgba(228, 228, 231, 0.92);
  white-space: nowrap;
}
.rv-edition-plaque--legendary {
  color: rgb(var(--gold-leaf));
  border-color: rgba(var(--gold-leaf), 0.45);
}

/* Bewegung aus: OS-Präferenz, Touch, globaler Killswitch */
@media (prefers-reduced-motion: reduce) {
  .rv-rarity--silver::after,
  .rv-rarity--legendary::after,
  .group:hover .rv-rarity--silver::after,
  .rv-rarity-fx .rv-rarity--legendary::after {
    animation: none !important;
  }
}
/* Touch: keine Dauer-Animation — Sweep komplett aus. */
@media (hover: none) {
  .group:hover .rv-rarity--silver::after,
  .rv-rarity-fx.rv-rarity--legendary::after,
  .rv-rarity-fx .rv-rarity--legendary::after {
    animation: none !important;
  }
}
html.rv-anim-off .rv-rarity--silver::after,
html.rv-anim-off .rv-rarity--legendary::after,
html.rv-anim-off .group:hover .rv-rarity--silver::after,
html.rv-anim-off .rv-rarity-fx .rv-rarity--legendary::after {
  animation: none !important;
}
