@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --font-heading: 'Plus Jakarta Sans', sans-serif;
    --font-body: 'Inter', sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Precision light: motion curves shared by CSS and framer-motion */
    --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-spring: cubic-bezier(0.32, 0.72, 0, 1);

    --background: 0 0% 100%;
    --foreground: 210 20% 12%;
    --card: 0 0% 100%;
    --card-foreground: 210 20% 12%;
    --popover: 0 0% 100%;
    --popover-foreground: 210 20% 12%;
    --primary: 199 89% 48%;
    --primary-foreground: 0 0% 100%;
    --secondary: 210 20% 96%;
    --secondary-foreground: 210 20% 12%;
    --muted: 210 15% 96%;
    --muted-foreground: 210 10% 45%;
    --accent: 199 89% 95%;
    --accent-foreground: 199 89% 30%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 0 0% 98%;
    --border: 210 15% 90%;
    --input: 210 15% 90%;
    --ring: 199 89% 48%;
    --chart-1: 199 89% 48%;
    --chart-2: 173 58% 39%;
    --chart-3: 197 37% 24%;
    --chart-4: 43 74% 66%;
    --chart-5: 27 87% 67%;
    --radius: 0.625rem;
    --sidebar-background: 0 0% 98%;
    --sidebar-foreground: 240 5.3% 26.1%;
    --sidebar-primary: 199 89% 48%;
    --sidebar-primary-foreground: 0 0% 98%;
    --sidebar-accent: 199 89% 95%;
    --sidebar-accent-foreground: 199 89% 30%;
    --sidebar-border: 220 13% 91%;
    --sidebar-ring: 199 89% 48%;
  }

  .dark {
    --background: 210 20% 6%;
    --foreground: 0 0% 95%;
    --card: 210 20% 8%;
    --card-foreground: 0 0% 95%;
    --popover: 210 20% 8%;
    --popover-foreground: 0 0% 95%;
    --primary: 199 89% 48%;
    --primary-foreground: 0 0% 100%;
    --secondary: 210 20% 14%;
    --secondary-foreground: 0 0% 95%;
    --muted: 210 15% 14%;
    --muted-foreground: 210 10% 55%;
    --accent: 199 89% 15%;
    --accent-foreground: 199 89% 70%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 0 0% 98%;
    --border: 210 15% 18%;
    --input: 210 15% 18%;
    --ring: 199 89% 48%;
    --chart-1: 220 70% 50%;
    --chart-2: 160 60% 45%;
    --chart-3: 30 80% 55%;
    --chart-4: 280 65% 60%;
    --chart-5: 340 75% 55%;
    --sidebar-background: 210 20% 6%;
    --sidebar-foreground: 0 0% 95%;
    --sidebar-primary: 199 89% 48%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 199 89% 15%;
    --sidebar-accent-foreground: 199 89% 70%;
    --sidebar-border: 210 15% 18%;
    --sidebar-ring: 199 89% 48%;
  }
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }

  body {
    @apply bg-background text-foreground;
  }

  /* Display headings: tighten tracking as size grows (body text stays at 0) */
  h1, h2 {
    letter-spacing: -0.02em;
  }
}

@layer components {
  /* Translucent header: content scrolls underneath instead of behind a solid bar */
  .site-header-material {
    /* 0.92 rather than 0.82: at lower opacity the dark hero and CTA bands showed through as a muddy grey */
    background-color: rgba(255, 255, 255, 0.92);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
  }

  /* Mobile product action bar, same material as the header */
  .action-bar-material {
    background-color: rgba(255, 255, 255, 0.86);
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    backdrop-filter: saturate(180%) blur(16px);
  }

  /* Browsers without backdrop-filter get a solid surface so text stays legible */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .site-header-material,
    .action-bar-material {
      background-color: #ffffff;
    }
  }
}

/* Press feedback: respond on press, not just on hover (hover does not exist on touch) */
button:not(:disabled),
a.rounded-lg,
a.rounded-xl {
  transition-property: color, background-color, border-color, box-shadow, opacity, transform, scale;
}
/* `scale` (not `transform`) so elements already positioned with a transform keep it.
   Wide rows and inline text buttons opt out with .press-flat: 0.97 of an 800px row is a 25px lurch,
   so they get a background tint on press instead. */
