/* ============================================================
   Rubik webfont — self-hosted (no third-party requests).
   Variable font, weights 400-700. Latin + Latin-Extended subsets,
   matching what google-webfonts-helper serves for `latin,latin-ext`.
   License: SIL Open Font License 1.1, see fonts/OFL.txt.
   ============================================================ */

@font-face {
    font-family: 'Rubik';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('fonts/rubik-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Rubik';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('fonts/rubik-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   Footing Color Palette — CSS Custom Properties
   Light mode (default) and dark mode variants.
   ============================================================ */

:root {
    /* --- Brand --- */
    --ft-primary: #516d5f;
    --ft-primary-hover: #445e51;
    --ft-primary-border: #3a5346;
    --ft-accent: #b89e78;
    --ft-accent-hover: #a88e68;
    --ft-accent-text: #3a2e1e;
    /* Accent used as FOREGROUND text rather than as the .btn-accent fill. A single tan
       cannot do both jobs at AA: light enough to carry dark button text (5.16:1 against
       --ft-accent-text) is far too light to be read on cream (#b89e78 on --ft-bg is 2.29:1).
       Same hue and saturation as --ft-accent, lower lightness. */
    --ft-accent-strong: #7b6441;
    --ft-accent-strong-hover: #635239;
    /* Text drawn ON a saturated brand fill -- the primary button, the "move on" button, and
       the sticky net-total bar (which is --ft-primary when positive and --ft-amount-negative
       when negative). White works on light's dark fills; in dark the same fills are light
       sages and corals chosen to be read AS text on a dark ground, so white on them is
       2.66:1. The ink flips with the scheme instead of the fills moving. */
    --ft-fill-text: #ffffff;

    /* --- Monetary --- */
    --ft-amount-positive: #516d5f;
    --ft-amount-negative: #c0392b;

    /* --- Text --- */
    --ft-text: #2c3530;
    --ft-text-muted: #5e6a61;

    /* --- Backgrounds --- */
    --ft-bg: #f6f2ec;
    --ft-bg-surface: #ffffff;
    --ft-bg-topbar: #ede8e0;
    --ft-bg-topbar-border: #dfd8cc;

    /* --- Focus --- */
    --ft-focus-ring: #258cfb;

    /* --- Validation --- */
    --ft-valid: #26b050;
    --ft-invalid: #c0392b;

    /* --- Error UI --- */
    --ft-error-bg: #b32121;
    --ft-error-text: #ffffff;
    --ft-error-ui-bg: #fef9e7;

    /* --- Reconnect modal --- */
    --ft-modal-bg: #ffffff;
    --ft-modal-shadow: rgba(0, 0, 0, 0.3);
    --ft-modal-backdrop: rgba(0, 0, 0, 0.4);
    --ft-modal-btn-bg: #516d5f;
    --ft-modal-btn-hover: #445e51;
    --ft-modal-spinner: #516d5f;

    /* --- Checkbox --- */
    --ft-checkbox-border: #929292;

    /* --- Typography Scale --- */
    --ft-text-xs: 0.75rem;
    --ft-text-sm: 0.875rem;
    --ft-text-base: 1rem;
    --ft-text-lg: 1.125rem;
    --ft-text-xl: 1.25rem;
    --ft-text-2xl: 1.5rem;
    --ft-text-3xl: 2rem;

    /* --- Font Weights (Rubik) --- */
    --ft-weight-body: 400;
    --ft-weight-label: 500;
    --ft-weight-heading: 600;
    --ft-weight-title: 700;

    /* --- Spacing --- */
    --ft-space-xs: 0.25rem;
    --ft-space-sm: 0.5rem;
    --ft-space-md: 1rem;
    --ft-space-lg: 1.5rem;
    --ft-space-xl: 2rem;
    --ft-space-2xl: 3rem;
    --ft-space-3xl: 4rem;

    /* --- Border Radius --- */
    --ft-radius-sm: 0.25rem;
    --ft-radius-md: 0.5rem;
    --ft-radius-lg: 0.75rem;

    /* --- Shadows --- */
    --ft-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --ft-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* Dark mode: explicit data-theme attribute takes priority */
[data-theme="dark"] {
    /* --- Brand --- */
    --ft-primary: #7da893;
    --ft-primary-hover: #8fb8a2;
    --ft-primary-border: #6b9680;
    --ft-accent: #d4b88a;
    --ft-accent-hover: #e0c89a;
    --ft-accent-text: #2e2418;
    /* Dark's accent is already a foreground colour (8.33:1 on --ft-bg), so the text role
       needs no separate value here; the token exists for light's sake and is mirrored so
       call sites can use it unconditionally. */
    --ft-accent-strong: #d4b88a;
    --ft-accent-strong-hover: #e0c89a;
    /* See the light block: dark's fills are light, so the ink on them is dark.
       6.44:1 on --ft-primary, 4.86:1 on --ft-amount-negative. */
    --ft-fill-text: #171d19;

    /* --- Monetary --- */
    --ft-amount-positive: #7da893;
    --ft-amount-negative: #e06050;

    /* --- Text --- */
    --ft-text: #e2ded6;
    --ft-text-muted: #9a9690;

    /* --- Backgrounds --- */
    --ft-bg: #1c2420;
    --ft-bg-surface: #252e2a;
    --ft-bg-topbar: #222b26;
    --ft-bg-topbar-border: #333d37;

    /* --- Focus --- */
    --ft-focus-ring: #5ca8f5;

    /* --- Validation --- */
    --ft-valid: #3cc060;
    --ft-invalid: #e06050;

    /* --- Error UI --- */
    --ft-error-bg: #a02020;
    --ft-error-text: #ffffff;
    --ft-error-ui-bg: #2a2520;

    /* --- Reconnect modal --- */
    --ft-modal-bg: #252e2a;
    --ft-modal-shadow: rgba(0, 0, 0, 0.5);
    --ft-modal-backdrop: rgba(0, 0, 0, 0.6);
    --ft-modal-btn-bg: #7da893;
    --ft-modal-btn-hover: #8fb8a2;
    --ft-modal-spinner: #7da893;

    /* --- Checkbox --- */
    --ft-checkbox-border: #6a6a66;

    /* --- Shadows (darker for dark backgrounds) --- */
    --ft-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
    --ft-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* Fallback: apply dark mode when no explicit theme is set and OS prefers dark */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
        /* --- Brand --- */
        --ft-primary: #7da893;
        --ft-primary-hover: #8fb8a2;
        --ft-primary-border: #6b9680;
        --ft-accent: #d4b88a;
        --ft-accent-hover: #e0c89a;
        --ft-accent-text: #2e2418;
        /* Dark's accent is already a foreground colour (8.33:1 on --ft-bg), so the text role
           needs no separate value here; the token exists for light's sake and is mirrored so
           call sites can use it unconditionally. */
        --ft-accent-strong: #d4b88a;
        --ft-accent-strong-hover: #e0c89a;
        /* See the light block: dark's fills are light, so the ink on them is dark.
           6.44:1 on --ft-primary, 4.86:1 on --ft-amount-negative. */
        --ft-fill-text: #171d19;

        /* --- Monetary --- */
        --ft-amount-positive: #7da893;
        --ft-amount-negative: #e06050;

        /* --- Text --- */
        --ft-text: #e2ded6;
        --ft-text-muted: #9a9690;

        /* --- Backgrounds --- */
        --ft-bg: #1c2420;
        --ft-bg-surface: #252e2a;
        --ft-bg-topbar: #222b26;
        --ft-bg-topbar-border: #333d37;

        /* --- Focus --- */
        --ft-focus-ring: #5ca8f5;

        /* --- Validation --- */
        --ft-valid: #3cc060;
        --ft-invalid: #e06050;

        /* --- Error UI --- */
        --ft-error-bg: #a02020;
        --ft-error-text: #ffffff;
        --ft-error-ui-bg: #2a2520;

        /* --- Reconnect modal --- */
        --ft-modal-bg: #252e2a;
        --ft-modal-shadow: rgba(0, 0, 0, 0.5);
        --ft-modal-backdrop: rgba(0, 0, 0, 0.6);
        --ft-modal-btn-bg: #7da893;
        --ft-modal-btn-hover: #8fb8a2;
        --ft-modal-spinner: #7da893;

        /* --- Checkbox --- */
        --ft-checkbox-border: #6a6a66;

        /* --- Shadows (darker for dark backgrounds) --- */
        --ft-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
        --ft-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
    }
}

/* ============================================================
   Base Reset
   ============================================================ */

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

body {
    margin: 0;
}

h1, h2, h3, h4, h5, h6 {
    margin-top: 0;
    margin-bottom: 0.5rem;
    font-weight: 600;
    line-height: 1.2;
}

p {
    margin-top: 0;
    margin-bottom: 1rem;
}

ul, ol {
    margin-top: 0;
    margin-bottom: 1rem;
}

dl {
    margin-top: 0;
    margin-bottom: 1rem;
}

dt {
    font-weight: 700;
}

dd {
    margin-bottom: 0.5rem;
    margin-left: 0;
}

a {
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

button, input, select, textarea {
    font-family: inherit;
    font-size: inherit;
}

/* ============================================================
   Page Chrome — Header, Nav, Main
   (Promoted from MainLayout.razor.css / NavMenu.razor.css so the
   static landing page, which cannot use Blazor scoped CSS, shares
   the same rules as the Blazor app.)
   ============================================================ */

.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background-color: var(--ft-bg-topbar);
    border-bottom: 1px solid var(--ft-bg-topbar-border);
}

main {
    width: 100%;
    max-width: 54rem;
    margin: 0 auto;
    padding: 0 1rem;
}

.site-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 3.5rem;
    padding: 0 1rem;
    max-width: 54rem;
    margin: 0 auto;
}

.site-wordmark {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--ft-text);
    text-decoration: none;
}

.site-wordmark:hover {
    color: var(--ft-primary);
}

.site-nav-actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.site-nav-link {
    font-size: 0.9rem;
    color: var(--ft-text-muted);
    text-decoration: none;
    padding: 0.25rem 0.75rem;
    border-radius: 0.25rem;
    transition: color 0.15s, background-color 0.15s;
}

.site-nav-link:hover,
.site-nav-link.active {
    color: var(--ft-primary);
    background-color: var(--ft-sidebar-hover-bg);
}

/* ============================================================
   Layout Utilities (replacing Bootstrap utilities)
   ============================================================ */

.d-flex { display: flex !important; }
.flex-column { flex-direction: column !important; }
.justify-content-center { justify-content: center !important; }
.align-items-center { align-items: center !important; }
.align-self-center { align-self: center !important; }
.h-100 { height: 100% !important; }
.w-100 { width: 100% !important; }
.text-danger { color: var(--ft-invalid) !important; }

/* ============================================================
   Button Base (replacing Bootstrap .btn)
   ============================================================ */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--ft-text);
    text-align: center;
    text-decoration: none;
    vertical-align: middle;
    cursor: pointer;
    user-select: none;
    background-color: transparent;
    border: 1px solid transparent;
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    border-radius: var(--ft-radius-md);
    transition: color 0.15s, background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.btn:disabled,
