/*
Theme Name: u123 Hub
Theme URI: https://u123.co.uk/
Author: Citytalk Group
Description: The hub theme for u123.co.uk - a departures board listing the projects on this domain, with an approach scope showing the same list as radar contacts. Self-contained: fonts are self-hosted, and there are no external scripts or trackers.
Version: 0.2.0
Requires at least: 6.5
Requires PHP: 8.1
License: GPL-2.0-or-later
Text Domain: u123-hub
*/

/* ---------------------------------------------------------------------------
 * One committed look: amber on hangar black, the way a departures board and a
 * radar scope both are. There is deliberately no light theme and no theme
 * toggle - a lit board on a white page is not the same object, and offering a
 * switch would mean designing something this page is not.
 *
 * Version 0.1.0 had both themes and a toggle. That is why the tokens below no
 * longer carry a :root[data-theme="light"] block, and why header.php no longer
 * runs an inline script before first paint.
 * ------------------------------------------------------------------------ */

/* -------------------------------------------------------------- the faces --
 * Self-hosted, latin subset. See assets/fonts/README.txt for why these are not
 * linked from Google's CDN. font-display:swap, so the board is readable before
 * the flaps arrive.
 * ------------------------------------------------------------------------ */
@font-face {
  font-family: "Barlow Condensed";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("assets/fonts/barlow-condensed-600.woff2") format("woff2");
}
@font-face {
  font-family: "Barlow Condensed";
  font-style: normal; font-weight: 700; font-display: swap;
  src: url("assets/fonts/barlow-condensed-700.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("assets/fonts/ibm-plex-mono-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("assets/fonts/ibm-plex-mono-600.woff2") format("woff2");
}

:root {
  --black:  #0a0c0b;   /* not pure black - a trace of green in it */
  --board:  #0e100e;
  --panel:  #12150f;
  --rule:   #22261f;
  --rule2:  #171a16;

  --amber:  #ffb300;   /* the signal colour. One per screen. */
  --bone:   #f5f2e9;
  --bone2:  #8d8b7e;
  --bone3:  #5a594f;
  --go:     #7ddc8f;

  --maxw:   1140px;
  --fD: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
  --fM: "IBM Plex Mono", Consolas, "SF Mono", Menlo, monospace;
  --fB: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--black); }

body {
  margin: 0;
  background: var(--black);
  color: var(--bone);
  font-family: var(--fB);
  font-size: 16px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

p { margin: 0; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 26px; width: 100%; }

a:focus-visible, button:focus-visible, canvas:focus-visible {
  outline: 3px solid var(--amber); outline-offset: 3px;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--amber); color: var(--black);
  font-family: var(--fM); font-size: 12px; padding: 10px 16px; z-index: 99;
}
.skip:focus { left: 12px; top: 12px; }

.ic { display: block; flex: none; }

/* ------------------------------------------------------------- the header */

.site-head { border-bottom: 1px solid var(--rule); }
.site-head .wrap { display: flex; align-items: center; gap: 14px; height: 68px; }

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--amber); }
.brand .wm {
  font-family: var(--fD); font-weight: 700; font-size: 26px;
  letter-spacing: .11em; text-transform: uppercase; color: var(--bone); line-height: 1;
}
.brand:hover .wm { color: var(--amber); }

.clock {
  margin-left: auto; font-family: var(--fM); font-size: 11px;
  letter-spacing: .2em; color: var(--bone3); font-variant-numeric: tabular-nums;
}

main { flex: 1 0 auto; }

/* --------------------------------------------------------------- the hero */

.hero { padding: clamp(46px, 7vw, 86px) 0 clamp(40px, 6vw, 70px); }
.hero .wrap {
  display: grid; gap: clamp(34px, 5vw, 60px);
  align-items: center; grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .hero .wrap { grid-template-columns: 1.15fr .85fr; }
}

.eyebrow {
  font-family: var(--fM); font-size: 10.5px; font-weight: 600;
  letter-spacing: .26em; text-transform: uppercase; color: var(--amber);
  margin: 0 0 20px; display: flex; align-items: center; gap: 10px;
}
.eyebrow .bulb {
  width: 7px; height: 7px; border-radius: 50%; background: var(--go);
  animation: bulb 2.6s ease-out infinite;
}
@keyframes bulb {
  0%        { box-shadow: 0 0 0 0 rgba(125, 220, 143, .55); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(125, 220, 143, 0); }
}

h1 {
  font-family: var(--fD); font-weight: 700; text-transform: uppercase;
  font-size: clamp(2.5rem, 7.2vw, 4.9rem); line-height: .94;
  letter-spacing: .015em; margin: 0; color: var(--bone);
}
h1 .dim { color: var(--bone3); }
h1 .flip-line { display: block; }

.lede { margin: 24px 0 0; color: var(--bone2); font-size: 1.02rem; max-width: 46ch; }
.lede strong { color: var(--bone); font-weight: 600; }

/* -------------------------------------------------------------- the scope */

.scope { position: relative; width: 100%; max-width: 400px; margin: 0 auto; }