button:not(:disabled):not(.press-flat):active,
a.rounded-lg:not(.press-flat):active,
a.rounded-xl:not(.press-flat):active {
  scale: 0.97;
  transition-duration: 100ms;
}
.press-flat:active {
  opacity: 0.7;
  transition-duration: 60ms;
}

/* FAQ accordion: animate to natural height via grid rows, critically damped feel, no overshoot */
.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 280ms cubic-bezier(0.32, 0.72, 0, 1), opacity 200ms ease-out;
}
.faq-panel[data-open="true"] {
  grid-template-rows: 1fr;
  opacity: 1;
}
.faq-chevron {
  transition: transform 280ms cubic-bezier(0.32, 0.72, 0, 1), color 150ms ease;
}

/* Modal: materialise from slightly smaller with the scrim fading in, rather than appearing from nowhere */
@keyframes modal-scrim-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-surface-in {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
.modal-scrim { animation: modal-scrim-in 200ms ease-out both; }
.modal-surface { animation: modal-surface-in 280ms cubic-bezier(0.32, 0.72, 0, 1) both; }

@media (prefers-reduced-motion: reduce) {
  button:not(:disabled):active,
  a.rounded-lg:active,
  a.rounded-xl:active {
    scale: none;
  }
  .faq-panel,
  .faq-chevron {
    transition: opacity 150ms ease;
  }
  .modal-surface { animation: modal-scrim-in 150ms ease-out both; }
}

@media (prefers-reduced-transparency: reduce) {
  .site-header-material,
  .action-bar-material {
    background-color: #ffffff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

@media (prefers-contrast: more) {
  .site-header-material,
  .action-bar-material {
    background-color: #ffffff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-color: #18212B;
  }
}

/* ────────────────────────────────────────────────────────────────────────────
   Precision light design layer
   Ink bands for hero, proof and footer; paper for the catalogue so specs read
   cleanly. One button colour (brand blue). The UV glow is the only decorative
   colour and sits behind lamp imagery, never behind text.
   ──────────────────────────────────────────────────────────────────────────── */
@layer components {
  /* Small group labels (footer columns, menu groups, product brand). Not used
     as kickers above headings. Set in the heading face: monospace is kept for
     lamp codes, wavelengths, caps and wattages only. */
  .eyebrow {
    @apply font-heading text-xs font-semibold uppercase tracking-[0.08em] text-brand;
  }
  .eyebrow-dark {
    @apply font-heading text-xs font-semibold uppercase tracking-[0.08em] text-brand-cyan;
  }
  .display-1 {
    @apply font-heading font-bold tracking-[-0.03em] leading-[1.04];
  }
  .display-2 {
    @apply font-heading font-bold tracking-[-0.025em] leading-[1.1];
  }
  .lede {
    @apply font-body text-base sm:text-lg leading-relaxed;
  }

  /* Monospaced code chip: lamp codes, wavelengths, caps and wattages */
  .code-chip {
    @apply inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 font-mono text-[11px] font-medium tracking-tight;
    border-color: rgba(0, 119, 182, 0.22);
    background-color: rgba(0, 159, 227, 0.07);
    color: #005A8C;
  }
  .code-chip-dark {
    @apply inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 font-mono text-[11px] font-medium tracking-tight;
    border-color: rgba(255, 255, 255, 0.16);
    background-color: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.86);
  }

  /* Buttons: one primary colour, consistent heights (44px touch targets) */
  .btn {
    @apply inline-flex min-h-[44px] items-center justify-center gap-2 rounded-xl px-5 text-sm font-semibold font-body transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2;
  }
  .btn-primary {
    @apply btn bg-brand text-white hover:bg-brand-hover focus-visible:ring-brand/50;
  }
  .btn-secondary {
    @apply btn border border-line bg-white text-fg hover:border-brand/40 hover:text-brand focus-visible:ring-brand/40;
  }
  .btn-ghost-dark {
    @apply btn border border-white/20 text-white hover:bg-white/10 focus-visible:ring-white/50 focus-visible:ring-offset-ink;
  }

  /* Card surface used across catalogue, medical and product pages */
  .surface {
    @apply rounded-2xl border border-line bg-white;
  }
  .surface-interactive {
    @apply surface transition-[box-shadow,border-color,transform] duration-300 hover:-translate-y-0.5 hover:border-brand/30 hover:shadow-lift focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40;
  }

  /* Ink band: dark surface with a soft cyan wash. The engineering grid is now
     reserved for the home hero (.ink-grid) so it means something there
     instead of sitting behind every dark section. */
  .ink-band {
    background-color: #0B1620;
    background-image: radial-gradient(ellipse 80% 60% at 70% 0%, rgba(0, 159, 227, 0.10), transparent 60%);
  }
  .ink-grid {
    background-image:
      radial-gradient(ellipse 80% 60% at 70% 0%, rgba(0, 159, 227, 0.10), transparent 60%),
      linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
    background-size: auto, 48px 48px, 48px 48px;
    background-position: center, -1px -1px, -1px -1px;
  }
  .paper-grid {
    background-color: #F5F8FB;
    background-image:
      linear-gradient(rgba(11, 22, 32, 0.035) 1px, transparent 1px),
      linear-gradient(90deg, rgba(11, 22, 32, 0.035) 1px, transparent 1px);
    background-size: 32px 32px;
  }

  /* Lamp panel bleed: the hero's dark canvas carries the same colour as the
     section behind it, so its rectangular edge is dissolved by a soft radial
     mask. The engineering grid fades out into the lamp instead of stopping at
     a hard line. */
  .lamp-bleed {
    -webkit-mask-image: radial-gradient(ellipse 94% 92% at 50% 50%, black 52%, transparent 100%);
    mask-image: radial-gradient(ellipse 94% 92% at 50% 50%, black 52%, transparent 100%);
  }

  /* UV glow: sits behind lamp imagery only */
  .uv-glow {
    background:
      radial-gradient(closest-side, rgba(124, 92, 255, 0.45), transparent 70%),
      radial-gradient(closest-side, rgba(0, 159, 227, 0.35), transparent 75%);
    filter: blur(24px);
  }

  /* Skeleton shimmer for route loading */
  .skeleton {
    position: relative;
    overflow: hidden;
    background-color: #EAF0F5;
  }
  .skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent);
    animation: skeleton-sweep 1.4s var(--ease-out-quint) infinite;
  }
}

