/* EuphoricQuartz — the homepage's 3D layer (design/3d, local experiment).
   Loaded after styles.css, on the two homepages only; the Enterprise pages do
   not load it. Pairs with crystal.js (the WebGL scene, which adds .eq-3d to
   <html>) and motion.js (which adds .eq-motion and .eq-cursor-on).

   Everything here is additive: with JavaScript off, or WebGL unavailable,
   none of the .eq-* classes exist and the page is the one styles.css draws.
   Colour only from the tokens; the gradient only where design_system_quartzo
   allows it (lights, rules, one phrase per title). */

/* --- The scene ---------------------------------------------------------------
   A direct child of <body>, fixed, behind every section (they are z-index 1
   and transparent). The footer has its own background and covers it. On touch
   the canvas is sized to the large viewport, so the collapsing URL bar does
   not resize it mid-scroll. */

.scene-3d {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100vh;
  height: 100lvh;
  pointer-events: none;
}

/* The scene replaces the 2D wave and draws its own light. */
.eq-3d .bg-field,
.eq-3d .hero-figure::before {
  display: none;
}

/* --- Hero ------------------------------------------------------------------ */

@media (min-width: 821px) {
  .hero .hero-grid {
    min-height: calc(100svh - 79px);   /* the header's height, as scroll-padding-top */
    padding-block: 40px 112px;
  }
}

/* Corner brackets and a live readout around the crystal: an instrument, not
   a picture. Only once the scene is running — the numbers come from it. */
.hud {
  display: none;
}

.eq-3d .hud {
  display: block;
  position: absolute;
  inset: 0;
  pointer-events: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--t-4);
  --c: var(--line-2);
  --l: 14px;
  background:
    linear-gradient(var(--c), var(--c)) left top / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) left top / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right top / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) right top / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom / 1px var(--l) no-repeat;
}

.hud > span {
  position: absolute;
  white-space: nowrap;
}

.hud b {
  font-weight: 400;
  color: var(--t-2);
  font-variant-numeric: tabular-nums;
}

.hud-tl { left: 22px; top: 12px; }
.hud-tr { right: 22px; top: 12px; }
.hud-br { right: 22px; bottom: 0; }

/* Narrow: the caption needs the whole bottom edge. */
@media (max-width: 560px) {
  .hud-br { display: none; }
}

/* The caption sits inside the bottom-left bracket. */
.eq-3d .fig-caption {
  left: 22px;
}

/* "Scroll": a hairline that draws itself downwards, desktop only. */
.hero-scroll {
  display: none;
}

@media (min-width: 821px) {
  .hero-scroll {
    position: absolute;
    left: 50%;
    bottom: 28px;
    translate: -50% 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 10px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--t-4);
  }

  .hero-scroll:hover {
    color: var(--fg-strong);
  }

  .hero-scroll::after {
    content: "";
    width: 1px;
    height: 44px;
    background: linear-gradient(var(--q-2), transparent);
    transform-origin: top;
    animation: eq-scroll-line 2.2s cubic-bezier(0.6, 0, 0.2, 1) infinite;
  }
}

@keyframes eq-scroll-line {
  0%    { transform: scaleY(0); transform-origin: top; }
  50%   { transform: scaleY(1); transform-origin: top; }
  50.1% { transform: scaleY(1); transform-origin: bottom; }
  100%  { transform: scaleY(0); transform-origin: bottom; }
}

/* --- Team: the numbers ----------------------------------------------------- */

.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 34px 0 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.stats > div {
  display: flex;
  flex-direction: column-reverse;   /* number above, label below; dt first in the markup */
  justify-content: flex-end;
  gap: 10px;
  padding: 22px 16px 22px 0;
}

.stats > div + div {
  padding-left: 18px;
  border-left: 1px solid var(--line);
}

.stats dd {
  margin: 0;
  font-size: clamp(34px, 4vw, 46px);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--fg-strong);
  font-variant-numeric: tabular-nums;
}

.stats dt {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--t-4);
}

@media (max-width: 560px) {
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .stats > div:nth-child(3) {
    padding-left: 0;
    border-left: none;
  }

  .stats > div:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
}

/* The boxes take a dark glass over the scene, on desktop only — a blur over
   a canvas that redraws every frame is not something to ask of a phone. */
