/* Tile-sphere hero, shared by the home page and the network page (ported from prototypes/tile-sphere).
   The SVG mark (#gpl-mark with the tile sweep) renders first; assets/js/sphere/story.js adds .is-gl once the WebGL
   sphere is drawing, and the mark fades out as tiles stream out of the green full stop. .ts--flat (reduced motion,
   no WebGL2, Save-Data or a lost context) keeps the SVG mark. .ts--hero: the canvas covers only the hero and
   scrolls away with it; otherwise (network page) one fixed canvas runs the whole story. */

.ts { position: relative; }

/* ---------- Canvas ---------- */
.ts__canvas {
  position: fixed;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  visibility: hidden;
}
.ts--hero .ts__canvas { position: absolute; }
.ts.is-gl .ts__canvas.is-on { visibility: visible; }
.ts--flat .ts__canvas { display: none; }

/* ---------- Hero ---------- */
.ts-hero { border-bottom: 0; }
.ts-hero__in { row-gap: 0; }
.ts-hero__in > :not(.ts-hero__orb) { position: relative; z-index: 2; }
.ts-hero__title { grid-column: 1 / 8; grid-row: 2; margin-top: clamp(32px, 6.5vh, 80px); font-weight: inherit; }
.ts-hero__kicker {
  display: block;
  max-width: 17em;
  font-size: clamp(22px, 2.25vw, 34px);
  font-weight: 700;
  font-stretch: 88%;
  line-height: 1.06;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.ts-hero__word {
  display: block;
  margin-top: clamp(18px, 3vh, 32px);
  margin-inline-start: -0.04em;
  font-size: clamp(72px, 12.2vw, 192px);
  font-weight: 800;
  font-stretch: 75%;
  line-height: 0.84;
  letter-spacing: -0.05em;
}
.ts-hero__line { display: block; white-space: nowrap; }
.ts-hero__dot { display: inline-block; color: var(--green); transform-origin: 50% 80%; }
.ts-hero__orb {
  position: relative;
  z-index: 2;
  grid-column: 8 / 13;
  grid-row: 2 / 5;
  align-self: center;
  justify-self: end;
  width: min(100%, 72vh);
  aspect-ratio: 1;
  margin-top: 24px;
}
.ts-hero__mark { width: 100%; height: 100%; transition: opacity 0.45s var(--ease-out); }
.ts.is-gl .ts-hero__mark { opacity: 0; }
.ts-hero__cap {
  position: absolute;
  inset: auto 0 -36px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 12px;
  color: var(--ink-2);
  font-size: 11px;
}
.ts.is-gl .ts-hero__cap [data-ts-count] { font-variant-numeric: tabular-nums; }
.ts-hero__lead { grid-column: 1 / 6; grid-row: 3; }
.ts-hero__actions { grid-column: 1 / 8; grid-row: 4; }

/* Pause for the idle turn and the glint (they repeat, so visitors can stop them). */
.ts-pause {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 5px 10px;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-size: 11px;
  cursor: pointer;
}
.ts-pause[hidden] { display: none; }
.ts-pause::before { content: ""; width: 8px; height: 9px; border-inline: 3px solid currentColor; }
.ts-pause[aria-pressed="true"]::before { width: 0; height: 0; border-block: 5px solid transparent; border-inline-start: 8px solid currentColor; border-inline-end: 0; }
[dir="rtl"] .ts-pause[aria-pressed="true"]::before { transform: scaleX(-1); }
.ts-pause:hover { background: var(--ink); color: var(--paper); }

/* ---------- Hero-to-bullet flight (home: assets/js/home/orb-flight.js) ---------- */
/* The sphere comes apart and its tiles reassemble in the "GPL at a glance." bullet. .ts--fly fixes the canvas to
   the viewport so the WebGL tiles can leave the hero (which clips); .ts-swarm is the SVG version, 78 clones of the
   mark's tiles in a fixed overlay, each placed by a transform matrix in viewport px. While a flight is under way
   (.is-flying) the resting mark hides and the tiles take over at the same spot; the canvas rises over the hero copy
   and the next section (at rest the intro tiles stay behind the wordmark). .is-landed: the title's bullet shows
   under the tiles, which fade out; going back, the tiles return at once. With WebGL the overlay crossfades out. */
.ts--fly .ts__canvas { position: fixed; }
.ts--fly.is-flying .ts__canvas { z-index: 3; }
.ts--fly .ts-hero__orb { z-index: 3; }
.ts--fly .ts-hero__mark { transition: none; }
.ts--fly.is-gl .ts-hero__mark { transition: opacity 0.45s var(--ease-out); }
.ts--fly:is(.is-flying, .is-landed) .ts-hero__mark { opacity: 0; transition: none; }
.ts-swarm {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  visibility: hidden;
  fill: url(#gpl-grad);
}
.ts--fly.is-flying .ts-swarm { visibility: visible; }
.ts--fly.is-gl .ts-swarm { opacity: 0; visibility: hidden; transition: opacity 0.45s var(--ease-out), visibility 0s linear 0.45s; }
.ts--fly.is-landed .ts-swarm { opacity: 0; visibility: hidden; transition: opacity 0.2s linear 0.08s, visibility 0s linear 0.28s; }
.ts--fly.is-landed .ts__canvas { opacity: 0; transition: opacity 0.26s linear; }

@keyframes ts-emit {
  0% { transform: none; }
  18% { transform: scale(1.9); color: var(--lime); }
  100% { transform: none; }
}
.motion .ts-hero__dot.is-emit { animation: ts-emit 1.1s var(--ease-out); }

@media (max-width: 899px) {
  .ts-hero__orb { grid-column: 1 / -1; grid-row: 2; justify-self: center; width: min(86%, 330px, 40svh); margin-top: 24px; margin-bottom: 44px; }
  .ts-hero__cap { justify-content: center; }
  .ts-hero__cap [data-ts-count] { display: none; }
  .ts-hero__title { grid-column: 1 / -1; grid-row: 3; margin-top: 18px; }
  .ts-hero__kicker { font-size: 21px; }
  .ts-hero__word { margin-top: 14px; font-size: clamp(54px, 16.8vw, 88px); }
  .ts-hero__lead { grid-column: 1 / -1; grid-row: 4; }
  .ts-hero__actions { grid-column: 1 / -1; grid-row: 5; }
}

/* Arabic line spacing */
:lang(ar) .ts-hero__kicker { line-height: 1.35; }