@keyframes skeleton-sweep { to { transform: translateX(100%); } }

/* Hero lamp: the tube warms up on load, then breathes very slightly */
@keyframes lamp-warm {
  0% { opacity: 0.15; }
  12% { opacity: 0.7; }
  16% { opacity: 0.3; }
  24% { opacity: 0.9; }
  100% { opacity: 1; }
}
@keyframes lamp-breathe {
  /* `scale`, not `transform`, so the element keeps its centring translate */
  0%, 100% { opacity: 0.9; scale: 1; }
  50% { opacity: 1; scale: 1.04; }
}
.lamp-arc { animation: lamp-warm 1.6s ease-out both; }
.lamp-bloom { animation: lamp-warm 1.6s ease-out both, lamp-breathe 6s ease-in-out 1.6s infinite; }

/* Cursor glow: a soft UV light follows the pointer across interactive cards.
   Position comes from --mx/--my set by the Ambient component. */
.surface-interactive,
.glow-track {
  position: relative;
  isolation: isolate;
}
.surface-interactive::after,
.glow-track::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms var(--ease-out-quint);
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(124, 92, 255, 0.10), rgba(0, 159, 227, 0.06) 40%, transparent 70%);
  z-index: -1;
}
.surface-interactive:hover::after,
.glow-track:hover::after { opacity: 1; }

/* Cinematic page hero: slow drifting light, and display sizes for the H1 and
   intro that each page passes in as children */
