/* ==========================================================================
   debt-watch — design system
   Sibling of mycra: same spacing scale, same control shapes, same feedback
   rules. No framework, no CDN, no build step. Mobile-first; every layout is
   verified to work at 360px wide.

   --------------------------------------------------------------------------
   UTILITY CLASSES — the contract other pages are written against.
   These names are stable. Add, never rename.
   --------------------------------------------------------------------------
   LAYOUT
     .container            page gutter + max width (already in base.html <main>)
     .pagehead             page title row: h1 on the left, actions on the right
     .section-title        small uppercase muted heading above a block
     .grid                 auto-fit grid, min column 220px
     .grid-2 / .grid-3     explicit 2- / 3-column grid (collapses on phones)

   SURFACES
     .card                 bordered panel, 16px padding, 16px bottom margin
     .card-hd              header strip inside a .card (title + actions)
     .card-bd              flush body inside a .card (use with .card-hd)
     .stat                 stat tile
     .stat-val             stat value  (big number)
     .stat-lbl             stat label  (small uppercase)
     .stat-sub             stat footnote (optional, muted)
     .empty                empty-state block ("no bills yet …")

   TABLES
     .table-wrap           horizontal scroll container — ALWAYS wrap .table
     .table                data table (th/td/tfoot styled)

   BUTTONS
     .btn                  base button / link-button
     .btn-primary          filled accent
     .btn-ghost            transparent, hairline border
     .btn-danger           destructive
     .btn-sm               compact size modifier
     .btn-block            full width modifier
     .btn-link             borderless text button (inline row actions)

   FORMS
     .form-grid            multi-column field grid (auto-fit, min 220px)
     .form-row             one field: label + control (+ .help / .err)
     .span2                modifier: make a .form-row span the full grid width
     label                 block label above a control
     label.inline          checkbox / radio row label
     .input .select .textarea   controls (bare input/select/textarea inside
                           .form-row, .form-grid and .filters are styled too)
     .help                 muted hint under a control
     .err                  red error text under a control
     .form-actions         button row with a hairline above it
     .filters              filter bar (grid of fields + actions), list pages
     .filters-actions      button group inside .filters
     .alert .alert-error .alert-ok   page-level message blocks

   CHIPS + STATUS PILLS (all are self-contained pills; `.chip .chip-auto`
   and a bare `.chip-auto` both render correctly)
     .chip                 neutral pill
     .chip-auto            "auto" — autopay account, never nags
     .chip-card            credit card       (alias: .chip-credit_card)
     .chip-utility         utility           (alias: .chip-subscription)
     .chip-loc             line of credit    (alias: .chip-line_of_credit)
     .chip-loan            loan
     .chip-other           other
     .chip-est             "estimated" flag on a derived balance
     .status-paid          bill fully covered by payments
     .status-partial       some payment recorded
     .status-overdue       past due, still owing
     .status-due-soon      inside DUE_SOON_DAYS
     .status-upcoming      future
     .dot                  10px colour dot (set background inline from Account.Color)

   METER (utilization: green < 30%, amber 30–70%, red > 70%)
     .meter                track
     .meter-fill           fill — set width inline, e.g. style="width:42%"
     .meter-warn           amber modifier (on .meter or on .meter-fill)
     .meter-bad            red modifier   (on .meter or on .meter-fill)
     .meter-lbl            caption line under a meter

   TEXT
     .money                tabular figures, no wrap
     .money-neg            negative / owing amount (red)
     .money-pos            paid-off / credit amount (green)
     .muted                secondary text
     .right                text-align right   (alias: .num, also right-aligns)
     .center               text-align center
     .nowrap               white-space nowrap

   CHARTS (rendered by /charts.js — see that file for the JS API)
     .chart .chart-svg .chart-legend .chart-key .chart-tip .chart-table

   PAGE MODULES (bottom of this file — one page each, no <style> in templates)
     dashboard      .dash .dash-attention .dash-stats .dash-accounts
                    .dash-chart .dash-recent
                    .att-list .att-row .att-main .att-acct .att-meta .att-amt
                    .att-act .att-more (+ .is-overdue modifier on .att-row)
                    .acct-grid .acct-tile .acct-tile-hd .acct-bal .acct-line
                    .acct-next
     bills list     .bills-table .due-sub (+ tr.is-overdue, tr.autopay)
     payments list  .payments-table .amount .sub-line .settles
                    .total-strip .total-val
     both lists     .month-total
     charts page    .chart-controls .ctl .ctl-lbl .seg .chk
                    .series-toggles .series-toggle (.key .nm) .chart-note
                    .chart-card
     payment form   .pay-context .bill-hint
     settings       .set-user .set-about .set-note .set-match (+ .ok / .bad)
   ========================================================================== */

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

