/* ── Color palette ─────────────────────────────────────────────────────
   Amber Ember — warm amber base (#C8741A) with charcoal-tinted neutrals.

   Primitives (new):
     --color-brand-50..900      Warm amber scale
     --color-neutral-50..900    Warm-tinted charcoal scale
   Semantic surfaces/text/borders (new):
     --surface-page/-card/-nav/-overlay
     --text-primary/-secondary/-tertiary/-inverse/-brand
     --border-default/-strong/-brand
     --focus-ring

   Legacy aliases (kept for template compatibility and the drift-guard test
   at tests/test_css_variables.py, which enumerates the expected names).
   Every pre-existing --color-* variable continues to resolve to a sensible
   value in the new palette.
   -------------------------------------------------------------------- */
:root {
  /* ── Brand scale (Amber Ember) ─────────────────────────────────────── */
  --color-brand-50:   #FDF4E8;
  --color-brand-100:  #FAE3C1;
  --color-brand-200:  #F4C47D;
  --color-brand-300:  #E8A04A;
  --color-brand-400:  #D98628;
  --color-brand-500:  #C8741A;  /* base */
  --color-brand-600:  #A85D12;
  --color-brand-700:  #84470D;
  --color-brand-800:  #5C3009;
  --color-brand-900:  #341A04;

  /* ── Neutral (warm-tinted charcoal) ────────────────────────────────── */
  --color-neutral-50:  #FAFAF7;
  --color-neutral-100: #F2F0EB;
  --color-neutral-200: #E4E0D8;
  --color-neutral-300: #C8C3B8;
  --color-neutral-400: #A09A8E;
  --color-neutral-500: #716B5F;
  --color-neutral-600: #504B41;
  --color-neutral-700: #34302A;
  --color-neutral-800: #1E1C17;
  --color-neutral-900: #100E0A;

  /* ── Surfaces (light mode) ─────────────────────────────────────────── */
  --surface-page:    #FAFAF7;
  --surface-card:    #FFFFFF;
  --surface-overlay: rgba(30, 28, 23, 0.5);
  --surface-nav:     #1E1C17;

  /* ── Text ──────────────────────────────────────────────────────────── */
  --text-primary:   #1E1C17;
  --text-secondary: #504B41;
  --text-tertiary:  #A09A8E;
  --text-inverse:   #FAFAF7;
  --text-brand:     #A85D12;

  /* ── Borders ───────────────────────────────────────────────────────── */
  --border-default: #E4E0D8;
  --border-strong:  #C8C3B8;
  --border-brand:   #C8741A;

  /* ── Interactive ───────────────────────────────────────────────────── */
  --focus-ring: rgba(200, 116, 26, 0.4);
  --layout-max-width: 1140px;

  /* ── Legacy aliases (literal hex so the drift-guard test matches) ──── */
  /* Brand (was indigo) — primary actions, links, focus rings */
  --color-primary:          #C8741A;  /* = --color-brand-500 */
  --color-primary-hover:    #A85D12;  /* = --color-brand-600 */
  --color-primary-bg:       #FDF4E8;  /* = --color-brand-50  */

  /* Text */
  --color-text:             #1E1C17;  /* = --text-primary    */
  --color-text-muted:       #716B5F;  /* = --color-neutral-500 */
  --color-text-subtle:      #A09A8E;  /* = --color-neutral-400 */
  --color-text-tertiary:    #504B41;  /* = --color-neutral-600 */

  /* Surfaces */
  --color-surface:          #FFFFFF;  /* = --surface-card */
  --color-surface-subtle:   #FAFAF7;  /* = --color-neutral-50  */
  --color-page-bg:          #F2F0EB;  /* = --color-neutral-100 */

  /* Borders */
  --color-border:           #C8C3B8;  /* = --border-strong  */
  --color-border-light:     #E4E0D8;  /* = --border-default */
  --color-border-subtle:    #F2F0EB;  /* = --color-neutral-100 */

  /* Status — Success (earthy green) */
  --color-success:          #2D7D52;
  --color-success-dark:     #1E5538;
  --color-success-bg:       #EBF6F0;
  --color-success-border:   #8EC7A8;
  --color-success-bright:   #3A9D68;

  /* Status — Danger */
  --color-danger:           #C0392B;
  --color-danger-dark:      #8E2116;
  --color-danger-bg:        #FBEAE8;
  --color-danger-border:    #E2837A;
  --color-danger-bright:    #D94A3A;

  /* Status — Warning (= brand amber) */
  --color-warning:          #C8741A;  /* = --color-brand-500 */
  --color-warning-dark:     #84470D;  /* = --color-brand-700 */
  --color-warning-bg:       #FDF4E8;  /* = --color-brand-50  */
  --color-warning-border:   #F4C47D;  /* = --color-brand-200 */
  --color-warning-bright:   #D98628;  /* = --color-brand-400 */
  --color-warning-text:     #A85D12;  /* = --color-brand-600 */

  /* Status — Info (earthy blue) */
  --color-info:             #2471A3;
  --color-info-bg:          #EAF2F8;
  --color-info-border:      #93BDE0;

  /* Accent — violet (split/batch badges — kept distinct from brand amber) */
  --color-violet:           #5b21b6;
  --color-violet-bg:        #ede9fe;

  /* Nav (dark charcoal) */
  --color-nav-bg:           #1E1C17;  /* = --surface-nav */
  --color-nav-text:         #A09A8E;  /* = --color-neutral-400 */
  --color-nav-text-active:  #E8A04A;  /* = --color-brand-300   */
  --color-nav-input-bg:     #34302A;  /* = --color-neutral-700 */
  --color-nav-input-border: #504B41;  /* = --color-neutral-600 */
  --color-nav-input-focus:  #D98628;  /* = --color-brand-400   */
}

