/* ==========================================================================
   Exile Tools — Art
   The image-led surfaces: the Gemplanner hero (home), the TraXile scene
   (home) and the Gemplanner build hero (results page). Loaded after pages.css.

   Shared signature: one faceted crystal / socket motif, carved stone, brass
   only on carved edges, red only as energy and markers. All artwork is inline
   SVG drawn for this site (home/templates/home/art/), the fog textures in
   ../art/ were generated for it, plus the skill gem inventory icons the
   Gemplanner already uses. The home hero sits on one painted backdrop,
   ../art/et-bg.webp (ruins with the ET emblem in the wall).

   Motion (see foundation.css): Atmospheric Drift on .art-layer and .fog,
   Energy Trace on .trace, Tactile Response on hover. Animations only run
   while the artwork is on screen (.is-inview, set by site.js) and the tab is
   visible.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Shared pieces
   -------------------------------------------------------------------------- */

/* Static film grain over an artwork surface */
.gp-hero::after,
.tx-story::after,
.build-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--grain);
  opacity: var(--grain-opacity);
  mix-blend-mode: var(--grain-blend);
}

/* Crystal (home/art/crystal.html) */
.crystal__f--1 { fill: var(--crystal-4); }
.crystal__f--2 { fill: var(--crystal-3); }
.crystal__f--3 { fill: var(--crystal-3); }
.crystal__f--4 { fill: var(--crystal-1); }
.crystal__f--5 { fill: var(--crystal-2); }
.crystal__f--6 { fill: var(--crystal-1); }
.crystal__f--face-l { fill: var(--crystal-4); }
.crystal__f--face-r { fill: var(--crystal-2); }
.crystal__core { fill: var(--crystal-5); opacity: 0.42; }
.crystal__edge { fill: none; stroke: var(--crystal-edge); stroke-width: 1.4; stroke-linejoin: round; }
.crystal__edge--inner { opacity: 0.55; }
.crystal__spec { fill: none; stroke: #FFFFFF; stroke-width: 2.4; stroke-linecap: round; opacity: 0.7; }

/* Skill gem socket — a real gem icon set into carved stone, ringed in its attribute colour */
.socket {
  --gem-ring: var(--gem, var(--gem-none));
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, var(--socket-hi) 0%, var(--socket-bg) 72%);
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--gem-ring) 70%, transparent),
    0 0 0 4px var(--socket-bg),
    0 0 0 5px color-mix(in srgb, var(--brass) 55%, transparent),
    inset 0 3px 8px rgb(0 0 0 / 0.55);
  transition: box-shadow var(--motion-tactile) var(--ease-ui), translate var(--motion-tactile) var(--ease-ui);
}
.socket img { width: 78%; height: auto; }

/* Energy Trace: a short dash that runs along a path once per cycle. Hidden when not animating. */
.trace {
  fill: none;
  stroke: var(--crystal-5);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 7 93;
  stroke-dashoffset: 7;
  opacity: 0;
}

/* Primary CTA with a cut corner — same control, forged edge */
.btn--forged {
  --cut: 10px;
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
  padding-inline: var(--space-5) var(--space-6);
}
.btn--forged .icon { transition: transform var(--motion-fast) var(--ease-ui); }
.btn--forged:hover .icon { transform: translateX(2px); }
.btn--forged:focus-visible { clip-path: none; }
.btn--lg { min-height: 56px; padding-inline: var(--space-6) calc(var(--space-6) + 4px); font-size: 17px; --cut: 12px; }
.btn--lg .icon { width: 18px; height: 18px; }

/* Carved geometry shared by the home stage and the results build hero */
.gp-art__hex { fill: none; stroke: var(--art-line-strong); stroke-width: 1.2; }
.gp-art__hex--outer { stroke: var(--art-line); stroke-width: 1; }
.gp-art__hex--runes { stroke: var(--brass); stroke-width: 7; stroke-dasharray: 2 14 18 14; opacity: 0.35; }
.gp-art__link { fill: none; stroke-linecap: round; }
.gp-art__link--bed { stroke: var(--socket-bg); stroke-width: 14; }
.gp-art__link--core { stroke: var(--brass); stroke-width: 2; opacity: 0.8; }
.trace--link { stroke-width: 4; }
.ring { fill: none; stroke: var(--art-line-strong); }
.ring--outer { stroke-width: 1.5; }
.ring--ticks { stroke: var(--brass); stroke-width: 6; stroke-dasharray: 1 11; opacity: 0.55; }
.ring--runes { stroke-width: 9; stroke-dasharray: 22 7 4 7 11 16 3 9; opacity: 0.5; }
.ring--inner { stroke: var(--brass); stroke-width: 1.2; opacity: 0.6; }

/* --------------------------------------------------------------------------
   Home — Gemplanner hero
   Depth, back to front: artwork (ruins, ET emblem in the right wall) → scrim
   from the left → far fog → stage (diffuse depth forms, the trail of sockets,
   crystal) → veil → mid fog → near fog → ground haze → copy and the plan
   shard. The floating navigation runs over the top.

   Art direction: the artwork is cropped on purpose (--art-x / --art-y, per
   breakpoint) so the emblem stays in view, and the stage is placed relative
   to the emblem, not to the viewport: --emblem-* follow the crop of the
   artwork, the crystal sits --gem-dx / --gem-dy away from it (fractions of the
   rendered artwork). That keeps the two motifs apart at every width.
   -------------------------------------------------------------------------- */
.gp-hero {
  --art-ratio: 2.1316;   /* et-bg.webp, 1831 × 859 */
  --art-x: 0.65;         /* object-position of the artwork, 0 … 1 */
  --art-y: 0.4;
  --emblem-u: 0.84;      /* centre of the ET emblem within the artwork, 0 … 1 */
  --emblem-v: 0.33;
  --gem-dx: -0.17;       /* crystal centre relative to the emblem centre, in artwork widths / heights */
  --gem-dy: 0.17;
  --stage-scale: 0.4;    /* stage width in artwork widths … */
  --stage-max: 860px;    /* … capped, so the progression never grows past this on wide screens */
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  min-height: clamp(720px, calc(100svh - var(--league-h)), 980px); /* runs under the floating navigation; the league bar sits above */
  background: var(--art-void);
}
.gp-backdrop { position: absolute; inset: 0; z-index: -8; }
.gp-backdrop__art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: calc(var(--art-x) * 100%) calc(var(--art-y) * 100%);
}
/* Directed scrim: dark behind the copy, falling off across the middle, gone before the emblem.
   Stops follow the content container, so the copy sits in the same darkness at every width. */
