/* ── Charts ──────────────────────────────────────────────── */
.charts-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 32px;
}

#overviewGrid,
#txnChartsGrid,
.widget-grid {
  grid-template-columns: repeat(20, 1fr);
}

@keyframes chartCardIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 24px;
  min-width: 0;
  contain: layout;
  position: relative; /* anchors the .nw-tick corners */
}

/* Every widget — chart cards, stat cards, the budget bar, range bars — enters
   the same way when it is inserted, then fills in as its own data arrives.
   The animation runs once per insertion, so a data refresh never re-hides a
   widget. There is deliberately no grid-wide "hide until everything loads":
   it made non-chart widgets wait on the slowest request on the page. */
.widget-grid [data-widget] {
  animation: chartCardIn 0.35s cubic-bezier(0.25, 1, 0.5, 1) both;
}
.widget-grid [data-widget]:nth-child(1) { animation-delay: 0.04s; }
.widget-grid [data-widget]:nth-child(2) { animation-delay: 0.09s; }
.widget-grid [data-widget]:nth-child(3) { animation-delay: 0.14s; }
.widget-grid [data-widget]:nth-child(4) { animation-delay: 0.19s; }
.widget-grid [data-widget]:nth-child(5) { animation-delay: 0.24s; }

#overviewGrid [data-widget-type="full"],
.widget-grid [data-widget-type="full"]  { grid-column: span 20; }
#overviewGrid [data-widget-type="half"],
.widget-grid [data-widget-type="half"]  { grid-column: span 10; }
#overviewGrid [data-widget-type="mini"],
.widget-grid [data-widget-type="mini"]  { grid-column: span 4; }

#txnChartsGrid [data-widget-type="mini"] { grid-column: span 4; }
#txnChartsGrid [data-widget-type="half"] { grid-column: span 10; }

.chart-title {
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.chart-subtitle {
  font-size: var(--text-caption);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 6px;
}
.chart-subtitle span {
  color: var(--text-bright);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.chart-delta {
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  margin-left: 8px;
  font-family: var(--font-mono);
}

/* Widget header dropdowns share one look with .hld-acct-select (below). */
.chart-title select {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0.04em;
  padding: 3px 20px 3px 6px;
  margin-right: 20px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%238d8470'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
}
.chart-title select:focus { outline: none; border-color: var(--accent); color: var(--text); }
.chart-title select option { background: var(--surface); color: var(--text); }
.txn-table-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: 20px;
  flex-shrink: 0;
}
.txn-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  background: var(--surface2);
  border: 1px solid var(--accent-border);
  color: var(--accent-text);
  border-radius: 6px;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s;
}
.txn-add-btn:hover { background: var(--accent-dim); border-color: var(--accent); }
#ovTxnCategory {
  min-width: 140px;
}

.chart-wrap { position: relative; height: 220px; }


#ovTxnTableWrap {
  max-height: 440px;
  overflow-y: auto;
}
#ovTxnTableWrap thead th {
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
  padding: 8px 16px;
  text-align: left;
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.chart-wrap.tall { height: 280px; }

/* ── Transaction table sortable headers ───────────────────── */
.ov-txn-th {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.ov-txn-th:hover { color: var(--text-bright); }
.ov-txn-th--active { color: var(--accent); }
.ov-txn-sort-ind {
  font-size: 9px;
  margin-left: 4px;
  opacity: 0.8;
}

/* ── Transaction table pagination ─────────────────────────── */
.ov-txn-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 12px 0 4px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}
.ov-txn-page-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  padding: 4px 12px;
  cursor: pointer;
  letter-spacing: 0.04em;
  transition: border-color 0.15s, color 0.15s;
}
.ov-txn-page-btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.ov-txn-page-btn:disabled {
  opacity: 0.3;
  cursor: default;
}
.ov-txn-page-info {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--muted);
  min-width: 60px;
  text-align: center;
}

/* ── Drag-and-drop layout ─────────────────────────────────── */
.drag-target { cursor: grab; }
.drag-target:active { cursor: grabbing; }

#txnChartsGrid .drag-handle,
#txnChartsGrid .budget-drag-handle { display: none; }
#txnChartsGrid .drag-target { cursor: default; }

.drag-handle {
  position: absolute;
  top: 10px;
  right: 12px;
  opacity: 0;
  transition: opacity 0.15s;
  color: var(--muted);
  font-size: var(--text-sm);
  user-select: none;
  cursor: grab;
}
.chart-card:hover .drag-handle { opacity: 1; }
.chart-card .drag-handle { font-size: 20px; }

