/* ============================================================
   AI Hero — image + chip cluster + capture bar.

   Layout:
     - Hero shell with full-bleed cluster centerpiece
     - Cluster = 3-col grid (left chips · image · right chips)
       + a chipped bar spanning image width below
     - Chips sit OUTSIDE the image in the side columns. Each chip
       connects to a specific in-frame element via dashed lines
       drawn in three SVG layers (left col + image + right col)

   Brand rules:
     - Angular: no rounded corners
     - Chipped corners use clip-path on wrapper + inset content
     - No translateY hover
     - Cyan = data layer (lines, reticles, chip borders, eyebrows)
     - Purple = chrome (image wrapper border, bottom bar)
   ============================================================ */

/* ============================================================
   Hero shell
   ============================================================ */

.ai-hero-v2 {
  position: relative;
  padding: calc(var(--space-3xl) + 2.5rem) 0 var(--space-2xl);
  isolation: isolate;
}
.ai-hero-v2__bg {
  position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(ellipse 60% 50% at 25% 30%, rgba(123,112,251,0.18) 0%, transparent 60%),
    radial-gradient(ellipse 50% 40% at 80% 70%, rgba(84,255,224,0.10) 0%, transparent 55%),
    var(--black);
  mask-image: linear-gradient(to bottom, black 0, black 80%, transparent 100%);
}
.ai-hero-v2__bg::after {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(123,112,251,0.06) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(123,112,251,0.06) 1px, transparent 1px);
  background-size: 60px 60px;
  mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, black 0%, transparent 75%);
}

.ai-hero-v2__head {
  max-width: 880px;
  /* Tightened bottom gap so the CTAs sit closer to the graphic
     than the default --space-xl (4rem) — visual reads as one unit. */
  margin: 0 auto var(--space-lg);
  text-align: center;
}
.ai-hero-v2__head .label {
  display: inline-block;
  color: var(--purple-tint);
  letter-spacing: 0.18em;
  font-weight: 700;
  font-size: 0.75rem;
  margin-bottom: 0.85rem;
}
.ai-hero-v2__head h1 {
  font-family: var(--font-heading);
  font-weight: 900; font-stretch: 125%;
  font-size: clamp(2.75rem, 5.2vw, 4.75rem);
  line-height: 0.95;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  margin: 0 0 1.25rem;
}
.ai-hero-v2__head h1 span { color: var(--cyan); }
.ai-hero-v2__head p {
  font-size: 1.0625rem;
  line-height: 1.55;
  color: rgba(245, 244, 244, 0.72);
  max-width: 640px;
  margin: 0 auto 1.75rem;
}
.ai-hero-v2__head .ctas {
  display: inline-flex; gap: var(--space-sm);
}

/* Disclaimer under the cluster — tongue-in-cheek note that the
   stylised hero is illustrative, not a literal data preview. */
.ai-hero-v2__disclaimer {
  width: min(1560px, calc(100vw - 4rem), calc(100vh + 360px));
  margin: 1.25rem auto 0;
  text-align: center;
  font-family: 'JetBrains Mono', var(--font-body);
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: rgba(245, 244, 244, 0.4);
}

/* ============================================================
   Visual cluster — left chips · image · right chips · bar
   ============================================================ */

@property --mask-r {
  syntax: '<length>';
  inherits: true;
  initial-value: 0px;
}
@property --scan-y {
  syntax: '<percentage>';
  inherits: true;
  initial-value: -10%;
}

.cluster {
  position: relative;
  /* Width caps:
       1560px       — design cap on 4K+
       100vw - 4rem — gutter on narrow viewports
       100vh + 360px — viewport-height cap so the cluster relaxes
                       on 1080p (lands at ~1440px wide) without
                       collapsing the chip vertical spacing. The
                       closest chip pair is 15.09% of image-height
                       apart, so image-height must stay above ~470
                       to keep chips from stacking on top of each
                       other; this floor enforces that. */
  width: min(1560px, calc(100vw - 4rem), calc(100vh + 360px));
  margin: 0 auto;
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr) 260px;
  grid-template-rows: auto auto;
  column-gap: 32px;
  row-gap: 0;
}

.cluster__chips {
  position: relative;
  align-self: stretch;
  height: 100%;
}
.cluster__chips--left  { grid-column: 1; grid-row: 1; }
.cluster__chips--right { grid-column: 3; grid-row: 1; }

.cluster__chips .chip {
  position: absolute;
  left: 0; right: 0;
  transform: translateY(-50%);
}

