/* home · 4 of 4: custom time picker, day navigation, calendar day view, today briefing, column stacks, weather, contrast audit.
   Split from home.css 2026-07-29 (1665 lines). The four load in order from
   templates/index.html and cascade as one sheet: order between them is
   load-bearing (the contrast audit block at the end of day.css wins on it). */
/* ── custom time picker ──────────────────────────────────────────────────── */
.time-dropdown-wrap { position: relative; }
.time-dropdown-trigger {
  cursor: pointer; user-select: none;
  display: flex; align-items: center;
}
.time-dropdown-trigger.placeholder { color: var(--fg-faint); font-style: italic; }
.time-dropdown-trigger.open { border-color: var(--accent-dim); }
.time-dropdown-list {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0;
  z-index: 2000;
  overflow-y: scroll;
  background: var(--bg-elev);
  border: 1px solid var(--accent-dim);
  border-radius: var(--r-card);
  box-shadow: 0 4px 16px rgba(0,0,0,0.25);
}
.time-dropdown-item {
  padding: 0 12px;
  font-size: 14px; color: var(--fg);
  cursor: pointer;
}
.time-dropdown-item:hover { background: var(--bg-hover, var(--bg-elev)); color: var(--fg); }
.tb-weekday-name { font-family: var(--font-display); font-size: 32px; line-height: 0.95; color: var(--fg); }
/* day-navigation arrows + back-to-today chip in the briefing header */
.tb-daynav-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; font-size: 20px; line-height: 1;
  color: var(--fg-dim); background: var(--bg-elev-2);
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  cursor: pointer; transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.tb-daynav-arrow:hover:not(:disabled) { color: var(--accent); border-color: var(--accent-faint); }
.tb-daynav-arrow:disabled { opacity: 0.3; cursor: default; }
/* right-aligned text link (not a pill) so it reads as a nav action, separated
   from the day name — margin-left:auto floats it to the right edge of the day
   column, left of the weather tile. */
.tb-daynav-today {
  margin-left: auto; padding: 0; font-size: 13px;
  letter-spacing: 0.02em; color: var(--fg-dim);
  background: transparent; border: 0; cursor: pointer;
  transition: color 0.12s;
}
.tb-daynav-today:hover { color: var(--accent); }
.tb-datemeta { font-size: 13px; color: var(--fg-dim); margin-top: var(--s-2); letter-spacing: 0.02em; }
.tb-progress { flex: 1; height: 7px; background: var(--bg-elev-2); border: 1px solid var(--line-strong); border-radius: var(--r-pill); overflow: hidden; }
.tb-progress-fill { display: block; height: 100%; background: var(--accent); }
.tb-prog-pct { font-size: 11px; color: var(--fg-faint); letter-spacing: 0.12em; text-transform: uppercase; white-space: nowrap; }

/* The old `.tb-weather` topbar tile (38px temp, hard shadow, .tb-wx-top/-bot,
   .tb-temp/.tb-cond/.tb-hilo/.tb-precip) lived here until 2026-07-27. Every one
   of those classes was overridden by `.day-weather` further down the file — two
   rulesets fighting through specificity to style one component — and the tile
   itself was already unreferenced. Deleted; the weather block now owns its own
   vocabulary in one place (see "weather block", below `.col-head`). */

/* timeline rail head (shared by the day-view grid below) */
.tb-rail-head { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2); }
.tb-rail-t { font-family: var(--font-display); font-size: 12px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--fg-mute); }
.tb-count { font-family: var(--font-display); font-size: 10px; color: var(--accent); border: 1.5px solid var(--accent); border-radius: var(--r); padding: 2px 6px; }
.tb-rail-rule { flex: 1; height: 1px; background: var(--line); }

/* calendar day view — vertical hour grid with events placed by their times */
.tb-day { max-height: 62vh; overflow-y: auto; padding-top: 12px; }
.tb-day-allday { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-bottom: var(--s-2); }
.tb-day-chip {
  font-size: 13px; color: var(--fg); text-transform: lowercase;
  border: 1.5px solid var(--line); border-left: 4px solid var(--accent); border-radius: var(--r);
  background: var(--bg-elev); padding: 3px var(--s-2);
}
.tb-day-chip.done { color: var(--fg-dim); text-decoration: line-through; }