.chart-card--ghost  { opacity: 0.4; border: 1px dashed var(--accent) !important; }
.chart-card--chosen { box-shadow: 0 8px 24px var(--shadow-color); }

/* ── Widget trash zone ────────────────────────────────────── */
#widgetTrashZone {
  position: fixed;
  bottom: 28px;
  left: calc(50vw + 110px); /* centered in main content area (220px sidebar / 2 = 110px offset) */
  transform: translateX(-50%) scale(0.85);
  display: none;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--surface2);
  border: 2px dashed var(--border);
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.2s, border-color 0.15s, color 0.15s, background 0.15s, transform 0.2s;
  z-index: 9999;
  pointer-events: none;
}
#widgetTrashZone.visible {
  display: flex;
  opacity: 1;
  transform: translateX(-50%) scale(1);
  pointer-events: auto;
}
#widgetTrashZone.active {
  border-color: var(--red);
  border-style: solid;
  color: var(--red);
  background: var(--red-dim);
  transform: translateX(-50%) scale(1.2);
}
body.sidebar-collapsed #widgetTrashZone {
  left: 50vw;
}

/* ── Overview empty state ─────────────────────────────────── */
#overviewEmptyState {
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px 0 32px;
}
#overviewEmptyMsg {
  font-size: var(--text-base);
  color: var(--muted);
  font-family: var(--font-sans);
  margin: 0;
  text-align: center;
}

/* ── Add widget button (in-flow, below widgets) ───────────── */
#addWidgetBtn {
  margin: 16px auto 32px;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--surface2);
  border: 2px dashed var(--border);
  color: var(--muted);
  cursor: pointer;
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
#addWidgetBtn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-dim);
}

.custom-page-empty-state {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px 0 32px;
}

.custom-page-empty-msg {
  font-size: var(--text-base);
  color: var(--muted);
  font-family: var(--font-sans);
  margin: 0;
  text-align: center;
}

.custom-page-add-btn {
  margin: 16px auto 32px;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--surface2);
  border: 2px dashed var(--border);
  color: var(--muted);
  cursor: pointer;
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.custom-page-add-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-dim);
}

/* ── Add widget picker grid ───────────────────────────────── */
.widget-back-btn {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  cursor: pointer;
  padding: 4px 0;
  margin-bottom: 4px;
  letter-spacing: 0.04em;
}
.widget-back-btn:hover { color: var(--text); }

.widget-picker-section {
  font-size: var(--text-caption);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-family: var(--font-sans);
  margin: 14px 0 6px;
}
.widget-picker-section:first-child { margin-top: 4px; }
.widget-picker-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  padding: 4px 0;
}
.widget-picker-card {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.widget-picker-card:hover { border-color: var(--accent); }
.widget-preview {
  background: var(--bg);
  border-radius: 4px;
  overflow: hidden;
  height: 88px;
}
.widget-preview--stat {
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.widget-preview--progress {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.widget-preview svg {
  width: 100%;
  height: 100%;
  display: block;
}
.widget-preview .preview-line { stroke: var(--accent); fill: none; stroke-width: 2; }
.widget-preview .preview-area { fill: var(--accent); opacity: 0.15; }
.widget-preview .preview-bar  { fill: var(--accent); opacity: 0.65; }

/* donut preview */
.preview-donut-wrap {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
}
.preview-donut {
  width: 54px; height: 54px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) 0% 34%, var(--color-investment) 34% 57%, var(--color-loan) 57% 74%, var(--muted) 74% 100%);
  -webkit-mask: radial-gradient(circle, transparent 36%, black 37%);
  mask: radial-gradient(circle, transparent 36%, black 37%);
}

/* horizontal bars preview (top categories) */
.preview-hbars {
  display: flex; flex-direction: column; justify-content: center;
  gap: 7px; padding: 8px 12px; width: 100%; height: 100%;
}
.preview-hbar {
  height: 7px; border-radius: 2px; width: var(--w);
  background: var(--accent); opacity: 0.7;
}

/* budget progress preview */
.preview-progress {
  display: flex; align-items: center; justify-content: center;
  padding: 0 16px; width: 100%; height: 100%;
}
.preview-progress-track {
  height: 6px; border-radius: 3px; background: var(--border);
}
.preview-progress-fill {
  height: 100%; border-radius: 3px; background: var(--accent);
}
.preview-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  gap: 6px;
  padding: 8px 6px;
  text-align: center;
}
.preview-stat-value {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-bright);
  font-family: var(--font-mono);
  white-space: nowrap;
}
.widget-picker-label {
  font-size: var(--text-caption);
  color: var(--text);
  font-family: var(--font-sans);
  margin-top: 7px;
  text-align: center;
}