/* Image cell. Wrapper provides the purple stroke via its
   background; the image is inset 1.5px and clipped to the same
   chip shape minus the 1.5px ring. Chip is TL-only — the bar
   below carries the BR chip, image+bar form one Z-diagonal. */
.cluster__image {
  grid-column: 2; grid-row: 1;
  position: relative;
  aspect-ratio: 1586 / 992;
  align-self: start;
  background: rgba(123, 112, 251, 0.7);
  /* Suppress mobile long-press save-image popover + text-select
     handles. Hover/lens is the only intended interaction; the
     image-save menu would only let users grab an asset they
     can't usefully consume. JS pairs this with a contextmenu
     handler for desktop right-click. */
  -webkit-touch-callout: none;
          user-select: none;
  -webkit-user-select: none;
  clip-path: polygon(
    34px 0, 100% 0,
    100% 100%,
    0 100%, 0 34px
  );
  --mx: 50%;
  --my: 50%;
  --mask-r: 0px;
  --mask-feather: 26px;
  cursor: crosshair;
  transition: --mask-r 0.22s cubic-bezier(.4,.1,.3,1);
}

/* Hover state is tracked separately from scan state (data-hover
   on the parent vs data-state) so the lens can layer additively
   on top of an in-flight scan rather than interrupting it. */
.cluster__image[data-hover="true"] {
  --mask-r: 110px;
}

.cluster__image img,
.cluster__image canvas.ai-effect {
  position: absolute; inset: 1.5px;
  width: calc(100% - 3px); height: calc(100% - 3px);
  display: block;
  clip-path: polygon(
    32.5px 0, 100% 0,
    100% 100%,
    0 100%, 0 32.5px
  );
}
.cluster__image img         { object-fit: cover; }
.cluster__image canvas.ai-effect {
  background: var(--black);
  pointer-events: none;
}

/* Active layer in each mode — never masked. */
.cluster__image[data-mode="normal"] img,
.cluster__image[data-mode="ai"]     canvas.ai-effect {
  -webkit-mask-image: none;
          mask-image: none;
}

/* Reveal layer — masked to a circle around the cursor. */
.cluster__image[data-mode="normal"] canvas.ai-effect,
.cluster__image[data-mode="ai"]     img {
  -webkit-mask-image: radial-gradient(
    circle at var(--mx) var(--my),
    #000 0,
    #000 var(--mask-r),
    transparent calc(var(--mask-r) + var(--mask-feather))
  );
          mask-image: radial-gradient(
    circle at var(--mx) var(--my),
    #000 0,
    #000 var(--mask-r),
    transparent calc(var(--mask-r) + var(--mask-feather))
  );
}

/* Scanning — animate --scan-y on the parent so mask + scan-line
   share one clock. Two distinct keyframe names so the value
   resets cleanly between phases. */
.cluster__image[data-state="scanning-in"] {
  animation: scanYIn 4s cubic-bezier(.4,.05,.3,1) forwards;
}
.cluster__image[data-state="scanning-out"] {
  animation: scanYOut 4s cubic-bezier(.4,.05,.3,1) forwards;
}
@keyframes scanYIn  { 0% { --scan-y: -8%; } 100% { --scan-y: 108%; } }
@keyframes scanYOut { 0% { --scan-y: -8%; } 100% { --scan-y: 108%; } }

/* Scan masks list the radial hover mask first + the linear scan
   mask second; multiple mask-image values composite additively
   by default, so the hover lens reveals through the scan without
   interrupting it. --mask-r is 0 unless data-hover is set, so the
   radial contributes nothing when the cursor isn't over the image. */