/* ---------- design tokens (light) ---------- */
:root {
    color-scheme: light;

    /* surfaces + ink */
    --bg:            #f5f6f8;
    --card:          #ffffff;
    --card-alt:      #fafbfc;
    --border:        #e1e4e8;
    --border-strong: #d0d7de;
    --text:          #1f2328;
    --muted:         #6e7781;

    /* accent + intents */
    --primary:       #0969da;
    --primary-hover: #0858bd;
    --primary-soft:  #ddf4ff;
    --on-primary:    #ffffff;
    --focus-ring:    rgba(9, 105, 218, 0.20);

    --danger:        #cf222e;
    --danger-hover:  #a40e26;
    --on-danger:     #ffffff;
    --success:       #1a7f37;
    --warning:       #9a6700;

    /* tinted pills: fg / bg pairs */
    --neutral-fg: #57606a;  --neutral-bg: #eef1f4;
    --ok-fg:      #116329;  --ok-bg:      #dafbe1;
    --warn-fg:    #7d4e00;  --warn-bg:    #fff8c5;
    --bad-fg:     #a40e26;  --bad-bg:     #ffebe9;
    --info-fg:    #0a4d8c;  --info-bg:    #ddf4ff;
    --aqua-fg:    #0e6b52;  --aqua-bg:    #d7f7ee;
    --violet-fg:  #5b3fbf;  --violet-bg:  #eee7ff;

    /* meter */
    --meter-track: #eaeef2;
    --meter-ok:    #1a7f37;
    --meter-warn:  #bf8700;
    --meter-bad:   #cf222e;

    /* chart chrome */
    --chart-surface: #ffffff;
    --chart-grid:    #e8ebef;
    --chart-axis:    #d0d7de;
    --chart-ink:     #1f2328;
    --chart-muted:   #6e7781;

    /* categorical series palette — validated for CVD separation and for
       contrast against the light chart surface. Fixed order, never cycled;
       past 8 series, fold into "Other". */
    --dw-c1: #2a78d6;  /* blue    */
    --dw-c2: #eb6834;  /* orange  */
    --dw-c3: #1baf7a;  /* aqua    */
    --dw-c4: #eda100;  /* yellow  */
    --dw-c5: #e87ba4;  /* magenta */
    --dw-c6: #008300;  /* green   */
    --dw-c7: #4a3aa7;  /* violet  */
    --dw-c8: #e34948;  /* red     */

    /* shape + motion */
    --radius:    8px;
    --radius-sm: 6px;
    --pill:      999px;
    --shadow:    0 1px 2px rgba(31, 35, 40, 0.06);
    --shadow-lg: 0 8px 28px rgba(31, 35, 40, 0.16);
    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- design tokens (dark) ----------
   Selected for the dark surface, not an automatic flip. The OS setting is
   honoured unless the document explicitly stamps data-theme="light"; an
   explicit data-theme="dark" always wins. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --bg:            #0d1117;
        --card:          #161b22;
        --card-alt:      #1b222b;
        --border:        #2b3440;
        --border-strong: #3d4855;
        --text:          #e6edf3;
        --muted:         #8b949e;

        --primary:       #58a6ff;
        --primary-hover: #79c0ff;
        --primary-soft:  #10243b;
        --on-primary:    #0d1117;
        --focus-ring:    rgba(88, 166, 255, 0.25);

        --danger:        #ff7b72;
        --danger-hover:  #ff9a93;
        --on-danger:     #0d1117;
        --success:       #3fb950;
        --warning:       #d29922;

        --neutral-fg: #9aa4af;  --neutral-bg: #21262d;
        --ok-fg:      #57d364;  --ok-bg:      #10261a;
        --warn-fg:    #e3b341;  --warn-bg:    #2b2413;
        --bad-fg:     #ff8b82;  --bad-bg:     #2d1618;
        --info-fg:    #79c0ff;  --info-bg:    #10243b;
        --aqua-fg:    #56d4b0;  --aqua-bg:    #0f2a24;
        --violet-fg:  #b3a4ff;  --violet-bg:  #1e1a33;

        --meter-track: #21262d;
        --meter-ok:    #3fb950;
        --meter-warn:  #d29922;
        --meter-bad:   #f85149;

        --chart-surface: #161b22;
        --chart-grid:    #232b35;
        --chart-axis:    #313b47;
        --chart-ink:     #e6edf3;
        --chart-muted:   #8b949e;

        --dw-c1: #3987e5;
        --dw-c2: #d95926;
        --dw-c3: #199e70;
        --dw-c4: #c98500;
        --dw-c5: #d55181;
        --dw-c6: #008300;
        --dw-c7: #9085e9;
        --dw-c8: #e66767;

        --shadow:    0 1px 2px rgba(0, 0, 0, 0.4);
        --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.55);
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --bg:            #0d1117;
    --card:          #161b22;
    --card-alt:      #1b222b;
    --border:        #2b3440;
    --border-strong: #3d4855;
    --text:          #e6edf3;
    --muted:         #8b949e;

    --primary:       #58a6ff;
    --primary-hover: #79c0ff;
    --primary-soft:  #10243b;
    --on-primary:    #0d1117;
    --focus-ring:    rgba(88, 166, 255, 0.25);

    --danger:        #ff7b72;
    --danger-hover:  #ff9a93;
    --on-danger:     #0d1117;
    --success:       #3fb950;
    --warning:       #d29922;

    --neutral-fg: #9aa4af;  --neutral-bg: #21262d;
    --ok-fg:      #57d364;  --ok-bg:      #10261a;
    --warn-fg:    #e3b341;  --warn-bg:    #2b2413;
    --bad-fg:     #ff8b82;  --bad-bg:     #2d1618;
    --info-fg:    #79c0ff;  --info-bg:    #10243b;
    --aqua-fg:    #56d4b0;  --aqua-bg:    #0f2a24;
    --violet-fg:  #b3a4ff;  --violet-bg:  #1e1a33;

    --meter-track: #21262d;
    --meter-ok:    #3fb950;
    --meter-warn:  #d29922;
    --meter-bad:   #f85149;

    --chart-surface: #161b22;
    --chart-grid:    #232b35;
    --chart-axis:    #313b47;
    --chart-ink:     #e6edf3;
    --chart-muted:   #8b949e;

    --dw-c1: #3987e5;
    --dw-c2: #d95926;
    --dw-c3: #199e70;
    --dw-c4: #c98500;
    --dw-c5: #d55181;
    --dw-c6: #008300;
    --dw-c7: #9085e9;
    --dw-c8: #e66767;

    --shadow:    0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.55);
}