/* ── Widget picker hover description ──────────────────────────
   Positioned by JS and only ever shown to a mouse (see
   _initWidgetTips). The pointer-events lock matters: the tip sits
   under the cursor's path between cards, and a tip that could take
   a pointerover would fight the card it describes.               */
.widget-tip {
  position: fixed;
  z-index: 300;
  width: 260px;
  max-width: calc(100vw - 20px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 8px 22px var(--shadow-color);
  padding: 9px 11px;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
}

.widget-tip.visible {
  opacity: 1;
  visibility: visible;
}

/* Belt and braces behind the JS capability check: a touch device must never
   see this, even if something else adds the class. */
@media (hover: none), (pointer: coarse) {
  .widget-tip { display: none; }
}

/* ── Stock ticker chip (add widget picker) ────────────────── */
.stock-ticker-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.stock-ticker-chip {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  padding: 4px 10px;
  cursor: pointer;
  letter-spacing: 0.04em;
  transition: border-color 0.15s, color 0.15s;
}
.stock-ticker-chip:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* ── Page-level range bar ─────────────────────────────────── */
.widget-grid [data-widget-type="bar"] { grid-column: 1 / -1; }

.range-bar-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  height: 44px;
  min-width: 0;
}

.range-bar-drag {
  opacity: 0.4;
  font-size: var(--text-sm);
  cursor: grab;
  flex-shrink: 0;
}

.range-bar-label {
  font-size: var(--text-caption);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  flex-shrink: 0;
}

.range-bar-btns {
  display: flex;
  gap: 4px;
  margin-left: auto;
}

.range-bar-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  padding: 3px 10px;
  cursor: pointer;
  transition: border-color 0.1s, color 0.1s;
}

.range-bar-btn:hover {
  border-color: var(--text-dim);
  color: var(--text);
}

.range-bar-btn.active {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.range-bar-select {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  padding: 4px 8px;
  margin-left: auto;
  cursor: pointer;
}

/* Page header range slot */
.page-range-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.page-date-widget {
  display: flex;
  align-items: center;
  gap: 2px;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--muted);
  white-space: nowrap;
}

.page-range-header .range-bar-btns {
  margin-left: 0;
}

.page-range-header .range-bar-select {
  margin-left: 0;
}

.page-range-header:not(:hover) .range-bar-remove,
.range-bar-wrap:not(:hover) .range-bar-remove {
  opacity: 0 !important;
  pointer-events: none;
}

.range-bar-remove {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: var(--text-base);
  line-height: 1;
  padding: 2px 4px;
  margin-left: 6px;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.1s, color 0.1s;
}
.range-bar-remove:hover {
  opacity: 1;
  color: var(--red);
}

/* Hide per-widget range selects when a page range bar is present */
.has-page-range [data-widget="net_worth"] #nwRange,
.has-page-range [data-widget="net_worth_half"] #nwHalfRange,
.has-page-range [data-widget="net_worth_detail"] #nwdRange,
.has-page-range [data-widget="holdings"] #holdingsRangeOv,
.has-page-range [data-widget="holdings_wide"] #holdingsWideRangeOv,
.has-page-range [data-widget="spending"] #spendRangeOv { display: none; }

/* Widget picker preview for bar type */
.widget-preview--bar {
  height: 28px;
  display: flex;
  align-items: center;
  padding: 0 8px;
}

.preview-range-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  justify-content: flex-end;
}

.preview-range-btn {
  font-size: 9px;
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 2px 6px;
}

.preview-range-btn.active {
  border-color: var(--accent);
  color: var(--accent);
}

/* ── Net worth widget (Option A) ─────────────────────────── */
.nw-widget { padding: 24px; position: relative; }

.nw-tick { position: absolute; width: 10px; height: 10px; border: 1px solid var(--accent);
  opacity: 0.55; pointer-events: none; }
.nw-tick.tl { top: -1px; left:  -1px; border-right: 0; border-bottom: 0; }
.nw-tick.tr { top: -1px; right: -1px; border-left:  0; border-bottom: 0; }
.nw-tick.bl { bottom: -1px; left:  -1px; border-right: 0; border-top: 0; }
.nw-tick.br { bottom: -1px; right: -1px; border-left:  0; border-top: 0; }

