/* Cargostrife TV - broadcast overlay furniture.
 *
 * ONE IMPLEMENTATION, TWO HOSTS. It mounts over the <video> on tv.html today,
 * and over the game itself on the stream box when the channel goes live. So
 * nothing here may assume a page around it: no body styles, no fixed pixel
 * sizes, every measurement relative to the container.
 *
 * SCALE. --u is one percent of the container width, set by the script on every
 * resize. A lower third that reads correctly in a 700px web player AND in a
 * 1920px broadcast is the whole reason for it; a px anywhere in this file is a
 * bug at one size or the other.
 *
 * COLOUR. --team is the company being watched, straight from the payload, and
 * every accent reads it. It transitions, so a cut between companies carries the
 * livery change instead of snapping.
 */

.cstv {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  font-family: "Barlow Condensed", "Arial Narrow", system-ui, sans-serif;
  color: var(--ink);
  --u: 8px;
  --ink: #eaf1f9;
  --dim: #93a3b8;
  --ground: rgba(8, 12, 17, 0.86);
  --edge: rgba(126, 150, 180, 0.22);
  --team: #5aa9e6;
  --safe: calc(var(--u) * 3.2);
}

.cstv * { box-sizing: border-box; margin: 0; }

.cstv .mono {
  font-family: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ---- zones ------------------------------------------------------------- */
.cstv .z { position: absolute; display: flex; }
.cstv .z-ident { top: var(--safe); left: var(--safe); }
.cstv .z-state { top: var(--safe); right: var(--safe); }
.cstv .z-table { top: 50%; right: var(--safe); transform: translateY(-50%); }
/* THE LOWER THIRD AND THE COMMENTARY SHARE THE BOTTOM AND MUST NOT FIGHT FOR
 * IT. Centred subtitles over a bottom-left name plate looked right on an empty
 * frame and clipped the income figure the moment both were up. They sit side
 * by side instead: who on the left, what the desk is saying on the right. The
 * widths are deliberately under half each so a long company name and a long
 * line of commentary still clear each other. */
.cstv .z-lower { left: var(--safe); max-width: 47%; }
.cstv .z-say   { right: var(--safe); width: 44%; justify-content: flex-end; }

/* With nothing beside it - a break package - the commentary takes the middle,
 * which is where a caption belongs when it is the only thing on screen. */
.cstv .z-say.solo { right: auto; left: 50%; margin-left: -29%; width: 58%;
                    justify-content: center; }
.cstv .z-break { inset: 0; }

/* The status bar the game draws along the very bottom carries the date and the
 * live market multipliers, and it is deliberately NOT cropped - so the lower
 * third and the subtitle sit above it rather than over it. */
.cstv .z-lower, .cstv .z-say { bottom: calc(var(--safe) + var(--u) * 2.4); }

/* ---- shared ------------------------------------------------------------ */
.cstv .card {
  background: var(--ground);
  border: 1px solid var(--edge);
  -webkit-backdrop-filter: blur(calc(var(--u) * 0.5)) saturate(1.1);
  backdrop-filter: blur(calc(var(--u) * 0.5)) saturate(1.1);
}

/* ---- ident ------------------------------------------------------------- */
.cstv .ident { display: flex; align-items: stretch; }
.cstv .ident .mark {
  background: var(--team);
  color: #06090d;
  font-weight: 700;
  font-size: calc(var(--u) * 1.5);
  letter-spacing: 0.1em;
  padding: 0 calc(var(--u) * 0.9);
  display: flex;
  align-items: center;
  transition: background 600ms ease;
}
.cstv .ident .body { padding: calc(var(--u) * 0.5) calc(var(--u) * 1.1) calc(var(--u) * 0.6); }
.cstv .ident .world {
  font-weight: 600;
  font-size: calc(var(--u) * 1.45);
  line-height: 1.15;
  white-space: nowrap;
}
.cstv .ident .bar {
  margin-top: calc(var(--u) * 0.42);
  height: calc(var(--u) * 0.2);
  background: rgba(255, 255, 255, 0.14);
  position: relative;
  overflow: hidden;
}
.cstv .ident .bar i {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--team);
  transition: width 900ms ease, background 600ms ease;
}
.cstv .ident .prog {
  margin-top: calc(var(--u) * 0.34);
  font-size: calc(var(--u) * 0.85);
  letter-spacing: 0.1em;
  color: var(--dim);
}

/* ---- live state -------------------------------------------------------- */
.cstv .state {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 0.55);
  padding: calc(var(--u) * 0.5) calc(var(--u) * 0.95);
}
.cstv .state .dot {
  width: calc(var(--u) * 0.6);
  height: calc(var(--u) * 0.6);
  border-radius: 50%;
  background: #ff3b30;
  animation: cstv-pulse 2s ease-in-out infinite;
}
.cstv .state .txt {
  font-weight: 700;
  font-size: calc(var(--u) * 1.05);
  letter-spacing: 0.2em;
}
@keyframes cstv-pulse { 50% { opacity: 0.25; } }