.gp-scrim {
  --l: max(0px, (100% - var(--container)) / 2);
  --w: calc(min(100%, var(--container)) * var(--scrim-reach, 1));
  position: absolute;
  inset: 0;
  z-index: -6;
  pointer-events: none;
  background:
    /* a soft lid under the floating navigation, so its links read over the bright sky and the arch */
    linear-gradient(180deg,
      color-mix(in srgb, var(--art-void) 72%, transparent) 0%,
      color-mix(in srgb, var(--art-void) 32%, transparent) calc(var(--header-h) * 0.8),
      transparent calc(var(--header-h) + 80px)),
    linear-gradient(90deg,
    color-mix(in srgb, var(--art-void) var(--scrim-max), transparent) 0%,
    color-mix(in srgb, var(--art-void) calc(var(--scrim-max) - 6%), transparent) calc(var(--l) + var(--w) * 0.3),
    color-mix(in srgb, var(--art-void) calc(var(--scrim-max) * 0.7), transparent) calc(var(--l) + var(--w) * 0.44),
    color-mix(in srgb, var(--art-void) calc(var(--scrim-max) * 0.45), transparent) calc(var(--l) + var(--w) * 0.56),
    color-mix(in srgb, var(--art-void) calc(var(--scrim-max) * 0.2), transparent) calc(var(--l) + var(--w) * 0.7),
    color-mix(in srgb, var(--art-void) calc(var(--scrim-max) * 0.06), transparent) calc(var(--l) + var(--w) * 0.82),
    transparent calc(var(--l) + var(--w) * 0.9));
}
/* The floor of the hero dissolves into the darkness the TraXile table rises from — no dividing line */
.gp-hero::before {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: 0;
  height: 220px;
  background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--art-seam) 55%, transparent) 55%, var(--art-seam) 100%);
  pointer-events: none;
}

/* The stage spans the hero as a size container, so the SVG can be placed in the artwork's coordinates */
.gp-stage {
  position: absolute;
  inset: 0;
  z-index: -5;
  container-type: size;
  pointer-events: none;
  transition: translate var(--motion-tactile) var(--ease-ui);
}
.gp-stage__svg {
  --art-w: max(100cqw, 100cqh * var(--art-ratio));
  --art-h: max(100cqh, 100cqw / var(--art-ratio));
  --emblem-x: calc((100cqw - var(--art-w)) * var(--art-x) + var(--art-w) * var(--emblem-u));
  --emblem-y: calc((100cqh - var(--art-h)) * var(--art-y) + var(--art-h) * var(--emblem-v));
  --stage-w: min(var(--art-w) * var(--stage-scale), var(--stage-max));
  position: absolute;
  /* crystal centre = (640, 215) in the 900 × 720 viewBox */
  left: calc(var(--emblem-x) + var(--art-w) * var(--gem-dx) - var(--stage-w) * 0.711);
  top: calc(var(--emblem-y) + var(--art-h) * var(--gem-dy) - var(--stage-w) * 0.239);
  width: var(--stage-w);
  height: auto;
  aspect-ratio: 900 / 720;
  overflow: visible;
}
/* Diffuse depth forms behind the gems: gradients only (no filters), so drifting them costs nothing.
   Kept low — the artwork already carries the red light. */
.gp-depth__aura { opacity: 0.5; transition: opacity 600ms var(--ease-ui); }
.gp-depth__aura--wide { opacity: 0.16; }
.gp-depth__column { opacity: 0.5; }
.gp-depth__haze { opacity: 0.4; }
.gp-ground-glow { opacity: 0.5; }
.gp-hero:hover .gp-depth__aura:not(.gp-depth__aura--wide) { opacity: 0.62; }

/* The trail: a blurred glow and a fine thread instead of a carved, outlined channel */
.gp-trail__glow { fill: none; stroke: var(--art-light); stroke-width: 16; stroke-linecap: round; opacity: 0.6; }
.gp-trail__thread { fill: none; stroke: var(--brass); stroke-width: 1.3; stroke-linecap: round; opacity: 0.38; }
.trace--trail { stroke-width: 2.4; stroke-dasharray: 18 82; stroke-dashoffset: 18; }
.trace--trail-halo { stroke: var(--crystal-4); stroke-width: 12; stroke-opacity: 0.22; }

/* Sockets: one ring in the gem's colour on a dark bed — no second brass outline */
.gp-socket__rim { fill: var(--socket-bg); fill-opacity: 0.85; }
.gp-socket__ring { fill: none; stroke: var(--gem, var(--gem-none)); stroke-width: 2; opacity: 0.55; transition: opacity var(--motion-tactile) var(--ease-ui); }
.gp-socket image { transition: filter var(--motion-tactile) var(--ease-ui); }
.gp-hero:hover .gp-stage { translate: 0 -3px; }
.gp-hero:hover .gp-socket__ring { opacity: 0.9; transition-delay: calc(var(--i, 0) * 45ms); }
.gp-hero:hover .gp-socket image { filter: brightness(1.12); transition-delay: calc(var(--i, 0) * 45ms); }

.gp-hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: 1fr auto;
  gap: var(--space-7) var(--space-5);
  padding-block: calc(var(--header-h) + var(--space-8)) var(--space-6);
}
.gp-hero__copy { grid-column: 1 / span 6; grid-row: 1; align-self: center; }
.gp-hero__title {
  /* Orbitron Bold, ≈ 6.8 em wide — at the token size the word spans the copy column */
  font-size: var(--fs-display);
  font-weight: var(--display-weight-hero);
  line-height: 1.05;
  white-space: nowrap;
  color: var(--text);
  text-shadow: 0 2px 30px var(--art-void);
}
.gp-hero__claim {
  max-width: 21ch;
  margin-top: var(--space-5);
  font-family: var(--font-ui);  /* two voices per component: Orbitron names, Instrument Sans speaks */
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.22;
  letter-spacing: -0.015em;
  color: var(--text);
}
.gp-hero__lead { max-width: 44ch; margin-top: var(--space-4); font-size: 17px; line-height: 1.6; color: var(--text-muted); }
.gp-hero__lead strong { color: var(--text); }
.gp-hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-6); margin-top: var(--space-7); }
.gp-hero__note { margin-top: var(--space-4); font-size: var(--fs-meta); color: var(--text-muted); }