/* ── Dark-mode tokens (defined, dormant — no toggle yet) ───────────────────
   These only activate when <html data-theme="dark"> is set explicitly.
   We intentionally do NOT use @media (prefers-color-scheme: dark) here so
   the app stays in light mode regardless of OS preference until a toggle
   is added. */
[data-theme="dark"] {
  --surface-page:    #100E0A;
  --surface-card:    #1E1C17;
  --surface-overlay: rgba(10, 9, 6, 0.7);
  --surface-nav:     #100E0A;

  --text-primary:   #F2F0EB;
  --text-secondary: #A09A8E;
  --text-tertiary:  #504B41;
  --text-inverse:   #1E1C17;
  --text-brand:     #E8A04A;

  --border-default: #34302A;
  --border-strong:  #504B41;

  --focus-ring: rgba(200, 116, 26, 0.5);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Preserve native hidden-attribute semantics.
   The shared `.notice { display:flex; }` rule can otherwise override the
   browser default `[hidden] { display:none; }`, causing hidden banners to
   render as empty boxes on first paint. */
[hidden] { display: none !important; }

body {
  font-family: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  color: var(--color-text);
  background: var(--color-page-bg);
  line-height: 1.5;
  min-height: 100vh;
}

[data-ui-mode="mobile"] {
  --layout-max-width: 760px;
}

/* ── Nav — two-row primary/secondary layout ───────────────────────────────
   Row 1 (.nav-primary, darker neutral-900): Budget wordmark + main
     workflow links (Import, Categorize, Dashboard, Charts) + utility
     group (Mobile app, Sign out) anchored right via margin-left: auto.
   Row 2 (.nav-secondary, lighter neutral-800): supporting pages
     (Adjustments, Transactions, Accounts, Categories).
   Mobile utility actions are moved to a footer action strip so nav rows
     remain compact in phone layouts.
   Active page: amber-tinted chip + brighter text. Inactive: neutral-400.
   Both rows use flex-wrap so narrow viewports produce a natural
   two-then-three-row stack without overflow or horizontal scroll.
   ─────────────────────────────────────────────────────────────────────── */
nav {
  background:
    radial-gradient(circle at 44px 30px, rgba(200, 116, 26, 0.22), transparent 48%),
    var(--color-neutral-900);
  font-family: inherit;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.04);
}
.nav-primary,
.nav-secondary {
  display: flex;
  flex-wrap: wrap;           /* intentional — permits two-row mobile layout */
  align-items: center;
  gap: 0;
  padding: 0 16px;
}
.nav-primary {
  background: var(--color-neutral-900);
  border-bottom: 1px solid var(--color-neutral-700);
}
.nav-secondary {
  background: var(--color-neutral-800);
  border-bottom: 1px solid var(--color-neutral-700);
}