.btn[disabled] {
    opacity: 0.65;
    cursor: not-allowed;
}

.btn-link {
    text-decoration: none;
    color: var(--ft-primary);
    background-color: transparent;
    border-color: transparent;
    padding: 0;
}

.btn-link:hover {
    text-decoration: none;
    color: var(--ft-primary-hover);
}

/* ============================================================
   Card Base (replacing Bootstrap .card)
   ============================================================ */

.card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: var(--ft-bg-surface);
    background-clip: border-box;
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-md);
}

.card-header {
    padding: 0.5rem 1rem;
    margin-bottom: 0;
    background-color: var(--ft-bg-topbar);
    border-bottom: 1px solid var(--ft-bg-topbar-border);
}

.card-header:first-child {
    border-radius: calc(var(--ft-radius-md) - 1px) calc(var(--ft-radius-md) - 1px) 0 0;
}

.card-body {
    flex: 1 1 auto;
    padding: 1rem;
}

/* ============================================================
   Form Controls Base (replacing Bootstrap form styles)
   ============================================================ */

.form-control,
.form-select {
    display: block;
    width: 100%;
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--ft-text);
    background-color: var(--ft-bg-surface);
    background-clip: padding-box;
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-md);
    transition: border-color 0.15s, box-shadow 0.15s;
    -webkit-appearance: none;
    appearance: none;
}

