/* ==========================================================================
   HS GADGETS — premium dark-first design system
   No build step. No framework. Light + dark both designed properly.

   Contents
     01  Tokens
     02  Reset & base
     03  Ambient layers (noise, orbs, grid)
     04  Cursor
     05  Nav
     06  Buttons
     07  Hero + kinetic type
     08  Marquee
     09  Product cards
     10  Catalog controls
     11  Features
     12  Reviews
     13  Contact
     14  Footer
     15  Motion / reveals
     16  Responsive
     17  Reduced motion
   ========================================================================== */

/* ============================ 01 TOKENS ================================== */

:root {
  /* Brand — violet through fuchsia to sky. Chosen to sit on true black
     rather than the washed indigo the first pass used. */
  --a1: #8b5cf6;   /* violet   */
  --a2: #38bdf8;   /* sky      */
  --a3: #e879f9;   /* fuchsia  */
  --wa: #25d366;   /* whatsapp */

  --grad: linear-gradient(120deg, var(--a1), var(--a3) 52%, var(--a2));

  /* Dark surfaces — true black, so the gradients actually glow */
  --bg:        #000000;
  --bg-2:      #08080e;
  --surface:   rgba(255,255,255,.05);
  --surface-2: rgba(255,255,255,.03);
  --line:      rgba(255,255,255,.10);
  --line-2:    rgba(255,255,255,.06);

  --ink:   #f6f7fb;
  --ink-2: #a8b0c4;
  --ink-3: #6d7488;

  --glow-1: rgba(139,92,246,.34);
  --glow-2: rgba(56,189,248,.24);
  --glow-3: rgba(232,121,249,.22);
  --glow-4: rgba(139,92,246,.16);

  /* Panels get a gradient of their own rather than a flat fill. The top
     inset hairline is what keeps them reading as raised surfaces once the
     fill stops being a solid block. */
  --card-bg: linear-gradient(155deg, rgba(255,255,255,.09) 0%, rgba(255,255,255,.035) 55%, rgba(139,92,246,.05) 100%);
  --card-inset: inset 0 1px 0 rgba(255,255,255,.10);

  --shadow:    0 1px 2px rgba(0,0,0,.4), 0 18px 44px -18px rgba(0,0,0,.75);
  --shadow-lg: 0 2px 8px rgba(0,0,0,.5),  0 46px 90px -30px rgba(0,0,0,.9);

  --radius:    22px;
  --radius-sm: 14px;
  --maxw:      1180px;
  --nav-h:     64px;

  --ease: cubic-bezier(.22,1,.36,1);
  --ease-out: cubic-bezier(.16,1,.3,1);

  color-scheme: dark;
}

html[data-theme="light"] {
  /* Palette sampled from the silk reference: soft blue, periwinkle,
     lilac, rose, peach, cream. The pastels themselves are far too pale
     to put white text on, so they drive the washes while the accents
     below are deepened versions of the same hues. */
  --p-blue:  #a9cbe8;
  --p-peri:  #bfc4e8;
  --p-lilac: #d3c2e4;
  --p-rose:  #f1b9d2;
  --p-peach: #f8cba4;
  --p-cream: #fbe6cb;

  --a1: #6d5fb0;   /* deepened periwinkle */
  --a2: #3f8bc4;   /* deepened sky        */
  --a3: #c25f92;   /* deepened rose       */

  --grad: linear-gradient(120deg, var(--a1), var(--a3) 50%, var(--a2));

  --bg:        #ffffff;
  --bg-2:      #fdfcff;
  --surface:   #ffffff;
  --surface-2: #fcfaff;
  --line:      rgba(24,18,48,.10);
  --line-2:    rgba(24,18,48,.055);

  --ink:   #0b0818;
  --ink-2: #4d4664;
  --ink-3: #857f9d;

  --glow-1: rgba(169,203,232,.62);   /* blue   */
  --glow-2: rgba(241,185,210,.52);   /* rose   */
  --glow-3: rgba(248,203,164,.50);   /* peach  */
  --glow-4: rgba(211,194,228,.55);   /* lilac  */

  /* Around 70% opaque rather than solid, so the wash reads through and the
     panels sit in the page instead of on top of it. Light theme only —
     dark panels are already translucent. */
  --card-bg: linear-gradient(155deg, rgba(255,255,255,.74) 0%, rgba(255,255,255,.60) 50%, rgba(252,246,252,.56) 100%);
  --card-inset: inset 0 1px 0 rgba(255,255,255,.7);

  /* Softer, since a translucent panel with a heavy shadow reads as a
     cut-out floating above the page rather than part of it. */
  --shadow:    0 1px 2px rgba(17,12,40,.03), 0 14px 32px -20px rgba(17,12,40,.12);
  --shadow-lg: 0 2px 8px rgba(17,12,40,.05), 0 38px 72px -34px rgba(17,12,40,.18);

  color-scheme: light;
}

