/* ── Tokens ───────────────────────────────────────────────── */
:root {
  --cream:       #f4efe4;
  --paper:       #faf6ec;
  --ink:         #1f2a3d;
  --ink-soft:    #3a4863;
  --muted:       #5e6679;   /* AA on --cream (4.7:1) — primary low-emphasis text */
  --faint:       #a8aebc;   /* non-text only: rules, separator marks, decorative icons */
  --rule:        #e3ddcd;
  --rule-soft:   #ece6d6;
  --accent:      #3d5a9c;
  --accent-soft: #e6ecf6;
  --today:       #c2552e;
  --today-soft:  #f6e6dc;
  --today-edge:  #eed4c0;

  --serif: 'Newsreader', Georgia, serif;
  --sans:  'Inter Tight', system-ui, -apple-system, sans-serif;
  --mono:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ── Reset ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, p { margin: 0; }

/* ── Page shell ───────────────────────────────────────────── */
.page {
  max-width: 1280px;
  margin: 0 auto;
  padding: 52px 64px 48px;     /* spec §5: 52px top, 64px sides */
}

/* ── Header ───────────────────────────────────────────────── */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 36px;          /* spec §5: header → today-pills 36px */
}
.page-head h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 40px;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--ink);
}
.tagline {
  margin-top: 12px;
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink-soft);  /* italic + small + serif compounds the contrast hit; bump from --muted */
  letter-spacing: 0.01em;
}
.meta {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-align: right;
  line-height: 1.7;
  white-space: nowrap;
}
.meta-counts { color: var(--muted); }

/* ── Perspective override ─────────────────────────────────
   Top-right meta line above the counts. Quiet by design — most viewers
   never touch it. The dropdown opens directly below, right-aligned. */
.meta { position: relative; }
.meta-perspective {
  font-family: var(--sans);
  font-size: 12px;
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
  margin-bottom: 12px;
  letter-spacing: 0;
}
.meta-pers-label   { color: var(--muted); }
.meta-pers-city    { color: var(--ink); font-weight: 500; }
.meta-pers-offset  {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  margin-left: 6px;
}
.meta-pers-divider { color: var(--faint); margin: 0 6px 0 12px; }
.meta-pers-change {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--accent);
  cursor: pointer;
}
.meta-pers-change:hover { text-decoration: underline; }
.meta-pers-reset {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 11px;
  color: var(--muted);
  cursor: pointer;
  margin-left: 8px;
}
.meta-pers-reset:hover { color: var(--accent); }
.meta-pers-reset[hidden] { display: none; }

/* ── "Viewing N ahead/behind" pill ────────────────────────
   Shows in the meta column below the counts when scrubber delta ≠ 0,
   so the projected nature of the times reads from anywhere on the page.
   Visual language reuses today-pill geometry but with a hollow muted
   dot and a transparent fill — never reads as celebratory. */
.meta-scrub-pill {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  margin-top: 8px;
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--muted) 50%, transparent);
  background: transparent;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink);
  white-space: nowrap;
  transition: opacity 120ms ease;
}
.meta-scrub-pill[hidden] { display: none; }
.scrub-pill-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  border: 1px solid var(--muted);
  background: transparent;
  margin-right: 8px;
  flex-shrink: 0;
}
.scrub-pill-text {
  /* Stabilize width: digits go tabular and the text reserves enough
     room for the longest possible string ("Viewing 11h 45m behind").
     text-align: center keeps the visible text centered within that
     reserved block, so shorter strings don't sit flush-left with a
     dead gap before the separator. */
  display: inline-block;
  min-width: 11.5em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.scrub-pill-sep {
  color: var(--muted);
  margin: 0 6px;
}
.scrub-pill-reset {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
}
.scrub-pill-reset:hover { text-decoration: underline; }
.scrub-pill-reset:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 2px;
  border-radius: 2px;
}

.perspective-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  width: 240px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.06);
  padding: 8px;
  z-index: 20;
}
.perspective-menu[hidden] { display: none; }
.pmenu-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  height: 28px;
  padding: 0 8px;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  user-select: none;
}
.pmenu-row:hover         { background: var(--accent-soft); }
.pmenu-row.selected      { background: transparent; }
.pmenu-row.selected::before {
  content: '';
  position: absolute;
  left: -2px;
  top: 6px; bottom: 6px;
  width: 4px;
  border-radius: 2px;
  background: var(--accent);
}
.pmenu-divider {
  height: 1px;
  background: var(--rule-soft);
  margin: 6px 4px;
}
.pmenu-city   { font-family: var(--sans); font-size: 14px; color: var(--ink); }
.pmenu-offset { font-family: var(--mono); font-size: 11px; color: var(--muted); }