@keyframes aurora-drift {
  0%, 100% { translate: 0 0; scale: 1; }
  50% { translate: -6% 4%; scale: 1.12; }
}
@keyframes aurora-drift-b {
  0%, 100% { translate: 0 0; scale: 1; }
  50% { translate: 8% -6%; scale: 0.92; }
}
.hero-aurora { animation: aurora-drift 18s ease-in-out infinite; }
.hero-aurora-b { animation: aurora-drift-b 22s ease-in-out infinite; }
.cinematic-copy h1 {
  font-family: var(--font-heading);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.02;
  font-size: clamp(2.4rem, 1.4rem + 4.2vw, 4.75rem);
  text-wrap: balance;
  margin-bottom: 1.25rem;
}
.cinematic-copy h1.h1-long {
  font-size: clamp(2.1rem, 1.3rem + 2.8vw, 3.5rem);
}
.cinematic-copy h1 + p,
.cinematic-copy .lede {
  font-size: clamp(1rem, 0.9rem + 0.4vw, 1.2rem);
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.68);
}

/* Scrollbar-free horizontal rails (chips, brand marks) */
.rail { scrollbar-width: none; }
.rail::-webkit-scrollbar { display: none; }

@media (prefers-reduced-motion: reduce) {
  .skeleton::after,
  .lamp-arc,
  .lamp-bloom,
  .hero-aurora,
  .hero-aurora-b { animation: none; }
  .surface-interactive:hover { transform: none; }
}
/* ────────────────────────────────────────────────────────────────────────────
   Interaction layer: every control answers the pointer.
   --ease-spring-out is a critically damped spring sampled into linear(), so
   CSS transitions settle the way the framer-motion springs do.
   ──────────────────────────────────────────────────────────────────────────── */
:root {
  --ease-spring-out: linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.281 6.7%, 0.723 12.9%, 0.938 16.7%, 1.017 19.4%, 1.067, 1.077 24.1%, 1.069 26.4%, 1.019 32.1%, 0.999 37.4%, 0.994 41.8%, 1.001 53.4%, 1);
  --ease-settle: linear(0, 0.157 4.6%, 0.512 12.4%, 0.781 20.3%, 0.913 27.3%, 0.973 34.1%, 0.996 42.8%, 1);
}

/* Browser surfaces carry the brand too */
::selection { background: rgba(0, 159, 227, 0.22); color: inherit; }
input, textarea { caret-color: #0077B6; }

/* Buttons lift a pixel on hover and settle on a spring */
.btn,
.btn-primary,
.btn-secondary,
.btn-ghost-dark {
  transition-property: color, background-color, border-color, box-shadow, translate, scale;
  transition-duration: 380ms;
  transition-timing-function: var(--ease-settle);
}
@media (hover: hover) {
  .btn-primary:hover { translate: 0 -1px; box-shadow: 0 8px 20px -10px rgba(0, 119, 182, 0.7); }
  .btn-secondary:hover,
  .btn-ghost-dark:hover { translate: 0 -1px; }
}

/* Directional arrows in buttons lean the way they point */
:is(.btn, .btn-primary, .btn-secondary, .btn-ghost-dark) svg:is(.lucide-arrow-right, .lucide-arrow-up-right) {
  transition: translate 420ms var(--ease-spring-out);
}
@media (hover: hover) {
  :is(.btn, .btn-primary, .btn-secondary, .btn-ghost-dark):hover svg.lucide-arrow-right { translate: 3px 0; }
  :is(.btn, .btn-primary, .btn-secondary, .btn-ghost-dark):hover svg.lucide-arrow-up-right { translate: 2px -2px; }
}

/* Fields: the focus ring grows in rather than snapping on */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
  transition: border-color 200ms ease, box-shadow 260ms var(--ease-settle), background-color 200ms ease;
}

/* Interactive cards settle on the spring curve instead of a flat ease */
.surface-interactive {
  transition-timing-function: var(--ease-settle);
  transition-duration: 420ms;
}

/* Side drawers arrive from the edge they live on, and leave the same way */
@keyframes drawer-in { from { translate: 100% 0; } to { translate: 0 0; } }
.drawer-surface { animation: drawer-in 520ms var(--ease-settle) both; }

/* Images develop in once loaded instead of popping */
img[data-develop] { transition: opacity 600ms var(--ease-settle), filter 700ms var(--ease-settle); }
img[data-develop="loading"] { opacity: 0; filter: blur(8px); }

