/* ==========================================================================
   textures.css — Decorative texture + interaction primitives
   --------------------------------------------------------------------------
   Scientific / playful surface treatments and shared hover behaviors.
   All decorative layers use `pointer-events: none`. All animated rules wrap
   their motion in `prefers-reduced-motion: reduce` no-ops further down.
   ========================================================================== */

/* ── Constellation dots (subtle radial pattern) ── */
.tx-constellation {
  background-image: radial-gradient(
    circle,
    var(--color-primary-alpha-20) 1px,
    transparent 1.6px
  );
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(
    ellipse at center,
    #000 55%,
    transparent 100%
  );
          mask-image: radial-gradient(
    ellipse at center,
    #000 55%,
    transparent 100%
  );
  pointer-events: none;
}

/* ── Diagonal grid ── */
.tx-diag-grid {
  background-image: repeating-linear-gradient(
    135deg,
    var(--color-secondary-alpha-06) 0 1px,
    transparent 1px 18px
  );
  pointer-events: none;
}

/* ── Waveform / signal lines (faint static oscilloscope motif, GCO-97) ──
   A tiling SVG of stacked sine traces in the brand colors. Masked top/bottom
   so it concentrates behind section content. Static (no animation). */
.tx-waveform {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='120' viewBox='0 0 240 120'><g fill='none' stroke-width='1.1'><path d='M0 30 Q60 12 120 30 T240 30' stroke='%233E93EB' stroke-opacity='0.13'/><path d='M0 60 Q60 42 120 60 T240 60' stroke='%2348D0D4' stroke-opacity='0.13'/><path d='M0 90 Q60 72 120 90 T240 90' stroke='%233E93EB' stroke-opacity='0.11'/></g></svg>");
  background-size: 240px 120px;
  background-repeat: repeat;
  -webkit-mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 22%,
    #000 78%,
    transparent 100%
  );
          mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 22%,
    #000 78%,
    transparent 100%
  );
  pointer-events: none;
}

/* ── Isoline divider (stacked sine waves SVG data-uri) ── */
.tx-isoline-divider {
  display: block;
  width: 100%;
  height: 80px;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 80' preserveAspectRatio='none'><g fill='none' stroke='%233E93EB' stroke-opacity='0.18' stroke-width='1.2'><path d='M0 20 Q150 4 300 20 T600 20 T900 20 T1200 20'/><path d='M0 40 Q150 22 300 40 T600 40 T900 40 T1200 40' stroke='%2348D0D4' stroke-opacity='0.18'/><path d='M0 60 Q150 44 300 60 T600 60 T900 60 T1200 60'/></g></svg>");
  pointer-events: none;
}

/* ── Section texture layer (Phase 8) ──
   Hosts a `.tx-*` paint utility as a full-bleed layer behind section
   content, without touching the existing markup. The host section must be
   `position: relative`; its content wrapper must be positioned (relative)
   so it stacks above this z-index:0 layer. Decorative + inert. */
.section-tx {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* ── Film grain (tiny SVG noise, multiplies under content) ── */
.tx-grain {
  position: relative;
  isolation: isolate;
}

.tx-grain::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.025;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.6 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  z-index: 0;
}

/* ── Fireflies (ambient drifting dots) ──
   Markup:
     <div class="tx-fireflies" aria-hidden="true">
       <span class="tx-fireflies__dot"></span> ... (~14)
     </div>
   Each dot reads its `--firefly-i` from inline style (0..N) so the cascade
   below distributes start positions and animation delays without bespoke
   per-child rules. */
.tx-fireflies {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.tx-fireflies__dot {
  --firefly-i: 0;
  --firefly-count: 14;
  position: absolute;
  top: calc((var(--firefly-i) * 53%) - (100% * (var(--firefly-i) / var(--firefly-count))));
  left: calc((var(--firefly-i) * 37%) - (100% * (var(--firefly-i) / var(--firefly-count))));
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    var(--color-secondary) 0%,
    var(--color-secondary-alpha-40) 60%,
    transparent 100%
  );
  opacity: 0;
  animation: firefly-drift 9s ease-in-out infinite;
  animation-delay: calc(var(--firefly-i) * -0.7s);
  filter: blur(0.5px);
}

.tx-fireflies__dot:nth-child(even) {
  background: radial-gradient(
    circle,
    var(--color-primary) 0%,
    var(--color-primary-alpha-40) 60%,
    transparent 100%
  );
  animation-duration: 11s;
}

@keyframes firefly-drift {
  0%, 100% {
    transform: translate(0, 0);
    opacity: 0;
  }
  10% {
    opacity: 0.6;
  }
  50% {
    transform: translate(28px, -22px);
    opacity: 0.45;
  }
  90% {
    opacity: 0.55;
  }
}

/* ── Hover background-fade primitive ── */
.fx-hover-bg-fade {
  position: relative;
  isolation: isolate;
  transition: color var(--transition-base);
}

.fx-hover-bg-fade::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-primary-alpha-06);
  opacity: 0;
  transition: opacity var(--transition-base);
  pointer-events: none;
  z-index: -1;
}

.fx-hover-bg-fade:hover::before,
.fx-hover-bg-fade:focus-visible::before {
  opacity: 1;
}

/* ── Glow shadow on hover (footer social icons, etc.) ── */
.fx-glow-hover {
  transition: box-shadow var(--transition-base),
              color var(--transition-base),
              transform var(--transition-base);
}

.fx-glow-hover:hover,
.fx-glow-hover:focus-visible {
  box-shadow: 0 0 0 1px var(--color-primary-alpha-30),
              0 0 16px var(--color-primary-alpha-40);
  color: var(--color-primary);
}

/* ── Animated rotating gradient border ──
   Uses @property --grad-rotation so the angle is animatable. Browsers
   without @property degrade to the static conic gradient at angle 0 —
   visually identical to a thin colored ring, no JS fallback needed. */
@property --grad-rotation {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.fx-grad-border {
  --grad-rotation: 0deg;
  --grad-thickness: 2px;
  position: relative;
  isolation: isolate;
}

.fx-grad-border::before {
  content: "";
  position: absolute;
  inset: calc(var(--grad-thickness) * -1);
  border-radius: inherit;
  padding: var(--grad-thickness);
  background: conic-gradient(
    from var(--grad-rotation),
    var(--color-primary),
    var(--color-secondary),
    var(--color-accent),
    var(--color-primary)
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
          mask-composite: exclude;
  animation: grad-spin 8s linear infinite;
  pointer-events: none;
  z-index: -1;
}

@keyframes grad-spin {
  to {
    --grad-rotation: 360deg;
  }
}

/* ── Reduced motion: freeze every animated primitive in this file ── */
@media (prefers-reduced-motion: reduce) {
  .tx-fireflies__dot,
  .fx-grad-border::before {
    animation: none;
  }

  .tx-fireflies__dot {
    opacity: 0.4;
  }
}