.nw-head { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 28px; }
.nw-eyebrow { font-size: var(--text-caption); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-dim);
  display: flex; align-items: center; gap: 10px; }
.nw-eyebrow::before { content: ''; width: 6px; height: 6px; background: var(--accent);
  display: inline-block; }

.nw-range { display: flex; gap: 2px; }
.nw-range button { background: transparent; border: 1px solid var(--border);
  color: var(--text-dim); font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.08em; padding: 3px 8px; cursor: pointer; transition: all .15s; }
.nw-range button:hover { color: var(--text); }
.nw-range button.active { border-color: var(--accent); color: var(--accent);
  background: var(--accent-dim); }

.nw-overlay { position: relative; height: 320px; margin-top: 4px; }
.nw-overlay svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.nw-num-float { position: absolute; top: 0; left: 0; pointer-events: none;
  text-shadow: 0 0 24px var(--surface); }
.nw-num-label { font-size: 10px; color: var(--text-dim); letter-spacing: 0.14em;
  text-transform: uppercase; margin-bottom: 6px; }
.nw-num { font-family: var(--font-display); font-size: 56px; font-weight: 500;
  color: var(--text-bright); letter-spacing: -0.02em; line-height: 0.9; }
.nw-num .cents { font-size: 22px; color: var(--text-dim); font-weight: 400; }
.nw-delta { font-family: var(--font-mono); font-size: var(--text-base);
  color: var(--green); margin-top: 10px; letter-spacing: 0.02em; }
.nw-delta.neg { color: var(--red); }
.nw-delta .muted { color: var(--text-dim); margin-left: 6px; }

.nw-overlay .gridline    { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 4; }
.nw-overlay .nw-line     { fill: none; stroke: var(--accent); stroke-width: 1.5; }
.nw-overlay .nw-area     { fill: var(--accent); opacity: 0.08; }
.nw-overlay .nw-dot      { fill: var(--accent); }
.nw-overlay .nw-dot-ring { fill: none; stroke: var(--accent); stroke-width: 1; opacity: 0.4; }
.nw-overlay .nw-cross    { stroke: var(--text-dim); stroke-width: 1; stroke-dasharray: 2 2; opacity: 0.4; }
.nw-overlay .nw-monthlabel { font-family: var(--font-mono); font-size: 9px;
  fill: var(--muted); letter-spacing: 0.08em; text-transform: uppercase; }

[data-widget-type="half"] .nw-overlay      { height: 180px; }
[data-widget-type="half"] .nw-num          { font-size: 36px; }
[data-widget-type="half"] .nw-num .cents   { font-size: 16px; }

/* In widget-grid, nw-widgets stretch to the tallest sibling in the row.
   Allow the chart overlay to grow and fill that extra space. */
.widget-grid .nw-widget {
  display: flex;
  flex-direction: column;
}

.widget-grid [data-widget-type="half"] .nw-overlay {
  flex: 1;
  height: auto;
  min-height: 180px;
}

.widget-grid [data-widget-type="full"] .nw-overlay {
  flex: 1;
  height: auto;
  min-height: 320px;
}

/* On a phone the floating figure spans most of the card's width, so the line
   ran straight through it wherever the series peaked, and the crosshair cut
   through the delta below it. Stack the figure above the chart instead; the
   overlay keeps its height and the SVG takes what's left. Renderers measure
   the SVG, and the spvb tooltips offset by its position, so neither cares. */
@media (max-width: 768px) {
  .nw-overlay { display: flex; flex-direction: column; }
  .nw-overlay .nw-num-float { position: relative; left: 0; margin-bottom: 8px; text-shadow: none; }
  .nw-overlay svg { position: relative; inset: auto; flex: 1; height: auto; min-height: 0; }
  /* Half widgets span the full row here; give the chart room under the figure. */
  .widget-grid [data-widget-type="half"] .nw-overlay { min-height: 240px; }
}

