:root {
  --bg: #030303;
  --surface: #0b0a09;
  --surface-raised: #11100e;
  --line: rgba(211, 171, 121, 0.16);
  --line-strong: rgba(211, 171, 121, 0.28);
  --text: #b99a73;
  --text-bright: #e1bc86;
  --muted: #715b43;
  --urgent: #e4825f;
  --soon: #d8a35c;
  --scheduled-bg: #250b09;
  --scheduled-line: rgba(211, 75, 54, 0.48);
}

/* Self-hosted so the board renders identically everywhere.
 *
 * The stacks below used to name only fonts that ship with an OS, which meant
 * three different boards: a Mac resolved "Avenir Next", a PC fell through to
 * "Segoe UI", and the kiosk — where none of DIN Alternate, Avenir Next
 * Condensed, Avenir Next or Segoe UI exists — landed on Noto Sans with every
 * weight above 400 synthesized. Noto Sans is what the wall display has
 * actually been drawing all along, so standardizing on it is the choice that
 * leaves the one surface that matters looking the same, and brings the other
 * two into line with it.
 *
 * One variable file covers 400-900, so 650/750/800/900 are now real weights
 * rather than a browser smearing Regular. Vendored rather than linked: the
 * kiosk must not need fonts.gstatic.com reachable to draw a departure time.
 * latin-ext is only fetched when a glyph in its range is actually used.
 * See public/vendor/fonts/README.md. */
@font-face {
  font-family: "Noto Sans";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/vendor/fonts/NotoSans-latin.woff2") format("woff2");
  unicode-range: ;
}

@font-face {
  font-family: "Noto Sans";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/vendor/fonts/NotoSans-latin-ext.woff2") format("woff2");
  unicode-range: ;
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
}

body {
  margin: 0;
  overflow: hidden;
  color: var(--text);
  background:
    radial-gradient(circle at 48% -30%, rgba(116, 77, 38, 0.11), transparent 46%),
    var(--bg);
  font-family: "Noto Sans", "DIN Alternate", "Avenir Next Condensed", sans-serif;
  font-variant-numeric: tabular-nums lining-nums;
}

.app-shell {
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 8px 12px;
  transition: filter 0.8s ease;
}

/* Desk-presence dimming (toggled by app.js from /api/presence) and night
   mode (time-based, see applyDayNight in app.js) share the same real
   light-output cut via filter — night mode's color-tuning alone isn't dark
   enough on its own, whether that's late at night or sitting right next to
   the screen during the day. */
/* Both are gated on .allow-dim, which app.js sets only for the kiosk display
   itself (or ?dim=1). Cutting light output is right when the screen is a foot
   from your face on the desk; it's just an unreadably dark page when the same
   board is opened on another machine's monitor over Tailscale. app.js also
   keeps remote viewers out of night mode so they retain the normal readable
   palette. Failing without the class means "bright", which is the right way
   round for something you need to be able to read. */
html.allow-dim.desk-dim .app-shell,
html.allow-dim[data-mode="night"] .app-shell {
  filter: brightness(0.22) saturate(0.7);
}

:root[data-mode="night"] {
  --line: rgba(181, 143, 96, 0.13);
  --line-strong: rgba(181, 143, 96, 0.23);
  --text: #80694e;
  --text-bright: #b08d61;
  --muted: #594631;
  --urgent: #c66b4e;
  --soon: #b8874b;
}

/* The wall display is viewed in a dark room, so its night palette is lower
   luminance than the handheld view without flattening the information hierarchy. */
:root[data-mode="night"] body:not(.mobile-page) {
  --line: rgba(132, 104, 70, 0.09);
  --line-strong: rgba(132, 104, 70, 0.16);
  --text: #5e4e3b;
  --text-bright: #7a6245;
  --muted: #3f3225;
  --urgent: #8d4b39;
  --soon: #806036;
  --scheduled-bg: #160605;
  --scheduled-line: rgba(132, 45, 34, 0.3);
  background: #000;
}

.topbar {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(10px, 1.4vh, 16px);
  padding: 0 3px clamp(10px, 1.3vh, 15px);
}

.title-block {
  display: flex;
  align-items: baseline;
  gap: 14px;
}

.eyebrow {
  margin: 0;
  color: var(--muted);
  font-size: clamp(10px, 1.15vw, 15px);
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

h1 {
  margin: 0;
  color: var(--text-bright);
  font-size: clamp(25px, 2.6vw, 40px);
  font-weight: 750;
  letter-spacing: -0.025em;
  line-height: 1;
}

.status-cluster {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.2vw, 18px);
}

