/* CSS custom properties (aka CSS variables): each --name below is defined
   once here and reused throughout this file via var(--name), so a color
   only ever needs changing in one place. :root just means "the whole
   document" -- these are usable everywhere, not scoped to one element. */
:root {
  /* Tells the browser this page is light-themed, so native controls it
     draws itself (checkboxes, scrollbars) use a matching light appearance
     instead of following the OS's own dark/light setting regardless of
     ours. Overridden to "dark" below when dark mode is on. */
  color-scheme: light;
  --color-bg: #e3b36b;
  --color-card: #ffffff;
  /* Slightly different from --color-card so overlays like the settings
     panel read as a distinct layer floating above the cards, not just
     another card. */
  --color-panel: #f7f1e6;
  --color-text: #1f2328;
  --color-muted: #83766a;
  --color-border: #e8e6e1;
  --color-accent: #b45309;
  /* Text/icon color to use on top of --color-accent -- needs to flip
     between themes since the accent itself gets lighter in dark mode
     (see below), so one fixed color can't stay readable on both. */
  --color-accent-contrast: #ffffff;
  --color-danger: #b00020;
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
  background: var(--color-bg);
  color: var(--color-text);
}

.dashboard {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  padding: 1rem;
  min-height: 100vh;
}

/* News : Weather : Fun Fact/Clock = 2 : 1 : 1 -- i.e. News takes half the
   column's height, and the other two rows take a quarter each (same height
   as each other), regardless of how much each one's own content needs. */
.right-column {
  display: grid;
  grid-template-rows: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.25rem;
  height: calc(100vh - 2rem);
  min-width: 0;
}

.widget-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  min-width: 0;
}

.widget {
  background: var(--color-card);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

#trains-widget {
  max-height: calc(100vh - 2rem);
}

.widget h2,
.settings-panel-header h2 {
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.widget h2 {
  margin: 0 0 0.75rem 0.75rem;
  flex-shrink: 0;
}

/* This doesn't replace the shared ".widget h2" rule above -- both apply to
   the same element at once (CSS rules stack unless they set the same
   property, in which case the more specific selector wins). This one only
   adds flex layout on top of the margin/font settings already set above. */
#trains-widget h2 {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  /* .widget-hint right below carries the bottom gap instead, so this
     doesn't need its own -- otherwise the two would stack. */
  margin-bottom: 0.25rem;
}

.widget-hint {
  margin: 0 0 0.75rem 0.75rem;
  font-size: 0.8rem;
  color: var(--color-muted);
}

#fact-refresh,
#station-search-clear,
#settings-close {
  font-size: 1rem;
  line-height: 1;
  border: 1px solid var(--color-border);
  background: var(--color-card);
  border-radius: 6px;
  padding: 0.2rem 0.5rem;
  cursor: pointer;
  vertical-align: middle;
  color: var(--color-text);
}

#fact-refresh:hover,
#station-search-clear:hover,
#settings-close:hover {
  background: var(--color-bg);
  border-color: var(--color-accent);
}

#fact-refresh:focus-visible,
#news-list a:focus-visible,
#station-search-input:focus-visible,
#station-search-clear:focus-visible,
#settings-toggle:focus-visible,
#settings-close:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.station-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  font-weight: 400;
  letter-spacing: normal;
}

/* visibility (not the hidden attribute) so the button keeps its layout
   space -- otherwise it appearing/disappearing shifts the search input
   next to it. */
#station-search-clear.is-hidden {
  visibility: hidden;
}

#station-search-input,
#favorite-station-input {
  /* Form inputs don't inherit font styling from their parent by default
     (browsers give them their own base font) -- "font: inherit" grabs the
     surrounding text's font wholesale, then font-size below overrides just
     that one piece of it. */
  font: inherit;
  font-size: 0.85rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  /* Inputs also default to a plain white background regardless of theme --
     harmless in light mode (the card is white too), but glaring in dark
     mode without this. */
  background: var(--color-card);
  color: var(--color-text);
}

#station-search-input {
  width: 11rem;
}