@media (prefers-reduced-motion: reduce) {
  .btn-primary:hover,
  .btn-secondary:hover,
  .btn-ghost-dark:hover { translate: none; }
  :is(.btn, .btn-primary, .btn-secondary, .btn-ghost-dark):hover svg { translate: none; }
  .drawer-surface { animation: modal-scrim-in 150ms ease-out both; }
  img[data-develop="loading"] { filter: none; }
}

/* Manufacturer marquee */
@keyframes marquee-x { from { translate: 0 0; } to { translate: -50% 0; } }
.marquee {
  -webkit-mask-image: linear-gradient(to right, transparent, black 6%, black 94%, transparent);
  mask-image: linear-gradient(to right, transparent, black 6%, black 94%, transparent);
}
.marquee-track { animation: marquee-x 32s linear infinite; }
.marquee-track.marquee-reverse { animation-direction: reverse; }
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee-track { animation: none; width: auto; flex-wrap: wrap; }
  .marquee-track > ul[aria-hidden="true"] { display: none; }
  .marquee-track > ul { flex-wrap: wrap; row-gap: 0.5rem; }
  .marquee-track li[aria-hidden="true"] { display: none; }
}

/* ────────────────────────────────────────────────────────────────────────────
   Hero lamp cluster: the four approved lamp photographs on one soft blue studio
   wash. Each frame is the measured bounding box of the product inside its
   photograph, so the lamp, its pins and its fittings sit exactly where the
   layout puts them and nothing is clipped. Nothing moves: the artwork is in
   place from the first frame and only its light animates, in sequence over 1.2
   seconds, then holds a faint highlight. Phones and reduced-motion users get the
   final still.
   ──────────────────────────────────────────────────────────────────────────── */
.hero-cluster {
  position: relative;
  width: 100%;
  /* Space is reserved before the artwork loads, so the hero never shifts.
     The box ends exactly at the lowest lamp (the xenon), so the caption below it
     sits a measured 20px under the artwork's lowest point at every width. */
  aspect-ratio: 61 / 40;
}
/* One soft blue studio wash behind the whole cluster, so the four lamps read as
   a single lit set rather than four separate pictures */
.hero-cluster__studio {
  position: absolute;
  inset: 8% 0% 0%;
  border-radius: 999px;
  background: radial-gradient(60% 54% at 50% 52%, rgba(0, 159, 227, 0.2), rgba(0, 159, 227, 0.06) 46%, transparent 74%);
  filter: blur(26px);
}
/* The frame screens onto the band, so its black ground disappears completely and
   only the lamp is left. --fx/--fy/--fw/--fh come from the measured crop and
   scale the square photograph up until the frame holds nothing but the product. */
.hero-lamp {
  position: absolute;
  rotate: -12deg;
  mix-blend-mode: screen;
}
.hero-lamp__base {
  position: absolute;
  left: var(--fx);
  top: var(--fy);
  width: var(--fw);
  height: var(--fh);
  max-width: none;
  display: block;
  filter: brightness(0.92) contrast(1.1) saturate(1.02);
  -webkit-user-select: none;
  user-select: none;
}

/* Three tubes tilted up to the right on the same 12 degrees, stacked tight:
   the clear gap between them is a quarter smaller than before, while each start
   and end stays staggered (right ends 78%, 86%, 94%) so the glass, pins and
   fittings still read as separate parts instead of one bar. The compact xenon
   tucks into the cluster: half its lens diameter higher and a full lens
   diameter further left than it sat, so it reads as part of the group while a
   navy strip still separates its crown from the glass above. Its frame sits on
   the bottom edge, so the caption is the only thing beneath the artwork. Every
   offset is a percentage, so the whole arrangement holds its proportions down to
   phone width. */
.hero-lamp--tl { left: 2%; top: 28.5%; width: 76%; --cue: 100ms; }
.hero-lamp--t8 { left: 10%; top: 45.66%; width: 76%; --cue: 420ms; }
.hero-lamp--amalgam { left: 18%; top: 62.82%; width: 76%; --cue: 700ms; }
.hero-lamp--xenon { left: 47.34%; top: 84.06%; width: 36%; rotate: 0deg; --cue: 960ms; }

