/* Home Accounting App - mobile-first stylesheet.
   One file, no build step or preprocessor -- plain CSS with custom
   properties (below) for the palette, so a theme change only touches the
   :root block. Organized top to bottom roughly in the order a page renders:
   variables, reset, page shell, typography, then components (cards, forms,
   buttons, rows, nav) grouped near where they're first needed, with the
   most page-specific blocks (account cards, drag-to-reorder) at the end. */

/* ---- Theme variables ---- */
:root {
    --bg: #f2f5f5;
    --card: #ffffff;
    --text: #1f2430;
    --muted: #5b6b6a;
    --primary: #0f6f66;
    --primary-dark: #0b544d;
    --danger: #c1462f;
    --warn: #c68a2e;
    --border: #c5d2d0;      /* card/input outlines */
    --divider: #9fb3b0;     /* row separators - needs more contrast than card borders */
    --radius: 10px;
}

/* ---- Reset + page shell ---- */
* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding-bottom: 72px; /* room for bottom nav */
}

.topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 16px;
    background: var(--primary);
    color: white;
    position: sticky;
    top: 0;
    z-index: 10;
}
.app-name { font-weight: 600; font-size: 1.05rem; }
.logout-link { color: white; text-decoration: none; font-size: 0.85rem; opacity: 0.9; }
.topbar-right { display: flex; align-items: center; gap: 14px; }
/* Quick "add expense" shortcut -- deliberately icon-only (a plain "+") to
   fit next to "Log out" in the top bar even on narrow phone screens, rather
   than a labeled button that would force a wrap. */
.quick-add-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: white;
    text-decoration: none;
    font-size: 1.2rem;
    line-height: 1;
    font-weight: 600;
}

.content {
    padding: 16px;
    max-width: 640px;
    margin: 0 auto;
}
.content.content-wide {
    max-width: 1400px;
}

/* ---- Typography ---- */
h1 { font-size: 1.3rem; margin: 0 0 12px; }
h2 { font-size: 1.05rem; margin: 20px 0 8px; }
h3 { font-size: 0.95rem; margin: 0 0 6px; color: var(--muted); }

/* Standalone section heading (not inside a .card-title-bar) that still
   needs to read as a strong section break -- e.g. index.php's "Budget vs
   actual" title, which otherwise looked no more prominent than a plain h2
   despite kicking off a whole page section. Sized between h1 and the
   default h2, colored to match the teal used by every other section header
   in the app (.card-title-bar h2/h3 below). */
.section-title { font-size: 1.2rem; color: var(--primary-dark); text-align: center; }

/* Plain divider between page sections that aren't each wrapped in their own
   .card -- e.g. between the Savings goals card and the Budget vs actual
   section on index.php. Browsers' default <hr> renders as a chunky inset
   groove that clashes with this app's flat design, so it's reset to a
   single thin line matching the row-divider color used elsewhere. */
.section-divider { border: none; border-top: 1px solid var(--divider); margin: 16px 0 4px; }

/* "Total spent vs budget" card (index.php) -- same light-teal tint as
   .card-title-bar so the grand total reads as a highlighted summary rather
   than blending in with the group cards below it. Compound selector
   (.card.total-budget-card, not just .total-budget-card) so its background
   reliably beats the plain .card rule's white background regardless of
   which one happens to come later in this file -- two single-class
   selectors of equal specificity would otherwise let source order decide,
   which is what silently kept this looking white before. Font size is
   bumped above .balance-item's normal 0.92rem too, so the total reads as a
   headline number rather than just another row. Targets the bare <strong>
   tags (label + amount) rather than a new class on each, but loses to
   .amt.neg's higher specificity when over budget, so the red over-budget
   color still wins. */
.card.total-budget-card { background: #e2f0ee; border-color: var(--primary); margin-top: 24px; margin-bottom: 24px; }
.total-budget-card strong { color: var(--primary-dark); }
.total-budget-card .balance-item { font-size: 1.1rem; }

/* ---- Card component (the app's primary content container) ---- */
.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px;
    margin-bottom: 12px;
}

/* Title band that bleeds to the card's edges, for a stronger header. */
.card-title-bar {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    background: #e2f0ee;
    margin: -14px -14px 12px -14px;
    padding: 10px 14px;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: 1px solid var(--border);
}
.card-title-bar h2, .card-title-bar h3 {
    margin: 0;
    color: var(--primary-dark);
    font-weight: 700;
}
.card-title-bar .cat-nums { color: var(--primary-dark); font-weight: 600; }

/* Collapsible variant -- a <details><summary class="card-title-bar"> in
   place of the usual <div>, for cards that are reference info you'll check
   once rather than something you need visible on every visit (e.g.
   planning.php's "Subscribe to a live calendar"). Closed by default (plain
   HTML <details> behavior, no JS needed); the chevron is a CSS pseudo-element
   so no extra markup is needed in the page either. Attached to the h2 (not
   the summary itself) so it sits right after the title text as part of the
   same flex item, instead of being pushed to the far right by the title
   bar's justify-content: space-between. */
