/* TV Wall — laid out once at 1920×1080 and scaled whole to the screen by tv.js, like the
   Warehouse KPI page: every size here is in TV pixels and nothing ever scrolls. Drawn from the
   picture Brad sent: frosted white panels on a pale-blue sky, navy titles, blue and green. */

:root {
  --navy: #13207A;
  --ink: #1C2B45;
  --soft: #4C5F86;
  --blue: #1E88F0;
  --green: #18C98A;
  --glass: rgba(255, 255, 255, .55);
  --glass-in: rgba(255, 255, 255, .5);
  --edge: rgba(255, 255, 255, .85);
  --ground: linear-gradient(170deg, #EAF3FD 0%, #E3EFFC 45%, #DCEBFB 100%);
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; }
body {
  font-family: "Segoe UI Variable Display", "Segoe UI", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  background: var(--ground);
}

.stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1920px;
  height: 1080px;
  transform-origin: 0 0;
  background: var(--ground);
  overflow: hidden;
  visibility: hidden;     /* until tv.js has scaled it */
}
.stage.is-fit { visibility: visible; }
.ground { position: absolute; inset: 0; width: 100%; height: 100%; }
.sweep { fill: #FFFFFF; fill-opacity: .35; }

.board {
  position: absolute;
  left: 78px;
  right: 78px;
  top: 256px;
  height: 606px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
}

.panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  padding: 26px 44px 28px;
  background: var(--glass);
  border: 2px solid var(--edge);
  border-radius: 30px;
  box-shadow: 0 20px 60px rgba(40, 90, 160, .10), inset 0 1px 0 rgba(255, 255, 255, .9);
  backdrop-filter: blur(14px);
}
.panel-head { display: flex; align-items: center; gap: 30px; margin-bottom: 20px; }
.badge {
  width: 136px;
  height: 136px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: none;
}
.badge svg { width: 74px; height: 74px; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.badge-blue { background: radial-gradient(circle at 40% 35%, #E3F0FF, #C9E1FB); }
.badge-blue svg { stroke: var(--blue); }
.badge-green { background: radial-gradient(circle at 40% 35%, #E2FBF1, #C4F1DE); }
.badge-green svg { stroke: var(--green); }
.badge-green svg circle { fill: var(--green); stroke: none; }
h1 { margin: 0; font-size: 52px; font-weight: 800; letter-spacing: -.02em; color: var(--navy); line-height: 1.05; }
.kicker { margin: 8px 0 0; font-size: 22px; font-weight: 600; letter-spacing: .32em; color: #2E54C8; }

/* ── Did You Know? ── */
.fact-box {
  position: relative;
  flex: 1;
  min-height: 0;
  padding: 26px 40px 30px 152px;
  background: var(--glass-in);
  border: 2px solid var(--edge);
  border-radius: 22px;
  display: flex;
  align-items: center;
}
.doc {
  position: absolute;
  left: 14px;
  top: 10px;
  width: 116px;
  height: 116px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: radial-gradient(circle at 40% 35%, #E2FBF1, #CDF4E3);
}
.doc svg { width: 64px; height: 64px; }
.doc rect { fill: var(--green); }
.doc path { stroke: #FFFFFF; stroke-width: 2.2; stroke-linecap: round; fill: none; }
.fact {
  margin: 0;
  font-size: 40px;
  font-weight: 600;
  line-height: 1.32;
  color: var(--navy);
  transition: opacity .6s ease, transform .6s ease;
}
.fact.is-out { opacity: 0; transform: translateY(10px); }
.fact.is-empty { font-size: 28px; font-weight: 500; color: var(--soft); }
.dots { position: absolute; left: 0; right: 0; bottom: 16px; display: flex; justify-content: center; gap: 10px; }
.dots i { width: 10px; height: 10px; border-radius: 50%; background: rgba(30, 136, 240, .22); }
.dots i.is-on { background: var(--blue); }

/* ── Upcoming ── */
.events { list-style: none; margin: 0; padding: 0; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 18px; }
.event {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  align-items: stretch;
  background: var(--glass-in);
  border: 2px solid var(--edge);
  border-radius: 20px;
  overflow: hidden;
}
.when {
  width: 128px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: linear-gradient(160deg, #DCEBFC, #C9E0FA);
  color: var(--blue);
}
.event:nth-child(2) .when { background: linear-gradient(160deg, #D9F7EA, #C2F0DB); color: #10B27A; }
.when .mon { font-size: 20px; font-weight: 800; letter-spacing: .12em; }
.when .day { font-size: 44px; font-weight: 800; line-height: 1; }
.when .dow { font-size: 15px; font-weight: 700; letter-spacing: .1em; opacity: .8; }
.what {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10px 30px;
  border-left: 2px solid rgba(255, 255, 255, .9);
  margin: 14px 0;
}
.what .title { margin: 0; font-size: 32px; font-weight: 800; color: var(--navy); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.what .sub { margin: 4px 0 0; font-size: 22px; color: var(--soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.what .sub b { color: var(--blue); font-weight: 700; }
.event.is-empty .what .title { font-weight: 500; font-size: 26px; color: var(--soft); }
.event.is-empty .when { background: rgba(220, 235, 252, .5); }

/* ══ THE PLANE, across the top ═════════════════════════════════════════════════════════════
   Pisces Central's own plane (web/sky.js draws it), so the CSS below is COPIED from
   web/styles.css (the block that starts "THE PLANE, far off") — keep the two in step. It tows
   the TV's own banners (IT → TV Wall), not the hub's announcements. Sized up after the copy:
   the wall is read from across a room, so the plane is nearer and clearer than the hub's. */
:root { --sans: "Segoe UI", system-ui, sans-serif; }
/* THE PLANE, far off. Everything is sized in em off one font size that follows the window,
   so a wider screen gets a proportionally bigger — never a closer — plane. Its haze is the
   filter: a little less saturated and a little less contrasty than something near. */
.sky-lane { position: absolute; inset: 0; overflow: hidden; }
.sky-flight {
  position: absolute;
  top: var(--sky-top, 5%);
  left: 0;
  transform: translate3d(110vw, 0, 0);
  font-size: clamp(10px, calc(7px + .34vw), 15px);
  opacity: .93;
  filter: saturate(.8) contrast(.88);
  will-change: transform;
}
.sky-bob { display: flex; align-items: center; animation: sky-bob 6.5s ease-in-out infinite alternate; }
.sky-plane { flex: none; width: 3.2em; height: auto; overflow: visible; }
.sky-body, .sky-tailplane { fill: #2d2f33; }
.sky-window { fill: #a9b4bd; }
.sky-wing { fill: #efe3be; }
.sky-strut, .sky-gear { fill: none; stroke: #36383c; stroke-width: .9; stroke-linecap: round; }
.sky-wheel { fill: #1c1d20; }
.sky-prop { fill: rgba(70, 70, 70, .32); transform-box: fill-box; transform-origin: center;
            animation: sky-prop .14s linear infinite; }
.sky-tow { flex: none; width: 4.4em; height: 1.6em; margin-left: -.45em; overflow: visible; }
.sky-tow path { fill: none; stroke: rgba(38, 38, 38, .5); stroke-width: .8;
                vector-effect: non-scaling-stroke; }
/* White cloth, red capitals, a dark lead pole — the look of the real thing. The faint
   vertical seams are the panels a towed banner is sewn from. */
.sky-banner {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  min-height: 1.62em;
  padding: .06em .8em;
  border-left: 2px solid #3a3a3a;
  background:
    repeating-linear-gradient(90deg, transparent 0 1.1em, rgba(0, 0, 0, .05) 1.1em 1.16em),
    var(--cloth, #f4f1eb);
  color: var(--cloth-ink, #a3232b);
  font-family: "Bahnschrift SemiCondensed", "Bahnschrift", "Arial Narrow",
               "Roboto Condensed", var(--sans);
  font-stretch: semi-condensed;
  font-size: 1em;
  font-weight: 700;
  letter-spacing: .07em;
  line-height: 1.2;
  white-space: pre;
  transform-origin: left center;
  animation: sky-flutter 1.9s ease-in-out infinite alternate;
}
.sky-banner.is-caps { text-transform: uppercase; }

/* THE CLOTH — the whole banner's colour, for colour-coding one kind of notice from another —
   and the ink that reads best on it when a run names no colour of its own. The ids are the
   closed list in server/announcement-routes.js and web/sky.js. */
.sky-cloth-white  { --cloth: #f4f1eb; --cloth-ink: #a3232b; }
.sky-cloth-yellow { --cloth: #f6dc5f; --cloth-ink: #1b1c1f; }
.sky-cloth-sky    { --cloth: #cfe4f5; --cloth-ink: #0b3a82; }
.sky-cloth-pink   { --cloth: #f6d0da; --cloth-ink: #8a1538; }
.sky-cloth-mint   { --cloth: #cdeed8; --cloth-ink: #15592f; }
.sky-cloth-navy   { --cloth: #14305e; --cloth-ink: #ffffff; }

/* THE FORMATS a run can carry. Classes, never inline styles: the CSP forbids those, and a
   closed list is what the server stores anyway. Underline and strike share one property, so
   the pair has a rule of its own. */
.fx-b { font-weight: 800; }
.sky-banner .fx-b { font-weight: 900; }
.fx-i { font-style: italic; }
.fx-u { text-decoration-line: underline; }
.fx-x { text-decoration-line: line-through; }
.fx-u.fx-x { text-decoration-line: underline line-through; }
.fx-c-red    { color: #b0232c; }
.fx-c-navy   { color: #0b3a82; }
.fx-c-black  { color: #1b1c1f; }
.fx-c-green  { color: #16753a; }
.fx-c-orange { color: #cc5a07; }
.fx-c-purple { color: #6a2c9e; }
.fx-c-blue   { color: #1766c0; }
.fx-c-white  { color: #ffffff; }
.fx-z-sm { font-size: .78em; }
.fx-z-lg { font-size: 1.3em; }
.fx-z-xl { font-size: 1.65em; }
.fx-f-classic { font-family: Georgia, "Times New Roman", serif; font-stretch: normal;
                letter-spacing: .03em; }
.fx-f-script { font-family: "Segoe Script", "Brush Script MT", "Lucida Handwriting", cursive;
               font-stretch: normal; letter-spacing: 0; }
@keyframes sky-bob { from { transform: translateY(-1.5px); } to { transform: translateY(1.5px); } }
@keyframes sky-prop { 50% { transform: scaleY(.5); } }
@keyframes sky-flutter {
  0%   { transform: skewY(-.8deg) scaleY(.97); }
  50%  { transform: skewY(.3deg) scaleY(1.01); }
  100% { transform: skewY(.9deg) scaleY(.98); }
}

.sky-lane { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 5; }
.sky-flight { font-size: clamp(14px, 1.45vw, 42px); opacity: 1; filter: none; }

/* ══ THE PISCES SEMI, along the bottom ═════════════════════════════════════════════════════
   Facing right, driving left to right, below the two panels. Its trailer carries the Employee
   of the Month; tv.js moves it with the Web Animations API and hides it between runs. */
.truck {
  position: absolute;
  left: 0;
  top: 868px;
  width: 980px;
  height: 205px;
  z-index: 3;
  will-change: transform;
}
.truck[hidden] { display: none; }
.truck-art { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible;
  filter: drop-shadow(0 10px 18px rgba(20, 50, 110, .18)); }
/* Proportioned after the side-view picture Brad sent (a modern aero tractor, a 53' box):
   white paint with a teal stripe and teal lower body, a white trailer with amber marker lights
   along its rails; chrome steps, grille and bumper. */
.t-body { fill: url(#t-white); stroke: #BFCAD9; stroke-width: 2; }
.t-shade { fill: #FFFFFF; }
.t-teal { fill: url(#t-teal); }
.t-rail { fill: #DDE3EB; }
.t-post { fill: #EEF2F7; stroke: #D5DDE8; stroke-width: 1.5; }
.t-stripe { fill: #13207A; }
.t-stripe2 { fill: #18C98A; }
.t-under { fill: #2C3446; }
.t-fifth { fill: #1F2533; }
.t-leg { fill: #59616F; }
.t-foot { fill: #3B4252; }
.t-flap { fill: #1E2230; }
.t-red { fill: #D93A33; }
.t-amber { fill: #F5A623; }
.t-win { fill: url(#t-glass); stroke: #A7B6C8; stroke-width: 1.5; }
.t-seam { fill: none; stroke: #C9D3E0; stroke-width: 2; }
.t-seamline { fill: none; stroke: rgba(150, 165, 185, .6); stroke-width: 1.5; }
.t-handle { fill: #AEB8C6; }
.t-arm { fill: none; stroke: #2A3140; stroke-width: 3.5; stroke-linecap: round; }
.t-mirror { fill: #2A3140; }
.t-skirt-t { fill: url(#t-teal); stroke: #124F61; stroke-width: 1.5; }
.t-steps { fill: url(#t-chrome); stroke: #8E99A9; stroke-width: 1; }
.t-grille-frame { fill: url(#t-chrome); stroke: #8E99A9; stroke-width: 1; }
.t-slat { stroke: #59616F; stroke-width: 2; }
.t-bumper { fill: url(#t-chrome); stroke: #8E99A9; stroke-width: 1; }
.t-light { fill: #FFF2B8; stroke: #F5D46B; stroke-width: 1.5; }
.t-arch { fill: #1B2230; }
.t-tyre { fill: #23262F; }
.t-tread { fill: none; stroke: #343947; stroke-width: 2; }
.t-rim { fill: #E8ECF2; stroke: #FFFFFF; stroke-width: 1.5; }
.t-hub { fill: #8E99A9; }
.t-lug { fill: #5F6878; }
.t-spoke { stroke: #C3CBD6; stroke-width: 2.5; stroke-linecap: round; }
.t-wheel { transform-box: fill-box; transform-origin: center; animation: t-roll .9s linear infinite; }
.truck.is-parked .t-wheel { animation: none; }
@keyframes t-roll { to { transform: rotate(360deg); } }
/* The trailer's side: x 4–900 of 1240, y 10–170 of 260 in the drawing. */
.trailer-text {
  position: absolute;
  left: 3.1%;
  width: 68%;
  top: 6.2%;
  height: 50%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 0 28px;
}
.trailer-text p { margin: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eom-label { font-size: 21px; font-weight: 800; letter-spacing: .26em; color: #18A877; }
.eom-name { font-size: 54px; font-weight: 800; color: #13207A; line-height: 1.1; letter-spacing: -.01em; }
.eom-role { font-size: 21px; font-weight: 600; color: #4C5F86; }