.form-control:focus,
.form-select:focus {
    color: var(--ft-text);
    background-color: var(--ft-bg-surface);
    border-color: var(--ft-focus-ring);
    outline: 0;
    box-shadow: 0 0 0 0.25rem rgba(37, 140, 251, 0.25);
}

.form-control::placeholder {
    color: var(--ft-text-muted);
    opacity: 1;
}

/* ============================================================
   Bootstrap Icons Replacement (.bi-x)
   ============================================================ */

.bi-x::before {
    content: "×";
    font-style: normal;
    font-weight: 700;
    font-size: 1.1em;
    line-height: 1;
}

/* ============================================================
   Global Styles
   ============================================================ */

html, body {
    font-family: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-weight: var(--ft-weight-body);
    font-size: var(--ft-text-base);
    height: 100%;
    color: var(--ft-text);
    background-color: var(--ft-bg);
}

a, .btn-link {
    color: var(--ft-primary);
}

a:hover, .btn-link:hover {
    color: var(--ft-primary-hover);
}

.btn-primary {
    color: var(--ft-fill-text);
    background-color: var(--ft-primary);
    border-color: var(--ft-primary-border);
}

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

.btn-primary:active, .btn-primary:focus-visible {
    background-color: var(--ft-primary-hover);
    border-color: var(--ft-primary-border);
}

.btn-accent {
    color: var(--ft-accent-text);
    background-color: var(--ft-accent);
    border-color: var(--ft-accent-hover);
}

.btn-accent:hover {
    background-color: var(--ft-accent-hover);
    border-color: var(--ft-accent-hover);
}

.btn-accent:active, .btn-accent:focus-visible {
    background-color: var(--ft-accent-hover);
    border-color: var(--ft-accent-hover);
}

.btn-accordian-header:focus {
    outline: none;
    box-shadow: none;
    text-decoration: none;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--ft-focus-ring);
}

.content {
    padding: 1.5rem 0 4rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--ft-valid);
}

.invalid {
    outline: 1px solid var(--ft-invalid);
}

.validation-message {
    color: var(--ft-invalid);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--ft-error-bg);
    padding: 1rem 1rem 1rem 3.7rem;
    color: var(--ft-error-text);
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

#blazor-error-ui {
    color-scheme: light only;
    background: var(--ft-error-ui-bg);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.darker-border-checkbox.form-check-input {
    border-color: var(--ft-checkbox-border);
}

.monetary-amount-sensitive .monetary-amount-highlight-positive {
    color: var(--ft-amount-positive);
}

.monetary-amount-sensitive .monetary-amount-highlight-negative {
    color: var(--ft-amount-negative);
}

/* ============================================================
   Money Flow Section — Header and Form
   ============================================================ */

