:root {
  --bg: #f3f2ee;
  --surface: #ffffff;
  --text: #1b1a17;
  --text-muted: #6b6a63;
  --accent: #3d6e8c;
  --accent-soft: #e3ecf1;
  --border: #d9d7ce;
  --done: #d97757;
  --radius: 3px;
  --radius-sm: 2px;
  --gap: 16px;
  --font-body: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
}

body {
  padding-bottom: 76px; /* room for bottom nav */
  min-height: 100vh;
}

header.app-header {
  padding: 20px var(--gap) 8px;
}

header.app-header h1 {
  font-size: 1.3rem;
  margin: 0;
}

main {
  padding: 0 var(--gap) var(--gap);
  max-width: 960px;
  margin: 0 auto;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

/* Dashboard: a standardized 3-unit-wide grid. 1 unit = 1 column = a square block
   (aspect-ratio 1). A widget spanning N columns stays a clean N:1 rectangle of
   unit squares. Below 1024px this drops back to a plain single-column stack —
   the sidebar nav (below, min-width:768px) reserves 244px off the left, so a
   3-column grid doesn't have real room to give each unit square until well
   past that; below 1024px each widget just reads fine full-width with its
   natural height instead of being squeezed into a too-small square. */
#view-dashboard {
  display: grid;
  gap: var(--gap);
}

#view-dashboard .card {
  margin-bottom: 0;
  min-width: 0;
}

@media (min-width: 1024px) {
  #view-dashboard {
    /* minmax(0, 1fr), not bare 1fr — a bare 1fr track can't shrink below its
       content's intrinsic width, and the Calendar timeline's content is wide
       enough that it blew the whole grid out past the viewport without this. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  #view-dashboard .card {
    aspect-ratio: 1;
  }

  #view-dashboard #weather-widget-card {
    grid-column: span 2;
    /* Not aspect-ratio: 2/1 — that ratio is computed from the spanned width
       *including* the gap between the two columns it spans, which makes it
       taller than a real "1 unit tall" (visibly taller than its row-mate).
       Cancel the inherited square ratio and let it stretch (the grid default)
       to match whatever height its 1-unit-tall row-mate's own aspect-ratio:1
       actually establishes for the row — that's the one true unit height. */
    aspect-ratio: auto;
  }

  /* Weather's content (icon+temp, then a toggle, then a forecast strip) stacks
     to more than a 1-unit-tall box regardless of width on its own — the extra
     width from going 2-wide only helps if something actually uses it. Split
     into two columns: current conditions on the left, the toggle+forecast
     stacked on the right, so the whole thing fits inside the shorter box
     instead of just being a wide box with the same tall content. */
  #weather-widget-card {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 16px;
  }

  #weather-widget-card .card-header,
  #weather-widget-card .synced-at {
    grid-column: 1 / -1;
  }

  #weather-widget-card .wx-body {
    grid-column: 1;
    grid-row: 3 / span 2;
    align-self: center;
  }

  #weather-widget-card #wx-toggle {
    grid-column: 2;
    grid-row: 3;
    margin: 0 0 8px;
  }

  #weather-widget-card .wx-forecast-strip {
    grid-column: 2;
    grid-row: 4;
    align-self: center;
  }

  #view-dashboard #calendar-widget-card {
    grid-column: span 3;
    aspect-ratio: 3 / 1;
  }
}

/* Date/Time and Pomodoro read as one big centered number, not a list of fields —
   fill the card's full (grid-stretched) height and center everything in it. */
#datetime-widget-card,
#pomodoro-widget-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

#pomodoro-widget-card .quick-actions {
  justify-content: center;
}

.card h2 {
  font-size: 1rem;
  margin: 0 0 12px;
}

/* Buttons */
button {
  font: inherit;
  border: none;
  border-radius: var(--radius);
  padding: 10px 14px;
  cursor: pointer;
  background: var(--accent);
  color: white;
}

button:disabled {
  background: var(--border);
  color: var(--text-muted);
  cursor: not-allowed;
}

button.secondary {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
}

/* Quick actions bar */
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Inline quick-add form */
.quick-add-form {
  display: none;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.quick-add-form.open {
  display: flex;
}

.quick-add-form input,
.quick-add-form select {
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

/* Date/Time widget */
.dt-time {
  font-family: var(--font-mono);
  font-size: 4rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.dt-date {
  color: var(--text-muted);
  margin-top: 4px;
}

/* Pomodoro widget */
.pomo-mode {
  color: var(--accent);
  font-weight: 600;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.pomo-mode.pomo-mode-break {
  color: var(--done);
}

.pomo-clock {
  font-family: var(--font-mono);
  font-size: 4rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  margin: 4px 0 16px;
}

/* Calendar widget */
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.card-header h2 {
  margin: 0;
}

.fin-ledger-header-actions {
  display: flex;
  gap: 8px;
}

.icon-btn {
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  color: var(--accent);
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.icon-btn:active {
  transform: scale(0.94);
}

.icon-btn.syncing svg {
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.card > .synced-at {
  display: block;
  margin: 2px 0 12px;
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* Calendar day picker (7 days: today + next 6) */
.day-picker {
  display: flex;
  gap: 4px;
  margin: 4px 0 14px;
}

.day-pill {
  flex: 1;
  min-width: 0;
  background: none;
  color: var(--text-muted);
  text-align: center;
  padding: 6px 2px 8px;
  border-radius: var(--radius);
  font-size: 0.72rem;
}

.day-pill .dow {
  display: block;
  font-weight: 600;
  margin-bottom: 2px;
}

.day-pill .dom {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 4px;
}

.day-pill .dot-row {
  display: flex;
  justify-content: center;
  gap: 2px;
  height: 4px;
}

.day-pill .dot-row span {
  width: 4px;
  height: 4px;
  border-radius: var(--radius-sm);
  background: var(--text-muted);
  opacity: 0.4;
}

.day-pill.active {
  background: var(--accent-soft);
  color: var(--accent);
}

.day-pill.active .dom {
  color: var(--accent);
}

.day-pill.active .dot-row span {
  background: var(--accent);
  opacity: 1;
}

/* All-day events for the selected day */
.allday-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.allday-chip {
  font-size: 0.72rem;
  font-weight: 600;
  color: white;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
}

/* Timeline: hour grid + time-positioned event blocks, for the selected day only */
.timeline {
  position: relative;
  max-height: 320px;
  overflow-y: auto;
}

.tl-hours {
  position: absolute;
  left: 0;
  top: 0;
  width: 34px;
}

.tl-hour-label {
  position: absolute;
  left: 0;
  right: 6px;
  font-size: 0.66rem;
  color: var(--text-muted);
  text-align: right;
  transform: translateY(-6px);
}

.tl-track {
  position: absolute;
  left: 40px;
  right: 4px;
  top: 0;
  bottom: 0;
}

.tl-hour-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px solid var(--border);
}

/* Current-time indicator — only rendered on today's grid, computed at render
   time (page load / sync / switching back to today), not on a live ticking
   timer — matches the app's no-auto-refresh rule. */
.tl-now-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 2px solid var(--done);
  z-index: 2;
}

.tl-now-dot {
  position: absolute;
  left: -4px;
  top: -4px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-sm);
  background: var(--done);
}

.tl-event {
  position: absolute;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  border-radius: var(--radius-sm);
  padding: 2px 6px;
  font-size: 0.74rem;
  font-weight: 600;
  color: white;
  overflow: hidden;
  line-height: 1.3;
}

.tl-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Short events (below COMPACT_HEIGHT_THRESHOLD in timeGrid.js) show title +
   time on one line instead of two stacked — keeps the box legible without
   needing to inflate its height (which caused the overlap-clustering bug
   fixed alongside this: a short event's real, un-padded duration is what
   determines whether it truly overlaps a neighbor). */
.tl-compact {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tl-compact-time {
  font-weight: 400;
  opacity: 0.85;
}

.tl-event .t {
  display: block;
  font-size: 0.64rem;
  font-weight: 400;
  opacity: 0.85;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.empty-note {
  color: var(--text-muted);
  font-size: 0.9rem;
  text-align: center;
  padding: 12px 0;
}

/* Weather widget */
.wx-body {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 2px 0 4px;
}

.wx-emoji {
  font-size: 2.4rem;
  line-height: 1;
}

.wx-readout {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.wx-temp {
  font-size: 1.7rem;
  font-weight: 700;
  line-height: 1;
}

.wx-desc {
  font-size: 0.87rem;
  color: var(--text-muted);
}

.wx-range {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.wx-toggle {
  display: flex;
  gap: 4px;
  background: var(--bg);
  border-radius: var(--radius);
  padding: 3px;
  margin: 16px 0 16px;
}

.wx-toggle button {
  flex: 1;
  min-width: 0;
  background: none;
  color: var(--text-muted);
  padding: 8px 10px;
  font-size: 0.82rem;
  border-radius: var(--radius-sm);
}

.wx-toggle button.active {
  background: var(--surface);
  color: var(--accent);
  font-weight: 600;
  border: 1px solid var(--border);
}

/* Finance's own tab bar reuses .wx-toggle's segmented-control look, just with more
   buttons than the 2-option weather toggle it was built for — wraps to a second row
   instead of squeezing every label unreadably thin on a narrow screen. */
.fin-tab-bar {
  flex-wrap: wrap;
  margin: 0 0 16px;
}

.fin-tab-bar button {
  flex: 1 1 auto;
  min-width: 90px;
}

.fin-account-row .tracker-row {
  gap: 8px;
}

.fin-account-balance-prefix {
  color: var(--text-muted);
}

.fin-account-balance-input {
  width: 90px;
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
}

.fin-account-type-row {
  margin-top: 4px;
  gap: 8px;
}

.fin-account-type-label {
  margin: 0;
}

.fin-account-type-select {
  font: inherit;
  font-size: 0.85rem;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
}

.wx-forecast-strip {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  padding: 4px 2px 8px;
  /* Scrollbar hidden rather than reserved — still scrolls by touch/trackpad/wheel,
     but its appearing/disappearing can never shift the card's height. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.wx-forecast-strip::-webkit-scrollbar {
  display: none;
}

/* Today: many hours, fixed-width items, always scrollable */
.wx-forecast-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  min-width: 48px;
  flex-shrink: 0;
}

/* This week: exactly 7 items, stretch to fill the card on wide screens,
   only falling back to a scroll if they can't all fit comfortably */
.wx-forecast-strip.week-view {
  gap: 10px;
}

.wx-forecast-strip.week-view .wx-forecast-item {
  flex: 1 1 46px;
  min-width: 46px;
}

.wx-forecast-label {
  font-size: 0.74rem;
  color: var(--text-muted);
}

.wx-forecast-emoji {
  font-size: 1.3rem;
}

.wx-forecast-temp {
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.wx-forecast-low {
  font-weight: 400;
  color: var(--text-muted);
}

/* Daily checklist */
.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

@media (min-width: 1024px) {
  /* Matches the dashboard unit-grid's own breakpoint above — only bind the
     list's height once the grid itself is actually active. Inside the
     fixed-square dashboard unit, the list scrolls internally rather than
     growing the card — same self-bounded pattern the Calendar timeline
     already uses (.timeline's own max-height/overflow-y). */
  #daily-checklist-widget-card .checklist {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
  }

  #daily-checklist-widget-card {
    display: flex;
    flex-direction: column;
  }

  /* Same self-bounded pattern as the checklist above — fills the square with
     venue/date now that there's a second line per row, but scrolls internally
     rather than pushing the card taller if it ever runs a little long. */
  #music-upcoming-widget-card #mu-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
  }

  #music-upcoming-widget-card {
    display: flex;
    flex-direction: column;
  }

  /* Textareas scroll internally on their own (no extra wrapper needed like
     the checklist/upcoming lists above) — just let it flex to fill the
     square below the header. */
  #scratchpad-widget-card .scratchpad-textarea {
    flex: 1;
    min-height: 0;
  }

  #scratchpad-widget-card {
    display: flex;
    flex-direction: column;
  }
}

.scratchpad-textarea {
  width: 100%;
  min-height: 160px;
  border: none;
  outline: none;
  resize: none;
  background: transparent;
  color: var(--text);
  font: inherit;
  padding: 0;
}

.scratchpad-textarea::placeholder {
  color: var(--text-muted);
}

.checklist li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px;
}

.checklist input[type="checkbox"] {
  width: 22px;
  height: 22px;
  accent-color: var(--done);
  flex-shrink: 0;
}

.checklist .item-text {
  flex: 1;
}

.checklist li.done .item-text {
  text-decoration: line-through;
  color: var(--text-muted);
}

.checklist-add {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

.checklist-add input {
  flex: 1;
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

/* Habit tracker (Trackers section) */
.tr-empty .tr-week-nav,
.tr-empty .tracker-section {
  display: none;
}

/* Add-habit form sits at the bottom of the card, after today's list */
.tr-add-actions {
  margin-top: 18px;
}

.tr-add-row {
  display: flex;
  gap: 8px;
}

.tr-add-icon-btn {
  width: 42px;
  height: 42px;
  font-size: 1.2rem;
}

.tr-freq-picker {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.freq-type-row {
  display: flex;
  gap: 6px;
}

.freq-type-btn {
  flex: 1;
  min-width: 0;
  background: var(--bg);
  color: var(--text-muted);
  border: 1px solid var(--border);
  padding: 8px 6px;
  font-size: 0.78rem;
  border-radius: var(--radius-sm);
}

.freq-type-btn.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent-soft);
  font-weight: 600;
}

.freq-days-row {
  display: flex;
  gap: 4px;
}

.freq-day-btn {
  flex: 1;
  min-width: 0;
  background: var(--bg);
  color: var(--text-muted);
  border: 1px solid var(--border);
  padding: 7px 0;
  font-size: 0.7rem;
  border-radius: var(--radius-sm);
}

.freq-day-btn.active {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}

.freq-count-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.freq-count-input {
  width: 56px;
  font: inherit;
  padding: 7px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  text-align: center;
}

/* Week nav: prev/next arrows flanking the date strip */
.tr-week-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 14px;
}

.tr-week-nav-btn {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-muted);
}

.tr-week-nav-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Date strip reuses the calendar's .day-pill, plus a done/total fraction */
.tr-date-strip {
  flex: 1;
  min-width: 0;
  margin: 0;
}

.tr-date-frac {
  display: block;
  font-size: 0.62rem;
  color: var(--text-muted);
  margin-top: 2px;
}

.day-pill.active .tr-date-frac {
  color: var(--accent);
}

.tr-date-pill:disabled {
  opacity: 0.35;
  cursor: default;
}

.tracker-section-title {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin: 18px 0 6px;
}

.tracker-empty-msg {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 10px 4px;
}

.tracker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.tracker-item {
  padding: 10px 0;
  border-top: 1px solid var(--border);
}

.tracker-item:first-child {
  border-top: none;
}

.fin-property-row-active {
  background: var(--accent-soft);
  border-radius: var(--radius);
  padding-left: 8px;
  padding-right: 8px;
  margin: 0 -8px;
}

.tracker-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.tracker-check {
  width: 22px;
  height: 22px;
  accent-color: var(--done);
  flex-shrink: 0;
}

/* Used on both a <span> (per-habit) and a <button> (add-habit form) — reset the
   button-element defaults (padding, white text) so both render identically. */
.tracker-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  cursor: pointer;
}