.hint {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #554534;
  font-size: clamp(10px, 1vw, 14px);
  white-space: nowrap;
}

.hint kbd {
  padding: 2px 5px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 4px;
  background: transparent;
  font: inherit;
  font-weight: 800;
}

.status-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: clamp(10px, 1vw, 14px);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.status-pill::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #6e5032;
  box-shadow: 0 0 0 3px rgba(110, 80, 50, 0.12);
}

.status-pill[data-state="live"]::before {
  background: #9e8b52;
}

.status-pill[data-state="error"]::before {
  background: var(--urgent);
}

.clock {
  min-width: 94px;
  color: var(--text-bright);
  font-size: clamp(20px, 2vw, 30px);
  font-weight: 700;
  letter-spacing: -0.02em;
  text-align: right;
}

.board-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-rows: repeat(6, minmax(0, 1fr));
  gap: clamp(5px, 0.75vh, 9px);
}

.board-card,
.loading-card {
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: clamp(11px, 1vw, 16px);
  background: linear-gradient(100deg, var(--surface-raised), var(--surface) 32%);
}

.board-card {
  --card-accent: #78442e;
  position: relative;
  display: grid;
  grid-template-columns: clamp(198px, 15.5vw, 260px) minmax(0, 1fr);
}

.board-card::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: var(--card-accent);
}

.board-card[data-data-state="scheduled"] {
  border-color: var(--scheduled-line);
  background:
    linear-gradient(90deg, rgba(117, 27, 20, 0.22), transparent 38%),
    var(--scheduled-bg);
}

.board-card[data-data-state="scheduled"]::before {
  background: #a43b2d;
}

body:not(.mobile-page) {
  background: #000;
}

body:not(.mobile-page) .board-card,
body:not(.mobile-page) .loading-card,
body:not(.mobile-page) .board-card[data-data-state="scheduled"] {
  background: #000;
}

.route-rail {
  position: relative;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  border-right: 1px solid var(--line);
}

.route-chip {
  max-width: 100%;
  overflow: visible;
  color: var(--text-bright);
  font-family: "Noto Sans", "Avenir Next", "Segoe UI", sans-serif;
  font-size: clamp(126px, min(10.85vw, 19.3vh), 212px);
  font-weight: 900;
  letter-spacing: -0.045em;
  line-height: 0.74;
  text-align: center;
  text-wrap: balance;
  white-space: normal;
}

.route-chip-compact {
  font-size: clamp(22px, min(2.2vw, 3.5vh), 30px);
  line-height: 0.94;
}

.route-kicker {
  order: -1;
  margin: 0 0 5px;
  color: var(--muted);
  font-size: clamp(8px, 0.75vw, 11px);
  font-weight: 800;
  letter-spacing: 0.22em;
}

.direction-grid {
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  overflow: hidden;
}

.direction-panel {
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(150px, 0.54fr) minmax(0, 1.46fr);
  align-items: center;
  column-gap: 2px;
  padding: 0 1px;
  overflow: hidden;
}

body:not(.mobile-page) .direction-panel.has-via {
  grid-template-columns: 180px minmax(0, 1fr);
}

.direction-panel + .direction-panel {
  border-left: 1px solid var(--line);
}

.section-info,
.direction-head,
.detail-column {
  min-width: 0;
}

.section-info {
  position: relative;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  overflow: hidden;
}

.destination-row {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
}

.section-route {
  flex: 0 0 auto;
  color: var(--text-bright);
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  padding: 2px 5px;
  font-size: clamp(12px, 1vw, 16px);
  font-weight: 900;
}

.direction-dir {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--text-bright);
  font-size: clamp(28px, min(2.65vw, 4.4vh), 42px);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body:not(.mobile-page) .board-card[data-data-state="scheduled"] .destination-row {
  margin-left: -3px;
  padding: 3px 5px 2px;
  border-radius: 5px;
  background: rgba(116, 31, 24, 0.38);
}