.card-header h2 {
    margin: 0;

    /* The heading carries no visible text of its own -- the nested .btn-link below does, and
       pins its own size in rem -- so the level is free to be whatever the document outline
       needs (F-03 moved it from h5 to h2). This line keeps the UA's heading size from leaking
       in behind that: without it the element computes the h2 default (24px), and the first
       descendant sized in `em` would silently inherit it. Matching .btn-link's size means the
       whole subtree agrees on one number. */
    font-size: var(--ft-text-sm);
}

.card-header .btn-link {
    font-weight: var(--ft-weight-heading);
    font-size: var(--ft-text-sm);
    padding: var(--ft-space-xs) 0;
    width: 100%;
    text-align: left;
    display: flex;
    align-items: center;
    gap: var(--ft-space-sm);
}

.card-body {
    padding: var(--ft-space-md) var(--ft-space-lg);
}

#moneyFlows dl {
    display: grid;

    /* F-12. `1fr` is `minmax(auto, 1fr)`, and that `auto` floor is the track's min-content
       width -- which is the 327px intrinsic width of the description field's `size="30"`
       (MoneyFlowCard.razor). Against 238px of available space at the 320 floor the track simply
       refused to shrink, and the row ran 143px past the viewport. `minmax(0, 1fr)` removes the
       floor from the track; the `min-width: 0` below removes it from the controls inside. Both
       are needed -- W-05 measured each alone and neither fixes it, and relaxing the FIRST track
       instead (`minmax(0, auto) 1fr`) makes it worse by collapsing the label column to 0px.
       This is a no-op at Tablet and Desktop, where the tracks stay 167px 439px. */
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--ft-space-sm) var(--ft-space-md);
    align-items: center;
    margin-bottom: var(--ft-space-md);
}

#moneyFlows dt {
    font-weight: var(--ft-weight-label);
    color: var(--ft-text-muted);
    font-size: var(--ft-text-sm);
}

#moneyFlows dd {
    margin-bottom: 0;
    display: flex;
    align-items: center;
    gap: var(--ft-space-sm);
    flex-wrap: wrap;
}

/* The other half of the F-12 repair -- see the `dl` rule above. A form control is a flex item
   here, and a flex item's default `min-width: auto` resolves to its content-based minimum,
   which for `<input size="30">` is 327px. Relaxing the grid track alone just moves the refusal
   to shrink down one level. Like the track change, this only does anything below ~430px: at
   Tablet and Desktop the controls are already narrower than the space they have. */
#moneyFlows dd input,
#moneyFlows dd select {
    min-width: 0;
    max-width: 100%;
}

/* ============================================================
   Landing Page — Hero & Cards
   ============================================================ */

.ft-hero {
    text-align: center;
    padding: var(--ft-space-2xl) var(--ft-space-md) var(--ft-space-xl);
}

.ft-hero h1 {
    font-size: var(--ft-text-3xl);
    font-weight: var(--ft-weight-title);
    color: var(--ft-text);
    margin-bottom: var(--ft-space-sm);
}

.ft-hero .ft-tagline {
    font-size: var(--ft-text-lg);
    color: var(--ft-text-muted);
    max-width: 32rem;
    margin: 0 auto var(--ft-space-xl);
    line-height: 1.6;
}

.ft-narrative {
    max-width: 36rem;
    margin: 0 auto;
    padding: 0 var(--ft-space-md) var(--ft-space-xl);
}

.ft-narrative p {
    font-size: var(--ft-text-base);
    line-height: 1.8;
    color: var(--ft-text-muted);
    margin-bottom: var(--ft-space-md);
}

.ft-narrative p em {
    color: var(--ft-accent-strong);
    font-style: italic;
}

.ft-value-section {
    text-align: center;
    max-width: 36rem;
    margin: 0 auto;
    padding: var(--ft-space-xl) var(--ft-space-md);
    border-top: 1px solid var(--ft-bg-topbar-border);
}

.ft-value-section h2 {
    font-size: var(--ft-text-2xl);
    font-weight: var(--ft-weight-heading);
    color: var(--ft-primary);
    margin-bottom: var(--ft-space-sm);
}

.ft-value-section p {
    font-size: var(--ft-text-base);
    line-height: 1.6;
    color: var(--ft-text-muted);
    margin-bottom: var(--ft-space-md);
}

.ft-privacy-note {
    font-size: var(--ft-text-sm) !important;
    font-style: italic;
    color: var(--ft-text-muted);
}

.ft-value-section .btn {
    margin-top: var(--ft-space-sm);
}

/* ============================================================
   Landing Page Footer
   ============================================================ */