.tracker-icon:hover,
.tracker-icon:focus {
  background: var(--accent-soft);
  outline: none;
}

.tracker-name-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.tracker-name {
  cursor: text;
  padding: 3px 6px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tracker-name:hover,
.tracker-name:focus {
  background: var(--bg);
  outline: none;
}

.tracker-freq-label {
  font-size: 0.68rem;
  color: var(--text-muted);
  padding: 0 6px;
}

.tracker-inline-input {
  font: inherit;
  padding: 3px 6px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.tracker-name-wrap .tracker-inline-input {
  width: 100%;
}

.tracker-menu-wrap {
  position: relative;
  flex-shrink: 0;
}

.tracker-menu-btn {
  width: 30px;
  height: 30px;
}

.tracker-menu {
  position: absolute;
  top: 36px;
  right: 0;
  z-index: 3;
  min-width: 160px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.tracker-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  color: var(--text);
  border-radius: 0;
  padding: 10px 14px;
  font-size: 0.85rem;
}

.tracker-menu-item:hover {
  background: var(--bg);
}

.tracker-menu-item.danger {
  color: #b3453f;
}

.tracker-note-row {
  margin: 8px 0 2px;
}

.tracker-note-input {
  width: 100%;
  font: inherit;
  font-size: 0.85rem;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.tracker-icon-panel,
.tracker-freq-panel,
.tracker-history {
  margin: 10px 0 2px;
  padding: 12px;
  background: var(--bg);
  border-radius: var(--radius);
}

.tracker-freq-panel .quick-actions {
  margin-top: 10px;
}

/* Full emoji-picker-element component, used by the add-habit form and each
   habit's icon panel — themed to match the app's palette/radius tokens. It's a
   Shadow DOM component, so CSS custom properties are the only way in. */
emoji-picker {
  width: 100%;
  height: 320px;
  --background: var(--surface);
  --border-color: var(--border);
  --border-radius: var(--radius-sm);
  --button-active-background: var(--accent-soft);
  --button-hover-background: var(--bg);
  --category-font-color: var(--text-muted);
  --indicator-color: var(--accent);
  --input-border-color: var(--border);
  --input-border-radius: var(--radius-sm);
  --input-font-color: var(--text);
  --input-placeholder-color: var(--text-muted);
  --outline-color: var(--accent);
  --num-columns: 7;
}

.icon-picker-loading {
  color: var(--text-muted);
  font-size: 0.85rem;
  text-align: center;
  padding: 40px 0;
}

.icon-picker-clear {
  display: block;
  width: 100%;
  background: none;
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 8px 0;
  margin-top: 6px;
}

.icon-picker-clear:hover {
  color: var(--text);
}

.thist-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.thist-header .icon-btn {
  width: 26px;
  height: 26px;
  background: none;
  border: none;
  color: var(--text-muted);
}

.thist-label {
  font-size: 0.82rem;
  font-weight: 600;
}

.thist-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.thist-dow {
  text-align: center;
  font-size: 0.65rem;
  color: var(--text-muted);
  padding-bottom: 2px;
}

.thist-day {
  aspect-ratio: 1;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.thist-day.empty {
  background: none;
}

.thist-day.today {
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

.thist-day.done {
  background: var(--done);
  color: white;
  font-weight: 600;
}

.thist-day:disabled {
  opacity: 0.35;
  cursor: default;
}

/* This week card: a weekday header row + one dot-row per habit. The header's
   spacer must match .week-habit-name-wrap's flex-basis so the day columns line
   up with the dot columns below them. */
.week-header-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.week-header-spacer {
  flex: 1;
  min-width: 0;
}

.week-header-days {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.week-header-day {
  width: 14px;
  text-align: center;
  font-size: 0.68rem;
  color: var(--text-muted);
}

.week-header-day.today {
  color: var(--accent);
  font-weight: 700;
}

.week-habit-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.week-habit-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.week-habit-name-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
}

.week-habit-icon {
  font-size: 0.85rem;
  flex-shrink: 0;
}

.week-habit-name {
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.week-habit-freq {
  font-size: 0.68rem;
  color: var(--text-muted);
  flex-shrink: 0;
}

.week-dots {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.week-dot {
  width: 14px;
  height: 14px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
}

.week-dot.done {
  background: var(--done);
  border-color: var(--done);
}

.week-dot.off {
  opacity: 0.3;
  border-style: dashed;
}

/* Bottom nav */
nav.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}

nav.bottom-nav button {
  flex: 1;
  min-width: 0;
  background: none;
  color: var(--text-muted);
  border-radius: 0;
  padding: 12px 1px;
  font-size: 0.72rem;
}

nav.bottom-nav button.active {
  color: var(--accent);
  font-weight: 600;
}

.nav-brand {
  display: none;
}

/* On wider screens, the nav becomes a rounded floating sidebar instead of a bottom bar */
@media (min-width: 768px) {
  body {
    padding-bottom: 0;
    padding-left: 244px;
  }

  header.app-header h1 {
    display: none; /* the wordmark now lives at the top of the sidebar instead */
  }

  header.app-header {
    padding-top: 32px;
  }

  nav.bottom-nav {
    top: 20px;
    bottom: 20px;
    left: 20px;
    right: auto;
    width: 200px;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 18px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }

  .nav-brand {
    display: block;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 700;
    padding: 4px 12px 18px;
  }

  nav.bottom-nav button {
    flex: none;
    text-align: left;
    padding: 10px 12px;
    font-size: 0.9rem;
    border-radius: var(--radius);
  }

  nav.bottom-nav button.active {
    background: var(--accent-soft);
    color: var(--accent);
  }
}

/* Finance */
.fin-field-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 12px 0 6px;
}

/* Scoped to a direct child of <form> (the genuine first field at the top of a
   modal), not just any element's first child — every modal's field list is a flat
   run of labels/inputs directly inside its <form>, EXCEPT wherever a field is
   wrapped in its own <div> for conditional show/hide (a gift card's extra fields,
   a transfer's "likely matches" list, a renewal's payment-history section, and
   several others). Matching bare `:first-child` zeroed the margin on those wrapped
   labels too, since each is the first child of ITS OWN wrapper div — even though
   visually they sit mid-form, not at the top — leaving them jammed against
   whatever came before with no gap at all. */
form > .fin-field-label:first-child {
  margin-top: 0;
}

#fin-import-account,
#fin-import-file,
#fin-ledger-search {
  width: 100%;
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

#fin-ledger-search {
  /* .card-header h2 zeroes its own bottom margin (so a header with a button stays
     vertically centered) — the ledger card's next element is a bare input with no
     margin of its own to fill that gap, unlike other cards whose first element
     (a list, a button) happens to carry enough spacing to hide it. */
  margin-top: 12px;
  margin-bottom: 10px;
}

.fin-ledger-date-filter {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.fin-ledger-date-filter input[type="date"] {
  flex: 1 1 0;
  min-width: 0;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

.fin-ledger-date-filter span {
  color: var(--text-muted);
}

.fin-ledger-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.fin-ledger-filter-row select {
  flex: 1 1 0;
  min-width: 110px;
  font: inherit;
  font-size: 0.85rem;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

.fin-ledger-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 12px;
}

.fin-ledger-pager span {
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* One unified pill (arrow / tappable label / arrow) rather than a row of separate
   boxed buttons — the label doubles as the "jump to a specific month/quarter" open
   trigger for the picker below it (see .fin-dash-period-picker), with a caret shown
   only when that's actually available (month/quarter — a year has no finer grain to
   jump into, so it stays a plain centered label there). */
.fin-dash-period-nav {
  display: flex;
  align-items: center;
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: 4px;
  margin: 10px 0 8px;
}

.fin-dash-period-arrow {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--accent);
  font-size: 1rem;
}

.fin-dash-period-arrow:hover {
  background: rgba(255, 255, 255, 0.5);
}

.fin-dash-period-arrow:disabled {
  background: none;
  opacity: 0.35;
}

.fin-dash-period-jump {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  background: none;
  color: var(--accent);
  font-weight: 700;
  font-size: 1rem;
  padding: 8px 0;
}

.fin-dash-period-jump.not-jumpable {
  cursor: default;
  color: var(--text);
}

/* Plain (non-clickable) centered label for a .fin-dash-period-nav pill that has no
   picker to open — the trend chart's own prev/next nav, which pages a fixed 6-month
   window rather than jumping to an arbitrary one. Same centering/typography as
   .fin-dash-period-jump, just a span instead of a button and no caret. */
.fin-dash-period-nav-label {
  flex: 1;
  text-align: center;
  font-weight: 700;
  font-size: 1rem;
  color: var(--text);
}

.fin-dash-period-caret {
  font-size: 0.65rem;
  opacity: 0.8;
  transition: transform 0.15s ease;
}

.fin-dash-period-jump.open .fin-dash-period-caret {
  transform: rotate(180deg);
}

.fin-dash-period-picker {
  margin: 0 0 8px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.fin-dash-period-picker-year {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 8px;
  font-size: 0.85rem;
  font-weight: 700;
}

.fin-dash-period-picker-year button {
  background: none;
  color: var(--text-muted);
  font-size: 0.95rem;
  padding: 2px 6px;
}

.fin-dash-period-picker-year button:disabled {
  opacity: 0.35;
}

.fin-dash-period-picker-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}

.fin-dash-period-picker-grid.quarters {
  grid-template-columns: repeat(2, 1fr);
}

.fin-dash-period-picker-grid button {
  background: var(--surface);
  color: var(--text);
  font-size: 0.8rem;
  padding: 8px 0;
  border-radius: var(--radius-sm);
}

.fin-dash-period-picker-grid button:hover {
  background: var(--accent-soft);
}

.fin-dash-period-picker-grid button.current {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}

.fin-dash-period-picker-grid button:disabled {
  opacity: 0.35;
}

/* Quiet by default (no filled circle) — visible only on hover/focus, so a long
   list of rows doesn't read as a wall of solid buttons. */
.fin-cat-remove,
.fin-cat-chevron {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.fin-cat-remove:hover,
.fin-cat-remove:focus-visible,
.fin-cat-chevron:hover,
.fin-cat-chevron:focus-visible {
  background: var(--border);
  color: var(--text);
}

.fin-cat-remove {
  width: 28px;
  height: 28px;
  font-size: 1.1rem;
  line-height: 1;
}

.fin-cat-chevron {
  width: 24px;
  height: 24px;
  font-size: 0.85rem;
  transition: transform 0.15s ease;
}

.fin-cat-chevron[aria-expanded="true"] {
  transform: rotate(90deg);
}

.fin-cat-count {
  font-size: 0.7rem;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1px 8px;
  flex-shrink: 0;
}

.fin-cat-parent {
  padding-bottom: 6px;
}

.fin-subcat-list {
  list-style: none;
  margin: 2px 0 4px 20px;
  padding: 0 0 0 12px;
  border-left: 2px solid var(--border);
}

.fin-cat-sub {
  padding: 6px 0;
}

/* Categories tab: each pool (Expense/Savings/Investment/Income) renders as a grid of
   tiles rather than a list of rows — tapping one opens the shared category modal
   (rename, subcategory chips, remove) instead of exposing those controls inline on
   every row, the "Counts as" dropdown's old spot included. */
.fin-cat-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
  /* .card-header h2 zeroes its own bottom margin (so the pool count badge stays
     vertically centered next to the title) — restore the breathing room a plain
     .card h2's default 12px bottom margin would have given, same fix #fin-ledger-search
     already needed for the same reason. */
  margin-top: 12px;
}

.fin-cat-tile {
  background: var(--bg);
  border: 2px solid transparent;
  border-radius: var(--radius);
  padding: 12px 10px;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: padding 0.15s ease;
  font: inherit;
  color: var(--text);
  cursor: pointer;
}

.fin-cat-tile:hover {
  border-color: var(--border);
}

.fin-cat-tile-name {
  font-size: 0.85rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fin-cat-tile-sub {
  font-size: 0.72rem;
  color: var(--text-muted);
}

.fin-cat-tile-sub-over {
  color: #b3453f;
  font-weight: 600;
}

.fin-cat-tile-giftcard {
  background: #fdf6ec;
}

.fin-cat-tile-sub-spent {
  color: var(--accent);
  font-weight: 600;
}

/* Categories and Budgets share this exact tile grid (Budgets' own tiles just add
   .fin-budget-tile on top) — bumped together once there's enough width for it to
   read as "roomier," not just "more small tiles per row." Same 640px breakpoint the
   rest of Finance's wide-layout treatment already uses. */
@media (min-width: 640px) {
  .fin-cat-tile-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
  }
  .fin-cat-tile {
    padding: 16px 14px;
  }
  .fin-cat-tile-name {
    font-size: 0.95rem;
  }
  .fin-cat-tile-sub {
    font-size: 0.8rem;
  }
  .fin-cat-tile-bar {
    height: 6px;
    margin-top: 6px;
  }
}

.fin-cat-tile-add {
  background: none;
  border: 2px dashed var(--border);
  color: var(--text-muted);
  align-items: center;
  justify-content: center;
  flex-direction: row;
  gap: 6px;
  font-weight: 600;
  font-size: 0.85rem;
}

.fin-cat-tile-add:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.fin-pool-count {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.fin-cat-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}

.fin-cat-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 6px 5px 11px;
  font-size: 0.78rem;
}

.fin-cat-chip-name {
  cursor: text;
  border-radius: 4px;
}

.fin-cat-chip-name:hover,
.fin-cat-chip-name:focus {
  background: var(--surface);
  outline: none;
}

.fin-cat-chip .tracker-inline-input {
  font-size: inherit;
}

.fin-cat-chip-remove {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  padding: 2px;
  font: inherit;
}

.fin-cat-chip-add {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 11px;
  font-size: 0.78rem;
  color: var(--text-muted);
  cursor: pointer;
  font: inherit;
}

.fin-cat-chip-add:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.fin-cat-subcat-inline-form {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.fin-cat-subcat-inline-form input {
  flex: 1;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
}

#fin-cat-modal-form {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Every Finance modal's fields share this one treatment. Previously only the
   category modal's own Name field (#fin-cat-modal-name) and the ledger edit modal's
   (.fin-edit-form) had matching input/select styling — the Account, Budget, and
   Recurring bill modals reuse the same .fin-modal shell but never got it, so their
   fields rendered as bare unstyled browser controls sitting inside an otherwise
   polished modal. Matches any input/select directly inside `.fin-modal`, not just
   ones inside a `<form>` — a field sitting outside a form (e.g. the gift card
   modal's account picker, which can't be form-wrapped itself without nesting the
   inline "+ New gift card" mini-form inside it, silently invalid HTML) still needs
   the same look. */
.fin-modal input:not([type="checkbox"]):not([type="radio"]),
.fin-modal select {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

.fin-modal input:not([type="checkbox"]):not([type="radio"]):focus,
.fin-modal select:focus {
  outline: none;
  border-color: var(--accent);
}

.fin-checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--text);
  margin: 14px 0 6px;
  cursor: pointer;
}

.fin-checkbox-label input[type="checkbox"] {
  width: auto;
  flex-shrink: 0;
}

.fin-secret-field-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.fin-secret-field-row input {
  flex: 1 1 0;
  min-width: 0;
}

.fin-secret-field-row .icon-btn {
  font-size: 0.95rem;
  flex-shrink: 0;
}

.fin-edit-split-item {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

.fin-edit-split-item select {
  flex: 1.4 1 0;
  min-width: 0;
}

.fin-edit-split-item input {
  flex: 1 1 0;
  min-width: 0;
}

.fin-edit-split-item .icon-btn {
  flex-shrink: 0;
}

.fin-edit-split-remaining {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 4px 0 8px;
}

.fin-edit-split-remaining.fin-edit-split-remaining-bad {
  color: #b3453f;
}

/* Breathing room above a modal form's action row (Save/Remove) and above a
   remove-confirm block, wherever either sits directly in a Finance modal's form.
   Previously this depended entirely on whichever ad-hoc layout that particular form
   happened to use — #fin-cat-modal-form's own flex `gap: 4px` gave it a little, but
   the Account/Budget/Recurring-bill modals are plain block-flow forms with no gap at
   all, so their buttons sat flush against the field above with zero space. One rule
   here instead of tuning each form's own layout individually. Doesn't touch the
   ledger's transaction-edit modal (.fin-edit-form) — its own more specific
   `.fin-edit-form .quick-actions` rule already wins and is unaffected. */
.fin-modal form > .quick-actions,
.fin-modal form > .fin-ledger-confirm {
  margin-top: 18px;
}

#fin-cat-modal-reassign-row {
  margin: 8px 0;
}

#fin-dash-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 10px;
}

.fin-dash-tile {
  background: var(--bg);
  border-radius: var(--radius);
  padding: 12px;
  border: 2px solid transparent;
  cursor: pointer;
  text-align: left;
}

.fin-dash-tile.active {
  border-color: var(--accent);
}

.fin-dash-tile-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fin-dash-tile-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-sm);
}

.fin-dash-tile-amount {
  font-family: var(--font-mono);
  font-size: 1.1rem;
  font-weight: 700;
}

.fin-dash-tile-pct {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Stacked (pie above tiles) below the breakpoint, same as always — side by side
   once there's enough width for both to sit comfortably (same 640px breakpoint the
   modal sheet-vs-dialog switch already uses), with the pie vertically centered
   against the tile grid's full height rather than pinned to its top. */
.fin-dash-breakdown-layout {
  display: flex;
  flex-direction: column;
}

.fin-dash-pie-wrap {
  display: flex;
  justify-content: center;
  margin: 4px 0 16px;
}

.fin-dash-pie {
  width: 180px;
  height: 180px;
}

@media (min-width: 640px) {
  .fin-dash-breakdown-layout {
    flex-direction: row;
    align-items: center;
    gap: 28px;
  }
  .fin-dash-pie-wrap {
    margin: 0;
  }
  #fin-dash-body {
    flex: 1 1 0;
    min-width: 0;
  }
  .fin-dash-pie {
    width: 210px;
    height: 210px;
  }
}

