/* Public site: live map and history. */

.page-map main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  height: calc(100vh - 56px);
  min-height: 480px;
}
.view-area { position: relative; min-width: 0; height: 100%; display: flex; flex-direction: column; }
#map { flex: 1; min-height: 360px; background: var(--surface-2); }
.view-area > .chart { flex: 1; min-height: 0; }

/* Rewind bar: the map and side panels as they stood up to 48 hours ago. */
.rewind {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.rewind button { padding: 4px 9px; font-size: 0.82rem; }
.rewind .rw-range { flex: 1 1 200px; min-width: 140px; accent-color: var(--accent); }
/* A fixed width, so the slider keeps its length as the time changes (decision 209). */
/* The bar's label is spoken only (a quiet live region); the visible time is a fixed-width slot,
   so the slider keeps its length as the time changes (decision 209). */
.rewind .rw-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.rewind .rw-time { font-size: 0.85rem; font-variant-numeric: tabular-nums; flex: none; width: 19.5em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink-2); }
.map-time { display: none; }
/* The Live button keeps its place while live (hidden), so the slider never changes length. */
.rewind .rw-live { visibility: hidden; }
.rewind.past { background: var(--warn-bg); border-bottom-color: var(--warn); }
.rewind.past .rw-time { color: var(--ink); font-weight: 700; }
.rewind.past .rw-live { visibility: visible; border-color: var(--accent); color: var(--accent); }
.rewind .rw-play[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.conn.past .dot { background: var(--warn); }
/* Side panel: Activity, Recent trains and Receivers fold open and closed and each scrolls on
   its own; Weather, the safety note and legal links stay pinned at the bottom. */
.side {
  overflow: hidden;
  border-left: 1px solid var(--line);
  background: var(--bg);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.side-stack { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 12px 16px 10px; overflow: hidden; }
.fold { flex: 0 0 auto; display: flex; flex-direction: column; min-height: 0; }
.fold.open { flex: 0 1 auto; min-height: 96px; }
.fold:not(.open) .fold-body { display: none; }
.fold-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.fold-btn {
  all: unset; cursor: pointer; flex: 1; display: inline-flex; align-items: baseline; gap: 6px;
}
.fold-btn::before { content: "\25B8"; display: inline-block; width: 0.9em; transition: transform 0.15s; }
.fold-btn[aria-expanded="true"]::before { transform: rotate(90deg); }
.fold-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.side-weather {
  flex: 0 0 auto; max-height: 45%; overflow-y: auto; overscroll-behavior: contain;
  border-top: 1px solid var(--line); padding: 10px 16px 12px; background: var(--bg);
}
.side-weather p { margin: 8px 0 0; }
.side section h2 {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
  border-bottom: 2px solid var(--ink);
  padding-bottom: 4px;
}
.side section h2 .muted { text-transform: none; letter-spacing: 0; font-weight: 500; }

.conn { font-size: 0.78rem; color: #c9c6bf; display: flex; align-items: center; gap: 6px; }
.conn .dot { margin: 0; }
.conn.live .dot { background: var(--ok); }
.conn.poll .dot { background: var(--warn); }
.conn.down .dot { background: transparent; border: 2px solid var(--offline); }


.alerts { list-style: none; margin: 0; padding: 0; }
.alerts li { padding: 8px 0; border-bottom: 1px solid var(--line); }
.alerts .title { font-weight: 700; }
.alerts .title::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--train-now);
  border-radius: 50%;
  margin-right: 7px;
  vertical-align: 1px;
}
.alerts .msg { font-size: 0.86rem; color: var(--ink-2); }
.alerts time { font-size: 0.78rem; color: var(--ink-3); }
.alerts li.fresh { background: linear-gradient(90deg, color-mix(in srgb, var(--train-now) 16%, transparent), transparent 70%); }

.rx-list { list-style: none; margin: 0; padding: 0; }
.rx-list li { display: flex; align-items: center; padding: 5px 0; gap: 4px; }
.rx-list .state { margin-left: auto; font-size: 0.8rem; color: var(--ink-3); }
.rx-list .note { font-size: 0.8rem; color: var(--ink-3); display: block; }

.wx { border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; background: var(--surface); margin-bottom: 8px; }
.wx .place { font-weight: 700; }
.wx .now { display: flex; align-items: baseline; gap: 10px; margin: 4px 0; }
.wx .temp { font-size: 1.6rem; font-weight: 700; }
.wx .periods { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; font-size: 0.78rem; color: var(--ink-2); }
.wx .periods b { display: block; color: var(--ink); }
.wx .nws-alert { margin-top: 6px; font-size: 0.82rem; color: var(--danger); font-weight: 600; }
.wx .stale { font-size: 0.75rem; color: var(--warn); }

/* Map key */
.map-key { margin: 0; padding: 6px 12px; background: var(--surface); border-bottom: 1px solid var(--line); line-height: 1.5; }
.map-key .offline-area {
  display: inline-block; width: 14px; height: 14px; border-radius: 50%; margin-right: 6px; vertical-align: -2px;
  background: color-mix(in srgb, var(--offline-area) 45%, transparent); border: 1px solid var(--offline-area);
}
.map-key .phone-area {
  display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 6px; vertical-align: -1px;
  background: color-mix(in srgb, var(--phone-area) 30%, transparent); border: 1px solid var(--phone-area);
}
.cap-badge.phone-badge { border-color: var(--phone-area); color: var(--phone-area); }
.map-key .area {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 6px;
  background: color-mix(in srgb, var(--accent) 30%, transparent);
  border: 1px solid var(--accent);
}

.leaflet-container { font: inherit; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--surface); color: var(--ink); }
.leaflet-popup-content { margin: 12px 14px; min-width: 220px; }
.leaflet-container a.leaflet-popup-close-button { color: var(--ink-3); }