/*
   F-01. The landing footer sits OUTSIDE <main> (index.html) so that it exposes the
   contentinfo landmark -- a <footer> nested in main/article/section/aside/nav is generic.
   Everything below exists to make that structural move invisible, because it is a landmark
   repair and not a redesign; the numbers it has to hit are pinned in LandingFooterTests.

   Outside main the footer loses main's `max-width: 54rem; margin: 0 auto; padding: 0 1rem`,
   and its `border-top` -- the only thing it paints -- would stretch edge to edge (832px ->
   1280px at desktop). It cannot take that box back with padding: the border is drawn on the
   BORDER box, which padding is inside of. So it reproduces main's *content* box directly:
   52rem is main's 54rem cap less its two 1rem gutters, and `calc(100% - 2rem)` is those
   gutters below the cap. That is identical to main's content box at every width -- below
   the cap both give x=16, and above it main's content edge (W-864)/2 + 16 and this one's
   (W-832)/2 are the same number.

   `.ft-landing-content` hands over the vertical half. `.content`'s `padding-bottom: 4rem`
   used to fall below the footer; with the footer outside main it would fall ABOVE it
   instead, dropping the footer 64px and leaving no tail. Zeroing it on the landing article
   and carrying that 4rem down here puts both back. The tool page now needs the same handover
   for the same reason and has its own modifier, `.ft-tool-content`, below; the two are kept
   separate rather than merged into one selector because the 4rem means something different
   on each page -- see the tool footer's block.

   The 4rem tail is PADDING and not `margin-bottom`, which is the obvious way to write it and
   is wrong: a last child's bottom margin does not extend the scrollable area, so the document
   came back 64px shorter with `scrollHeight` flush against the footer's border box (measured,
   both -- 0.33px at 320 and -0.13px at 1280, against 64px before). Padding is inside the
   border box and does count. Nothing is painted below the `border-top`, and the flex line is
   placed by the padding above it, so 2rem of bottom padding or 6rem looks identical; only the
   scroll extent can tell, which is exactly the thing being preserved.
*/

.ft-landing-content {
    padding-bottom: 0;
}

.ft-landing-footer {
    display: flex;
    justify-content: center;
    gap: 1.5rem;
    width: calc(100% - 2rem);
    max-width: 52rem;
    margin: 2rem auto 0;
    padding: 2rem 0 6rem;
    border-top: 1px solid var(--ft-bg-topbar-border);
}

.ft-landing-footer a {
    font-size: 0.85rem;
    color: var(--ft-text-muted);
    text-decoration: none;
    transition: color 0.15s;
}

.ft-landing-footer a:hover {
    color: var(--ft-primary);
}


/* ============================================================
   Tool Page Footer
   ============================================================ */

/*
   F-01, tool half. The privacy promise -- "your data never leaves your browser" -- shipped
   only on the landing page, so the one page where someone actually types their finances was
   the one page that never made it. This footer carries it there. The `contentinfo` landmark
   the tool page also gains is a side effect of doing it correctly, not the reason.

   Geometry is the landing footer's recipe, for the landing footer's reason: outside `main`
   the footer has none of `main`'s `max-width: 54rem; margin: 0 auto; padding: 0 1rem`, and
   `border-top` is drawn on the BORDER box, which padding is inside of, so it cannot buy the
   box back with padding and would rule edge to edge. `calc(100% - 2rem)` with a 52rem cap is
   `main`'s CONTENT box restated: 54rem less two 1rem gutters at the cap, those gutters below
   it. Measured identical to `article.content` at all four viewports; `ToolFooterTests` pins
   both that equality and the literals.

   `.ft-tool-content` zeroes `.content { padding-bottom: 4rem }` and the footer's
   `padding-bottom: 6rem` carries it back plus its own 2rem, exactly as on the landing page --
   but the 4rem is doing a SECOND job here that it does not do there, which is why the two
   modifiers stay separate. `.ft-sticky-total` is `position: fixed; bottom: 0`, so the bottom
   4rem of the tool page is clearance: without it, whatever is last in the document sits
   behind the bar when you scroll to the end. Leaving `.content`'s padding alone and letting
   it fall above the footer would have put that clearance in the wrong place -- 64px of gap
   above the border-top, and the privacy line itself under the bar. Do not "simplify" the
   6rem to 2rem; the line goes behind the net-total bar at every viewport if you do.

   Tail as PADDING, not `margin-bottom`: a last child's bottom margin does not extend the
   scrollable area, so the clearance would not exist where it is needed. `p`'s global
   `margin-bottom: 1rem` (app.css:264) is zeroed for the same arithmetic reason -- the
   landing footer's child is an inline `a` and never had one.
*/

.ft-tool-content {
    padding-bottom: 0;
}

.ft-tool-footer {
    width: calc(100% - 2rem);
    max-width: 52rem;
    margin: 2rem auto 0;
    padding: 2rem 0 6rem;
    border-top: 1px solid var(--ft-bg-topbar-border);
}

.ft-tool-footer p {
    margin: 0;
}


/* ============================================================
   Find My Footing Page — Header
   ============================================================ */

.ft-page-header {
    margin-bottom: var(--ft-space-lg);
}

.ft-page-header h1 {
    font-size: var(--ft-text-2xl);
    font-weight: var(--ft-weight-title);
    color: var(--ft-text);
    margin-bottom: var(--ft-space-xs);
}

.ft-page-header p {
    color: var(--ft-text-muted);
    font-size: var(--ft-text-sm);
    margin: 0;
}

/* ============================================================
   Sticky Net Total Bar
   ============================================================ */