/* Plan shard — three rows of a Gem Plan in the app's own row language (socketed icon, attribute edge) */
.plan-shard {
  --cut: 16px;
  grid-column: 10 / span 3;
  grid-row: 1 / span 2;
  align-self: end;
  margin: 0 calc(-1 * var(--space-4)) 0 0;
  padding: var(--space-4) var(--space-4) var(--space-3);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
  box-shadow: 0 36px 60px -32px rgb(0 0 0 / 0.7);
}
.plan-shard__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0 0 var(--space-3) var(--space-1);
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--display-weight);
  line-height: 1.5;
  letter-spacing: var(--display-tracking-label);
  color: var(--text);
}
.plan-shard__head span + span { font-family: var(--font-ui); font-size: var(--fs-meta); letter-spacing: 0; color: var(--brass-text); }
.plan-shard__rows { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.plan-shard__rows li {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  background: linear-gradient(90deg, color-mix(in srgb, var(--gem, var(--gem-none)) 10%, transparent) 0%, transparent 60%);
  box-shadow: inset 3px 0 0 var(--gem, var(--gem-none));
}
.plan-shard__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, var(--socket-hi) 0%, var(--socket-bg) 75%);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--gem, var(--gem-none)) 65%, transparent), inset 0 2px 5px rgb(0 0 0 / 0.5);
}
.plan-shard__icon img { width: 32px; height: 32px; }
.plan-shard__gem { display: grid; min-width: 0; font-size: var(--fs-ui-sm); font-weight: 600; line-height: 1.3; }
.plan-shard__gem span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-min); font-weight: 400; color: var(--text-muted); }
.plan-shard__as { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-min); color: var(--text-muted); }
.plan-shard__as img { width: 18px; height: 18px; }


/* --------------------------------------------------------------------------
   Fog — volumetric haze in five depths (Atmospheric Drift)
   Three pre-rendered, horizontally seamless fog textures (../art/fog-*.webp:
   domain-warped fractal noise, generated for this site) are used as masks over
   theme-tinted sheets:
     fog-bank   dense banks          → far + near
     fog-wisps  torn, thinner wisps  → mid, catches the crystal's light
     fog-veil   wide, soft veils     → veil (behind the chain) + low (ground haze)
   Two motions are layered per depth, both transform/opacity only:
     · the sheet is one tile wider than its layer and slides by exactly one tile
       (linear, minutes long, alternating directions between depths → shear);
     · the layer itself swells: slow, irregular lift, spread and density change
       (fog-swell, each depth on its own prime-ish period, so the composite never
       visibly repeats).
   Horizontal masks keep the copy column clear; the textures fade to nothing at
   their top and bottom, so no layer has an edge. Paused off screen and in a
   hidden tab; still frame with reduced motion; fewer layers on small screens.
   -------------------------------------------------------------------------- */