/* ---------- base ---------- */
html { -webkit-text-size-adjust: 100%; }

body {
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    overflow-wrap: break-word;
}

a { color: var(--primary); }
a:hover { color: var(--primary-hover); }

h1 { font-size: 22px; letter-spacing: -0.02em; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }

hr { border: none; border-top: 1px solid var(--border); margin: 16px 0; }

:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ---------- topbar ---------- */
.topbar {
    background: var(--card);
    border-bottom: 1px solid var(--border);
    padding: 10px 0;
    margin-bottom: 20px;
    padding-top: max(10px, env(safe-area-inset-top));
}
.topbar-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px 20px;
    flex-wrap: wrap;
}
.brand-group { display: flex; align-items: center; gap: 8px; min-width: 0; }
.brand {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.02em;
    text-decoration: none;
    color: var(--text);
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.brand:hover { color: var(--text); }
.brand-mark { width: 20px; height: 20px; display: block; flex: none; }
.version {
    padding: 1px 8px;
    border: 1px solid var(--border);
    border-radius: var(--pill);
    color: var(--muted);
    font-family: var(--mono);
    font-size: 11px;
    line-height: 1.7;
    white-space: nowrap;
}

.topnav {
    display: flex;
    align-items: center;
    gap: 4px 18px;
    flex-wrap: wrap;
}
.topnav a,
.topnav button {
    display: inline-block;
    padding: 4px 0;
    text-decoration: none;
    color: var(--text);
    font-size: 15px;
    font-family: inherit;
    background: none;
    border: none;
    cursor: pointer;
    line-height: 1.5;
}
.topnav a:hover,
.topnav button:hover { color: var(--primary); }
.topnav a.active {
    color: var(--primary);
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--primary);
}
.topnav .nav-muted,
.topnav button { color: var(--muted); }
.logout-form { display: inline; }

/* ---------- page shell ---------- */
.container {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 16px calc(56px + env(safe-area-inset-bottom));
}

.pagehead {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.pagehead h1 { font-size: 22px; }
.pagehead .sub { color: var(--muted); font-size: 13px; margin-top: 2px; }
.pagehead-actions,
.pagehead > div:last-child:not(:first-child) {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.section-title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    margin: 22px 0 10px;
}
.section-title:first-child { margin-top: 0; }

/* ---------- grids ---------- */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
}
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 760px) { .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) {
    .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
    .grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- card ---------- */
.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 16px;
    box-shadow: var(--shadow);
}
.card > :last-child { margin-bottom: 0; }
.card h2 { font-size: 16px; margin-bottom: 12px; }
.card h3 {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    margin: 18px 0 10px;
}

/* .card-hd / .card-bd cancel the card's own padding so a header strip can run
   edge to edge. They also work on a plain padded .card. */