.ft-sticky-total {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 200;
    cursor: pointer;
    transition: background-color 0.3s;
}

.ft-sticky-total--positive {
    background-color: var(--ft-primary);
}

.ft-sticky-total--negative {
    background-color: var(--ft-amount-negative, #dc3545);
}

.ft-sticky-total__summary {
    /* Button reset -- same reasoning as .ft-entry-chip__delete further down. This row is the toggle
       for the net-total detail panel, and it is the summary rather than the whole bar that
       became a button: .ft-sticky-total also contains the expanded panel's <h2> and <p>, which
       are flow content a <button> may not contain. `width: 100%` because a button does not
       stretch to its container the way the <div> it replaces did. */
    appearance: none;
    background: none;
    border: none;
    font: inherit;
    width: 100%;
    cursor: pointer;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    height: 3rem;
    padding: 0 1rem;
    color: var(--ft-fill-text);
    font-weight: var(--ft-weight-heading);
}

.ft-sticky-total__summary .monetary-amount-highlight-positive,
.ft-sticky-total__summary .monetary-amount-highlight-negative {
    color: var(--ft-fill-text);
}

.ft-sticky-total__amount {
    transition: transform 0.2s;
}

.ft-sticky-total__chevron {
    font-size: 0.7rem;
    opacity: 0.7;
    margin-left: 0.25rem;
}

.ft-sticky-total__detail {
    padding: var(--ft-space-md) var(--ft-space-lg);
    background-color: var(--ft-bg-surface);
    border-top: 1px solid var(--ft-bg-topbar-border);
    color: var(--ft-text);
    max-width: 54rem;
    margin: 0 auto;
}

.ft-sticky-total__detail h2 {
    font-size: var(--ft-text-base);
    font-weight: var(--ft-weight-heading);
    margin-bottom: var(--ft-space-xs);
    color: var(--ft-text);
}

.ft-sticky-total__detail p {
    font-size: var(--ft-text-sm);
    color: var(--ft-text-muted);
    margin-bottom: 0;
    line-height: 1.5;
}

/* ============================================================
   Export Button Area
   ============================================================ */

.ft-export {
    padding: var(--ft-space-md) 0;
    text-align: center;
}

.ft-export .btn {
    padding: var(--ft-space-sm) var(--ft-space-xl);
    font-size: var(--ft-text-sm);
    border-radius: var(--ft-radius-md);
}

.ft-compact-actions {
    padding: var(--ft-space-md) 0;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ft-space-sm);
}

.ft-switch-flow {
    background: none;
    border: none;
    padding: 0;
    font-size: var(--ft-text-sm);
    color: var(--ft-accent-strong);
    text-decoration: none;
    cursor: pointer;
}

.ft-switch-flow:hover {
    text-decoration: underline;
}

/* ============================================================
   Accent Highlights — Inline Help & Secondary Links
   ============================================================ */

/* ============================================================
   Conversational Progressive Flow (First-Time Users)
   ============================================================ */

.ft-conversational {
    max-width: 42rem;
}

.ft-section-card {
    margin-bottom: var(--ft-space-xs);
    border-radius: var(--ft-radius-md) !important;
    border-bottom: 1px solid var(--ft-bg-topbar-border) !important;
}

.ft-conversational > .ft-section-card + div {
    background-color: var(--ft-bg-surface);
    border: 1px solid var(--ft-bg-topbar-border);
    border-top: 0;
    border-radius: 0 0 var(--ft-radius-md) var(--ft-radius-md);
    margin-bottom: var(--ft-space-lg);
}

.ft-conversational > .ft-section-card + div > .card-body {
    padding: var(--ft-space-md) var(--ft-space-lg);
}

.ft-guiding-sentence {
    font-size: var(--ft-text-lg);
    font-weight: var(--ft-weight-label);
    color: var(--ft-text);
    margin-bottom: var(--ft-space-md);
    line-height: 1.5;
}

.ft-move-on {
    margin-top: var(--ft-space-md);
    text-align: right;
}

.ft-move-on__btn {
    font-size: var(--ft-text-sm) !important;
    padding: var(--ft-space-xs) var(--ft-space-lg) !important;
    border-color: var(--ft-primary) !important;
    color: var(--ft-primary) !important;
    border-radius: var(--ft-radius-md) !important;
    transition: background-color 0.15s, color 0.15s !important;
}

.ft-move-on__btn:hover {
    background-color: var(--ft-primary) !important;
    color: var(--ft-fill-text) !important;
}

.ft-move-on__btn--ready {
    background-color: var(--ft-primary) !important;
    color: var(--ft-fill-text) !important;
    animation: ft-move-on-pulse 0.4s ease 0.8s both;
}

@keyframes ft-move-on-pulse {
    0% { opacity: 0.7; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.04); }
    100% { opacity: 1; transform: scale(1); }
}

/* ============================================================
   Compact Summary View (Returning Users)
   ============================================================ */

.ft-compact-summary {
    max-width: 42rem;
}

.ft-compact-summary .ft-section-card {
    margin-bottom: 0;
    border-radius: 0 !important;
    border-bottom: 0 !important;
}