.tb-day-grid { position: relative; }
/* one hour line + its gutter label */
.tb-day-hr { position: absolute; left: 0; right: 0; height: 0; }
.tb-day-hr-label {
  position: absolute; left: 0; top: -7px; width: 44px; text-align: right;
  font-family: var(--font-display); font-size: 10px; letter-spacing: 0.04em;
  color: var(--fg-faint); text-transform: uppercase;
}
.tb-day-hr-line { position: absolute; left: 50px; right: 0; top: 0; height: 1px; background: var(--line-soft); }

/* the "now" indicator — a line across the grid with a dot in the gutter */
.tb-day-now { position: absolute; left: 44px; right: 0; height: 0; z-index: 3; pointer-events: none; }
.tb-day-now::after { content: ""; position: absolute; left: 6px; right: 0; top: 0; height: 1.5px; background: var(--alert); }
.tb-day-now-dot { position: absolute; left: 0; top: -3px; width: 7px; height: 7px; border-radius: var(--r); background: var(--alert); }

/* "time skip" divider — stands in for a long event's collapsed dead middle.
   Dashed top/bottom so it reads as a deliberate cut, not a stray panel; the
   label states the true skipped duration so the event's real length stays
   legible even though the band itself is a fixed height. */
.tb-day-skip {
  position: absolute; left: 50px; right: 0; z-index: 4; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  border-top: 1px dashed var(--line-strong); border-bottom: 1px dashed var(--line-strong);
  background: var(--bg-elev);
}
.tb-day-skip-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--fg-dim); background: var(--bg); padding: 1px var(--s-2); border-radius: var(--r-pill);
}

/* event blocks live in the lane area right of the gutter; absolute-positioned
   by start (top) / duration (height), with left+width set per overlap lane */
.tb-day-lanes { position: absolute; left: 50px; right: 0; top: 0; bottom: 0; }
.tb-day-ev {
  position: absolute; box-sizing: border-box; overflow: hidden;
  display: flex; flex-direction: column; gap: 2px;
  border: 1.5px solid var(--line); border-left: 4px solid var(--accent); border-radius: var(--r);
  background: var(--bg-elev); padding: 5px var(--s-2) 5px 10px;
  margin-right: 5px; margin-bottom: 2px;
}
.tb-day-ev.is-task { border-left-style: dashed; }
.tb-day-ev.has-link { cursor: pointer; }
.tb-day-ev.has-link:hover { border-color: var(--accent); }
.tb-day-ev-name { display: block; font-size: 14px; line-height: 1.3; color: var(--fg); text-transform: lowercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right: 18px; }
.tb-day-ev-time { display: block; font-size: 11.5px; color: var(--accent); font-weight: 700; letter-spacing: 0.03em; }
.tb-day-ev.done .tb-day-ev-name { color: var(--fg-dim); text-decoration: line-through; }

/* clickable location → Google Maps directions; stays on its own line under time */
.tb-day-ev-loc {
  display: flex; align-items: center; gap: 4px; margin-top: 1px;
  font-size: 11.5px; color: var(--fg-mute); text-decoration: none; cursor: pointer;
  text-transform: lowercase; white-space: nowrap; overflow: hidden;
}
.tb-day-ev-loc:hover { color: var(--accent); }
.tb-day-ev-loc:hover .tb-day-ev-loc-txt { text-decoration: underline; }
.tb-day-ev-loc-pin { flex: none; opacity: 0.85; }
.tb-day-ev-loc-txt { overflow: hidden; text-overflow: ellipsis; }

/* pencil edit affordance — top-right, revealed on hover (keyboard-focusable) */
.tb-day-ev-edit {
  position: absolute; top: 2px; right: 3px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0;
  border: none; background: transparent; color: var(--fg-mute); cursor: pointer;
  opacity: 0; transition: opacity 0.12s ease;
}
/* 18px glyph, 24px hit area (WCAG 2.5.8). Overlay rather than a bigger box so a
   short event block does not get its corner clipped by the block's overflow:hidden. */
.tb-day-ev-edit::after { content: ""; position: absolute; inset: -3px; }
.tb-day-ev:hover .tb-day-ev-edit, .tb-day-ev-edit:focus-visible { opacity: 1; }
.tb-day-ev-edit:hover { color: var(--accent); }

/* calm empty-state filler for a panel with no cards on a light day */
.tb-panel-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 5px; text-align: center; min-height: 64px;
  padding: var(--s-3);
  border: 1.5px dashed var(--line); border-radius: var(--r-card);
}
.tb-pe-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px;
  border: 1.5px solid var(--line); color: var(--fg-mute);
  font-size: 15px; opacity: 0.7;
}
.tb-pe-title { font-family: var(--font-display); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--fg-mute); }
.tb-pe-sub { font-size: 12px; color: var(--fg-faint); font-style: italic; }