.card-hd {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px 12px;
    flex-wrap: wrap;
    margin: -16px -16px 14px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--card-alt);
    border-radius: var(--radius) var(--radius) 0 0;
}
.card-hd h2, .card-hd h3 { margin: 0; font-size: 15px; text-transform: none; letter-spacing: 0; color: var(--text); }
.card-hd .card-hd-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.card-bd { margin: 0 -16px -16px; padding: 14px 16px; }
.card-bd > :last-child { margin-bottom: 0; }
.card-hd + .card-bd { margin-top: -14px; }
.card-bd + .card-bd { border-top: 1px solid var(--border); }
.card-bd.flush { padding: 0; }

.card-accent { border-left: 3px solid var(--primary); }
.card-danger { border-color: var(--bad-bg); background: var(--bad-bg); }
.card-danger h2, .card-danger h3 { color: var(--bad-fg); }

/* ---------- stat tiles ---------- */
.stat {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    box-shadow: var(--shadow);
    min-width: 0;
}
.stat-lbl {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    margin-bottom: 6px;
}
.stat-val {
    font-size: 24px;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.2;
}
.stat-val.sm { font-size: 18px; }
.stat-val.lg { font-size: 30px; }
.stat-sub { font-size: 12px; color: var(--muted); margin-top: 6px; }
.stat.accent { background: var(--primary-soft); border-color: var(--primary-soft); }
.stat.accent .stat-lbl { color: var(--info-fg); }
.stat.bad .stat-val { color: var(--danger); }
.stat.good .stat-val { color: var(--success); }
.card .stat { box-shadow: none; }

/* ---------- tables ---------- */
.table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}
.card > .table-wrap:only-child,
.card-bd.flush > .table-wrap { margin: 0; }

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.table th,
.table td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.table th {
    font-weight: 700;
    color: var(--muted);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover td { background: var(--card-alt); }
.table tfoot td {
    font-weight: 700;
    border-top: 2px solid var(--border);
    border-bottom: none;
    background: var(--card-alt);
}
.table a { color: var(--primary); text-decoration: none; font-weight: 500; }
.table a:hover { text-decoration: underline; }
.table td.actions { white-space: nowrap; text-align: right; }
.table td.actions form { display: inline; }
.table .row-muted td { color: var(--muted); }

/* mycra-compatible alias */
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th, .data-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.data-table th { font-weight: 700; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tfoot td { font-weight: 700; border-top: 2px solid var(--border); border-bottom: none; background: var(--card-alt); }
.data-table a { color: var(--primary); text-decoration: none; }

/* ---------- buttons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--card);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.btn:hover { background: var(--card-alt); border-color: var(--muted); color: var(--text); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn.disabled { opacity: 0.5; pointer-events: none; }

.btn-primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--on-primary); }

.btn-ghost { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn-ghost:hover { background: var(--card-alt); border-color: var(--muted); }

.btn-danger { background: var(--danger); border-color: var(--danger); color: var(--on-danger); }
.btn-danger:hover { background: var(--danger-hover); border-color: var(--danger-hover); color: var(--on-danger); }

.btn-sm { padding: 5px 10px; font-size: 13px; border-radius: var(--radius-sm); }
.btn-block { width: 100%; }

.btn-link {
    background: none;
    border: none;
    padding: 4px 2px;
    color: var(--primary);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
}
.btn-link:hover { text-decoration: underline; background: none; }
.btn-link.danger { color: var(--danger); }

/* mycra-compatible alias */
.btn-secondary { background: var(--card); border-color: var(--border-strong); color: var(--text); }

/* ---------- forms ---------- */
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px 18px;
}
.form-grid > .span2,
.form-row.span2 { grid-column: 1 / -1; }

.form-row { margin-bottom: 14px; min-width: 0; }
.form-grid > .form-row { margin-bottom: 0; }

label {
    display: block;
    margin-bottom: 5px;
    font-size: 13px;
    font-weight: 600;
    color: var(--muted);
    letter-spacing: 0.01em;
}
label.inline {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    cursor: pointer;
}
label.inline input { width: auto; margin: 0; }
label .req { color: var(--danger); }

.input, .select, .textarea,
.form-row input:not([type="checkbox"]):not([type="radio"]),
.form-row select,
.form-row textarea,
.form-grid input:not([type="checkbox"]):not([type="radio"]),
.form-grid select,
.form-grid textarea,
.filters input:not([type="checkbox"]):not([type="radio"]),
.filters select {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: 15px;
    font-family: inherit;
    line-height: 1.4;
    background: var(--card);
    color: var(--text);
    min-width: 0;
}
.textarea, .form-row textarea, .form-grid textarea { min-height: 80px; resize: vertical; }

.input:focus, .select:focus, .textarea:focus,
.form-row input:focus, .form-row select:focus, .form-row textarea:focus,
.form-grid input:focus, .form-grid select:focus, .form-grid textarea:focus,
.filters input:focus, .filters select:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--focus-ring);
}
input[type="checkbox"], input[type="radio"] { accent-color: var(--primary); width: 16px; height: 16px; }
input[type="color"] { padding: 2px; height: 38px; cursor: pointer; }
::placeholder { color: var(--muted); opacity: 0.8; }