.scope-face {
  position: relative; aspect-ratio: 1; border-radius: 50%;
  border: 1px solid var(--rule);
  background: radial-gradient(circle at 50% 50%, #0d120e, #080a09 72%);
  box-shadow: inset 0 0 60px rgba(0, 0, 0, .9), 0 0 0 7px #0c0e0c, 0 0 0 8px var(--rule);
}
#radar { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; touch-action: none; }
#radar.hit { cursor: pointer; }

.tip {
  position: absolute; z-index: 4; pointer-events: none;
  transform: translate(-50%, -124%);
  background: var(--panel); border: 1px solid var(--amber);
  padding: 6px 9px; white-space: nowrap;
  font-family: var(--fM); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--amber);
  opacity: 0; transition: opacity .12s ease;
}
.tip.on { opacity: 1; }

.readout {
  margin-top: 16px; border: 1px solid var(--rule); background: var(--board);
  font-family: var(--fM); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
}
.readout-hdr {
  padding: 8px 12px; border-bottom: 1px solid var(--rule); color: var(--bone3);
  display: flex; justify-content: space-between; gap: 12px;
}
.readout-hdr b { color: var(--go); font-weight: 500; }
.readout-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background: var(--rule); margin: 0;
}
.readout .cell { background: var(--board); padding: 10px 12px; }
.readout .cell dt { color: var(--bone3); font-size: 9px; letter-spacing: .18em; margin-bottom: 5px; }
.readout .cell dd { margin: 0; color: var(--bone); font-size: 12px; font-variant-numeric: tabular-nums; }
.readout .cell dd.go { color: var(--go); }
.readout .cell dd.idle { color: var(--bone3); }

.hint {
  margin: 10px 2px 0; font-family: var(--fM); font-size: 9.5px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--bone3); text-align: center;
}

/* -------------------------------------------------------------- the board */

.board { border-top: 1px solid var(--rule); position: relative; background: var(--board); }
.board::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--amber), transparent);
  opacity: .7; animation: refresh 7s linear infinite;
}
@keyframes refresh { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.row {
  display: grid; grid-template-columns: 98px 1fr 130px; gap: 18px;
  align-items: center; padding: 20px 0; border-bottom: 1px solid var(--rule2);
  text-decoration: none; color: inherit;
}
.rowhdr {
  padding: 11px 0; border-bottom: 1px solid var(--rule);
  font-family: var(--fM); font-size: 9.5px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--bone3);
}
.row[data-contact] { transition: background .18s ease; }
.row.lit { background: #141812; }
a.row:hover .dest, a.row:focus-visible .dest { color: var(--amber); }

.svc { font-family: var(--fM); font-size: 13px; letter-spacing: .08em; color: var(--amber); }
.svc.off { color: var(--bone3); }

.dest {
  font-family: var(--fD); font-size: clamp(1.4rem, 3.4vw, 1.9rem); font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase; color: var(--bone);
  line-height: 1.1; transition: color .18s ease;
}
.dest.off { color: var(--bone3); }
.dest .note {
  display: block; font-family: var(--fB); font-size: 13px; font-weight: 400;
  text-transform: none; letter-spacing: 0; color: var(--bone2);
  margin-top: 7px; line-height: 1.6; max-width: 56ch;
}
.dest .host {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 9px;
  font-family: var(--fM); font-size: 11px; font-weight: 400;
  letter-spacing: .06em; text-transform: none; color: var(--amber);
}

.stat { justify-self: end; text-align: right; }

/* --------------------------------------------------------- the split-flap */

.flap { display: inline-flex; gap: 2px; font-family: var(--fM); font-weight: 600; }
.flap span {
  display: inline-block; min-width: .62em; text-align: center;
  font-size: 10px; letter-spacing: .14em; padding: 4px 1px;
  background: #151812; color: var(--bone3);
  border-top: 1px solid #202419; border-bottom: 1px solid #050605;
}
.flap.go span { color: var(--go); }
.flap span.turn { animation: flip .11s linear; }
@keyframes flip {
  from { transform: scaleY(.15); filter: brightness(1.8); }
  to   { transform: scaleY(1); }
}

/* Before the script runs the status is one plain text node, and it still has
   to look like a board cell. flap() adds .split once it has cut the word into
   per-character cells, at which point the rules above take over. */
.flap:not(.split) {
  display: inline-block;
  font-size: 10px; letter-spacing: .14em; padding: 4px 7px;
  background: #151812; color: var(--bone3);
  border-top: 1px solid #202419; border-bottom: 1px solid #050605;
}
.flap.go:not(.split) { color: var(--go); }

h1 .flap { gap: 3px; }
h1 .flap span {
  background: none; border: 0; padding: 0; color: inherit;
  font-family: var(--fD); font-size: inherit; letter-spacing: inherit; min-width: .34em;
}
h1 .flap:not(.split) {
  display: block; background: none; border: 0; padding: 0;
  font-size: inherit; letter-spacing: inherit; color: inherit;
}

/* ------------------------------------------------------------- the footer */

.site-foot {
  border-top: 1px solid var(--rule); padding: 30px 0 46px; flex: none;
  background: var(--black);
}
.site-foot .wrap {
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between;
  font-family: var(--fM); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--bone3);
}

/* ------------------------------------------------------------------ small */

@media (max-width: 640px) {
  .row { grid-template-columns: 1fr auto; gap: 8px 14px; }
  .svc { grid-column: 1 / -1; }
  .readout-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