/* ========================= 02 RESET & BASE =============================== */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 26px);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color .5s var(--ease), color .5s var(--ease);

  /* A very faint tint carried down the whole page. Without this the areas
     below the hero fall back to flat white (light) or flat black (dark),
     which reads as unfinished rather than minimal. Fixed attachment keeps
     it steady while the page scrolls. */
  background-color: var(--bg);
  background-image:
    radial-gradient(58% 42% at 90% 2%,  var(--glow-3), transparent 60%),
    radial-gradient(54% 40% at 60% 14%, var(--glow-2), transparent 62%),
    radial-gradient(56% 44% at 3% 30%,  var(--glow-1), transparent 62%),
    radial-gradient(50% 38% at 30% 70%, var(--glow-4), transparent 62%),
    radial-gradient(58% 42% at 82% 96%, var(--glow-2), transparent 62%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

img, svg { display: block; max-width: 100%; }

/* Several components set an explicit display, which would otherwise beat the
   [hidden] attribute the JS uses to hide empty rows. */
[hidden] { display: none !important; }

/* Panels are translucent, so they need a blur behind them — otherwise the
   dot field and wash read straight through and the text loses its footing. */
.card, .feature, .contact-card, .cta-band, .search-box input, .hero-pill, .chip {
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
}
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: color-mix(in srgb, var(--a1) 60%, transparent); color: #fff; }

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: 22px; }

.section { position: relative; padding: clamp(64px, 9vw, 120px) 0; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Section heading */
.eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: Oswald, Inter, sans-serif;
  font-size: .78rem; font-weight: 500; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 14px;
}
.eyebrow::before {
  content: ""; width: 26px; height: 1px;
  background: var(--grad);
}

.section-head { margin-bottom: clamp(28px, 4vw, 52px); max-width: 62ch; }
.section-head h2 {
  font-family: Oswald, Inter, sans-serif;
  font-weight: 600; text-transform: uppercase; letter-spacing: .005em;
  font-size: clamp(1.9rem, 4.6vw, 3.1rem);
  line-height: 1.02;
}
.section-head p { color: var(--ink-2); margin-top: 14px; font-size: 1.03rem; }

.grad-text {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}

/* ====================== 03 AMBIENT LAYERS ================================ */