.input.is-error, .form-row.has-error .input,
.form-row.has-error input, .form-row.has-error select { border-color: var(--danger); }

.help { margin-top: 5px; font-size: 12px; color: var(--muted); line-height: 1.45; }
.err  { margin-top: 5px; font-size: 12px; color: var(--danger); font-weight: 500; }

.form-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}
.form-actions .spacer { flex: 1 1 auto; }

/* mycra-compatible alias */
.form-group { margin-bottom: 14px; }
.form-group label { display: block; margin-bottom: 5px; }
.form-group input:not([type="checkbox"]):not([type="radio"]),
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: 15px;
    font-family: inherit;
    background: var(--card);
    color: var(--text);
}

/* ---------- filter bar ---------- */
.filters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px 14px;
    align-items: end;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 16px;
    box-shadow: var(--shadow);
}
.filters .form-row { margin-bottom: 0; }
.filters label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.filters-actions {
    display: flex;
    gap: 8px;
    align-items: end;
    flex-wrap: wrap;
}
.filters-actions .btn { flex: 0 0 auto; }
.filters .span2 { grid-column: 1 / -1; }

/* mycra-compatible aliases */
.filter-bar { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; margin-bottom: 16px; }
.filter-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px 14px; }
.filter-field label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.filter-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* ---------- alerts ---------- */
.alert {
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    margin-bottom: 14px;
    font-size: 14px;
    border: 1px solid transparent;
}
.alert-error { background: var(--bad-bg); color: var(--bad-fg); border-color: var(--bad-bg); }
.alert-ok    { background: var(--ok-bg);  color: var(--ok-fg);  border-color: var(--ok-bg); }
.alert-warn  { background: var(--warn-bg); color: var(--warn-fg); border-color: var(--warn-bg); }
.alert-info  { background: var(--info-bg); color: var(--info-fg); border-color: var(--info-bg); }

/* ---------- empty state ---------- */
.empty {
    padding: 26px 18px;
    text-align: center;
    color: var(--muted);
    font-size: 14px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    background: var(--card-alt);
}
.empty strong { display: block; color: var(--text); font-size: 15px; margin-bottom: 4px; }
.empty a { font-weight: 500; }
.card > .empty { border: none; background: none; padding: 18px 0; }

/* ---------- chips + status pills ---------- */
.chip, .chip-auto, .chip-card, .chip-credit_card, .chip-utility, .chip-subscription,
.chip-loc, .chip-line_of_credit, .chip-loan, .chip-other, .chip-est,
.status-paid, .status-partial, .status-overdue, .status-due-soon, .status-upcoming,
.status-none,
.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    border-radius: var(--pill);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.6;
    white-space: nowrap;
    vertical-align: middle;
    background: var(--neutral-bg);
    color: var(--neutral-fg);
}
.chip-auto        { background: var(--violet-bg); color: var(--violet-fg); }
.chip-card,
.chip-credit_card { background: var(--info-bg);   color: var(--info-fg); }
.chip-loc,
.chip-line_of_credit { background: var(--primary-soft); color: var(--info-fg); }
.chip-loan        { background: var(--warn-bg);   color: var(--warn-fg); }
.chip-utility,
.chip-subscription { background: var(--aqua-bg);  color: var(--aqua-fg); }
.chip-other       { background: var(--neutral-bg); color: var(--neutral-fg); }
.chip-est         { background: transparent; color: var(--muted); border: 1px dashed var(--border-strong); font-weight: 500; }

.status-paid     { background: var(--ok-bg);      color: var(--ok-fg); }
.status-partial  { background: var(--info-bg);    color: var(--info-fg); }
.status-overdue  { background: var(--bad-bg);     color: var(--bad-fg); }
.status-due-soon { background: var(--warn-bg);    color: var(--warn-fg); }
.status-upcoming { background: var(--neutral-bg); color: var(--neutral-fg); }
/* `statusclass ""` — a bill whose status never got derived. Should not happen;
   styled anyway so it degrades to a neutral pill rather than unstyled text. */
.status-none     { background: var(--neutral-bg); color: var(--neutral-fg); }

/* autopay accounts never nag: a due_soon/upcoming row on an autopay account
   reads neutral, the "auto" chip carries the meaning. */
.autopay .status-due-soon { background: var(--neutral-bg); color: var(--neutral-fg); }

.dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex: none;
    background: var(--muted);
    box-shadow: 0 0 0 2px var(--card);
    vertical-align: -1px;
}
.dot-lg { width: 14px; height: 14px; }

