/* ============================================================
   Stack — section 06 (StackArc: 3D orbiting ring of tool tiles)
   Ported from refer/index.html ("Design in Motion — StackArc").
   Runs on desktop AND mobile — no flat-grid fallback below a width
   cutoff (the source demo bailed under 560px; the responsive
   containment math in layout() already handles small viewports).
   Reduced motion still gets a flat, static fallback. See EXCEPTIONS.md.

   Dropped from the source demo: the Dribbble CTA button, the
   page-load curtain reveal (built for a page where this WAS the
   hero; here it's section 06, deep in the scroll), and the bespoke
   grey palette (--bg/--text/etc now come from tokens.css, not a
   second palette).
   ============================================================ */

/* 680vh — owner request Aug 2026: the orbit ring (Stack), the
   scatter/gather grid (Stack Β· 02), AND About's own arrival (heading
   settles up, a lede line fades in) all share ONE pinned stage now, not
   several separate adjacent sticky sections. Repeated reports about
   "too much scroll"/"empty scrolling" at section handoffs turned out to
   be inherent to the seam itself — no amount of retiming any one
   section's own fade could remove the fact that one sticky box has to
   fully release before the next takes over. One shared sticky box
   removes the seam entirely: there's exactly one lock, one release.
   Combined run = the orbit's own 140vh + the grid's own 320vh + the
   About lede's own 120vh = 580vh, plus the one shared 100vh viewport
   baseline = 680vh. ORBIT_FRAC/GRID_FRAC/LEDE_FRAC (140/320/120, all
   over 580) in both stack-arc.js and skills-scatter.js slice this one
   shared timeline into each act's own turn — see either file for the
   exact remap. Once the lede finishes, the pin releases into #about's
   own normal-flow body, picking the narrative up right where the lede
   left off. */
.stackAll{ position:relative; height:680vh; background:var(--bg); --cols:5; }
@media (max-width:899.98px){ .stackAll{ --cols:4; } }
.stackAll__stick{ position:sticky; top:0; height:100vh; overflow:hidden; }

/* Header nav targets — see index.html comment for why none of these
   land at a literal phase-start. 60vh into the shared stage lands
   within the orbit's own ~140vh slice at target~0.42 (comfortably past
   the ~0.26 fly-in span). 270vh lands within the grid's own slice, at
   local rawGather~0.58 (cards well into gathering, not just-arrived).
   560vh lands near the end of the lede phase (140 orbit + 320 grid +
   120 lede = 460-580vh), 20vh short of the pin's own release at 580vh
   — heading already eased up, lede line already faded in. */
.arc__navmark{ position:absolute; top:60vh; left:0; width:1px; height:1px; pointer-events:none; }
#sc-nav{ top:270vh; }
#about-nav{ top:560vh; }

.arc__layer{ position:absolute; inset:0; z-index:3; }
.arc__guide{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; z-index:0; }
.arc__guide path{ fill:none; stroke:var(--thread); stroke-width:1; opacity:.5; }

.arc__stage{ position:absolute; inset:0; z-index:1; perspective:2200px; perspective-origin:50% 50%; }
.arc__scene{ position:absolute; inset:0; transform-style:preserve-3d; }

/* Heading is a 3D citizen of the scene, so tiles sort around it */
.arc__head{
  position:absolute; inset:0; transform-style:preserve-3d;
  display:flex; flex-direction:column; justify-content:center;
  padding-inline:var(--pad-inline); pointer-events:none; text-align:center;
}
.arc__line{
  font-family:var(--font-display); font-weight:400;
  font-size:var(--fs-d1); line-height:.85; margin:0;
  white-space:nowrap; color:var(--text); will-change:transform;
  text-transform:uppercase;
}
.arc__line--b{ align-self:flex-end; }
.arc__line--a{ align-self:flex-start; }
.arc__sub{
  margin:2.2vh auto; max-width:38ch; text-align:center;
  font-size:12.5px; letter-spacing:.05em; line-height:1.45;
  text-transform:uppercase; color:var(--text-muted);
}

.arc__ring{ position:absolute; inset:0; transform-style:preserve-3d; }

.tile{
  position:absolute; left:50%; top:50%;
  width:calc(300px*var(--ts,1)); height:calc(192px*var(--ts,1));
  margin:calc(-96px*var(--ts,1)) 0 0 calc(-150px*var(--ts,1));
  background:var(--surface);
  border-radius:var(--r-md); overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  backface-visibility:hidden; will-change:transform,opacity;
  /* --shadow (tokens.css), not a flat rgba: same theme-aware fix as
     the Work cards — a black shadow is invisible against dark theme's
     near-black field. */
  box-shadow:0 18px 40px -22px var(--shadow);
}

/* Owner request: real tool logos, not procedurally-drawn name tiles.
   Markup is inlined per tile (stack-arc.js), not loaded via <img src>
   or mask-image url() — an external mask-image read a local SVG file's
   alpha data the same way <canvas> drawImage does, which Chromium
   treats as a tainted/CORS-gated read under file://, silently
   rendering nothing (confirmed: tiles showed their background/border/
   shadow but no icon). An inlined <svg> has no resource fetch to taint,
   so it renders identically whether the page is opened as a bare file
   or served over http. `fill` cascades from here onto every path
   (none of the source files hardcode their own), same as any other
   coloured element on the page — no special-casing needed for the
   theme-toggle's difference-blend hover to invert it correctly. */
.tile__icon{
  display:flex; align-items:center; justify-content:center;
  width:44%; height:44%; fill:var(--text);
}
.tile__icon svg{ width:100%; height:100%; display:block; }

/* No depth to read under reduced motion — the merged .stackAll falls
   back to plain stacked document flow: ring content first, then (via
   skills-scatter.css's own reduced rules for .sc__panA/.skill/.sc__panB)
   the grid content right after it, both as normal static blocks inside
   one no-longer-sticky container. */
@media (prefers-reduced-motion:reduce){
  .stackAll{ height:auto; }
  .stackAll__stick{ position:static; height:auto; overflow:visible; }
  .arc__layer{ position:static; padding-block:var(--sp-7); }
  .arc__guide{ display:none; }
  .arc__stage{ position:static; perspective:none; }
  .arc__scene{ position:static; transform-style:flat; }
  .arc__head{ position:static; padding:0; display:block; margin-bottom:var(--sp-7); }
  .arc__ring{ position:static; display:flex; flex-wrap:wrap; gap:var(--sp-4); }
  .tile{ position:static; margin:0; opacity:1; transform:none; width:auto; min-width:160px; height:92px; flex:1 1 160px; }
}
:focus-visible{ outline:2px solid var(--text); outline-offset:3px; }