/* ── Spending Overview Widget ─────────────────────────────── */
.spend-ov-card { position: relative; }
.spend-ov-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}
/* Matches .nw-eyebrow: same tracking, gap and 6px square bullet. */
.spend-ov-title {
  font-size: var(--text-caption);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 10px;
}
.spend-ov-accent-dot {
  width: 6px;
  height: 6px;
  background: var(--accent);
  display: inline-block;
  flex-shrink: 0;
}
.spend-ov-gauge-wrap {
  position: relative;
  height: 195px;
}
.spend-ov-svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}
.spend-ov-center {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
  white-space: nowrap;
  padding-bottom: 4px;
}
.spend-ov-center-label {
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.spend-ov-center-val {
  font-family: var(--font-display);
  font-size: 46px;
  color: var(--text-bright);
  line-height: 1;
}
.spend-ov-cents { font-size: 24px; }
.spend-ov-stats {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 12px 0 16px;
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.spend-ov-cat-count { color: var(--muted); }
.spend-ov-list-header {
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.spend-ov-list-header::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.spend-ov-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.spend-ov-row {
  display: grid;
  grid-template-columns: 24px 1fr auto 68px;
  align-items: start;
  gap: 8px;
}
.spend-ov-rank {
  font-size: var(--text-caption);
  color: var(--muted);
  font-family: var(--font-mono);
  padding-top: 2px;
}
.spend-ov-cat-wrap { min-width: 0; }
.spend-ov-cat-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 5px;
}
.spend-ov-swatch {
  width: 9px;
  height: 9px;
  border-radius: 1px;
  flex-shrink: 0;
}
.spend-ov-cat-name {
  font-size: 13px;
  color: var(--text-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spend-ov-bar-track {
  height: 2px;
  background: var(--border);
  border-radius: 1px;
  overflow: hidden;
}
.spend-ov-bar-fill {
  height: 100%;
  border-radius: 1px;
  transition: width 0.6s cubic-bezier(0.25, 1, 0.5, 1);
}
.spend-ov-pct {
  font-size: var(--text-caption);
  color: var(--muted);
  font-family: var(--font-mono);
  padding-top: 2px;
  text-align: right;
}
.spend-ov-amount {
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--text-bright);
  text-align: right;
  line-height: 1.1;
  white-space: nowrap;
}

/* ── Investments Overview Widget ────────────────────────────── */
.inv-ov-card { padding-bottom: 24px; }
.inv-ov-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Holdings widget (investment accent) ────────────────────── */
.hld-widget .nw-tick                    { border-color: var(--color-investment); }
.hld-widget .nw-eyebrow::before         { background: var(--color-investment); }
.hld-widget .nw-range button.active     { border-color: var(--color-investment); color: var(--color-investment); background: color-mix(in srgb, var(--color-investment) 10%, transparent); }
.hld-widget .nw-overlay .nw-line        { stroke: var(--color-investment); }
.hld-widget .nw-overlay .nw-area        { fill: var(--color-investment); }
.hld-widget .nw-overlay .nw-dot         { fill: var(--color-investment); }
.hld-widget .nw-overlay .nw-dot-ring    { stroke: var(--color-investment); }
.hld-widget .nw-delta                   { color: var(--color-investment); }

/* The table/stat investment widgets carry the same investment accent. */
.cb-widget .nw-tick,
.inv-act-widget .nw-tick,
[data-widget="holdings_table"] .nw-tick { border-color: var(--color-investment); }
.cb-widget .nw-eyebrow::before,
.inv-act-widget .nw-eyebrow::before,
[data-widget="holdings_table"] .nw-eyebrow::before { background: var(--color-investment); }
.cb-widget .chart-title select:focus,
.inv-act-widget .chart-title select:focus { border-color: var(--color-investment); }

/* Amounts in the Top Categories list are figures, so mono. */
.category-total-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Category rows that filter the page's transactions table (only rendered as
   links when the page has one; see filterTxnTableByCategory). */
.cat-row { transition: opacity 0.2s ease; }
.cat-row--link {
  cursor: pointer;
  margin-left: -6px; margin-right: -6px;
  padding: 4px 6px;
}
.cat-row--link:hover { background: var(--surface2); }
.cat-row--link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cat-row.is-filter-active { box-shadow: inset 2px 0 0 var(--accent); }
.cat-row.is-filter-active span:first-child { color: var(--text-bright) !important; }
.cat-row.is-filter-dim { opacity: 0.45; }

/* Room above the table when a category click scrolls to it. */
[data-widget="txn_table"] { scroll-margin-top: 16px; }

/* Flashed on the table's category select when a widget click sets it. */
@keyframes txn-filter-flash {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); border-color: var(--accent); }
  100% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent) 0%, transparent); }
}
.txn-filter-flash { animation: txn-filter-flash 0.9s ease-out; }

.hld-acct-select {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0.04em;
  padding: 3px 6px;
  cursor: pointer;
  max-width: 140px;
  margin-right: 10px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%238d8470'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
  padding-right: 20px;
}
.hld-acct-select:focus { outline: none; border-color: var(--color-investment); color: var(--text); }
.hld-acct-select option { background: var(--surface); color: var(--text); }