.acct-name { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }

/* ---------- meter ---------- */
.meter {
    position: relative;
    height: 8px;
    border-radius: var(--pill);
    background: var(--meter-track);
    overflow: hidden;
    margin: 8px 0 0;
}
.meter-lg { height: 12px; }
.meter-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: var(--pill);
    background: var(--meter-ok);
    transition: width 0.25s ease;
}
.meter-warn .meter-fill, .meter-fill.meter-warn { background: var(--meter-warn); }
.meter-bad  .meter-fill, .meter-fill.meter-bad  { background: var(--meter-bad); }
.meter-lbl {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    margin-top: 6px;
    font-size: 12px;
    color: var(--muted);
}
.meter-lbl .value { font-weight: 600; color: var(--text); }

/* ---------- text utilities ---------- */
.money {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    white-space: nowrap;
}
.money-neg { color: var(--danger); }
.money-pos { color: var(--success); }
.muted     { color: var(--muted); }
.right, .num { text-align: right; }
.num { font-variant-numeric: tabular-nums; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.small  { font-size: 12px; }
.strong { font-weight: 600; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stack { display: flex; flex-direction: column; gap: 4px; }
.row   { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mt0 { margin-top: 0; } .mb0 { margin-bottom: 0; }
.mt8 { margin-top: 8px; } .mb8 { margin-bottom: 8px; }
.mt16 { margin-top: 16px; } .mb16 { margin-bottom: 16px; }
.hidden { display: none !important; }
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0;
    margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- charts (see /charts.js) ---------- */
.chart { position: relative; width: 100%; min-width: 0; }
.chart-svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart-svg text { font-family: var(--font); }

.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    margin-top: 10px;
    font-size: 12px;
    color: var(--muted);
}
.chart-legend-item { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.chart-key { width: 14px; height: 3px; border-radius: 2px; flex: none; background: var(--muted); }
.chart-key.box { width: 11px; height: 11px; border-radius: 3px; }

.chart-tip {
    position: absolute;
    z-index: 30;
    min-width: 120px;
    max-width: 220px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: var(--card);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow-lg);
    font-size: 12px;
    color: var(--text);
    pointer-events: none;
    visibility: hidden;
}
.chart-tip.on { visibility: visible; }
.chart-tip .tip-x { font-weight: 700; margin-bottom: 5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; font-size: 11px; }
.chart-tip .tip-row { display: flex; align-items: center; gap: 7px; margin-top: 3px; }
.chart-tip .tip-name { color: var(--muted); flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chart-tip .tip-val { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

.chart-table { margin-top: 10px; font-size: 12px; }
.chart-table > summary { cursor: pointer; color: var(--muted); font-size: 12px; padding: 4px 0; }
.chart-table > summary:hover { color: var(--primary); }
.chart-table table { width: 100%; border-collapse: collapse; margin-top: 6px; }
.chart-table th, .chart-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); text-align: right; font-variant-numeric: tabular-nums; }
.chart-table th:first-child, .chart-table td:first-child { text-align: left; font-variant-numeric: normal; }
.chart-table th { color: var(--muted); font-weight: 600; white-space: nowrap; }

.chart-empty {
    padding: 30px 16px;
    text-align: center;
    color: var(--muted);
    font-size: 13px;
}

/* ==========================================================================
   PAGE MODULES
   Layout that belongs to exactly one page. It lives here rather than in a
   per-page <style> block so there is ONE stylesheet to cache, one place to
   audit, and one set of tokens in play. Everything below is built from the
   same variables as the components above.
   ========================================================================== */

/* ---------- dashboard ---------- */
/* Attention first on a phone, the stat row first on a desktop. */
.dash { display: flex; flex-direction: column; }
.dash-attention { order: 1; }
.dash-stats     { order: 2; }
.dash-accounts  { order: 3; }
.dash-chart     { order: 4; }
.dash-recent    { order: 5; }
@media (min-width: 721px) {
    .dash-stats     { order: 1; }
    .dash-attention { order: 2; }
}

/* Attention rows are a grid, not a table — a table cannot wrap at 360px. */
.att-list { list-style: none; }
.att-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    row-gap: 8px;
    align-items: center;
    padding: 11px 0;
    border-bottom: 1px solid var(--border);
}
.att-row:first-child { padding-top: 2px; }
.att-row:last-child  { border-bottom: none; padding-bottom: 2px; }
.att-main { min-width: 0; }
.att-acct { display: flex; align-items: center; gap: 7px; min-width: 0; font-weight: 600; }
.att-acct a { text-decoration: none; }
.att-meta { font-size: 12px; color: var(--muted); margin-top: 3px; }
.att-amt { text-align: right; font-weight: 700; white-space: nowrap; }
.att-act { grid-column: 1 / -1; display: flex; gap: 6px; justify-content: flex-end; align-items: center; }
.att-act form { display: inline; }
.att-row.is-overdue .att-meta { color: var(--bad-fg); font-weight: 600; }
.att-more { padding-top: 10px; font-size: 13px; }
@media (min-width: 560px) {
    .att-row { grid-template-columns: minmax(0, 1fr) auto auto; }
    .att-act { grid-column: auto; }
}

/* Account grid: one compact tile per account. */
.acct-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.acct-tile {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 13px 14px;
    display: flex;
    flex-direction: column;
    gap: 7px;
}
.acct-tile-hd { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.acct-tile-hd .acct-name { font-weight: 600; text-decoration: none; }
.acct-bal { font-size: 21px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.acct-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
    color: var(--muted);
}
.acct-line .value { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.acct-next {
    border-top: 1px solid var(--border);
    padding-top: 7px;
    font-size: 12px;
    color: var(--muted);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: wrap;
}
.dash-recent .table td { vertical-align: middle; }

/* ---------- bills list ---------- */
/* Overdue rows stand out — but never on an autopay account, which pays itself
   and only needs a calm "auto" chip. Scoped to this table. */
.bills-table tbody tr.is-overdue td { background: var(--bad-bg); }
.bills-table tbody tr.is-overdue:hover td { background: var(--bad-bg); }
.bills-table tbody tr.is-overdue td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
.bills-table tbody tr.autopay .status-overdue { background: var(--warn-bg); color: var(--warn-fg); }
.bills-table td.actions .btn { margin-left: 4px; }
.bills-table .due-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.bills-table tr.is-overdue .due-sub { color: var(--bad-fg); font-weight: 600; }

/* ---------- payments list ---------- */
/* Money that has left the bank is good news — the amount column leads. */
.payments-table td.amount { font-weight: 700; }
.payments-table td.actions .btn { margin-left: 4px; }
.payments-table .sub-line { font-size: 12px; color: var(--muted); margin-top: 2px; }
.payments-table .settles a { font-weight: 600; }
.total-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 16px;
    align-items: baseline;
    justify-content: space-between;
    font-variant-numeric: tabular-nums;
}
.total-strip .total-val { font-size: 20px; font-weight: 700; }

/* shared by both list pages */
.month-total { font-variant-numeric: tabular-nums; font-size: 13px; }

@media (max-width: 560px) {
    .bills-table td.actions .btn,
    .payments-table td.actions .btn { margin: 2px 0 2px 4px; }
}

/* ---------- charts page ---------- */
.chart-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 18px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
    margin-bottom: 16px;
}
.chart-controls .ctl { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chart-controls .ctl-lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    font-weight: 700;
    white-space: nowrap;
}
.seg { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); overflow: hidden; }
.seg a {
    padding: 6px 12px;
    font-size: 13px;
    line-height: 1.3;
    text-decoration: none;
    color: var(--text);
    background: var(--card);
    border-right: 1px solid var(--border);
}
.seg a:last-child { border-right: none; }
.seg a:hover { background: var(--card-alt); color: var(--text); }
.seg a[aria-pressed="true"] { background: var(--primary); color: var(--on-primary); }
.chk { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; cursor: pointer; }
.chk input { width: 16px; height: 16px; }