/* White tube: an even glow held inside the glass. It fades out well before each
   end, so the resting light stays off the end caps and pins, and its edge is
   soft enough that it never reads as a painted stripe over the glass. */
.hero-lamp__even {
  position: absolute;
  left: 0%;
  right: 0%;
  top: var(--glass-top);
  height: var(--glass-h);
  border-radius: 999px;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.08), rgba(226, 246, 255, 0.6) 46%, rgba(255, 255, 255, 0.08));
  filter: blur(3.5px);
  mix-blend-mode: screen;
  opacity: 0.26;
  -webkit-mask-image: linear-gradient(to right, transparent 4%, black 18%, black 82%, transparent 96%);
  mask-image: linear-gradient(to right, transparent 4%, black 18%, black 82%, transparent 96%);
}

/* Clear tubes: the highlight is clipped by a pill exactly as thick as the glass,
   so it never spills onto the band around the tube */
.hero-lamp__glass {
  position: absolute;
  left: 0%;
  right: 0%;
  top: var(--glass-top);
  height: var(--glass-h);
  border-radius: 999px;
  overflow: hidden;
  mix-blend-mode: screen;
  pointer-events: none;
}
.hero-lamp__sweep {
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 38%, rgba(226, 246, 255, 0.9) 50%, rgba(255, 255, 255, 0.85) 55%, transparent 64%);
  background-size: 240% 100%;
  background-position: 130% 0;
  filter: blur(1px);
  opacity: 0.4;
}

/* Xenon lamp: a small glow held at the lens, no wider than the lamp's bulb */
.hero-lamp__lens {
  position: absolute;
  left: 35.6%;
  top: 29.4%;
  width: 11%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, #ffffff 0%, rgba(224, 247, 250, 0.94) 36%, rgba(159, 216, 255, 0.42) 60%, transparent 76%);
  mix-blend-mode: screen;
  opacity: 0.5;
}

/* Each light rises once, then settles to a faint highlight that it holds */
@keyframes hero-lamp-even {
  0% { opacity: 0; }
  55% { opacity: 0.42; }
  100% { opacity: 0.26; }
}
@keyframes hero-lamp-sweep {
  0% { opacity: 0; background-position: 130% 0; }
  40% { opacity: 0.8; }
  100% { opacity: 0.4; background-position: -60% 0; }
}
@keyframes hero-lamp-lens {
  0% { opacity: 0; scale: 0.6; }
  55% { opacity: 0.9; scale: 1.06; }
  100% { opacity: 0.5; scale: 1; }
}

/* Already seen this session: the lamps hold their resting light, no replay */
.hero-cluster.is-settled .hero-lamp__even { opacity: 0.26; }
.hero-cluster.is-settled .hero-lamp__sweep { opacity: 0.4; }
.hero-cluster.is-settled .hero-lamp__lens { opacity: 0.5; }

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  /* Lights stay off until the artwork has painted, so the sequence is never
     spent on an empty box. The lamps themselves are already in place. */
  .hero-cluster:not(.is-playing):not(.is-settled) .hero-lamp__even,
  .hero-cluster:not(.is-playing):not(.is-settled) .hero-lamp__sweep,
  .hero-cluster:not(.is-playing):not(.is-settled) .hero-lamp__lens { opacity: 0; }

  /* Switch on in sequence, the last cue landing at 0.96s so the whole run is
     over inside 1.2 seconds, then hold the faint final highlight */
  .hero-cluster.is-playing .hero-lamp__even {
    animation: hero-lamp-even 420ms cubic-bezier(0.22, 1, 0.36, 1) var(--cue) both;
  }
  .hero-cluster.is-playing .hero-lamp__sweep {
    animation: hero-lamp-sweep 300ms cubic-bezier(0.22, 1, 0.36, 1) var(--cue) both;
  }
  .hero-cluster.is-playing .hero-lamp__lens {
    animation: hero-lamp-lens 260ms cubic-bezier(0.22, 1, 0.36, 1) var(--cue) both;
  }
}