summary.card-title-bar {
    cursor: pointer;
    user-select: none;
    list-style: none; /* suppresses the native disclosure marker in Firefox/Safari */
}
summary.card-title-bar::-webkit-details-marker { display: none; } /* same, for Chrome/Safari */
summary.card-title-bar h2::after {
    content: '▸';
    display: inline-block;
    margin-left: 10px;
    color: var(--primary-dark);
    font-size: 1.3rem;
    line-height: 1;
    vertical-align: -2px;
}
details[open] > summary.card-title-bar h2::after {
    content: '▾';
}

/* "Action" variant -- solid color instead of the light tint, for cards that
   want input rather than just showing you something (e.g. planning.php's
   "Add planned expense"). The solid fill is the visual cue that this card
   works differently from the read-only ones around it. */
.card-title-bar.action { background: var(--primary); border-bottom-color: var(--primary-dark); }
.card-title-bar.action h2, .card-title-bar.action h3 { color: #fff; }
.card-title-bar.action .cat-nums { color: #fff; }
/* Collapsible + action combined (e.g. "+ Add planned expense"): the chevron
   above defaults to --primary-dark, which is invisible against this variant's
   solid --primary background -- override it to white here. */
summary.card-title-bar.action h2::after { color: #fff; }

/* Caution variant for the Debts card -- a muted warm tint on the header
   only (not the full card border) so it reads as "different" from the
   teal cards without shouting. Deliberately softer than --danger, which is
   reserved for actual over-budget/negative-balance warnings elsewhere. */
.card-title-bar.danger {
    background: #f3e6e2;
    border-bottom-color: #ddbcb2;
}
.card-title-bar.danger h2, .card-title-bar.danger h3 { color: #9c5140; }
.card-title-bar.danger .cat-nums { color: #9c5140; }

/* Positive-toned variant for the Savings goals card -- same idea as .danger
   above (a tinted title band makes the card read as "different" from the
   plain teal ones at a glance), but warm gold instead of warm red: progress
   toward a goal is something to feel good about, not be warned about. */
.card-title-bar.savings {
    background: #fbf0d6;
    border-bottom-color: #e8cb84;
}
.card-title-bar.savings h2, .card-title-bar.savings h3 { color: #8a6414; }
.card-title-bar.savings .cat-nums { color: #8a6414; }

/* ---- Overdue planned-expense flags (dashboard: next to the category or
   account a planned expense belongs to -- see getOverduePlannedExpenses()
   in functions.php and index.php's renderOverdueFlags()). Started out
   deliberately small/discreet (the opposite of the banner this replaced),
   but that made it too easy to miss next to a category name -- sized up and
   bolded so it actually reads as a warning at a glance. ---- */
.overdue-flag { display: inline-flex; align-items: center; gap: 2px; margin-left: 4px; }
.overdue-triangle {
    color: var(--danger);
    font-size: 1.15em;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
}
.overdue-dismiss {
    width: auto;
    background: none;
    border: none;
    color: var(--muted);
    font-size: 1.1em;
    font-weight: 700;
    line-height: 1;
    padding: 0 2px;
    margin: 0;
    cursor: pointer;
}
.overdue-dismiss:hover { color: var(--danger); background: none; }

/* ---- Simple label/value rows (account balances, planned expense list, etc.) ---- */
.balance-item {
    display: flex;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid var(--divider);
    font-size: 0.92rem;
}
.balance-item:last-child { border-bottom: none; }
.balance-item .amt { font-weight: 600; }
.amt.neg { color: var(--danger); }

/* ---- Budget progress rows (dashboard budget-vs-actual, debt/savings cards) ---- */
.budget-row { margin-bottom: 12px; }
.budget-row .labels {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    margin-bottom: 4px;
}
.budget-row .labels .cat-name { color: var(--text); }
/* Category name itself turns bold red when it has an overdue flag next to
   it -- the ⚠ alone (even sized up, see .overdue-triangle above) was still
   easy to miss at a glance, so the name carries the warning too now. Full
   selector chain (not just .cat-name.cat-name-overdue) so this reliably
   beats the plain .cat-name color rule regardless of source order. */
.budget-row .labels .cat-name.cat-name-overdue { color: var(--danger); font-weight: 700; }
/* Same overdue row, but only the [planned/unpaid] bracket inside the
   numbers turns red -- that's the actual problem amount (the overdue bill
   itself), so it's the one part worth flagging. The rest of the line
   (already spent / budget) stays its normal muted color rather than going
   red wholesale, which diluted which number was actually the issue. */
.budget-row .labels .cat-nums-overdue .cat-planned { color: var(--danger); }
/* Groups the category name with its overdue flag (if any) into one flex
   item -- .labels is itself a flex row with justify-content:space-between,
   so without this wrapper the name, the flag, and .cat-nums were three
   separate flex children and space-between spread all three evenly across
   the row, stranding the flag out near the middle instead of right next to
   the name it belongs to. */
.cat-name-wrap { display: inline-flex; align-items: center; }
.budget-row .labels .cat-nums { color: var(--muted); }
.bar-track {
    background: var(--border);
    border-radius: 6px;
    height: 8px;
    overflow: hidden;
    display: flex;
}
.bar-fill { height: 100%; background: var(--primary); } /* .good uses this base color as-is, only .over overrides it */
.bar-fill.over { background: var(--danger); }
.bar-fill.savings { background: #c99b2e; } /* matches the gold Savings goals card-title-bar */
/* Planned-but-not-yet-paid portion of a category's budget bar (dashboard's
   Budget vs actual) -- same colors as the "actual" segments (.good/.over)
   but faded, so a known upcoming bill reads as "reserved, not spent yet"
   rather than being mistaken for money already gone. */
.bar-fill.planned { background: var(--primary); opacity: 0.35; }
.bar-fill.planned-over { background: var(--danger); opacity: 0.35; }
/* Income categories (Clinic sales, etc.) get inverted bar semantics vs.
   expense categories -- for an expense, filled-and-still-green means "on
   track"; for income, the equivalent state is "haven't hit the target yet",
   which should read as neutral/muted rather than the same reassuring green.
   Once actual >= budget (target reached or exceeded), the fill switches to
   the plain .bar-fill green -- no separate class needed for that state. */
.bar-fill.income-under { background: var(--muted); }
/* Same "more is better" logic for category_type='savings' rows (a recurring
   monthly savings allocation like "80 EUR/month into ETF", distinct from
   the goal-tracked Savings goals card up top) -- muted while under this
   month's target, gold (matching .bar-fill.savings used by the tracked
   goals) once it's been set aside. */
.bar-fill.savings-under { background: var(--muted); }
.cat-planned { color: var(--muted); font-style: italic; }
/* Secondary "this month's pace toward the goal" line on a Debts/Savings
   goals row -- only rendered when the category also has a monthly_budget
   set (see getTrackerMonthlyProgress() in functions.php). Nested inside the
   same .budget-row as the main checkpoint bar so it inherits .labels'
   flex layout and .cat-nums' muted color for free; the dashed top border
   plus thin bar are what visually subordinate it to the main goal bar
   above rather than competing with it. */
.tracker-monthly { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--border); }
.bar-track.thin { height: 5px; }

/* ---- Forms + buttons (every page's add/edit forms share these base styles) ---- */
form { display: flex; flex-direction: column; gap: 10px; }
label { font-size: 0.85rem; color: var(--muted); margin-bottom: 2px; }
input, select, textarea, button {
    font-size: 1rem;
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid var(--border);
    width: 100%;
    font-family: inherit;
}
button {
    background: var(--primary);
    color: white;
    border: none;
    font-weight: 600;
    cursor: pointer;
    margin-top: 4px;
}
button:hover { background: var(--primary-dark); }
button.secondary { background: var(--muted); }
button.danger { background: var(--danger); }
/* Export CSV button (transactions.php quick-links row) -- deliberately a
   different color from the gray quick-filter buttons next to it (This
   month/Last 3 months/etc.), since it does something different (downloads a
   file) rather than just changing what's shown on screen. */
button.export-btn { background: #2f6fa8; }
button.export-btn:hover { background: #24567f; }

/* ---- Tables (not heavily used -- most tabular data uses .tx-row / .balance-item instead) ---- */
table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
th, td { text-align: left; padding: 8px 6px; border-bottom: 1px solid var(--divider); }
th { color: var(--muted); font-weight: 600; font-size: 0.8rem; border-bottom: 2px solid var(--divider); }

/* ---- Transaction list rows (transactions.php, planning.php "Upcoming") ---- */
.tx-list .tx-row {
    display: flex;
    justify-content: space-between;
    padding: 10px 0;
    border-bottom: 1px solid var(--divider);
}
.tx-reconcilable-list .tx-row { align-items: center; } /* vertically centers .amt-actions (a single-line group) against the 2-line info block beside it -- scoped to transactions.php only, not planning.php's Upcoming list, which shares .tx-row but not this layout */
/* min-width: 0 lets the info block (note/date/account text) actually shrink
   and wrap on narrow phones instead of fighting .amt-actions for width --
   without it, flexbox's default min-width:auto was letting a long note
   squeeze the amount+actions column narrower than "5.00 €" needs, which is
   what was wrapping amounts onto two lines. flex-shrink: 0 on .amt-actions
   is the other half of the fix: the amount/kebab column now holds its
   natural width no matter what, and the info block absorbs the squeeze via
   its own normal text wrapping instead. */
.tx-reconcilable-list .tx-row > div:first-child { min-width: 0; flex: 1 1 auto; }
.tx-row .meta { font-size: 0.8rem; color: var(--muted); }
.tx-row .amt.income { color: var(--primary); }
.tx-row .amt.expense { color: var(--danger); }
.tx-row .amt.transfer { color: var(--warn); }
.tx-row a { font-size: 0.78rem; color: var(--muted); margin-left: 8px; }
/* Round icon-button base, shared by the reconcile/edit/delete trio in
   .tx-actions below (transactions.php's per-transaction row). Kept generic
   (no color baked in beyond the neutral default) so the same base works for
   a plain letter ("R") or an emoji glyph -- emoji ignore the CSS `color`
   property anyway, only the circle/border around them responds to it. */
.row-icon-btn {
    width: 30px;
    height: 30px;
    padding: 0;
    margin: 0;
    border-radius: 50%;
    border: 1.5px solid var(--border);
    background: var(--bg);
    color: var(--muted);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.row-icon-btn:hover { border-color: var(--muted); }
/* Reconciliation toggle specifically -- grey/outlined = not yet checked
   against the bank, filled in the primary color = reconciled. Class toggled
   via JS after each AJAX response (see footer.php). The row's own status is
   now shown by the left-edge stripe below instead of a whole-row fade. */
.reconcile-toggle.is-reconciled {
    background: var(--primary);
    border-color: var(--primary);
    color: white;
}
/* Status stripe -- a colored left edge on every transaction row, gray by
   default and primary-green once reconciled (is-reconciled-row, the same
   class the reconcile-toggle click handler already sets -- no extra JS
   needed). Deliberately just a color, no text label: quick to scan down a
   whole list. Scoped to .tx-reconcilable-list (transactions.php only) since
   planning.php's Upcoming list shares .tx-row-wrap but has no reconcile
   concept at all. */
.tx-reconcilable-list .tx-row-wrap {
    border-left: 3px solid var(--border);
    padding-left: 10px;
}
.tx-reconcilable-list .tx-row-wrap.is-reconciled-row { border-left-color: var(--primary); }

/* Amount block on top, reconcile/edit/delete underneath -- .amt-actions is a
   right-aligned column (not a row) so the amount always gets its own full
   line rather than sharing width with three icon buttons. That squeeze was
   actually what caused a long amount like "100.00 €" to wrap onto two lines
   -- .tx-row's align-items: center (above) is what vertically centers this
   whole 2-line column against the 2-line info block beside it. */
.amt-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: 0 0 auto; }
.amt-line { display: flex; align-items: center; gap: 8px; }
.tx-row .amt { white-space: nowrap; } /* never break "5.00 €" across two lines, no matter how tight the row gets */
.tx-kebab { display: none; } /* shown only under the 600px breakpoint below */
/* Row of action icons (reconcile / edit / delete), sitting under the amount.
   flex-wrap + details[open] going full-width means the edit form still drops
   onto its own line and expands to full width once opened, even though the
   trio otherwise sits compactly at the right edge. */
.tx-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.tx-actions form { display: contents; } /* delete's <form> is just a CSRF/id carrier -- its button should sit as a normal flex item, not get its own box */
/* .tx-row-wrap .tx-actions (not just .tx-actions) so this beats the shared
   ".tx-row-wrap details { margin-top: 6px }" rule below on specificity
   rather than source order -- otherwise the Edit icon would sit 6px lower
   than its R/delete neighbors in the row. */
.tx-row-wrap .tx-actions details { margin-top: 0; }
.tx-actions details[open] { flex: 1 1 100%; }
/* Below 600px (the app's existing phone breakpoint, see the bottom-nav rules
   further down) the three icons collapse behind a "..." next to the amount
   instead of always showing under it -- tapping the kebab reveals the same
   .tx-actions block (not a duplicate) via .kebab-open on the row wrapper. */
@media (max-width: 599px) {
    .tx-actions { display: none; }
    .tx-kebab { display: inline-flex; }
    .tx-row-wrap.kebab-open .tx-actions { display: flex; margin-top: 2px; }
}

/* ---- Expandable "mark paid" row (planning.php Upcoming list) --
   a .tx-row plus a collapsed <details> form for confirming the actual
   paid date/amount, so the row doesn't need a separate edit page. This
   summary styling (text link, right-aligned) is also still what
   planning.php's own "Mark paid"/"Edit" links use -- transactions.php's
   icon-styled Edit summary overrides it below via a higher-specificity
   rule rather than changing this shared one. ---- */
.tx-row-wrap { border-bottom: 1px solid var(--divider); padding: 10px 0; }
.tx-row-wrap:last-child { border-bottom: none; }
.tx-row-wrap .tx-row { border-bottom: none; padding: 0; }
.tx-row-wrap details { margin-top: 6px; }
.tx-row-wrap details summary {
    cursor: pointer;
    color: var(--primary);
    font-weight: 600;
    font-size: 0.82rem;
    list-style: none;
    text-align: right;
}
.tx-row-wrap details summary::-webkit-details-marker { display: none; }
.tx-row-wrap details[open] summary { margin-bottom: 8px; }
/* Overrides the shared summary styling just above, for transactions.php's
   icon-only Edit trigger specifically (planning.php's text-link summaries
   are untouched since they don't carry this class). */
.tx-row-wrap details summary.row-icon-btn {
    color: var(--muted);
    font-size: 0.95rem;
    text-align: center;
}
.tx-row-wrap details form {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px;
}
.tx-row-wrap details .field { flex: 1 1 130px; display: flex; flex-direction: column; gap: 2px; }
.tx-row-wrap details label { margin: 0; }
.tx-row-wrap details input { margin: 0; }
.tx-row-wrap details button { flex: 0 0 auto; width: auto; margin: 0; }

/* ---- Split-line rows (add_sale_aymeric.php 5-way split, add_income_nastia.php 3-way allocation) ---- */
.split-line {
    display: flex;
    justify-content: space-between;
    padding: 6px 0;
    font-size: 0.9rem;
    border-bottom: 1px dashed var(--border);
}
.split-line:last-child { border-bottom: none; font-weight: 700; }

/* ---- Status messages + filters ---- */
.error { color: var(--danger); font-size: 0.9rem; }
.success {
    color: var(--primary-dark);
    background: #e2f0ee;
    border: 1px solid var(--primary);
    border-radius: 8px;
    padding: 8px 12px;
    font-size: 0.88rem;
    font-weight: 600;
}
.hint { color: var(--muted); font-size: 0.8rem; margin-top: -4px; }
/* Nested field groups inside a tracker's conditional section (debt/savings
   fields on categories.php and the dashboard's quick-edit modal) -- these
   sit inside a plain <div>, not the <form> itself, so they don't inherit
   the form's own `gap: 10px` rhythm between label/input pairs and don't
   get one of their own by default (a bare div's children just stack with
   0 gap). Without this the two label+input pairs plus the hint below them
   end up crammed together, the hint's own -4px margin-top making it worse.
   Reapplying the same flex+gap pattern here keeps the spacing consistent
   with the rest of the form instead of introducing a cramped-looking
   exception. */
.tracker-fields { display: flex; flex-direction: column; gap: 10px; }
.tracker-fields .hint { margin-top: 0; }
/* flex-direction: row is explicit on purpose -- .filter-bar is applied to a
   <form>, and the generic `form { flex-direction: column }` rule below
   would otherwise win (it's the only rule setting that property, so the
   cascade uses it regardless of .filter-bar's higher selector specificity
   on the properties it DOES set). Without this, every field stacks full
   width/full height instead of sitting in a row -- exactly what happened
   to transactions.php's filter bar once it grew past 2 fields. */
.filter-bar { display: flex; flex-direction: row; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.filter-bar select { width: auto; flex: 1; min-width: 120px; }
.filter-bar input[type="text"],
.filter-bar input[type="date"],
.filter-bar input[type="month"] { width: auto; }

/* ---- Month navigation (dashboard) ---- */
.month-nav {
    display: flex;
    align-items: stretch;
    gap: 8px;
    margin-bottom: 16px;
}
.month-nav form { flex: 1; margin: 0; }
.month-nav input[type="month"] { width: 100%; margin: 0; }
.month-nav .nav-btn {
    flex: 0 0 auto;
    width: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--muted);
    color: white;
    border-radius: 8px;
    text-decoration: none;
    font-size: 1.1rem;
}
.month-nav .nav-btn.today-btn {
    width: auto;
    padding: 0 14px;
    font-size: 0.85rem;
    font-weight: 600;
    background: var(--primary);
}

/* ---- Bottom tab bar (fixed, every logged-in page -- see includes/footer.php) ---- */
.bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: white;
    border-top: 1px solid var(--border);
    display: flex;
    z-index: 10;
}
.bottom-nav a {
    flex: 1;
    text-align: center;
    padding: 8px 2px;
    text-decoration: none;
    color: var(--muted);
    font-size: 0.65rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
.bottom-nav a .icon { font-size: 1.1rem; }
.bottom-nav a.active { color: var(--primary); font-weight: 600; }
/* Slight divider before Trends -- it's the newest/least core destination,
   tacked on at the end rather than folded into the original flow. */
.bottom-nav a.nav-separated { border-left: 1px solid var(--border); margin-left: 2px; }

/* ---- Login screen (login.php -- the only unauthenticated page besides the public token endpoints) ---- */
.login-body {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    background: var(--primary);
}
.login-box {
    background: white;
    padding: 28px 24px;
    border-radius: var(--radius);
    width: 90%;
    max-width: 340px;
    text-align: center;
}
.login-box h1 { font-size: 1.2rem; margin-bottom: 16px; }

/* ---- Small responsive tweak: slightly larger bottom-nav labels once there's room ---- */
@media (min-width: 600px) {
    .bottom-nav a { font-size: 0.72rem; }
}

/* Trends is hidden from the bottom bar on phones (it was the tab that made
   the bar feel cramped) -- still reachable there via the hamburger menu,
   which always lists every destination regardless of screen size. On wider
   screens there's room for it, so it stays in the bottom bar too. */
@media (max-width: 599px) {
    .bottom-nav a.nav-separated { display: none; }
}

/* ---- Account cards grid (accounts.php) ---- */
.account-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 16px;
}
.account-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 18px;
    box-shadow: 0 1px 3px rgba(20, 25, 35, 0.06);
    display: flex;
    flex-direction: column;
}
.account-card .acc-name {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 0 0 6px;
}
.account-card .acc-meta {
    display: flex;
    justify-content: space-between;
    font-size: 0.82rem;
    color: var(--muted);
    padding: 4px 0;
    border-bottom: 1px solid var(--divider);
}
.account-card .acc-meta:last-of-type { border-bottom: none; }
.account-card .acc-balance {
    font-size: 1.4rem;
    font-weight: 700;
    margin: 12px 0 10px;
}
.account-card .acc-balance.neg { color: var(--danger); }
.account-card .owner-tag {
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--muted);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 2px 9px;
    margin-bottom: 8px;
    width: fit-content;
}

/* Accounts page heading + owner filter, side by side (was three full-size
   buttons stacked below the title -- shrunk down to match the same pill
   look as .owner-tag above, so the filter reads as "which of these tags"
   rather than a separate, heavier control). */
.page-title-row { display: flex; justify-content: flex-start; align-items: center; flex-wrap: wrap; gap: 14px; margin-bottom: 12px; }
.page-title-row h1 { margin: 0; }
.owner-filter-group { display: flex; gap: 6px; flex-wrap: wrap; }
.owner-filter-btn {
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--muted);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 4px 12px;
    text-decoration: none;
    cursor: pointer;
}
.owner-filter-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.account-card details summary {
    cursor: pointer;
    color: var(--primary);
    font-weight: 600;
    font-size: 0.88rem;
    list-style: none;
    margin-top: auto;
    padding-top: 8px;
}
.account-card details summary::-webkit-details-marker { display: none; }
.account-card details[open] summary { margin-bottom: 10px; }
.account-card details form { margin-top: 4px; }

.account-card.add-card {
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--border);
    box-shadow: none;
    min-height: 180px;
    text-align: center;
}
.account-card.add-card > details { width: 100%; }
.account-card.add-card > details > summary {
    color: var(--muted);
    font-size: 0.95rem;
    text-align: center;
    padding-top: 0;
}
.account-card.add-card .plus {
    display: block;
    font-size: 2rem;
    line-height: 1;
    color: var(--primary);
    margin-bottom: 6px;
}
.account-card.add-card details[open] summary { display: none; }

/* ---- Income/sale entry cards (add_sale_aymeric.php "Recent sales",
   add_income_nastia.php "Recent income entries") -- each card logs one
   income event: the amount landing in a receiving account, plus an optional
   split into transfer legs. These styles separate that structure visually:
   a title band for the date/amount (mirrors .card-title-bar), a highlighted
   "received into" line for the income leg, and a distinctly bordered/tinted
   block for the transfer split, so the three pieces don't blur into one
   wall of text. ---- */
.entry-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 10px;
    background: #e2f0ee;
    margin: -14px -14px 12px -14px;
    padding: 10px 14px;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: 1px solid var(--border);
}
.entry-header .entry-date { font-weight: 700; color: var(--primary-dark); font-size: 0.95rem; display: block; }
.entry-header .entry-note { font-weight: 400; color: var(--muted); font-size: 0.78rem; display: block; margin-top: 2px; }
.entry-header .entry-amt { font-weight: 700; color: var(--primary-dark); font-size: 1.1rem; white-space: nowrap; }

.income-leg-row {
    display: flex;
    align-items: center;
    gap: 8px;
    background: #eef7f5;
    border: 1px solid var(--primary);
    border-radius: 8px;
    padding: 7px 12px;
    font-size: 0.85rem;
    margin-bottom: 10px;
}
.income-leg-row .leg-icon { color: var(--primary); font-weight: 700; }

.transfer-block {
    border-left: 3px solid var(--warn);
    background: #fbf3e6;
    border-radius: 0 8px 8px 0;
    padding: 2px 12px;
    margin-bottom: 10px;
}
.transfer-block-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #9c7318;
    font-weight: 700;
    padding: 7px 0 2px;
}
.transfer-block .split-line { border-bottom: 1px dashed #e3cd9c; }
.transfer-block .split-line:last-child { border-bottom: none; }
.transfer-block .split-line .to-acct { font-weight: 600; }

.no-split-note {
    font-size: 0.82rem;
    color: var(--muted);
    background: var(--bg);
    border: 1px dashed var(--border);
    border-radius: 8px;
    padding: 7px 12px;
    margin-bottom: 10px;
}

.entry-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-top: 4px;
    padding-top: 10px;
    border-top: 1px solid var(--divider);
}
.entry-actions details { flex: 1; margin: 0; }
.entry-actions > form { flex: 0 0 auto; margin: 0; }
.edit-toggle {
    cursor: pointer;
    color: var(--primary);
    font-weight: 600;
    font-size: 0.85rem;
    list-style: none;
}
.edit-toggle::-webkit-details-marker { display: none; }
.remove-link {
    color: var(--danger);
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.reconcile-block {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--divider);
}
.reconcile-block h4 {
    margin: 0 0 8px;
    font-size: 0.75rem;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* ---- Share/allocation slots in the add + edit split forms
   (add_sale_aymeric.php, add_income_nastia.php) -- each share gets its own
   bordered box instead of a flat stack of labels, so its amount and
   destination account read as one unit and each account is visually
   distinct from its neighbors. ---- */
.share-slot {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--bg);
}
.share-slot-label { font-weight: 600; font-size: 0.85rem; color: var(--primary-dark); margin-bottom: 6px; }
.share-slot-fields { display: flex; gap: 10px; flex-wrap: wrap; }
.share-slot-fields > div { flex: 1 1 120px; display: flex; flex-direction: column; gap: 2px; }
.share-slot-fields label { margin: 0; }

/* ---- Attachment badge + preview modal (transactions.php) -- clicking a
   📎 badge opens this in-page overlay instead of a new tab: straight to the
   preview if there's one attachment, or a pick-a-file list first if there
   are several. Everything stays on the same page/tab. ---- */
.attach-badge {
    color: var(--muted);
    text-decoration: none;
    cursor: pointer;
}
.attach-badge:hover { color: var(--primary); text-decoration: underline; }

.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(15, 20, 30, 0.65);
    z-index: 100;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.modal-overlay.open { display: flex; }
.modal-box {
    background: var(--card);
    border-radius: var(--radius);
    max-width: 520px;
    width: 100%;
    max-height: 88vh;
    overflow-y: auto;
    padding: 18px 16px 16px;
    position: relative;
}
.modal-close {
    position: absolute;
    top: 6px;
    right: 8px;
    background: none;
    border: none;
    font-size: 1.6rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    width: auto;
    padding: 4px 8px;
    margin: 0;
}
.modal-close:hover { color: var(--text); background: none; }
.modal-list-item {
    display: block;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: 8px;
    text-decoration: none;
    color: var(--text);
    font-size: 0.9rem;
}
.modal-list-item:hover { background: var(--bg); }
.modal-preview-img {
    max-width: 100%;
    max-height: 70vh;
    display: block;
    margin: 0 auto;
    border-radius: 6px;
}
.modal-preview-pdf {
    width: 100%;
    height: 70vh;
    border: 1px solid var(--border);
    border-radius: 6px;
}
.modal-preview-caption {
    text-align: center;
    font-size: 0.8rem;
    color: var(--muted);
    margin-top: 8px;
}

/* ---- Spending trends (trends.php) -- one combined multi-category chart per
   panel, built/rescaled entirely client-side (see the inline <script> on
   that page); these classes are just the static shell + checkbox picker. ---- */
.trend-graph-panel { margin-bottom: 16px; }
/* The chart itself gets its own tinted, bordered box distinct from the
   category/group picker below it -- same "boxed-off section within a card"
   idea as .card-title-bar, just without bleeding to the card's edges since
   this one isn't a header. */
.trend-chart-box {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 10px 4px;
}
.trend-chart { width: 100%; height: 220px; display: block; }
.trend-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    font-size: 0.78rem;
    color: var(--text);
    margin: 8px 0 4px;
    min-height: 1.2em;
}
.legend-item { display: inline-flex; align-items: center; gap: 5px; }
.legend-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}
.trend-budget-toggle-label {
    border-top: 1px solid var(--border);
    padding-top: 8px;
    margin-top: 2px;
}
/* Picker section sits below the chart box, with its own heading so the two
   areas read as clearly separate parts of the same card. */