/* Fine noise so flat dark areas don't band */
.noise {
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
html[data-theme="light"] .noise { opacity: .022; mix-blend-mode: multiply; }

/* Page-wide ambient layer. Fixed, so the field stays put while content
   scrolls over it and the cursor can reach it from any section. */
.bg-layer {
  position: fixed; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
}
/* Everything readable sits above it. */
main, .site-footer { position: relative; z-index: 1; }

.orbs { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
.orb {
  position: absolute; border-radius: 50%;
  filter: blur(90px);
  will-change: transform;
}
.orb-1 { width: 46vw; height: 46vw; left: -12vw; top: -14vw; background: var(--glow-1);
         animation: drift1 22s var(--ease) infinite alternate; }
.orb-2 { width: 40vw; height: 40vw; right: -10vw; top: 4vw;  background: var(--glow-2);
         animation: drift2 26s var(--ease) infinite alternate; }
.orb-3 { width: 32vw; height: 32vw; left: 34vw; bottom: -16vw; background: var(--glow-3);
         animation: drift3 30s var(--ease) infinite alternate; }

@keyframes drift1 { to { transform: translate3d(7vw, 5vw, 0) scale(1.14); } }
@keyframes drift2 { to { transform: translate3d(-6vw, 8vw, 0) scale(1.2); } }
@keyframes drift3 { to { transform: translate3d(4vw, -6vw, 0) scale(.88); } }

/* Interactive dot field arranged in concentric rings. Drawn on canvas so
   the dots can respond to the cursor and to periodic outward pulses. */
.rings-canvas {
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
}

/* Static CSS fallback — used only when motion is reduced, or before the
   canvas initialises, so the hero is never bare. */
.rings {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: repeating-radial-gradient(
    circle at 78% 12%,
    transparent 0 92px,
    var(--line-2) 92px 93px
  );
  mask-image: radial-gradient(circle at 78% 12%, #000 8%, rgba(0,0,0,.55) 45%, transparent 78%);
  -webkit-mask-image: radial-gradient(circle at 78% 12%, #000 8%, rgba(0,0,0,.55) 45%, transparent 78%);
}
/* Once the canvas is running the CSS rings would double up. */
body.field-on .rings { display: none; }

/* Wide colour wash. This is what keeps light mode from looking grey —
   the tint does the work a grey fill used to. */
.wash {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(120% 80% at 12% 0%,  var(--glow-1), transparent 58%),
    radial-gradient(100% 70% at 92% 22%, var(--glow-2), transparent 62%),
    radial-gradient(90%  75% at 50% 108%, var(--glow-3), transparent 60%);
}

/* Scroll progress */
.progress {
  position: fixed; top: 0; left: 0; height: 2px; z-index: 90;
  width: 100%; transform-origin: 0 50%; transform: scaleX(0);
  background: var(--grad);
}
@supports (animation-timeline: scroll()) {
  .progress {
    animation: progress linear;
    animation-timeline: scroll(root block);
  }
  @keyframes progress { to { transform: scaleX(1); } }
}

/* ============================ 04 CURSOR ================================== */

/* The ribbon canvas sits under the dot and ring. */
.cursor-canvas {
  position: fixed; inset: 0; z-index: 94;
  pointer-events: none;
}

.cursor, .cursor-ring {
  position: fixed; top: 0; left: 0; z-index: 95;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
  transition: opacity .3s ease;
}
.cursor {
  width: 8px; height: 8px;
  background: #fff;
  box-shadow: 0 0 10px 2px color-mix(in srgb, var(--a2) 85%, transparent),
              0 0 22px 6px color-mix(in srgb, var(--a1) 55%, transparent);
  transform: translate3d(-50%, -50%, 0);
}
html[data-theme="light"] .cursor {
  background: var(--a1);
  box-shadow: 0 0 8px 2px color-mix(in srgb, var(--a2) 55%, transparent);
}
.cursor-ring {
  width: 34px; height: 34px;
  border: 1px solid color-mix(in srgb, var(--a1) 70%, transparent);
  transform: translate3d(-50%, -50%, 0);
  transition: opacity .3s ease, width .32s var(--ease), height .32s var(--ease),
              background-color .32s var(--ease), border-color .32s var(--ease);
}
body.cursor-on .cursor, body.cursor-on .cursor-ring { opacity: 1; }
body.cursor-on { cursor: none; }
body.cursor-on a, body.cursor-on button, body.cursor-on input { cursor: none; }

/* Ring swells over interactive things */
.cursor-ring.is-hover {
  width: 62px; height: 62px;
  background: color-mix(in srgb, var(--a1) 14%, transparent);
  border-color: color-mix(in srgb, var(--a2) 80%, transparent);
}
.cursor-ring.is-press { width: 26px; height: 26px; }

/* ============================== 05 NAV =================================== */

.nav {
  position: fixed; top: 14px; left: 50%; z-index: 80;
  transform: translateX(-50%);
  width: calc(100% - 28px); max-width: var(--maxw);
  height: var(--nav-h);
  display: flex; align-items: center; gap: 18px;
  padding: 0 10px 0 18px;
  background: color-mix(in srgb, var(--bg-2) 72%, transparent);
  border: 1px solid var(--line);
  border-radius: 18px;
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  transition: box-shadow .4s var(--ease), background .4s var(--ease),
              height .4s var(--ease), border-color .4s var(--ease);
}
.nav.scrolled { box-shadow: var(--shadow); height: 56px; }

.brand { display: flex; align-items: center; gap: 10px; margin-right: auto; }
/* The mark itself carries the brand, so it sits on the surface rather than
   inside a coloured tile — a gradient chip behind it fought with the logo. */
.brand-mark {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
}
.brand-mark img { width: 100%; height: 100%; object-fit: contain; }

/* Dark logo on light backgrounds, white logo on dark. */
.mark-dark  { display: none; }
.mark-light { display: block; }
html[data-theme="dark"] .mark-dark  { display: block; }
html[data-theme="dark"] .mark-light { display: none; }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .mark-dark  { display: block; }
  html:not([data-theme="light"]) .mark-light { display: none; }
}
/* Wordmark: "HS" semibold, "Gadgets" light — the weight contrast is what
   makes it read as one lockup rather than two words. */
.brand-name {
  font-family: Oswald, Inter, sans-serif;
  font-size: 1.24rem;
  letter-spacing: .09em; text-transform: uppercase;
  white-space: nowrap;
}
.bn-hs { font-weight: 600; }
.bn-g  { font-weight: 300; }

.nav-links { display: none; align-items: center; gap: 4px; }
.nav-links a {
  position: relative;
  padding: 8px 14px; border-radius: 10px;
  font-size: .9rem; font-weight: 500; color: var(--ink-2);
  transition: color .25s var(--ease), background .25s var(--ease);
}
.nav-links a::after {
  content: ""; position: absolute; left: 14px; right: 14px; bottom: 4px;
  height: 1px; background: var(--grad);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .35s var(--ease);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { transform: scaleX(1); }

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

.icon-btn {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 11px;
  color: var(--ink-2);
  transition: color .25s, border-color .25s, background .25s, transform .25s var(--ease);
}
.icon-btn:hover { color: var(--ink); border-color: color-mix(in srgb, var(--a2) 60%, transparent); transform: translateY(-2px); }
.icon-btn svg { width: 17px; height: 17px; }

.nav-cta { display: none; }

/* ============================ 06 BUTTONS ================================= */

.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 13px 24px;
  border-radius: 12px;
  font-size: .94rem; font-weight: 600; letter-spacing: .01em;
  white-space: nowrap;
  overflow: hidden;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease),
              border-color .3s var(--ease), color .3s var(--ease);
}
.btn svg { width: 17px; height: 17px; flex: none; }

.btn-primary { background: var(--grad); color: #fff; background-size: 180% 100%; }
.btn-primary:hover { transform: translateY(-3px); box-shadow: 0 20px 40px -14px var(--a1); background-position: 100% 0; }

.btn-wa { background: var(--wa); color: #05240f; }
.btn-wa:hover { transform: translateY(-3px); box-shadow: 0 20px 40px -14px var(--wa); }

.btn-ghost { border: 1px solid var(--line); color: var(--ink); background: var(--surface-2); }
.btn-ghost:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--a2) 70%, transparent); }

.btn[disabled], .btn.is-disabled { opacity: .45; pointer-events: none; }

/* Same reasoning as the tilt cards — magnetic offset is set per-frame. */
.btn[data-magnetic]:hover {
  transition: box-shadow .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease);
}

