/* The crossing and the timeline -- shared by the index-change family.
   js/crossing.js draws both; this sheet owns every `xg-` rule, the way
   css/replay.css owns `.rp-*` for every form that draws the replay chart.
   Session 48: lifted from forms/indexchange.css when The Rebalance became
   the second form to draw them, so one fix reaches both cards.

   ONE NUMBER DRIVES THE MOTION. The caller writes `--xg-p` (0..1, linear in
   time) onto `.xg-field` every frame; everything that moves is a calc() of
   it. A mark eases with a cubic-out written as arithmetic (1 - (1-p)^3)
   after its own delay `--xg-d` (`--xg-k` is 1/(1-d), written by the JS: a
   multiplication rather than a division by a variable, which WebKit's calc
   did not always accept). No CSS transitions on moving parts -- the caller's
   clock is the only timekeeper, which is what lets skip, pause and
   reduced-motion all paint the same final frame.

   MEMBERSHIP IS CHROME, NOT DIRECTION. Marks are ink and muted; the hero
   alone takes `--brand`. `--up`/`--down` appear nowhere in this sheet.

   TYPE IS DESIGN PX, VIA TOKENS (rule 8, amended session 34). */

/* ------------------------------------------------------------ the field */

/* Exactly as tall as its roster: the heads' row (30px), the rows
   (`--xg-rows-h`, the JS writes the bottom of the last row), and 34px for
   the state word. A field with no state word drops that reserve. */
.xg-field{position:relative;flex:none;
  height:calc(30px + var(--xg-rows-h) * 1px + 34px);
  --xg-p:0;--xg-rows-h:29;
  --xg-e:calc(1 - (1 - var(--xg-p)) * (1 - var(--xg-p)) * (1 - var(--xg-p)))}
.xg-field--nostate{height:calc(30px + var(--xg-rows-h) * 1px + 10px)}

.xg-chrome{font-size:var(--fs-10);letter-spacing:var(--ls-14);text-transform:uppercase;
  color:var(--muted);font-weight:600;white-space:nowrap}

/* Two heads, one centred over each half. They name PLACES, not actions, so
   they are true in every frame: at the start the joiners really are not in
   the index and the leavers really are; at the end the reverse. */
.xg-side{position:absolute;top:5px;width:50%;text-align:center}
.xg-side--out{left:0}
.xg-side--in{right:0}
.xg-side--in .xg-chrome{color:var(--ink)}
/* A long index name ("S&P SmallCap 600") ran its two heads together at the
   half-width; past twelve characters the heads step down a token and
   tighten, and stay inside their halves. */
.xg-field--longname .xg-side .xg-chrome{font-size:var(--fs-9);letter-spacing:var(--ls-11)}
.xg-side{padding:0 4px;box-sizing:border-box}
.xg-part{margin-left:6px;font-size:var(--fs-9);letter-spacing:var(--ls-12);text-transform:uppercase;
  color:var(--dim);font-weight:600;white-space:nowrap}

/* The index's edge: one vertical rule down the middle, stopping above the
   state word. */
.xg-edge{position:absolute;left:50%;top:24px;bottom:30px;width:1px;
  background:var(--edge);transform:translateX(-.5px)}
.xg-field--nostate .xg-edge{bottom:6px}

/* The lanes. A mark's X is a percentage of the field, and the two resting
   places are the centres of the two halves -- 25% outside, 75% inside --
   so each column settles centred under its own head. A joiner runs
   25% -> 75%; a leaver runs the same track the other way. `--xg-q` is that
   mark's own eased progress after its delay. */
.xg-lanes{position:absolute;left:0;right:0;top:30px;bottom:0;pointer-events:none}
.xg-mark{position:absolute;top:calc(var(--xg-top,0) * 1px);
  --xg-d:0;--xg-k:1;
  --xg-r:clamp(0, (var(--xg-p) - var(--xg-d)) * var(--xg-k), 1);
  --xg-q:calc(1 - (1 - var(--xg-r)) * (1 - var(--xg-r)) * (1 - var(--xg-r)));
  font-size:var(--fs-13);font-weight:700;letter-spacing:var(--ls-04);
  color:var(--deck);line-height:1;pointer-events:auto;
  transform:translateX(-50%)}