.ft-compact-summary .ft-section-card:first-of-type {
    border-top-left-radius: var(--ft-radius-md) !important;
    border-top-right-radius: var(--ft-radius-md) !important;
}

.ft-compact-summary .ft-section-card:last-of-type {
    border-bottom-left-radius: var(--ft-radius-md) !important;
    border-bottom-right-radius: var(--ft-radius-md) !important;
    border-bottom: 1px solid var(--ft-bg-topbar-border) !important;
}

/* When the section body is shown, the card after it needs bottom border removed */
.ft-compact-summary .ft-section-card + div {
    border-bottom: 0 !important;
    border-radius: 0 !important;
    margin-bottom: 0 !important;
}

.ft-compact-header {
    font-size: var(--ft-text-base) !important;
    padding: var(--ft-space-sm) 0 !important;
    justify-content: space-between !important;
}

.ft-chevron {
    font-size: 0.6rem;
    opacity: 0.6;
    margin-left: auto;
    padding-left: var(--ft-space-sm);
    transition: transform 0.2s;
}

/* ============================================================
   Inline Tooltips (replaces Bootstrap Popovers)
   ============================================================ */

.ft-tooltip {
    position: relative;
    color: var(--ft-accent-strong);
    cursor: help;
    border-bottom: 1px dashed var(--ft-accent-strong);
    white-space: nowrap;
}

.ft-tooltip::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 0.4rem);
    left: 50%;
    transform: translateX(-50%);
    background-color: var(--ft-text);
    color: var(--ft-bg-surface);
    padding: 0.35rem 0.6rem;
    border-radius: var(--ft-radius-sm);
    font-size: var(--ft-text-xs);
    font-weight: var(--ft-weight-body);
    line-height: 1.4;
    white-space: normal;
    width: 15rem;
    text-align: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 100;
}

.ft-tooltip:hover::after,
.ft-tooltip:focus::after {
    opacity: 1;
}

/* ============================================================
   Money Input Adornment (fo-si0.9)
   ============================================================ */

.ft-input-money {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-sm);
    background-color: var(--ft-bg-surface);
    transition: border-color 0.2s;
    overflow: hidden;
}

.ft-input-money:focus-within {
    border-color: var(--ft-focus-ring);
    box-shadow: 0 0 0 2px rgba(37, 140, 251, 0.15);
}

.ft-input-money__prefix {
    padding: var(--ft-space-xs) var(--ft-space-sm);
    color: var(--ft-text-muted);
    font-size: var(--ft-text-sm);
    font-weight: var(--ft-weight-label);
    background-color: var(--ft-bg-topbar);
    border-right: 1px solid var(--ft-bg-topbar-border);
    user-select: none;
}

.ft-input-money__field {
    border: none !important;
    box-shadow: none !important;
    background-color: transparent !important;
    padding: var(--ft-space-xs) var(--ft-space-sm) !important;
    font-size: var(--ft-text-sm);
    color: var(--ft-text);
    width: 7rem;
    outline: none;
}

.ft-period-select {
    padding: var(--ft-space-xs) var(--ft-space-sm) !important;
    border: 1px solid var(--ft-bg-topbar-border) !important;
    border-radius: var(--ft-radius-sm) !important;
    background-color: var(--ft-bg-surface) !important;
    color: var(--ft-text) !important;
    font-size: var(--ft-text-sm) !important;
    transition: border-color 0.2s !important;
    cursor: pointer;
}

.ft-period-select:focus {
    border-color: var(--ft-focus-ring) !important;
    box-shadow: 0 0 0 2px rgba(37, 140, 251, 0.15) !important;
    outline: none !important;
}

.ft-add-btn {
    transition: transform 0.15s, background-color 0.15s !important;
}

.ft-add-btn:hover {
    transform: translateY(-1px);
}

/* ============================================================
   Entry Chips (fo-si0.10)
   ============================================================ */

.ft-entry-list {
    list-style: none;
    padding: 0;
    margin: var(--ft-space-md) 0 0;
    display: flex;
    flex-direction: column;
    gap: var(--ft-space-xs);
}

.ft-entry-chip {
    display: flex;
    align-items: center;
    gap: var(--ft-space-sm);
    padding: var(--ft-space-xs) var(--ft-space-sm);
    background-color: var(--ft-bg-topbar);
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-md);
    font-size: var(--ft-text-sm);
}

.ft-entry-chip__name {
    flex: 1;
    color: var(--ft-text);
    font-weight: var(--ft-weight-label);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ft-entry-chip__amount {
    color: var(--ft-text-muted);
    white-space: nowrap;
    font-size: var(--ft-text-xs);
}

.ft-entry-chip__delete {
    /* Button reset. This is a real <button> so a keyboard user can reach it (F-05); it was a
       <span role="button"> with no tabindex. These five declarations neutralise the UA button
       styling -- background, border, and the `font` shorthand the UA sets, which would
       otherwise override the inherited family. `font: inherit` must stay ABOVE font-size and
       line-height below, which are the values this control actually wants. */
    appearance: none;
    background: none;
    border: none;
    font: inherit;
    text-align: inherit;

    cursor: pointer;
    color: var(--ft-text-muted);
    font-size: 1.1rem;
    line-height: 1;
    flex-shrink: 0;
    transition: color 0.15s, transform 0.15s;
    padding: 2px;
    border-radius: var(--ft-radius-sm);
}

.ft-entry-chip__delete:hover {
    color: var(--ft-amount-negative);
    transform: scale(1.2);
}

/* ============================================================
   Export Button and Privacy Banner (fo-si0.11)
   ============================================================ */

.ft-privacy-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--ft-space-sm);
    font-size: var(--ft-text-sm);
    color: var(--ft-text-muted);
    margin-bottom: var(--ft-space-lg);
    padding: var(--ft-space-sm) var(--ft-space-md);
    background-color: var(--ft-bg-topbar);
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-md);
}