/* Sheen sweep */
.btn::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.32) 50%, transparent 62%);
  transform: translateX(-120%);
  transition: transform .7s var(--ease);
}
.btn:hover::after { transform: translateX(120%); }

/* ============================== 07 HERO ================================== */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  padding: calc(var(--nav-h) + 70px) 0 70px;
  overflow: hidden;
}
.hero .wrap { position: relative; z-index: 2; }

.hero-pill {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 15px 7px 9px; margin-bottom: 26px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: 999px;
  font-size: .82rem; color: var(--ink-2);
  backdrop-filter: blur(10px);
}
.hero-pill .live {
  position: relative; width: 7px; height: 7px; border-radius: 50%;
  background: var(--wa); flex: none;
}
.hero-pill .live::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 1px solid var(--wa); opacity: .55;
  animation: ping 2.2s var(--ease) infinite;
}
@keyframes ping { to { transform: scale(2.1); opacity: 0; } }

.hero h1 {
  font-family: Oswald, Inter, sans-serif;
  font-weight: 600; text-transform: uppercase;
  font-size: clamp(2.6rem, 9.5vw, 6.6rem);
  line-height: .95; letter-spacing: -.005em;
  max-width: 15ch;
}

/* Kinetic type: each line rises + unblurs on load */
.line { display: block; overflow: hidden; }
.line > span {
  display: inline-block;
  transform: translateY(105%) rotate(2deg);
  filter: blur(9px);
  opacity: 0;
  animation: riseIn 1.05s var(--ease-out) forwards;
  animation-delay: calc(var(--d, 0) * 110ms + 120ms);
}
@keyframes riseIn {
  to { transform: translateY(0) rotate(0); filter: blur(0); opacity: 1; }
}

/* Weight + tracking shift as the hero scrolls away */
@supports (animation-timeline: view()) {
  .kinetic {
    animation: kinetic linear both;
    animation-timeline: view();
    animation-range: exit 0% exit 90%;
  }
  @keyframes kinetic {
    to { letter-spacing: .05em; opacity: .25; filter: blur(3px); }
  }
}

.hero p {
  margin-top: 24px;
  font-size: clamp(1rem, 1.9vw, 1.16rem);
  color: var(--ink-2);
  max-width: 52ch;
}

/* Longer intro copy: a wider measure and slightly smaller type keep it
   from turning into a wall of text under the headline. */
.hero-lede {
  max-width: 64ch;
  font-size: clamp(.97rem, 1.6vw, 1.06rem);
  line-height: 1.72;
  text-wrap: pretty;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 36px; }

.hero-stats {
  display: flex; flex-wrap: wrap; gap: clamp(24px, 5vw, 60px);
  margin-top: clamp(44px, 7vw, 78px);
  padding-top: 30px;
  border-top: 1px solid var(--line-2);
}
.stat strong {
  display: block;
  font-family: Oswald, sans-serif; font-weight: 600;
  font-size: clamp(1.7rem, 3.4vw, 2.5rem); line-height: 1;
}
.stat span { font-size: .84rem; color: var(--ink-3); letter-spacing: .04em; }