.fog {
  --fog-h: clamp(300px, 42vw, 600px);
  --fog-ratio: 2.857;                              /* fog-bank / fog-wisps: 1600 × 560 */
  --fog-tile: calc(var(--fog-h) * var(--fog-ratio));
  position: absolute;
  left: 0;
  right: 0;
  height: var(--fog-h);
  overflow: hidden;
  pointer-events: none;
}
.fog__sheet {
  position: absolute;
  top: 0;
  left: var(--fog-offset, 0px);
  width: calc(100% + 2 * var(--fog-tile));
  height: 100%;
  background: var(--fog-tint);
  opacity: var(--fog-opacity);
  -webkit-mask: var(--fog-texture) repeat-x 0 0 / var(--fog-tile) 100%;
  mask: var(--fog-texture) repeat-x 0 0 / var(--fog-tile) 100%;
  will-change: transform;
}
.fog--far {
  --fog-texture: url("../art/fog-bank.webp");
  --fog-tint: var(--fog-tint-far);
  --fog-opacity: var(--fog-opacity-far);
  bottom: 8%;
  z-index: -7;
}
.fog--veil {
  --fog-h: clamp(360px, 50vw, 720px);
  --fog-ratio: 2.692;                              /* fog-veil: 1400 × 520 */
  --fog-texture: url("../art/fog-veil.webp");
  --fog-tint: var(--fog-tint-veil);
  --fog-opacity: var(--fog-opacity-veil);
  --fog-offset: calc(var(--fog-tile) * -0.3);
  top: 4%;
  z-index: -4;
  -webkit-mask-image: linear-gradient(90deg, transparent 6%, rgb(0 0 0 / 0.5) 34%, #000 58%);
  mask-image: linear-gradient(90deg, transparent 6%, rgb(0 0 0 / 0.5) 34%, #000 58%);
}
.fog--mid {
  --fog-h: clamp(240px, 32vw, 460px);
  --fog-texture: url("../art/fog-wisps.webp");
  --fog-tint: var(--fog-tint-mid);
  --fog-opacity: var(--fog-opacity-mid);
  top: 16%;
  z-index: -3;
  -webkit-mask-image: linear-gradient(90deg, transparent 10%, #000 54%);
  mask-image: linear-gradient(90deg, transparent 10%, #000 54%);
}
.fog--near {
  --fog-h: clamp(240px, 32vw, 460px);
  --fog-texture: url("../art/fog-bank.webp");
  --fog-tint: var(--fog-tint-near);
  --fog-opacity: var(--fog-opacity-near);
  --fog-offset: calc(var(--fog-tile) * -0.42);
  bottom: -4%;
  z-index: -2;
  -webkit-mask-image: linear-gradient(90deg, rgb(0 0 0 / 0.4) 0%, #000 48%);
  mask-image: linear-gradient(90deg, rgb(0 0 0 / 0.4) 0%, #000 48%);
}
.fog--low {
  --fog-h: clamp(220px, 26vw, 380px);
  --fog-ratio: 2.692;
  --fog-texture: url("../art/fog-veil.webp");
  --fog-tint: var(--fog-tint-near);
  --fog-opacity: var(--fog-opacity-low);
  --fog-offset: calc(var(--fog-tile) * -0.71);
  bottom: -12%;
  z-index: -1;
  -webkit-mask-image: linear-gradient(90deg, rgb(0 0 0 / 0.55) 0%, #000 40%);
  mask-image: linear-gradient(90deg, rgb(0 0 0 / 0.55) 0%, #000 40%);
}

:root,
:root[data-theme="dark"] {
  --fog-tint-far: rgb(150 156 166);
  --fog-tint-veil: rgb(196 180 180);  /* lit from behind by the crystal */
  --fog-tint-mid: rgb(222 186 180);   /* catches the crystal's light */
  --fog-tint-near: rgb(178 180 186);
  --fog-opacity-far: 0.52;
  --fog-opacity-veil: 0.28;
  --fog-opacity-mid: 0.34;
  --fog-opacity-near: 0.58;
  --fog-opacity-low: 0.4;
}
:root[data-theme="light"] {
  --fog-tint-far: #FFFFFF;
  --fog-tint-veil: #FFF7F2;
  --fog-tint-mid: #FFF4EE;
  --fog-tint-near: #FBF8F3;
  --fog-opacity-far: 0.3;
  --fog-opacity-veil: 0.22;
  --fog-opacity-mid: 0.24;
  --fog-opacity-near: 0.42;
  --fog-opacity-low: 0.5;
}

/* --------------------------------------------------------------------------
   Home — TraXile, the second tool
   Its own world: analysis. The section is composed around one monumental
   chart (home/art/traxile.html) that is the background itself — maps per
   session rising out of the dark under the copy towards a red light in the
   upper right. Depth, back to front: section ground and the seam from the
   hero → diffuse lights (drift) → far ghost series (blurred, most parallax)
   → mid: last league, drop lines → main: area and curve → points and notes
   → scrim from the left → copy. No board, no grid, no boxes.
   -------------------------------------------------------------------------- */
:root,
:root[data-theme="dark"] { --tx-curve: var(--red-300); --tx-core: var(--red-500); --tx-ground: #0C0B0D; }
:root[data-theme="light"] { --tx-curve: var(--red-600); --tx-core: var(--red-600); --tx-ground: #EDE6DA; }

.tx-story {
  --tx-p: 0;    /* scroll position of the section, -1 … 1 (site.js); drives the parallax */
  --tx-h: clamp(680px, 56vw, 900px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  align-items: center;
  min-height: var(--tx-h);
  background:
    radial-gradient(ellipse 70% 80% at 88% 30%, color-mix(in srgb, var(--tx-glow) 34%, transparent) 0%, transparent 70%),
    linear-gradient(180deg, var(--art-seam) 0%, var(--tx-ground) 30%, var(--bg) 100%);
}
:root,
:root[data-theme="dark"] { --tx-glow: var(--red-900); }
:root[data-theme="light"] { --tx-glow: var(--red-100); }

/* Diffuse lights: an ember behind the latest session, a brass lamp low under the copy, a haze between */
.tx-field { position: absolute; inset: 0; z-index: -3; pointer-events: none; }
.tx-light {
  position: absolute;
  border-radius: 50%;
  translate: 0 calc(var(--tx-p) * var(--depth, 40px));
  will-change: transform;
}
.tx-light--ember {
  --depth: 46px;
  width: 62vw; height: 62vw; max-width: 1100px; max-height: 1100px;
  right: -22vw; top: -30%;
  background: radial-gradient(circle, color-mix(in srgb, var(--tx-core) 26%, transparent) 0%, color-mix(in srgb, var(--tx-core) 8%, transparent) 38%, transparent 68%);
}
.tx-light--lamp {
  --depth: 28px;
  width: 54vw; height: 40vw;
  left: -14vw; bottom: -18%;
  background: radial-gradient(ellipse, color-mix(in srgb, var(--brass) 14%, transparent) 0%, transparent 66%);
}
.tx-light--haze {
  --depth: 64px;
  width: 46vw; height: 30vw;
  left: 40%; top: 34%;
  background: radial-gradient(ellipse, color-mix(in srgb, var(--tx-curve) 7%, transparent) 0%, transparent 70%);
}

/* The plot: as tall as the section, in the aspect ratio of the viewBox, anchored right — on most
   screens it is wider than the space beside the copy and runs on underneath it */
.tx-plot {
  position: absolute;
  z-index: -2;
  top: 0;
  right: max(-4vw, calc((100vw - 2200px) / 2));
  height: 100%;
  aspect-ratio: 1600 / 1000;
  margin: 0;
  pointer-events: none;
}
.tx-depth { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.tx-depth--far {
  translate: 0 calc(var(--tx-p) * 52px);
  filter: blur(5px);
  opacity: 0.85;
}
.tx-depth--mid { translate: 0 calc(var(--tx-p) * 18px); }
/* the curve rises out of the dark: faded at its start, full from the middle of the plot */
.tx-depth--main {
  -webkit-mask-image: linear-gradient(90deg, transparent 4%, #000 34%);
  mask-image: linear-gradient(90deg, transparent 4%, #000 34%);
}

.tx-ghost { fill: none; stroke-linecap: round; }
.tx-ghost--hours { stroke: var(--brass); stroke-width: 6; opacity: 0.2; }
.tx-ghost--deaths { stroke: var(--tx-curve); stroke-width: 5; opacity: 0.16; }
.tx-ghost--echo { stroke: var(--tx-curve); stroke-width: 110; opacity: 0.035; }

.tx-prev { fill: none; stroke: var(--text-muted); stroke-width: 2; stroke-dasharray: 2 9; stroke-linecap: round; opacity: 0.42; }
.tx-prev__end { fill: var(--tx-ground); stroke: var(--text-muted); stroke-width: 2; opacity: 0.6; }
.tx-drops { opacity: 0.32; }

.tx-line { fill: none; stroke: var(--tx-curve); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.tx-line--glow { stroke: var(--tx-core); stroke-width: 12; opacity: 0.22; filter: blur(7px); }
.trace--chart { stroke: #FFF4EE; stroke-width: 3.5; stroke-dasharray: 4 96; }
:root[data-theme="light"] .trace--chart { stroke: var(--red-200); }

/* Session points */
.tx-points { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }
.tx-points li {
  --s: 7px;
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  width: var(--s);
  height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  border-radius: 50%;
  background: var(--tx-curve);
  box-shadow: 0 0 0 3px var(--tx-ground);
  opacity: clamp(0.25, calc((var(--x) - 14) / 26), 1); /* the early sessions stay in the dark */
}
.tx-points .is-death {
  --s: 10px;
  border-radius: 1px;
  background: var(--brass-text);
  rotate: 45deg;
}
.tx-points .is-key { --s: 11px; }
.tx-points .is-key.is-death { --s: 13px; }
/* a soft halo around the marked points, the latest one a little stronger */
.tx-points .is-key::after {
  content: "";
  position: absolute;
  inset: -16px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--tx-core) 34%, transparent) 0%, transparent 70%);
}
.tx-points .is-death.is-key::after { rotate: -45deg; background: radial-gradient(circle, color-mix(in srgb, var(--brass) 34%, transparent) 0%, transparent 70%); }
.tx-points .is-now { --s: 14px; background: #FFF4EE; box-shadow: 0 0 0 3px var(--tx-core), 0 0 0 7px color-mix(in srgb, var(--tx-ground) 80%, transparent); }
.tx-points .is-now::after { inset: -34px; }
:root[data-theme="light"] .tx-points .is-now { background: var(--bg); }

/* Notes: a value in the heading face and a quiet caption on a short leader — no tooltip boxes.
   (Not Orbitron: its wide, proportional digits would push the notes off their leaders.) */
.tx-notes { position: absolute; inset: 0; }
.tx-note {
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  display: grid;
  gap: 2px;
  margin: 0;
  white-space: nowrap;
  font-size: var(--fs-meta);
  line-height: 1.3;
  color: var(--text-muted);
  text-shadow: 0 0 12px var(--tx-ground), 0 0 4px var(--tx-ground);
}
.tx-note b {
  font-family: var(--font-head);
  font-size: 30px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.tx-note::before { content: ""; position: absolute; background: currentColor; opacity: 0.45; }
/* below and to the right of the point, beside its drop line */
.tx-note--death { translate: 16px 22px; }
.tx-note--death::before { display: none; }
.tx-note--death b { color: var(--brass-text); }
/* above and to the left, leader down to the point */
.tx-note--mid { translate: calc(-100% + 1px) calc(-100% - 30px); justify-items: end; text-align: right; padding-right: 14px; }
.tx-note--mid::before { right: 0; bottom: -24px; width: 1px; height: 38px; }
/* left of the latest point, level with it */
.tx-note--now { translate: calc(-100% - 38px) -50%; justify-items: end; text-align: right; }
.tx-note--now::before { right: -26px; top: 50%; width: 16px; height: 1px; }
.tx-note--now b { font-size: 40px; color: var(--accent-text); }

/* Legend under the latest session, with the sample-data label */
.tx-legend {
  position: absolute;
  right: 22%;
  bottom: 5%;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: var(--space-1) var(--space-4);
  max-width: 40%;
  font-size: var(--fs-min);
  color: var(--text-muted);
  text-shadow: 0 0 10px var(--tx-ground);
}
.tx-legend__title { font-family: var(--font-display); font-size: var(--fs-label); font-weight: var(--display-weight); line-height: 1.5; letter-spacing: var(--display-tracking-label); color: var(--text); }
.tx-legend__note { flex-basis: 100%; text-align: right; letter-spacing: 0.02em; color: var(--brass-text); }
.tx-key { display: inline-flex; align-items: center; gap: 6px; }
.tx-key::before { content: ""; flex: none; }
.tx-key--now::before { width: 14px; height: 3px; border-radius: 2px; background: var(--tx-curve); }
.tx-key--prev::before { width: 14px; height: 0; border-top: 2px dotted var(--text-muted); }
.tx-key--death::before { width: 7px; height: 7px; background: var(--brass-text); transform: rotate(45deg); }

/* Scrim: the copy stands on calm dark ground; a little ground haze at the foot of the section */
.tx-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    /* the seam: the hero's floor continues for a moment, then the new world opens below it */
    linear-gradient(180deg,
      var(--art-seam) 0%,
      color-mix(in srgb, var(--art-seam) 72%, transparent) 7%,
      color-mix(in srgb, var(--art-seam) 30%, transparent) 14%,
      transparent 22%),
    linear-gradient(90deg,
      color-mix(in srgb, var(--tx-ground) 90%, transparent) 0%,
      color-mix(in srgb, var(--tx-ground) 78%, transparent) max(24%, calc((100vw - var(--container)) / 2 + 360px)),
      color-mix(in srgb, var(--tx-ground) 30%, transparent) max(40%, calc((100vw - var(--container)) / 2 + 600px)),
      transparent max(54%, calc((100vw - var(--container)) / 2 + 780px))),
    linear-gradient(0deg, color-mix(in srgb, var(--bg) 70%, transparent) 0%, transparent 16%);
}

.tx-story__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-5);
  padding-block: var(--space-9);
}
.tx-story__copy { grid-column: 1 / span 5; display: grid; gap: var(--space-5); }
.tx-story__title { display: grid; gap: var(--space-2); }
.tx-story__invite { font-family: var(--font-ui); font-size: var(--fs-h3); font-weight: 500; line-height: 1.2; letter-spacing: -0.01em; color: var(--text-muted); }
.tx-story__name {
  font-family: var(--font-display);
  font-size: var(--fs-tool);
  font-weight: var(--display-weight);
  line-height: var(--display-leading);
  letter-spacing: var(--display-tracking);
  color: var(--text);
}
.tx-story__lead { max-width: 40ch; color: var(--text-muted); }
.tx-story__copy .button-row { margin-top: var(--space-2); }
.tx-story__cta { border-color: var(--brass); background: color-mix(in srgb, var(--tx-ground) 70%, transparent); }
.tx-story__cta:hover { border-color: var(--brass-text); color: var(--brass-text); }
.tx-story__cta .icon { transition: transform var(--motion-fast) var(--ease-ui); }
.tx-story__cta:hover .icon { transform: translateY(2px); }

/* The log the app reads — real Client.txt line shapes, fading with age: the source of the curve */
.tx-log {
  display: grid;
  gap: var(--space-1);
  margin: var(--space-5) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-min);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
.tx-log li { display: flex; gap: var(--space-3); }
.tx-log li:nth-child(1) { opacity: 0.4; }
.tx-log li:nth-child(2) { opacity: 0.55; }
.tx-log li:nth-child(3) { opacity: 0.72; }
.tx-log li:nth-child(4) { opacity: 0.85; }
.tx-log time { color: var(--brass-text); }
.tx-log__result {
  align-items: center;
  margin-top: var(--space-2);
  font-size: var(--fs-ui-sm);
  font-weight: 600;
  color: var(--text);
}
.tx-log__result::before { content: ""; width: 8px; height: 8px; flex: none; background: var(--tx-curve); transform: rotate(45deg); }
.tx-log__result span { font-family: var(--font-display); font-size: var(--fs-label); font-weight: var(--display-weight); line-height: 1.5; letter-spacing: var(--display-tracking-label); color: var(--brass-text); }

/* --------------------------------------------------------------------------
   Gemplanner — build hero (results page)
   -------------------------------------------------------------------------- */
.build-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: clamp(260px, 30vw, 360px);
  margin-bottom: var(--space-7);
  background:
    radial-gradient(ellipse 50% 90% at 78% 46%, color-mix(in srgb, var(--hero-tint-a, var(--art-light)) 30%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 34% 70% at 92% 80%, color-mix(in srgb, var(--hero-tint-b, var(--art-light)) 22%, transparent) 0%, transparent 72%),
    var(--art-void);
}
.build-hero__art { position: absolute; inset: 0 0 0 38%; z-index: -1; }
.build-hero__svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.build-hero__scrim { position: absolute; inset: 0; z-index: -1; background: var(--art-scrim); }
.build-hero__sockets {
  position: absolute;
  right: calc(var(--gutter) + clamp(150px, 16vw, 250px));
  top: 52%;
  translate: 0 -50%;
  display: grid;
  grid-template-columns: repeat(4, 56px);
  gap: 18px 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.build-hero__sockets li:nth-child(even) { translate: 0 28px; }
.build-hero__sockets .socket { width: 56px; }
.build-hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: start;
  gap: var(--space-5);
  align-content: end;
  min-height: inherit;
  padding-block: var(--space-8) var(--space-6);
}
.build-hero__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  max-width: 22ch;
  /* the title is user-given and can be long: the readable heading face, not the wide display face */
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(34px, 4.2vw, 60px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  overflow-wrap: anywhere;
}
.build-hero__class {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-4);
  max-width: none;
  font-size: var(--fs-lead);
  color: var(--text-muted);
}
.build-hero__class strong { color: var(--text); font-weight: 600; }
.build-hero__attrs { display: inline-flex; gap: 6px; }
.build-hero__attrs span { width: 10px; height: 10px; background: var(--gem); transform: rotate(45deg); }
.build-hero__facts { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); margin: var(--space-3) 0 0; font-size: var(--fs-ui-sm); color: var(--text-muted); }
.build-hero__facts div { display: flex; gap: var(--space-2); }
.build-hero__facts dt { color: var(--brass-text); }
.build-hero__facts dd { margin: 0; color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.build-hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-2); }
.build-hero__actions .btn { min-height: 48px; }
.build-hero__actions .btn--secondary { background: color-mix(in srgb, var(--art-stone) 80%, transparent); }
.build-hero__feedback { min-height: 1.6em; margin-top: calc(-1 * var(--space-3)); font-size: var(--fs-ui-sm); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   Motion — Atmospheric Drift + Energy Trace (Tactile Response is in the rules above)
   -------------------------------------------------------------------------- */
@keyframes drift-rise {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(0, -9px, 0); }
}
@keyframes drift-sway {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(-10px, 3px, 0); }
}
@keyframes drift-far {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(6px, 0, 0); }
}
/* Fog: one tile per cycle, linear — a cycle is minutes long, so the eye reads it as weather, not motion */
@keyframes fog-drift {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-1 * var(--fog-tile)), 0, 0); }
}
/* Fog swell: lift, spread and density change at uneven stops — reads as turbulence, not as a loop */
@keyframes fog-swell {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1, 1); opacity: 0.74; }
  19% { transform: translate3d(1.2%, -12px, 0) scale(1.03, 1.06); opacity: 1; }
  46% { transform: translate3d(-0.8%, 5px, 0) scale(1.015, 0.97); opacity: 0.84; }
  71% { transform: translate3d(0.6%, -6px, 0) scale(1.045, 1.04); opacity: 0.96; }
  88% { transform: translate3d(-0.3%, 2px, 0) scale(1.01, 1); opacity: 0.8; }
}
@keyframes trace-run {
  0% { stroke-dashoffset: 7; opacity: 0; }
  6% { opacity: 1; }
  58% { opacity: 1; }
  66%, 100% { stroke-dashoffset: -100; opacity: 0; }
}
/* The trail: one slow pulse of light per cycle — eased travel, a soft fade in and out, then a long rest */
@keyframes trail-run {
  0% { stroke-dashoffset: 18; }
  70%, 100% { stroke-dashoffset: -100; }
}
@keyframes trail-fade {
  0%, 70%, 100% { opacity: 0; }
  12%, 56% { opacity: 1; }
}
/* …and each socket brightens briefly as the pulse passes it */
@keyframes socket-glint {
  0%, 18%, 100% { opacity: 0.55; }
  7% { opacity: 0.95; }
}
@keyframes route-draw {
  from { stroke-dashoffset: 100; }
  to { stroke-dashoffset: 0; }
}

[data-art] .art-layer--crystal { animation: drift-rise 12s var(--ease-drift) infinite; }
[data-art] .art-layer--far { animation: drift-far 16s var(--ease-drift) infinite; }
[data-art] .art-layer--map { animation: drift-sway 16s var(--ease-drift) infinite; }
[data-art] .trace { animation: trace-run var(--motion-trace) linear infinite; }
[data-art] .trace--trail { animation: trail-run 10s cubic-bezier(0.45, 0, 0.55, 1) infinite, trail-fade 10s linear infinite; }
[data-art] .gp-socket__ring { animation: socket-glint 10s var(--ease-drift) infinite; animation-delay: calc(1.6s + var(--i, 0) * 0.95s); }

[data-art] .fog__sheet { animation: fog-drift var(--fog-speed, 180s) linear infinite; }
[data-art] .fog--far .fog__sheet { --fog-speed: 260s; }
[data-art] .fog--veil .fog__sheet { --fog-speed: 310s; animation-direction: reverse; }
[data-art] .fog--mid .fog__sheet { --fog-speed: 170s; }
[data-art] .fog--near .fog__sheet { --fog-speed: 136s; }
[data-art] .fog--low .fog__sheet { --fog-speed: 220s; animation-direction: reverse; }
[data-art] .fog { animation: fog-swell var(--fog-swell, 41s) var(--ease-drift) infinite; transform-origin: 60% 70%; }
[data-art] .fog--far { --fog-swell: 53s; animation-delay: -11s; }
[data-art] .fog--veil { --fog-swell: 61s; animation-delay: -37s; }
[data-art] .fog--mid { --fog-swell: 29s; animation-delay: -5s; }
[data-art] .fog--near { --fog-swell: 43s; animation-delay: -19s; }
[data-art] .fog--low { --fog-swell: 37s; animation-delay: -27s; }

/* TraXile: the instrument comes to life once it is on screen (only when JS can tell us that).
   The curve is uncovered from left to right in one slow, even pass; each session point lights up as the
   curve reaches it, the marked points last; the notes and the legend settle in after. Afterwards only the
   lights drift, the far series sways a little, and a rare Energy Trace runs along the curve. */
@keyframes tx-fade { from { opacity: 0; } }
@keyframes tx-uncover { from { clip-path: inset(-10% 100% -10% 0); } to { clip-path: inset(-10% -2% -10% 0); } }
@keyframes tx-point { from { opacity: 0; scale: 0.3; } }
@keyframes tx-halo { from { opacity: 0; scale: 0.2; } }
@keyframes tx-note { from { opacity: 0; transform: translateY(6px); } }
@keyframes tx-ember { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-3vw, 2vw) scale(1.06); } }
@keyframes tx-lamp { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(4vw, -1.5vw); } }
@keyframes tx-haze { 0%, 100% { transform: translate(0, 0); opacity: 1; } 50% { transform: translate(-6vw, -2vw); opacity: 0.55; } }
@keyframes tx-sway { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-14px, 6px); } }

