/* ==========================================================================
   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; }

/* ---------------- the running line, top right ------------------------------
   Figma 14679:25513. The footer's marquee, in the black room.

   THE KEYFRAMES LIVE HERE NOW, AND THAT IS THE REPAIR. They used to be
   declared in css/footer.css against .ftr__track, and this rule borrowed them
   by name — one description of the loop, so the two could not drift apart. It
   was the right instinct and it had one failure mode nobody watches for: the
   footer was rewritten, .ftr__track and its @keyframes went with it, and the
   ONLY remaining user of the animation was this file. A missing @keyframes is
   not an error in CSS. The declaration below stayed valid, matched nothing,
   and the line simply stopped moving — silently, with no console to tell you.

   So the animation now lives beside its only user. If a marquee is ever wanted
   again elsewhere, borrow it FROM here rather than moving it back. */
.hud__ticker{
  position: absolute; top: 10px; right: 10px;
  width: 283px; height: 16px;
  background: rgba(255,255,255,.1);
  overflow: hidden;
  display: flex; align-items: center;
}
.hud__tick{
  display: flex; align-items: center; gap: 32px;
  padding-left: 6px;
  white-space: nowrap;
  color: rgba(255,255,255,.5);
  animation: ftr-run var(--hud-run, 18s) linear infinite;
  will-change: transform;
}
/* LEFT TO RIGHT: from one copy back to zero, so the content travels rightward
   and the copy behind it arrives to fill the gap. The loop closes only because
   the distance moved is a whole number of copies — 50% of the track. The
   markup in index.html repeats the set four times, and two copies of travel is
   still a whole number of them, so it stays seamless. */
@keyframes ftr-run{
  from{ transform: translateX(-50%); }
  to  { transform: translateX(0); }
}
.hud__tick .s{ color: rgba(255,255,255,.25); }
@media (prefers-reduced-motion: reduce){
  .hud__tick{ animation: none; }
}

/* ---------------- the awards -----------------------------------------------
   Figma 14679:25559 draws it at x1627 y53 on a 1920x1080 frame, 283 wide and
   305 tall, with the longitude row directly under it at y355.

   THE HEIGHT IS DERIVED FROM THAT ROW, not typed. 32.9% is where .hud__coord
   sits, so the list always stops the same 10px above it — a typed 305 would be
   correct at 1080 and overlap the coordinates on anything shorter, which is
   most laptops.

   THE GRADIENT IS THE SENTENCE. The list is longer than the box and keeps
   going as the page scrolls; a hard edge at the bottom would say it ends
   there. The mask is what turns a clipped list into one that continues. */
.hud__awards{
  position: absolute; top: 53px; right: 10px;
  width: 283px;
  height: calc(32.9% - 63px);
  overflow: hidden;
  /* TWO STOPS, AND THE SECOND ONE IS THE POINT. Written as
     `transparent 100%` the ramp spends the whole 308px getting there, so the
     list was still legible most of the way down where the file has it gone by
     the second group's first line. Figma's fade is finished at about three
     fifths of the box; the remaining two fifths are empty on purpose, which is
     what leaves the coordinates below it sitting on clean black. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 var(--aw-solid, 5%), transparent var(--aw-gone, 92%));
          mask-image: linear-gradient(180deg, #000 0%, #000 var(--aw-solid, 5%), transparent var(--aw-gone, 92%));
}
.hud__awtrack{ will-change: transform; }

/* NO GAP BETWEEN GROUPS, and the arithmetic is the reason. Figma puts the
   second group's top at 165 and calls the first group 155 tall — 155 is the
   frame hugging the last line's 5px of ink, not the row's height. Eleven rows
   at the file's own 15px pitch is 165, so stacking them flush lands the second
   group exactly where the file draws it. A 10px gap on top of that would be
   the difference counted twice. */
.hud__awgrp{ display: flex; align-items: flex-start; }
.hud__awname{ flex: 0 0 90px; width: 90px; }
.hud__awlist{ flex: 1 1 auto; }
.hud__awrow{
  display: flex; justify-content: space-between; align-items: flex-start;
  height: 15px;
  color: rgba(255,255,255,.55);
}
/* The count column is its own 20px so the x1s line up as a column rather than
   ragging with the name above them. */
.hud__awrow > p:last-child{ flex: 0 0 20px; text-align: right; }
.hud__awtot{ color: #fff; }
.hud__awname{ color: #fff; }