/* Scroll hint */
/* ============================ 08 MARQUEE ================================= */

.marquee {
  position: relative;
  padding: 20px 0;
  border-block: 1px solid var(--line-2);
  background: var(--surface-2);
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex; gap: 44px; width: max-content;
  animation: slide 34s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track span {
  font-family: Oswald, sans-serif; font-weight: 500;
  font-size: 1.05rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 44px;
  white-space: nowrap;
}
.marquee-track span::after {
  content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--a2); opacity: .6;
}
@keyframes slide { to { transform: translateX(-50%); } }

/* ========================= 09 PRODUCT CARDS ============================== */

.grid {
  display: grid; gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 262px), 1fr));
}

.card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--card-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transform-style: preserve-3d;
  transition: transform .45s var(--ease), box-shadow .45s var(--ease), border-color .45s var(--ease);
}

/* Glow follows the pointer across the card */
.card::before {
  content: ""; position: absolute; inset: -1px; z-index: 0;
  border-radius: inherit;
  background: radial-gradient(360px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--a1) 26%, transparent), transparent 62%);
  opacity: 0; transition: opacity .4s var(--ease);
  pointer-events: none;
}
.card:hover::before { opacity: 1; }
.card:hover { box-shadow: var(--shadow-lg), var(--card-inset); border-color: color-mix(in srgb, var(--a2) 42%, var(--line)); }
.card.is-out { opacity: .55; }

/* While tilting, transform is driven per-frame by JS — transitioning it
   would smear every mousemove. Transform still eases back on mouseleave. */
.card[data-tilt]:hover {
  transition: box-shadow .45s var(--ease), border-color .45s var(--ease);
}

.card-media {
  position: relative; z-index: 1;
  aspect-ratio: 4 / 3;
  background: var(--bg-2);
  display: grid; place-items: center;
  overflow: hidden;
}
.card-media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .7s var(--ease), filter .5s var(--ease);
}
.card:hover .card-media img { transform: scale(1.07); }

.ph { display: grid; place-items: center; gap: 8px; color: var(--ink-3); opacity: .45; }
.ph svg { width: 32px; height: 32px; }
.ph span { font-family: Oswald, sans-serif; font-size: .68rem; letter-spacing: .18em; text-transform: uppercase; }

.badge {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  padding: 5px 10px; border-radius: 7px;
  background: var(--grad); color: #fff;
  font-family: Oswald, sans-serif; font-size: .7rem; font-weight: 500; letter-spacing: .07em;
  box-shadow: 0 8px 20px -8px var(--a1);
}
.badge-off { top: auto; bottom: 12px; }

/* Photo count, so multi-shot listings advertise themselves */
.shot-count {
  position: absolute; right: 12px; bottom: 12px; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 7px;
  background: rgba(6,4,16,.6); color: #fff;
  font-size: .72rem; font-weight: 600;
  backdrop-filter: blur(6px);
}
.shot-count svg { width: 12px; height: 12px; }

.card[data-id] { cursor: pointer; }
.card[data-id]:focus-visible { outline: 2px solid var(--a2); outline-offset: 3px; }
.badge-out { background: var(--ink-3); left: auto; right: 12px; box-shadow: none; }

/* Condition grade. Colour-coded so buyers can scan the grid at a glance —
   and so an honest "Fair" never gets dressed up as something better. */
/* Each grade needs two classes to match, or the neutral `.badge.cond`
   fallback outranks it and every grade renders grey. */
.badge.cond { background: var(--ink-3); box-shadow: none; }
.badge.cond-likenew   { background: #10b981; }
.badge.cond-excellent { background: #0ea5e9; }
.badge.cond-good      { background: #f59e0b; }
.badge.cond-fair      { background: #f97316; }

.card-specs {
  font-size: .82rem; color: var(--ink-2);
  padding: 7px 10px;
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  line-height: 1.45;
}

.warranty {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 11px;
  font-size: .8rem; font-weight: 600;
  color: var(--a2);
}
.warranty svg { width: 14px; height: 14px; flex: none; }

.card-body { position: relative; z-index: 1; padding: 17px; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.card-brand { font-family: Oswald, sans-serif; font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); }
.card-title { font-size: 1.02rem; font-weight: 600; line-height: 1.35; }
.card-desc { font-size: .86rem; color: var(--ink-2); line-height: 1.5; }

.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag {
  padding: 3px 9px; border-radius: 6px;
  background: var(--surface-2); border: 1px solid var(--line-2);
  font-size: .71rem; color: var(--ink-3);
}

.card-foot { margin-top: auto; padding-top: 6px; }
.price { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 13px; }
.price-now { font-family: Oswald, sans-serif; font-size: 1.42rem; font-weight: 600; letter-spacing: .01em; }
.price-mrp { font-size: .85rem; color: var(--ink-3); text-decoration: line-through; }
.price-ask { font-size: .95rem; font-weight: 600; color: var(--ink-2); }
.card .btn { width: 100%; padding-block: 11px; }

/* ======================= 10 CATALOG CONTROLS ============================= */

.catalog-bar { display: flex; flex-direction: column; gap: 15px; margin-bottom: 26px; }

.search-box { position: relative; }
.search-box > svg {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--ink-3); pointer-events: none;
}
.search-box input {
  width: 100%; padding: 14px 16px 14px 44px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: 13px; color: var(--ink); font: inherit; font-size: .95rem;
  backdrop-filter: blur(10px);
  transition: border-color .3s, box-shadow .3s;
}
.search-box input::placeholder { color: var(--ink-3); }
.search-box input:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--a2) 70%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--a1) 16%, transparent);
}

