/* =============================================================================================
   Vector Group — placeholder site stylesheet.

   An ORIGINAL design language for the group: deep-space blue, light as the only material, and the
   mark's own 60° geometry everywhere. It deliberately shares nothing with The Mail Hub's tokens,
   fonts or components.

   The page ships a strict Content-Security-Policy (no inline styles), so every animation delay is
   a custom property here and assets/app.js only ever sets custom properties on elements.
   ============================================================================================= */

@font-face {
  font-family: 'Syncopate';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/syncopate-700.woff2') format('woff2');
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/assets/fonts/space-grotesk.woff2') format('woff2');
}

:root {
  color-scheme: dark;

  --void: #02060f;
  --beam: #5ad1ff;
  --ion: #a8ecff;
  --white: #f4fbff;
  --text-dim: rgba(176, 212, 240, 0.62);
  --text-faint: rgba(176, 212, 240, 0.4);

  --font-display: 'Syncopate', 'Arial Black', 'Helvetica Neue', sans-serif;
  --font-ui: 'Space Grotesk', system-ui, sans-serif;

  --mark-size: clamp(190px, 36vmin, 330px);
  --tilt-x: 0deg;
  --tilt-y: 0deg;

  /* The intro choreography, in order of appearance */
  --t-badge: 0.1s;
  --t-rings: 0.3s;
  --t-tri: 0.5s;      /* the triangle grows up from its vertex */
  --t-inner: 0.95s;   /* the inner V */
  --t-outer: 1.4s;    /* the arrows */
  --t-heads: 2.3s;
  --t-word: 2s;
  --t-tag: 2.8s;
  --t-foot: 3.2s;
  --draw: 1s;
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
}

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

html,
body {
  height: 100%;
  margin: 0;
}

body {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--void) radial-gradient(ellipse 70% 60% at 50% 42%, #071b3e 0%, #04102a 40%, var(--void) 78%) fixed;
  color: var(--white);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
  touch-action: pinch-zoom; /* no panning to hand off, so touch drags reach the field */
}

#lattice,
#field {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.stage {
  position: relative;
  display: grid;
  justify-items: center;
  gap: clamp(26px, 5vh, 46px);
  padding: 24px 16px 72px;
  user-select: none;
  -webkit-user-select: none;
}

/* ---- the mark ------------------------------------------------------------------------------- */

.mark-wrap {
  position: relative;
  width: var(--mark-size);
  aspect-ratio: 1;
  transform: perspective(900px) rotateX(var(--tilt-x)) rotateY(var(--tilt-y));
  transition: transform 0.45s ease-out;
}

/* The badge's own light on the field behind it */
.mark-wrap::before {
  content: '';
  position: absolute;
  inset: -40%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(52, 152, 232, 0.38) 0%, rgba(26, 96, 190, 0.16) 36%, rgba(26, 96, 190, 0) 66%);
  filter: blur(14px);
  opacity: 0;
  animation: glow-in 1.4s ease var(--t-badge) forwards, glow-breathe 6.5s ease-in-out 1.6s infinite;
  pointer-events: none;
}

.mark-float {
  position: relative;
  width: 100%;
  height: 100%;
  animation: float 7s ease-in-out infinite;
}