.trend-picker { margin-top: 14px; }
.trend-picker-heading {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--muted);
    margin: 0 0 6px;
}
.trend-picker-group summary {
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--muted);
    padding: 6px 0;
}
.trend-cat-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.88rem;
    color: var(--text);
    padding: 6px 4px 6px 14px;
    cursor: pointer;
}
.trend-cat-label input[type="checkbox"] { width: auto; flex-shrink: 0; }
.trend-group-label { font-weight: 600; border-bottom: 1px solid var(--divider); margin-bottom: 2px; }

/* ---- Top-bar hamburger + slide-down nav menu -- a backup way to reach
   every destination if the bottom tab bar is ever covered (e.g. the
   on-screen keyboard while a text field is focused). Same overlay/.open
   toggle convention as the attachment preview modal above, but anchored to
   the top as a dropdown panel rather than a centered dialog. ---- */
.topbar-left { display: flex; align-items: center; gap: 10px; }
.hamburger-btn {
    background: none;
    border: none;
    color: white;
    font-size: 1.5rem;
    line-height: 1;
    padding: 2px 6px;
    margin: 0;
    cursor: pointer;
    width: auto;
}
.nav-menu-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(15, 20, 30, 0.5);
    z-index: 50;
}
.nav-menu-overlay.open { display: block; }
.nav-menu-box {
    position: relative; /* anchors .modal-close (position:absolute) to this box, not the full-screen overlay */
    background: var(--card);
    max-width: 640px;
    margin: 0 auto;
    box-shadow: 0 4px 14px rgba(15, 20, 30, 0.2);
    border-radius: 0 0 var(--radius) var(--radius);
    max-height: 85vh;
    overflow-y: auto;
}
.nav-menu-close-row {
    display: flex;
    justify-content: flex-end;
    padding: 4px 8px 0;
}
.nav-menu-box a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 16px;
    text-decoration: none;
    color: var(--text);
    border-bottom: 1px solid var(--divider);
    font-size: 0.95rem;
}
.nav-menu-box a:last-child { border-bottom: none; }
.nav-menu-box a.active { color: var(--primary); font-weight: 600; }
.nav-menu-box a .icon { font-size: 1.15rem; width: 24px; text-align: center; }