.filters { display: flex; gap: 9px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.filters::-webkit-scrollbar { display: none; }

.chip {
  flex: none; padding: 9px 17px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: 999px;
  font-size: .87rem; font-weight: 500; color: var(--ink-2);
  white-space: nowrap;
  transition: all .3s var(--ease);
}
.chip:hover { color: var(--ink); transform: translateY(-2px); border-color: color-mix(in srgb, var(--a2) 55%, transparent); }
.chip.is-active { background: var(--grad); border-color: transparent; color: #fff; box-shadow: 0 10px 24px -10px var(--a1); }

.result-count { font-size: .88rem; color: var(--ink-3); margin-bottom: 18px; }

.empty { text-align: center; padding: 70px 20px; color: var(--ink-3); }
.empty svg { width: 40px; height: 40px; opacity: .35; margin: 0 auto 16px; }
.empty p { font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.empty small { font-size: .89rem; }

/* =========================== 11 FEATURES ================================= */

.features { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }

.feature {
  position: relative;
  box-shadow: var(--card-inset);
  padding: 30px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .45s var(--ease), border-color .45s var(--ease), box-shadow .45s var(--ease);
}
.feature:hover { transform: translateY(-5px); border-color: color-mix(in srgb, var(--a2) 40%, var(--line)); box-shadow: var(--shadow), var(--card-inset); }
.feature-num {
  font-family: Oswald, sans-serif; font-size: .78rem; letter-spacing: .16em;
  color: var(--ink-3); margin-bottom: 18px;
}
.feature-icon {
  width: 44px; height: 44px; margin-bottom: 16px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: color-mix(in srgb, var(--a1) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--a1) 26%, transparent);
  color: var(--a2);
}
.feature-icon svg { width: 20px; height: 20px; }
.feature h3 { font-size: 1.1rem; font-weight: 650; margin-bottom: 8px; }
.feature p { font-size: .92rem; color: var(--ink-2); }

/* ============================ 12 REVIEWS ================================= */

/* Two rails drifting in opposite directions. The motion is decoration —
   the reviews themselves must stay readable, so the rails pause on hover
   and on keyboard focus, and under reduced motion they stop being a
   marquee altogether and become a plain horizontal scroller. */

.reviews-head {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 14px 26px; margin-bottom: clamp(26px, 4vw, 40px);
}
.reviews-score {
  display: flex; align-items: baseline; gap: 10px;
}
.reviews-avg {
  font-family: Oswald, sans-serif; font-weight: 600;
  font-size: clamp(2.1rem, 5vw, 2.9rem); line-height: 1;
  background: var(--grad); -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.reviews-meta {
  display: flex; flex-direction: column; gap: 3px;
  color: var(--ink-2); font-size: .93rem;
}
/* Pushed to the far end of the row rather than sitting against the score. */
#reviews-link { margin-left: auto; }

.rev-rail {
  position: relative;
  overflow: hidden;
  padding: 10px 0;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.rev-rail + .rev-rail { margin-top: 18px; }

.rev-track {
  display: flex; gap: 18px; width: max-content;
  /* --dur is set in JS from the track's real width, so a rail with four
     reviews and a rail with forty both drift at the same speed. */
  animation: revSlide var(--dur, 60s) linear infinite;
}
.rev-track.is-reverse { animation-direction: reverse; }
.rev-rail:hover .rev-track,
.rev-rail:focus-within .rev-track { animation-play-state: paused; }

/* display:contents so the two sets don't become flex items themselves —
   the cards inside them do. */
.rev-set { display: contents; }

@keyframes revSlide { to { transform: translateX(-50%); } }

.rev-card {
  flex: none;
  width: clamp(268px, 74vw, 352px);
  display: flex; flex-direction: column; gap: 12px;
  padding: 22px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--card-inset);
  transition: border-color .45s var(--ease), box-shadow .45s var(--ease);
}
.rev-card:hover {
  border-color: color-mix(in srgb, var(--a2) 40%, var(--line));
  box-shadow: var(--shadow), var(--card-inset);
}

.rev-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.rev-stars { display: inline-flex; gap: 2px; }
.rev-stars svg { width: 15px; height: 15px; }
.rev-stars .on   { color: #fbbc05; }
.rev-stars .off  { color: var(--ink-3); opacity: .45; }
.rev-g { width: 17px; height: 17px; flex: none; opacity: .9; }

.rev-quote {
  font-size: .93rem; line-height: 1.62; color: var(--ink-2);
}

.rev-who { display: flex; align-items: center; gap: 11px; margin-top: auto; padding-top: 4px; }
.rev-avatar {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--grad);
  color: #fff; font-weight: 650; font-size: .85rem;
}
.rev-name { font-size: .89rem; font-weight: 600; }
.rev-date { font-size: .78rem; color: var(--ink-3); }

/* ============================ 13 CONTACT ================================= */

.contact-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }

.contact-card {
  box-shadow: var(--shadow), var(--card-inset);
  padding: 32px;
  background: var(--card-bg); border: 1px solid var(--line);
  border-radius: var(--radius);
  backdrop-filter: blur(12px);
}
.contact-card h3 {
  font-family: Oswald, sans-serif; font-weight: 500; text-transform: uppercase;
  letter-spacing: .05em; font-size: 1.16rem; margin-bottom: 20px;
}
.contact-row { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 15px; font-size: .93rem; }
.contact-row svg { width: 17px; height: 17px; flex: none; margin-top: 4px; color: var(--a2); }
.contact-row span { color: var(--ink-2); }
.contact-row a { transition: color .25s; }
.contact-row a:hover { color: var(--a2); }
.contact-actions { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 22px; }

/* A visit has to be arranged first. Set as a badge rather than another grey
   contact row, because as fine print at the end of an opening-hours line it
   gets skimmed and someone drives out to a closed shutter. */
.appt-note {
  display: inline-flex; align-items: center; gap: 8px;
  margin: -4px 0 15px;
  padding: 7px 13px;
  border-radius: 999px;
  font-size: .82rem; font-weight: 600; line-height: 1;
  color: var(--a2);
  background: color-mix(in srgb, var(--a1) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--a1) 30%, transparent);
}
.appt-note svg { width: 14px; height: 14px; flex: none; }


/* CTA band */
.cta-band {
  position: relative;
  padding: clamp(44px, 7vw, 76px);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--card-bg);
  overflow: hidden;
  text-align: center;
}
.cta-band::before {
  content: ""; position: absolute; inset: -40%; z-index: 0;
  background: conic-gradient(from 0deg, transparent, var(--glow-1), transparent 40%, var(--glow-2), transparent 70%);
  animation: spin 18s linear infinite;
  opacity: .5;
}
.cta-band > * { position: relative; z-index: 1; }
@keyframes spin { to { transform: rotate(360deg); } }
.cta-band h2 {
  font-family: Oswald, sans-serif; font-weight: 600; text-transform: uppercase;
  font-size: clamp(1.8rem, 5vw, 3.2rem); line-height: 1.02;
}
.cta-band p { color: var(--ink-2); margin: 14px auto 0; max-width: 48ch; }
.cta-band .contact-actions { justify-content: center; }