.xg-mark--in{left:calc(25% + 50% * var(--xg-q))}
.xg-mark--out{left:calc(75% - 50% * var(--xg-q));color:var(--muted)}
.xg-mark--hero{font-size:var(--fs-29);letter-spacing:var(--ls-n015);color:var(--brand);font-weight:800}
/* Dense (more than six rows a column, js/crossing.js): the mark steps down one
   token and the JS writes a 20px pitch into each mark's `--xg-top`. */
.xg-field--dense .xg-mark{font-size:var(--fs-12)}
/* A mark still short of the edge is "outside" the ink of the index: the
   roster dims until it has crossed, so the settled frame reads inside=ink. */
.xg-mark--in:not(.xg-mark--hero){opacity:calc(.55 + .45 * var(--xg-q))}
.xg-mark--out:not(.xg-mark--hero){opacity:calc(1 - .45 * var(--xg-q))}

/* The state word under the field: `was` while the marks move, `now` once
   they have locked. Two spans stacked; the clock's last fifth swaps them. */
.xg-verb{position:absolute;left:0;right:0;bottom:0;height:18px;text-align:center;
  font-size:var(--fs-11);letter-spacing:var(--ls-12);text-transform:uppercase;
  font-weight:600;pointer-events:none}
.xg-verb span{position:absolute;left:0;right:0;top:0}
.xg-verb-was{color:var(--dim);opacity:clamp(0, (0.82 - var(--xg-p)) * 12, 1)}
.xg-verb-now{color:var(--ink);opacity:clamp(0, (var(--xg-p) - 0.8) * 8, 1)}

/* ---------------------------------------------------------- the timeline */

/* `--xg-tl` is the as-of mark's calendar position, unitless 0..1 (a
   percentage times a percentage is not a length calc() will take);
   `--xg-tl-p` is the caller's clock, linear, so the mark and any line the
   caller draws beside it advance together. */
.xg-timeline{position:relative;flex:none;margin:26px 0 0;height:36px;--xg-tl:0.5;--xg-tl-p:0}
.xg-tl-rule{position:absolute;left:4px;right:4px;top:6px;height:1px;background:var(--edge)}
.xg-tl-mark{position:absolute;top:6px;width:9px;height:9px;border-radius:50%;
  transform:translate(-50%,-50%);background:var(--ground);border:1.5px solid var(--muted)}
.xg-tl-mark--a{left:4px;background:var(--muted)}
.xg-tl-mark--e{left:calc(100% - 4px);border-color:var(--ink)}
.xg-tl-mark--t{left:calc(4px + (100% - 8px) * var(--xg-tl) * var(--xg-tl-p));
  width:7px;height:7px;background:var(--brand);border-color:var(--brand)}
/* The moving mark's own date, riding with it. */
.xg-tl-now{position:absolute;top:-16px;transform:translateX(-50%);
  left:calc(4px + (100% - 8px) * var(--xg-tl) * var(--xg-tl-p));
  font-size:var(--fs-9);letter-spacing:var(--ls-12);text-transform:uppercase;font-weight:600;
  color:var(--brand);white-space:nowrap}
.xg-tl-labels{position:absolute;left:0;right:0;top:15px;display:flex;justify-content:space-between;
  font-size:var(--fs-11);color:var(--muted);letter-spacing:var(--ls-005)}
.xg-tl-lab b{font-weight:600;color:var(--dim);text-transform:uppercase;font-size:var(--fs-9);
  letter-spacing:var(--ls-12);margin-right:4px}
.xg-tl-lab--e{text-align:right}
.xg-tl-lab--e b{color:var(--ink)}

@media (prefers-reduced-motion: reduce){
  .xg-field{--xg-p:1}
  .xg-timeline{--xg-tl-p:1}
}