.cluster__image[data-state="scanning-in"][data-mode="normal"] canvas.ai-effect,
.cluster__image[data-state="scanning-in"][data-mode="ai"]     img {
  -webkit-mask-image:
    radial-gradient(
      circle at var(--mx) var(--my),
      #000 0,
      #000 var(--mask-r),
      transparent calc(var(--mask-r) + var(--mask-feather))
    ),
    linear-gradient(
      to bottom,
      #000 0%, #000 var(--scan-y),
      transparent calc(var(--scan-y) + 6%)
    );
          mask-image:
    radial-gradient(
      circle at var(--mx) var(--my),
      #000 0,
      #000 var(--mask-r),
      transparent calc(var(--mask-r) + var(--mask-feather))
    ),
    linear-gradient(
      to bottom,
      #000 0%, #000 var(--scan-y),
      transparent calc(var(--scan-y) + 6%)
    );
}
.cluster__image[data-state="scanning-out"][data-mode="normal"] canvas.ai-effect,
.cluster__image[data-state="scanning-out"][data-mode="ai"]     img {
  -webkit-mask-image:
    radial-gradient(
      circle at var(--mx) var(--my),
      #000 0,
      #000 var(--mask-r),
      transparent calc(var(--mask-r) + var(--mask-feather))
    ),
    linear-gradient(
      to bottom,
      transparent 0%, transparent var(--scan-y),
      #000 calc(var(--scan-y) + 6%)
    );
          mask-image:
    radial-gradient(
      circle at var(--mx) var(--my),
      #000 0,
      #000 var(--mask-r),
      transparent calc(var(--mask-r) + var(--mask-feather))
    ),
    linear-gradient(
      to bottom,
      transparent 0%, transparent var(--scan-y),
      #000 calc(var(--scan-y) + 6%)
    );
}

/* Hover ring — cyan annulus + glow tracing the lens edge. */
.cluster__image .hover-ring {
  position: absolute;
  inset: 1.5px;
  pointer-events: none;
  z-index: 4;
  clip-path: polygon(
    32.5px 0, 100% 0,
    100% 100%,
    0 100%, 0 32.5px
  );
  background: radial-gradient(
    circle at var(--mx) var(--my),
    transparent 0,
    transparent calc(var(--mask-r) - 0.5px),
    rgba(84, 255, 224, 0.95) var(--mask-r),
    rgba(84, 255, 224, 0.4)  calc(var(--mask-r) + 1.5px),
    transparent calc(var(--mask-r) + 4px)
  );
  opacity: 0;
  transition: opacity 0.18s ease;
  filter: drop-shadow(0 0 8px rgba(84, 255, 224, 0.55));
}
.cluster__image[data-hover="true"] .hover-ring { opacity: 1; }

/* Horizontal scan line. Range matches mask --scan-y exactly. */
.cluster__image .scan-line {
  position: absolute;
  left: 1.5px; right: 1.5px;
  top: 0;
  height: 2px;
  pointer-events: none;
  z-index: 5;
  background: linear-gradient(
    to right,
    transparent,
    rgba(84, 255, 224, 0.95) 25%,
    rgba(84, 255, 224, 0.95) 75%,
    transparent
  );
  box-shadow: 0 0 14px rgba(84, 255, 224, 0.7),
              0 0 28px rgba(84, 255, 224, 0.4);
  opacity: 0;
}
.cluster__image[data-state="scanning-in"] .scan-line {
  animation: scanLineA 4s cubic-bezier(.4,.05,.3,1) forwards;
}
.cluster__image[data-state="scanning-out"] .scan-line {
  animation: scanLineB 4s cubic-bezier(.4,.05,.3,1) forwards;
}
@keyframes scanLineA {
  0%   { top: -8%; opacity: 0; }
  6%   { opacity: 1; }
  94%  { opacity: 1; }
  100% { top: 108%; opacity: 0; }
}
@keyframes scanLineB {
  0%   { top: -8%; opacity: 0; }
  6%   { opacity: 1; }
  94%  { opacity: 1; }
  100% { top: 108%; opacity: 0; }
}

/* Column connector layers — JS sets size + viewBox at runtime. */
.connectors {
  position: absolute;
  pointer-events: none;
  z-index: 4;
  overflow: visible;
}
.connectors--left  { left: 0;  }
.connectors--right { right: 0; }

/* In-image connector layer — viewBox locked to source-image. */
.cluster__image .image-lines {
  position: absolute;
  inset: 1.5px;
  width: calc(100% - 3px); height: calc(100% - 3px);
  pointer-events: none;
  z-index: 3;
  overflow: visible;
  clip-path: polygon(
    32.5px 0, 100% 0,
    100% 100%,
    0 100%, 0 32.5px
  );
}

/* ============================================================
   Chip
   ============================================================ */