@media (pointer: fine) {
  .eq-3d .team-grid,
  .eq-3d .contact-form {
    background: color-mix(in srgb, var(--bg) 62%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
  }
}

/* --- Scroll progress ------------------------------------------------------- */

.eq-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--quartzo);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* --- Titles rise word by word (motion.js) ---------------------------------- */

.eq-motion .eq-split .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.eq-motion .eq-split .wi {
  display: inline-block;
  transform: translate3d(0, 110%, 0);
  transition: transform 1s cubic-bezier(0.2, 0.8, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 55ms);
}

.eq-motion .eq-split.is-in .wi {
  transform: none;
}

/* These titles now enter through their words; the block-level rise from
   styles.css would double it. */
.eq-motion .hero-copy > .hero-title,
.eq-motion .what-intro > .section-title,
.eq-motion .contact-copy > .contact-title {
  animation: none;
}

.lw {
  transition: opacity 0.25s linear;
}

/* --- Cards: tilt and a light under the pointer ----------------------------- */

.eq-tilt,
.eq-glow {
  position: relative;
  isolation: isolate;
}

.eq-tilt {
  transform: perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.eq-tilt::before,
.eq-glow::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(140px circle at var(--mx, 50%) var(--my, 50%), var(--q-glow), transparent 70%),
    radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), var(--q-glow), transparent 70%);
  opacity: 0;
  transition: opacity 0.4s;
}

.eq-tilt:hover::before,
.eq-glow:hover::before {
  opacity: 1;
}

/* A row's top hairline draws itself in the gradient on hover — one of the
   page's dividing rules, which is where the gradient is allowed. */
.eq-tilt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -1px;
  height: 1px;
  background: var(--quartzo);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
  pointer-events: none;
}

.eq-tilt:hover::after {
  transform: scaleX(1);
}

.eq-tilt .cap-num {
  transition: color 0.3s;
}

.eq-tilt:hover .cap-num {
  color: var(--fg-strong);
}

.eq-magnetic {
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), background-color 0s, border-color 0s;
}

/* --- HUD cursor (motion.js, fine pointers only) ---------------------------- */

html.eq-cursor-on,
html.eq-cursor-on * {
  cursor: none !important;
}

html.eq-cursor-on input,
html.eq-cursor-on textarea,
html.eq-cursor-on select {
  cursor: text !important;
}

.eq-cursor,
.eq-reticle {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s;
}

.eq-cursor-in .eq-cursor,
.eq-cursor-in .eq-reticle {
  opacity: 1;
}

.eq-cursor-field .eq-cursor,
.eq-cursor-field .eq-reticle {
  opacity: 0;
}

.eq-cursor {
  mix-blend-mode: difference;
}

.eq-cursor::before {
  content: "";
  position: absolute;
  left: -3px;
  top: -3px;
  width: 6px;
  height: 6px;
  background: var(--fg-strong);
}

.eq-reticle::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 34px;
  height: 34px;
  translate: -50% -50%;
  --c: var(--t-3);
  --l: 8px;
  background:
    linear-gradient(var(--c), var(--c)) left top / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) left top / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right top / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) right top / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom / var(--l) 1px no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom / 1px var(--l) no-repeat;
  transition: width 0.35s cubic-bezier(0.2, 0.8, 0.2, 1), height 0.35s cubic-bezier(0.2, 0.8, 0.2, 1), rotate 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Over a link: a diamond — a quartz facet. */
.eq-cursor-link .eq-reticle::before {
  width: 44px;
  height: 44px;
  rotate: 45deg;
  --c: var(--q-2);
}

/* Over the crystal: wide open, in the gradient's light end. */
.eq-crystal-hover .eq-reticle::before {
  width: 96px;
  height: 96px;
  rotate: 0deg;
  --l: 14px;
  --c: var(--q-3);
}

.eq-cursor-down .eq-reticle::before {
  width: 22px;
  height: 22px;
}

/* --- Film grain over everything, desktop only ------------------------------ */

@media (pointer: fine) {
  .eq-3d body::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 50;
    pointer-events: none;
    opacity: 0.05;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }
}

/* --- Reduced motion -----------------------------------------------------------
   motion.js does not run its animations at all, and crystal.js draws a still
   frame; this only stops the CSS loops. */

@media (prefers-reduced-motion: reduce) {
  .hero-scroll::after {
    animation: none;
  }

  .eq-tilt,
  .eq-magnetic {
    transition: none;
  }
}