/* ---- lower third ------------------------------------------------------- */
.cstv .lower { width: 100%; }
.cstv .lower .strap {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--u) * 0.55);
  background: var(--team);
  color: #06090d;
  padding: calc(var(--u) * 0.24) calc(var(--u) * 0.85);
  font-weight: 700;
  font-size: calc(var(--u) * 0.98);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: background 600ms ease;
}
.cstv .lower .main {
  background: var(--ground);
  border: 1px solid var(--edge);
  border-left: calc(var(--u) * 0.3) solid var(--team);
  padding: calc(var(--u) * 0.7) calc(var(--u) * 1.3) calc(var(--u) * 0.85);
  transition: border-color 600ms ease;
}
.cstv .lower .who {
  font-weight: 700;
  font-size: calc(var(--u) * 3.1);
  line-height: 1;
  text-wrap: balance;
}
.cstv .lower .meta {
  margin-top: calc(var(--u) * 0.55);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 0.5);
  flex-wrap: wrap;
}
.cstv .chip {
  display: inline-flex;
  align-items: baseline;
  gap: calc(var(--u) * 0.3);
  border: 1px solid var(--edge);
  padding: calc(var(--u) * 0.2) calc(var(--u) * 0.6);
  font-size: calc(var(--u) * 1.05);
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1.3;
}
.cstv .chip .k {
  font-size: calc(var(--u) * 0.78);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
}
.cstv .chip.tier { border-color: transparent; color: #06090d; font-weight: 700; }
.cstv .chip.human { background: var(--team); color: #06090d; border-color: transparent; }
.cstv .chip.ai { color: var(--dim); }

/* The figures row. Labels small and quiet, numbers large and mono, because a
 * viewer reads the number and only glances at what it is called. Tabular
 * figures matter here more than anywhere: cash ticks while it is on screen and
 * proportional digits would make the whole row shuffle sideways. */
.cstv .figs {
  margin-top: calc(var(--u) * 0.6);
  padding-top: calc(var(--u) * 0.55);
  border-top: 1px solid rgba(126, 150, 180, 0.16);
  display: flex;
  gap: calc(var(--u) * 1.8);
  flex-wrap: wrap;
}
.cstv .fig { display: flex; flex-direction: column; gap: calc(var(--u) * 0.12); }
.cstv .fig .k {
  font-size: calc(var(--u) * 0.75);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
}
.cstv .fig .v { font-size: calc(var(--u) * 1.5); font-weight: 600; line-height: 1; }
.cstv .fig .v i { font-style: normal; color: var(--dim); font-size: 0.62em; }
.cstv .fig .v.up { color: #6ee7a0; }
.cstv .fig .v.down { color: #f8909a; }

/* ---- standings --------------------------------------------------------- */
.cstv .table { min-width: calc(var(--u) * 30); padding: calc(var(--u) * 0.9) 0 calc(var(--u) * 0.5); }
.cstv .table h4 {
  font-weight: 700;
  font-size: calc(var(--u) * 1.05);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 0 calc(var(--u) * 1.1) calc(var(--u) * 0.7);
  color: var(--dim);
}
.cstv .row {
  display: grid;
  grid-template-columns: calc(var(--u) * 2.2) calc(var(--u) * 0.45) 1fr auto;
  align-items: center;
  gap: calc(var(--u) * 0.55);
  padding: calc(var(--u) * 0.34) calc(var(--u) * 1.1);
  font-size: calc(var(--u) * 1.28);
  line-height: 1.25;
}
.cstv .row + .row { border-top: 1px solid rgba(126, 150, 180, 0.1); }
.cstv .row .pos { color: var(--dim); font-weight: 600; text-align: right; }
.cstv .row .swatch { width: calc(var(--u) * 0.45); height: calc(var(--u) * 1.1); }
.cstv .row .nm { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .row .pts { font-weight: 600; }
.cstv .row.me { background: rgba(255, 255, 255, 0.06); }
.cstv .row.bot .nm { color: var(--dim); }

/* ---- the vehicle breakdown --------------------------------------------- */
/* Shares the right-hand zone with the standings, which yield to it. Built as
 * a label/value ladder rather than the chip row the lower third uses, because
 * these are six related figures about one thing and a reader scans them down
 * a column. */
.cstv .veh { min-width: calc(var(--u) * 27); padding: calc(var(--u) * 0.9) 0 calc(var(--u) * 0.7); }
.cstv .veh h4 {
  font-weight: 700;
  font-size: calc(var(--u) * 0.95);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--team);
  padding: 0 calc(var(--u) * 1.1);
  transition: color 600ms ease;
}
.cstv .veh .vname {
  font-size: calc(var(--u) * 1.85);
  font-weight: 700;
  line-height: 1.1;
  padding: calc(var(--u) * 0.22) calc(var(--u) * 1.1) calc(var(--u) * 0.6);
}
.cstv .vload { padding: 0 calc(var(--u) * 1.1) calc(var(--u) * 0.7); }
.cstv .vbar {
  height: calc(var(--u) * 0.34);
  background: rgba(255, 255, 255, 0.13);
  position: relative;
  overflow: hidden;
  margin-bottom: calc(var(--u) * 0.28);
}
.cstv .vbar i { position: absolute; inset: 0 auto 0 0; background: var(--team);
                transition: width 700ms ease, background 600ms ease; }
.cstv .vload span { font-size: calc(var(--u) * 0.95); color: var(--dim);
                    letter-spacing: 0.04em; }
.cstv .vfigs { border-top: 1px solid rgba(126, 150, 180, 0.14); }
.cstv .vrow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: calc(var(--u) * 1.2);
  padding: calc(var(--u) * 0.33) calc(var(--u) * 1.1);
}
.cstv .vrow + .vrow { border-top: 1px solid rgba(126, 150, 180, 0.08); }
.cstv .vrow .k { font-size: calc(var(--u) * 0.98); color: var(--dim); font-weight: 600; }
.cstv .vrow .v { font-size: calc(var(--u) * 1.28); font-weight: 600; }
.cstv .vrow .v.up { color: #6ee7a0; }
.cstv .vrow .v.down { color: #f8909a; }

/* ---- the rundown ------------------------------------------------------- */
/* A break is FURNITURE OVER THE LIVE GAME, never a cut to a card: the world
 * keeps running behind it, which is what makes it read as a broadcast rather
 * than a pause. So the zone is inset rather than full-bleed and the board
 * floats in it with the map still visible around the edges. */
.cstv .z-segment { inset: 0; align-items: center; justify-content: center;
                   pointer-events: none; }
.cstv .segwrap { width: 72%; max-height: 84%; display: flex;
                 align-items: center; justify-content: center; }
.cstv .segwrap.hour { width: 84%; }
.cstv .seg { width: 100%; padding: calc(var(--u) * 1.3) 0 calc(var(--u) * 1.1); }
.cstv .seg .sgeye {
  font-size: calc(var(--u) * 0.78);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--team);
  font-weight: 700;
  padding: 0 calc(var(--u) * 1.6);
  transition: color 600ms ease;
}
.cstv .seg h2 {
  font-size: calc(var(--u) * 2.9);
  font-weight: 700;
  line-height: 1.04;
  padding: calc(var(--u) * 0.24) calc(var(--u) * 1.6) 0;
}
.cstv .seg .sgsub {
  font-size: calc(var(--u) * 1.02);
  color: var(--dim);
  padding: calc(var(--u) * 0.1) calc(var(--u) * 1.6) calc(var(--u) * 0.7);
}

/* one row per company: rank, name, figure, a bar, and the line that makes it
 * a story rather than a number */
.cstv .seg .sgrows { border-top: 1px solid rgba(126, 150, 180, 0.16); }
.cstv .seg .sgrow {
  display: grid;
  grid-template-columns: calc(var(--u) * 2.2) 1fr auto;
  grid-template-areas: "p n v" "p b b" "p d d" "p s s";
  align-items: baseline;
  gap: calc(var(--u) * 0.12) calc(var(--u) * 0.8);
  padding: calc(var(--u) * 0.5) calc(var(--u) * 1.6);
}
.cstv .seg .sgrow + .sgrow { border-top: 1px solid rgba(126, 150, 180, 0.09); }
.cstv .seg .sgp { grid-area: p; font-size: calc(var(--u) * 1.3); color: var(--dim);
                  font-weight: 700; align-self: center; }
.cstv .seg .sgn { grid-area: n; font-size: calc(var(--u) * 1.5); font-weight: 700;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .seg .sgv { grid-area: v; font-size: calc(var(--u) * 1.5); font-weight: 700;
                  color: var(--team); transition: color 600ms ease; }
.cstv .seg .sgbar { grid-area: b; padding-top: calc(var(--u) * 0.12); }
.cstv .seg .sgd { grid-area: d; font-size: calc(var(--u) * 0.86); color: var(--dim); }

/* the hour carries the three boards that produced each rating */
.cstv .seg .sgb { grid-area: s; display: flex; gap: calc(var(--u) * 1.1);
                  padding-top: calc(var(--u) * 0.18); }
.cstv .seg .sgb span { font-size: calc(var(--u) * 0.92); font-weight: 600;
                       font-variant-numeric: tabular-nums; }
.cstv .seg .sgb i { font-style: normal; color: var(--dim); font-weight: 600;
                    font-size: 0.78em; letter-spacing: 0.12em;
                    text-transform: uppercase; margin-right: 0.45em; }

/* ---- the desk ---------------------------------------------------------- */
/* Four seats. The portraits are being drawn; each seat is a monogram plate in
 * that host's colour, in exactly the place the portrait will occupy, so the
 * layout is already right when the art lands. */
.cstv .sgdesk {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: calc(var(--u) * 0.8);
  padding: calc(var(--u) * 0.9) calc(var(--u) * 1.6) 0;
  margin-top: calc(var(--u) * 0.5);
  border-top: 1px solid rgba(126, 150, 180, 0.16);
}
.cstv .sgdesk .seat { text-align: center; min-width: 0; }
.cstv .sgdesk .face {
  height: calc(var(--u) * 4.6);
  border-radius: 2px;
  background: linear-gradient(160deg,
              color-mix(in srgb, var(--seat) 30%, transparent),
              rgba(10, 14, 20, 0.55));
  border: 1px solid color-mix(in srgb, var(--seat) 45%, transparent);
  display: flex; align-items: center; justify-content: center;
}
.cstv .sgdesk .face span {
  font-size: calc(var(--u) * 1.5);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--seat);
}
.cstv .sgdesk .who { font-size: calc(var(--u) * 0.92); font-weight: 700;
                     padding-top: calc(var(--u) * 0.28);
                     white-space: nowrap; overflow: hidden;
                     text-overflow: ellipsis; }
.cstv .sgdesk .beat { font-size: calc(var(--u) * 0.72); color: var(--dim);
                      letter-spacing: 0.14em; text-transform: uppercase; }

/* ---- the company mark -------------------------------------------------- */
/* Drawn on a canvas by logo.js after insertion. Sized in --u like everything
 * else so it scales with the frame, and it simply stays blank if logo.js has
 * not loaded - the lower third never depends on it. */
.cstv .lower .clogo {
  width: calc(var(--u) * 3.4);
  height: calc(var(--u) * 3.4);
  flex: 0 0 auto;
  align-self: center;
  margin: 0 calc(var(--u) * 0.7) 0 calc(var(--u) * 0.2);
  border-radius: 2px;
}

/* ---- their prices ------------------------------------------------------ */
/* The personal board carries a fourth column the world board does not: the
 * EDGE over the world price, which is the whole reason the panel exists. */
.cstv .mkt2 .mrow { grid-template-columns: calc(var(--u) * 7) 1fr calc(var(--u) * 3.4) calc(var(--u) * 4.2); }
.cstv .mkt2 .pmw { font-size: calc(var(--u) * 0.85); color: #6ee7a0; text-align: right; }

/* ---- the board breakdown ----------------------------------------------- */
/* Why the leader is the leader: the three boards score.nut actually ranks on,
 * under the same head row the plain standings panel uses. */
.cstv .bd .bdrow { padding: calc(var(--u) * 0.42) 0 calc(var(--u) * 0.5); }
.cstv .bd .bdrow + .bdrow { border-top: 1px solid rgba(126, 150, 180, 0.12); }
.cstv .bd .bdhead {
  display: grid;
  grid-template-columns: calc(var(--u) * 1.6) calc(var(--u) * 0.7) 1fr auto;
  align-items: center;
  gap: calc(var(--u) * 0.6);
  padding: 0 calc(var(--u) * 1.1) calc(var(--u) * 0.3);
}
.cstv .bd .bdhead .nm {
  font-weight: 600;
  font-size: calc(var(--u) * 1.15);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cstv .bd .bdrow.me .bdhead .nm { color: var(--team); }
.cstv .bd .bdrow.bot .bdhead .nm { opacity: 0.72; }
.cstv .bd .bdhead .pts { font-size: calc(var(--u) * 1.25); font-weight: 700; }

/* three measures on one baseline, so the SHAPE of a company reads at a glance */
.cstv .bd .bdbars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(var(--u) * 0.7);
  padding: 0 calc(var(--u) * 1.1);
}
.cstv .bd .bdcell { min-width: 0; }
.cstv .bd .bdlab {
  display: block;
  font-size: calc(var(--u) * 0.66);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cstv .bd .bdval {
  display: block;
  font-size: calc(var(--u) * 0.92);
  font-weight: 600;
  color: var(--dim);
  padding-top: calc(var(--u) * 0.08);
}
/* the board this company LEADS - the actual answer to 'why' */
.cstv .bd .bdcell.top .bdlab { color: #6ee7a0; }
.cstv .bd .bdcell.top .bdval { color: #6ee7a0; font-weight: 700; }

.cstv .bd .bdfoot {
  font-size: calc(var(--u) * 0.72);
  color: var(--dim);
  padding: calc(var(--u) * 0.5) calc(var(--u) * 1.1) 0;
  border-top: 1px solid rgba(126, 150, 180, 0.12);
  margin-top: calc(var(--u) * 0.35);
}

/* ---- the transit map ---------------------------------------------------- */
/* The canvas has a fixed backing store and is scaled by CSS, so the diagram
 * is drawn once in logical pixels and reads the same on a 1080p burn-in and
 * in the small web player. */
.cstv .tmapwrap {
  padding: calc(var(--u) * 0.15) calc(var(--u) * 0.7) 0;
}
.cstv .tmap {
  display: block;
  width: 100%;
  height: auto;
}
.cstv .tlegs {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--u) * 0.75);
  padding: calc(var(--u) * 0.35) calc(var(--u) * 1.1) calc(var(--u) * 0.15);
}
.cstv .tleg {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--u) * 0.3);
  font-size: calc(var(--u) * 0.9);
  color: var(--dim);
}
.cstv .tleg i {
  width: calc(var(--u) * 0.85);
  height: calc(var(--u) * 0.28);
  border-radius: calc(var(--u) * 0.14);
}
.cstv .tleg b { color: #dfe7f1; }

/* THE MAP CARD'S FOOTERS. The footer rule above is scoped `.bd .bdfoot`,
 * and a map is an `.insp.card`, not a `.bd` - so the network map's own
 * "Busiest:" line has never had any styling and has been rendering at
 * full card size. Found by putting the card in front of a browser rather
 * than by reading the CSS. Same treatment, scoped to the map card. */
.cstv .tmapcard .bdfoot {
  font-size: calc(var(--u) * 0.72);
  color: var(--dim);
  padding: calc(var(--u) * 0.5) calc(var(--u) * 1.1) 0;
  border-top: 1px solid rgba(126, 150, 180, 0.12);
  margin-top: calc(var(--u) * 0.35);
}

/* THE GUIDE LINE ON THE HEALTH MAP. The legend names the bands; this says
 * what the bands ARE. It sits ABOVE the ordinary footer and carries no top
 * rule of its own, so guide and figure read as one block rather than two
 * separate footers stacked - which is what they looked like at first.
 * Slightly brighter than a normal footer because it is the one line on the
 * card a viewer is meant to actually read rather than glance at. */
.cstv .tmapcard .bdfoot.tguide {
  border-top: none;
  margin-top: 0;
  padding-bottom: calc(var(--u) * 0.1);
  color: #b8c6d8;
  line-height: 1.35;
}

/* ---- inspections ------------------------------------------------------- */
/* One card shape for the town, industry, stakeholder, brand and market
 * panels. They rotate through the same slot, so sharing the frame is what
 * makes the rotation read as one graphics package rather than five unrelated
 * boxes taking turns. */
.cstv .insp { width: calc(var(--u) * 30); padding: calc(var(--u) * 0.9) 0 calc(var(--u) * 0.8); }
.cstv .insp h4 {
  font-weight: 700;
  font-size: calc(var(--u) * 0.95);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--team);
  padding: 0 calc(var(--u) * 1.1);
  transition: color 600ms ease;
}
.cstv .insp .iname {
  font-size: calc(var(--u) * 1.95);
  font-weight: 700;
  line-height: 1.08;
  padding: calc(var(--u) * 0.24) calc(var(--u) * 1.1) 0;
}
.cstv .insp .isub {
  font-size: calc(var(--u) * 0.98);
  color: var(--dim);
  padding: calc(var(--u) * 0.12) calc(var(--u) * 1.1) calc(var(--u) * 0.6);
}
.cstv .insp .sect {
  font-size: calc(var(--u) * 0.8);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
  padding: calc(var(--u) * 0.55) calc(var(--u) * 1.1) calc(var(--u) * 0.3);
  border-top: 1px solid rgba(126, 150, 180, 0.14);
  margin-top: calc(var(--u) * 0.3);
}
.cstv .insp .big {
  font-size: calc(var(--u) * 3.2);
  font-weight: 600;
  line-height: 1;
  padding: calc(var(--u) * 0.3) calc(var(--u) * 1.1) 0;
}
.cstv .insp .big.up { color: #6ee7a0; }
.cstv .insp .biglab {
  font-size: calc(var(--u) * 0.88);
  color: var(--dim);
  padding: 0 calc(var(--u) * 1.1) calc(var(--u) * 0.55);
}

/* label / value ladder, shared */
.cstv .rws { border-top: 1px solid rgba(126, 150, 180, 0.14); }
.cstv .rw {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: calc(var(--u) * 1);
  padding: calc(var(--u) * 0.3) calc(var(--u) * 1.1);
}
.cstv .rw + .rw { border-top: 1px solid rgba(126, 150, 180, 0.08); }
.cstv .rw .k { font-size: calc(var(--u) * 0.95); color: var(--dim); font-weight: 600; }
.cstv .rw .v { font-size: calc(var(--u) * 1.2); font-weight: 600; }
.cstv .rw .v.up { color: #6ee7a0; }
.cstv .rw .v.down { color: #f8909a; }

/* a measure bar, shared by needs, shares, awareness and the market board */
.cstv .mbar {
  height: calc(var(--u) * 0.3);
  background: rgba(255, 255, 255, 0.12);
  position: relative;
  overflow: hidden;
  margin: calc(var(--u) * 0.1) 0;
}
.cstv .mbar i {
  position: absolute; inset: 0 auto 0 0;
  background: var(--team);
  transition: width 700ms ease, background 600ms ease;
}
.cstv .mbar.ok i    { background: #4ade80; }
.cstv .mbar.short i { background: #fbbf24; }
.cstv .mbar.warm i  { background: #fbbf24; }
.cstv .mbar.hot i   { background: #fb7185; }

/* stakeholders: name, share bar, holding, and what it paid */
.cstv .hold { border-top: 1px solid rgba(126, 150, 180, 0.14); }
.cstv .hrow {
  display: grid;
  grid-template-columns: 1fr calc(var(--u) * 6) auto;
  grid-template-areas: "n b p" "n b m";
  align-items: center;
  gap: 0 calc(var(--u) * 0.7);
  padding: calc(var(--u) * 0.42) calc(var(--u) * 1.1);
}
.cstv .hrow + .hrow { border-top: 1px solid rgba(126, 150, 180, 0.08); }
.cstv .hname { grid-area: n; font-weight: 600; font-size: calc(var(--u) * 1.15);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .hbar  { grid-area: b; }
.cstv .hpts  { grid-area: p; font-size: calc(var(--u) * 1.05); font-weight: 600;
               text-align: right; }
.cstv .hpts i { font-style: normal; color: var(--dim); font-size: 0.72em; }
.cstv .hpaid { grid-area: m; font-size: calc(var(--u) * 0.9); color: #6ee7a0;
               text-align: right; }

/* town needs */
.cstv .nrow {
  display: grid;
  grid-template-columns: calc(var(--u) * 7) 1fr auto;
  align-items: center;
  gap: calc(var(--u) * 0.6);
  padding: calc(var(--u) * 0.26) calc(var(--u) * 1.1);
}
.cstv .nrow .nk { font-size: calc(var(--u) * 0.95); font-weight: 600;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .nrow .nv { font-size: calc(var(--u) * 0.95); color: var(--dim); }

/* industry cargo table */
.cstv .cgs { border-top: 1px solid rgba(126, 150, 180, 0.14); }
.cstv .chd, .cstv .crow {
  display: grid;
  grid-template-columns: 1fr auto calc(var(--u) * 4) calc(var(--u) * 3);
  gap: calc(var(--u) * 0.5);
  align-items: baseline;
  padding: calc(var(--u) * 0.26) calc(var(--u) * 1.1);
}
.cstv .chd {
  font-size: calc(var(--u) * 0.72);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
}
.cstv .chd span:not(:first-child), .cstv .crow .cp,
.cstv .crow .ct, .cstv .crow .fx { text-align: right; }
.cstv .crow { font-size: calc(var(--u) * 1.05); font-weight: 600; }
.cstv .crow .cn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .crow .fx { color: var(--dim); }
.cstv .crow .fx.up { color: #6ee7a0; }
.cstv .crow .ct { color: var(--dim); }

/* market board */
.cstv .mkt { border-top: 1px solid rgba(126, 150, 180, 0.14); }
.cstv .mrow {
  display: grid;
  grid-template-columns: calc(var(--u) * 8) 1fr calc(var(--u) * 3.4);
  align-items: center;
  gap: calc(var(--u) * 0.6);
  padding: calc(var(--u) * 0.28) calc(var(--u) * 1.1);
}
.cstv .mrow .mn { font-size: calc(var(--u) * 1) ; font-weight: 600;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cstv .mrow .mv { font-size: calc(var(--u) * 1.1); font-weight: 600; text-align: right; }
.cstv .mrow .mv.warm { color: #fbbf24; }
.cstv .mrow .mv.hot  { color: #fb7185; }

/* ---- the gallery wipe --------------------------------------------------- */
/* A sports gallery does not cut between graphics. This runs for a third of a
 * second on a CHANGE only - unlike the idle animation that cost a whole core
 * in software rendering, a one-off transition is free. */
.cstv .swipe {
  position: absolute;
  top: 0; bottom: 0; right: 0;
  width: calc(var(--u) * 32);
  background: linear-gradient(90deg, transparent 0%, var(--team) 22%,
                              var(--team) 78%, transparent 100%);
  opacity: 0.85;
  pointer-events: none;
  animation: cstv-swipe 620ms cubic-bezier(.5,0,.2,1) both;
}
@keyframes cstv-swipe {
  0%   { transform: translateX(110%); opacity: 0; }
  35%  { opacity: 0.85; }
  100% { transform: translateX(-115%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .cstv .swipe { display: none; } }

/* ---- commentary -------------------------------------------------------- */
.cstv .say {
  width: 100%;
  padding: calc(var(--u) * 0.6) calc(var(--u) * 1.1);
  border-left: calc(var(--u) * 0.24) solid var(--sp);
  text-align: left;
}
.cstv .say .nm {
  font-weight: 700;
  font-size: calc(var(--u) * 0.92);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sp);
}
.cstv .say .tx {
  margin-top: calc(var(--u) * 0.22);
  font-size: calc(var(--u) * 1.4);
  line-height: 1.32;
  font-weight: 500;
}

/* ---- break package ----------------------------------------------------- */
.cstv .break {
  width: 100%;
  height: 100%;
  background: linear-gradient(160deg, #0a0f16 0%, #070a0e 62%, #0d0a12 100%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 calc(var(--u) * 8);
}
.cstv .break .eyebrow {
  font-weight: 700;
  font-size: calc(var(--u) * 1.15);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--team);
}
.cstv .break h2 {
  margin-top: calc(var(--u) * 0.7);
  font-weight: 700;
  font-size: calc(var(--u) * 4.6);
  line-height: 0.98;
  text-wrap: balance;
}
.cstv .break .sub {
  margin-top: calc(var(--u) * 0.5);
  font-size: calc(var(--u) * 1.5);
  color: var(--dim);
}
.cstv .break .facts {
  margin-top: calc(var(--u) * 2.6);
  display: flex;
  gap: calc(var(--u) * 4);
  flex-wrap: wrap;
}
.cstv .break .fact .k {
  font-weight: 600;
  font-size: calc(var(--u) * 1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
}
.cstv .break .fact .v {
  margin-top: calc(var(--u) * 0.3);
  font-size: calc(var(--u) * 3.4);
  font-weight: 600;
  line-height: 1;
}
.cstv .break .fact .s {
  margin-top: calc(var(--u) * 0.25);
  font-size: calc(var(--u) * 1.05);
  color: var(--dim);
}
.cstv .break .rule {
  margin-top: calc(var(--u) * 2.2);
  height: calc(var(--u) * 0.22);
  width: calc(var(--u) * 12);
  background: var(--team);
}

/* ---- flat: the burn-in variant ------------------------------------------
 * MEASURED, NOT GUESSED. On the stream box there is no GPU, so backdrop-filter
 * blurs a 1920-wide region in software behind every card, and the pulsing LIVE
 * dot forces the whole overlay to recomposite continuously. Together they cost
 * a FULL CORE - WebKit measured at 104% - which took the box to 2.5 of 3 cores
 * and put the CPU budget out of reach. Both are free on the web player, where a
 * real GPU composites them, so this is a variant rather than a deletion.
 *
 * The ground goes more opaque to make up for the lost blur. Over pixel art at
 * broadcast size the difference is close to invisible; the core is not.
 */
.cstv.flat .card {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgba(8, 12, 17, 0.93);
}
.cstv.flat .lower .main { background: rgba(8, 12, 17, 0.93); }
.cstv.flat .state .dot { animation: none; }

/* ---- entrances --------------------------------------------------------- */
.cstv .in-l { animation: cstv-in-l 520ms cubic-bezier(.16,.84,.34,1) both; }
.cstv .in-r { animation: cstv-in-r 520ms cubic-bezier(.16,.84,.34,1) both; }
.cstv .in-u { animation: cstv-in-u 460ms cubic-bezier(.16,.84,.34,1) both; }
.cstv .in-f { animation: cstv-in-f 620ms ease both; }
.cstv .out  { animation: cstv-out 340ms ease both; }

@keyframes cstv-in-l { from { opacity: 0; transform: translateX(calc(var(--u) * -2.2)); } }
@keyframes cstv-in-r { from { opacity: 0; transform: translateX(calc(var(--u) * 2.2)); } }
@keyframes cstv-in-u { from { opacity: 0; transform: translateY(calc(var(--u) * 1.4)); } }
@keyframes cstv-in-f { from { opacity: 0; } }
@keyframes cstv-out  { to   { opacity: 0; transform: translateY(calc(var(--u) * 0.5)); } }

@media (prefers-reduced-motion: reduce) {
  .cstv .in-l, .cstv .in-r, .cstv .in-u, .cstv .in-f, .cstv .out { animation-duration: 1ms; }
  .cstv .state .dot { animation: none; }
}

/* The hourly exchange. Plain type on a plain ground - it sits under a table
   that is already busy, and the only colour is the speaker's own seat. */
.sgtalk{margin:14px 0 0;border-top:1px solid rgba(255,255,255,.10);padding:12px 0 0}
.sgtalk .turn{display:flex;gap:10px;align-items:baseline;margin:0 0 7px}
.sgtalk .turn:last-child{margin-bottom:0}
.sgtalk .tw{flex:0 0 auto;min-width:132px;font:600 11px/1.4 'IBM Plex Mono',monospace;
  letter-spacing:.12em;text-transform:uppercase;color:var(--t,#9fb0c4)}
.sgtalk .tt{flex:1 1 auto;font:500 17px/1.35 'Barlow Condensed',sans-serif;
  color:#e9eff6;letter-spacing:.01em}

/* ---- the cutaway ------------------------------------------------------- */
/* A GRAPHIC OVER GAMEPLAY IS A CAPTION. Every other panel here sits beside the
 * match and lets the eye stay on the trains, which is right for a lower third
 * and wrong for a breakdown: the numbers get glanced at and the segment reads
 * as decoration. So the show stops. This zone is OPAQUE and full bleed, the
 * overlay is burnt into the video, and between them that is the only way this
 * channel can cut away from the picture at all.
 *
 * The director owns when. It flags a window on the segment itself and this
 * simply renders while the flag is up - the clock belongs to the show, not to
 * whichever panel happens to be mounted.
 *
 * NO BLUR AND NO IDLE ANIMATION, deliberately. This composites in software
 * beside a video encoder on three cores, where backdrop-filter and one pulsing
 * dot were measured at a whole core between them. The only motion is the
 * entrance, and the bars are plain divs with a width. */
/* AN EMPTY ZONE MUST NOT PAINT, and this one is the only zone that could.
 * Every zone div is created at mount and lives for the session, so a zone
 * with inset:0 AND a background is an opaque sheet over the whole frame
 * whenever no panel happens to be in it - which is almost always. Shipped
 * that way for a few minutes and the burn-in went black but for the game's
 * own toolbar, because the sheet is the overlay and the toolbar is not.
 * The other inset zones (break, segment) never hit this: they carry no
 * background of their own and paint nothing when empty. */
.cstv .z-full:empty { display: none; }
.cstv .z-full {
  inset: 0;
  align-items: center;
  justify-content: center;
  background: #070b10;
  pointer-events: none;
}
.cstv .fchart {
  width: 78%;
  max-height: 88%;
  display: flex;
  flex-direction: column;
  /* The team colour rides the top edge, so a cutaway still says whose story
   * this is even with no company name on the screen. */
  border-top: calc(var(--u) * 0.3) solid var(--team);
  padding: calc(var(--u) * 1.4) 0 calc(var(--u) * 0.9);
  transition: border-color 600ms ease;
}
.cstv .fchart .fceye {
  font-size: calc(var(--u) * 0.9);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--team);
  font-weight: 700;
  transition: color 600ms ease;
}
.cstv .fchart h2 {
  font-size: calc(var(--u) * 4.2);
  font-weight: 700;
  line-height: 1.02;
  padding-top: calc(var(--u) * 0.2);
}
.cstv .fchart .fcsub {
  font-size: calc(var(--u) * 1.35);
  color: var(--dim);
  padding-bottom: calc(var(--u) * 0.9);
}
.cstv .fchart .fcrows {
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 0.62);
}
/* One row is a four column grid so rank, name and figure share a baseline and
 * the bar spans beneath them. Laid out by grid rather than by margins: these
 * repeat, and a repeated thing whose edges drift is the tell that it was
 * spaced by hand. */
.cstv .fchart .fcrow {
  display: grid;
  grid-template-columns: calc(var(--u) * 2.2) 1fr auto;
  grid-template-areas: "p n v" ". b b" ". d d";
  align-items: baseline;
  column-gap: calc(var(--u) * 0.7);
  padding-bottom: calc(var(--u) * 0.2);
  border-bottom: 1px solid var(--edge);
}
.cstv .fchart .fcp { grid-area: p; color: var(--dim); font-size: calc(var(--u) * 1.3); }
.cstv .fchart .fcn { grid-area: n; font-size: calc(var(--u) * 1.7); font-weight: 600; }
.cstv .fchart .fcv { grid-area: v; font-size: calc(var(--u) * 1.7); font-weight: 700; }
.cstv .fchart .fcd {
  grid-area: d;
  font-size: calc(var(--u) * 0.92);
  color: var(--dim);
  padding-bottom: calc(var(--u) * 0.24);
}
.cstv .fchart .fcbar {
  grid-area: b;
  height: calc(var(--u) * 0.42);
  background: rgba(126, 150, 180, 0.16);
  margin: calc(var(--u) * 0.22) 0 calc(var(--u) * 0.16);
}
.cstv .fchart .fcbar > i {
  display: block;
  height: 100%;
  background: var(--team);
  transition: width 700ms cubic-bezier(0.2, 0.8, 0.2, 1), background 600ms ease;
}
/* The leader is the story. It gets the size, and everything under it is read
 * against it rather than competing with it. */
.cstv .fchart .fcrow.lead .fcn,
.cstv .fchart .fcrow.lead .fcv { font-size: calc(var(--u) * 2.3); }
.cstv .fchart .fcrow.lead .fcbar { height: calc(var(--u) * 0.62); }
.cstv .fchart .fcfoot {
  font-size: calc(var(--u) * 0.82);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dim);
  padding-top: calc(var(--u) * 0.8);
}