.cluster .chip {
  /* position is set by .cluster__chips .chip (absolute) above; no
     override here so source-order doesn't clobber it back to relative.
     Padding/min-height kept tight so chips don't collide vertically
     when the cluster shrinks on 1080p screens. */
  isolation: isolate;
  padding: 8px 13px 9px;
  min-height: 0;
  display: flex; flex-direction: column; justify-content: center;
  background: transparent;
}
.cluster .chip::before,
.cluster .chip::after {
  content: '';
  position: absolute;
  clip-path: polygon(
    7px 0, 100% 0,
    100% calc(100% - 7px), calc(100% - 7px) 100%,
    0 100%, 0 7px
  );
}
.cluster .chip::before {
  inset: 0; z-index: -2;
  background: rgba(84, 255, 224, 0.55);
}
.cluster .chip::after {
  inset: 1.5px; z-index: -1;
  background: rgba(14, 11, 22, 0.94);
}

.chip__eyebrow {
  font-family: var(--font-heading);
  font-weight: 900; font-stretch: 125%;
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cyan);
  opacity: 0.92;
  margin-bottom: 4px;
}
.chip__value {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.75rem;
  line-height: 1.35;
  letter-spacing: 0.015em;
  color: var(--white);
  opacity: 0.9;
}
.chip__sub {
  font-family: 'JetBrains Mono', var(--font-body);
  font-weight: 400;
  font-size: 0.65rem;
  letter-spacing: 0.02em;
  color: rgba(245, 244, 244, 0.55);
  margin-top: 3px;
}

/* ============================================================
   Bottom bar — capture metadata. Bottom-right Z-diagonal chip cut.
   ============================================================ */

.cluster__bar {
  grid-column: 2; grid-row: 2;
  position: relative;
  isolation: isolate;
  display: flex; align-items: stretch;
  height: 50px;
}
.cluster__bar::before,
.cluster__bar::after {
  content: '';
  position: absolute;
  clip-path: polygon(
    0 0, 100% 0,
    100% calc(100% - 14px), calc(100% - 14px) 100%,
    0 100%
  );
}
.cluster__bar::before {
  inset: 0; z-index: -2;
  background: rgba(123, 112, 251, 0.55);
}
.cluster__bar::after {
  inset: 0 1.5px 1.5px 1.5px; z-index: -1;
  background: rgba(14, 11, 22, 0.95);
}

.capture-info {
  flex: 1;
  display: flex; align-items: center;
  gap: 14px;
  padding: 0 22px;
  font-family: 'JetBrains Mono', var(--font-body);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: rgba(245, 244, 244, 0.72);
  white-space: nowrap;
  overflow: hidden;
}
.capture-info__live {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--cyan);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.capture-info__live::before {
  content: ''; width: 6px; height: 6px;
  background: var(--cyan);
  animation: livePulse 1.4s ease-in-out infinite;
}
.capture-info__sep {
  color: rgba(123, 112, 251, 0.55);
}
.capture-info__field {
  overflow: hidden; text-overflow: ellipsis;
}
.capture-info__label {
  color: rgba(245, 244, 244, 0.4);
  margin-right: 5px;
}
@keyframes livePulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

/* ============================================================
   Connector lines + reticles + anchors
   ============================================================ */

.conn,
.mask-arrows path {
  fill: none;
  stroke: rgba(84, 255, 224, 0.75);
  stroke-width: 2.4;
  stroke-dasharray: 7 5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 4px rgba(84, 255, 224, 0.32));
  animation: connDash 2s linear infinite;
}
.conn-flow {
  animation: connDash 2s linear infinite;
}
/* Positive offset → dashes flow tip → chip (outward from image). */
@keyframes connDash {
  to { stroke-dashoffset: 36; }
}

/* Anchor on the chip side — small open circle hugging the chip. */
.conn-anchor {
  fill: var(--black);
  stroke: rgba(84, 255, 224, 1);
  stroke-width: 1.6;
  vector-effect: non-scaling-stroke;
  r: 3;
}

/* Target reticle — currentColor inside #reticle propagates here. */
.conn-reticle {
  color: rgba(84, 255, 224, 1);
  filter: drop-shadow(0 0 4px rgba(84, 255, 224, 0.55));
  animation: reticlePulse 2.2s ease-in-out infinite;
}
@keyframes reticlePulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* ============================================================
   Glitch-in cascade — only on first scan
   ============================================================ */

@keyframes glitchAppear {
  0%   { opacity: 0; }
  10%  { opacity: 0.55; }
  20%  { opacity: 0.05; }
  35%  { opacity: 0.8;  }
  50%  { opacity: 0.25; }
  70%  { opacity: 1;    }
  82%  { opacity: 0.7;  }
  100% { opacity: 1;    }
}