/* ============================= 14 FOOTER ================================= */

/* Same translucent treatment as the panels. A solid fill here cut a hard
   band across the page wash, which was the one place the gradient stopped. */
.site-footer {
  border-top: 1px solid var(--line-2);
  padding: 40px 0;
  background: var(--card-bg);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
}
.site-footer .wrap { display: flex; flex-direction: column; gap: 18px; align-items: center; text-align: center; }
.footer-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 22px; }
.footer-links a { font-size: .89rem; color: var(--ink-3); transition: color .25s; }
.footer-links a:hover { color: var(--ink); }
.copyright { font-size: .83rem; color: var(--ink-3); }

/* FAB */
.fab {
  position: fixed; right: 20px; bottom: 20px; z-index: 85;
  width: 56px; height: 56px;
  display: grid; place-items: center;
  background: var(--wa); color: #05240f;
  border-radius: 50%;
  box-shadow: 0 10px 30px -8px rgba(37,211,102,.6);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.fab:hover { transform: scale(1.09) rotate(6deg); box-shadow: 0 14px 38px -8px rgba(37,211,102,.8); }
.fab svg { width: 27px; height: 27px; }

/* ===================== 13b DEVICE DETAIL SHEET =========================== */

.sheet { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: 20px; }

.sheet-backdrop {
  position: absolute; inset: 0;
  background: rgba(4,2,12,.62);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  animation: fadeIn .3s var(--ease);
}
@keyframes fadeIn { from { opacity: 0 } }

.sheet-panel {
  position: relative; z-index: 1;
  width: min(940px, 100%); max-height: 88vh;
  display: grid; gap: 0;
  grid-template-columns: 1fr;
  background: var(--card-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg), var(--card-inset);
  backdrop-filter: saturate(150%) blur(20px); -webkit-backdrop-filter: saturate(150%) blur(20px);
  overflow: auto; overscroll-behavior: contain;
  animation: sheetIn .42s var(--ease-out);
}
@keyframes sheetIn { from { opacity: 0; transform: translateY(26px) scale(.985); } }

.sheet-close {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: 11px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  transition: transform .25s var(--ease), border-color .25s;
}
.sheet-close:hover { transform: rotate(90deg); border-color: color-mix(in srgb, var(--a3) 60%, transparent); }
.sheet-close svg { width: 17px; height: 17px; }

.sheet-media { padding: 18px; }
.sheet-stage {
  aspect-ratio: 4 / 3; border-radius: var(--radius-sm); overflow: hidden;
  background: var(--bg-2); display: grid; place-items: center;
}
.sheet-stage img { width: 100%; height: 100%; object-fit: cover; }
.sheet-stage .ph svg { width: 40px; height: 40px; }

.sheet-thumbs { display: flex; gap: 9px; margin-top: 10px; flex-wrap: wrap; }
.sheet-thumb {
  width: 68px; aspect-ratio: 4 / 3; flex: none;
  border-radius: 9px; overflow: hidden; cursor: pointer;
  border: 2px solid transparent; opacity: .6;
  transition: opacity .25s, border-color .25s, transform .25s var(--ease);
  background: var(--bg-2);
}
.sheet-thumb img { width: 100%; height: 100%; object-fit: cover; }
.sheet-thumb:hover { opacity: 1; transform: translateY(-2px); }
.sheet-thumb.is-on { opacity: 1; border-color: var(--a1); }

.sheet-info { padding: 6px 22px 24px; display: flex; flex-direction: column; gap: 11px; }
.sheet-brand {
  font-family: Oswald, sans-serif; font-size: .74rem;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3);
}
.sheet-title {
  font-family: Oswald, sans-serif; font-weight: 600; text-transform: uppercase;
  font-size: clamp(1.4rem, 3vw, 2rem); line-height: 1.05;
}
.sheet-badges { display: flex; flex-wrap: wrap; gap: 8px; }
.sheet-badges .badge { position: static; }
.sheet-specs {
  font-size: .93rem; color: var(--ink-2);
  padding: 11px 13px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--line-2);
}
.sheet-desc { font-size: .95rem; color: var(--ink-2); }
.sheet-foot { margin-top: auto; padding-top: 8px; }
.sheet-foot .price-now { font-size: 1.7rem; }

