/* ═══════════════════════════════════════════════════════════════
   folded-space.css — interactive 4D-folded centerpiece
   ═══════════════════════════════════════════════════════════════ */

@layer pages {

  /* ─── folded space module ─── */
  .folded-space {
    position: relative;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: var(--s-4) 0 var(--s-5);
  }

  /* ─── hero placement: when used as the hero logo, constrain size ─── */
  .hero-portal-wrap {
    position: relative;
    width: min(420px, 70vw);
    margin: 0 auto;
  }
  .hero-portal-wrap .fs-controls-grid {
    gap: 14px 22px;
  }

  /* ─── stage wrapper allows exterior linework to overflow ─── */
  .fs-stage-wrap {
    position: relative;
    overflow: visible;
    isolation: isolate;
  }

  /* ─── spinning portal halo behind the canvas ─── */
  /* Two conic-gradient discs counter-rotating behind the stage. They sit
     at z-index: -1 inside the wrapper's stacking context so the opaque
     stage hides the centre — only a soft accent-tinted halo bleeds out
     past the stage edges. Heavily blurred to read as light, not pattern. */
  /* Glow halos are now STATIC (no rotation animation). Rotating an
     element with `filter: blur(...)` forces the compositor to re-blur
     a large area every single frame — the worst-case CSS perf cost on
     the home page after the shader. The visual is essentially the
     same: a soft accent halo bleeding past the stage edge. */
  .fs-portal-glow {
    position: absolute;
    inset: -60px;
    z-index: -1;
    pointer-events: none;
    border-radius: 50%;
    background: conic-gradient(from 0deg,
      transparent 0deg,
      transparent 20deg,
      var(--accent) 60deg,
      var(--accent-glow) 90deg,
      transparent 150deg,
      transparent 210deg,
      var(--accent-glow) 270deg,
      var(--accent) 300deg,
      transparent 340deg,
      transparent 360deg);
    filter: blur(14px);
    opacity: 0.55;
  }
  .fs-portal-glow-2 {
    inset: -40px;
    background: conic-gradient(from 180deg,
      transparent 0deg,
      transparent 30deg,
      var(--accent-glow) 80deg,
      transparent 140deg,
      var(--accent) 220deg,
      transparent 300deg,
      transparent 360deg);
    filter: blur(10px);
    opacity: 0.45;
    /* Slight static offset so the two halos don't perfectly overlap */
    transform: rotate(45deg);
  }

  /* ─── exterior floating jagged linework ─── */
  .fs-exterior {
    position: absolute;
    inset: -22px;
    width: calc(100% + 44px);
    height: calc(100% + 44px);
    pointer-events: none;
    z-index: 4;
    overflow: visible;
    /* fs-jag-drift animation removed — translating a large SVG with
       multiple polylines forced the entire group to re-composite
       every frame. Static linework still adds the same character. */
  }
  .fs-jag {
    fill: none;
    stroke: var(--accent);
    stroke-width: 0.4;
    vector-effect: non-scaling-stroke;
    opacity: 0.8;
    /* drop-shadow removed — the parent .fs-exterior has a constant
       fs-jag-drift animation, which forces the compositor to
       re-rasterize the filter every frame for every child path. The
       glow effect read negligibly here anyway. */
    stroke-linejoin: miter;
    stroke-linecap: square;
  }
  .fs-jag-thin {
    stroke-width: 0.25;
    opacity: 0.55;
  }
  .fs-jag-glyph line {
    stroke: var(--accent);
    stroke-width: 0.3;
    vector-effect: non-scaling-stroke;
    opacity: 0.7;
  }
  @keyframes fs-jag-drift {
    0%, 100% { transform: translate(0, 0); }
    50%      { transform: translate(2px, -2px); }
  }

  .fs-stage {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    height: auto;
    min-height: 360px;
    border: none;
    overflow: hidden;
    background: #04050a;
    box-shadow:
      inset 0 0 0 0.5px rgba(255,255,255,0.04),
      0 30px 80px -40px rgba(0,0,0,0.8),
      0 0 60px -20px var(--accent-glow);
  }

  /* ─── organic tech-portal frame ─── */
  .fs-canvas { z-index: 0; }

  .fs-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 2;
    overflow: visible;
  }
  .fs-frame-edge,
  .fs-frame-edge-inner {
    fill: none;
    stroke: var(--accent);
    vector-effect: non-scaling-stroke;
  }
  .fs-frame-edge {
    stroke-width: 1;
    opacity: 0.55;
    /* drop-shadow removed; the inner dashed-march animation otherwise
       forced re-raster of the filtered output every frame. */
  }
  .fs-frame-edge-inner {
    stroke-width: 0.5;
    stroke-dasharray: 1.2 4;
    opacity: 0.35;
    animation: fs-edge-march 24s linear infinite;
  }
  @keyframes fs-edge-march {
    to { stroke-dashoffset: -100; }
  }

  /* corner brackets */
  .fs-bracket {
    position: absolute;
    width: 36px;
    height: 36px;
    pointer-events: none;
    z-index: 3;
    overflow: visible;
  }
  .fs-bracket path,
  .fs-bracket-tick {
    fill: none;
    stroke: var(--accent);
    stroke-width: 1.2;
    /* drop-shadow removed (was 4 separate filtered SVGs at the corners). */
  }
  .fs-bracket-dot {
    fill: var(--accent);
    /* drop-shadow removed — combined with the constant pulse animation
       this was forcing per-frame re-raster on each corner. */
    animation: fs-dot-pulse 3s ease-in-out infinite;
  }
  .fs-bracket-tl { top: -2px; left: -2px; }
  .fs-bracket-tr { top: -2px; right: -2px; }
  .fs-bracket-bl { bottom: -2px; left: -2px; }
  .fs-bracket-br { bottom: -2px; right: -2px; }

  @keyframes fs-dot-pulse {
    0%, 100% { opacity: 0.5; transform: scale(0.85); transform-origin: center; }
    50%      { opacity: 1; transform: scale(1.1); }
  }

  /* organic vines — subtle animated paths down the sides */
  .fs-vines {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 2;
    overflow: visible;
  }
  .fs-vine {
    fill: none;
    stroke: var(--accent);
    stroke-width: 0.6;
    stroke-dasharray: 6 10;
    opacity: 0.3;
    /* drop-shadow removed — combined with fs-vine-flow animation it
       forced per-frame re-raster. Strokes themselves are visible. */
    animation: fs-vine-flow 9s linear infinite;
  }
  .fs-vine-2 { animation-direction: reverse; animation-duration: 13s; }
  @keyframes fs-vine-flow {
    to { stroke-dashoffset: -64; }
  }

  .fs-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    cursor: grab;
    touch-action: none;
  }

  /* ─── alien tendril bridge between portal & control surface ─── */
  .fs-tendrils {
    display: block;
    width: 100%;
    height: 56px;
    margin: -1px 0;
    overflow: visible;
    pointer-events: none;
  }
  .fs-tendril {
    fill: none;
    stroke: var(--accent);
    vector-effect: non-scaling-stroke;
    /* drop-shadow removed — children below also strip it. */
    stroke-linecap: round;
  }
  .fs-tendril-main {
    stroke-width: 1.4;
    opacity: 0.7;
  }
  .fs-tendril-thin {
    stroke-width: 0.9;
    opacity: 0.5;
  }
  .fs-tendril-hair {
    stroke-width: 0.5;
    opacity: 0.35;
    stroke-dasharray: 3 4;
    animation: fs-vine-flow 6s linear infinite;
  }
  .fs-tendril-nodes circle {
    fill: var(--accent);
  }
  .fs-tendril-vesicles circle {
    fill: var(--accent);
    opacity: 0.65;
    /* drop-shadow removed — combined with fs-dot-pulse this caused
       per-frame re-raster on every vesicle circle. */
    animation: fs-dot-pulse 3.5s ease-in-out infinite;
  }
  .fs-tendril-vesicles circle:nth-child(2) { animation-delay: 0.6s; }
  .fs-tendril-vesicles circle:nth-child(3) { animation-delay: 1.2s; }
  .fs-tendril-vesicles circle:nth-child(4) { animation-delay: 1.8s; }

  /* ─── control surface ─── */
  .fs-controls {
    padding: var(--s-4) var(--s-5);
    border: 0.5px solid var(--line-edge);
    background: var(--bg-pane-strong);
    position: relative;
  }

  .fs-controls::before,
  .fs-controls::after {
    content: "";
    position: absolute;
    width: 14px;
    height: 14px;
    border: 0.5px solid var(--accent);
    opacity: 0.5;
  }
  .fs-controls::before { top: -1px; left: -1px;  border-right: none; border-bottom: none; }
  .fs-controls::after  { bottom: -1px; right: -1px; border-left: none;  border-top: none; }

  .fs-controls-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--s-4);
    padding-bottom: var(--s-3);
    border-bottom: 0.5px dashed var(--line-hairline);
  }
  .fs-controls-eyebrow {
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--accent);
  }
  .fs-controls-stamp {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .fs-controls-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--s-4) var(--s-5);
  }
  @media (max-width: 640px) {
    .fs-controls-grid { grid-template-columns: 1fr; }
  }

  /* ─── notch slider (rectangular, NOT generic round) ─── */
  .fs-slider {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .fs-slider-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-family: var(--font-mono);
  }
  .fs-slider-label {
    font-size: 10.5px;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-secondary);
  }
  .fs-slider-val {
    font-size: 11px;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
    letter-spacing: var(--tracking-mono);
  }

  .fs-slider-track {
    position: relative;
    height: 22px;
    cursor: ew-resize;
    user-select: none;
    background: linear-gradient(180deg, rgba(0,0,0,0.4), rgba(0,0,0,0.15));
    border: 0.5px solid var(--line-edge);
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.5);
  }
  .fs-slider-track.dragging,
  .fs-slider-track:hover {
    border-color: var(--accent);
  }

  .fs-slider-fill {
    position: absolute;
    top: 0; left: 0;
    height: 100%;
    background: linear-gradient(90deg,
      var(--accent-soft, var(--accent-glow)),
      var(--accent) 120%);
    box-shadow: inset 0 0 12px var(--accent-glow);
    clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 0 100%);
    pointer-events: none;
  }

  .fs-slider-ticks {
    position: absolute;
    inset: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 4px;
    pointer-events: none;
  }
  .fs-tick {
    width: 1px;
    height: 6px;
    background: var(--line-bright, var(--line-edge));
    opacity: 0.35;
  }
  .fs-tick.major {
    height: 10px;
    opacity: 0.6;
  }

  .fs-slider-cursor {
    position: absolute;
    top: 0;
    bottom: 0;
    transform: translateX(-50%);
    pointer-events: none;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .fs-slider-cursor-bar {
    width: 2px;
    height: 100%;
    background: var(--accent);
    box-shadow:
      0 0 6px var(--accent-glow),
      0 0 12px var(--accent-glow);
  }
  .fs-slider-cursor-readout {
    position: absolute;
    top: -16px;
    font-family: var(--font-mono);
    font-size: 9px;
    color: var(--accent);
    letter-spacing: 0;
    background: rgba(0,0,0,0.6);
    padding: 1px 4px;
    border: 0.5px solid var(--accent);
  }

  /* below-stage compact summary on mobile */
  @media (max-width: 720px) {
    .fs-stage { aspect-ratio: 4 / 5; min-height: 480px; }
  }
}
