/* The streamed picture's furniture — shared by every surface that draws it.
 *
 * Spec: docs/streamed-picture-style-guide.md. Consumed by index.html (the full renderer),
 * overlay.html (the transparent OBS layer) and boatcam.html (the tile). Three surfaces drawing the
 * same four anchors from one stylesheet, so they cannot drift the way the two i18n tables did.
 *
 * SIZES ARE A FRACTION OF FRAME HEIGHT, never px. One number then works at 720p capture, 1080p
 * output and inside a PiP tile. The scale mirrors brand/tokens.json `type.airScale`.
 */

:root {
  /* The composition height these fractions are resolved against. A surface that is NOT a full
     1920×1080 frame — a quarter-size boat-cam tile — overrides this with the OUTPUT frame's height,
     never its own: text at 2% of a quarter-tile is 0.5% of the picture, i.e. invisible. */
  --hud-frame-h: 1080px;

  --hud-race-clock: calc(var(--hud-frame-h) * 0.037);
  --hud-event: calc(var(--hud-frame-h) * 0.024);
  --hud-team: calc(var(--hud-frame-h) * 0.022);
  /* The programme timestamp is provenance, not the subject of the shot. Keep it at the normal value
     size so it remains readable without dominating the lower-left corner. A larger clock burned into
     device footage belongs inside that source picture and no longer dictates every rendered view. */
  --hud-stamp: calc(var(--hud-frame-h) * 0.022);
  --hud-value: calc(var(--hud-frame-h) * 0.022);
  --hud-unit: calc(var(--hud-frame-h) * 0.015);
  /* The floor. Nothing viewer-facing may be smaller — 11px labels (1.0%) survived on a desktop
     monitor and died on a phone and in low-bitrate h264. */
  --hud-min: calc(var(--hud-frame-h) * 0.018);
  /* …with ONE exception, and it is a different kind of text. A licence attribution is an obligation
     to the data supplier, not information the picture is asking the viewer to read: it has to be
     present and legible on a still or a pause, and it must not compete with the reading it credits.
     The floor above governs everything the viewer is meant to take in at a glance, and still does. */
  --hud-credit: calc(var(--hud-frame-h) * 0.013);

  /* The drawn HEIGHT of the sanctioning authority's mark (lower right, above ours) — a picture size,
     not a type size, so it is not in the scale above. Derived rather than picked: the supplied
     lockup sets its wordmark at about a fifth of its own height, and 6.5 % puts that wordmark's caps
     on `--hud-credit`. That is deliberately the credit class and not the 1.8 % floor — like the
     weather attribution, this has to be present and legible on a still without competing with the
     readouts the viewer is actually asked to take in. */
  --hud-sanction: calc(var(--hud-frame-h) * 0.065);

  /* Title-safe insets: 5% action-safe / 10% title-safe. The old fixed 18/28px was fine for YouTube
     and wrong for a venue screen with overscan. */
  --hud-safe-x: calc(var(--hud-frame-h) * 0.033);
  --hud-safe-y: calc(var(--hud-frame-h) * 0.028);

  /* Vertical space the upper-left identity block RESERVES, for surfaces that stack their own
     content beneath it (the standings column, the overlay's leaderboard).
     A token rather than a number at each site: the block grew from one row to four when the LIVE
     badge became event + matchup + clock + chip, and the standings column — still padded for the
     old single-row banner — ended up drawn straight through the race clock. Anything placed below
     the block offsets by this. */
  --hud-identity-h: calc(var(--hud-frame-h) * 0.226);
}

/* ---- shared plate ---------------------------------------------------------------------------
 * A boat cam points at the sky: white text over bright water disappears. Every element sits on a
 * plate or carries an outline — never bare text over the picture. */
.hud-plate {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
}

.hud-num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* ---- upper left: who is racing --------------------------------------------------------------- */
#identity {
  top: var(--hud-safe-y);
  left: var(--hud-safe-x);
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

#identity .idRow { display: flex; align-items: center; gap: 10px; padding: 7px 14px; }

#eventName {
  font-size: var(--hud-event);
  font-weight: 700;
  letter-spacing: 0.06em;
}
/* The simulated marker is a DESCRIPTION of the data source, never a behavioural branch. */
/* "(Simulated)" reads as part of the event's title, at the end of it — not a chip. A boxed badge
   beside the name looked like something the competition had been awarded; the parenthesis reads as
   what it is, a qualification of the name it follows. Lighter and slightly smaller so it recedes
   behind the event, and never bold: it describes the data, it is not part of the identity. */