@media (min-width: 780px) {
  .sheet-panel { grid-template-columns: 1.05fr .95fr; }
  .sheet-media { padding: 20px 10px 20px 20px; }
  .sheet-info { padding: 26px 26px 26px 12px; }
}

body.sheet-open { overflow: hidden; }

/* ======================== 15 MOTION / REVEALS ============================ */

.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .85s var(--ease-out), transform .85s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 75ms);
}
.reveal.in { opacity: 1; transform: none; }

/* ========================== 16 RESPONSIVE ================================ */

@media (min-width: 800px) {
  .nav-links { display: flex; }
  .nav-cta { display: inline-flex; }
}

@media (max-width: 560px) {
  .hero { min-height: auto; padding-top: calc(var(--nav-h) + 54px); }
  .contact-card, .feature { padding: 24px; }
}

/* Theme swap crossfade (View Transitions API) */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .45s;
  animation-timing-function: var(--ease);
  mix-blend-mode: normal;
}

/* ======================= 17 REDUCED MOTION =============================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .line > span { opacity: 1; transform: none; filter: none; }
  .orb, .rings { animation: none; }
  .cursor, .cursor-ring, .cursor-canvas { display: none; }

  /* The rails are decoration; the reviews inside them are content. The
     blanket animation-duration:.01ms above would slam each track to its
     end frame and leave half the reviews parked off-screen, so with motion
     off they stop being marquees and become a plain swipeable scroller. */
  .rev-track { animation: none !important; transform: none !important; }
  .rev-set.rev-dup { display: none; }
  .rev-rail {
    overflow-x: auto; scroll-snap-type: x proximity;
    mask-image: none; -webkit-mask-image: none;
  }
  .rev-card { scroll-snap-align: start; }
}