.tb-card {
  break-inside: avoid; margin-bottom: 0;
  border: 2px solid var(--line); border-top: 3px solid var(--accent); border-radius: var(--r-card);
  background: var(--bg-elev);
}
.tb-card-alert { border-top-color: var(--alert); }
.tb-card-h { display: flex; align-items: center; justify-content: space-between; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
.tb-card-name { font-family: var(--font-display); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--fg-mute); }
.tb-card-alert .tb-card-name { color: var(--alert); }
.tb-card-badge { font-family: var(--font-display); font-size: 10px; color: var(--accent); border: 1.5px solid var(--accent); border-radius: var(--r); padding: 2px 6px; }
.tb-card-alert .tb-card-badge { color: var(--alert); border-color: var(--alert); }
.tb-card-b { padding: var(--s-2) var(--s-3) var(--s-3); }
.tb-li { display: flex; gap: var(--s-2); align-items: baseline; font-size: 14px; color: var(--fg); padding: 4px 0; }
.tb-li + .tb-li { border-top: 1px dashed var(--line-soft); }
.tb-li::before { content: ""; flex: none; width: 6px; height: 6px; margin-top: 6px; background: var(--accent); border-radius: var(--r); }
.tb-card-alert .tb-li::before { background: var(--alert); }
.tb-li-when { font-weight: 700; color: var(--accent); letter-spacing: 0.02em; }
.tb-li-src { color: var(--fg-faint); font-style: italic; font-size: 12px; }
.tb-pill { font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--alert); border: 1px solid var(--alert); border-radius: var(--r); padding: 1px 6px; margin-left: auto; align-self: center; }
.tb-pill-soft { color: var(--warn); border-color: var(--warn); }
/* long-stale overdue (30d+) drops the full-alarm red — same red for a 2-day slip
   and a 4-month one trains the eye to tune the color out entirely (home critique
   P2: overdue triage). Text carries the actual age so the signal isn't just lost. */
.tb-pill-stale { color: var(--fg-dim); border-color: var(--line-strong); text-transform: none; letter-spacing: 0.02em; }
.tb-empty { font-size: 13px; color: var(--fg-dim); font-style: italic; margin-bottom: var(--s-4); }

/* tickable checklist rows (bring/prep). Inherit .tb-li layout but swap the
   decorative bullet for a real checkbox; checking strikes the row through. */
.tb-check-li { width: 100%; text-align: left; background: none; border: none; cursor: pointer; font: inherit; }
.tb-check-li::before { display: none; }
.tb-check {
  flex: none; width: 15px; height: 15px; margin-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--accent); border-radius: var(--r);
  font-size: 10px; line-height: 1; color: var(--on-accent); background: transparent;
}
.tb-check-li.is-done .tb-check { background: var(--accent); }
.tb-check-text { flex: 1; color: var(--fg); }
.tb-check-li:hover .tb-check-text { color: var(--accent); }
.tb-check-li.is-done .tb-check-text { color: var(--fg-faint); text-decoration: line-through; }
.tb-li-tag {
  font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent);
  border: 1px solid var(--line-strong); border-radius: var(--r); padding: 1px 5px;
  margin-left: auto; align-self: center; flex: none;
}

/* "done" recap — what I did that day, a hand-authored plain-language summary of
   the big strokes (not the raw op log). Read-only history, so it reads as flowing
   prose rather than checkable rows: dimmed, comfortable line-height, an accent
   rule on the left to mark it as a record. Multiple paragraphs space apart. */
.tb-recap { display: flex; flex-direction: column; gap: 8px; }
.tb-recap-p {
  margin: 0;
  color: var(--fg-dim);
  line-height: 1.5;
  font-size: 0.92em;
  padding-left: 10px;
  border-left: 2px solid var(--accent);
}

/* checklist register: one checked row per genuinely-completed thing, each a
   one-line title that expands to the fuller explanation (native <details>). The
   check is a static record (these are already done), not an interactive toggle. */