.tx-story { --tx-reveal: 3.6s; --tx-start: 400ms; }
[data-art] .tx-light--ember { animation: tx-ember 47s var(--ease-drift) infinite; }
[data-art] .tx-light--lamp { animation: tx-lamp 61s var(--ease-drift) infinite; animation-delay: -20s; }
[data-art] .tx-light--haze { animation: tx-haze 38s var(--ease-drift) infinite; animation-delay: -9s; }
[data-art] .tx-depth--far { animation: tx-sway 29s var(--ease-drift) infinite; }
[data-art].tx-story .trace--chart { animation-duration: 14s; animation-delay: calc(var(--tx-start) + var(--tx-reveal) + 2s); } /* one pass every 14 s */

.art-armed .tx-story .tx-depth--main { animation: tx-uncover var(--tx-reveal) linear var(--tx-start) both paused; }
.art-armed .tx-story .tx-depth--mid { animation: tx-fade 1.6s var(--ease-ui) 200ms both paused; }
/* the reveal is linear, so a point at x % is reached after x % of it */
.art-armed .tx-story .tx-points li { animation: tx-point 700ms var(--ease-ui) both paused; animation-delay: calc(var(--tx-start) + var(--x) / 100 * var(--tx-reveal) - 150ms); }
.art-armed .tx-story .tx-points .is-key::after { animation: tx-halo 1.4s var(--ease-ui) both paused; animation-delay: calc(var(--tx-start) + var(--x) / 100 * var(--tx-reveal) + 200ms); }
.art-armed .tx-story .tx-note { animation: tx-note 900ms var(--ease-ui) both paused; animation-delay: calc(var(--tx-start) + var(--x) / 100 * var(--tx-reveal) + 450ms); }
.art-armed .tx-story .tx-legend { animation: tx-fade 1.2s var(--ease-ui) both paused; animation-delay: calc(var(--tx-start) + var(--tx-reveal) + 300ms); }
.art-armed .tx-story.is-inview .tx-depth--main,
.art-armed .tx-story.is-inview .tx-points li,
.art-armed .tx-story.is-inview .tx-points .is-key::after,
.art-armed .tx-story.is-inview .tx-note,
.art-armed .tx-story.is-inview .tx-legend,
.art-armed .tx-story.is-inview .tx-depth--mid { animation-play-state: running; }
/* …and the log lines arrive one after another (Tactile Response: state feedback) */
.art-armed .tx-story .tx-log li { animation: quiet-reveal var(--motion-medium) var(--ease-ui) both paused; }
.art-armed .tx-story.is-inview .tx-log li { animation-play-state: running; }
.tx-log li:nth-child(2) { animation-delay: 240ms; }
.tx-log li:nth-child(3) { animation-delay: 480ms; }
.tx-log li:nth-child(4) { animation-delay: 720ms; }
.tx-log li:nth-child(5) { animation-delay: 1400ms; }