.fin-dash-pie-slice {
  cursor: pointer;
  transition: stroke-width 0.15s ease;
}

.fin-dash-pie-slice:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.fin-dash-pie-total-label {
  font-size: 7px;
  fill: var(--text-muted);
}

.fin-dash-pie-total-amount {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  fill: var(--text);
}

.fin-dash-detail {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.fin-dash-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.fin-dash-detail-header h3 {
  margin: 0;
  font-size: 0.95rem;
}

.fin-dash-detail-close {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  width: 24px;
  height: 24px;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.fin-dash-detail-close:hover {
  background: var(--border);
  color: var(--text);
}

.fin-dash-subcat-row {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  color: var(--text-muted);
  padding: 6px 0;
  border-top: 1px solid var(--border);
}

.fin-dash-subcat-row:first-child {
  border-top: none;
}

/* Budget/goal progress bars — shared between the Budgets tab, the Goals tab, and the
   dashboard's compact read-only summaries of both. */
.fin-budget-bar-track {
  height: 8px;
  border-radius: 4px;
  background: var(--bg);
  overflow: hidden;
  margin-top: 6px;
}

.fin-budget-bar-fill {
  height: 100%;
  border-radius: 4px;
  background: var(--accent);
}

.fin-budget-bar-fill.over {
  background: #b3453f;
}

.fin-budget-bar-fill.reached {
  background: var(--done);
}

/* Slimmer variant of the same bar for inside a Budgets-tab tile, where the
   default 8px height/6px margin reads too heavy next to a two-line tile. */
.fin-cat-tile-bar {
  height: 5px;
  margin-top: 4px;
}

.fin-budget-bar-label {
  display: flex;
  justify-content: space-between;
  font-size: 0.82rem;
  color: var(--text-muted);
  margin-top: 4px;
}

.fin-budgets-hint {
  margin-top: 0;
}

#fin-recurring-detect-row {
  margin-top: 14px;
}

.fin-budget-row .tracker-row,
.fin-goal-row .tracker-row {
  gap: 8px;
}

.fin-goal-contribute-input {
  width: 100px;
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
}

.fin-budget-widget-row {
  margin-bottom: 14px;
}

.fin-budget-widget-row:last-child {
  margin-bottom: 0;
}

.fin-movement-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.fin-movement-mini-card {
  padding: 14px;
  text-align: left;
}

.fin-movement-mini-clickable {
  cursor: pointer;
}

.fin-movement-mini-clickable:hover {
  background: var(--bg);
}

.fin-movement-mini-clickable.active {
  border-color: var(--accent);
}

.fin-movement-mini-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.fin-movement-mini-amount {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 700;
}

.fin-movement-mini-amount.income {
  color: var(--done);
}

.fin-property-rate {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Stands in for the old Properties list/picker card while there's only one property
   to show — see the comment above #fin-properties-list-card in properties.js. */
.fin-property-heading {
  font-size: 1.15rem;
  margin: 4px 0 12px;
}

.fin-property-summary-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin: -8px 0 16px;
}

/* Same look, but sitting right under a plain .card-header h2 (the payoff card) rather
   than under the FY summary's mini-card grid — that -8px above is tuned to pull up
   under the grid specifically and overlaps a bare heading if reused here. */
.fin-property-payoff-summary {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin: 0 0 10px;
}

.fin-movement-net {
  font-weight: 700;
  font-size: 1.6rem;
}

.fin-movement-net.balanced {
  color: var(--done);
}

.fin-movement-net.over {
  color: #b3453f;
}

.fin-movement-hint {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-top: 4px;
}

/* Simple CSS bar chart — no charting library, six equal-width columns. */
.fin-trend-chart {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 140px;
  padding-top: 8px;
}

.fin-trend-col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
}