#eventName .sim {
  margin-left: 0.4em;
  font-size: 0.78em;
  font-weight: 500;
  opacity: 0.78;
}

#matchup { font-size: var(--hud-team); font-weight: 600; }
#matchup .vs { opacity: 0.6; margin: 0 4px; font-weight: 500; }
/* The race's own name, ahead of the sides. Dimmed: it identifies the race, the teams are the
   story — and it must not compete with the two nations for the eye. */
#matchup .raceNo { opacity: 0.75; margin-right: 8px; font-variant-numeric: tabular-nums; }

#raceBox { display: flex; align-items: baseline; gap: 12px; padding: 6px 16px; }
#raceClock {
  font-size: var(--hud-race-clock);
  font-weight: 800;
  line-height: 1.02;
  color: var(--vr-clock-racing);
}
#raceBox.pre #raceClock { color: var(--vr-clock-countdown); }
#raceBox.run #raceClock { color: var(--vr-clock-racing); }
#raceBox.done #raceClock { color: var(--vr-clock-finished); }
#raceBox .lbl {
  font-size: var(--hud-unit);
  letter-spacing: 0.16em;
  opacity: 0.7;
  text-transform: uppercase;
}

/* NO SIGNAL — a statement about the DATA (nothing has arrived for 43 s), not a liveness claim, so
   it survives the no-mode-word rule. An unlit, slowly breathing lamp reads as "nothing is
   arriving" from across a gallery.
   The selectors are ID+ID deliberately: `#identity .idRow` above is (1,1,0) and would otherwise
   beat a bare `#signalChip` (1,0,0), leaving an empty chip permanently on the picture. */
#identity #signalChip,
#identity #ageChip { display: none; }
#identity #signalChip.on { display: flex; align-items: center; gap: 9px; }
#identity #ageChip.on { display: block; }
#signalChip { align-items: center; gap: 9px; padding: 5px 13px; font-size: var(--hud-unit); }
#signalChip .dot {
  width: 12px; height: 12px; border-radius: 50%;
  background: #7a7a7a; animation: hud-nosignal 1.6s ease-in-out infinite;
}
@keyframes hud-nosignal { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* The AGE chip is for OPERATORS only (?ops=1) — the delay they calibrate against. Never on a
   viewer stream: there the timestamp is the whole disclosure. */
#ageChip { padding: 5px 13px; font-size: var(--hud-unit); opacity: 0.85; }

/* ---- bottom row: when, and whom ------------------------------------------------------------- */
#bottomBar {
  left: 0; right: 0;
  bottom: var(--hud-safe-y);
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 16px;
  padding: 0 var(--hud-safe-x);
  z-index: 7;
}

#stamp {
  flex: 0 0 auto;
  /* Padding in EMs, so the plate grows with the type it wraps. It was 7px/16px around 21px text;
     the same fixed numbers around 43px text read as a label crammed into a box. */
  padding: 0.33em 0.7em;
  font-size: var(--hud-stamp);
  font-weight: 600;
  /* Tabular figures AND a fixed-width offset, or the ticking tenths digit reflows the whole row. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  white-space: nowrap;
}

/* The subject boat: bib chip, then team, then sail — then the numbers. */
#boatBar { flex: 0 0 auto; display: none; align-items: center; gap: 14px; padding: 6px 16px; }
#boatBar.on { display: flex; }
#boatBar .fields { display: flex; align-items: center; gap: 14px; }
/* An explicit rule between fields. Bib, sail and speed are all numbers; without a separator
   "▌7 Japan 2 9.4 kn" reads as one run of digits — the graphic form of the two-adjacent-numbers
   rule that governs commentary prose. */
#boatBar .fields > * + * { border-left: 1px solid var(--panel-edge); padding-left: 14px; }
#boatBar .val { font-size: var(--hud-value); font-weight: 700; font-variant-numeric: tabular-nums; }
#boatBar .who { font-size: var(--hud-team); font-weight: 600; display: flex; align-items: center; gap: 9px; }

/* THE BIB IS A CHIP, never a text node beside the team name — the hard boundary is what stops the
   digits running together. Its colour is the team's own, from event data. */
.bibChip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.9em;
  padding: 2px 8px;
  border-radius: 5px;
  border: 2px solid rgba(255, 255, 255, 0.85);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.25;
}