.series-toggles { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.series-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: var(--pill);
    border: 1px solid var(--border-strong);
    background: var(--card);
    color: var(--text);
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
}
.series-toggle:hover { background: var(--card-alt); }
.series-toggle .key { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.series-toggle[aria-pressed="false"] { opacity: 0.45; }
.series-toggle[aria-pressed="false"] .nm { text-decoration: line-through; }

.chart-note { font-size: 12px; color: var(--muted); }
.chart-card .card-hd-actions { font-size: 12px; color: var(--muted); }

@media (max-width: 400px) {
    .chart-controls { padding: 10px 12px; }
    .seg a { padding: 6px 10px; font-size: 12px; }
}

/* ---------- payment form ---------- */
.pay-context .stat-val.sm { font-size: 20px; }
.bill-hint { min-height: 0; }

/* ---------- settings ---------- */
.set-user .stat-val { overflow-wrap: anywhere; }
.set-about th { width: 42%; }
.set-about td { font-size: 13px; }
.set-note { margin-top: 12px; }
.set-match.ok  { color: var(--success); font-weight: 500; }
.set-match.bad { color: var(--danger); font-weight: 500; }

/* ---------- login ---------- */
.login-wrap {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 16px;
    background:
        radial-gradient(1000px 500px at 50% -10%, var(--primary-soft), transparent 70%),
        var(--bg);
}
.login-card {
    width: 100%;
    max-width: 380px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 28px 24px;
    box-shadow: var(--shadow-lg);
}
.login-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 4px;
}
.login-brand svg { width: 30px; height: 30px; display: block; }
.login-card h1 { text-align: center; font-size: 25px; }
.login-card .tagline { text-align: center; color: var(--muted); font-size: 13px; margin-bottom: 22px; }
.login-card .form-row { margin-bottom: 14px; }
.login-card .btn { margin-top: 6px; }
.login-foot { text-align: center; margin-top: 18px; font-size: 11px; color: var(--muted); font-family: var(--mono); }