.fin-trend-bar-track {
  flex: 1;
  width: 100%;
  display: flex;
  align-items: flex-end;
}

.fin-trend-bar {
  width: 100%;
  min-height: 2px;
  border-radius: 4px 4px 0 0;
  background: var(--accent-soft);
}

.fin-trend-amount {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-top: 6px;
}

.fin-trend-label {
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* Trends tab: a multi-line SVG chart, one polyline per toggled-on category, drawn to
   a shared scale so relative size across categories stays honest. */
.fin-trends-svg {
  width: 100%;
  height: auto;
  display: block;
  margin-top: 4px;
}

.fin-trends-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.fin-trends-axis-label,
.fin-trends-month-label {
  font-size: 8px;
  fill: var(--text-muted);
}

.fin-trends-month-label {
  text-anchor: middle;
}

.fin-trends-guideline {
  stroke: var(--accent);
  stroke-width: 1;
  stroke-dasharray: 2 2;
  opacity: 0.5;
}

.fin-trends-line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.fin-trends-point {
  stroke: var(--surface);
  stroke-width: 1;
}

/* Invisible full-height tap target per month column, sitting above the drawn lines
   so a tap/click anywhere in that column (not just exactly on a point) selects it. */
.fin-trends-band {
  fill: transparent;
  cursor: pointer;
}

.fin-trends-band:hover,
.fin-trends-band:focus {
  fill: var(--accent-soft);
  opacity: 0.4;
  outline: none;
}

.fin-trends-select-hint {
  color: var(--text-muted);
  font-size: 0.85rem;
  text-align: center;
  padding: 12px 0 0;
  margin: 0;
}

.fin-trends-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 14px;
}

.fin-trends-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 10px 5px 8px;
  font-size: 0.78rem;
  color: var(--text);
  opacity: 0.45;
}

.fin-trends-chip.active {
  opacity: 1;
  border-color: var(--accent-soft);
  background: var(--accent-soft);
}