#favorite-station-input {
  width: 100%;
}

#favorite-station-input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.station-suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.25rem;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  box-shadow: var(--shadow-card);
  list-style: none;
  padding: 0.25rem;
  min-width: 12rem;
  font-weight: 400;
  z-index: 10;
}

/* The Trains header's search box sits at the right edge of the widget, so
   its dropdown needs to hang from the right instead of the panel-picker's
   left-aligned default above. */
.station-search .station-suggestions {
  left: auto;
  right: 0;
}

.station-suggestions li {
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.85rem;
}

.station-suggestions li:hover {
  background: var(--color-bg);
}

.station-suggestions li.station-suggestions-empty {
  color: var(--color-muted);
  cursor: default;
}

.station-suggestions li.station-suggestions-empty:hover {
  background: none;
}

/* News/Weather/Fun Fact all fit their content to the available space in JS
   (see trimToFit in dashboard.js) and must never show a scrollbar, so
   hidden is the right default. Trains is the one widget with a genuinely
   long, natively-scrolling list -- it opts back into scrolling below. */
.widget-content {
  overflow: hidden;
  flex: 1;
  min-height: 0;
  padding-left: 0.75rem;
}

#trains-widget .widget-content {
  overflow-y: auto;
}

/* News handles its own left indent via #news-list li's padding instead
   (see below), so its hover highlight can bleed further left than the
   text -- the shared indent above would only push the text over, not
   the highlight box with it. */
#news-widget .widget-content {
  padding-left: 0;
}

/* Shared by the weather widget's resolved-location note and the news
   widget's source note -- both are a small muted aside next to a heading. */
.widget-heading-note {
  color: var(--color-muted);
  font-weight: 500;
  font-size: 0.95rem;
}

.weather-forecast {
  display: flex;
  gap: 1rem;
  overflow: hidden;
}

.weather-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}

/* Marks where the forecast crosses into the next calendar day. */
.weather-slot--new-day {
  border-left: 1px solid var(--color-border);
  padding-left: 0.75rem;
}

.weather-time {
  font-size: 0.8rem;
  color: var(--color-muted);
}

.weather-icon {
  font-size: 1.75rem;
}

.weather-temp {
  font-weight: 500;
}

.train-block {
  margin-bottom: 1rem;
}

/* With exactly 2 favorite stations, show them side by side instead of
   stacked, each with its own independently-scrolling list -- otherwise one
   station having far more departures than the other pushes everything else
   down instead of just scrolling its own column. */
#trains-defaults.trains-defaults--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  height: 100%;
}

#trains-defaults.trains-defaults--split .train-block {
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin-bottom: 0;
}

#trains-defaults.trains-defaults--split .train-list {
  flex: 1;
  overflow-y: auto;
  /* Without this, a flex item won't shrink below its content's natural
     size, so the list would grow instead of scrolling -- the same fix
     used elsewhere in this file for flex/grid children that need to
     scroll rather than expand. */
  min-height: 0;
}

.train-block h3,
.settings-section h3 {
  color: var(--color-muted);
  font-size: 0.9rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.settings-section h3 {
  margin: 0;
}

.train-block h3 {
  position: sticky;
  top: 0;
  background: var(--color-card);
  margin: 0;
  padding: 0.5rem 0;
}

.train-list,
#news-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.train-list li,
#news-list li {
  border-bottom: 1px solid var(--color-border);
}

.train-list li {
  padding: 0.5rem 0;
  display: grid;
  grid-template-columns: 4.5em 1fr 2.5em;
  gap: 0.5rem;
  align-items: baseline;
  font-variant-numeric: tabular-nums;
}

.train-list li>span:nth-child(2) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* The "no departures" message is plain text, not the usual 3 spans --
   without this it inherits the grid above and gets squeezed into the
   4.5em time column, wrapping one word per line. */
.train-list li.train-empty {
  display: block;
}

.error {
  color: var(--color-danger);
}

.flag {
  color: var(--color-danger);
  font-weight: bold;
}

.news-time {
  color: var(--color-muted);
  margin-right: 0.5rem;
  font-variant-numeric: tabular-nums;
}