/* Row link base — child combinator keeps utility-group anchors out. */
.nav-primary > a,
.nav-secondary > a {
  display: inline-block;
  padding: 10px 14px;
  font-size: 14px;
  letter-spacing: -0.01em;
  white-space: nowrap;
  text-decoration: none;
  color: var(--color-neutral-400);
  font-weight: 400;
  border-radius: 999px;
  border: 1px solid transparent;
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}
.nav-primary > a:hover,
.nav-secondary > a:hover {
  color: var(--color-brand-300);
  background: rgba(200, 116, 26, 0.09);
}
.nav-primary > a.active,
.nav-secondary > a.active {
  color: #FDE4C2;
  font-weight: 600;
  background: linear-gradient(180deg, rgba(200, 116, 26, 0.24), rgba(200, 116, 26, 0.10));
  border-color: rgba(232, 160, 74, 0.42);
}

/* Wordmark — title in rounded amber chip, with accent color on "Ledge". */
.nav-primary .brand {
  padding: 0;
  margin-right: 16px;
  border: none;
  background: transparent;
}
.nav-primary .brand:hover {
  background: transparent;
  border-color: transparent;
}
.nav-primary .brand-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(200, 116, 26, 0.14);
  box-shadow: inset 0 0 0 1px rgba(232, 160, 74, 0.30);
}
.nav-primary .brand-main,
.nav-primary .brand-accent {
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.03em;
  line-height: 1;
}
.nav-primary .brand-main {
  color: #FFFFFF;
}
.nav-primary .brand-accent {
  color: var(--color-brand-300);
}
.nav-primary .brand {
  margin-right: 20px;
}

/* Utility group — right-aligned via margin-left: auto. Desktop shows
   the row-1 copy; mobile swaps to the row-2 copy (see media block). */
.nav-util {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
}
.nav-util--row2 { display: none; }

.nav-util .signout-btn {
  background: none;
  border: 1px solid var(--color-neutral-700);
  padding: 4px 12px;
  border-radius: 6px;
  font-size: 12px;
  color: var(--color-neutral-400);
  cursor: pointer;
  text-decoration: none;
}
.nav-util .signout-btn:hover {
  color: var(--color-brand-300);
  border-color: var(--color-brand-500);
}
.nav-util .mobile-app-link {
  font-size: 13px;
  color: var(--color-neutral-400);
  text-decoration: none;
}
.nav-util .mobile-app-link:hover { color: var(--color-brand-300); }
.nav-util .mobile-app-link--legacy {
  font-size: 12px;
  opacity: 0.78;
}
.nav-util .mobile-app-link--legacy:hover {
  opacity: 1;
}
.ui-mode-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 4px 12px;
  border: 1px solid var(--color-neutral-700);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.02);
  color: var(--color-neutral-300);
  font-size: 12px;
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}
.ui-mode-toggle:hover {
  color: var(--color-brand-300);
  border-color: var(--color-brand-500);
  background: rgba(200, 116, 26, 0.08);
}
.ui-mode-toggle:focus-visible {
  outline: 2px solid var(--color-brand-400);
  outline-offset: 2px;
}

/* Mobile — tighter padding, utility group moves to Row 2 */
@media (max-width: 640px) {
  .nav-primary,
  .nav-secondary { padding: 0 12px; }
  .nav-primary > a,
  .nav-secondary > a {
    padding: 8px 9px;
    font-size: 12px;
  }
  .nav-primary .brand {
    margin-right: 6px;
  }
  .nav-primary .brand-main,
  .nav-primary .brand-accent {
    font-size: 16px;
  }
  .nav-util--row1 { display: none; }
}