.fin-trends-detail:not(:empty) {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.fin-trends-detail-month {
  font-weight: 700;
  font-size: 0.9rem;
  margin-bottom: 6px;
}

.fin-trends-detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 0;
  font-size: 0.85rem;
}

.fin-trends-detail-row-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fin-trends-detail-total {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 0.88rem;
  padding-top: 8px;
  margin-top: 4px;
  border-top: 1px dashed var(--border);
}

/* Spending-vs-Income detail panel's Net line, when spending outpaced income that
   month — same red as everywhere else "over" is signaled (budgets, over-budget tiles). */
.fin-trends-detail-total.negative {
  color: #b3453f;
}

.fin-dash-detail-tx-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}

.fin-dash-tx-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  border-top: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.fin-dash-tx-row:first-child {
  border-top: none;
}

.fin-dash-tx-row:hover {
  background: var(--bg);
}

.fin-review-group {
  padding: 12px 0;
  border-top: 1px solid var(--border);
}

.fin-review-group:first-child {
  border-top: none;
  padding-top: 0;
}

.fin-review-group-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.fin-review-group-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.fin-review-merchant {
  font-weight: 600;
}

.fin-review-meta {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.fin-review-error {
  color: #b3453f;
  font-size: 0.85rem;
  line-height: 1.4;
  margin: 12px 0 0;
}

.fin-review-cat-select {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

.fin-review-newcat {
  margin-top: 8px;
}

.fin-newcat-input {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.fin-review-toggle {
  background: none;
  color: var(--accent);
  padding: 8px 0 0;
  font-size: 0.8rem;
}

.fin-review-rows {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.fin-review-row-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.82rem;
  color: var(--text-muted);
}

.fin-review-skip-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
}

.fin-ledger-day {
  margin-bottom: 14px;
}

.fin-ledger-date-header {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 4px;
}

/* `li.fin-ledger-row` (type + class) matches .checklist li's own specificity —
   needs the type prefix to reliably win the tie and override its display:flex,
   since this row is now a column of stacked pieces (main row, delete confirm)
   rather than a single flex line. */
li.fin-ledger-row {
  display: block;
  padding: 0;
}

.fin-ledger-row-main {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px;
}

.fin-ledger-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.fin-ledger-meta {
  font-size: 0.76rem;
  color: var(--text-muted);
}

/* A linked-transfer/reimbursement marker sitting right in the description line
   (not just the meta line below) — small and muted so it doesn't compete with the
   description text, but always in the same spot so it's recognizable at a glance
   while scrolling a long list. */
.fin-ledger-badge {
  display: inline-block;
  margin-right: 4px;
  font-size: 0.85em;
  opacity: 0.65;
}

.fin-ledger-amount {
  font-family: var(--font-mono);
  font-weight: 600;
  white-space: nowrap;
}

.fin-ledger-amount.income {
  color: var(--done);
}

/* Quiet by default (no filled circle), same treatment as the Categories list's
   remove/chevron buttons — small enough, and light enough at rest, to avoid an
   accidental tap deleting real financial data. */
.fin-ledger-edit-btn,
.fin-ledger-remove {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.fin-ledger-edit-btn:hover,
.fin-ledger-edit-btn:focus-visible,
.fin-ledger-remove:hover,
.fin-ledger-remove:focus-visible {
  background: var(--border);
  color: var(--text);
}

.fin-ledger-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin: 6px 0 0;
  font-size: 0.85rem;
}

.fin-ledger-confirm .quick-actions {
  gap: 6px;
}

.fin-ledger-confirm-delete {
  background: #b3453f;
}

/* Edit modal — a bottom sheet on phones (thumb-reachable, matches the app's bottom-nav
   posture), a centered dialog once there's room for one. */
.fin-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .fin-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.fin-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .fin-modal {
    border-radius: var(--radius);
  }
}

.fin-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.fin-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.fin-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.fin-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.fin-edit-form {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.fin-edit-form input,
.fin-edit-form select {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

.fin-edit-form input:disabled,
.fin-edit-form select:disabled {
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.7;
}

.fin-edit-locked-note {
  font-size: 0.76rem;
  color: var(--text-muted);
  line-height: 1.4;
  margin: 2px 0 10px;
}

.fin-edit-form .quick-actions {
  margin-top: 10px;
}

.fin-edit-link-row {
  display: flex;
  gap: 8px;
  margin: 4px 0 10px;
}

.fin-edit-link-row .fin-edit-action-btn {
  flex: 1 1 0;
}

.fin-edit-transfer:has(> :not([hidden])) {
  margin: 4px 0 10px;
}

/* These are occasional, secondary actions (most transactions are neither a transfer
   nor a reimbursement) — sized down from the app's default button chrome so they
   don't read as a primary call-to-action next to Save. */
.fin-edit-action-btn {
  display: inline-flex;
  width: auto;
  padding: 7px 12px;
  font-size: 0.82rem;
}

.fin-edit-candidate-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.fin-edit-candidate-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.fin-edit-candidate-link-btn {
  flex-shrink: 0;
  padding: 6px 12px;
  font-size: 0.82rem;
}

.fin-edit-linked-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 0.85rem;
}

.fin-edit-reimburse-remove-btn {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.fin-edit-reimburse-remove-btn:hover {
  background: var(--border);
  color: var(--text);
}

.fin-edit-attachments {
  margin: 4px 0 10px;
}

.fin-edit-attachment-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.fin-edit-attachment-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.fin-edit-attachment-thumb {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  flex-shrink: 0;
}

.fin-edit-attachment-icon {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.fin-edit-attachment-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.85rem;
}

.fin-edit-attachment-download {
  flex-shrink: 0;
  color: var(--accent);
  text-decoration: none;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
}

.fin-edit-attachment-remove {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.fin-edit-attachment-remove:hover {
  background: var(--border);
  color: var(--text);
}

.fin-edit-attachment-add-label {
  display: inline-block;
  margin-top: 8px;
  font-size: 0.85rem;
  color: var(--accent);
  cursor: pointer;
}

.fin-edit-reimburse-summary {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 8px 0 0;
}

/* Stub / coming soon pages */
.stub-page {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}

.stub-page h2 {
  color: var(--text);
  margin-bottom: 8px;
}

/* Auth screen */
.auth-screen {
  max-width: 360px;
  margin: 60px auto;
  padding: 0 var(--gap);
}

.auth-screen .card {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.auth-screen input {
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.auth-error {
  color: #b3453f;
  font-size: 0.85rem;
  min-height: 1em;
}

/* Blocks */
.bl-template-list {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.bl-template-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius);
  background: var(--bg);
}

.bl-template-title {
  font-weight: 600;
  font-size: 0.9rem;
}

.bl-template-meta {
  flex: 1;
  color: var(--text-muted);
  font-size: 0.78rem;
}

.bl-inactive {
  opacity: 0.5;
}

.bl-ticket-chip {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
  font-size: 0.82rem;
}

.bl-ticket-chip.armed {
  background: var(--accent);
  color: white;
}

.bl-placed {
  cursor: pointer;
}

/* Week view: hour column pinned on the left, 7 scrollable day columns each
   with their own mini hour-grid, sharing one common hour range so rows align. */
.week-grid {
  display: flex;
  overflow: auto;
  max-height: 420px;
  border-radius: var(--radius);
  scroll-snap-type: x mandatory; /* horizontal scroll always settles on a whole
    day column, never stops mid-column showing a half-visible sliver of the
    next/previous day */
}

.week-hours {
  position: sticky;
  left: 0;
  z-index: 3;
  flex-shrink: 0;
  width: 34px;
  background: var(--surface);
}

.week-hours-spacer {
  height: 30px;
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 4;
}

.week-hours-labels {
  position: relative;
}

.week-days-scroll {
  display: flex;
  flex: 1;
}

.week-day-col {
  flex: 1 1 0;
  min-width: 92px;
  border-left: 1px solid var(--border);
  scroll-snap-align: start;
}

.week-day-header {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface);
  text-align: center;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-muted);
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  height: 30px;
  box-sizing: border-box;
}

.week-day-header.today {
  color: var(--accent);
}

.week-day-track {
  position: relative;
}

.week-day-track .tl-event {
  font-size: 0.62rem;
  padding: 2px 4px;
}

.week-day-track .tl-event .t {
  font-size: 0.56rem;
}

.bl-field-row {
  display: flex;
  gap: 8px;
}

.bl-field {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.bl-field-label {
  font-size: 0.72rem;
  color: var(--text-muted);
  font-weight: 600;
}

.bl-field select,
.bl-field input {
  width: 100%;
}

/* Music tab: three sub-tabs (Events/Upcoming/Artists), same .wx-toggle pill Finance
   already reuses for its own tab bar — bare in the container, not wrapped in a .card. */
.mus-tab-bar {
  margin: 0 0 16px;
}

.mus-field-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 12px 0 6px;
}

.mus-field-label:first-child {
  margin-top: 0;
}

/* Add/edit event form — same labeled-field shape as Finance's transaction edit
   modal (.fin-edit-form), its own prefixed copy rather than a shared class. */
.mus-edit-form {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mus-edit-form input {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

.mus-edit-form .quick-actions {
  margin-top: 10px;
}

.mus-edit-checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--text-muted);
  margin: 4px 0 2px;
}

.mus-edit-checkbox-label input {
  width: auto;
  flex-shrink: 0;
  padding: 0;
  border: none;
  background: none;
}

#mus-search {
  /* Same fix as #fin-ledger-search/#art-search: .card-header h2 zeroes its own
     bottom margin, so this needs its own margin-top or the "Events" title and
     this input sit almost flush against each other. */
  width: 100%;
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  margin-top: 12px;
  margin-bottom: 10px;
}

#mus-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

/* Year nav — same pill/arrow shape as Finance's dashboard period nav
   (.fin-dash-period-nav), its own prefixed copy per this app's per-pillar-CSS
   convention rather than a shared class. */
.mus-year-nav {
  display: flex;
  align-items: center;
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: 4px;
  margin: 10px 0 8px;
}

.mus-year-nav-arrow {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--accent);
  font-size: 1rem;
}

.mus-year-nav-arrow:hover {
  background: rgba(255, 255, 255, 0.5);
}

.mus-year-nav-arrow:disabled {
  background: none;
  opacity: 0.35;
}

.mus-year-nav-label {
  flex: 1;
  text-align: center;
  font-weight: 700;
  font-size: 1rem;
  color: var(--text);
}

/* Per-year stats — same shape as Finance's movement mini-cards + spending pie,
   its own prefixed copy per this app's convention. */
.mus-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin-bottom: 10px;
}