.tb-recap-list { display: flex; flex-direction: column; gap: 6px; }
.tb-recap-li {
  color: var(--fg-dim);
  line-height: 1.45;
  font-size: 0.92em;
}
.tb-recap-sum {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  cursor: pointer;
  list-style: none;  /* kill the native triangle; the row itself is the affordance */
}
.tb-recap-sum::-webkit-details-marker { display: none; }
.tb-recap-li.is-bare .tb-recap-sum { cursor: default; }
.tb-recap-mark {
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--accent);
  font-weight: 600;
}
/* the title is one line — the explanation lives behind the expand, so a long
   day's recap stays a scannable list instead of a wall of paragraphs. */
.tb-recap-text {
  flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tb-recap-li[open] .tb-recap-text { white-space: normal; }
.tb-recap-detail {
  margin: 4px 0 8px 22px;
  padding-left: 10px;
  border-left: 2px solid var(--accent);
  line-height: 1.5;
}
/* expander for the capped recap list (see chrome.jsx TodayDoneCap RECAP_CAP) —
   a plain text-link affordance, not another card, so it doesn't add its own
   visual weight to a section that's already meant to be quiet. */
.tb-recap-more {
  display: block; margin-top: var(--s-2); padding: 0;
  font-size: 12px; color: var(--accent); text-decoration: underline;
  background: none; border: 0; cursor: pointer; text-align: left;
}
.tb-recap-more:hover { opacity: 0.8; }

/* narrow windows / phones: drop the 3-up card grid to 2 then 1, and stack the
   header band. (The .tb-weather min-width reset that used to live here went with
   the tile itself — the weather block is fluid now and needs no override.) */
@media (max-width: 780px) {
  .tb-cards { column-count: 2; }
}
.time-dropdown-item.active { color: var(--accent); background: var(--accent-faint); }

/* ---------------- today briefing (structure intact, styling inherited) ----------------
   The today briefing keeps its original 3-cell structure (calendar / done / prep). The
   ONLY thing that changed is styling: it inherits the standard uniform page background
   — no tinted --bg-elev band, no frames — so it reads as part of the same one-shade
   sheet as everything else. Its cells share the body's column template (--home-cols)
   and use the SAME divider as .col (var(--line)), so the body columns below follow the
   today-brief columns as one continuous set of columns (a subtle hairline marks where
   the briefing ends). (Earlier tries tinted the band, then framed the cells, then
   dissolved the briefing into the columns — all wrong; the fix is restyle-only.) */
.today-header {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  background: transparent;
}
.th-date { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.th-weekday { display: flex; align-items: center; gap: var(--s-2); }
.th-prog { display: flex; align-items: center; gap: var(--s-2); flex: 0 1 340px; min-width: 200px; }

/* uniform surface; a soft hairline (matching the panel separators) marks the end of
   the briefing. the grid shares the body column template so cells line up with the
   columns beneath. */
.today-zone { background: transparent; border-bottom: 1px solid var(--line); }
.today-zone-grid {
  display: grid; grid-template-columns: var(--home-cols);
  align-items: stretch; max-height: 380px;
}
.today-cap {
  min-width: 0; overflow-y: auto;
  padding: var(--s-3) var(--s-4) var(--s-4);
  border-right: 1px solid var(--line);   /* same divider as .col, so columns are continuous */
}
.today-cap:last-child { border-right: 0; }
.today-cap::-webkit-scrollbar { width: 6px; }
.today-cap::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: var(--r-pill); }

/* ---------------- home 3-column stacks ----------------
   The old full-width today header + 3-cell today zone were dissolved into the three
   body columns; each .col is now one continuous top-to-bottom stack. A .col-head
   gives the left/middle columns a section title (schedule / tasks) styled like the
   card panels' .panel-title. The today calendar (.col-cal), day-view checklist
   (.col-prep), done recap (.col-done), and the weather band (.day-weather) are plain
   blocks — no grid-cell borders, no per-block header (the right column stays
   header-less until the tasks head). */
.col-head {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-4) var(--s-4) var(--s-2);
  border-bottom: 1px solid var(--panel-head-line);
}
/* the column-level heads (schedule / recap / tasks) are the primary section
   markers; sub-panels nested inside them (cards, subscriptions) should read as
   subordinate, not the same weight — home critique P2 called out the flattened
   hierarchy where every panel-title reads identically loud. */
.col-head .panel-title { font-size: var(--title-1); font-weight: 600; }
.col-rest-divider .panel-head .panel-title { font-size: var(--title-3); font-weight: 500; color: var(--fg-mute); }
.col-cal, .col-prep, .col-done, .col-bring { min-width: 0; padding: var(--s-3) var(--s-4) var(--s-4); }
/* the day schedule is always fully expanded — no inner scroll on the calendar grid;
   the whole left column flows and the page scroll handles it. */