.direction-panel[data-color="west"] .direction-dir { color: #bc7778; }
.direction-panel[data-color="east"] .direction-dir { color: #c69d52; }
.direction-panel[data-color="north"] .direction-dir { color: #b8a85f; }
.direction-panel[data-color="south"] .direction-dir { color: #c78e5b; }

.stop-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 8px;
  min-width: 0;
  margin-top: clamp(2px, 0.35vh, 4px);
}

.direction-stop {
  flex: 1 1 100%;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--text);
  font-size: clamp(17px, 1.35vw, 27px);
  font-weight: 600;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body:not(.mobile-page) .direction-panel.is-detour .direction-stop {
  margin-left: -4px;
  padding: 3px 5px 2px;
  border-radius: 4px;
  color: #bd7770;
  background: rgba(116, 31, 24, 0.52);
}

.walk-adjust,
.detour-badge {
  flex: 0 0 auto;
  padding: 3px 6px;
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  color: var(--muted);
  font-size: clamp(10px, 0.88vw, 13px);
  font-weight: 900;
  letter-spacing: 0.06em;
  line-height: 1;
  text-transform: uppercase;
}

body:not(.mobile-page) .section-info.has-walk .detail-column {
  padding-right: 52px;
}

body:not(.mobile-page) .section-info.has-walk .walk-adjust {
  position: absolute;
  right: 3px;
  bottom: 8px;
  padding: 0;
  border: 0;
  color: var(--text-bright);
  font-size: clamp(30px, 2.65vw, 40px);
  letter-spacing: -0.04em;
  line-height: 1;
}

.detour-badge {
  color: var(--urgent);
  border-color: rgba(228, 130, 95, 0.45);
}

.direction-value {
  position: relative;
  min-width: 0;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.direction-minutes {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 52px;
  color: var(--text-bright);
  font-family: "Noto Sans", "Avenir Next", "Segoe UI", sans-serif;
  font-size: clamp(126px, min(10.85vw, 19.3vh), 212px);
  font-weight: 900;
  letter-spacing: -0.045em;
  line-height: 0.74;
  white-space: nowrap;
}

.direction-minutes[data-values="2"] {
  justify-content: center;
  gap: clamp(36px, 3vw, 60px);
  padding: 0;
  font-size: clamp(126px, min(10.85vw, 19.3vh), 212px);
}

body:not(.mobile-page) .direction-minutes[data-values="2"] {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 60px;
}

body:not(.mobile-page) .direction-minutes[data-values="2"] .countdown-value:first-child {
  justify-self: end;
}

body:not(.mobile-page) .direction-minutes[data-values="2"] .countdown-value:last-child {
  justify-self: start;
}

.direction-minutes[data-display="clock"] {
  width: 100%;
  height: auto;
  color: var(--text);
  font-size: clamp(126px, min(10.85vw, 19.3vh), 212px);
  font-weight: 900;
  letter-spacing: -0.045em;
  line-height: 0.74;
}

.direction-minutes[data-values="3"] {
  gap: 48px;
  font-size: clamp(108px, min(10vw, 18vh), 136px);
}

.countdown-value {
  display: block;
  flex: 0 0 auto;
}

body:not(.mobile-page) .countdown-value:nth-child(2) {
  color: #a63429;
}

:root[data-mode="night"] body:not(.mobile-page) .countdown-value:nth-child(2) {
  color: #7d2d24;
}

.direction-minutes[data-urgency="now"] { color: var(--urgent); }
.direction-minutes[data-urgency="soon"] { color: var(--soon); }

.empty-caption {
  position: absolute;
  margin: 0;
  transform: translateY(3.2em);
  color: var(--muted);
  font-size: clamp(8px, 0.75vw, 11px);
  font-weight: 900;
  letter-spacing: 0.13em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
}

.detail-column {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 4px 7px;
  flex-wrap: wrap;
}

.detail-label {
  display: none;
  color: var(--muted);
  font-size: clamp(8px, 0.7vw, 10px);
  font-weight: 900;
  letter-spacing: 0.16em;
}

.direction-next {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  color: var(--text-bright);
  font-size: clamp(27px, 2.3vw, 33px);
  font-weight: 750;
  line-height: 0.9;
  white-space: normal;
}

.departure-time {
  display: block;
  white-space: nowrap;
}

.via-details {
  display: grid;
  gap: 2px;
}

.via-detail,
.service-note {
  margin: 0;
  color: var(--text);
  font-size: clamp(9px, 0.82vw, 13px);
  font-weight: 650;
  line-height: 1.1;
  white-space: nowrap;
}

.direction-panel.has-via .detail-column {
  gap: 2px;
  flex-wrap: nowrap;
}

.direction-panel.has-via .direction-next {
  gap: 1px;
  font-size: clamp(22px, 1.75vw, 26px);
  line-height: 1.02;
}

.direction-panel.has-via .via-detail {
  font-size: clamp(8px, 0.62vw, 9px);
}

:root[data-mode="night"] .direction-panel[data-color="west"] .direction-dir { color: #9d6264; }
:root[data-mode="night"] .direction-panel[data-color="east"] .direction-dir { color: #a78349; }
:root[data-mode="night"] .direction-panel[data-color="north"] .direction-dir { color: #97894e; }
:root[data-mode="night"] .direction-panel[data-color="south"] .direction-dir { color: #a5754a; }

:root[data-mode="night"] body:not(.mobile-page) .direction-panel[data-color="west"] .direction-dir { color: #6d4446; }
:root[data-mode="night"] body:not(.mobile-page) .direction-panel[data-color="east"] .direction-dir { color: #745b32; }
:root[data-mode="night"] body:not(.mobile-page) .direction-panel[data-color="north"] .direction-dir { color: #675d35; }
:root[data-mode="night"] body:not(.mobile-page) .direction-panel[data-color="south"] .direction-dir { color: #725034; }

:root[data-mode="night"] body:not(.mobile-page) .board-card::before {
  opacity: 0.62;
}

.service-note {
  color: var(--urgent);
  font-weight: 800;
}

.loading-card {
  grid-row: 1 / -1;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: clamp(18px, 2vw, 30px);
}

@media (max-width: 1200px) {
  .board-card {
    grid-template-columns: 118px minmax(0, 1fr);
  }

  .direction-panel {
    grid-template-columns: minmax(130px, 1fr) auto;
  }

  .detail-column {
    display: none;
  }
}

@media (max-width: 900px) {
  html,
  body {
    height: auto;
    min-height: 100%;
    overflow: auto;
  }

  .app-shell {
    height: auto;
    min-height: 100dvh;
    padding: 14px;
  }

  .hint {
    display: none;
  }

  .board-grid {
    display: flex;
    flex-direction: column;
    gap: 9px;
  }

  .board-card {
    min-height: 150px;
    grid-template-columns: 104px minmax(0, 1fr);
  }

  .direction-panel {
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: 9px;
    padding: 12px;
  }

  .direction-value {
    align-items: flex-start;
  }
}

@media (max-width: 560px) {
  .app-shell {
    padding:
      calc(env(safe-area-inset-top) + 10px)
      calc(env(safe-area-inset-right) + 10px)
      calc(env(safe-area-inset-bottom) + 16px)
      calc(env(safe-area-inset-left) + 10px);
  }

  .topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    min-height: 48px;
    background: var(--bg);
  }

  .eyebrow,
  .status-pill {
    display: none;
  }

  h1 {
    font-size: 24px;
  }

  .clock {
    min-width: 0;
    font-size: 20px;
  }

  .board-card {
    min-height: 172px;
    grid-template-columns: 76px minmax(0, 1fr);
  }

  .route-rail {
    padding: 10px;
  }

  .route-chip {
    font-size: 25px;
    white-space: normal;
  }

  .direction-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .direction-panel {
    padding: 10px 8px;
  }

  .direction-dir {
    font-size: clamp(17px, 5vw, 22px);
  }

  .stop-row {
    align-items: flex-start;
    flex-direction: column;
    gap: 5px;
  }

  .direction-stop {
    font-size: 11px;
  }

  .direction-minutes,
  .direction-minutes[data-chars="3"],
  .direction-minutes[data-chars="4"],
  .direction-minutes[data-chars="5"],
  .direction-minutes[data-chars="6"] {
    font-size: clamp(40px, 12vw, 54px);
  }

  .direction-minutes[data-values="2"] {
    gap: 7px;
    font-size: clamp(36px, 11vw, 48px);
  }

  .direction-minutes[data-values="3"] {
    gap: 5px;
    font-size: clamp(29px, 8.5vw, 38px);
  }

  .walk-adjust {
    display: none;
  }
}

/* Why a section is showing a stop it isn't configured for (see detourReason
   in app.js). Distinct from the urgent .service-note it sits beside — this
   is context, not something to act on, so it reads quieter. Unlike that
   note it's allowed to wrap: the reason text comes from RTD and its length
   isn't ours to control, and truncating it to one line loses the "thru
   Sep 4" that makes it useful. */
.service-note.detour-note {
  color: var(--muted);
  font-weight: 600;
  white-space: normal;
}

:root[data-mode="night"] .service-note.detour-note {
  color: var(--muted);
}