/* ── Net Worth Detail Widget ─────────────────────────────── */
.nwd-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin-top: 14px;
  padding: 0 2px;
}
.nwd-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  color: var(--text-dim);
  min-width: 0;
  cursor: default;
  transition: opacity 0.12s ease;
}

/* Mirrors the band highlight in the chart, so pointing at either one picks
   the account out in both places. */
.nwd-legend-item.dim { opacity: 0.35; }
.nwd-legend-item.active .nwd-name { color: var(--text-bright); }
.nwd-legend-item.active .nwd-swatch { opacity: 1; }
.nwd-swatch {
  width: 8px;
  height: 8px;
  border-radius: 1px;
  flex-shrink: 0;
  opacity: 0.85;
}
.nwd-name {
  color: var(--text);
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nwd-val {
  color: var(--accent);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.nwd-val.neg { color: var(--red); }

.nwd-zero-label {
  font-family: var(--font-mono);
  font-size: 9px;
  fill: var(--text-dim);
  opacity: 0.6;
  letter-spacing: 0.06em;
}
.nwd-y-label {
  font-family: var(--font-mono);
  font-size: 9px;
  fill: var(--muted);
  letter-spacing: 0.04em;
}

/* Net Worth · Detail carries the same accent treatment and floating readout as
   the spend-vs-budget widget below. */
.nwd-widget .nw-tick            { border-color: var(--accent); }
.nwd-widget .nw-eyebrow::before { background: var(--accent); }
.nwd-widget .nw-delta           { color: var(--accent); }
.nwd-widget .nw-delta.neg       { color: var(--red); }

.nwd-overlay { height: 320px; }
.widget-grid .nwd-widget[data-widget-type="full"] .nw-overlay { min-height: 320px; }

/* Clear of the y-axis labels, which the other nw-widgets do not have. */
.nwd-widget .nw-num-float { left: 54px; }
/* Stacked above the chart on phones (see .nw-overlay above), so no offset. */
@media (max-width: 768px) { .nwd-widget .nw-num-float { left: 0; } }

.nwd-crosshair { stroke: var(--accent); }
.nwd-dot       { fill: var(--accent); }
.nwd-dot-ring  { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0.4; }

.nwd-overlay path[data-nwd-idx] {
  transition: fill-opacity 0.12s ease, stroke-opacity 0.12s ease;
}

/* ── Spend vs Budget Widget ──────────────────────────────── */
.spvb-widget .nw-tick          { border-color: var(--accent); }
.spvb-widget .nw-eyebrow::before { background: var(--accent); }
.spvb-widget .nw-delta         { color: var(--accent); }
.spvb-widget .nw-delta.neg     { color: var(--red); }

.spvb-overlay { height: 320px; }

.widget-grid .spvb-widget[data-widget-type="half"] .nw-overlay,
.widget-grid .spvb-widget[data-widget-type="full"] .nw-overlay {
  min-height: 320px;
}

.spvb-month-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--text-dim);
}

.spvb-area { fill: var(--accent); opacity: 0.12; }
.spvb-line { fill: none; stroke: var(--accent); stroke-width: 2; }
.spvb-dot  { fill: var(--accent); }
.spvb-dot-ring { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0.4; }
.spvb-cross { stroke: var(--accent); stroke-width: 1; opacity: 0.5; }

.spvb-total-line {
  fill: none;
  stroke: var(--bg);
  stroke-width: 1.5;
  opacity: 0.8;
}

.spvb-budget-line {
  stroke: var(--text);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  opacity: 0.85;
  filter: drop-shadow(0 0 3px var(--bg)) drop-shadow(0 0 3px var(--bg));
}
.spvb-budget-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  fill: var(--text);
  letter-spacing: 0.04em;
  filter: drop-shadow(0 0 3px var(--bg)) drop-shadow(0 0 3px var(--bg));
}
.spvb-cat-label {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.02em;
  opacity: 0.85;
}
.spvb-tooltip {
  display: none;
  position: absolute;
  z-index: 20;
  background: var(--bg);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 8px 12px;
  pointer-events: none;
  min-width: 180px;
  max-width: 260px;
  box-shadow: 0 6px 24px var(--shadow-color-soft);
}
.spvb-tip-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border);
}
.spvb-tip-row:last-child { border-bottom: none; }
.spvb-tip-name {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spvb-tip-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
