/* ==========================================================================
   hud.css — the instrument panel over block 01 of the index page.

   FROM FIGMA, AT FIGMA'S NUMBERS. The frame is 1920x1080 with a 10px inset and
   a 283px left rail, and every offset below is that frame's. Two of them are
   worth naming because they are not arbitrary:

     the rail is 283px          the map, the panel and the progress bar are all
                                exactly this wide, so they stack as one column
     the bar is 28px            css/ui.css already had it, and Figma's bar is
                                28px too — so "10px above the bar" is a real
                                measurement in both places rather than a guess

   The vertical stack is read from the BOTTOM up, because that is how the frame
   is built: bar 28, gap 10, progress 42, gap 10, panel 212. Written as top
   offsets it would only hold at 1080px tall.

   TYPE. 10px / letter-spacing -0.4px / uppercase / line-height .5 — the same
   four values .cols already uses, and line-height .5 is load-bearing there for
   the same reason it is here: at 1 every stacked pair grows about 5px and the
   6px gaps stop reading as gaps. The tokens are css/ui.css's.
   ========================================================================== */

.hud{
  position: fixed; inset: 0; z-index: 40;
  pointer-events: none;
  font-size: var(--ui-10); letter-spacing: -0.4px; line-height: .5;
  text-transform: uppercase; color: #fff;
  /* Block 01 only. js/hud.js fades this out as the second block takes the
     screen — the panel belongs to the black room, and none of it is legible
     over white. Opacity rather than display, so it can cross-fade with the
     transition instead of blinking off at a threshold. */
  opacity: 0; transition: opacity .28s linear;
}
.hud.is-on{ opacity: 1; }
.hud p{ margin: 0; }

/* The `//` separators, everywhere they appear. Figma: #c8c8c8 at 50%, which is
   also --ui-grey — so it is the token, halved, rather than a fourth grey. */
.hud__sep{ color: var(--ui-grey); opacity: .5; }

/* ---------------- the map, top left --------------------------------------- */
.hud__map{ position: absolute; left: 10px; top: 10px; width: 283px; }

