/* ═══════════════════════════════════════════
   FREE FORGE LABS — Link Sphere v3.0
   A rotating 3D cloud of links orbiting a
   pinned brand core. Chaos, but with a center.
   ═══════════════════════════════════════════ */

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

:root {
  --bg: #060608;
  --font-display: 'Orbitron', 'Courier New', monospace;
  --font-mono: 'Share Tech Mono', 'Courier New', monospace;
  --accent: #06D6A0;
}

html, body {
  height: 100%;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 50%, #0d0d1e 0%, var(--bg) 70%);
  color: #e0e0ff;
  font-family: var(--font-mono);
}

/* ─── AMBIENT BACKGROUND ─── */
/* three.js starfield canvas — pinned behind everything (see index.html) */
.bg-stars {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;        /* clicks pass through to the sphere stage */
  z-index: 0;
}

/* ─── LAUNCHER STAGE (shared shell; a launcher builds its DOM inside) ─── */
.launcher-stage {
  position: fixed;
  inset: 0;
  z-index: 1;                   /* above the background canvas, below nothing */
}

/* ─── SPHERE LAUNCHER ─── */
.sphere-stage {
  cursor: grab;
  touch-action: none;          /* let us own touch-drag, not the browser */
}
.sphere-stage.grabbing { cursor: grabbing; }

.sphere {
  position: absolute;
  inset: 0;
  pointer-events: none;        /* only the nodes themselves are interactive */
}

/* ─── BRAND CORE (pinned center) ─── */
.core {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  pointer-events: none;
  z-index: 50;                 /* sits at the visual middle of the cloud */
}

.core-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.4em;
  color: rgba(6, 214, 160, 0.6);
  margin-bottom: 0.9rem;
}

.core-eyebrow .cursor {
  display: inline-block;
  width: 0;
  border-right: 7px solid var(--accent);
  height: 0.7em;
  vertical-align: middle;
  animation: blink-cursor 1s step-end infinite;
}

.core-name {
  font-family: var(--font-display);
  font-size: clamp(0.5rem, 1.3vw, 0.85rem);
  letter-spacing: 0.6em;
  color: rgba(255, 255, 255, 0.4);
  text-transform: uppercase;
  text-shadow: 0 0 18px rgba(131,56,236,0.5);
}

@keyframes blink-cursor {
  0%, 100% { border-color: var(--accent); }
  50%       { border-color: transparent; }
}

/* ─── NODES ─── */
/* Position/scale/opacity/z-index are all driven per-frame by JS;
   CSS just handles look, hover, and the icon/label stack. */
.node {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  text-decoration: none;
  user-select: none;
  will-change: transform, opacity;
}

.node-ig {
  line-height: 0;
  filter: drop-shadow(0 0 4px rgba(0,0,0,0.8));
}
/* SVG icons size off the node, inherit color via currentColor */
.node-ig svg {
  width: 3.4rem;
  height: 3.4rem;
  display: block;
}

/* Active link nodes — bright, labeled, glowing in brand color */
.node-active {
  cursor: pointer;
  color: #fff;
}
.node-active .node-ig svg {
  stroke: var(--c);                       /* icon itself wears the brand color */
}
.node-active .node-ig {
  filter: drop-shadow(0 0 8px var(--c)) drop-shadow(0 0 16px var(--c)) brightness(1.15);
  transition: transform 0.15s ease, filter 0.15s ease;
}
.node-il {
  font-family: var(--font-mono);
  font-size: 0.46rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.85);
  text-shadow: 0 0 6px var(--c);
  white-space: nowrap;
}
.node-active:hover .node-ig {
  transform: scale(1.35);
  filter: drop-shadow(0 0 20px var(--c)) brightness(1.3);
}
.node-active:hover .node-il { color: #fff; }

/* Soon nodes — dim, no label. Pure atmosphere. */
.node-soon {
  color: rgba(255,255,255,0.32);
}
.node-soon .node-ig svg {
  width: 2.6rem;            /* smaller than active nodes so they recede */
  height: 2.6rem;
}

/* ─── GRID LAUNCHER (magnetic "pop toward you" dock) ─── */
/* The stage gets perspective so each node's translateZ reads as real
   depth — icons physically pop off the screen toward the viewer. */
.grid-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1100px;
}

/* The plane holds the hex lattice (nodes absolutely positioned by JS)
   and tilts toward the cursor (JS sets its rotateX/Y). preserve-3d lets
   the children's translateZ stack into real depth. Size is set by JS. */
.grid-plane {
  position: relative;
  transform-style: preserve-3d;
  will-change: transform;
}

/* Each node is absolutely placed on its lattice point (left/top + size
   set by JS); transform centers it and drives the magnet pop. */
.grid-node {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transform: translate(-50%, -50%);
  text-decoration: none;
  user-select: none;
  transform-style: preserve-3d;
  will-change: transform;
}
.grid-node .g-ig { line-height: 0; filter: drop-shadow(0 0 4px rgba(0,0,0,0.8)); }
.grid-node svg {
  width: clamp(1.7rem, 4.4vw, 2.5rem);
  height: clamp(1.7rem, 4.4vw, 2.5rem);
  display: block;
}

/* Active link nodes — bright, brand-colored, glow grows with --pop
   (the proximity value JS writes each frame). */
.grid-node.active { color: #fff; cursor: pointer; }
.grid-node.active svg { stroke: var(--c); }
.grid-node.active .g-ig {
  filter: drop-shadow(0 0 calc(5px + var(--pop, 0) * 18px) var(--c))
          brightness(calc(1 + var(--pop, 0) * 0.35));
}

/* Label sits absolutely under the icon (so it never reflows the grid)
   and fades in as the node pops toward you. */
.g-il {
  position: absolute;
  bottom: -0.7rem;
  font-family: var(--font-mono);
  font-size: 0.44rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 0 6px var(--c);
  white-space: nowrap;
  /* Only the focused icon(s) show a label — ramp from pop 0.45→0.85 — so
     the magnet can light up a wide area without flooding the screen with
     text. Keeps clutter down without spacing icons out or shrinking them. */
  opacity: clamp(0, calc((var(--pop, 0) - 0.45) * 2.5), 1);
  pointer-events: none;
}

/* Filler glyphs — dim atmosphere at the grid's edges. */
.grid-node.soon { color: rgba(255,255,255,0.2); }
.grid-node.soon svg { width: clamp(1.4rem, 3.6vw, 2rem); height: clamp(1.4rem, 3.6vw, 2rem); }

/* Grid wordmark — pinned top-center (the grid fills the middle). */
.grid-brand {
  position: fixed;
  top: 1.4rem;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-display);
  font-size: clamp(0.5rem, 1.3vw, 0.8rem);
  letter-spacing: 0.6em;
  color: rgba(255, 255, 255, 0.4);
  text-transform: uppercase;
  text-shadow: 0 0 18px rgba(131,56,236,0.5);
  z-index: 60;
  pointer-events: none;
}

/* ─── MOBILE ─── */
@media (max-width: 768px) {
  .node-ig svg      { width: 2.7rem; height: 2.7rem; }
  .node-soon .node-ig svg { width: 2rem; height: 2rem; }
  .node-il { font-size: 0.4rem; }
}