/* Only animate what is visible: paused until site.js marks the artwork as in view */
.art-armed [data-art] .art-layer,
.art-armed [data-art] .trace,
.art-armed [data-art] .gp-socket__ring,
.art-armed [data-art] .fog,
.art-armed [data-art] .fog__sheet,
.art-armed [data-art] .tx-light,
.art-armed [data-art] .tx-depth--far { animation-play-state: paused; }
.art-armed [data-art].is-inview .art-layer,
.art-armed [data-art].is-inview .trace,
.art-armed [data-art].is-inview .gp-socket__ring,
.art-armed [data-art].is-inview .fog,
.art-armed [data-art].is-inview .fog__sheet,
.art-armed [data-art].is-inview .tx-light,
.art-armed [data-art].is-inview .tx-depth--far { animation-play-state: running; }
.tab-hidden [data-art] * { animation-play-state: paused !important; }

/* Reduced motion: everything holds still — the fog stays as a quiet still frame */
@media (prefers-reduced-motion: reduce) {
  [data-art] .art-layer,
  [data-art] .trace,
  [data-art] .fog,
  [data-art] .fog__sheet { animation: none !important; }
  [data-art] .fog__sheet { will-change: auto; }
  .art-armed .tx-story .tx-log li { animation: none !important; }
  [data-art] .trace { display: none; }
  [data-art] .gp-socket__ring { animation: none !important; }
  /* TraXile: the finished chart as a still frame — no reveal, no drift, no parallax */
  .tx-story .tx-light,
  .tx-story .tx-depth,
  .tx-story .tx-points li,
  .tx-story .tx-points li::after,
  .tx-story .tx-note,
  .tx-story .tx-legend { animation: none !important; translate: none; will-change: auto; }
  .gp-stage { transition: none; }
}