/* Flash messages wrapper — individual flashes render the shared .notice
   primitive (see "Notice primitive" section below). The old .flash /
   .flash-success / .flash-error / .flash-info rules were removed when
   base.html migrated to .notice-*. Fixed: ux_review/11b_major.md #10. */
.flash-wrap { max-width: var(--layout-max-width); margin: 0 auto; padding: 12px 24px 0; }

/* Skip-nav — visually hidden until focused; lets keyboard users jump past
   the nav bar directly to #main-content. Fixed: ux_review/11b_minor.md #5. */
.skip-nav {
  position: absolute;
  top: -999px;
  left: 0;
  padding: 8px 16px;
  background: var(--color-primary);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  border-radius: 0 0 4px 0;
  text-decoration: none;
  z-index: 9999;
}
.skip-nav:focus {
  top: 0;
}

/* Flash banner dismiss — pins the shared .notice-close button to the top-right
   corner. Parent .notice.is-banner has position:relative to anchor it.
   Fixed: ux_review/11b_minor.md #4. */
.notice.is-banner .notice-close {
  position: absolute;
  top: 6px;
  right: 8px;
  flex: none;
  font-size: 18px;
  padding: 0 4px;
}

/* Layout */
main { max-width: var(--layout-max-width); margin: 0 auto; padding: 32px 24px 64px; }
h1 { font-size: 20px; font-weight: 700; margin-bottom: 24px; color: var(--color-text); }
h2 { font-size: 16px; font-weight: 600; margin-bottom: 14px; color: var(--color-text); }

/* Shell-level mobile mode - shared layout only.
   Page-specific mobile variants still belong in the individual templates.
   This mode:
     - tightens the shell width
     - keeps nav utilities visible without relying on viewport-only media rules
     - stacks shared form rows and enables horizontal table scrolling
*/
[data-ui-mode="mobile"] nav {
  position: sticky;
  top: 0;
  z-index: 40;
}
[data-ui-mode="mobile"] .nav-primary,
[data-ui-mode="mobile"] .nav-secondary {
  padding-left: 12px;
  padding-right: 12px;
}
[data-ui-mode="mobile"] .nav-primary > a,
[data-ui-mode="mobile"] .nav-secondary > a {
  padding: 8px 9px;
  font-size: 12px;
}
[data-ui-mode="mobile"] .nav-primary .brand {
  margin-right: 6px;
}
[data-ui-mode="mobile"] .nav-primary .brand-main,
[data-ui-mode="mobile"] .nav-primary .brand-accent {
  font-size: 16px;
}
[data-ui-mode="mobile"] .nav-util {
  display: none;
}
[data-ui-mode="mobile"] .flash-wrap {
  padding: 10px 14px 0;
}
[data-ui-mode="mobile"] main {
  padding: 18px 14px 44px;
}
[data-ui-mode="mobile"] .form-row {
  flex-direction: column;
  align-items: stretch;
}
[data-ui-mode="mobile"] .form-group,
[data-ui-mode="mobile"] .form-group.grow {
  min-width: 100%;
}
[data-ui-mode="mobile"] .table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
[data-ui-mode="mobile"] .btn,
[data-ui-mode="mobile"] .btn-secondary,
[data-ui-mode="mobile"] .btn-primary {
  min-height: 44px;
}

/* Mobile-only footer utility strip.
   Business logic: keep "Sign out" and "Legacy React app" available without
   forcing a third nav row in compact/mobile layouts. */
.mobile-footer-actions {
  display: none;
}
[data-ui-mode="mobile"] .mobile-footer-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: var(--layout-max-width);
  margin: 0 auto 18px;
  padding: 0 14px;
}
@media (max-width: 640px) {
  .mobile-footer-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    max-width: var(--layout-max-width);
    margin: 0 auto 18px;
    padding: 0 14px;
  }
}