.ft-privacy-banner__icon {
    font-size: var(--ft-text-base);
    flex-shrink: 0;
    margin-top: 1px;
}

.ft-privacy-banner em {
    font-style: normal;
    line-height: 1.5;
    flex: 1;
}

.ft-clear-btn {
    font-size: var(--ft-text-xs) !important;
    padding: var(--ft-space-xs) var(--ft-space-sm) !important;
    color: var(--ft-text-muted) !important;
    border: 1px solid var(--ft-bg-topbar-border) !important;
    border-radius: var(--ft-radius-sm) !important;
    background-color: transparent !important;
    white-space: nowrap;
    flex-shrink: 0;
    align-self: center;
    transition: color 0.15s, border-color 0.15s, background-color 0.15s !important;
}

.ft-clear-btn:hover {
    color: var(--ft-amount-negative) !important;
    border-color: var(--ft-amount-negative) !important;
    background-color: var(--ft-bg-surface) !important;
}

.ft-export-btn {
    padding: var(--ft-space-sm) var(--ft-space-xl) !important;
    font-size: var(--ft-text-sm) !important;
    border-radius: var(--ft-radius-md) !important;
    transition: transform 0.15s, background-color 0.15s !important;
    cursor: pointer;
}

.ft-export-btn:hover {
    transform: translateY(-1px);
}

.text-info {
    color: var(--ft-accent-strong) !important;
}

a.text-info:hover {
    color: var(--ft-accent-strong-hover) !important;
}

/* ============================================================
   Theme Toggle
   ============================================================ */

.theme-toggle {
    background: none;
    border: 1px solid var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-sm);
    cursor: pointer;
    padding: var(--ft-space-xs) var(--ft-space-sm);
    font-size: var(--ft-text-lg);
    line-height: 1;
    color: var(--ft-text);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.2s;
}

.theme-toggle:hover {
    background-color: var(--ft-bg-topbar-border);
}

.theme-toggle .icon-sun,
.theme-toggle .icon-moon {
    display: none;
}

/* Show sun icon in dark mode (click to switch to light) */
[data-theme="dark"] .theme-toggle .icon-sun {
    display: inline;
}

[data-theme="dark"] .theme-toggle .icon-moon {
    display: none;
}

/* Show moon icon in light mode (click to switch to dark) */
[data-theme="light"] .theme-toggle .icon-moon {
    display: inline;
}

[data-theme="light"] .theme-toggle .icon-sun {
    display: none;
}

/* When no explicit theme, default to showing moon (assume light) */
:root:not([data-theme]) .theme-toggle .icon-moon {
    display: inline;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) .theme-toggle .icon-sun {
        display: inline;
    }

    :root:not([data-theme]) .theme-toggle .icon-moon {
        display: none;
    }
}

/* ============================================================
   Micro-interactions and Transitions (fo-si0.15)
   ============================================================ */

/* Section reveal animation */
.ft-section--open {
    animation: ft-reveal 0.3s ease-out;
}

@keyframes ft-reveal {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Newly revealed section card — gentle highlight that fades */
.ft-section-card {
    animation: ft-card-appear 0.4s ease-out;
}

@keyframes ft-card-appear {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Card header hover */
.card-header .btn-link:hover {
    background-color: var(--ft-bg-topbar-border);
    border-radius: var(--ft-radius-sm);
}

/* Focus ring transition on all interactive elements */
input:focus,
select:focus,
textarea:focus,
button:focus-visible {
    transition: box-shadow 0.15s, border-color 0.15s;
}

/* Chevron rotation animation */
.ft-chevron {
    transition: transform 0.2s ease;
}

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

/* Entry chip entrance */
.ft-entry-chip {
    animation: ft-chip-in 0.15s ease-out;
}

@keyframes ft-chip-in {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* ============================================================
   Branded Loading State (fo-si0.15)
   ============================================================ */

.ft-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--ft-space-md);
    height: 100%;
    min-height: 8rem;
    color: var(--ft-text-muted);
}

.ft-loading__spinner {
    display: block;
    width: 2rem;
    height: 2rem;
    border: 2px solid var(--ft-bg-topbar-border);
    border-top-color: var(--ft-primary);
    border-radius: 50%;
    animation: ft-spin 0.7s linear infinite;
}

.ft-loading__text {
    font-size: var(--ft-text-sm);
    color: var(--ft-text-muted);
}

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