.pop h3 { margin: 0 0 2px; font-size: 1rem; }
.pop .sub { color: var(--ink-3); font-size: 0.82rem; margin-bottom: 6px; }
.pop dl { display: grid; grid-template-columns: auto 1fr; gap: 1px 10px; margin: 6px 0; font-size: 0.84rem; }
.pop dt { color: var(--ink-3); }
.pop dd { margin: 0; }
.pop .status { font-weight: 700; display: flex; align-items: center; }
.pop .covers { list-style: none; padding: 0; margin: 4px 0 0; font-size: 0.84rem; }
.pop .covers li { padding: 3px 0; border-top: 1px solid var(--line); }
.pop .stale-note { font-size: 0.75rem; color: var(--ink-3); }

/* Notification dialog */
dialog {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
  max-width: min(420px, calc(100vw - 32px));
  padding: 18px;
}
dialog::backdrop { background: rgba(0, 0, 0, 0.45); }
dialog .row { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; }
dialog .actions { display: flex; gap: 8px; justify-content: flex-end; }

/* History */
.page-history main { max-width: 1200px; margin: 0 auto; padding: 18px 16px 40px; }
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  align-items: flex-end;
  margin-bottom: 14px;
}
.filters fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; min-width: 0; max-width: 100%; }
.filters legend, .filters .lbl { font-weight: 600; font-size: 0.82rem; color: var(--ink-2); padding: 0; margin-bottom: 4px; }
.filters .inline { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.filters .inline label { font-weight: 500; display: flex; align-items: center; gap: 4px; }
.filters select { max-width: 100%; }
#f-crossing { width: 22rem; max-width: 100%; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 14px; }
.chip {
  font-size: 0.82rem;
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: 999px;
  padding: 3px 10px;
}
.chip b { margin-left: 4px; }
.hist-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.hist-actions .count { margin-right: auto; color: var(--ink-3); font-size: 0.88rem; }
table.history td.when { white-space: nowrap; }
table.history .crossing-link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent);
  text-decoration: underline;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
}
.load-more { margin: 16px auto 0; display: block; }

/* Phones and narrow tablets (decision 207): the live map page is a fixed screen that never
   scrolls. Below the bar, the map and the panel's parts are one stack of sections (Map, Regions
   in the overview, Crossings, Recent trains, Receivers, Weather and notes), one open at a time:
   the open one fills the rest of the screen and scrolls inside itself, the map pans. On wider
   screens the section headings are hidden and the map and panel sit side by side as before. */
.pf > .pf-head, .key-btn { display: none; }
.map-pf { display: contents; }
@media (max-width: 900px) {
  /* Pinned to the visible screen like the embed (decision 261): fixed at the top and as tall as
     the part of the screen that shows (--app-h, measured by the map script from the visual
     viewport, since Firefox for Android draws its toolbar over 100dvh), and no desktop minimum. The sections share that height; if even their closed headings do not
     fit (a small phone held sideways), the stack scrolls rather than running off the screen. */
  body.page-map { position: fixed; top: 0; left: 0; right: 0; height: 100dvh; height: var(--app-h, 100dvh); min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
  body.page-map > .topbar { flex: none; }
  .page-map main { display: flex; flex-direction: column; flex: 1; min-height: 0; height: auto; grid-template-columns: none; overflow-y: auto; overscroll-behavior: contain; }
  .page-map .side, .page-map .side-stack { display: contents; }
  .page-map .pf { display: flex; flex-direction: column; flex: none; min-height: 0; padding: 0 16px; border-bottom: 1px solid var(--line); background: var(--bg); }
  .page-map .pf.hidden { display: none; }
  .page-map .map-pf { padding: 0; }
  .page-map .pf > h2:first-child {
    display: flex; justify-content: space-between; align-items: baseline; margin: 0; padding: 11px 0; border: 0;
    font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-2);
  }
  .page-map .map-pf > h2:first-child { padding: 11px 16px; }
  /* The open section takes exactly the space left after the headings and clips anything larger:
     its body is sized from that space (basis 0), never from its content, which Safari measures
     differently for the map (decision 261). */
  .page-map .pf.pf-open { flex: 1 1 0; overflow: hidden; }
  .page-map .pf.pf-open > h2:first-child { color: var(--ink); }
  /* The map's time sits in its title bar; the rewind bar keeps only its controls, so the slider
     never changes length (decision 209). The bar's own label stays for screen readers. */
  .page-map .map-time {
    display: block; text-transform: none; letter-spacing: 0; font-weight: 600; font-size: 0.8rem;
    font-variant-numeric: tabular-nums; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-left: 12px;
  }
  .page-map .map-time.past { color: var(--warn); font-weight: 700; }
  .page-map .rewind .rw-time { display: none; } /* the Map title bar shows it */
  .page-map .pf > .pf-body, .page-map .pf > .fold-body { display: none; }
  .page-map .pf.pf-open > .pf-body, .page-map .pf.pf-open > .fold-body {
    display: block; flex: 1 1 0; min-height: 0; max-height: none; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 12px;
  }
  .page-map .map-pf.pf-open > .view-area { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; overflow: hidden; padding: 0; position: relative; height: auto; }
  .page-map #map { flex: 1 1 0; min-height: 0; height: auto; }
  .page-map .view-area > .chart { height: auto; max-height: none; }
  .page-map .pf-desk { display: none; }
  .page-map .side-weather { max-height: none; overflow: visible; border-top: 0; }
  .page-map .region-switch, .page-map .yt-live-box, .page-map .embed-rx { flex: none; padding: 8px 16px; border-bottom: 1px solid var(--line); }
  /* The map key sits behind a Key button on the map, so it never pushes the map off screen. */
  .page-map #map-key { display: none; max-height: 40%; overflow-y: auto; }
  body.page-map.key-open #map-key { display: flex; }
  .key-btn { display: block; font-weight: 700; padding: 5px 10px; background: var(--surface); color: var(--ink); }
}
/* Short screens: more compact section headings, so more room for the open section. */
@media (max-width: 900px) and (max-height: 700px) {
  .page-map .pf > h2:first-child { padding: 8px 0; }
  .page-map .map-pf > h2:first-child { padding: 8px 16px; }
  .page-map .region-switch, .page-map .yt-live-box, .page-map .embed-rx { padding: 5px 16px; }
}
/* Very short screens (a phone held sideways): the rewind bar on one slim row, as on narrow phones,
   and a slimmer YouTube button, so the map keeps some height. */