@media (max-width: 720px) {
  /* Perspective control becomes a single button; dropdown is full-width
     below the meta area. (The full-screen sheet variant is a follow-up.) */
  .meta-perspective { justify-content: flex-start; flex-wrap: wrap; }
  .perspective-menu { width: 100%; left: 0; right: auto; }
}

/* ── Body grid ────────────────────────────────────────────── */
.body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  column-gap: 192px;
  row-gap: 56px;
  align-items: start;
}
.clusters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 56px;
  row-gap: 32px;       /* §2: gap between clusters > gap inside a cluster */
}
.empty {
  grid-column: 1 / -1;
  font-family: var(--serif);
  font-style: italic;
  color: var(--muted);
  padding: 48px 0;
}

/* ── Cluster ──────────────────────────────────────────────── */
.cluster { padding-bottom: 12px; }
.cluster-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}
/* Two-line cluster header. Line 1: signed offset relative to viewer
   ("LOCAL · YOU" / "−1 HR" / "+7 HRS"), all caps mono. Line 2: an italic
   muted serif qualitative hint ("their afternoon · still working"). */
.cluster-label {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.12em;
  color: var(--accent);
  text-transform: uppercase;
}
.cluster.cluster-local .cluster-label {
  /* §4 conformance: LOCAL · YOU uses the today coral so the viewer's
     anchor stands apart from the offset-blue of every other cluster. */
  color: var(--today);
}
.cluster-hint {
  font-family: var(--serif);
  font-size: 13px;
  font-style: italic;
  color: var(--muted);
  margin-top: 4px;
  letter-spacing: 0.01em;
}

.cluster-time {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--mono);
  color: var(--ink);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.cluster-time .t {
  font-size: 32px;
  font-weight: 400;
  letter-spacing: -0.02em;
}
.cluster-time .colon {
  letter-spacing: -0.04em;
  margin: 0 -1px;
}
.cluster-time .meta {
  font-size: 14px;
  color: var(--muted);
  letter-spacing: 0.04em;
  font-family: var(--mono);
  text-align: left;
}
.cluster-time .dot {
  color: var(--faint);
  margin: 0 2px;
}

/* (The .cluster-holiday / .next-line classes used to render a
   "Next [country] [holiday], [date]" line below the cluster header
   rule. Removed entirely — that info now lives only in the 14-day
   sidebar. Cluster headers are exactly 2 lines on the left + 1 on
   the right, which keeps every header at the same height without
   needing a min-height reservation.) */

.today-pill {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  background: var(--today-soft);
  color: var(--today);
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.04em;
}
.today-pill::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--today);
  display: inline-block;
}

/* ── Cluster cities grid ──────────────────────────────────────
   All rows in a cluster share one grid via subgrid, so icon / name /
   temp / weather columns line up on the same x-axis. Per-cluster
   only — alignment doesn't span clusters (would orphan single-city
   clusters). Column template per spec:
     icon (fixed 32px) · name (flex, ≥80px) · temp (auto) · wx (auto). */
.cluster-cities {
  display: grid;
  grid-template-columns: 32px minmax(80px, 1fr) auto auto;
  column-gap: 16px;
  align-items: center;
}

/* ── City row (subgrid child) ─────────────────────────────── */
.city-row {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  align-items: center;
  padding: 12px 0;
}
.city-row + .city-row { border-top: 1px dashed var(--rule-soft); }

/* Holiday dimming: city rows whose country has a today-holiday in the
   API render at 0.55 opacity; if ≥75% of a cluster's cities are on
   holiday the cluster head also dims. The weather phrase slot is
   replaced with "holiday · {name}" by the renderer (see app.js). */
.city-row.on-holiday { opacity: 0.55; }
.cluster-head.dimmed { opacity: 0.55; }

/* §5: when on holiday, the weather slot becomes a serif italic line
   "holiday · {name}". Glyph hidden (the slot's first child is the
   .holiday-phrase span — no .glyph rendered for holiday rows). */