.mobile-footer-actions .ui-mode-toggle,
.mobile-footer-actions .signout-btn,
.mobile-footer-actions .mobile-app-link {
  min-height: 36px;
}

.mobile-footer-actions .signout-btn,
.mobile-footer-actions .mobile-app-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 10px;
  border-radius: 999px;
  text-decoration: none;
  font-size: 12px;
  border: 1px solid var(--color-neutral-700);
  color: var(--color-neutral-400);
}

/* Cards */
.card {
  background: var(--color-surface);
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.07), 0 1px 2px rgba(0, 0, 0, 0.07);
  padding: 24px;
  margin-bottom: 24px;
}
.card-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  margin-bottom: 16px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-border-light);
}
/* Compact field-level note — sits below a form input to explain a subtle behaviour.
   Kept at 11px / muted so it doesn't compete with the label or the input itself.
   Fixed: ux_review/11b_major.md #43 (YTD impact on allotment changes). */
.field-note {
  font-size: 11px;
  color: var(--color-text-subtle);
  margin-top: 4px;
  margin-bottom: 0;
  line-height: 1.4;
}

/* Optional one-line explainer that sits directly under .card-title.
   Pulls up against the title's bottom margin so the pair reads as a
   single header block. Fixed: ux_review/11b_major.md #31. */
.card-subtitle {
  font-size: 13px;
  line-height: 1.45;
  color: var(--color-text-muted);
  margin-top: -8px;
  margin-bottom: 16px;
}

/* Tables */
.table-wrap {
  background: var(--color-surface);
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.07);
  overflow: hidden;
  margin-bottom: 24px;
}
table { width: 100%; border-collapse: collapse; }
th {
  background: var(--color-surface-subtle);
  color: var(--color-text-muted);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 10px 16px;
  text-align: left;
  border-bottom: 1px solid var(--color-border-light);
}
td {
  padding: 11px 16px;
  border-bottom: 1px solid var(--color-border-subtle);
  vertical-align: middle;
  color: var(--color-nav-input-bg);
}
tr:last-child td { border-bottom: none; }
tbody tr.data-row:nth-child(even) td { background: var(--color-surface-subtle); }
tbody tr.data-row:hover td { background: var(--color-brand-50); }
.row-inactive td { color: var(--color-text-subtle); }

/* Badges */
.badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; }
.badge-active   { background: var(--color-success-bg); color: var(--color-success-dark); }
.badge-inactive { background: var(--color-border-subtle); color: var(--color-text-muted); }

/* Forms */
.form-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.form-group { display: flex; flex-direction: column; gap: 4px; min-width: 130px; }
.form-group.grow { flex: 1; min-width: 180px; }
label {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
input[type="text"], select {
  padding: 7px 10px;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  font-size: 13px;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  outline: none;
}
input[type="text"]:focus, select:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(99,102,241,0.12);
}
input[type="file"] { font-size: 13px; color: var(--color-nav-input-bg); }
.checkbox-row { display: flex; align-items: center; gap: 6px; padding-bottom: 2px; }
.checkbox-row input[type="checkbox"] { width: 14px; height: 14px; cursor: pointer; }
.checkbox-row label {
  font-size: 13px; text-transform: none; letter-spacing: 0;
  color: var(--color-nav-input-bg); cursor: pointer; font-weight: 400;
}

/* Buttons */
.btn {
  display: inline-block;
  padding: 7px 16px;
  border-radius: 5px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  border: none;
  text-decoration: none;
  white-space: nowrap;
}
.btn-primary { background: var(--color-primary); color: var(--color-surface); }
.btn-primary:hover { background: var(--color-primary-hover); }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-secondary { background: var(--color-surface-subtle); color: var(--color-text-tertiary); border: 1px solid var(--color-border); }
.btn-secondary:hover { background: var(--color-border-subtle); }
.btn-link {
  background: none; border: none; color: var(--color-primary); font-size: 12px;
  padding: 0; cursor: pointer; font-family: inherit;
  text-decoration: underline; text-underline-offset: 2px;
}
.btn-link:hover { color: var(--color-primary-hover); }
.btn:focus-visible, .btn-link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Inline edit row */
.edit-row td { padding: 0; border-bottom: 1px solid var(--color-border-light); }
.edit-panel { padding: 16px 20px; background: var(--color-surface-subtle); }