/* ---------- toast (styles live here so they follow the theme) ---------- */
.toast-container {
    position: fixed;
    left: 12px;
    right: 12px;
    top: calc(12px + env(safe-area-inset-top));
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}
@media (min-width: 640px) {
    .toast-container { left: auto; right: 20px; top: 20px; align-items: flex-end; }
}
.toast {
    pointer-events: auto;
    max-width: 420px;
    width: fit-content;
    padding: 11px 16px;
    border-radius: var(--radius);
    color: #fff;
    background: #24292f;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    box-shadow: var(--shadow-lg);
    cursor: pointer;
    animation: toastIn 0.22s ease;
}
.toast-success    { background: linear-gradient(135deg, #1a7f37 0%, #17a34a 100%); }
.toast-error      { background: linear-gradient(135deg, #cf222e 0%, #a40e26 100%); }
.toast-warn       { background: linear-gradient(135deg, #9a6700 0%, #bf8700 100%); }
.toast-info,
.toast-processing { background: linear-gradient(135deg, #0969da 0%, #218bff 100%); }
@keyframes toastIn { from { transform: translateY(-10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .toast { animation: none; }
    .meter-fill { transition: none; }
}

/* ---------- offline page ---------- */
.offline-wrap { max-width: 460px; margin: 48px auto 0; text-align: center; }
.offline-wrap .glyph { font-size: 44px; line-height: 1; margin-bottom: 10px; }

/* ---------- phone ---------- */
@media (max-width: 720px) {
    body { font-size: 16px; }

    .topbar { padding: 8px 0 6px; margin-bottom: 14px; }
    .topbar-inner { padding: 0 12px; gap: 6px 12px; }
    .topnav { width: 100%; gap: 2px 16px; }
    .topnav a, .topnav button { font-size: 16px; padding: 3px 0; }
    .brand { font-size: 19px; }

    .container { padding: 0 12px calc(44px + env(safe-area-inset-bottom)); }

    .pagehead { margin-bottom: 12px; }
    .pagehead h1 { font-size: 24px; }

    .card { padding: 14px; margin-bottom: 14px; }
    .card-hd { margin: -14px -14px 12px; padding: 11px 14px; }
    .card-bd { margin: 0 -14px -14px; padding: 12px 14px; }
    .card-hd + .card-bd { margin-top: -12px; }

    .stat { padding: 12px 14px; }
    .stat-val { font-size: 22px; }
    .stat-val.lg { font-size: 27px; }

    .table { font-size: 15px; }
    .table th, .table td, .data-table th, .data-table td { padding: 9px 8px; }
    .table th, .data-table th { font-size: 11px; }

    .btn { font-size: 15px; padding: 9px 15px; }
    .btn-sm { font-size: 13px; padding: 6px 11px; }
    .form-actions .btn { flex: 1 1 auto; }

    /* ≥16px keeps iOS Safari from auto-zooming the page on focus */
    .input, .select, .textarea,
    .form-row input:not([type="checkbox"]):not([type="radio"]),
    .form-row select, .form-row textarea,
    .form-grid input:not([type="checkbox"]):not([type="radio"]),
    .form-grid select, .form-grid textarea,
    .form-group input:not([type="checkbox"]):not([type="radio"]),
    .form-group select, .form-group textarea,
    .filters input:not([type="checkbox"]):not([type="radio"]),
    .filters select { font-size: 16px; padding: 10px 12px; }

    .filters { padding: 12px 14px; }
    .filters-actions .btn { flex: 1 1 auto; }
}

/* 360px phones: give tables and filters every pixel */
@media (max-width: 400px) {
    .container { padding-left: 10px; padding-right: 10px; }
    .card { padding: 12px; }
    .card-hd { margin: -12px -12px 10px; padding: 10px 12px; }
    .card-bd { margin: 0 -12px -12px; padding: 10px 12px; }
    .card-hd + .card-bd { margin-top: -10px; }
    .filters { grid-template-columns: minmax(0, 1fr); }
    .table th, .table td { padding: 8px 6px; }
    .topnav { gap: 2px 13px; }
    .topnav a, .topnav button { font-size: 15px; }
}

@media print {
    .topbar, .filters, .form-actions, .btn, .toast-container, .chart-tip { display: none !important; }
    body { background: #fff; }
    .card { break-inside: avoid; box-shadow: none; }
}