.col-cal .tb-day { max-height: none; overflow: visible; }
.col-prep .tb-card { margin-top: var(--s-3); }
.col-prep .tb-card:first-of-type { margin-top: 0; }

/* a bare .col-done sitting directly at the top of its column (no col-head
   above it) drops its own top padding so it starts flush with the column's
   top edge instead of leaving a gap where a header would have been. Inert
   now that a "recap" col-head precedes it (no longer :first-child) — left in
   place in case done ever renders header-less again. */
.col > .col-done:first-child { padding-top: 0; }

/* soft break between the today-scoped block (calendar / recap / bring+due) and
   the column's remaining content below it (forward schedule / cards+subs /
   planner list) — dashed + --line-soft, the same low-contrast idiom used for
   in-panel row separators (event-row, sub-row), not the solid --line-strong
   used for structural boundaries like .col-head. The divider's TOP is aligned
   across columns by the shared `.body` grid row (see "body grid" above), so
   this only needs one fixed spacing value, not a per-column computed one. */
.col-rest-divider { border-top: 1px dashed var(--line-soft); margin-top: var(--s-2); padding-top: var(--s-3); }
/* Only the FIRST panel in a .col-rest-divider sits flush against the dashed
   divider line, so only its .panel-head drops the default var(--s-4) top padding
   (which would otherwise double up with the divider's own padding-top and make
   the middle column's gap bigger than the other two). Scoped to :first-child so
   a SECOND stacked panel (Subscriptions, below CreditCards) keeps its top padding
   and doesn't jam its header against the panel above — that missing gap was the
   "subscriptions header cut off at top". */
.col-rest-divider > .panel:first-child .panel-head { padding-top: 0; }

/* ---------------------------------------------------------------------------
   weather block — the top of the right column, above the "tasks" head.

   NOT a card. It was a bordered chip floating over an otherwise unboxed column,
   which is most of what made it read as unrefined: the only box in the viewport,
   its left edge off the column's text inset, and no header of its own. Now it is
   a plain column block on the same var(--s-4) inset as .col-cal / .col-done /
   .col-bring, closed by the same hairline .col-head uses — the column's opening
   band instead of an orphan tile.

   Top padding is --s-5 so the temp's first baseline lands on the same line as the
   "schedule" and "recap" heads in the sibling columns (26px/1.2 title at --s-4 vs
   20px/1.2 value at --s-5). All three columns now start on one baseline.

   Four tiers, ranked by how fast the number changes:
     1. .wx-now        right now — temp (--title-2) + condition + the day's rain chip
     2. .wx-temps      the other temperatures (H/L, feels-like), grouped with the
                       headline because they are the same KIND of number
     3. .wx-rail       the whole day midnight→midnight, as one object
     4. .wx-cond-meta  the day's standing conditions (wind, uv, sun)
   Vertical rhythm follows that ranking instead of one uniform gap: 2px inside the
   temperature group, --s-3 before the chart (a new group), --s-2 after it. No dot
   separators anywhere — space does the grouping. ------------------------------ */
.day-weather {
  padding: var(--s-5) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--panel-head-line);
}
.wx-void { font-size: 13px; color: var(--fg-dim); font-style: italic; }

.wx-now { display: flex; align-items: baseline; gap: var(--s-2); }
.wx-temp {
  font-family: var(--font-display);
  font-feature-settings: var(--feat-display), var(--feat-tnum);
  font-size: var(--title-2); line-height: var(--title-lh); color: var(--fg);
}
.wx-cond { font-size: 13px; color: var(--fg-dim); min-width: 0; }
/* the day's max rain chance, pushed to the column's right edge: it is the one
   piece of row 1 that is a state flag rather than a reading, so it splits the row
   deliberately instead of crowding the condition text. */
/* Outlined, not a solid accent fill: the hourly bars below are solid accent, and
   two different meanings can't both own the loudest treatment in one 90px block.
   Same outlined-badge idiom as .tb-count / .tb-card-badge. */