/* ── Category type-ahead combobox ─────────────────────────────────────
   Shared by /transactions (edit + add panels), /categorize, and
   /adjustments. Previously three separate copies in each template with
   drift (see ux_review/11b_major.md #9). ARIA roles come from the JS
   builders (`initCatCombo` in app.js and `buildEpCategoryCombo` /
   static add-panel HTML in transactions.html); see #6.
   Settled on the 13px / 7px 10px sizing from transactions.html to match
   the rest of the form inputs defined above.
   ------------------------------------------------------------------ */
.cat-group { display: flex; gap: 6px; align-items: center; }
.cat-combo-wrap { position: relative; flex: 1; }
.cat-input {
  width: 100%; box-sizing: border-box; padding: 7px 10px;
  border: 1px solid var(--color-border); border-radius: 5px; font-size: 13px;
  font-family: inherit; color: var(--color-text); background: var(--color-surface); outline: none;
}
.cat-input:focus { border-color: var(--color-primary); box-shadow: 0 0 0 2px rgba(99,102,241,0.12); }
.cat-input.has-suggestion { border-color: var(--color-primary); background: var(--color-primary-bg); }
.cat-dropdown {
  display: none; position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 300;
  background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 5px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.1); max-height: 260px; overflow-y: auto;
}
.cat-opt { padding: 6px 10px; font-size: 13px; cursor: pointer; color: var(--color-text); white-space: nowrap; }
.cat-opt:hover, .cat-opt.active, .cat-opt[aria-selected="true"] { background: var(--color-primary-bg); color: var(--color-primary-hover); }
/* The hidden native <select> backing the combobox on pages that progressively
   enhance a server-rendered <select> (categorize, adjustments). */
.cat-select { flex: 1; padding: 7px 10px; border: 1px solid var(--color-border); border-radius: 5px; font-size: 13px; font-family: inherit; color: var(--color-text); background: var(--color-surface); outline: none; }
.cat-select:focus { border-color: var(--color-primary); box-shadow: 0 0 0 2px rgba(99,102,241,0.12); }
.cat-select.has-suggestion { border-color: var(--color-primary); background: var(--color-primary-bg); }

/* Import result grid */
.result-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 4px; }
.result-item { text-align: center; padding: 20px 16px; background: var(--color-surface-subtle); border-radius: 6px; border: 1px solid var(--color-border-light); }
.result-item .num { font-size: 32px; font-weight: 700; line-height: 1; }
.result-item .num.parsed   { color: var(--color-primary); }
.result-item .num.inserted { color: var(--color-success); }
.result-item .num.skipped  { color: var(--color-warning); }
.result-item .lbl { font-size: 12px; color: var(--color-text-muted); margin-top: 6px; }

/* Misc */
.text-muted { color: var(--color-text-subtle); font-size: 12px; }
.mono { font-family: "Cascadia Code", "Fira Code", "Consolas", monospace; font-size: 12px; }
.mt-16 { margin-top: 16px; }
.mb-0  { margin-bottom: 0; }

/* Visually hides element while keeping it accessible to screen readers */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}
/* Fixed: ux_review/11b_minor.md #6 #10 — moved from charts.html */