.city-wx .holiday-phrase {
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  color: var(--muted);
}
.city-icon {
  color: var(--ink-soft);
  opacity: 0.85;
  line-height: 0;
  /* Center the SVG in its 32px lattice cell even when the glyph
     doesn't fill the full column width. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
}
.city-icon svg { width: 32px; height: 32px; }
.city-icon-fallback {
  width: 32px; height: 22px;
  border: 1px solid var(--rule);
  border-radius: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  opacity: 0.85;
  line-height: 1;
}
.city-name {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.12em;
  color: var(--ink);
}
.city-temp {
  font-family: var(--mono);
  font-size: 15px;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}
.city-temp .slash { color: var(--faint); }
.city-temp .c     { color: var(--muted); }
.city-temp.stale  { color: var(--muted); }
.city-wx {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  color: var(--muted);
  font-style: italic;
  min-width: 100px;
}
.city-wx .glyph { color: var(--faint); line-height: 0; }
.city-wx .glyph svg { width: 22px; height: 22px; }

/* ── Sidebar (desktop) ────────────────────────────────────── */
.sidebar { display: block; }
.sidebar-card {
  background: var(--paper);
  border-radius: 6px;
  border: 1px solid var(--rule);
  padding: 22px 24px 24px;
}
.sidebar-h {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--muted);          /* §4: each accent use is a claim on
                                   attention; sidebar heading isn't one. */
  margin-bottom: 4px;
}
.sidebar-tag {
  font-family: var(--serif);
  font-size: 15px;
  font-style: italic;
  color: var(--muted);
  margin-bottom: 18px;
}
.week-group + .week-group { margin-top: 18px; }
.week-label {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.1em;
  margin-bottom: 10px;
}
.holiday-row {
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 10px;
  padding: 8px 0;
  align-items: baseline;
}
.holiday-row + .holiday-row { border-top: 1px solid var(--rule-soft); }
.holiday-when {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.holiday-name {
  font-size: 15px;
  color: var(--ink);
  line-height: 1.3;
}
.holiday-chips {
  display: flex;
  gap: 10px;
  margin-top: 6px;
  flex-wrap: wrap;
}

/* ── Country chip ─────────────────────────────────────────── */
/* §4 color discipline: country chips are quiet identifiers, not
   highlights. Muted text on paper bg with a hairline rule border. No
   per-country color, no swatch. */
.chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.chip-swatch {
  width: 16px;
  height: 10px;
  border-radius: 1.5px;
  opacity: 0.7;
  display: inline-block;
  flex-shrink: 0;
}

/* ── Mobile sidebar (accordion) — hidden on desktop ───────── */
.sidebar-mobile { display: none; }

/* ── Time scrubber row ─────────────────────────────────────
   Above the cluster grid, below the today-pill strip. Slim and
   secondary by design — thin track, small labels, small thumb,
   no panel chrome. The cluster grid is the dashboard; this is a tool. */
.scrubber-row {
  margin-top: 40px;       /* gap to today-strip; bumped for breathing room */
  margin-bottom: 48px;    /* gap to cluster grid */
  /* Flex (not grid) so the middle column reliably claims remaining
     space on initial paint. Grid's 1fr was occasionally measured
     against intrinsic min-content of the descendant <input type="range">
     and collapsed the labels until first interaction reflowed it. */
  display: flex;
  align-items: center;
  gap: 16px;
}
/* When the today-strip is hidden, the gap above the scrubber widens
   slightly since there's no warm pill row separating it from the header. */
.today-strip[hidden] + .scrubber-row { margin-top: 48px; }

/* Reset button — only visible when delta ≠ 0. Bumped to 32px and
   accent-bordered so it's hard to miss when a scrubbed view is live. */
.scrubber-reset {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--paper);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.scrubber-reset-glyph { font-size: 14px; line-height: 1; }
.scrubber-reset:hover { background: var(--accent-soft); }
.scrubber-reset:active {
  background: var(--accent);
  color: var(--paper);
}
.scrubber-reset:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 2px;
}
.scrubber-reset[hidden] { display: none; }