/* A bib whose CODE would only repeat the team name beside it goes up as a colour swatch: the colour
   is what distinguishes the team on the water, and a team is identified by its three-letter code —
   never by the number printed on the physical vest. Narrower than a chip carrying text, so it reads
   as a mark of colour rather than an empty box someone forgot to fill. */
.bibChipBlank {
  min-width: 0.9em;
  padding: 2px 0;
}

/* ---- upper right: the conditions ------------------------------------------------------------- */
#wind {
  top: var(--hud-safe-y);
  right: var(--hud-safe-x);
  z-index: 7;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 9px 12px 8px;
}
#wind.on { display: flex; }
#wind .wlbl { font-size: var(--hud-unit); letter-spacing: 0.16em; opacity: 0.65; }
#wind .wread { font-size: var(--hud-value); font-weight: 700; font-variant-numeric: tabular-nums; }
/* The weather credit — a licence obligation (Open-Meteo is CC BY 4.0), and it travels WITH the block.
   Its TEXT names whoever actually supplied the reading, filled at render time (format.js
   `weatherCredit`); it is never a constant, because crediting the wrong party is worse than the
   obligation it would be discharging. Sized off `--hud-credit`, the one thing allowed below the
   readability floor — see the token for why. Empty when the source is unknown, and the block simply
   has no credit line rather than a guess. */
#wind .wcredit { font-size: var(--hud-credit); opacity: 0.55; letter-spacing: 0.02em; }
#wind .wcredit:empty { display: none; }

/* ---- lower right: whose broadcast, and under whose authority --------------------------------- */
/* The corner is a COLUMN of two plates: the sanctioning authority's mark above our own. Both hug
   the same right edge, so the pair reads as one block rather than as a mark with something parked
   beside it. `#sanction` is empty — and therefore absent — unless the event declares one
   (`presentation.sanctionMark`); nothing here names an organisation. */
#markStack {
  flex: 0 0 auto;
  margin-left: auto;          /* the whole column is hard right, as the mark alone used to be */
  display: flex;
  flex-direction: column;
  align-items: flex-end;      /* each plate is sized to its own mark, both flush right */
  gap: calc(var(--hud-frame-h) * 0.007);
}
#logo {
  flex: 0 0 auto;
  margin-left: auto;          /* always the last thing in the row, hard against the safe margin */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 15px;
  gap: calc(var(--hud-frame-h) * 0.008);
}
/* The approved transparent ViewRegatta lockup is an indivisible asset.  In particular, its
   white slit between the red and green sails is part of the mark, not an optional CSS border. */
#logo .vr-lockup { display: block; height: calc(var(--hud-frame-h) * 0.056); width: auto;
  max-width: min(270px, 18vw); object-fit: contain; }
#logo .product-status {
  display: none;
  align-items: center;
  min-height: calc(var(--hud-frame-h) * 0.031);
  padding: 0 calc(var(--hud-frame-h) * 0.008);
  border: 1px solid rgba(255,255,255,0.48);
  border-radius: calc(var(--hud-frame-h) * 0.006);
  color: #fff;
  font-size: var(--hud-min);
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.12em;
}
#logo .product-status.on { display: flex; }

/* The sanctioning body's mark, above ours. WHITE ground, because the artwork is somebody else's
   copyright and is supplied in colour only: recolouring it to suit our dark plate is the one thing
   every brand manual here forbids outright, so the PLATE changes instead of the mark — the same
   treatment the gate apron gives a supplier's. No caption and no relationship text; the mark stands
   alone (docs/streamed-picture-style-guide.md §7). */
#sanction {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--hud-frame-h) * 0.008) calc(var(--hud-frame-h) * 0.012);
}
/* An event that declares no sanctioning body leaves the element empty — and an empty plate hanging
   over the mark would read as artwork that failed to arrive. */
#sanction:empty { display: none; }
#sanction.light { background: rgba(255, 255, 255, 0.94); border-color: rgba(255, 255, 255, 0.6); }
/* WHOLE and uniformly scaled from the artwork's own aspect — `width: auto` is the rule, not a
   default: a height with a fixed width is a stretched logotype. */
#sanction img { height: var(--hud-sanction); width: auto; display: block; }
/* The fallback when the artwork will not load: the organisation's NAME, never a redrawn mark. */
#sanction .name { font-size: var(--hud-min); font-weight: 700; letter-spacing: 0.04em; }
#sanction.light .name { color: #15314a; }