#news-list li {
  /* Symmetric padding: the left side both aligns the timestamp with the
     widget heading above and gives the hover highlight box room to
     extend left of the text instead of hugging it. */
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  transition: background-color 0.15s ease;
}

#news-list li:hover {
  background: var(--color-bg);
}

#news-list a {
  color: var(--color-text);
  text-decoration: none;
  font-weight: 500;
  line-height: 1.4;
}

#news-list a:visited {
  color: var(--color-text);
}

#news-list a:hover {
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
}

/* padding: 0.5rem 0 already zeroes left/right (the 2-value shorthand is
   top/bottom, left/right) -- centered content ignores .widget-content's
   heading-alignment indent for free, no extra override needed. */
.clock-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.5rem 0;
}

.clock-display {
  font-size: 2.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.clock-colon {
  color: var(--color-accent);
  display: inline-block;
  /* The colon glyph's ink sits lower than the digits' -- measured via
     canvas actualBoundingBox at this font: digits center ~14px above
     baseline, the colon ~10px, a 4px (0.1em) gap at this font size. */
  transform: translateY(-0.1em);
}

.clock-date {
  color: var(--color-accent);
  font-size: 1.15rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Dark mode: overriding these same custom properties is all that's needed --
   every color in this file is already written as var(--color-x), so nothing
   else has to change when [data-theme="dark"] is set on <html>. Kept in the
   same warm amber/brown family as the light theme above (rather than a
   generic neutral dark gray) so it reads as a dark version of the same app
   instead of an unrelated palette. */
[data-theme="dark"] {
  color-scheme: dark;
  --color-bg: #2b1c0e;
  --color-card: #3c2a17;
  --color-panel: #332410;
  --color-text: #f5ead9;
  --color-muted: #c2a688;
  --color-border: #55402a;
  --color-accent: #e8a54c;
  --color-accent-contrast: #2b1c0e;
  --color-danger: #ff6b6b;
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.4);
}

#settings-toggle {
  position: fixed;
  bottom: 1.5rem;
  left: 1.5rem;
  width: 2.75rem;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  line-height: 1;
  border: none;
  /* Filled with the accent color (rather than blending in like the other
     small icon buttons) so it reads as its own always-visible control, not
     something that belongs to a particular widget. */
  background: var(--color-accent);
  border-radius: 50%;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  color: var(--color-accent-contrast);
  z-index: 20;
}

#settings-toggle:hover {
  filter: brightness(1.1);
}

#settings-panel {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: 260px;
  max-width: 80vw;
  background: var(--color-panel);
  box-shadow: var(--shadow-card);
  padding: 1.25rem;
  z-index: 30;
  /* Off-screen by default; .is-open slides it into view. Doing this with
     transform (not display/visibility) is what makes it animate smoothly
     instead of just popping in. */
  transform: translateX(-100%);
  transition: transform 0.2s ease;
}

#settings-panel.is-open {
  transform: translateX(0);
}

.settings-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.settings-panel-header h2 {
  margin: 0;
}

.settings-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  cursor: pointer;
}

.settings-option input[type="checkbox"] {
  /* Removes the checkbox's own default margin so align-items: center above
     centers it against the label text with nothing extra thrown in. */
  margin: 0;
}

.settings-section {
  margin-top: 1.25rem;
}

.settings-hint {
  margin: 0.25rem 0 0.5rem;
  font-size: 0.8rem;
  color: var(--color-muted);
}

.favorite-station-search {
  position: relative;
}

.favorite-station-list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
}

.favorite-station-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.3rem 0;
  font-size: 0.9rem;
}

.favorite-remove {
  border: none;
  background: none;
  color: var(--color-muted);
  font-size: 1rem;
  line-height: 1;
  padding: 0 0.25rem;
  cursor: pointer;
}

.favorite-remove:hover {
  color: var(--color-accent);
}

@media (max-width: 700px) {
  .dashboard {
    grid-template-columns: 1fr;
  }

  .widget-pair {
    grid-template-columns: 1fr;
  }
}