@media (max-width: 900px) and (max-height: 500px) {
  .rewind { flex-wrap: nowrap; gap: 4px; padding: 3px 8px; }
  .rewind .rw-step { display: none; }
  .rewind button { padding: 2px 7px; font-size: 0.78rem; white-space: nowrap; flex: none; }
  .rewind .rw-range { flex: 1 1 auto; min-width: 60px; }
  .yt-live { padding: 2px 12px; }
}

@media (max-width: 640px) {
  table.history thead { display: none; }
  table.history, table.history tbody, table.history tr, table.history td { display: block; width: 100%; }
  table.history tr {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    margin-bottom: 10px;
    padding: 8px 10px;
  }
  table.history td { border: 0; padding: 2px 0; }
  table.history td[data-label]::before {
    content: attr(data-label);
    display: inline-block;
    min-width: 76px;
    color: var(--ink-3);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .filters { flex-direction: column; align-items: stretch; }
  .filters select, #f-crossing { width: 100%; }
}

.notfound { max-width: 560px; margin: 40px auto; }

/* Top bar: logo and nav left, search centered, tools right. List styles are in base.css. */
.bar-left { display: flex; align-items: center; gap: 16px; flex: 1; min-width: 0; flex-wrap: wrap; }
@media (max-width: 640px) {
  .bar-left { flex-wrap: nowrap; gap: 8px; }
}
.page-map .topbar {
  display: grid;
  /* The sides never shrink below their content (a longer status like "Rewound" would otherwise
     slide the tools under the search box); the search gives way instead. */
  grid-template-columns: minmax(max-content, 1fr) minmax(200px, 480px) minmax(max-content, 1fr);
  align-items: center;
}
.page-map .topbar .tools { justify-self: end; }
.map-search { position: relative; width: 100%; margin: 6px 0; }
.map-search .search-input {
  background: #f4f2ee;
  color: #1d1f22;
  border-color: #4a4f55;
  padding: 7px 10px;
}
.map-search .search-input::placeholder { color: #6b7078; }
.leaflet-tooltip.search-pin { font-weight: 700; }
/* Tablets and phones: logo and tabs, then the view switch (Map, Track chart) just left of the
   account menu, on the first row; search on the second. No connection status (the rewind bar
   says Live or Rewound), and signed-in visitors find browser alerts in their menu. Signed out,
   alerts and the theme sit beside the search. The tools' own box is dissolved so each can take
   its grid cell. */
.me-pop .notify-item { display: none; }
@media (max-width: 900px) {
  .page-map .topbar {
    grid-template-columns: minmax(0, 1fr) auto auto auto auto;
    grid-template-areas: "left left left view me" "search search search alerts theme";
    gap: 4px 8px; padding: 4px 12px;
  }
  .page-map .topbar:has(.me-menu) { grid-template-areas: "left left left view me" "search search search search search"; }
  .page-map .topbar .conn { display: none; }
  .page-map .topbar:has(.me-menu) #notify-btn { display: none; }
  .me-pop .notify-item:not(.hidden) { display: block; }
  .page-map .topbar .bar-left { grid-area: left; flex-wrap: nowrap; min-width: 0; }
  /* The tabs never run under the view switch: the logo mark stands in for the name, "Live" for
     "Live map", and if they still do not fit they scroll sideways. */
  .page-map .topnav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; min-width: 0; }
  .page-map .topnav::-webkit-scrollbar { display: none; }
  .page-map .topnav .nav-long { display: none; }
  .page-map .topbar .brand-lockup { display: none; }
  .page-map .topbar .brand-mark { display: block; width: 28px; height: 28px; }
  .page-map .topbar .tools { display: contents; }
  .page-map .topbar .view-switch { grid-area: view; }
  .page-map .topbar #notify-btn { grid-area: alerts; justify-self: end; }
  .page-map .topbar #theme-btn { grid-area: theme; justify-self: end; }
  .page-map .topbar .me-menu, .page-map .topbar .signin-btn { grid-area: me; justify-self: end; }
  .page-map .map-search { grid-area: search; margin: 0; }
}
@media (max-width: 640px) {
  .page-map .topbar button, .page-map .topbar .view-switch button { padding: 3px 8px; font-size: 0.82rem; }
  .map-search { grid-area: search; margin: 0 0 4px; }
  .map-search .search-input { padding: 5px 9px; }
  /* Rewind: one row. The step buttons go and the slider does the stepping, leaving room for Play
     and the Live button (the time is in the Map section's title bar). */
  .rewind { flex-wrap: nowrap; gap: 4px; padding: 4px 8px; }
  .rewind .rw-step { display: none; }
  .rewind button { padding: 3px 7px; font-size: 0.78rem; white-space: nowrap; flex: none; }
  .rewind .rw-range { flex: 1 1 auto; min-width: 60px; }
}

/* View switch (top bar) */
.view-switch { display: inline-flex; border: 1px solid #4a4f55; border-radius: var(--radius); overflow: hidden; }
.view-switch button { border: 0; border-radius: 0; background: transparent; color: #c9c6bf; padding: 5px 10px; }
.view-switch button + button { border-left: 1px solid #4a4f55; }
.view-switch button[aria-pressed="true"] { background: var(--focus); color: #16191c; }
/* The view switch shows words, and on phones two icons (with the words as their names). */
.view-switch .vs-icon { display: none; }
@media (max-width: 640px) {
  .view-switch .vs-icon { display: block; }
  .view-switch .vs-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .page-map .topbar .view-switch button { padding: 4px 9px; }
  .page-map .topnav .nav-long { display: none; }
}
/* Small phones: tighter tabs and Sign in, and no logo mark on the map (the Live tab is the same
   home link), so the tabs, the view switch and the menu fit on one row. */
@media (max-width: 400px) {
  .page-map .topbar .brand { display: none; }
  .page-map .topnav a { padding: 6px 6px; font-size: 0.82rem; }
  .page-map .topbar .signin-btn { padding: 3px 8px; font-size: 0.82rem; }
}

/* Track chart */
.chart { height: 100%; overflow-y: auto; padding: 14px 16px 30px; background: var(--bg); }
.chart-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.8rem; margin-bottom: 12px; align-items: center; }
.chart-legend > span { display: inline-flex; align-items: center; }
.chart-section { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 14px; box-shadow: var(--shadow); }
.chart-title { padding: 10px 14px 0; display: flex; gap: 6px; flex-wrap: wrap; align-items: baseline; }

.chart-svg { display: block; font-family: var(--sans); }
.chart-svg .rail { stroke: var(--ink); stroke-width: 1.6; }
.chart-svg .tie-bed { stroke: var(--ink-3); stroke-width: 12; stroke-dasharray: 2 6; opacity: 0.55; }
.chart-svg .axis { stroke: var(--ink-3); stroke-width: 1; }
.chart-svg .axis-label { fill: var(--ink-3); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-svg .cov { stroke-width: 1; }
.chart-svg .cov.online { fill: color-mix(in srgb, var(--accent) 22%, transparent); stroke: var(--accent); }
.chart-svg .cov.offline { fill: none; stroke: var(--ink-3); stroke-dasharray: 4 3; }
.chart-svg .cov-label { fill: var(--ink-2); font-size: 9px; font-weight: 600; }
.chart-svg .xing { cursor: pointer; }
.chart-svg .xing:focus { outline: none; }
.chart-svg .xing.selected .xing-label { font-weight: 700; }
.chart-svg .leader { fill: none; stroke: var(--line); stroke-width: 1; }
.chart-svg .road { stroke: var(--ink-2); stroke-width: 3; }
.chart-svg .xing.private .road { stroke-dasharray: 3 2; }
.chart-svg .xing-label { fill: var(--ink); font-size: 11px; }
.chart-svg .xing-mp { fill: var(--ink-3); font-size: 9.5px; font-variant-numeric: tabular-nums; }
.chart-svg .dev { fill: var(--ink-3); font-size: 9px; font-weight: 700; }
.chart-svg .mark { stroke: var(--surface); stroke-width: 2; }
/* Train marks (decision 210): amber blinking, amber, purple, purple outline; crew radio teal. */
.chart-svg .xing.nearby .mark { fill: var(--tel); stroke: var(--mark-ring); }
.chart-svg .xing.recent .mark { fill: var(--tel); }
.chart-svg .xing.earlier .mark { fill: var(--talk); }
.chart-svg .xing.past .mark { fill: var(--surface); stroke: var(--talk); stroke-width: 2.5; }
.chart-svg .xing.activity .mark { fill: var(--surface); stroke: var(--traffic); stroke-width: 2.5; }
.chart-svg .xing.nearby .xing-label { fill: var(--tel-ink); font-weight: 700; }
.chart-svg .xing.quiet .mark { fill: var(--quiet); r: 4.5; }
/* A stopped train (decisions 208, 210): a steady red outline on any status; only the fill blinks. */
.chart-svg g.xing.stopped .mark { stroke: var(--danger); stroke-width: 2.5; r: 6; }
@media (prefers-reduced-motion: no-preference) {
  .chart-svg g.xing.stopped.nearby .mark { animation-name: rs-blink-fill; }
}
.chart-svg .xing.offline .mark { fill: var(--surface); stroke: var(--offline); stroke-width: 2; stroke-dasharray: 2.5 2; }
.chart-svg .xing.unmonitored .mark { fill: var(--surface); stroke: var(--unmonitored); stroke-width: 1.5; r: 4; }
@media (prefers-reduced-motion: no-preference) {
  .chart-svg .xing.nearby .mark { animation: rs-blink-fast 0.5s infinite; }
}
@media (prefers-reduced-motion: reduce) {
  .chart-svg .xing.nearby .mark { stroke: var(--ink); stroke-width: 3; }
}
/* The focus ring comes after the status rules and matches their weight, so every status shows it. */
.chart-svg g.xing:focus .mark, .chart-svg g.xing.selected .mark { stroke: var(--focus); stroke-width: 3; }
/* Details float over the chart, beside the side panel. */
.chart-detail {
  position: fixed;
  z-index: 1500;
  top: 72px;
  right: 376px;
  width: min(360px, calc(100vw - 32px));
  max-height: calc(100vh - 96px);
  overflow-y: auto;
}
@media (max-width: 900px) {
  .chart-detail { top: auto; right: 16px; left: 16px; bottom: 16px; width: auto; max-height: 60vh; }
}
.chart-detail .actions { margin-top: 8px; }
.chart-empty { padding: 20px; }


/* History: newly arrived alerts glow for a few seconds. */
table.history tr.fresh td { background: color-mix(in srgb, var(--train-now) 18%, transparent); transition: background 2s; }
#hist-live { color: var(--ink-3); }

.notify-state { margin: 8px 0 0; color: var(--ink-2); }
.notify-state.bad { color: var(--danger); }
.stopped-note { color: var(--danger); font-weight: 600; }
.pop-trains-head { margin-top: 6px; font-weight: 700; color: var(--ink-2); }
.pop-trains { list-style: none; margin: 2px 0 4px; padding: 0; font-size: 0.85rem; }
.pop-trains li { padding: 1px 0; }

/* Transcripts in history, and receivers' capability badges in the side panel. */
.transcript { font-style: italic; }
.badges { display: block; }
.cap-badge { display: inline-block; font-size: 0.75rem; border: 1px solid var(--line); border-radius: 999px; padding: 0 6px; margin: 2px 4px 0 0; color: var(--ink-2); }

/* Trains view. */
.page-trains main { max-width: 900px; margin: 0 auto; padding: 18px 16px 40px; }
.page-trains .card { margin-bottom: 12px; }
.train-card { display: block; text-decoration: none; color: inherit; }
.train-card:hover, .train-card:focus-visible { border-color: var(--accent); }
.train-main { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.train-main .unit { font-weight: 700; font-size: 1.1rem; }
.train-meta { color: var(--ink-2); margin-top: 4px; }
ul.notes { list-style: none; padding: 0; margin: 0 0 12px; }
ul.notes li { border-left: 3px solid var(--line); padding: 6px 10px; margin-bottom: 8px; }
.note-body { white-space: pre-wrap; overflow-wrap: anywhere; }
.note-form { display: flex; flex-direction: column; gap: 6px; max-width: 560px; margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }
.note-form input, .note-form select, .note-form textarea { width: 100%; }
.note-row { display: grid; grid-template-columns: 1fr 120px; gap: 10px; }
.link-button { background: none; border: 0; padding: 0; color: var(--danger); text-decoration: underline; cursor: pointer; font: inherit; }
.pickers { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.yt-embed { position: relative; width: 100%; max-width: 560px; aspect-ratio: 16 / 9; margin: 6px 0; }
.yt-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: var(--radius); }
.yt-dialog { max-width: 760px; width: calc(100% - 32px); }
.yt-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; max-height: 60vh; overflow-y: auto; margin: 8px 0; }
.yt-item { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 6px; text-align: left; background: var(--surface-2); }
.yt-item img { width: 100%; height: auto; border-radius: 4px; }
.yt-item .t { font-weight: 600; font-size: 0.85rem; }
.yt-item .m { font-size: 0.75rem; color: var(--ink-3); }
.yt-item:disabled { opacity: 0.5; cursor: not-allowed; }
#pick-status:empty { display: none; }

/* Expandable rows in the side panel (Recent trains): the row is a toggle with a
   chevron; Recent trains rows also carry a popout link to the train's page. */
.row-toggle {
  display: grid; width: 100%; text-align: left; font-weight: 400; font-size: inherit; color: inherit;
  background: none; border: 0; border-radius: 0; padding: 0 0 0 20px; position: relative; cursor: pointer;
}
.row-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.row-toggle::before {
  content: ""; position: absolute; left: 3px; top: 0.45em; width: 6px; height: 6px;
  border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
  transform: rotate(-45deg); transition: transform 0.15s;
}
.row-toggle[aria-expanded="true"]::before { transform: rotate(45deg); top: 0.3em; }
.trains-list .row-head { display: flex; align-items: flex-start; gap: 6px; }
.train-row { flex: 1; min-width: 0; }
.train-row .title, .train-row .msg { display: block; }
.trains-list li.open { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--accent); padding-left: 6px; padding-right: 6px; }
.popout { flex: none; display: inline-flex; padding: 4px; margin: -2px -2px 0 0; border-radius: 4px; color: var(--ink-3); }
.popout:hover, .popout:focus-visible { color: var(--accent); background: var(--surface-2); }
.train-detail { padding: 6px 0 4px 20px; }
.alerts .train-detail li { padding: 0; border-bottom: 0; }
.train-detail h3 { margin: 12px 0 6px; font-size: 0.95rem; }
.tc-passes { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.tc-pass { font-size: 0.85rem; padding: 4px 10px; border-radius: 999px; }
.tc-pass[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.tc-note { padding: 8px 0; border-top: 1px solid var(--line); }
.tc-note .yt-embed { max-width: 100%; }
.tc-body { white-space: pre-line; overflow-wrap: anywhere; }
.tc-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.tc-add { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 4px; }
.tc-field { display: flex; flex-direction: column; gap: 3px; margin: 8px 0; font-weight: 600; font-size: 0.88rem; }
.tc-field input, .tc-field select, .tc-field textarea { width: 100%; font-weight: 400; }
.tc-field .help { font-weight: 400; }
.tc-add .pickers { margin: 8px 0 4px; }

/* Track chart zoom and pan controls. */
.chart-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 14px 0; }
.chart-btn { min-width: 34px; padding: 3px 9px; font-weight: 700; }
.chart-range { margin-left: 4px; }
.chart-scroll { overflow: hidden; touch-action: pan-y; cursor: grab; }
.chart-scroll.dragging { cursor: grabbing; user-select: none; }
.chart-scroll:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* Detector markers on the map (DOM icons over the canvas crossings) and the track chart. */
.det-icon { background: none; border: 0; }
/* Quiet: an opaque outline, so a lit crossing under it never shows through and tints it. */
.det-icon span {
  display: block; width: 12px; height: 12px; margin: 3px; transform: rotate(45deg); box-sizing: border-box;
  background: var(--surface); border: 2px solid var(--det); box-shadow: 0 0 0 1.5px var(--mark-ring);
}
.det-icon.recent span, .det-icon.nearby span { background: var(--det); }
@media (prefers-reduced-motion: no-preference) {
  .det-icon.nearby span { animation: rs-blink-fast 0.5s infinite; }
}
@media (prefers-reduced-motion: reduce) {
  .det-icon.nearby span { box-shadow: 0 0 0 3px var(--ink); }
}
.pop .det-facts { margin-top: 4px; }
.chart-svg .det-mark { fill: var(--surface); stroke: var(--det); stroke-width: 2; }
.chart-svg .det-mark.nearby, .chart-svg .det-mark.recent { fill: var(--det); stroke: var(--mark-ring); stroke-width: 1.5; }
@media (prefers-reduced-motion: no-preference) {
  .chart-svg .det-mark.nearby { animation: rs-blink-fast 0.5s infinite; }
}
.chart-svg .det-label { fill: var(--det-ink); font-size: 9px; font-weight: 700; }

/* The track chart's key: always open on wide screens (no summary), folded behind "Key" on phones. */
.chart-key > summary { display: none; }
@media (max-width: 900px) {
  .chart-key { margin-bottom: 10px; }
  .chart-key > summary {
    display: inline-block; cursor: pointer; font-weight: 700; padding: 4px 10px; border: 1px solid var(--line);
    border-radius: var(--radius); background: var(--surface); list-style: none;
  }
  .chart-key > summary::-webkit-details-marker { display: none; }
  .chart-key[open] > summary { margin-bottom: 8px; }
}

/* Region chooser on lists (Trains, History). */
.region-picks { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 10px; }
.region-picks .chip { text-decoration: none; color: var(--ink); }
.region-picks .chip.current { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); font-weight: 700; }
.region-picks .chip b { color: var(--talk-ink); }

/* Regions overview (decision 172): zoomed out, the panel lists regions instead of live data. */
.region-pick { padding: 12px 16px 4px; }
.region-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.region-item { width: 100%; text-align: left; display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; background: var(--surface); }
.region-item.active { border-color: var(--talk); box-shadow: inset 3px 0 0 var(--talk); }
body.region-overview .side-stack, body.region-overview .side-weather .pf-desk, body.region-overview #weather { display: none; }
body.region-overview #map-key, body.region-overview .key-btn { display: none; }
.leaflet-tooltip.region-label { background: var(--surface); color: var(--ink); border: 1px solid var(--line); font-size: 0.82rem; text-align: center; box-shadow: var(--shadow); cursor: pointer; }
.leaflet-tooltip.region-label.active { border-color: var(--talk); }
.leaflet-tooltip.region-label strong { font-size: 0.9rem; }
body.region-overview .rewind { display: none; }
.region-switch { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 16px 0; }
.region-switch .chip { cursor: pointer; }
/* Crossings panel (decision 260): the open region's crossings in track order, a group per line,
   with detectors in place and live cameras on their rows. */
.xing-list { list-style: none; margin: 0; padding: 0; }
.xing-list .meta { font-size: 0.8rem; color: var(--ink-3); }
.xl-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; padding: 12px 0 4px; border-bottom: 1px solid var(--line); }
.xl-head:first-child { padding-top: 2px; }
.xl-item, .xl-cams { border-bottom: 1px solid var(--line); }
/* Each line folds open and closed; its heading keeps the active count in view. */
.xl-line { border-bottom: 1px solid var(--line); }
.xl-line-btn { grid-template-columns: 1fr; gap: 1px; padding: 9px 0 9px 20px; }
.xl-line-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.xl-badge { font-size: 0.75rem; font-weight: 700; padding: 0 7px; border-radius: 999px; background: var(--tel); color: #16191c; }
.xl-badge.radio { background: transparent; color: var(--ink-2); border: 1px solid var(--line); font-weight: 600; }
.xl-rows { list-style: none; margin: 0; padding: 0 0 4px 20px; }
.xl-rows > .xl-item:last-child { border-bottom: 0; }
.xl-row { display: grid; grid-template-columns: 12px 1fr; gap: 1px 8px; width: 100%; padding: 6px 0; text-align: left; font: inherit;
  font-weight: 400; color: inherit; background: none; border: 0; border-radius: 0; cursor: pointer; }
.xl-row > .dot, .xl-row > .det-swatch { grid-row: span 3; margin: 4px 0 0; }
.xl-row > :not(.dot):not(.det-swatch) { grid-column: 2; }
.xl-row:hover .xl-name { text-decoration: underline; }
.xl-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.xl-name { font-weight: 600; }
.xl-status:empty { display: none; }
.xl-det .xl-name { font-weight: 500; }
.cam { padding: 0 0 8px 20px; }
.xl-cams .cam { padding: 6px 0; }
.cam-btn { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 0.86rem; text-decoration: none; cursor: pointer; }
.cam-btn:hover, .cam-btn[aria-expanded="true"] { border-color: var(--accent); }
.cam-icon { width: 8px; height: 8px; border-radius: 50%; background: var(--danger); flex: none; }
.cam-player { margin-top: 6px; }
.cam-player iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 6px; background: #000; }
.cam-player a { display: inline-block; margin-top: 4px; }
.yt-live-box { padding: 10px 16px 0; }
/* "Watch live on YouTube" (decision 258): shown only while the open region's stream is live. */
.yt-live { display: inline-flex; align-items: center; gap: 8px; padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink); font-weight: 600; text-decoration: none; }
.yt-live:hover { border-color: var(--danger); }
.yt-live.small { margin: 4px 0 0 10px; padding: 2px 10px; font-size: 0.85em; font-weight: 500; }
.yt-live-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--danger); animation: yt-pulse 2s infinite; }
@keyframes yt-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 50%, transparent); } 70%, 100% { box-shadow: 0 0 0 6px transparent; } }
@media (prefers-reduced-motion: reduce) { .yt-live-dot { animation: none; } }
.region-tip-name { all: unset; cursor: pointer; font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.region-tip-name:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.region-tip-live { color: var(--ink-2); }


/* Report a note or profile: a small disclosure next to the author line. */
details.report { display: inline-block; margin-left: .5rem; }
details.report > summary { display: inline; cursor: pointer; list-style: none; }
details.report > summary::-webkit-details-marker { display: none; }
details.report[open] { display: block; margin: .4rem 0 0; }
details.report form { max-width: 28rem; margin-top: .4rem; }
details.report input[name=reason] { width: 100%; }

/* Embedded live map (/embed/map, decision 201): no site header, so the map page fills the
   window, from 420 x 500 up. The connection status and a small mark sit at the end of the
   rewind bar. */
/* The Here button (decision 225), under the zoom buttons. */
.here-ctl .here-btn { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; border: 0;
  border-radius: 4px; background: var(--surface); color: var(--ink); cursor: pointer; }
.here-ctl .here-btn:hover { background: var(--surface-2); }
.here-ctl .here-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.here-ctl .here-btn.on { color: var(--accent); }
.rail-ctl .here-btn.on { background: var(--surface-2); }
@media (prefers-reduced-motion: no-preference) {
  .here-ctl .here-btn.busy svg { animation: rs-blink-fast 0.8s infinite; }
}
.page-map.embed main { height: 100vh; height: 100dvh; height: var(--app-h, 100dvh); min-height: 0; }
.embed #map { min-height: 0; }
.embed .rewind .conn { color: var(--ink-2); margin-left: auto; white-space: nowrap; }
/* Live is already said by the rewind label; the status keeps its words when not live. */
.embed .rewind .conn.live .label, .embed .rewind .conn.past .label { display: none; }
.embed-brand { display: inline-flex; flex: none; border-radius: 6px; }
.embed-brand img { display: block; width: 22px; height: 22px; }
.embed-brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.embed-rx { margin: 0; padding: 10px 16px 0; }
/* The embed's Track chart (decision 218): a section under the map in the left column that folds
   open and closed; open, it takes the lower part of the column and scrolls inside.
   Below 900 px it is one more section in the phone stack. */
@media (min-width: 901px) {
  .page-map.embed main { grid-template-rows: minmax(0, 1fr) auto; }
  .page-map.embed .view-area { grid-column: 1; grid-row: 1; }
  .page-map.embed .side { grid-column: 2; grid-row: 1 / span 2; }
  .embed .chart-pf { grid-column: 1; grid-row: 2; min-width: 0; border-top: 1px solid var(--line); background: var(--surface); }
  .embed .chart-pf > .pf-head { display: flex; margin: 0; }
  .embed .chart-pf > .pf-head .fold-btn { flex: 1; text-align: left; padding: 8px 14px; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; }
  .embed .chart-pf.open > .fold-body { height: 42vh; min-height: 200px; overflow: hidden; }
}
.embed .chart-pf .chart { height: 100%; }
.link-like { background: none; border: 0; padding: 0; font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer; }
.trains-list li.mine { box-shadow: inset 3px 0 0 var(--ink-2); }
.trains-list li.mine.open { box-shadow: inset 3px 0 0 var(--accent); }
.mine-tag { display: inline-block; justify-self: start; margin-top: 3px; font-size: 0.72rem; font-weight: 700; padding: 0 6px; border: 1px solid var(--line); border-radius: 999px; color: var(--ink-2); }
@media (max-width: 900px) {
  .embed .rewind { padding: 4px 8px; }
}

/* Phones and narrow tablets on the site (decision 263; the embed keeps its sections): the map
   fills the screen and is never hidden, a sheet over its lower part holds the panel, and a tab
   bar picks what the sheet shows (Map: a one-line summary; Crossings: the crossings, or the
   regions in the overview; Trains; More: receivers, weather and notes). The sheet is dragged,
   or its handle tapped, between peek, half and full height; the map script sets its height. */
.tabbar, .sheet-top, .more-menu { display: none; }
@media (max-width: 900px) {
  body.sheet-ui { --tabbar-h: 60px; }
  body.sheet-ui main { position: relative; display: block; overflow: hidden; }
  body.sheet-ui .map-pf { position: absolute; top: 0; left: 0; right: 0; bottom: var(--tabbar-h); display: flex; flex-direction: column;
    padding: 0; border: 0; }
  body.sheet-ui .map-pf > h2:first-child { display: none; }
  body.sheet-ui .map-pf > .view-area { display: flex; flex: 1 1 0; min-height: 0; }
  body.sheet-ui .rewind .rw-time { display: block; width: auto; max-width: 11em; }
  body.sheet-ui .leaflet-bottom { bottom: var(--sheet-h, 0px); }
  body.sheet-ui .side { position: absolute; left: 0; right: 0; bottom: var(--tabbar-h); z-index: 1100; display: block; height: 132px;
    overflow-y: auto; overscroll-behavior: contain; background: var(--surface); border-radius: 16px 16px 0 0;
    box-shadow: 0 -4px 18px rgba(22, 25, 28, 0.18); transition: height 0.2s ease; }
  body.sheet-ui.sheet-dragging .side { transition: none; }
  body.sheet-ui .sheet-top { display: block; position: sticky; top: 0; z-index: 2; padding: 0 16px 8px; background: var(--surface); }
  .sheet-handle { display: block; width: 100%; height: 26px; margin: 0; padding: 0; border: 0; background: transparent; cursor: grab; touch-action: none; }
  .sheet-handle span { display: block; width: 42px; height: 5px; margin: 0 auto; border-radius: 3px; background: var(--line); }
  .sheet-peek { margin: 0; font-weight: 600; }
  .sheet-peek .muted { font-weight: 400; }
  /* Only the open tab's parts show in the sheet. */
  body.sheet-ui .side > :not(.sheet-top), body.sheet-ui .side-stack > * { display: none; }
  body.sheet-ui .side > .side-stack { display: contents; }
  body.sheet-ui[data-tab="map"] .side > .region-switch, body.sheet-ui[data-tab="map"] .side > .yt-live-box,
  body.sheet-ui[data-tab="crossings"] .side > .region-pick, body.sheet-ui[data-tab="crossings"] .pf[data-pf="crossings"],
  body.sheet-ui[data-tab="trains"] .pf[data-pf="trains"],
  body.sheet-ui[data-tab="more"] .pf[data-pf="receivers"], body.sheet-ui[data-tab="more"] .pf[data-pf="weather"] { display: block; }
  body.sheet-ui[data-tab="map"] .side > .region-switch { display: flex; }
  /* More: the site's pages and settings, which leave the top bar on phones. */
  body.sheet-ui[data-tab="more"] .side > .more-menu { display: grid; }
  .more-menu { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 4px 16px 12px; }
  .more-menu a, .more-menu button { display: flex; align-items: center; min-height: 44px; padding: 0 12px; border: 1px solid var(--line);
    border-radius: var(--radius); background: var(--surface); color: var(--ink); font: inherit; font-weight: 600; text-decoration: none; text-align: left; }
  /* The top bar on one row: the mark (home), the search, the view switch and the account. */
  body.sheet-ui .topbar, body.sheet-ui .topbar:has(.me-menu) { grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "left search view me"; gap: 8px; padding: 6px 10px; }
  body.sheet-ui .topnav, body.sheet-ui .topbar #notify-btn, body.sheet-ui .topbar > .tools > #theme-btn { display: none !important; }
  body.sheet-ui .topbar .brand { display: inline-flex; }
  body.sheet-ui .topbar .bar-left { gap: 0; }
  body.sheet-ui .map-search { margin: 0; }
  body.sheet-ui .map-search .search-input { padding: 7px 10px; }
  body.sheet-ui .side .pf { padding: 0 16px; border: 0; background: transparent; }
  body.sheet-ui .side .region-switch, body.sheet-ui .side .yt-live-box { padding: 4px 16px 8px; border: 0; }
  body.sheet-ui .side .pf > .pf-body, body.sheet-ui .side .pf > .fold-body { display: block; max-height: none; overflow: visible; padding-bottom: 12px; }
  body.sheet-ui .side .pf > h2 { display: block; margin: 0; padding: 8px 0 4px; }
  body.sheet-ui .side .pf > h2 .fold-btn { pointer-events: none; padding-left: 0; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--ink-2); background: none; border: 0; }
  body.sheet-ui .side .pf > h2 .fold-btn::before { display: none; }
  body.sheet-ui .tabbar { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1200; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    height: var(--tabbar-h); background: #16191c; border-top: 3px solid var(--focus); }
  .tabbar button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: 44px; padding: 0;
    border: 0; border-radius: 0; background: transparent; color: #c9c6bf; font-size: 0.75rem; font-weight: 500; }
  .tabbar button[aria-pressed="true"] { color: var(--focus); font-weight: 700; }
  .tabbar button:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
}

/* Wayside indicators (decision 287), for signed-in users. */
.wi-key { display: inline-block; width: 11px; height: 11px; border-radius: 50%; background: #1f9d55; border: 1.5px solid #1b1f24; margin-right: 6px; vertical-align: middle; }
.wi-block-key { display: inline-block; width: 18px; height: 6px; border-radius: 3px; background: rgba(214, 48, 49, 0.45); margin-right: 6px; vertical-align: middle; }
.train-row .wi-status { color: var(--text); font-weight: 600; }
.train-row .wi-status.held { color: #d63031; }
.wi-popup { display: grid; gap: 2px; min-width: 180px; }
.chart-svg .wi-block rect { fill: rgba(214, 48, 49, 0.35); }
.chart-svg .wi-mast line { stroke: #1b1f24; stroke-width: 1.5; }
.chart-svg .wi-mast circle { stroke: #1b1f24; stroke-width: 1.2; fill: #8a8f98; }
.chart-svg .wi-mast.Clear circle { fill: #1f9d55; }
.chart-svg .wi-mast.Medium-Clear circle { fill: #7cb342; }
.chart-svg .wi-mast.Approach circle, .chart-svg .wi-mast.Approach-Medium circle { fill: #e0a800; }
.chart-svg .wi-mast.Stop circle { fill: #d63031; }
.chart-svg .wi-mast.stale circle { fill: #8a8f98; opacity: 0.5; }
:root[data-theme="dark"] .chart-svg .wi-mast line, :root[data-theme="dark"] .chart-svg .wi-mast circle { stroke: #e6e8eb; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .chart-svg .wi-mast line, :root:not([data-theme="light"]) .chart-svg .wi-mast circle { stroke: #e6e8eb; } }