.mus-stat-card {
  padding: 14px;
}

/* One stat card is a real <button> (opens the venue modal) — undo the global
   button reset's white-on-accent look so it reads identically to the other two
   plain stat cards, just with a click affordance added on top. */
.mus-stat-card-clickable {
  display: block;
  width: 100%;
  text-align: left;
  color: var(--text);
}

.mus-stat-card-clickable:hover {
  background: var(--bg);
}

.mus-stat-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.mus-stat-amount {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 700;
}

.mus-pie-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 4px 0 16px;
}

.mus-pie {
  width: 160px;
  height: 160px;
}

.mus-pie-total-label {
  font-size: 7px;
  fill: var(--text-muted);
}

.mus-pie-total-amount {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  fill: var(--text);
}

.mus-venue-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px 12px;
  width: 100%;
  margin-top: 12px;
}

.mus-venue-tile {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  overflow: hidden;
}

.mus-venue-tile-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-sm);
}

.mus-venue-tile-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mus-venue-tile-count {
  flex-shrink: 0;
  color: var(--text-muted);
  margin-left: auto;
}

.mus-spend-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
}

.mus-spend-row:first-child {
  border-top: none;
}

.mus-spend-info {
  min-width: 0;
}

.mus-spend-name {
  font-weight: 600;
  font-size: 0.92rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mus-spend-meta {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 1px;
}

.mus-spend-amount {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-weight: 700;
}

.mus-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  cursor: pointer;
}

/* A real <img> rather than a background-image crop, so a portrait poster (event
   posters are commonly 1080×1350, a 4:5 ratio) shows in full instead of having its
   top/bottom cropped off to fit a fixed box — the card just grows taller to fit it.
   Only the empty/no-photo state gets a fixed shape (a square), since there's
   nothing there to size around. */
.mus-card-thumb {
  background-color: var(--accent-soft);
  overflow: hidden;
  flex-shrink: 0;
}

.mus-card-thumb-empty {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mus-card-thumb img {
  display: block;
  width: 100%;
  height: auto;
}

.mus-card-thumb-fallback {
  font-size: 1.8rem;
  opacity: 0.6;
}

.mus-card-body {
  padding: 10px 12px;
}

.mus-card-name {
  font-weight: 600;
  font-size: 0.92rem;
}

.mus-card-subtitle {
  color: var(--text-muted);
  font-size: 0.78rem;
  margin-top: 1px;
}

/* Venue and date each get their own line rather than sharing one "Venue · Date"
   row — easier to scan, and gives the title/subtitle block real breathing room
   above it instead of everything sitting flush together. */
.mus-card-venue {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 10px;
}

.mus-card-date {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 1px;
}

.mus-card-type {
  display: inline-block;
  margin-top: 6px;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.7rem;
  font-weight: 600;
}

.mus-empty-msg {
  grid-column: 1 / -1;
}

.mus-card-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

/* Quiet by default (no filled circle) — the same treatment Finance's own edit/
   remove buttons use (.fin-ledger-edit-btn/.fin-ledger-remove), not the bolder
   .icon-btn look. Small and light at rest so it doesn't read as a prominent
   action, only reveals itself with a background on hover/focus. */
.mus-edit-btn,
.mus-delete-btn {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.mus-edit-btn:hover,
.mus-edit-btn:focus-visible,
.mus-delete-btn:hover,
.mus-delete-btn:focus-visible {
  background: var(--border);
  color: var(--text);
}

.mus-delete-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-top: 8px;
  font-size: 0.85rem;
}

.mus-delete-confirm .quick-actions {
  gap: 6px;
}

.mus-confirm-delete-btn {
  background: #b3453f;
}

.mus-detail-row {
  font-size: 0.9rem;
  margin-top: 6px;
}

.mus-ticket-row {
  font-size: 0.9rem;
}

.mus-ticket-row-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.mus-link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-size: 0.85rem;
  cursor: pointer;
}

.mus-linked-list {
  margin-top: 6px;
}

.mus-linked-item {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 2px 10px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
}

.mus-linked-item:first-child {
  border-top: none;
}

.mus-linked-item-info {
  min-width: 0;
}

.mus-linked-item-desc {
  font-size: 0.82rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mus-linked-item-meta {
  color: var(--text-muted);
  font-size: 0.75rem;
  margin-top: 1px;
}

.mus-linked-item-amount {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 0.85rem;
}

/* Same quiet-icon treatment as .mus-delete-btn/.fin-ledger-remove — unlinking
   isn't destructive to any real data (the transaction itself is untouched), but
   it should still read as a lightweight, deliberate tap rather than a primary
   action next to it. */
.mus-unlink-btn {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 20px;
  height: 20px;
  font-size: 0.85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.mus-unlink-btn:hover,
.mus-unlink-btn:focus-visible {
  background: var(--border);
  color: var(--text);
}

.mus-link-picker {
  margin-top: 8px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.mus-link-search {
  width: 100%;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.mus-link-candidates {
  max-height: 220px;
  overflow-y: auto;
  margin-top: 8px;
}

.mus-link-candidate {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 10px;
  padding: 8px 4px;
  border-top: 1px solid var(--border);
  cursor: pointer;
}

.mus-link-candidate:first-child {
  border-top: none;
}

.mus-link-candidate:hover {
  background: var(--accent-soft);
}

.mus-link-candidate-desc {
  font-weight: 600;
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mus-link-candidate-meta {
  grid-column: 1 / 2;
  color: var(--text-muted);
  font-size: 0.78rem;
}

.mus-link-candidate-amount {
  grid-column: 2 / 3;
  grid-row: 1 / 3;
  align-self: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 0.85rem;
}

.mus-link-picker .mus-link-cancel-btn {
  margin-top: 8px;
}

.mus-artist-section {
  margin-top: 10px;
}

.mus-artist-day {
  margin-top: 8px;
}

.mus-artist-day-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-weight: 600;
  margin-bottom: 4px;
}

.mus-artist-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.mus-artist-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px 4px 10px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 600;
}

.mus-artist-remove {
  background: none;
  border: none;
  color: var(--accent);
  width: 16px;
  height: 16px;
  padding: 0;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  cursor: pointer;
  opacity: 0.7;
}

.mus-artist-remove:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.5);
}

/* Same row shape as every other "input + icon-btn" control in this app (e.g. the
   Calendar/Weather sync row) — .mus-artist-add-btn is a plain .icon-btn, not its
   own bespoke button, and the input matches standard field styling (.mus-edit-form
   input) instead of the pill shape the chips themselves use. Kept out of the chip
   row entirely (its own row below) so it doesn't read as "one more tag". */
.mus-artist-add-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.mus-artist-input {
  flex: 1;
  min-width: 0;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

.mus-media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 8px;
  margin-top: 8px;
}

.mus-media-item {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--border);
}

.mus-media-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.mus-media-broken {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 0.7rem;
  color: var(--text-muted);
  text-align: center;
  padding: 4px;
}

.mus-media-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  border: none;
  background: rgba(36, 34, 46, 0.7);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mus-media-remove:active {
  transform: scale(0.92);
}

.mus-media-add-label {
  display: inline-block;
  margin-top: 10px;
  font-size: 0.85rem;
  color: var(--accent);
  cursor: pointer;
}

/* Event detail modal — bottom sheet on phones, centered dialog once there's room,
   same posture as Finance's transaction edit modal. */
.mus-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .mus-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.mus-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .mus-modal {
    border-radius: var(--radius);
  }
}

.mus-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.mus-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.mus-modal-heading {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.mus-modal-eyebrow {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-bottom: 1px;
}

.mus-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.mus-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

/* Same reasoning as .mus-card-thumb above — a real <img> so a portrait poster
   shows in full rather than being cropped to a fixed box. */
.mus-modal-thumb {
  border-radius: var(--radius);
  background-color: var(--accent-soft);
  overflow: hidden;
  margin-bottom: 12px;
}

.mus-modal-thumb-empty {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mus-modal-thumb img {
  display: block;
  width: 100%;
  height: auto;
}

.mus-modal-subtitle {
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-top: 1px;
}

.mus-modal-venue {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin-top: 6px;
}

.mus-modal-date {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin-top: 1px;
}

/* Artists tab */
#art-search {
  /* Same fix as #fin-ledger-search: .card-header h2 zeroes its own bottom margin
     (so a header with a "+" button stays vertically centered), so the element
     right after it needs its own margin-top or the title and this input sit
     almost flush against each other. */
  width: 100%;
  font: inherit;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  margin-top: 12px;
  margin-bottom: 10px;
}

#art-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

.art-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 14px;
  cursor: pointer;
}

.art-card-avatar {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-sm);
  background-color: var(--accent-soft);
  background-size: cover;
  background-position: center;
  margin-bottom: 8px;
  flex-shrink: 0;
}

.art-avatar-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  font-weight: 700;
  font-size: 1.1rem;
}

.art-card-name {
  font-weight: 600;
  font-size: 0.92rem;
}

.art-card-tally {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
}

.art-tally-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  flex-shrink: 0;
}

.art-tally-extra {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-left: 2px;
}

.art-empty-msg {
  grid-column: 1 / -1;
}