.mark {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* The light layer sits on the badge; its neon comes from GPU drop-shadows, not an SVG filter */
.mark-light {
  position: absolute;
  inset: 0;
  filter: drop-shadow(0 0 3px rgba(168, 236, 255, 0.9)) drop-shadow(0 0 12px rgba(90, 209, 255, 0.55));
}

.badge {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: badge-in 1.1s var(--ease-out) var(--t-badge) forwards;
}

.rim {
  fill: none;
  stroke: rgba(170, 222, 255, 0.4);
  stroke-width: 0.014;
}

.ring {
  fill: none;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
}

.ring-ticks {
  stroke: rgba(130, 200, 255, 0.55);
  stroke-width: 0.012;
  stroke-dasharray: 0.16 0.84; /* of a pathLength of 72: one tick per 5° */
  animation: ring-in 1.6s ease var(--t-rings) forwards, spin 90s linear infinite;
}

.ring-sweep {
  stroke: var(--ion);
  stroke-width: 0.014;
  stroke-linecap: round;
  stroke-dasharray: 0.11 0.89; /* of a pathLength of 1: an 11% arc */
  animation: ring-in 1.6s ease var(--t-rings) forwards, spin-reverse 14s linear infinite;
}

.vectors {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.core-pass {
  stroke: #fff;
  stroke-width: 0.045;
}

.core-pass .head {
  fill: #fff;
}

.glow-pass {
  stroke: var(--beam);
  stroke-width: 0.09;
  opacity: 0.4;
}

.glow-pass .head {
  fill: var(--beam);
}

.v {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draw var(--draw) var(--ease-out) var(--d) forwards;
}

.v-tri { --d: var(--t-tri); }
.v-inner { --d: var(--t-inner); }
.v-outer { --d: var(--t-outer); }

.head {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: head-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.3) var(--t-heads) forwards;
}

/* Nodes ignite the moment their line arrives, then breathe out of phase with each other */
.node {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation:
    ignite 0.7s cubic-bezier(0.2, 0.9, 0.3, 1.4) var(--d) forwards,
    breathe 3.8s ease-in-out calc(var(--d) + 0.7s + var(--phase, 0s)) infinite;
}

.node .halo { fill: rgba(130, 210, 255, 0.35); }
.node .dot { fill: #fff; }

.node-v1 { --d: var(--t-tri); }
.node-a,
.node-b { --d: calc(var(--t-tri) + 0.67s); } /* the sides reach the corners two-thirds of the way through the draw */
.node-v2 { --d: var(--t-inner); }
.node-d,
.node-e { --d: calc(var(--t-inner) + var(--draw)); }
.node-v3 { --d: var(--t-outer); }

.node-a { --phase: 0.4s; }
.node-b { --phase: 1.1s; }
.node-d { --phase: 1.9s; }
.node-e { --phase: 0.7s; }
.node-v2 { --phase: 2.4s; }
.node-v3 { --phase: 1.5s; }

/* ---- the words ------------------------------------------------------------------------------ */

.wordmark {
  margin: 0;
  font: 700 clamp(1.15rem, 3.4vw, 2.2rem) / 1 var(--font-display);
  letter-spacing: 0.34em;
  text-indent: 0.34em; /* balances the trailing letter-space so the word sits centred */
  text-align: center;
  white-space: nowrap;
  color: var(--white);
  text-shadow: 0 0 28px rgba(90, 209, 255, 0.35), 0 0 2px rgba(255, 255, 255, 0.4);
}

.wordmark .word {
  display: inline-block;
  opacity: 0;
  animation: fade-up 1.2s var(--ease-out) var(--t-word) forwards;
}

/* Once app.js has split the words into glyphs, the glyphs carry the reveal instead */
.wordmark.is-split .word {
  opacity: 1;
  animation: none;
}

.wordmark .gap {
  display: inline-block;
  width: 0.75em;
}

.wordmark .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  filter: blur(8px);
  animation: letter 0.9s var(--ease-out) calc(var(--t-word) + var(--i, 0) * 60ms) forwards;
}

.tagline {
  margin: 0;
  font: 400 clamp(0.66rem, 1.05vw, 0.78rem) / 1 var(--font-ui);
  letter-spacing: 0.46em;
  text-indent: 0.46em;
  text-transform: uppercase;
  color: var(--text-dim);
  opacity: 0;
  animation: fade-up 1.3s var(--ease-out) var(--t-tag) forwards;
}

/* ---- the colophon --------------------------------------------------------------------------- */

.colophon {
  position: fixed;
  inset: auto 0 0 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  padding: 0 16px max(20px, env(safe-area-inset-bottom));
  font: 400 0.72rem / 1.4 var(--font-ui);
  letter-spacing: 0.08em;
  color: var(--text-faint);
  opacity: 0;
  animation: fade-up 1.4s var(--ease-out) var(--t-foot) forwards;
}

.colophon .sep::before {
  content: '';
  display: block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
}

/* The copyright notice is the page's one link (the company's LinkedIn page): it reads as colophon
   text until hovered or focused, then brightens and underlines */
.colophon-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
}

.colophon-link:hover,
.colophon-link:focus-visible {
  color: var(--text-dim);
  border-bottom-color: currentColor;
}

.colophon-link:focus-visible {
  outline: 1px solid var(--beam);
  outline-offset: 3px;
}

/* ---- small screens -------------------------------------------------------------------------- */

@media (max-width: 640px) {
  :root { --mark-size: clamp(170px, 58vw, 250px); }

  .wordmark {
    font-size: clamp(1rem, 5.2vw, 1.4rem);
    letter-spacing: 0.26em;
    text-indent: 0.26em;
  }

  .wordmark .gap { width: 0.6em; }

  .tagline {
    letter-spacing: 0.34em;
    text-indent: 0.34em;
  }

  .colophon {
    flex-direction: column;
    gap: 4px;
  }

  .colophon .sep { display: none; }
}

@media (max-height: 520px) {
  :root { --mark-size: clamp(120px, 34vh, 200px); }
  .stage { gap: 16px; }
}

/* ---- motion --------------------------------------------------------------------------------- */

@keyframes draw { to { stroke-dashoffset: 0; } }

@keyframes badge-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes ring-in { to { opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin-reverse { to { transform: rotate(-360deg); } }

@keyframes ignite {
  0% { opacity: 0; transform: scale(0); }
  55% { opacity: 1; transform: scale(1.5); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes breathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.78; transform: scale(1.22); }
}

@keyframes head-in {
  from { opacity: 0; transform: scale(0.3); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

@keyframes glow-in { to { opacity: 1; } }

@keyframes glow-breathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.8; transform: scale(1.08); }
}

@keyframes letter {
  to { opacity: 1; transform: none; filter: blur(0); }
}

@keyframes fade-up {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* Everything jumps to its resting state; app.js draws the field once, as a still. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition: none !important;
  }
}