.wx-rain {
  margin-left: auto; flex: none; align-self: center;
  font-family: var(--font-display); font-size: 10px;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--accent); border: 1.5px solid var(--accent);
  padding: 1px 6px; border-radius: var(--r);
}
.wx-temps {
  display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap;
  margin-top: 2px; font-size: 11px; color: var(--fg-dim); letter-spacing: 0.02em;
}
/* feels-like is a different measure from H/L, so it sits one gap further out.
   Proximity does the grouping that a "·" was being used to fake. */
.wx-feels { margin-left: var(--s-2); }

/* 24-hour rail — the day as ONE object, midnight→midnight, replacing the old
   5-slot sampled strip. Everything inside is absolutely positioned on the same
   coordinate, left = hour/24, so the hour grid, the rain shape, the night
   shading and the now marker are all on one time axis by construction. The
   rail owns a fixed height and every child fills it, so nothing here can
   reflow the block as the data changes. */
.wx-rail-wrap { margin-top: var(--s-3); }
.wx-rail {
  position: relative; height: 26px; overflow: hidden;
  background: var(--bg-elev-2); border-radius: var(--r);
}
/* One hairline per hour, drawn UNDER the rain fill: an hour grid where the day
   is dry, quietly covered where it isn't. That ordering is why 24 marks in a
   ~90px block don't shred the shape — standard gridlines-behind-the-data. Every
   6th is stronger, which is what lets the sparse axis below carry only 3 labels. */
.wx-tick { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line-soft); }
.wx-tick.is-major { background: var(--line); }
/* Rain as bottom-anchored HEIGHT, scaled to the day's own ceiling (printed in
   row 1's flag). Height works here where it failed in the old 90x5px cell:
   the rail is 26px tall, so vertical extent reads as magnitude again. Opacity
   over the track was tried first and read as one flat bar — near-identical
   luminance carries almost no signal. */
.wx-fill {
  position: absolute; bottom: 0; width: calc(100% / 24);
  background: var(--accent);
}
/* Night is dimmed, not ticked — the shading carries sunrise/sunset ambiently,
   which is what let the two labelled marks come out. Two layers, because one
   wasn't enough: a wash alone was invisible on the light surfaces, where the
   track and the page are already nearly the same value, so the night stretch
   only showed where rain happened to be. The BED drops night to plain --bg,
   borrowing the theme's own designed bg/bg-elev-2 step, and reads on all six
   combos; the WASH sits over the rain so a 3am shower still reads as a 3am
   shower, just at night. */
.wx-night-bed { position: absolute; top: 0; bottom: 0; background: var(--bg); }
.wx-night { position: absolute; top: 0; bottom: 0; background: var(--bg); opacity: 0.45; }
/* Now marker: a single chevron, not a line plus a "now 9a" label — one mark
   instead of two, with --warn doing the work the words were doing. Semantic
   state, deliberately not --accent, which on this rail already means rain. */
.wx-nowmark {
  position: absolute; top: 0; width: 0; height: 0; margin-left: -4px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--warn);
}
/* Sparse axis. 24 labels will not fit at this width, so only the quarter marks,
   positioned on the same left = hour/24 coordinate as the ticks. Centered with a
   translate, which is safe only because 6a/noon/6p are all interior — the 12a and
   11p ends would clip, which is exactly why they aren't labelled. */
.wx-rail-axis { position: relative; height: 12px; margin-top: 3px; }
.wx-rail-axis > span {
  position: absolute; top: 0; transform: translateX(-50%);
  font-size: 10px; line-height: 1; color: var(--fg-dim); white-space: nowrap;
}
.wx-cond-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-3);
  margin-top: var(--s-2); font-size: 11px; color: var(--fg-dim); letter-spacing: 0.02em;
}

/* ============================================================================
   AUDIT (2026-07-24): content-bearing faint text lifted --fg-faint → --fg-dim.
   --fg-faint fails 4.5:1 on the light surfaces (~2.7:1 cobalt-light); --fg-dim
   clears it (5.5:1 light / 8.2:1 dark). Placeholders specifically must hit 4.5:1
   (WCAG 1.4.3). These win by source order (single-class / equal-specificity,
   later in the file). Purely decorative faint (carets, chevrons, ghost pip) is
   intentionally recessive and stays on --fg-faint / --fg-ghost.
   Shared across all themes (home.css is theme-agnostic) — a strict improvement.
   ============================================================================ */
input::placeholder,
.ep-input::placeholder,
.ep-textarea::placeholder { color: var(--fg-dim); font-style: italic; }

.task-empty, .task-detail-empty, .tb-pe-sub, .ghost-time { color: var(--fg-dim); }