/* ---- Edit-category modal (dashboard: click a category name) -- reuses
   .nav-menu-overlay's backdrop/open toggle and .nav-menu-box's base card
   styling, but with top margin + full rounding so it reads as a centered
   dialog rather than a menu hanging from the top edge. ---- */
.cat-edit-modal-box { margin-top: 60px; border-radius: var(--radius); padding: 18px; }
.cat-edit-modal-box h3 { margin-top: 0; }
.cat-name.clickable, .cat-name-link { cursor: pointer; }
.cat-name.clickable:hover, .cat-name-link:hover { text-decoration: underline; }

/* ---- Drag-to-reorder category lists (reorder_categories.php) ---- */
.reorder-list { list-style: none; margin: 0; padding: 0; }
.reorder-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 4px;
    border-bottom: 1px solid var(--divider);
    background: var(--card);
}
.reorder-item:last-child { border-bottom: none; }
.reorder-item.inactive { opacity: 0.55; }
.reorder-item .drag-handle {
    cursor: grab;
    color: var(--muted);
    font-size: 1.2rem;
    line-height: 1;
    padding: 4px 6px;
    touch-action: none; /* keeps touch drags from also scrolling the page */
}
.reorder-item .reorder-name { flex: 1; }
.reorder-item.sortable-ghost { opacity: 0.3; }
.reorder-item.sortable-chosen { background: var(--bg); border-radius: 6px; }

/* ---- Rename/delete group popovers (reorder_categories.php card-title-bar) ----
   Each is a <details> whose <summary> is just a small icon; opening it drops
   a small form in a popover anchored under the icon, rather than pushing the
   card's height around like a normal inline <details> reveal would (this one
   lives inside a flex title bar next to the group name, not its own row). */
.group-actions { display: flex; gap: 10px; align-items: center; }
.group-actions details { position: relative; }
.group-actions summary {
    cursor: pointer;
    list-style: none;
    font-size: 1.05rem;
    line-height: 1;
    color: var(--primary-dark);
}
.group-actions summary::-webkit-details-marker { display: none; }
.group-actions .group-delete summary { color: var(--danger); }

/* Delete-category disclosure on categories.php's edit card -- same
   red-summary treatment as .group-delete above, just not living inside a
   .group-actions flex bar so it needs its own cursor/color rule. */
.cat-delete summary { color: var(--danger); cursor: pointer; }
.group-actions details form {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 5;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px;
    box-shadow: 0 4px 14px rgba(15, 20, 30, 0.18);
    min-width: 220px;
}
.group-actions details form label { margin-top: 0; }
.group-actions details form button { margin-top: 8px; }