.hud__mapbox{
  position: relative; width: 283px; height: 142px; overflow: hidden;

  /* THE HATCH DRIFTS, and the geometry of the loop is the whole trick.

     The stripes are a repeating gradient with a 7px period measured along the
     GRADIENT AXIS, which is 105deg — not along x. Sliding it sideways by 7px
     would therefore land mid-stripe and the loop would jump. The horizontal
     period is p / sin(A): 7 / sin(105deg) = 7.246px, and translating by exactly
     that puts every line where its neighbour just was. Seamless, forever, with
     no second copy of the pattern to cross-fade.

     TRANSFORM on a layer of its own rather than background-position on the box.
     Both look identical; only one is composited. Animating background-position
     repaints a 283x142 area every frame on the main thread, and this page has
     a 250k-triangle mesh and an ASCII field already asking for that thread.
     The layer is 16px wider than the box and offset by half of that, so the
     travel never exposes an edge.

     Each of these is a dial in the panel (js/about-console.js, LINES), and
     --hatch-step is the one that is DERIVED and has to stay derived: change the
     spacing or the angle without recomputing it and the seam comes straight
     back. The console's setters do that, which is why neither is a plain
     variable row. */
  --hatch-angle:  105deg;
  --hatch-ink:    rgba(255,255,255,.11);
  --hatch-thick:  0.5px;               /* how heavy each line is */
  --hatch-period: 5px;                 /* spacing, along the gradient axis */
  --hatch-step:   5.176px;             /* = 5 / sin(105deg). Derived — see above */
  --hatch-speed:  0.313s;              /* one period per this long, i.e. 3.19/s */
}
.hud__mapbox::before{
  content: ""; position: absolute; top: 0; bottom: 0;
  left: -8px; right: -8px;
  background: repeating-linear-gradient(var(--hatch-angle),
      var(--hatch-ink) 0px, var(--hatch-ink) var(--hatch-thick),
      transparent var(--hatch-thick), transparent var(--hatch-period));
  animation: hud-hatch var(--hatch-speed) linear infinite;
  will-change: transform;
}
@keyframes hud-hatch{
  from{ transform: translateX(0); }
  to  { transform: translateX(var(--hatch-step)); }
}
/* A drifting background is exactly what this setting is for. */
@media (prefers-reduced-motion: reduce){
  .hud__mapbox::before{ animation: none; }
}
/* The four 3px corner blocks. */
.hud__corner{ position: absolute; width: 3px; height: 3px; background: #d9d9d9; }
.hud__corner--tl{ left: 0;  top: 0; }
.hud__corner--tr{ right: 0; top: 0; }
.hud__corner--bl{ left: 0;  bottom: 0; }
.hud__corner--br{ right: 0; bottom: 0; }

/* The figure, dead centre: Figma puts a 25x50 image at (129,46) of a 283x142
   box, and (283-25)/2 = 129, (142-50)/2 = 46. So it is centred, and saying so
   in transform survives a change to either number. */
/* .hud__figure IS GONE. It sized a PNG render of the page's own mesh; the map
   box now holds the live model instead (a .wfig host — see js/figure-host.js),
   which is pinned and sized by that module. assets/about/map-figure.png is no
   longer referenced by anything. */

/* The cursor's double. Red, and the only element here that moves.

   ONE PLACE, and it has to stay one place: js/hud.js clamps the square's travel
   by its own size so it never hangs out of the box, and it MEASURES that off
   this element rather than keeping a copy of the number. Change the size here
   and the travel follows; keep a second 6 in the JS and the two drift the first
   time either is touched, which shows up as a square that stops a few pixels
   short of one edge and overhangs the other. */
.hud__dot{
  position: absolute; left: 0; top: 0;
  width: 3px; height: 3px; background: red;
  will-change: transform;
}

/* The X and Y read-outs, in the bottom corners of the map box. */
.hud__xy{
  position: absolute; bottom: 0; height: 16px;
  display: flex; align-items: center; gap: 6px;
  padding: 0 6px; background: #fff; color: var(--ui-ink);
}
.hud__xy--x{ left: 0; }
.hud__xy--y{ right: 0; }
.hud__xy b{ font-weight: inherit; }
.hud__xy span{ min-width: 18px; text-align: right; }

/* The two label rows under the map. 10px below the box, 11px apart — both
   Figma's, and the second is why this is a grid rather than two lines of text:
   at line-height .5 the rows would otherwise sit 5px apart. */
/* ABSOLUTE, at Figma's own x offsets, because the strip is not a layout — it
   is seven labels pinned at 0, 14, 31, 190, 234 and 275 across 283px, on two
   rows 11px apart. Flowing it in a grid put "get out" on the first row beside
   "i am watching you" and the pair stopped reading as two voices. */
.hud__maplabels{ position: relative; height: 16px; margin-top: 10px; }
.hud__maplabels p{ position: absolute; white-space: nowrap; }
.hud__maplabels .r1{ top: 0; }
.hud__maplabels .r2{ top: 11px; }

/* ---------------- the coordinates, a third of the way down ---------------- */
/* Figma puts these at y=355 of 1080 — a proportion of the height rather than a
   distance from anything, so it is written as one. */
.hud__coord{ position: absolute; top: 32.9%; width: 283px;
             display: flex; justify-content: space-between; }
.hud__coord--l{ left: 10px; }
.hud__coord--r{ right: 10px; }

/* ---------------- the panel ----------------------------------------------- */
/* bottom = bar 28 + 10 + progress 42 + 10. Read from the bottom, as above. */
.hud__panel{
  position: absolute; left: 10px; bottom: 90px;
  width: 283px; height: 212px;
  display: flex; flex-direction: column; align-items: center; gap: 32px;
}
.hud__brackets{ display: flex; justify-content: space-between; width: 100%; }
.hud__panelbody{ width: 219px; display: flex; flex-direction: column; gap: 64px; }
.hud__row{ display: flex; gap: 60px; align-items: center; }
.hud__stack{ display: flex; flex-direction: column; gap: 10px; }
.hud__stack--tight{ gap: 6px; }
.hud__cellA{ width: 65px; }
.hud__cellB{ width: 94px; display: flex; flex-direction: column; gap: 8px; }
.hud__cellB .top{ display: flex; justify-content: space-between; align-items: flex-start; }
.hud__dot3{ width: 3px; height: 3px; background: #d9d9d9; }
.hud__dots{ display: flex; gap: 2px; align-items: center; }
.hud__row2{ display: flex; justify-content: space-between; align-items: flex-start; }
.hud__meta{ width: 94px; display: flex; flex-direction: column; gap: 32px; }
.hud__pair{ display: flex; gap: 13px; align-items: center; }
.hud__pair .l{ width: 39px; display: flex; flex-direction: column; gap: 6px; }
.hud__pair .r{ width: 42px; display: flex; flex-direction: column; gap: 6px;
               text-align: right; }
.hud__year{ display: flex; gap: 13px; align-items: center; }
.hud__reg{ width: 10px; height: 10px; }

/* ---------------- the progress bar ---------------------------------------- */
/* bottom = bar 28 + 10. */
.hud__progress{
  position: absolute; left: 10px; bottom: 38px;
  width: 283px; display: flex; flex-direction: column; gap: 16px;
}
.hud__ends{ display: flex; justify-content: space-between; }
/* THE TRACK IS TYPE, not a rule with a fill — which is Figma's own idea and a
   good one: the same string of slashes is drawn twice, once dim across the full
   283px and once bright inside a clipped box whose WIDTH IS THE PROGRESS. The
   two copies share a left edge and a font, so the bright slashes land exactly on
   the dim ones and the join is a character boundary rather than a cut. */
.hud__track{ position: relative; height: 5px; margin-top: 15px; }
.hud__slashes{
  position: absolute; left: 0; top: 0; width: 283px;
  white-space: nowrap; overflow: hidden;
}
.hud__slashes--dim{ color: rgba(218,236,241,.1); }
.hud__fill{ position: absolute; left: 0; top: 0; height: 5px; width: 0;
            overflow: hidden; }
.hud__fill .hud__slashes{ color: #daecf1; }

/* ---------------- the scroll label ---------------------------------------- */
.hud__scroll{ position: absolute; right: 10px; bottom: 38px; }