/* --------------------------------------------------------------------------
   Responsive — compositions are re-set, not just cropped
   -------------------------------------------------------------------------- */
/* Very wide screens: the artwork is cropped top and bottom instead of left and right, so the emblem
   moves outwards faster than the content — the crystal follows a little further from it */
@media (min-width: 2000px) {
  .gp-hero { --gem-dx: -0.2; --gem-dy: 0.13; }
}

@media (max-width: 1180px) {
  .gp-hero__copy { grid-column: 1 / span 7; }
  .plan-shard { grid-column: 9 / -1; }
}

@media (max-width: 1080px) {
  .gp-hero { min-height: 0; }
  .gp-hero__grid { grid-template-rows: auto auto auto; padding-block: calc(var(--header-h) + var(--space-8)) var(--space-6); }
  .gp-hero__copy { grid-column: 1 / span 8; }
  /* Tablet: the artwork becomes a band at the top, cropped to its right half so the emblem stands
     beside the copy; the crystal hangs below the emblem and the trail sweeps down-left through the
     band, above the plan shard, which moves down to clear it */
  .gp-hero {
    --art-band: clamp(600px, 80vw, 760px);
    --art-x: 0.85;
    --scrim-reach: 1.25;  /* the copy spans more of the width here */
    --gem-dx: -0.1;
    --gem-dy: 0.34;
    --stage-max: 640px;
  }
  .gp-backdrop,
  .gp-stage { bottom: auto; height: var(--art-band); }
  .gp-backdrop::after { content: ""; position: absolute; inset: 55% 0 0; background: linear-gradient(180deg, transparent, var(--art-void)); }
  .plan-shard { grid-column: 5 / -1; grid-row: 2; margin: calc(var(--art-band) * 0.34) 0 0; }
  /* TraXile, tablet: copy on top on a scrim from above, the chart takes the lower part of the section
     and still runs under the copy — taller than wide screens would give it */
  .tx-story { --tx-band: clamp(380px, 58vw, 560px); align-items: start; }
  .tx-plot { top: auto; bottom: 0; right: -6vw; height: calc(var(--tx-band) * 1.15); }
  .tx-story__grid { padding-block: var(--space-9) calc(var(--tx-band) - var(--space-4)); }
  .tx-story__copy { grid-column: 1 / span 8; }
  .tx-scrim {
    background:
      linear-gradient(180deg,
        var(--art-seam) 0%,
        color-mix(in srgb, var(--tx-ground) 84%, transparent) 12%,
        color-mix(in srgb, var(--tx-ground) 60%, transparent) calc(100% - var(--tx-band) * 1.1),
        transparent calc(100% - var(--tx-band) * 0.8)),
      linear-gradient(90deg, color-mix(in srgb, var(--tx-ground) 60%, transparent) 0%, transparent 46%);
  }
  .tx-light--ember { top: auto; bottom: -10%; width: 90vw; height: 90vw; }
  .tx-note--death { translate: calc(-100% - 16px) 18px; justify-items: end; text-align: right; }
  .tx-legend__title { display: none; }
  .build-hero__sockets { right: var(--gutter); opacity: 0.85; }
}