/* Same bottom-sheet-on-phone/centered-dialog modal shape as Music's own modals —
   own prefixed copy, per this app's per-tab CSS convention. */
.art-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .art-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.art-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .art-modal {
    border-radius: var(--radius);
  }
}

.art-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.art-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.art-modal-avatar-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

.art-modal-avatar-wrap {
  position: relative;
  flex-shrink: 0;
}

.art-modal-avatar {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-sm);
  background-color: var(--accent-soft);
  background-size: cover;
  background-position: center;
  font-size: 1.3rem;
}

.art-photo-remove {
  position: absolute;
  top: -2px;
  right: -2px;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  border: none;
  background: rgba(36, 34, 46, 0.7);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.art-photo-add-label {
  display: inline-block;
  font-size: 0.85rem;
  color: var(--accent);
  cursor: pointer;
}

.art-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.art-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.art-event-row {
  padding: 10px 0;
  border-top: 1px solid var(--border);
}

.art-event-row:first-child {
  border-top: none;
}

.art-event-name {
  font-weight: 600;
  font-size: 0.92rem;
}

.art-event-meta {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 1px;
}

.art-modal-actions {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

/* Same quiet treatment as Music's own edit/delete buttons (.mus-edit-btn/
   .mus-delete-btn) and, further back, Finance's .fin-ledger-remove — the one
   real "delete" button convention this app already has. */
.art-delete-btn {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.art-delete-btn:hover,
.art-delete-btn:focus-visible {
  background: var(--border);
  color: var(--text);
}

.art-delete-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-top: 8px;
  font-size: 0.85rem;
}

.art-delete-confirm .quick-actions {
  gap: 6px;
}

#art-confirm-delete-btn {
  background: #b3453f;
}

/* Upcoming Events tab — a plain list, no year-nav/stats/search: it's a short,
   soonest-first glance list by nature, not something you browse or filter. */
#upc-list {
  margin-top: 12px; /* .card-header h2 has margin:0 (keeps the "+"-button rows
  centered elsewhere) so whatever sits directly under the header needs its own
  top margin — the same fix already applied to #mus-search/#art-search. */
}

#upc-empty {
  margin-top: 12px;
}

.upc-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
}

.upc-row:first-child {
  border-top: none;
}

.upc-row-info {
  min-width: 0;
}

.upc-row-subtitle {
  color: var(--text-muted);
  font-size: 0.78rem;
}

.upc-row-name {
  font-weight: 600;
  font-size: 0.92rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.upc-row-meta {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 1px;
}

.upc-row-countdown {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

/* Total-spend stat card + its breakdown modal — same shape as Events' own Total
   Spend stat/modal, its own "upc-" prefixed copy per this app's usual rule of never
   sharing classes across sub-tabs even for visually identical components. Only one
   card here (not a grid like Events' three) since Upcoming has nothing to pair it
   with — no year/venue breakdown makes sense for a list that's inherently "right
   now onward". */
.upc-stat-card {
  display: block;
  width: 100%;
  text-align: left;
  color: var(--text);
  padding: 14px;
  margin-top: 12px; /* .card-header h2 has margin:0 (keeps the "+"-button row
  centered elsewhere) so whatever sits directly under the header needs its own top
  margin — the same fix already applied to #upc-list/#upc-empty above. */
}

.upc-stat-card:hover {
  background: var(--bg);
}

.upc-stat-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.upc-stat-amount {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 700;
}

.upc-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .upc-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.upc-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .upc-modal {
    border-radius: var(--radius);
  }
}

.upc-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.upc-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.upc-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.upc-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.upc-spend-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
}

.upc-spend-row:first-child {
  border-top: none;
}

.upc-spend-info {
  min-width: 0;
}

.upc-spend-name {
  font-weight: 600;
  font-size: 0.92rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.upc-spend-meta {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 1px;
}

.upc-spend-amount {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-weight: 700;
}

/* Kanban — a real side-by-side board. `main` is capped at 640px everywhere else
   in this app, but that was never a deliberate constraint for this section (just
   what the original skeleton happened to ship with) — widened only while this
   view is the visible one, so every other section's layout is untouched. */
main:has(> #view-kanban:not([hidden])) {
  max-width: 1100px;
}

.kan-board {
  display: flex;
  align-items: flex-start; /* flex's default (stretch) would force every column to
                               match whichever one has the most cards, padding out
                               shorter columns with dead space at the bottom */
  gap: var(--gap);
  overflow-x: auto;
  padding-bottom: 6px;
  scroll-snap-type: x proximity;
}

.kan-column {
  flex: 0 0 min(240px, 82vw);
  min-width: 0; /* a nowrap notes line inside would otherwise force this wider than
                   the flex-basis — the classic flex-item auto-min-width gotcha */
  min-height: min(560px, 70vh); /* a floor so a column with only 1-2 tasks still reads
                                    as a real column instead of a stub floating above
                                    a mostly-empty page; columns with more cards just
                                    grow taller than this on their own */
  margin-bottom: 0;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
}

.kan-count {
  color: var(--text-muted);
  font-weight: 400;
  font-size: 0.85rem;
}

.kan-column-list {
  list-style: none;
  margin: 12px 0 0; /* the header h2's own margin-bottom can't escape the flex
                       .card-header it sits in, so without this the "+" button
                       sits flush against the first card below it */
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1; /* fills the rest of the column, so the whole visible box is a real drop
              target — without this, a short column's list only occupied the space
              its own cards took up, and dropping into the blank space below that
              (inside the column but outside the actual list element) silently did
              nothing, which is what made cross-column dragging look broken */
}

.kan-column-list:empty {
  align-items: center;
  justify-content: center;
}

.kan-column-list:empty::before {
  content: "No tasks here.";
  color: var(--text-muted);
  font-size: 0.85rem;
}

.kan-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
}

.kan-card-title {
  font-weight: 600;
  font-size: 0.92rem;
}

.kan-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Plain text, not a tag chip — a due date isn't a category like the pillar tag next
   to it, just a colored label (like Finance's over-budget amounts) when it matters. */
.kan-due-badge {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-muted);
}

.kan-due-badge.due-soon {
  color: var(--done);
}

.kan-due-badge.overdue {
  color: #b3453f;
}

.kan-card-notes {
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kan-card-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
  margin-top: 2px;
}

.kan-move-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 24px;
  height: 24px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  cursor: pointer;
  flex-shrink: 0;
}

.kan-move-btn:hover,
.kan-move-btn:focus-visible {
  background: var(--border);
  color: var(--text);
}

.kan-move-btn:disabled {
  opacity: 0.25;
  cursor: default;
}

.kan-card.kan-dragging {
  opacity: 0.5;
}

.kan-card.kan-ghost {
  background: var(--accent-soft);
  border: 1px dashed var(--accent);
}

/* Add/edit modal — same bottom-sheet-on-phone/centered-dialog shape as every
   other modal in this app, own prefixed copy per the established convention. */
.kan-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .kan-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.kan-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .kan-modal {
    border-radius: var(--radius);
  }
}

.kan-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.kan-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.kan-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.kan-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.kan-field-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 12px 0 6px;
}

.kan-field-label:first-child {
  margin-top: 0;
}

.kan-form input,
.kan-form select,
.kan-form textarea {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

.kan-form textarea {
  resize: vertical;
  min-height: 60px;
}

.kan-delete-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-top: 10px;
  font-size: 0.85rem;
}

.kan-delete-confirm .quick-actions {
  gap: 6px;
}

.kan-confirm-delete-btn {
  background: #b3453f;
}

.kan-subtask-progress {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.kan-subtasks {
  margin-top: 12px;
}

.kan-subtask-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.kan-subtask-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
}

.kan-subtask-row input[type="checkbox"] {
  width: 20px;
  height: 20px;
  accent-color: var(--done);
  flex-shrink: 0;
}

.kan-subtask-text {
  flex: 1;
}

.kan-subtask-text.done {
  text-decoration: line-through;
  color: var(--text-muted);
}

.kan-subtask-add {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

.kan-subtask-add input {
  flex: 1;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
}

.jrn-page {
  padding: 32px 24px;
}

.jrn-page-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 28px;
}

.jrn-date {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 600;
}

.jrn-today-btn,
.jrn-edit-toggle-btn {
  flex-shrink: 0;
  padding: 6px 12px;
  font-size: 0.8rem;
}

/* History card's own header — "Today" lives here now, not up in the entry
   card, since jumping to today is a calendar-navigation action, not an
   entry-editing one (same reasoning that keeps Edit up with the date/fields
   it actually controls). */
.jrn-history-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.jrn-history-header h2 {
  margin: 0;
}

.jrn-edit-toggle-btn.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

/* Past days/weeks default to locked (view-only) so they can't be edited by an
   accidental tap — the Edit toggle above explicitly unlocks whichever one is
   currently selected. Today (and the current week, in Week mode) is never
   locked, so none of this applies there. */
.jrn-locked .jrn-gratitude-input,
.jrn-locked .jrn-rt-editor {
  background: var(--surface);
  cursor: default;
}

.jrn-locked .jrn-mood-btn:disabled {
  cursor: default;
}

.jrn-field-group {
  margin-bottom: 24px;
}

.jrn-field-group:last-of-type {
  margin-bottom: 4px;
}

.jrn-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 10px;
}

.jrn-mood-row {
  display: flex;
  gap: 8px;
}

.jrn-mood-btn {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  font-size: 1.5rem;
  line-height: 1;
  padding: 10px 8px;
  opacity: 0.55; /* unselected emoji sit back a bit so the picked one reads as picked */
}

.jrn-mood-btn.selected {
  background: var(--accent-soft);
  border-color: var(--accent);
  opacity: 1;
}

.jrn-gratitude-input {
  display: block;
  width: 100%;
  font: inherit;
  padding: 10px 2px;
  border: none;
  border-bottom: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  line-height: 1.6;
}