/* ───────────────────────────────────────────────────────────────────────
   Responsive rules — keep pages usable down to ~375px (iPhone SE portrait).
   Two breakpoints matching charts.html's existing style:
     · 900px — tablet / narrow desktop: stack multi-column grids, allow nav
               to wrap onto a second row, make wide tables horizontally
               scrollable inside their card wrapper (.table-wrap).
     · 600px — phone: nav gets compact, drawers go full-width (per-template),
               form rows stack vertically, font sizes shrink.
   Fixed: ux_review/11b_critical.md item #2 (zero @media queries).
─────────────────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  main { padding: 20px 16px 48px; }
  h1 { font-size: 18px; margin-bottom: 16px; }
  h2 { font-size: 15px; }

  /* Nav handles its own responsive sizing inside the nav block above
     (row-level flex-wrap + a dedicated ≤640px breakpoint). Nothing to
     override here. */

  .card { padding: 16px; }

  /* Key responsive fix — wide tables scroll horizontally inside their
     wrapper instead of forcing the whole page to scroll */
  .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media (max-width: 600px) {
  main { padding: 14px 10px 40px; }
  .flash-wrap { padding: 8px 12px 0; }

  /* Nav sizing for narrow viewports lives in the nav block's own
     @media (max-width: 640px) rule above — don't duplicate it here. */

  /* Form rows collapse to single-column stacks */
  .form-group { min-width: 100%; }

  /* Slightly tighter tables — users can still horizontal-scroll via
     .table-wrap rule above */
  th, td { padding: 7px 10px; font-size: 12px; }
  th { font-size: 10px; }

  /* Import page result tiles: 3-col grid is too tight on phones */
  .result-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

/* ── Empty-state component ───────────────────────────────────────────
   Shared zero-data messaging across dashboard / import / charts /
   adjustments. Replaces inline italic "No X" divs that provided no
   guidance. Each usage pairs the shared visual shell with contextual
   copy and a CTA (or a pointer to forms above on the same page).
   Fixed: ux_review/11b_major.md #7.
────────────────────────────────────────────────────────────────── */
.empty-state {
  padding: 32px 20px;
  text-align: center;
  color: var(--color-text-muted);
}
.empty-state-icon {
  font-size: 32px;
  line-height: 1;
  margin-bottom: 10px;
  opacity: 0.55;
}
.empty-state-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 6px;
}
.empty-state-body {
  font-size: 13px;
  line-height: 1.5;
  color: var(--color-text-muted);
  max-width: 420px;
  margin: 0 auto 14px;
}
.empty-state-actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}
/* Compact variant for drill-down / inline panels (chart panels, the
   off-budget collapsible, adjustments history). */
.empty-state.is-compact { padding: 20px 16px; }
.empty-state.is-compact .empty-state-icon { font-size: 22px; margin-bottom: 6px; }
.empty-state.is-compact .empty-state-title { font-size: 13px; }
.empty-state.is-compact .empty-state-body  { font-size: 12px; margin-bottom: 10px; }

/* ── Notice primitive ────────────────────────────────────────────────
   Shared visual shell for server flash, XHR toasts, inline-panel
   feedback, and chart-panel error states. Seven delivery mechanisms
   used to render four palettes in four positions with three hardcoded
   hex literals (#dc2626 / #16a34a / #fff) — now all share one token-
   driven look. Semantic variant carries the colour; positioning
   modifier carries the layout. Keeps behavioural differences
   (persistent banner vs. auto-dismiss toast vs. inline panel) while
   collapsing the visual drift. Fixed: ux_review/11b_major.md #10. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 13px;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-surface-subtle);
  margin-bottom: 8px;
}
.notice-icon { flex: 0 0 auto; font-size: 14px; line-height: 1.4; }
.notice-body { flex: 1 1 auto; }
.notice-body a { color: inherit; text-decoration: underline; font-weight: 600; }
.notice-close {
  flex: 0 0 auto;
  background: none; border: 0; padding: 2px 6px;
  font-size: 16px; line-height: 1;
  color: inherit; opacity: 0.55; cursor: pointer;
  font-family: inherit;
}
.notice-close:hover { opacity: 1; }

/* Semantic variants — colours delegate to the tokens introduced in #3. */
.notice-success { background: var(--color-success-bg); color: var(--color-success-dark); border-color: var(--color-success-border); }
.notice-error   { background: var(--color-danger-bg);  color: var(--color-danger-dark);  border-color: var(--color-danger-border); }
.notice-warning { background: var(--color-warning-bg); color: var(--color-warning-dark); border-color: var(--color-warning-border); }
.notice-info    { background: var(--color-info-bg);    color: var(--color-info);         border-color: var(--color-info-border); }