.scrubber {
  position: relative;
  flex: 1 1 0;             /* claim remaining space in the row */
  min-width: 0;
  /* Container height equals just the track-wrap. Labels are positioned
     absolutely below the track so the .scrubber's vertical center is
     the track's center — which then aligns with the row's center
     (and with the Now button on the left + readout on the right). */
}
.scrubber-track-wrap {
  position: relative;
  width: 100%;
  height: 16px;          /* hit area for the input */
  display: flex;
  align-items: center;
}
.scrubber-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-width: 0;          /* allow shrinking below browser default */
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 2;
}
.scrubber-input:focus { outline: none; }
.scrubber-track {
  position: relative;
  width: 100%;
  height: 4px;
  background: var(--rule-soft);
  border-radius: 2px;
}
.scrubber-fill {
  position: absolute;
  top: 0; bottom: 0;
  background: var(--accent);
  opacity: 0.6;
  border-radius: 2px;
  /* left + width set by JS */
}
.scrubber-tick {
  position: absolute;
  width: 1px;
  height: 6px;
  top: -1px;
  background: var(--rule);
  pointer-events: none;
  /* left set by JS for hour ticks */
}
.scrubber-tick-now {
  height: 12px;
  background: var(--faint);
  top: -4px;
  left: 50%;
}
.scrubber-thumb {
  position: absolute;
  top: 50%;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--cream);
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
  transform: translate(-50%, -50%);
  transition: left 120ms ease, box-shadow 120ms ease;
  pointer-events: none;
  z-index: 1;
  /* left set by JS */
}
.scrubber-input:focus-visible ~ .scrubber-thumb {
  box-shadow: 0 0 0 3px var(--accent-soft), 0 1px 3px rgba(0,0,0,0.08);
}
.scrubber-labels {
  /* Hang below the track absolutely so the .scrubber's box height is
     just the track-wrap (16px). That makes vertical centering of the
     row align the track midline with the Now button + readout. */
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--muted);
  user-select: none;
  pointer-events: none;
}
.scrubber-readout {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
  flex: 0 0 auto;
  /* Tabular numerals + a stable min-width so the row doesn't jitter
     horizontally as the digits / delta change with each tick. Widest
     content is "12:00 AM thu −12h 00m" — ~22 chars at 14px mono. */
  min-width: 200px;
  font-variant-numeric: tabular-nums;
}
.scrubber-readout .delta {
  color: var(--muted);
  font-size: 12px;
  margin-left: 6px;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  /* Readout drops below the slider on its own line. */
  .scrubber-row {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "reset slider"
      "readout readout";
    margin-bottom: 24px;
  }
  .scrubber-reset    { grid-area: reset; }
  .scrubber          { grid-area: slider; }
  .scrubber-readout  {
    grid-area: readout;
    text-align: left;
    min-width: 0;
    margin-top: 6px;
  }
}

/* ── "Today across the team" band — full-width, above the cluster grid.
   Renders the same .today-pill components used in cluster headers; the
   pills are ordered by cluster sequence (MEXICO → … → JAPAN). The band
   only appears when something is celebrated today; otherwise the JS
   sets [hidden] on the wrapper. */
.today-strip {
  /* No bottom margin — the scrubber-row's top margin (24px per spec §5)
     controls the gap between the today band and the scrubber. */
  margin-bottom: 0;
  display: flex;
  flex-wrap: wrap;
  /* Centered (not baseline) — pill chrome adds vertical padding that
     makes its baseline sit below the bare-text "Today in:" prefix.
     Centering aligns the visual mid-line of both elements. */
  align-items: center;
  column-gap: 12px;
  row-gap: 8px;
}
.today-strip[hidden] { display: none; }
/* "Today in:" prefix label — lifted out of every pill so the phrase
   isn't repeated. Italic Newsreader matches the page's existing
   subtitle voice. Sits at the start of the row only; pills follow on
   the same baseline and wrap independently of it. */
.today-prefix {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 14px;
  color: var(--muted);
  margin-right: 4px;
}

/* ── Footer ───────────────────────────────────────────────── */
.page-foot {
  margin-top: 56px;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 14px;
  color: var(--muted);
}
.footer-fetched { color: var(--ink-soft); font-family: var(--mono); }

/* ── Mobile (≤ 720px) ─────────────────────────────────────── */
@media (max-width: 720px) {
  .page {
    padding: 40px 24px 32px;
  }

  .page-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 24px;
  }
  .page-head h1 { font-size: 32px; }
  .tagline { font-size: 15px; }
  .meta { text-align: left; font-size: 12px; }

  .body {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .clusters {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 28px;
  }

  /* Hide the desktop sidebar, show the <details> accordion below clusters */
  .sidebar { display: none; }
  .sidebar-mobile {
    display: block;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 16px 18px;
  }
  .sidebar-mobile > summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.18em;
    color: var(--muted);          /* §4: matches desktop .sidebar-h */
  }
  .sidebar-mobile > summary::-webkit-details-marker { display: none; }
  .sidebar-mobile-count {
    font-family: var(--mono);
    font-size: 13px;
    color: var(--muted);
    letter-spacing: 0;
    font-weight: 400;
  }
  .sidebar-mobile #sidebarMobileList { margin-top: 14px; }
  .sidebar-mobile .holiday-row { grid-template-columns: 56px 1fr; padding: 10px 0; }
  .sidebar-mobile .holiday-row + .holiday-row { border-top: 1px solid var(--rule-soft); }

  .page-foot {
    margin-top: 32px;
    padding-top: 14px;
    flex-direction: column;
    gap: 4px;
    font-size: 13px;
  }
}