.jrn-gratitude-input + .jrn-gratitude-input {
  margin-top: 2px;
}

.jrn-gratitude-input:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

/* Reflection/Wins/Losses/Lessons/Focus are contenteditable divs, not textareas —
   basic bold/italic/underline via a small toolbar (js/journal.js's
   wireRichTextToolbar), so real formatting shows inline while typing rather
   than raw markdown syntax. */
.jrn-rt-toolbar {
  display: flex;
  gap: 4px;
  margin-bottom: 6px;
}

.jrn-rt-toolbar button {
  width: 28px;
  height: 28px;
  padding: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.jrn-rt-toolbar button.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.jrn-rt-editor {
  display: block;
  width: 100%;
  font: inherit;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  line-height: 1.7;
  min-height: 96px;
  overflow-y: auto;
}

.jrn-rt-editor.jrn-rt-editor-lg {
  min-height: 150px;
}

.jrn-rt-editor:focus {
  outline: none;
  border-color: var(--accent);
}

.jrn-rt-editor:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
}

.jrn-saved-at {
  font-size: 0.75rem;
  color: var(--text-muted);
  height: 1em;
}

/* Song of the day — a Spotify search-and-pick, same quiet-row-plus-✕ shape as
   Finance's linked-transaction tag and the same "results list re-renders, input
   never loses focus" pattern as its search picker. */
.jrn-song-add-btn {
  width: 100%;
}

.jrn-song-search-input {
  display: block;
  width: 100%;
  font: inherit;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  margin-bottom: 8px;
}

.jrn-song-search-input:focus {
  outline: none;
  border-color: var(--accent);
}

.jrn-song-results {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.jrn-song-result {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 6px 10px;
}

.jrn-song-hint {
  font-size: 0.85rem;
  color: var(--text-muted);
  padding: 6px 2px;
}

.jrn-song-picked {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
}

.jrn-song-art {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  flex-shrink: 0;
}

.jrn-song-art-empty {
  background: var(--border);
}

.jrn-song-info {
  flex: 1;
  min-width: 0;
}

.jrn-song-title {
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.jrn-song-artist {
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.jrn-song-clear {
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  padding: 0;
  width: 22px;
  height: 22px;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}

.jrn-song-clear:hover,
.jrn-song-clear:focus-visible {
  background: var(--border);
  color: var(--text);
}

/* Weekly review's read-only mood readout — one column per day of the week,
   pulled from that week's already-logged daily entries. Not editable here. */
.jrn-week-mood-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 24px;
  padding: 10px 4px;
  background: var(--bg);
  border-radius: var(--radius);
}

.jrn-week-mood-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex: 1;
}

.jrn-week-mood-dow {
  font-size: 0.65rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.jrn-week-mood-emoji {
  font-size: 1.3rem;
  line-height: 1;
}

/* Journal's history calendar reuses Trackers' .thist-* month-grid pattern as-is
   (same header/nav/grid markup and classes) rather than inventing a new one —
   these are the only two overrides it needs: bigger cells to fit a mood emoji
   (Trackers' cells only ever hold a bare day number), and a quieter "has an
   entry" tint instead of Trackers' solid --done block, since the emoji itself
   already carries the information and a loud color block on top would fight
   the "quiet page" feel. */
.jrn-cal-grid .thist-day {
  font-size: 1rem;
}

.jrn-cal-grid .thist-day.done {
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 400;
}

.jrn-cal-grid .thist-day.selected {
  box-shadow: inset 0 0 0 2px var(--accent);
}

[hidden] {
  display: none !important;
}

/* Career: top-level tab bar and Library's own inner sub-tab bar both reuse
   .wx-toggle's segmented-control look with the same wrap-to-second-row fix
   Finance's .fin-tab-bar already uses for more than two options. */
.car-tab-bar,
.car-lib-tab-bar {
  flex-wrap: wrap;
  margin: 0 0 16px;
}

.car-tab-bar button,
.car-lib-tab-bar button {
  flex: 1 1 auto;
  min-width: 90px;
}

/* Career's own modal — same shape as .kan-modal, its own prefix per this
   codebase's per-module convention (see .kan-modal-* / .mus-edit-form etc.). */
.car-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 26, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
}

@media (min-width: 640px) {
  .car-modal-overlay {
    align-items: center;
    padding: 20px;
  }
}

.car-modal {
  background: var(--surface);
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 18px 22px;
}

@media (min-width: 640px) {
  .car-modal {
    border-radius: var(--radius);
  }
}

.car-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.car-modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.car-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.car-modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.car-field-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 12px 0 6px;
}

.car-field-label:first-child {
  margin-top: 0;
}

.car-check-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 12px 0 0;
  font-size: 0.9rem;
}

/* .car-form input's own width: 100% is meant for text/date/number fields — a
   checkbox needs its native size instead, here and in .car-check-list below. */
.car-form input[type="checkbox"] {
  width: auto;
  flex-shrink: 0;
}

.car-form input,
.car-form select,
.car-form textarea {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

.car-form textarea {
  resize: vertical;
  min-height: 60px;
}

.car-delete-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-top: 10px;
  font-size: 0.85rem;
}

.car-delete-confirm .quick-actions {
  gap: 6px;
}

.car-confirm-delete-btn {
  background: #b3453f;
}

/* Bullet pool (inside the Experience modal) and the skill/experience checkbox
   list share the same plain-list-row look — small, quiet, no card chrome since
   they're already nested inside a modal. */
.car-bullet-list,
.car-check-list {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 160px;
  overflow-y: auto;
}

.car-bullet-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.88rem;
}

.car-bullet-text {
  flex: 1;
}

.car-remove-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  flex-shrink: 0;
}

.car-remove-btn:hover {
  color: var(--text);
}

.car-bullet-add {
  display: flex;
  gap: 8px;
}

.car-bullet-add input {
  flex: 1;
}

.car-check-list label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
}

/* Achievement bank's metric callout — a small quiet chip in front of the
   achievement text, same idea as .fin-ledger-badge's inline marker. */
.car-chip {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  padding: 1px 6px;
}

/* Applications: a real side-by-side pipeline board, same "widen main only while
   this section is visible" treatment as Kanban's own board (see .kan-board's
   own comment above) — Career's Library tab just gets the extra room for free,
   harmless since its own cards/forms don't stretch to fill it. */
main:has(> #view-career:not([hidden])) {
  max-width: 1100px;
}

.car-app-stats-row {
  display: flex;
  gap: var(--gap);
  flex-wrap: wrap;
}

.car-app-stat {
  display: flex;
  flex-direction: column;
  min-width: 70px;
}

.car-app-stat-num {
  font-family: var(--font-mono);
  font-size: 1.4rem;
  font-weight: 700;
}

.car-app-stat-label {
  font-size: 0.76rem;
  color: var(--text-muted);
}

.car-app-board {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  overflow-x: auto;
  padding-bottom: 6px;
  scroll-snap-type: x proximity;
  margin-top: 16px;
}

.car-app-column {
  flex: 0 0 min(240px, 82vw);
  min-width: 0;
  min-height: min(480px, 65vh);
  margin-bottom: 0;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
}

.car-app-count {
  color: var(--text-muted);
  font-weight: 400;
  font-size: 0.85em;
}

.car-app-column-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}

.car-app-card {
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  cursor: pointer;
}

.car-app-card-title {
  font-weight: 600;
  font-size: 0.9rem;
}

.car-app-card-company {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.car-app-card-meta {
  font-size: 0.76rem;
  color: var(--text-muted);
  margin-top: 4px;
}

.car-app-card-actions {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
  margin-top: 6px;
}

.car-app-card.car-app-dragging {
  opacity: 0.9;
  box-shadow: 0 4px 14px rgba(20, 18, 26, 0.18);
}

.car-app-card.car-app-ghost {
  opacity: 0.4;
}

/* Interview log — inline rows within the Application modal, same idea as
   Kanban's inline subtask list (a plain summary row that expands into a small
   editable form in place, rather than stacking a second modal on top). */
.car-interview-list {
  list-style: none;
  margin: 0 0 6px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.car-interview-row {
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 0.85rem;
  cursor: pointer;
}

.car-interview-row-editing {
  cursor: default;
}

.car-interview-row-editing input,
.car-interview-row-editing select,
.car-interview-row-editing textarea {
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  width: 100%;
}

.car-app-interviews-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Resume-snapshot picker inside the Application modal — skills/achievements as
   plain checklists, bullets grouped under a small heading per experience entry
   so it's clear which job each bullet is pulling from. */
.car-app-resume-exp-group {
  margin-bottom: 10px;
}

.car-app-resume-exp-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 4px;
}

/* Edit-columns modal — a plain reorderable list (SortableJS, same as the board
   itself) of the pipeline's user-editable stages. */
.car-stage-list {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.car-stage-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  cursor: grab;
}

.car-stage-label-input {
  flex: 1;
  min-width: 100px;
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.car-stage-terminal-label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.car-stage-terminal-label input[type="checkbox"] {
  width: auto;
  flex-shrink: 0;
}

.car-stage-row-status {
  flex-basis: 100%;
  font-size: 0.78rem;
  margin: 0;
}

/* Cover Letters tab — paragraphs grouped under a category heading, same
   look as the resume picker's per-experience groups above. */
.car-cl-group {
  margin-bottom: 14px;
}

.car-cl-group:last-child {
  margin-bottom: 0;
}

/* Goals' quiet skill-gap nudge — a row of tappable chips above the Goals
   card, hidden entirely when there's nothing to suggest. Deliberately not a
   .card itself: this is a passing nudge, not a section with its own weight. */
.car-goal-suggestions {
  margin-bottom: 16px;
}

#car-goal-suggestion-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.car-goal-suggestion-chip {
  background: var(--accent-soft);
  color: var(--accent);
  border: none;
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}

.car-goal-suggestion-chip:hover {
  filter: brightness(0.95);
}