/* Positioning modifiers — three presentations, one look.
   is-banner   : default, flows inline in page (Flask flash, inline panel notices)
   is-toast    : fixed top-of-viewport banner  (showError — dismissible, 8 s timeout)
   is-toast-br : fixed bottom-right            (showToast — undo actions, 5 s timeout)
   is-inline   : compact variant for tight panels (transactions side-panel, chart error) */
.notice.is-banner { margin-bottom: 8px; position: relative; }
.notice.is-toast  {
  position: fixed; z-index: 1000;
  top: 16px; left: 50%; transform: translateX(-50%);
  min-width: 280px; max-width: 560px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18);
  margin: 0;
}
.notice.is-toast-br {
  position: fixed; z-index: 1000;
  right: 24px; bottom: 24px;
  min-width: 280px; max-width: 420px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18);
  margin: 0;
}
.notice.is-inline {
  padding: 7px 10px;
  font-size: 12px;
  margin-bottom: 6px;
}

/* Undo-toast visibility animation — scoped to the single element that
   showToast() owns. Previously lived inline in categorize.html; moved
   here so the toast looks identical on every page (dashboard also
   calls showToast via restoreOffBudget). Pairs with `.notice.is-toast-br`
   which handles the positioning. Fixed: ux_review/11b_major.md #10. */
#undo-toast {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s, transform 0.2s;
  pointer-events: none;
}
#undo-toast.toast-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.toast-undo {
  background: none;
  border: 1px solid currentColor;
  color: inherit;
  padding: 3px 10px; border-radius: 4px;
  font-size: 12px; cursor: pointer; font-family: inherit;
  opacity: 0.85;
}
.toast-undo:hover { opacity: 1; background: rgba(0,0,0,0.05); }

/* ── Touch-target sizing ────────────────────────────────────────────
   `@media (pointer: coarse)` matches any device whose primary pointer
   is imprecise (finger, stylus), regardless of viewport width. That's
   the right axis for tap-target enforcement: a 320 px desktop window
   resized by a developer should still show compact density, but an
   800 px tablet/phone must give every interactive element ≥44 CSS px.
   Chose 44 px (WCAG 2.5.5 AAA + iOS HIG) rather than Material's 48 dp
   because it keeps the density closer to the pre-change desktop feel
   when the same device is briefly in a hybrid mode.
   Placed last so source-order beats the earlier width-scoped overrides
   (e.g. the 600 px nav-shrink above) when a single device matches both.
   Fixed: ux_review/11b_major.md #5.
────────────────────────────────────────────────────────────────── */
@media (pointer: coarse) {
  /* Nav: each link + Sign out / Mobile app become a ≥44 px hit. The
     base.html markup inline-styles padding on the 📱/Sign out anchors
     but doesn't set min-height or display — our declarations win. */
  nav a {
    min-height: 44px;
    display: flex;
    align-items: center;
    padding: 8px 12px;
    font-size: 13px;
  }
  nav .brand { min-height: 44px; }

  /* Small buttons (month-nav arrows, bulk-apply, etc.) — 32 instances
     across 10 templates all share this class. */
  .btn-sm {
    min-height: 44px;
    padding: 10px 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* btn-link stays inline (it's underlined text, not a button surface),
     but its tap zone needs to be generous. */
  .btn-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    padding: 4px 2px;
  }

  /* Checkbox rows: whole row becomes tap-zone via flex centering; the
     checkbox itself scales to 20 px (smallest size still native-rendered
     consistently across Chrome/Safari/Firefox). */
  .checkbox-row { min-height: 44px; }
  .checkbox-row input[type="checkbox"] { width: 20px; height: 20px; }
  .checkbox-row label { padding: 10px 0; font-size: 14px; }

  /* Split-row remove buttons — three separate implementations with the
     same 14/30 px desktop footprint. One shared override gets them all
     to 44×44. Text stays centred via inline-flex. */
  .remove-split-btn,
  .ap-split-row .ap-split-remove,
  .ep-split-row .ep-split-remove {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
}