.cluster.is-scanning .chip,
.cluster.is-scanning .conn,
.cluster.is-scanning .mask-arrows path,
.cluster.is-scanning .conn-reticle,
.cluster.is-scanning .conn-anchor {
  animation-name: glitchAppear, connDash;
  animation-duration: 0.7s, 2s;
  animation-delay: var(--appear-delay, 0s), 0s;
  animation-fill-mode: both, none;
  animation-iteration-count: 1, infinite;
  animation-timing-function: ease-out, linear;
}

/* Pre-scan: hide everything until the first scan starts. */
.cluster.pre-scan .chip,
.cluster.pre-scan .conn,
.cluster.pre-scan .mask-arrows path,
.cluster.pre-scan .conn-reticle,
.cluster.pre-scan .conn-anchor {
  opacity: 0;
}

/* ============================================================
   Responsive
   ============================================================ */

/* Tablet + below: collapse the 3-col cluster into a single column.
   Mobile order — image, bar, then ALL chips stacked below as a
   vertical readout. The connectors + in-image reticles hide since
   the chips are no longer at the image edges. */
@media (max-width: 980px) {
  .cluster {
    width: min(1560px, calc(100vw - 2rem));
    grid-template-columns: 1fr;
    /* Custom row-gap per pair — image + bar stay attached (zero
       gap) so the desktop image-TL + bar-BR Z-diagonal still
       reads. Spacing only opens up before the chip stacks. */
    grid-template-rows: auto auto 14px auto auto;
    column-gap: 0;
    row-gap: 0;
  }
  .cluster__chips {
    align-self: auto;
    height: auto;
    width: 100%;
  }
  .cluster__image        { grid-column: 1; grid-row: 1; }
  .cluster__bar          { grid-column: 1; grid-row: 2; }
  /* Row 3 is a 14px spacer — keeps the image+bar pair visually
     joined while separating them from the chip readout below. */
  .cluster__chips--left  { grid-column: 1; grid-row: 4; }
  .cluster__chips--right { grid-column: 1; grid-row: 5; }

  /* Flex column instead of the desktop's relative+absolute setup —
     chips fall into normal flow and size to their own content. */
  .cluster__chips--left,
  .cluster__chips--right {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  /* Drop chips out of absolute positioning. position:relative (not
     static) so the chip's ::before / ::after border + fill pseudos
     keep their positioning context — under static they fall through
     to .cluster and inset:0 stretches them across the whole cluster.
     !important wins against the inline style="top: calc(..)" that
     drives chip Y on desktop. */
  .cluster__chips .chip {
    position: relative !important;
    top: auto !important;
    left: auto;
    right: auto;
    transform: none !important;
    width: 100%;
    min-height: 0;
  }

  /* Match the 10px flex-gap between chips inside each group so all
     seven chips read as one continuous vertical list with even
     spacing (grid row-gap is 0 — see grid-template-rows above). */
  .cluster__chips--right { margin-top: 10px; }

  /* Hide the chip→image side bridges (they need chips at the
     image edges to land cleanly). Keep the in-image lines +
     reticles — they read as part of the render itself. */
  .connectors {
    display: none;
  }
}

/* Phone: single-column chip stack, tighter image chip-corner,
   compact bottom bar (some fields hide so the line doesn't
   overflow). */
@media (max-width: 640px) {
  .ai-hero-v2 {
    padding: calc(var(--space-2xl) + 1rem) 0 var(--space-xl);
  }
  .ai-hero-v2__head {
    margin-bottom: var(--space-md);
  }
  .ai-hero-v2__head .ctas {
    display: flex;
    flex-direction: column;
    width: 100%;
    gap: 0.75rem;
  }
  .ai-hero-v2__head .ctas .btn {
    width: 100%;
    justify-content: center;
  }

  .cluster {
    width: calc(100vw - 2rem);
    /* Spacer row stays small on phone too. */
    grid-template-rows: auto auto 10px auto auto;
  }

  /* Tighter chip spacing on phone — flex column inherited from
     the tablet rule, just slimmer gap. */
  .cluster__chips--left,
  .cluster__chips--right {
    gap: 8px;
  }
  .cluster__chips--right { margin-top: 8px; }

  /* Compact bar — drop the rate + build fields, smaller padding,
     allow wrapping if the remaining content still needs it. */
  .cluster__bar { height: auto; min-height: 44px; }
  .capture-info {
    padding: 0 14px;
    font-size: 0.65rem;
    gap: 10px;
    white-space: normal;
    flex-wrap: wrap;
  }
  .capture-info__field--hide-mobile { display: none; }
}