@media (max-width: 760px) {
  /* Hero: the stage becomes a band at the top, fog rolls through it, copy follows below */
  /* the band starts below the floating navigation */
  .gp-hero__grid { padding-block: calc(var(--header-h) + min(112vw, 580px) * 0.62) var(--space-6); row-gap: var(--space-6); }
  /* Mobile: the emblem may be cut by the edge; the crystal is the one gem motif, the trail is cut
     short — its lower sockets dissolve into the fog before they reach the headline */
  .gp-hero {
    --art-band: calc(var(--header-h) + min(100vw, 520px) * 0.95);
    --art-x: 0.85;
    --gem-dx: -0.15;
    --gem-dy: 0.2;
    --stage-scale: 0.47;
    --stage-max: 480px;
  }
  .gp-backdrop::after { inset: 40% 0 0; }
  .gp-stage__svg {
    -webkit-mask-image: linear-gradient(to top right, transparent 40%, #000 54%);
    mask-image: linear-gradient(to top right, transparent 40%, #000 54%);
  }
  /* Fog on small screens: three depths instead of five, a little thinner, no swell on the far bank */
  .fog { --fog-h: 260px; }
  .fog--far { top: calc(var(--header-h) + 18vw); bottom: auto; animation: none !important; }
  .fog--veil,
  .fog--mid { display: none; }
  .fog--near { top: calc(var(--header-h) + min(100vw, 520px) * 0.4); bottom: auto; -webkit-mask-image: none; mask-image: none; }
  .fog--low { --fog-h: 200px; top: calc(var(--header-h) + min(100vw, 520px) * 0.62); bottom: auto; -webkit-mask-image: none; mask-image: none; }
  :root { --fog-opacity-far: 0.44; --fog-opacity-near: 0.5; --fog-opacity-low: 0.3; }
  :root[data-theme="light"] { --fog-opacity-far: 0.3; --fog-opacity-near: 0.4; --fog-opacity-low: 0.4; }
  .gp-hero__copy, .plan-shard { grid-column: 1 / -1; }
  .gp-hero__title { font-size: clamp(38px, 12vw, 72px); }  /* Orbitron ≈ 6.8 em: spans ≈ 82 % of the width */
  .gp-hero__actions { gap: var(--space-4); margin-top: var(--space-6); }
  .gp-hero__actions .btn--primary { flex: 1 1 100%; }
  .plan-shard { margin: 0; }

  /* TraXile, mobile: name and copy first, then the chart as a band below — cropped to its later sessions,
     the far series and the lights reduced; one note less */
  .tx-story { --tx-band: clamp(300px, 86vw, 400px); }
  .tx-plot { right: -4vw; height: var(--tx-band); }
  .tx-story__grid { padding-block: var(--space-8) calc(var(--tx-band) + var(--space-2)); }
  .tx-story__copy { grid-column: 1 / -1; }
  .tx-story__name { font-size: clamp(36px, 12vw, 64px); }
  .tx-depth--far { filter: blur(3px); }
  .tx-ghost--echo, .tx-light--haze, .tx-note--mid, .tx-note--death, .tx-legend__title { display: none; }
  .tx-note b { font-size: 24px; }
  .tx-note--now b { font-size: 30px; }
  .tx-note--now { translate: calc(-100% - 30px) -50%; }
  .tx-note--now::before { right: -22px; width: 12px; }
  .tx-legend { right: calc(4vw + var(--gutter)); bottom: var(--space-4); max-width: none; gap: 2px var(--space-3); }

  /* Build hero: sockets become a strip behind the title */
  .build-hero__art { inset: 0; opacity: 0.6; }
  .build-hero__sockets { right: var(--gutter); top: var(--space-5); translate: none; grid-template-columns: repeat(4, 40px); gap: 10px 12px; }
  .build-hero__sockets li:nth-child(even) { translate: 0 14px; }
  .build-hero__sockets .socket { width: 40px; }
  .build-hero__grid { grid-template-columns: 1fr; padding-top: 120px; }
}

@media (max-width: 480px) {
  .plan-shard__rows li:nth-child(3) { display: none; }
  .tx-log { font-size: var(--fs-min); }
  .tx-log li { flex-direction: column; gap: 0; }
  .tx-log__result { flex-direction: row !important; flex-wrap: wrap; gap: var(--space-2) !important; }
  .build-hero__sockets { grid-template-columns: repeat(4, 34px); }
  .build-hero__sockets .socket { width: 34px; }
  .build-hero__actions { display: grid; grid-template-columns: 1fr 1fr; }
}
