/* ================================================================
   MOBILE-FIRST DESIGN SYSTEM — Phase A Foundation
   Personal Finance App · Dark theme · Blue/Cyan accent
   ----------------------------------------------------------------
   Loading order: AFTER style.css (overrides desktop defaults)
   Include: <link rel="stylesheet" href="./assets/css/mobile.css">
================================================================ */


/* ================================================================
   1. DESIGN TOKENS — extends :root from style.css
================================================================ */

:root {
    /* ---- Responsive breakpoints (Tailwind-aligned) ---------------------
       Use these vars in JS via getComputedStyle, or reference the literal
       value in @media queries (CSS custom properties cannot appear inside
       @media expressions).
       --------------------------------------------------------------------
        sm  = 640px   mobile-large / landscape phone
        md  = 768px   tablet portrait
        lg  = 1024px  laptop / tablet landscape — ⚠️ PIN cutoff threshold
        xl  = 1280px  desktop
        2xl = 1536px  wide desktop
       -------------------------------------------------------------------- */
    --bp-sm:  640px;
    --bp-md:  768px;
    --bp-lg:  1024px;
    --bp-xl:  1280px;
    --bp-2xl: 1536px;

    /* ---- Spacing scale (4px base) ---- */
    --space-1:   4px;
    --space-2:   8px;
    --space-3:   12px;
    --space-4:   16px;   /* base padding for containers */
    --space-5:   20px;
    --space-6:   24px;
    --space-8:   32px;
    --space-10:  40px;
    --space-12:  48px;
    --space-16:  64px;

    /* ---- Border radius ---- */
    --r-sm:  8px;
    --r-md:  12px;
    --r-lg:  16px;
    --r-xl:  20px;
    --r-2xl: 24px;
    --r-full: 9999px;

    /* ---- Typography (mobile-first) ---- */
    --fs-caption:   13px;
    --fs-body:      16px;        /* 16 = ป้องกัน iOS auto-zoom on input focus */
    --fs-h3:        17px;
    --fs-h2:        18px;
    --fs-h1:        22px;
    --fs-display:   28px;
    --fs-money:     32px;
    --fs-money-xl:  40px;

    --lh-tight:   1.15;
    --lh-normal:  1.45;
    --lh-loose:   1.6;

    --fw-regular: 400;
    --fw-medium:  500;
    --fw-semi:    600;
    --fw-bold:    700;

    /* ---- Semantic colors (money) ---- */
    --money-income:    #34d399;       /* emerald-400 */
    --money-income-bg: rgba(52, 211, 153, 0.12);
    --money-expense:   #fb7185;       /* rose-400   */
    --money-expense-bg:rgba(251, 113, 133, 0.12);
    --money-neutral:   var(--text-primary);

    /* ---- Surfaces (deeper than login card) ---- */
    --surface-1: rgba(255, 255, 255, 0.04);
    --surface-2: rgba(255, 255, 255, 0.06);
    --surface-3: rgba(255, 255, 255, 0.08);

    /* ---- Elevation (shadows) ---- */
    --elev-1: 0 1px 2px rgba(0, 0, 0, 0.25);
    --elev-2: 0 4px 12px -2px rgba(0, 0, 0, 0.35);
    --elev-3: 0 10px 30px -6px rgba(0, 0, 0, 0.5);
    --elev-fab: 0 8px 24px -4px rgba(59, 130, 246, 0.55),
                0 4px 10px -2px rgba(6, 182, 212, 0.35);

    /* ---- Tab bar height (for content padding-bottom) ---- */
    --tab-bar-h:  64px;
    /* 🆕 v3.1.1 rev4 — extra 12px lifts the tab bar / keyboards above the
       iOS home-indicator "chin" so they don't hug the curved screen edge.
       Was: calc(64px + env(safe-area-inset-bottom)).
       Now: calc(64px + env(safe-area-inset-bottom) + 12px). */
    --tab-bar-safe: calc(64px + env(safe-area-inset-bottom, 0px) + 12px);

    /* ---- Z-index scale ---- */
    --z-tab-bar:    100;
    --z-fab:        110;
    --z-sheet-bg:   200;
    --z-sheet:      210;
    --z-toast:      9999;
}


/* ================================================================
   2. BASE — mobile-first body / app shell
================================================================ */

html {
    /* iOS landscape auto-resize is already prevented by the viewport meta
       (user-scalable=no, maximum-scale=1) so text-size-adjust is redundant. */
    -webkit-tap-highlight-color: transparent;
    /* 🆕 v3.1.0 Phase O polish sweep (round 2) — smooth in-page anchor jumps
       (benefits: Accounts jump-chips, Security row expand, Health scroll-to-error). */
    scroll-behavior: smooth;
}

/* 🆕 v3.1.0 Phase O polish sweep (round 2) — consistent focus-visible ring
   across all interactive elements (buttons, links, inputs). Keyboard-only;
   mouse clicks suppress it via :focus-visible selector. */
:where(button, a, [role="button"], [tabindex]):focus-visible {
    outline: 2px solid var(--brand-500, #3b82f6);
    outline-offset: 2px;
    border-radius: 6px;
}

/* 🆕 v3.1.0 Phase O polish sweep (round 2) — respect reduced-motion pref.
   Disables scroll-behavior + all transitions/animations for users who
   enable "Reduce motion" in system settings. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

body.app-shell {
    margin: 0;
    /* 🔧 Override style.css's `body { height: 100vh; overflow: hidden }`
       — เพื่อให้ page scroll ได้ตามปกติ */
    height: auto;
    min-height: 100vh;
    overflow-x: hidden;
    overflow-y: visible;
    /* 🆕 v3.1.1 rev4 — iOS PWA first-paint fuzzy-top fix.
       `isolation: isolate` creates a new stacking context on body WITHOUT
       the containing-block side-effect of `transform: translateZ(0)`, so
       fixed children (bottom tab bar, FAB, modals) still anchor to the
       viewport correctly. Combined effect: iOS composites body as its own
       layer up front, matching what happens when the FAB sheet opens
       (position:fixed body) — so the "fuzzy top" that only cleared after
       a sheet open/close is cleared on initial paint instead. */
    isolation: isolate;
    background: linear-gradient(180deg, #0c1224 0%, #0f172a 100%);
    color: var(--text-primary);
    font-family: var(--font-main, "Poppins", system-ui, sans-serif);
    font-size: var(--fs-body);
    line-height: var(--lh-normal);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Disable text selection on UI chrome (tabs, FAB, etc.) */
.no-select {
    -webkit-user-select: none;
    user-select: none;
}

/* Main scrollable area — leave room for fixed bottom tab bar */
.app-main {
    padding: var(--space-4) var(--space-4) calc(var(--tab-bar-safe) + var(--space-6));
    min-height: 100vh;
}


/* ================================================================
   3. UTILITY — money display, layout helpers
================================================================ */

.money {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    font-weight: var(--fw-semi);
}

.money--income   { color: var(--money-income);  }
.money--expense  { color: var(--money-expense); }
/* 🆕 Option B — additional transaction types */
.money--transfer { color: #2563eb; }   /* blue — sideways move */
.money--opening  { color: #64748b; }   /* slate — neutral baseline */
.money--other    { color: #64748b; }   /* slate — uncategorized */
.money--lg      { font-size: var(--fs-money);    }
.money--xl      { font-size: var(--fs-money-xl); }

.row    { display: flex; align-items: center; }
.row-between { display: flex; align-items: center; justify-content: space-between; }
.col    { display: flex; flex-direction: column; }
.gap-1  { gap: var(--space-1); }
.gap-2  { gap: var(--space-2); }
.gap-3  { gap: var(--space-3); }
.gap-4  { gap: var(--space-4); }

.text-muted { color: var(--text-muted); }
.text-secondary { color: var(--text-secondary); }
.text-caption { font-size: var(--fs-caption); color: var(--text-muted); }
.text-h2 { font-size: var(--fs-h2); font-weight: var(--fw-semi); }
.text-h1 { font-size: var(--fs-h1); font-weight: var(--fw-bold); }


/* ================================================================
   4. CARD — basic + summary variant
================================================================ */

.card {
    background: var(--surface-1);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-lg);
    padding: var(--space-4);
    /* 🆕 v3.1.1 rev3 — removed `backdrop-filter: blur(10px)` from the
       card primitive. On iOS Safari PWA, every card running backdrop
       blur sampled the wrong source pixels on first paint — showing as
       a fuzzy halo across the top of every page. Opening any modal/
       sheet (e.g. the FAB add-transaction sheet) triggered a full
       recomposite that fixed the sampling, so the halo "disappeared"
       after the first sheet open/close; navigating to another page
       reset the first-paint and the halo came back.
       The filter was decorative on solid --surface-1 cards (no visible
       translucency to blur), so dropping it has no visual cost and
       eliminates the iOS rendering bug across the whole app. */
    /* 🆕 v3.1.0 Phase O polish — brand-tinted lift matching draft Hi-Fi */
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}

.card--clickable {
    cursor: pointer;
    transition: background 0.2s ease, transform 0.1s ease;
}

.card--clickable:active {
    background: var(--surface-2);
    transform: scale(0.99);
}

/* 🆕 v3.1.0 Phase Q Round 1 — Net Worth hero per draft §1a line 394.
   Switched from deep navy to brand-bright blue gradient (#2563eb → #1d3fae)
   with brand-tinted lift shadow. Keeps the cyan glow for depth at the top. */
/* 🆕 v3.1.1 rev4 — Net Worth "Premium Snapshot" card.
   Mid-refresh (Level 2) matching the Aurora Debit Card reference the user
   shared. Keeps the Phase Q brand-blue hero as the base, adds:
     • Deeper lift shadow + inner-border highlight (feels lifted off the page)
     • Matte dot pattern via ::after (subtle texture, no backdrop-filter)
     • Soft glow blob via ::before (depth without blur-rendering risk)
     • New .card__tag (WEALTH SNAPSHOT chip, matches the Debit tag style)
     • New .card__timestamp (AS OF {date}, bottom-right)
     • Numeric font tightened via tabular-nums for consistent digit widths. */
.card--summary {
    position: relative;       /* anchor for the balance toggle */
    /* 🆕 v3.1.1 rev4d — match the Reports page .bs-headline EXACTLY.
       Previous rev4c kept decorative extras (glow blob + matte dots +
       deeper shadow + border) that the Reports hero does NOT have, so
       the two cards still looked different. This revision strips all
       the extras down to the Reports formula so Home and Reports read
       identically side-by-side. The sparkline, chip, and timestamp
       added by Phase α still live inside the card — only the chrome
       changed. */
    background: var(--brand-gradient-hero);
    border: none;
    border-radius: 16px;
    color: #ffffff;
    padding: var(--space-5);
    box-shadow:
        0 6px 20px -4px rgba(37, 99, 235, 0.35),
        0 2px 6px -1px rgba(15, 23, 42, 0.12);
}

/* 🆕 "WEALTH SNAPSHOT" chip — tiny status tag at the top-left, next to the
   NET WORTH label. Matches the "DEBIT" tag style on the Aurora reference
   (uppercase, tracked, hairline border, semi-transparent fill). */
.card__tag {
    display: inline-block;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.88);
    border: 1px solid rgba(255, 255, 255, 0.18);
    padding: 3px 8px;
    border-radius: 999px;
    margin-left: 8px;
    vertical-align: middle;
    line-height: 1;
}

/* 🆕 "AS OF Oct 16, 2026" timestamp — bottom-right corner of the hero. */
.card__timestamp {
    position: absolute;
    bottom: var(--space-4);
    right: var(--space-5);
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    font-feature-settings: "tnum" 1;
    z-index: 2;
}
.card__timestamp strong {
    color: rgba(255, 255, 255, 0.85);
    font-weight: 500;
    margin-left: 4px;
}

/* 🆕 Tighten the big number so it reads as "amount", not "paragraph".
   tabular-nums keeps the digits a consistent width so a changing balance
   doesn't shift the layout. */
.card--summary .money--xl {
    font-feature-settings: "tnum" 1;
    letter-spacing: -0.02em;
}

/* 🆕 Eye toggle pinned to the top-RIGHT corner of the Net Worth card.
   Uses light-on-dark colors so it reads on the navy gradient. */
.balance-toggle--in-card {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
    /* 🆕 v3.1.1 rev3 — backdrop-filter removed (iOS first-paint fuzzy fix).
       The toggle sits inside the solid blue Net Worth hero card so blur
       had nothing translucent to work on — pure cost, no visible gain. */
    transition: background 0.15s ease, transform 0.08s ease;
    -webkit-tap-highlight-color: transparent;
    z-index: 2;
}
.balance-toggle--in-card:hover  { background: rgba(255, 255, 255, 0.24); }
.balance-toggle--in-card:active { transform: scale(0.92); }
.balance-toggle--in-card i { font-size: 17px; }

/* 🆕 Brighter delta colors — visible on dark navy gradient */
.card--summary .card__hint .money--income {
    color: #d9f99d;           /* lime-300 */
    font-weight: var(--fw-semi, 600);
}
.card--summary .card__hint .money--expense {
    color: #fda4af;           /* rose-300 */
    font-weight: var(--fw-semi, 600);
}
.card--summary .card__hint {
    color: rgba(255, 255, 255, 0.90);
    font-weight: var(--fw-medium, 500);
}

.card__label {
    font-size: var(--fs-caption);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-2);
}

.card__value {
    font-size: var(--fs-money);
    font-weight: var(--fw-bold);
    font-variant-numeric: tabular-nums;
}

.card__hint {
    margin-top: var(--space-2);
    font-size: var(--fs-caption);
    color: var(--text-secondary);
}


/* ================================================================
   5. LIST ITEM — transaction / account row
================================================================ */

.list-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: transparent;
    border-radius: var(--r-md);
    transition: background 0.15s ease;
    cursor: pointer;
}

.list-item:active {
    background: var(--surface-2);
}

.list-item__icon {
    flex-shrink: 0;
    width: 40px;             /* 🆕 Phase Q Round 2 — tightened to 40×40 per draft §1a line 406 */
    height: 40px;
    border-radius: 11px;     /* 🆕 Phase Q Round 2 — rounded square (was .pill) per draft */
    background: var(--surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: var(--text-primary);
}

.list-item__body {
    flex: 1;
    min-width: 0;          /* let text truncate */
}

/* 🆕 v3.1.0 Phase S §11 Round 6 — tighter typography per draft §11 lines
   2663-2665: title 13px/600, subtitle 11px muted. Reads more compact and
   matches the icon-tile scale from Round 2. */
.list-item__title {
    font-size: 13.5px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.list-item__subtitle {
    margin-top: 3px;
    font-size: 11.5px;
    color: var(--text-muted, #94a3b8);
    font-weight: var(--fw-medium, 500);
    line-height: 1.4;
}

.list-item__trailing {
    flex-shrink: 0;
    text-align: right;
}

/* 🆕 v3.1.0 Phase S §11 Round 6 — consistent chevron size + color inside
   .list-item. Matches draft §11 chevrons (color #cbd5e1, ~20px). Any
   trailing `.bx-chevron-right` inside a list-item picks up these styles. */
.list-item > .bx-chevron-right,
.list-item .list-item__chevron {
    font-size: 20px;
    color: var(--border-light, #cbd5e1);
    flex-shrink: 0;
    transition: color .14s ease, transform .14s ease;
}
.list-item:hover > .bx-chevron-right,
.list-item:hover .list-item__chevron {
    color: var(--text-muted, #94a3b8);
    transform: translateX(2px);
}

/* Date/Type group header (Today / Yesterday / ASSET / LIABILITIES) */
/* Now STICKY — stays at top while scrolling within section */
.list-group__header {
    position: sticky;
    top: 0;
    /* 🆕 v3.1.1 rev3 — solid #fff (was rgba 0.95 + backdrop blur 8px).
       The sticky header sits at the top of every list page and uses
       backdrop-filter: blur(8px). On iOS PWA that filter samples the
       wrong source pixels on first paint — the whole top of the page
       reads as a fuzzy halo until a modal (e.g. the FAB sheet) opens
       and forces a recomposite. 0.95 → 1 is visually unchanged on a
       light body gradient, and dropping the backdrop-filter kills the
       first-paint fuzziness across every list page (Activity, Accounts,
       Budget, Reports, etc.). */
    background: #fff;
    padding: var(--space-3) var(--space-4) var(--space-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semi);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    z-index: 5;
    border-bottom: 1px solid var(--border-soft);
    /* bleed to card edges so bg covers full width */
    margin: 0 calc(-1 * var(--space-2));
}


/* ================================================================
   6. BOTTOM TAB BAR — primary navigation
================================================================ */

.bottom-tab-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--tab-bar-safe);
    /* 🆕 v3.1.1 rev4 — add 12px to the padding-bottom so icons sit higher
       above the home-indicator chin (was: env(safe-area-inset-bottom)). */
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
    /* 🆕 v3.1.1 rev3 — solid #0f172a (was rgba 0.92 + backdrop blur 20px
       + saturate 140%). The tab bar is fixed on every page; its backdrop
       filter was one of the sources of iOS first-paint fuzziness. 0.92
       → 1 is a tiny visual change against solid content; losing the
       frosted-glass "see-through-to-scrollable" effect is the only
       cosmetic cost. Benefit: clean renders on every page load, no
       halo-until-FAB-opens anymore. */
    background: #0f172a;
    border-top: 1px solid var(--border-soft);
    display: flex;
    align-items: stretch;
    justify-content: space-around;
    z-index: var(--z-tab-bar);
    -webkit-user-select: none;
    user-select: none;
}

.bottom-tab-bar__item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: var(--space-2) var(--space-1);
    color: var(--text-muted);
    background: transparent;
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: color 0.15s ease;
    min-width: 44px;        /* touch target */
}

.bottom-tab-bar__icon {
    font-size: 22px;
    line-height: 1;
}

.bottom-tab-bar__label {
    font-size: 11px;
    font-weight: var(--fw-medium);
    line-height: 1;
}

.bottom-tab-bar__item:active {
    color: var(--text-secondary);
}

/* 🆕 v3.1.0 Phase Q Round 5 — active tab in brand blue (was cyan-light);
   consistent with every other active-state in the app now. */
.bottom-tab-bar__item {
    position: relative;      /* anchor for the ::before dot indicator */
}
.bottom-tab-bar__item.is-active {
    color: var(--brand-400, #60a5fa);
}

.bottom-tab-bar__item.is-active .bottom-tab-bar__icon {
    transform: scale(1.05);
    transition: transform 0.15s ease;
}

/* 🆕 Phase Q Round 5 — subtle brand indicator dot above the active tab.
   Reads clearly on the dark tab-bar; absent when the tab isn't active. */
.bottom-tab-bar__item.is-active::before {
    content: '';
    position: absolute;
    top: 4px;
    left: 50%;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--brand-400, #60a5fa);
    transform: translateX(-50%);
    box-shadow: 0 0 6px rgba(96, 165, 250, 0.75);
}

/* Centered slot for FAB — tab item รับช่องว่างไว้ */
.bottom-tab-bar__fab-slot {
    width: 64px;
    visibility: hidden;
}


/* ================================================================
   7. FAB — Floating Action Button (Add Transaction)
================================================================ */

/* 🆕 v3.1.0 Phase Q Round 6 — FAB polish: stronger brand shadow,
   icon-rotate hover micro-interaction, slightly tightened border. */
.fab {
    position: fixed;
    bottom: calc(var(--tab-bar-safe) - 28px);   /* ครึ่งหนึ่งทับ tab bar */
    left: 50%;
    transform: translateX(-50%);
    width: 56px;
    height: 56px;
    border-radius: var(--r-full);
    /* Round 1 — now matches profile-avatar via --brand-gradient
       (was --accent-gradient-2 cyan). Shadow uses the brand token stack. */
    background: var(--brand-gradient);
    color: #ffffff;
    border: 3px solid #0f172a;                  /* outline match dark tab-bar */
    box-shadow: var(--brand-shadow-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: var(--z-fab);
    transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.25s ease,
                filter 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}

.fab:hover {
    transform: translateX(-50%) translateY(-3px);
    filter: brightness(1.06) saturate(1.08);
    box-shadow: 0 14px 36px -4px rgba(37, 99, 235, 0.55),
                0 6px 14px -2px rgba(37, 99, 235, 0.35);
}

.fab:active {
    transform: translateX(-50%) scale(0.92);
    box-shadow: var(--brand-shadow-md);
}

.fab__icon {
    font-size: 28px;
    line-height: 1;
    transition: transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* 🆕 Playful hover: + icon rotates 90° (becomes ×, hints "tap to open sheet") */
.fab:hover .fab__icon {
    transform: rotate(90deg);
}
.fab:active .fab__icon {
    transform: rotate(90deg) scale(1.08);
}

@media (prefers-reduced-motion: reduce) {
    .fab, .fab__icon { transition: none; }
    .fab:hover .fab__icon,
    .fab:active .fab__icon { transform: none; }
}


/* ================================================================
   8. SHEET SYSTEM
        See section 71 (.app-sheet) for the unified bottom-sheet
        implementation. The old .bottom-sheet and .budget-sheet
        classes were removed on June 14, 2026 (Phase 4 cleanup).
================================================================ */


/* ================================================================
   8.1 SCREEN STACK — Multi-screen navigation within bottom sheet
        Used by Add Transaction: Form → Picker → Review
================================================================ */

.tx-screens {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    overflow: hidden;       /* clip slide-out screens */
}

.tx-screen {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface-1, #fff);
    transform: translateX(100%);
    transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
    visibility: hidden;
    will-change: transform;
}

.tx-screen.is-active {
    transform: translateX(0);
    visibility: visible;
    /* 🆕 2026-10-21 — Equal-z stacking is DOM-order based, so a screen that
       appears later in the partial (e.g. the Agency screens appended after
       the picker) would otherwise visually cover the picker when the user
       taps a combobox from Agency. Pulling the active screen above
       everything else makes DOM order irrelevant for the Z stack. */
    z-index: 2;
}

.tx-screen.is-prev {
    transform: translateX(-25%);   /* slight parallax behind */
    visibility: visible;
    pointer-events: none;
    z-index: 1;
}

/* Per-screen header */
.tx-screen__header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-soft);
    min-height: 56px;
}

.tx-screen__title {
    flex: 1;
    margin: 0;
    font-size: var(--fs-h2, 1.125rem);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
}

/* 🆕 Unified with .app-sheet__close visual (June 14, 2026)
   — circle 36×36, subtle bg, 22px icon. Inside .app-sheet--full
   (dark navy) they get the light-on-dark variant below. */
.tx-screen__close,
.tx-screen__back {
    flex: none;
    width: 36px; height: 36px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
    font-size: 22px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, transform 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}

/* 🆕 v3.1.0 Phase Z §3a Add-TX Round 2 — close/back hover gets brand tint
   (matches .page-header__back pattern from Phase U Round 6). */
.tx-screen__close:hover,
.tx-screen__back:hover {
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
}

.tx-screen__close:active,
.tx-screen__back:active {
    background: rgba(37, 99, 235, 0.16);
    transform: scale(0.92);
}

/* Dark variant — tx-screens live inside .app-sheet--full (dark navy panel) */
.app-sheet--full .tx-screen__close,
.app-sheet--full .tx-screen__back {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.85);
}
.app-sheet--full .tx-screen__close:hover,
.app-sheet--full .tx-screen__back:hover,
.app-sheet--full .tx-screen__close:active,
.app-sheet--full .tx-screen__back:active {
    background: rgba(255, 255, 255, 0.16);
}

/* Per-screen content */
.tx-screen__content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    padding: var(--space-4);
}

/* Picker content — no top padding, the sticky search wrap owns its own padding
   so items can scroll completely UNDER it with zero gap */
.tx-screen__content--picker {
    padding: 0 var(--space-4) var(--space-4);
}

/* ============================================
   🆕 v3.1.0 Phase G1 — Type Grid launcher (Screen 0)
   Draft §3a step 1 (4a grid). 4-col grid · 7 preset tiles · Advanced row.
   Tap tile → applySubtype() → push to Form screen.
   ============================================ */
.tx-screen__content--typegrid {
    padding: 14px 18px 20px;
}

.tx-typegrid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 9px;
    margin: 0 0 18px;
}

/* 🆕 v3.1.0 Phase Z §3a Add-TX Round 1 — typegrid tile polish:
   brand lift on hover (previously only on active) + icon scale animation
   so tiles feel tappable before you tap. */
.tx-typegrid__tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 10px 4px;
    border: none;
    border-radius: 14px;
    background: var(--pf-card, #ffffff);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
    cursor: pointer;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1),
                box-shadow 180ms ease,
                background 160ms ease;
}
.tx-typegrid__tile:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 32px -8px rgba(37, 99, 235, 0.20),
                0 4px 10px -2px rgba(15, 23, 42, 0.08);
    background: #fff;
}
.tx-typegrid__tile:active {
    transform: scale(0.94);
    background: rgba(37, 99, 235, 0.08);
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.15);
}
.tx-typegrid__tile:focus-visible {
    outline: 2px solid var(--brand-500, #3b82f6);
    outline-offset: 2px;
}

.tx-typegrid__icon {
    width: 40px; height: 40px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-size: 20px;
    transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tx-typegrid__tile:hover .tx-typegrid__icon { transform: scale(1.08); }
.tx-typegrid__tile:active .tx-typegrid__icon { transform: scale(1); }

.tx-typegrid__label {
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-primary, #1e293b);
    line-height: 1.3;
    text-align: center;
}
@media (prefers-reduced-motion: reduce) {
    .tx-typegrid__tile, .tx-typegrid__icon { transition: none; }
    .tx-typegrid__tile:hover .tx-typegrid__icon { transform: none; }
}

/* Color variants per subtype (Money-In green / Money-Out red / neutral grey) */
.tx-typegrid__tile--income  .tx-typegrid__icon { background: #f0fdf4; color: #16a34a; }
.tx-typegrid__tile--expense .tx-typegrid__icon { background: #fef2f2; color: #dc2626; }
.tx-typegrid__tile--neutral .tx-typegrid__icon { background: #f8fafc; color: #64748b; }
/* 🆕 2026-10-21 — Agency tile · purple accent so it stands apart from
   income/expense/transfer at a glance. */
.tx-typegrid__tile--agency  .tx-typegrid__icon { background: #faf5ff; color: #7c3aed; }

/* =========================================================
   AGENCY FLOW — aligned with Add-TX / Payment form design
   (brand blue tokens · .tx-field label pattern · .tx-review-hero)
   The Agency *tile* in typegrid keeps its purple accent to stand
   out from income/expense/neutral; inside the form everything
   follows the standard tx look so nothing feels foreign.
   ========================================================= */
.tx-screen__content--agency {
    padding: var(--space-4);
}
.tx-screen__title-icon {
    font-size: 20px;
    margin-right: 6px;
    vertical-align: -3px;
    color: var(--brand-700, #1d4ed8);
}

/* 🆕 2026-10-21 — Withdraw locked-destination chip · shown in place of the
   TO picker when a Cash account is detected. Non-interactive · communicates
   "money is going to Cash" visually so the user still sees the destination. */
.tx-withdraw-lock {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: var(--space-4);
    padding: 12px 14px;
    background: rgba(37, 99, 235, 0.06);
    border: 1px dashed rgba(37, 99, 235, 0.3);
    border-radius: var(--r-md);
    font-size: var(--fs-body);
    color: var(--text-primary);
}
.tx-withdraw-lock > i:first-child {
    font-size: 20px;
    color: var(--brand-700, #1d4ed8);
    flex-shrink: 0;
}
.tx-withdraw-lock__label {
    font-size: 11px;
    font-weight: 700;
    color: var(--pf-muted-2, #64748b);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.tx-withdraw-lock__name {
    flex: 1;
    font-weight: var(--fw-semi, 600);
    color: var(--brand-700, #1d4ed8);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tx-withdraw-lock__icon {
    font-size: 16px;
    color: var(--text-secondary);
    flex-shrink: 0;
}

/* Help button on screen header (reuse close size + hover) */
.tx-screen__help {
    flex: none;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(37, 99, 235, 0.08);
    border: none;
    color: var(--brand-700, #1d4ed8);
    font-size: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-right: 6px;
    transition: background 0.12s ease, transform 0.08s ease;
    -webkit-tap-highlight-color: transparent;
}
.tx-screen__help:hover  { background: rgba(37, 99, 235, 0.14); }
.tx-screen__help:active { transform: scale(0.92); background: rgba(37, 99, 235, 0.22); }

/* ===== Agency help screen · scrollable guide ===== */
.agency-help {
    padding: var(--space-4);
}
.agency-help-section {
    margin-bottom: 20px;
    padding: 14px;
    background: var(--pf-card, #fff);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-card-brand,
                0 6px 16px -6px rgba(37, 99, 235, 0.08),
                0 2px 4px -2px rgba(15, 23, 42, 0.05));
}
.agency-help-section > h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary, #0f172a);
}
.agency-help-section > h3 > i {
    color: var(--brand-700, #1d4ed8);
    font-size: 20px;
    flex-shrink: 0;
}
.agency-help-section > p,
.agency-help-section > ul,
.agency-help-section > ol {
    margin: 0 0 10px;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--text-primary);
}
.agency-help-section > ul,
.agency-help-section > ol {
    padding-left: 20px;
}
.agency-help-section > ul > li,
.agency-help-section > ol > li {
    margin-bottom: 6px;
}

/* Intro meta hint */
.agency-help-intro {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.05), rgba(37, 99, 235, 0.02));
    border-color: rgba(37, 99, 235, 0.2);
}
.agency-help-meta {
    font-size: 12.5px !important;
    color: var(--text-secondary) !important;
    font-style: italic;
    margin-top: 4px !important;
}

/* Per-situation header · icon + title inline */
.agency-help-sit-title {
    display: flex !important;
    align-items: center !important;
    gap: 10px !important;
    margin-bottom: 10px !important;
}
.agency-help-sit-title > .agency-chooser-item__icon {
    width: 36px;
    height: 36px;
    font-size: 18px;
}
.agency-help-when {
    font-size: 13px !important;
    color: var(--text-secondary) !important;
    margin-bottom: 10px !important;
}
.agency-help-when strong { color: var(--text-primary); }

/* Example block inside a section */
.agency-help-example {
    margin: 10px 0;
    padding: 10px 12px;
    background: rgba(15, 23, 42, 0.03);
    border-left: 3px solid var(--brand-500, #3b82f6);
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.agency-help-example p {
    margin: 0 0 6px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-primary);
}
.agency-help-example p:last-child { margin-bottom: 0; }
.agency-help-example__scenario { font-weight: var(--fw-semi, 600); }
.agency-help-example__steps    { color: var(--text-secondary); }
.agency-help-example__result em { color: var(--brand-700, #1d4ed8); font-style: normal; font-weight: 600; }

/* Warning variant (amber) · for surplus/shortfall */
.agency-help-example--warn {
    background: rgba(245, 158, 11, 0.08);
    border-left-color: #f59e0b;
}
.agency-help-example--warn ul {
    margin: 6px 0 0;
    padding-left: 18px;
    font-size: 12.5px;
}

/* Inline chip (used in intro) */
.agency-help-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px; height: 24px;
    background: rgba(37, 99, 235, 0.08);
    color: var(--brand-700, #1d4ed8);
    border-radius: 6px;
    vertical-align: middle;
    margin: 0 2px;
}

/* Tip line (follows examples) */
.agency-help-tip {
    margin-top: 10px !important;
    padding: 8px 10px;
    background: rgba(37, 99, 235, 0.06);
    border-radius: var(--r-sm);
    font-size: 12.5px !important;
    color: var(--text-secondary) !important;
}

/* Full-flow ordered list with per-step state */
.agency-help-flow {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.04), rgba(37, 99, 235, 0.01));
    border-color: rgba(37, 99, 235, 0.18);
}
.agency-help-flow-list {
    padding-left: 24px !important;
}
.agency-help-flow-list > li {
    margin-bottom: 10px !important;
    padding-left: 2px;
    font-size: 13px;
    line-height: 1.5;
}
.agency-help-flow-state {
    display: block;
    margin-top: 2px;
    padding: 4px 8px;
    background: rgba(15, 23, 42, 0.04);
    border-radius: var(--r-sm);
    font-size: 11.5px;
    color: var(--text-secondary);
    font-family: 'IBM Plex Mono', monospace;
}

/* ===== Agency chooser screen · 4 full-row list items with icon + desc ===== */
.agency-chooser-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.agency-chooser-item {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    padding: 14px 14px;
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    background: var(--pf-card, #fff);
    text-align: left;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.15s ease, border-color 0.15s ease;
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.10),
                0 2px 6px -2px rgba(15, 23, 42, 0.05));
    -webkit-tap-highlight-color: transparent;
}
.agency-chooser-item:hover {
    transform: translateY(-1px);
    border-color: rgba(37, 99, 235, 0.3);
    box-shadow: 0 14px 30px -10px rgba(37, 99, 235, 0.18),
                0 4px 8px -2px rgba(15, 23, 42, 0.08);
}
.agency-chooser-item:active {
    transform: scale(0.98);
    background: rgba(37, 99, 235, 0.03);
}

.agency-chooser-item__icon {
    flex-shrink: 0;
    width: 44px; height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    font-size: 22px;
}
.agency-chooser-item__icon--pay     { background: rgba(37, 99, 235, 0.1);  color: var(--brand-700, #1d4ed8); }
.agency-chooser-item__icon--collect { background: #f0fdf4;                 color: #16a34a; }
.agency-chooser-item__icon--receive { background: rgba(37, 99, 235, 0.1);  color: var(--brand-700, #1d4ed8); }
.agency-chooser-item__icon--settle  { background: rgba(100, 116, 139, 0.12); color: #475569; }

.agency-chooser-item__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.agency-chooser-item__name {
    font-size: var(--fs-body);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
    line-height: 1.3;
}
.agency-chooser-item__desc {
    font-size: var(--fs-caption);
    color: var(--text-secondary);
    line-height: 1.4;
}
.agency-chooser-item__chev {
    flex-shrink: 0;
    font-size: 22px;
    color: var(--text-secondary);
    transition: transform 0.15s ease;
}
.agency-chooser-item:hover .agency-chooser-item__chev { transform: translateX(2px); color: var(--brand-700, #1d4ed8); }

/* Agency form fields — rely on existing .tx-field + .tx-field__label spacing */
.tx-screen__content--agency .agency-amount-wrap,
.tx-screen__content--agency .agency-account-wrap,
.tx-screen__content--agency label.agency-label {
    display: block;
    margin-top: var(--space-4);
}
/* Labels wear the exact same uppercase caption treatment as other tx forms */
.agency-label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    color: var(--pf-muted-2, #64748b);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: 6px;
}

/* Person row — select + "Add new" square plus button */
.agency-person-row {
    display: flex;
    gap: 8px;
}
.agency-person { flex: 1; }
.agency-add-person {
    width: 48px; height: 48px;
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1.5px dashed rgba(37, 99, 235, 0.35);
    background: rgba(37, 99, 235, 0.05);
    color: var(--brand-700, #1d4ed8);
    border-radius: var(--r-md);
    cursor: pointer;
    transition: background 0.12s ease, transform 0.08s ease, border-color 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}
.agency-add-person:hover  { background: rgba(37, 99, 235, 0.1);  border-color: var(--brand-500, #3b82f6); }
.agency-add-person:active { transform: scale(0.92); background: rgba(37, 99, 235, 0.16); }
.agency-add-person i { font-size: 22px; }

/* Balance hint — brand-tinted info strip (matches .tx-balance-hint pattern) */
.agency-balance-hint {
    margin: 8px 0 0;
    padding: 8px 12px;
    background: rgba(37, 99, 235, 0.06);
    border-left: 3px solid var(--brand-500, #3b82f6);
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
    font-size: var(--fs-caption);
    color: var(--text-secondary);
}

/* Error strip — matches .totp-err / toast error color */
.agency-err {
    margin-top: var(--space-3);
    padding: 8px 12px;
    background: rgba(239, 68, 68, 0.08);
    color: #dc2626;
    border-radius: var(--r-sm);
    font-size: var(--fs-caption);
}

/* Surplus / shortfall banner — amber, matches .tx-balance-hint--warn tone */
.agency-diff {
    margin-top: var(--space-4);
    padding: 12px 14px;
    background: rgba(245, 158, 11, 0.08);
    border: 1px solid rgba(245, 158, 11, 0.3);
    border-radius: var(--r-md);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.agency-diff__msg {
    margin: 0;
    font-size: var(--fs-caption);
    color: #92400e;
    font-weight: var(--fw-semi);
}
.agency-diff__opts {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.agency-diff__opt {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--fs-caption);
    color: var(--text-primary);
    cursor: pointer;
}
.agency-diff__opt input[type="radio"] {
    width: 16px; height: 16px;
    accent-color: var(--brand-600, #2563eb);
}
.agency-diff__cat { margin-top: 2px; }

/* ===== Agency review screen — reuse .tx-review-hero look ===== */
.agency-review-hero {
    text-align: center;
    padding: 22px 18px;
    margin: var(--space-4);
    border-radius: 16px;
    background: var(--brand-gradient-deep);
    color: #fff;
    box-shadow: 0 10px 28px -4px rgba(37, 99, 235, 0.35),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
    animation: txReviewHeroPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@media (prefers-reduced-motion: reduce) {
    .agency-review-hero { animation: none; }
}
.agency-review-chip {
    display: inline-block;
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: 99px;
    padding: 3px 12px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #fff;
}
.agency-review-amount {
    margin: 14px 0 4px;
    font-size: 28px;
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.agency-review-person {
    margin: 0;
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.82);
}

.agency-review-lines {
    padding: 0 var(--space-4);
}
.agency-review-heading {
    margin: 0 0 10px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--pf-muted-2, #64748b);
    font-weight: 700;
}
.agency-review-leg { margin-bottom: 8px; }

/* Each ledger line in review — adopts .card shadow pattern */
.agency-leg {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--pf-card, #fff);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.12),
                0 2px 8px -2px rgba(15, 23, 42, 0.05));
}
.agency-leg__dr-cr {
    flex-shrink: 0;
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
}
.agency-leg__dr-cr--dr { background: rgba(37, 99, 235, 0.12); color: var(--brand-700, #1d4ed8); }
.agency-leg__dr-cr--cr { background: rgba(220, 38, 38, 0.12); color: #b91c1c; }
.agency-leg__body { flex: 1; min-width: 0; }
.agency-leg__account {
    font-size: var(--fs-body);
    font-weight: var(--fw-semi);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.agency-leg__hint {
    font-size: 11.5px;
    color: var(--text-secondary);
    margin-top: 2px;
}
.agency-leg__amount {
    font-size: var(--fs-body);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
}

.agency-review-note {
    margin: var(--space-4) var(--space-4) 0;
    padding: 10px 12px;
    background: var(--surface-2);
    border-radius: var(--r-sm);
    font-size: var(--fs-caption);
    font-style: italic;
    color: var(--text-secondary);
}

/* Advanced section — "Custom Dr/Cr multi-line" full-width row */
.tx-typegrid__section-heading {
    margin: 0 2px 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--pf-muted-2, #94a3b8);
}
/* 🆕 v3.1.0 Phase Z §3a Add-TX Round 2 — advanced row (Custom Dr/Cr):
   brand lift + hover + chevron slide + icon color intensify. Pattern matches
   .list-item row behavior for cross-sheet consistency. */
.tx-typegrid__advanced-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    border: none;
    border-radius: 14px;
    background: var(--pf-card, #ffffff);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
    cursor: pointer;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1),
                box-shadow 180ms ease,
                background 160ms ease;
}
.tx-typegrid__advanced-row:hover {
    transform: translateY(-1px);
    box-shadow: 0 14px 30px -8px rgba(37, 99, 235, 0.20),
                0 4px 10px -2px rgba(15, 23, 42, 0.08);
}
.tx-typegrid__advanced-row:hover .tx-typegrid__advanced-icon {
    background: var(--brand-50, #eef2ff);
    color: var(--brand-600, #2563eb);
}
.tx-typegrid__advanced-row:hover .tx-typegrid__advanced-chev {
    color: var(--brand-600, #2563eb);
    transform: translateX(3px);
}
.tx-typegrid__advanced-row:active {
    transform: scale(0.98);
    background: rgba(37, 99, 235, 0.06);
}
.tx-typegrid__advanced-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    background: var(--surface-2, #f1f5f9);
    color: #64748b;
    display: grid; place-items: center;
    font-size: 18px;
    flex-shrink: 0;
    transition: background .14s ease, color .14s ease;
}
.tx-typegrid__advanced-label {
    flex: 1;
    font-size: 13.5px;
    color: var(--text-primary, #0f172a);
    font-weight: 600;
    text-align: left;
}
.tx-typegrid__advanced-chev {
    color: var(--border-light, #cbd5e1);
    font-size: 20px;
    transition: color .14s ease, transform .14s ease;
}

/* Typegrid footer — single-button Close, subtle grey */
.tx-screen__footer--typegrid {
    display: flex;
    justify-content: center;
}
.tx-typegrid__cancel {
    min-width: 140px;
    justify-content: center;
}

/* 🆕 Per-screen footer — padding aligned with .tx-screen__footer--view
   (12px / 22px / 16px + safe-area-inset-bottom) so EVERY footer variant
   (view, is-split, --split review) has identical total height — including
   safe-area on iOS home-indicator devices. */
.tx-screen__footer {
    flex: 0 0 auto;
    padding: 12px 22px calc(16px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border-soft);
    background: var(--surface-1, #fff);
}

/* 🆕 UNIFIED height with .tx-screen__footer--view (44px via .pw-btn).
   Form footer (is-split: Delete | Save) and View footer (single Delete)
   now share the same button height for visual consistency. */
.tx-screen__footer .btn--primary,
.tx-screen__footer .btn--secondary {
    width: 100%;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 20px;
    border-radius: 12px;
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.18s ease, background 0.15s ease, border-color 0.15s ease, filter 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    line-height: 1;
}

.tx-screen__footer .btn--primary i,
.tx-screen__footer .btn--secondary i {
    font-size: 17px;
    line-height: 1;
}

/* PRIMARY — filled gradient brand button */
.tx-screen__footer .btn--primary {
    background: var(--brand-gradient);
    color: #ffffff;
    border: 1px solid transparent;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
}

.tx-screen__footer .btn--primary:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(59, 130, 246, 0.38);
}

.tx-screen__footer .btn--primary:active:not(:disabled) {
    transform: translateY(0) scale(0.99);
    box-shadow: 0 2px 6px rgba(59, 130, 246, 0.32);
}

.tx-screen__footer .btn--primary:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    box-shadow: none;
}

/* SECONDARY — 🆕 v3.1.0 Phase G6d: draft §5 line 630 style
   Grey filled bg (no border) + muted text → clear hierarchy vs primary Save */
.tx-screen__footer .btn--secondary {
    background: #f8fafc;
    color: #64748b;
    border: 1px solid transparent;
    box-shadow: none;
}

.tx-screen__footer .btn--secondary:hover:not(:disabled) {
    background: #eef2f7;
    color: #475569;
    transform: translateY(-1px);
}

.tx-screen__footer .btn--secondary:active:not(:disabled) {
    transform: translateY(0) scale(0.99);
    background: #e2e8f0;
}

.tx-screen__footer .btn--secondary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Split footer — Edit + Confirm side-by-side, equal width */
.tx-screen__footer--split {
    display: flex;
    gap: var(--space-3);
    align-items: stretch;
}

.tx-screen__footer--split .btn--primary,
.tx-screen__footer--split .btn--secondary {
    flex: 1;
    width: auto;
}

/* 🆕 v3.1.0 Phase G6d — draft §5 line 630: Cancel = auto content width,
   Save fills the rest. Save gets max visual weight as primary CTA. */
.tx-screen__footer--split .btn--secondary {
    flex: 0 0 auto;
    padding: 0 16px;
}
.tx-screen__footer--split .btn--primary {
    flex: 1 1 auto;
}


/* ================================================================
   8.2 ACCOUNT PICKER SCREEN — Big search + grouped item list
================================================================ */

/* Sticky search wrap — full-bleed solid bar; items disappear behind it when scrolled */
.picker-search-wrap {
    position: sticky;
    top: 0;
    z-index: 5;
    /* Full-bleed: cancel parent .tx-screen__content--picker side padding */
    margin: 0 calc(var(--space-4) * -1) var(--space-3);
    padding: var(--space-3) var(--space-4) var(--space-3);
    /* OPAQUE background — items scroll UNDER, never show through */
    background: var(--surface-1, #fff);
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
    box-shadow: 0 4px 12px -8px rgba(15, 23, 42, 0.18);
    /* Make input itself the positioning context for the icon */
    display: flex;
    align-items: center;
}

.picker-search-icon {
    position: absolute;
    left: calc(var(--space-4) + var(--space-3));
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-secondary);
    font-size: 20px;
    pointer-events: none;
    z-index: 1;
}

.picker-search {
    width: 100%;
    height: 44px;
    padding: 0 var(--space-3) 0 44px;
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    background: var(--surface-2);
    font-size: var(--fs-body);
    color: var(--text-primary);
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
}

.picker-search:focus {
    outline: none;
    border-color: var(--accent-blue, #3b82f6);
    background: var(--surface-1, #fff);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}

.picker-search::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

.picker-list {
    display: flex;
    flex-direction: column;
}

.picker-group {
    margin-bottom: var(--space-3);
}

.picker-group__title {
    font-size: 11px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    padding: var(--space-2) var(--space-1);
    margin: 0 0 var(--space-1);
}

/* 🆕 v3.1.0 Phase AC account-picker Round 1 — picker-item lift + hover
   with brand lift and better selected state. */
.picker-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3);
    background: var(--surface-1, #fff);
    border: 1.5px solid var(--border-soft, #eef1f5);
    border-radius: var(--r-md);
    margin-bottom: var(--space-2);
    cursor: pointer;
    text-align: left;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.03);
    transition: background .18s ease, border-color .18s ease,
                box-shadow .18s ease, transform .14s cubic-bezier(0.16, 1, 0.3, 1);
    -webkit-tap-highlight-color: transparent;
    font-family: inherit;
}
.picker-item:hover {
    background: var(--surface-2);
    border-color: #93c5fd;
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.16),
                0 2px 6px -1px rgba(15, 23, 42, 0.06);
    transform: translateY(-1px);
}
.picker-item:active {
    transform: scale(0.98);
}
.picker-item.is-selected {
    border-color: var(--brand-500, #3b82f6);
    background: rgba(37, 99, 235, 0.08);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.14),
                0 4px 12px -4px rgba(37, 99, 235, 0.22);
}

.picker-item__badge {
    flex-shrink: 0;
    padding: 2px 8px;
    border-radius: var(--r-sm);
    font-size: 10px;
    font-weight: var(--fw-bold, 700);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    min-width: 56px;
    text-align: center;
}

.picker-item__name {
    flex: 1;
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.picker-item__balance {
    font-size: var(--fs-caption, 0.75rem);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.picker-item__check {
    color: var(--accent-blue, #3b82f6);
    font-size: 20px;
    margin-left: var(--space-1);
}

.picker-empty {
    text-align: center;
    padding: var(--space-6) var(--space-4);
    color: var(--text-secondary);
}

.picker-empty i {
    font-size: 48px;
    opacity: 0.4;
    display: block;
    margin-bottom: var(--space-2);
}

.picker-empty p {
    margin: 0;
    font-size: var(--fs-body);
}

/* ============================================
   🆕 v3.1.0 Phase H — Account Picker (draft §24 Hi-Fi)
   Adds: Recent chip row · "+ Add new" sticky footer
   ============================================ */

/* Recent chips section (top-3 most recently selected accounts of matching type) */
/* 🆕 v3.1.0 Phase G10 rev2 — Recent uses .picker-item (identical to main list).
   Section separated from list below by a divider line. Hidden while searching. */
.picker-recent {
    /* 🆕 v3.1.0 Phase G10 rev6 rev2 — bg tint removed per user request.
       Keep clock icons + stronger 2px divider as the visual distinction. */
    margin: 0 0 12px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--pf-line, #eaedf1);
}
/* 🆕 v3.1.0 Phase G10 rev3 — safety rule ensuring [hidden] wins over any inherited display */
.picker-recent[hidden] {
    display: none !important;
}
.picker-recent__heading {
    /* 🆕 v3.1.0 Phase G10 rev6 — heading now flexes with a leading clock icon */
    margin: 0 0 8px;
    padding-left: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--pf-muted-2, #94a3b8);
}
.picker-recent__heading > i {
    font-size: 12px;
    color: var(--pf-muted-2, #94a3b8);
    line-height: 1;
}
/* 🆕 v3.1.0 Phase G10 rev6 — Clock icon prepended to each recent .picker-item.
   Placed BEFORE the badge so users read "🕒 [BANK] Kasikorn ..." top-to-bottom. */
.picker-recent__mark {
    font-size: 14px;
    color: #94a3b8;
    flex-shrink: 0;
    line-height: 1;
    margin-right: 2px;
}
.picker-recent__row {
    display: flex;
    flex-direction: column;
    /* 🆕 v3.1.0 Phase G10 rev5 — match main list spacing (var(--space-2) = 8px between items) */
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}
.picker-recent__cell {
    display: block;
    min-width: 0;
}
/* Recent .picker-item: drop its own margin-bottom since .picker-recent__row uses `gap`.
   Prevents double spacing between items + keeps last item flush with divider. */
.picker-recent .picker-item {
    margin-bottom: 0;
}

/* Picker footer — "+ Add new" sticky action */
.tx-screen__footer--picker {
    padding: 12px 18px calc(16px + env(safe-area-inset-bottom, 0px));
}
.picker-new-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    height: 48px;
    border: 1.5px dashed #93c5fd;
    border-radius: 12px;
    background: #f8fafc;
    color: var(--pf-primary, #2563eb);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1)),
                border-color 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1)),
                transform 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.picker-new-btn i { font-size: 18px; }
.picker-new-btn:hover {
    background: #eff6ff;
    border-color: var(--pf-primary, #2563eb);
}
.picker-new-btn:active { transform: scale(0.99); }

/* Ensure the account form sheet floats ABOVE the picker sheet (nested).
   .app-sheet base has z-index:var(--z-sheet,1200). Since acctSheet opens
   AFTER addSheet is already open, we lift its whole stacking context.
   🆕 v3.1.0 Phase H hotfix — z-index MUST stay under VKB layers so the
   virtual keyboard/NumPad can paint on top of the form:
     addSheet 1200 < acctSheet 5000 < NumPad 9500 < TextKeyboard 9600 < Toast 9999
   Full z-index scale refactor deferred to Phase O (design token pass). */
#acctSheet {
    z-index: 5000 !important;
}
#acctSheet .app-sheet__panel {
    z-index: 5000;
}


/* ================================================================
   8.3 REVIEW SCREEN — Read-only confirmation page
================================================================ */

/* 🆕 v3.1.0 Phase O §15 — gradient hero per draft §3a Review (Step 4).
   Replaces the stacked Type/Amount/Date rows at the top of the review
   body with a single bold summary card. */
/* 🆕 v3.1.0 Phase Z §3a Round 4 — Review hero animations:
   bounce-in on screen reveal (0.5s spring), 2-layer type-tinted shadow
   for better depth over the body background. */
.tx-review-hero {
    text-align: center;
    padding: 22px 18px;
    margin-bottom: 18px;
    border-radius: 16px;
    background: var(--brand-gradient-deep);
    color: #fff;
    box-shadow: 0 10px 28px -4px rgba(37, 99, 235, 0.35),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
    animation: txReviewHeroPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tx-review-hero--expense {
    background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
    box-shadow: 0 10px 28px -4px rgba(220, 38, 38, 0.35),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
}
.tx-review-hero--income {
    background: linear-gradient(135deg, #059669 0%, #065f46 100%);
    box-shadow: 0 10px 28px -4px rgba(5, 150, 105, 0.35),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
}
.tx-review-hero--transfer {
    background: linear-gradient(135deg, #0891b2 0%, #0e7490 100%);
    box-shadow: 0 10px 28px -4px rgba(8, 145, 178, 0.35),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
}
@keyframes txReviewHeroPop {
    0%   { opacity: 0; transform: scale(0.9) translateY(10px); }
    60%  { opacity: 1; transform: scale(1.02) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .tx-review-hero { animation: none; }
}
.tx-review-hero__chip {
    display: inline-block;
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: 99px;
    padding: 3px 12px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #fff;
}
.tx-review-hero__amount {
    margin: 14px 0 4px;
    font-size: 28px;
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.tx-review-hero__date {
    margin: 0;
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.82);
}

.review-meta {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin-bottom: var(--space-4);
}

.review-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border-soft);
}

.review-row:last-child {
    border-bottom: none;
}

.review-row__label {
    flex-shrink: 0;
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: var(--fw-semi, 600);
    text-transform: uppercase;
    letter-spacing: 0.6px;
}

.review-row__value {
    text-align: right;
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
    word-break: break-word;
}

.review-row__value.is-big {
    font-size: var(--fs-h2, 1.25rem);
    font-weight: var(--fw-bold, 700);
}

.review-section {
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: 2px solid var(--border-soft);
}

.review-section__title {
    font-size: 13px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin: 0 0 var(--space-2);
}

.review-line {
    display: grid;
    grid-template-columns: 48px 1fr auto;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) 0;
    border-bottom: 1px dashed var(--border-soft);
}

.review-line:last-of-type {
    border-bottom: none;
}

.review-line__entry {
    padding: 4px 0;
    border-radius: var(--r-sm);
    text-align: center;
    font-weight: var(--fw-bold, 700);
    font-size: 13px;
    letter-spacing: 0.3px;
}

.review-line__entry.is-dr {
    background: rgba(59, 130, 246, 0.12);
    color: #1d4ed8;
}

.review-line__entry.is-cr {
    background: rgba(16, 185, 129, 0.12);
    color: #047857;
}

.review-line__name {
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.review-line__amount {
    font-variant-numeric: tabular-nums;
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
}

.review-totals {
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 2px solid var(--border-soft);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.review-total-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-variant-numeric: tabular-nums;
}

.review-total-row__label {
    color: var(--text-secondary);
    font-weight: var(--fw-medium, 500);
}

.review-total-row__value {
    font-weight: var(--fw-bold, 700);
    color: var(--text-primary);
}

/* 🆕 v3.1.0 Phase Z §3a Round 4 — balance check: deeper tint + glow +
   icon color intensity + check-mark bounce on balanced state. */
.review-balance-check {
    margin-top: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--r-md);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: var(--fw-semi, 600);
    font-size: 13.5px;
    transition: background .18s ease, border-color .18s ease;
}
.review-balance-check i { font-size: 20px; }

.review-balance-check.is-balanced {
    background: #f0fdf4;
    color: #047857;
    border: 1.5px solid #86efac;
    box-shadow: 0 4px 14px -4px rgba(16, 185, 129, 0.22);
}
.review-balance-check.is-balanced i {
    color: #059669;
    animation: reviewBalanceCheckPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes reviewBalanceCheckPop {
    0%   { transform: scale(0.4) rotate(-20deg); }
    60%  { transform: scale(1.2) rotate(5deg); }
    100% { transform: scale(1) rotate(0); }
}

.review-balance-check.is-unbalanced {
    background: #fef2f2;
    color: #991b1b;
    border: 1.5px solid #fca5a5;
    box-shadow: 0 4px 14px -4px rgba(220, 38, 38, 0.22);
    animation: reviewUnbalancedShake 0.4s ease;
}
.review-balance-check.is-unbalanced i {
    color: #dc2626;
}
@keyframes reviewUnbalancedShake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
    .review-balance-check.is-balanced i,
    .review-balance-check.is-unbalanced { animation: none; }
}

.review-warn {
    margin-top: var(--space-4);
    padding: var(--space-3);
    border-radius: var(--r-md);
    background: rgba(251, 191, 36, 0.1);
    border: 1px solid rgba(251, 191, 36, 0.35);
    color: #92400e;
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    font-size: var(--fs-caption, 0.875rem);
}

.review-warn i {
    font-size: 20px;
    flex-shrink: 0;
}


/* ================================================================
   9. CHIP — filter / category tag
================================================================ */

.chip-row {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    padding: var(--space-2) var(--space-4);
    margin: 0 calc(var(--space-4) * -1);   /* bleed full width */
    scrollbar-width: none;
}

.chip-row::-webkit-scrollbar { display: none; }

.chip {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 6px 14px;
    height: 32px;
    border-radius: var(--r-full);
    background: var(--surface-2);
    border: 1px solid transparent;
    color: var(--text-secondary);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
}

.chip:active {
    transform: scale(0.96);
}

.chip.is-active {
    background: rgba(6, 182, 212, 0.15);
    border-color: rgba(6, 182, 212, 0.45);
    color: var(--accent-cyan-light);
}

.chip__icon { font-size: 14px; }


/* ================================================================
   10. SEGMENTED CONTROL — Income/Expense/Transfer
================================================================ */

.segmented {
    display: inline-flex;
    width: 100%;
    padding: 3px;
    border-radius: var(--r-md);
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
}

/* HTML `hidden` attribute must beat display:inline-flex above */
.segmented[hidden] {
    display: none !important;
}

.segmented__option {
    flex: 1;
    padding: var(--space-2) var(--space-3);
    background: transparent;
    border: none;
    border-radius: calc(var(--r-md) - 3px);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semi);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
}

.segmented__option.is-active {
    background: var(--brand-gradient);
    color: #ffffff;
    box-shadow: var(--elev-1);
}


/* ================================================================
   11. SKELETON LOADER
================================================================ */

.skeleton {
    background: linear-gradient(
        90deg,
        var(--surface-2) 0%,
        var(--surface-3) 50%,
        var(--surface-2) 100%
    );
    background-size: 200% 100%;
    animation: skeletonShimmer 1.4s ease-in-out infinite;
    border-radius: var(--r-sm);
}

.skeleton--line  { height: 14px; }
.skeleton--title { height: 22px; width: 50%; }
.skeleton--circle{ border-radius: var(--r-full); }
.skeleton--card  { height: 80px; }

/* 🆕 v3.1.0 Phase O polish sweep (round 3) — new skeleton variants */
.skeleton--pill   { height: 24px; width: 72px; border-radius: 999px; }
.skeleton--amount { height: 28px; width: 140px; border-radius: 6px; }
.skeleton--icon   { width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0; }
.skeleton--row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1.5px solid var(--border-soft, #eaedf1);
    background: transparent;
    animation: none; /* parent children shimmer independently */
}
.skeleton--row:last-child { border-bottom: 0; }
.skeleton--row .skeleton__body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* 🆕 v3.1.0 Phase O polish round 4 — Chart.js canvas skeletons.
   Positioned absolute over the (initially empty) canvas; auto-hidden
   using the :has() selector once Chart.js writes inline width/height
   onto the canvas. No JS hook needed. */
.report-chart-wrap,
.report-donut-wrap { position: relative; }

.chart-skel {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    transition: opacity 0.25s ease;
}
/* Chart.js sets inline style="display: block; ...; width: Xpx; height: Ypx;"
   on the canvas once the chart has rendered. We use that as our ready signal. */
.report-chart-wrap:has(canvas[style*="width"]) .chart-skel,
.report-donut-wrap:has(canvas[style*="width"]) .chart-skel {
    opacity: 0;
    visibility: hidden;
}

/* Bars variant — monthly trend chart */
.chart-skel--bars {
    display: flex;
    align-items: flex-end;
    justify-content: space-around;
    gap: 10%;
    padding: 10px 8px;
}
.chart-skel--bars span {
    flex: 1;
    max-width: 32px;
    border-radius: 6px 6px 0 0;
    background: linear-gradient(
        90deg,
        var(--surface-2) 0%,
        var(--surface-3) 50%,
        var(--surface-2) 100%
    );
    background-size: 200% 100%;
    animation: skeletonShimmer 1.4s ease-in-out infinite;
}

/* Donut variant — ring with transparent center */
.chart-skel--donut {
    display: grid;
    place-items: center;
}
.chart-skel--donut::before {
    content: '';
    width: 80%;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    background: conic-gradient(
        var(--surface-3) 0 25%,
        var(--surface-2) 25% 50%,
        var(--surface-3) 50% 75%,
        var(--surface-2) 75% 100%
    );
    mask: radial-gradient(circle, transparent 42%, #000 44%);
    -webkit-mask: radial-gradient(circle, transparent 42%, #000 44%);
    animation: skeletonSpin 2.4s linear infinite;
}
@keyframes skeletonSpin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .chart-skel--bars span,
    .chart-skel--donut::before { animation: none !important; }
}

@keyframes skeletonShimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}


/* ================================================================
   12. EMPTY STATE
================================================================ */

.empty-state {
    text-align: center;
    padding: var(--space-12) var(--space-4);
    color: var(--text-secondary);
}

.empty-state__icon {
    font-size: 56px;
    color: var(--text-muted);
    margin-bottom: var(--space-3);
    display: block;
}

.empty-state__title {
    font-size: var(--fs-h2);
    font-weight: var(--fw-semi);
    color: var(--text-primary);
    margin: 0 0 var(--space-2);
}

.empty-state__message {
    font-size: var(--fs-body);
    color: var(--text-secondary);
    margin: 0 0 var(--space-5);
    max-width: 320px;
    margin-left: auto;
    margin-right: auto;
}


/* ================================================================
   13. NUMBER PAD (สำหรับ amount input ใน Add Transaction)
================================================================ */

.number-pad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
    padding: var(--space-3);
}

.number-pad__key {
    height: 56px;
    border-radius: var(--r-md);
    background: var(--surface-2);
    border: none;
    color: var(--text-primary);
    font-size: 22px;
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: background 0.1s ease;
}

.number-pad__key:active {
    background: var(--surface-3);
}


/* ================================================================
   12b. ADD TRANSACTION FORM — Simple + Advanced
================================================================ */

/* 🆕 v3.1.0 Phase G6a — Amount input restyle per draft §5 line 624:
   [฿ bold blue 15px] [mono right-align 22px input] inside bordered box.
   Also #txSimple gets display:flex so per-subtype flex-order (Deposit) works. */
#txSimple {
    display: flex;
    flex-direction: column;
}
.tx-amount-wrap {
    display: block;
    text-align: left;
    /* 🆕 v3.1.0 Phase G6a fix — match .tx-field margin pattern (space-4 top)
       so Amount doesn't visually stick to the field above (FEE/Account). */
    margin: var(--space-4) 0 var(--space-3);
}
.tx-amount-label {
    /* 🆕 v3.1.0 Phase G6a fix7 — RESTORED to bold uppercase style (user pref).
       .tx-field__label below is updated to match this — all form labels consistent. */
    display: block;
    font-size: 11px;
    font-weight: 700;
    color: var(--pf-muted-2, #64748b);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: 6px;
}
.tx-amount-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--pf-card, #ffffff);
    border: 1.5px solid var(--border-soft, #eaedf1);
    border-radius: 12px;
    transition: border-color 160ms ease, box-shadow 180ms ease, background 160ms ease;
}
/* 🆕 v3.1.0 Phase Z §3a Round 3 — deeper 2-tone focus glow (match
   login input + security-method rename input). */
.tx-amount-row:focus-within {
    border-color: var(--brand-500, #3b82f6);
    background: var(--surface-1, #fff);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12),
                0 4px 12px -4px rgba(37, 99, 235, 0.22);
}
.tx-amount-currency {
    font-size: 15px;
    color: var(--pf-primary, #2563eb);
    font-weight: 700;
    flex-shrink: 0;
}
.tx-amount-input {
    flex: 1;
    /* 🆕 v3.1.0 Phase G6a fix — reset ALL UA input styling.
       Some browsers (particularly iOS Safari) render an inset border/background
       on <input type="text"> even when CSS says border:none — appearance:none
       forces the native "field" look off completely. box-shadow:none clears any
       inset shadow that some browsers use to simulate the border. */
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    border: none;
    outline: none;
    box-shadow: none;
    color: var(--pf-ink, #0e1f44);
    font-family: 'IBM Plex Mono', monospace;
    font-size: 22px;
    font-weight: 700;
    text-align: right;
    padding: 0;
    font-variant-numeric: tabular-nums;
    min-width: 0;
}
.tx-amount-input::placeholder { color: #cbd5e1; font-weight: 500; }

/* 🆕 v3.1.0 Phase G6a fix3 — ID-based override (specificity 1,0,0 — guaranteed win).
   Previous class-based override wasn't beating the shared .is-kb-active rule in
   some browsers/scenarios. #txAmount targets the specific input directly, forcing
   transparent bg/no border under ALL states (idle, hover, focus, kb-active). */
#txAmount,
#txAmount:focus,
#txAmount.is-kb-active,
#txAmount:focus-visible {
    -webkit-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
}

/* 🟢 Item 1: hide placeholder on focus */
.tx-amount-input:focus::placeholder {
    color: transparent;
}

/* 🟡 Balance warning under amount — shown only when amount fails validation */
.tx-amount-warn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.4);
    color: #b45309;
    border-radius: var(--r-sm);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
}
.tx-amount-warn i { font-size: 16px; }
/* Force [hidden] attribute to override display:flex above */
.tx-amount-warn[hidden] { display: none !important; }

/* 🛡️ DEFENSIVE — any element with the HTML `hidden` attribute must be hidden,
   regardless of how aggressive its class's display: flex/grid rule is.
   This prevents the "shows when it shouldn't" bug class-wide. */
[hidden] { display: none !important; }

.tx-field { margin-top: var(--space-4); }
.tx-field__label {
    /* 🆕 v3.1.0 Phase G6a fix7 — Match .tx-amount-label bold uppercase style
       (user pref: labels bold + smaller/tighter for better visual hierarchy).
       Affects all forms using .tx-field__label (Add Tx + Account form). */
    display: block;
    font-size: 11px;
    font-weight: 700;
    color: var(--pf-muted-2, #64748b);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: 6px;
}
/* 🆕 v3.1.0 Phase Z §3a Round 3 — form inputs: 1→1.5 border + brand focus
   glow matching login/security-method rename input pattern. */
.tx-select, .tx-input {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    height: 48px;
    padding: 0 var(--space-3);
    background: var(--surface-2);
    border: 1.5px solid var(--border-soft);
    border-radius: var(--r-md);
    color: var(--text-primary);
    font-size: var(--fs-body);
    color-scheme: light;
    font-family: inherit;
    font-weight: var(--fw-medium, 500);
    transition: border-color 160ms ease, box-shadow 180ms ease, background 160ms ease;
}
.tx-select:focus, .tx-input:focus {
    outline: none;
    border-color: var(--brand-500, #3b82f6);
    background: var(--surface-1, #fff);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
}

/* 🆕 Date input — Add/Edit Transaction (tx-input).
   We REPLACED the native iOS calendar popup with our custom calendar-grid
   date picker (date-picker.js), so we can now safely use appearance:none
   to clean up native rendering. Native fields used to expand past the
   container, especially on iOS where "yyyy-mm-dd" + calendar icon have a
   fixed intrinsic width. */
input[type="date"].tx-input {
    appearance: none;
    -webkit-appearance: none;
    display: block;
    text-align: left;
    line-height: 48px;
    font-family: inherit;
    font-size: var(--fs-body);
    font-weight: var(--fw-medium, 500);
    letter-spacing: normal;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    overflow: hidden;
}

/* iOS native picker pieces — keep typography consistent if anything leaks */
input[type="date"].tx-input::-webkit-date-and-time-value,
input[type="date"].tx-input::-webkit-datetime-edit,
input[type="date"].tx-input::-webkit-datetime-edit-fields-wrapper,
input[type="date"].tx-input::-webkit-datetime-edit-year-field,
input[type="date"].tx-input::-webkit-datetime-edit-month-field,
input[type="date"].tx-input::-webkit-datetime-edit-day-field,
input[type="date"].tx-input::-webkit-datetime-edit-text {
    text-align: left;
    font-family: inherit;
    font-size: var(--fs-body);
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
    line-height: 48px;
}

/* Hide native calendar-icon indicator — custom calendar-grid picker
   opens on focus instead, so the native icon is redundant. */
input[type="date"].tx-input::-webkit-calendar-picker-indicator {
    display: none;
    -webkit-appearance: none;
}
.tx-grid-2 {
    margin-top: var(--space-4);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
}

.tx-mode-toggle {
    background: transparent;
    border: 1px dashed var(--border-soft);
    color: var(--text-secondary);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--r-full);
    font-size: var(--fs-caption);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    transition: all 0.15s ease;
}
.tx-mode-toggle:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}
.tx-mode-toggle i { font-size: 16px; }

/* 🟢 Item 8: Note textarea */
.tx-textarea {
    height: auto !important;
    min-height: 56px;
    padding: var(--space-2) var(--space-3) !important;
    font-family: var(--font-main);
    resize: vertical;
    line-height: 1.4;
}
.tx-textarea__count {
    text-align: right;
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 4px;
}

/* ===== Advanced mode ===== */
.tx-help {
    font-size: var(--fs-caption);
    color: var(--text-secondary);
    background: rgba(6, 182, 212, 0.08);
    border-left: 3px solid var(--accent-cyan);
    padding: var(--space-3) var(--space-3);
    /* 🟢 Item 7: extra spacing between Smart-mode label & segmented control */
    margin-top: var(--space-4);
    margin-bottom: var(--space-4);
    border-radius: var(--r-sm);
}
.tx-help strong { color: var(--accent-cyan-light); }

/* ===== Advanced lines = vertical cards ===== */
.tx-lines {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.tx-line {
    position: relative;
    padding: var(--space-3) var(--space-3) var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* --- Header with line number + remove button (top-right) --- */
.tx-line__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.tx-line__num {
    font-size: var(--fs-caption);
    font-weight: var(--fw-semi);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.tx-line__remove {
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 20px;
    width: 32px;
    height: 32px;
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s ease;
}

.tx-line__remove:hover {
    background: rgba(244, 63, 94, 0.1);
    color: #e11d48;
    border-color: rgba(244, 63, 94, 0.25);
}

/* --- Field (label + control) --- */
.tx-line__field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.tx-line__label {
    font-size: 11px;
    font-weight: var(--fw-semi);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.tx-line__label-hint {
    font-weight: var(--fw-regular);
    text-transform: none;
    letter-spacing: 0;
    color: var(--text-muted);
    font-size: 11px;
}

/* --- Native <select> styled to match theme --- */
.tx-line__select-wrap {
    position: relative;
}

.tx-line__select-wrap::after {
    content: '';
    position: absolute;
    right: 14px;
    top: 50%;
    width: 12px;
    height: 12px;
    transform: translateY(-50%);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round'><polyline points='2,4 6,8 10,4'/></svg>");
    background-size: contain;
    pointer-events: none;
}

.tx-line__select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    height: 44px;
    padding: 0 36px 0 var(--space-3);
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    color: var(--text-primary);
    font-size: var(--fs-body);
    cursor: pointer;
    color-scheme: light;
}

.tx-line__select:focus {
    outline: none;
    border-color: var(--accent-cyan);
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15);
}

/* --- Amount row: input + Dr/Cr badge side by side --- */
.tx-line__amount-row {
    display: flex;
    align-items: stretch;
    gap: var(--space-2);
}

.tx-line__amount {
    flex: 1;
    height: 44px;
    padding: 0 var(--space-3);
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    color: var(--text-primary);
    font-size: var(--fs-body);
    font-variant-numeric: tabular-nums;
    font-weight: var(--fw-medium);
    text-align: right;
    color-scheme: light;
}

.tx-line__amount:focus {
    outline: none;
    border-color: var(--accent-cyan);
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15);
}

/* --- Dr / Cr badge (clickable button to toggle) --- */
.tx-line__hint {
    flex-shrink: 0;
    min-width: 64px;
    height: 44px;
    padding: 0 var(--space-2);
    border-radius: var(--r-md);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-caption);
    font-weight: var(--fw-bold);
    letter-spacing: 0.04em;
    background: var(--surface-2);
    color: var(--text-muted);
    border: 1px solid var(--border-soft);
    cursor: pointer;
    transition: all 0.15s ease;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}

.tx-line__hint:hover:not(:disabled) {
    transform: scale(1.05);
}

.tx-line__hint:active {
    transform: scale(0.96);
}

.tx-line__hint.is-dr {
    background: rgba(59, 130, 246, 0.15);     /* blue */
    color: #1d4ed8;
    border-color: rgba(59, 130, 246, 0.4);
}

.tx-line__hint.is-dr:hover {
    background: rgba(59, 130, 246, 0.22);
}

.tx-line__hint.is-cr {
    background: rgba(5, 150, 105, 0.15);      /* emerald */
    color: #047857;
    border-color: rgba(5, 150, 105, 0.4);
}

.tx-line__hint.is-cr:hover {
    background: rgba(5, 150, 105, 0.22);
}

.tx-add-line {
    background: rgba(59, 130, 246, 0.06);
    border: 1.5px dashed rgba(59, 130, 246, 0.4);
    color: #1d4ed8;
    padding: 14px var(--space-4);
    border-radius: var(--r-md);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: var(--fs-body);
    font-weight: var(--fw-semi, 600);
    font-family: inherit;
    width: 100%;
    margin-top: var(--space-3);
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}

.tx-add-line:hover {
    background: rgba(59, 130, 246, 0.12);
    border-color: rgba(59, 130, 246, 0.6);
    border-style: solid;
}

.tx-add-line:active {
    transform: scale(0.99);
}

.tx-add-line i {
    font-size: 20px;
    line-height: 1;
}

.tx-balance {
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    font-size: var(--fs-caption);
    color: var(--text-secondary);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.tx-balance strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.tx-balance__status {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--border-soft);
    font-weight: var(--fw-semi);
}
.tx-balance__status.is-balanced  { color: #059669; }
.tx-balance__status.is-unbalanced{ color: #e11d48; }


/* ================================================================
   12b-2. COMBOBOX (searchable select with badge prefix)
================================================================ */

.combobox {
    position: relative;
    width: 100%;
}

.combobox__trigger {
    width: 100%;
    height: 48px;
    padding: 0 var(--space-3);
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    color: var(--text-primary);
    font-size: var(--fs-body);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    text-align: left;
    transition: border-color 0.15s ease;
}

.combobox__trigger:hover {
    background: var(--surface-3);
}

.combobox.is-open .combobox__trigger {
    border-color: var(--accent-cyan);
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15);
}

.combobox__display {
    flex: 1;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.combobox__display.is-placeholder {
    color: var(--text-muted);
}

.combobox__caret {
    color: var(--text-secondary);
    font-size: 20px;
    transition: transform 0.2s ease;
    flex-shrink: 0;
}

.combobox.is-open .combobox__caret {
    transform: rotate(180deg);
}

.combobox__panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 1000;
    max-height: 280px;
    background: #ffffff;
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    box-shadow: 0 12px 32px -8px rgba(15, 23, 42, 0.35);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: comboboxOpen 0.15s ease;
}

/* 🆕 Open upward when there's no room below (JS adds class) */
.combobox__panel--up {
    top: auto;
    bottom: calc(100% + 4px);
    animation: comboboxOpenUp 0.15s ease;
}

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

/* 🛡️ HTML `hidden` attribute must beat `display: flex` above
   (CSS display normally overrides hidden — need !important to respect it) */
.combobox__panel[hidden] {
    display: none !important;
}

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

/* 🆕 Search wrap — กลมกลืนกับ panel มากขึ้น */
.combobox__search-wrap {
    position: relative;
    padding: var(--space-2) var(--space-2);
    border-bottom: 1px solid var(--border-soft);
    background: #ffffff;       /* ตรงกับพื้นหลัง panel */
}

.combobox__search-icon {
    position: absolute;
    left: calc(var(--space-2) + var(--space-3));
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 16px;
    pointer-events: none;
    z-index: 1;
}

.combobox__search {
    width: 100%;
    height: 36px;
    padding: 0 var(--space-3) 0 calc(var(--space-3) + 24px);   /* room for icon */
    background: #f8fafc;       /* soft slate-50 — กลืนกับ list ขาว */
    border: 1px solid var(--border-soft);
    border-radius: var(--r-sm);
    outline: none;
    font-size: var(--fs-caption);
    color: var(--text-primary);
    transition: border-color 0.15s ease, background 0.15s ease;
}

.combobox__search:focus {
    background: #ffffff;
    border-color: var(--accent-cyan);
    box-shadow: 0 0 0 2px rgba(6, 182, 212, 0.15);
}

.combobox__search::placeholder {
    color: var(--text-muted);
}

.combobox__list {
    overflow-y: auto;
    flex: 1;
    padding: var(--space-1);
}

.combobox__option {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--r-sm);
    cursor: pointer;
    font-size: var(--fs-caption);
    transition: background 0.1s ease;
}

.combobox__option:hover,
.combobox__option.is-highlighted {
    background: var(--surface-2);
}

.combobox__option.is-selected {
    background: rgba(6, 182, 212, 0.12);
}

.combobox__name {
    flex: 1;
    min-width: 0;                    /* 🆕 v3.1.0 G5b — enables ellipsis in flex child */
    color: var(--text-primary);
    font-weight: var(--fw-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combobox__empty {
    padding: var(--space-4);
    text-align: center;
    color: var(--text-muted);
    font-size: var(--fs-caption);
}

/* Badge — type prefix [Asset] / [Liab] / etc. */
.combobox__badge {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: var(--r-full);
    font-size: 10px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    min-width: 48px;
    justify-content: center;
}

.combobox__badge--asset    { background: rgba(5, 150, 105, 0.15);   color: #047857; }   /* emerald */
.combobox__badge--liab     { background: rgba(225, 29, 72, 0.15);   color: #be123c; }   /* rose */
.combobox__badge--equity   { background: rgba(139, 92, 246, 0.15);  color: #6d28d9; }   /* violet */
.combobox__badge--revenue  { background: rgba(59, 130, 246, 0.15);  color: #1d4ed8; }   /* blue */
.combobox__badge--expense  { background: rgba(245, 158, 11, 0.15);  color: #b45309; }   /* amber */


/* ================================================================
   12c. CONFIRM MODAL (for large amount)
================================================================ */
.confirm-modal {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.confirm-modal.is-open {
    opacity: 1;
    pointer-events: auto;
}
.confirm-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
}
.confirm-modal__dialog {
    position: relative;
    max-width: 360px;
    width: calc(100% - 32px);
    background: #ffffff;
    border-radius: var(--r-lg);
    padding: var(--space-5) var(--space-4);
    box-shadow: 0 25px 60px -10px rgba(0, 0, 0, 0.4);
}
.confirm-modal__title {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-h2);
    color: var(--text-primary);
}
.confirm-modal__body {
    margin: 0 0 var(--space-4);
    font-size: var(--fs-body);
    color: var(--text-secondary);
    line-height: 1.5;
}
.confirm-modal__body strong { color: var(--text-primary); }
.confirm-modal__actions {
    display: flex;
    gap: var(--space-2);
    justify-content: flex-end;
}
.confirm-modal__cancel, .confirm-modal__ok {
    padding: var(--space-2) var(--space-4);
    border-radius: var(--r-md);
    border: none;
    font-size: var(--fs-body);
    font-weight: var(--fw-semi);
    cursor: pointer;
}
.confirm-modal__cancel {
    background: var(--surface-2);
    color: var(--text-secondary);
}
.confirm-modal__ok {
    background: var(--brand-gradient);
    color: #fff;
}


/* ================================================================
   12d. TOAST WITH ACTION (Undo)
================================================================ */
.toast--with-action {
    padding-right: var(--space-3);
}
.toast__action {
    background: transparent;
    border: 1px solid currentColor;
    color: var(--accent-cyan-light);
    padding: 4px 12px;
    border-radius: var(--r-sm);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semi);
    cursor: pointer;
    flex-shrink: 0;
    margin-left: var(--space-2);
}
.toast__action:hover {
    background: rgba(6, 182, 212, 0.15);
}
.toast__action:disabled {
    opacity: 0.5;
    cursor: wait;
}


/* ================================================================
   13a. INFINITE SCROLL — skeleton + sentinel
================================================================ */

.infinite-sentinel {
    min-height: 60px;
    padding: var(--space-4) var(--space-2);
    display: flex;
    align-items: center;
    justify-content: center;
}

.infinite-skeleton {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
}

.infinite-end {
    text-align: center;
    color: var(--text-muted);
    font-size: var(--fs-caption);
    padding: var(--space-2);
}

.infinite-error {
    text-align: center;
    color: var(--money-expense);
    font-size: var(--fs-caption);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2);
}

.infinite-error i { font-size: 18px; }

.infinite-retry {
    background: transparent;
    border: 1px solid currentColor;
    color: inherit;
    padding: 4px 12px;
    border-radius: var(--r-sm);
    cursor: pointer;
    font-size: var(--fs-caption);
}

.infinite-retry:hover {
    background: rgba(244, 63, 94, 0.1);
}

/* "Load more" fallback button (manual trigger if observer doesn't fire) */
.infinite-load-more {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 10px 24px;
    border-radius: var(--r-full);
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    color: var(--text-secondary);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: all 0.15s ease;
}

.infinite-load-more:hover {
    background: var(--surface-3);
    color: var(--text-primary);
    transform: translateY(-1px);
}

.infinite-load-more:active {
    transform: translateY(0);
}

.infinite-load-more i {
    font-size: 18px;
}


/* ================================================================
   14. SIDEBAR (Desktop only — hidden on mobile)
================================================================ */

.sidebar {
    display: none;   /* hidden on mobile by default */
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    background: var(--surface-1, #fff);
    border-right: 1px solid var(--border-soft, #e2e8f0);
    flex-direction: column;
    padding: var(--space-4);
    gap: var(--space-3);
    z-index: 100;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    text-decoration: none;
    color: var(--text-primary);
    padding: var(--space-3) var(--space-2);
}

/* 🆕 personfin. lockup logo — replaces the old icon + text pair.
       Lockup SVG has 3.5:1 aspect ratio (420×120 viewBox), so we set a width
       and let height auto-scale. Max-height caps it on tall sidebar layouts. */
.sidebar__brand-logo {
    width: 160px;
    height: auto;
    max-height: 50px;
    display: block;
    user-select: none;
    -webkit-user-drag: none;
}

/* Legacy class kept in case any page still emits them — hide cleanly */
.sidebar__brand-icon,
.sidebar__brand-name { display: none; }

.sidebar__add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border: none;
    border-radius: var(--r-md);
    background: var(--brand-gradient);
    color: #fff;
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    font-size: var(--fs-body);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.sidebar__add:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(59, 130, 246, 0.35);
}

.sidebar__add:active {
    transform: translateY(0);
}

.sidebar__nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: var(--space-2);
}

.sidebar__item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--r-md);
    text-decoration: none;
    color: var(--text-secondary);
    font-weight: var(--fw-medium, 500);
    transition: background 0.15s ease, color 0.15s ease;
}

.sidebar__item i {
    font-size: 20px;
}

.sidebar__item:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}

.sidebar__item.is-active {
    background: rgba(59, 130, 246, 0.1);
    color: #1d4ed8;
}

.sidebar__footer {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border-soft);
}

.sidebar__user {
    flex: 1;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--r-md);
    text-decoration: none;
    color: var(--text-primary);
    min-width: 0;
}

.sidebar__user:hover {
    background: var(--surface-2);
}

.sidebar__avatar {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
}

.sidebar__user-info {
    min-width: 0;
    flex: 1;
}

.sidebar__user-name {
    margin: 0;
    font-weight: var(--fw-semi, 600);
    font-size: var(--fs-body);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar__user-role {
    margin: 0;
    font-size: var(--fs-caption);
    color: var(--text-secondary);
}

.sidebar__signout {
    /* F12 (v3.1.2+) — now a <button> inside .sidebar__signout-form,
       so reset native UA chrome. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font: inherit;
    cursor: pointer;
    background: transparent;
    border: none;
    padding: var(--space-2);
    border-radius: var(--r-md);
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 20px;
    transition: background 0.15s ease, color 0.15s ease;
}

.sidebar__signout:hover {
    background: rgba(239, 68, 68, 0.1);
    color: #dc2626;
}

/* 🆕 Version badge — tiny, subtle, sits at very bottom of sidebar.
   Click to copy (handled by app.js); shows green confirmation briefly. */
.sidebar__version {
    margin: var(--space-2) var(--space-3) var(--space-3);
    padding: 6px 10px;
    border-radius: var(--r-md);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--text-tertiary, #94a3b8);
    background: rgba(15, 23, 42, 0.03);
    text-align: center;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s ease, color 0.15s ease;
    font-variant-numeric: tabular-nums;
}

.sidebar__version:hover {
    background: rgba(59, 130, 246, 0.08);
    color: var(--primary, #3b82f6);
}

.sidebar__version.is-copied {
    background: rgba(16, 185, 129, 0.12);
    color: #059669;
}

/* ============================================================
   🆕 v3.1.0 Phase C — 2-level sidebar (groups + sub-items)
   Structure per CLAUDE.md: full 2-level, no collapsed/hamburger.
   ============================================================ */

/* Group wrapper + heading */
.sidebar__group {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 12px;
}
.sidebar__group-heading {
    margin: 4px 12px 6px;
    padding: 0;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    color: var(--pf-muted-3, #94a3b8);
}

/* Parent item (has sub-items below) — same look as .sidebar__item,
   but slightly weightier when active to distinguish from sub. */
.sidebar__item--parent { font-weight: 600; }
.sidebar__item--parent.is-active {
    background: rgba(31, 95, 230, 0.10);
    color: var(--pf-primary, #1F5FE6);
}

/* Sub-item — indented, smaller, no icon */
.sidebar__subitem {
    display: block;
    margin: 0 4px 0 32px;                  /* indent under parent icon */
    padding: 5px 10px;
    border-radius: var(--r-md, 12px);
    text-decoration: none;
    color: var(--pf-muted-2, #64748b);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    transition: background 0.12s, color 0.12s;
}
.sidebar__subitem:hover {
    background: rgba(15, 23, 42, 0.04);
    color: var(--pf-ink-2, #2b3242);
}
.sidebar__subitem.is-active {
    background: rgba(31, 95, 230, 0.08);
    color: var(--pf-primary, #1F5FE6);
    font-weight: 600;
}

/* Reset default nav gap so groups control spacing themselves */
.sidebar__nav {
    gap: 0;
    margin-top: var(--space-3, 12px);
}


/* ================================================================
   15. RESPONSIVE — Sidebar visible ≥1024px (per CLAUDE.md rule)
        Mobile <768 + Tablet 768-1023 = bottom tab bar (drill-in)
        Laptop 1024+ = sidebar 2-level, tab bar hidden
        🆕 v3.1.0 Phase C — breakpoint moved from 768 → 1024 per CLAUDE.md.
        Sidebar width scales: 1024→220px, 1280→260px, 1536→280px.
================================================================ */

@media (min-width: 1024px) {
    .sidebar {
        display: flex;
        width: 220px;                          /* compact laptop */
    }

    .app-main {
        margin-left: 220px;
        padding: var(--space-5) var(--space-6);
        padding-bottom: var(--space-6);
        max-width: 960px;
    }

    .bottom-tab-bar,
    .fab {
        display: none !important;
    }

    /* 🖥️ DESKTOP sheet rules live in section 71 (.app-sheet--slide / --full) */
}

/* 🆕 v3.1.0 Phase C — sidebar scales up at wider breakpoints (Q7=🅑 decision):
   1024→220px · 1280→260px · 1536→280px. Same 2-level depth throughout. */
@media (min-width: 1280px) {
    .sidebar     { width: 260px; }
    .app-main    { margin-left: 260px; max-width: 1020px; }
    .sidebar__item      { padding: var(--space-3, 12px); font-size: 14px; }
    .sidebar__subitem   { padding: 6px 12px; font-size: 13.5px; }
    .sidebar__group-heading { font-size: 11px; }
}
@media (min-width: 1536px) {
    .sidebar     { width: 280px; padding: var(--space-5, 20px); }
    .app-main    { margin-left: 280px; max-width: 1256px; }
    .sidebar__group     { margin-bottom: 16px; }
}


/* ================================================================
   16. JUMP NAV — Horizontal scrollable filter chips
        Hint: fade gradient + peek of next item suggests swipe right
================================================================ */

.jump-nav {
    position: relative;
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    overflow-y: hidden;
    padding: var(--space-2) var(--space-4);
    margin: 0 calc(var(--space-4) * -1) var(--space-3);  /* full-bleed */
    scroll-snap-type: x proximity;
    scrollbar-width: none;                                /* Firefox */
    -ms-overflow-style: none;                             /* IE/Edge */
    -webkit-overflow-scrolling: touch;
    /* Soft fade on right edge — hints scrollable */
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
}

.jump-nav::-webkit-scrollbar { display: none; }           /* Chrome/Safari */

.jump-nav__item {
    flex-shrink: 0;
    scroll-snap-align: start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 40px;
    padding: 0 var(--space-3);
    border-radius: var(--r-full);
    background: var(--surface-2, #f1f5f9);
    border: 1px solid var(--border-soft, #e2e8f0);
    color: var(--text-primary, #0f172a);
    text-decoration: none;
    font-size: var(--fs-caption, 0.875rem);
    font-weight: var(--fw-medium, 500);
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease, color 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}

.jump-nav__item:hover {
    background: rgba(59, 130, 246, 0.08);
    border-color: rgba(59, 130, 246, 0.35);
    color: #1d4ed8;
}

.jump-nav__item:active {
    transform: scale(0.96);
    background: rgba(59, 130, 246, 0.15);
}

.jump-nav__item.is-active {
    background: var(--brand-gradient);
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
}

/* Right-edge swipe hint — small bouncing chevron pill */
.jump-nav-wrap {
    position: relative;
    margin: 0 calc(var(--space-4) * -1) var(--space-3);   /* take full-bleed margin */
}

.jump-nav-wrap > .jump-nav {
    margin: 0;                /* wrap handles margin now */
}

.jump-nav-wrap::after {
    content: '\203A';         /* › single right chevron */
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.95);
    color: var(--accent-blue, #3b82f6);
    font-size: 20px;
    font-weight: 600;
    line-height: 28px;
    text-align: center;
    pointer-events: none;
    opacity: 0.85;
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12);
    animation: jumpNavHint 1.5s ease-in-out infinite;
}

@keyframes jumpNavHint {
    0%, 100% { transform: translate(0, -50%); opacity: 0.85; }
    50%      { transform: translate(6px, -50%); opacity: 1; }
}

/* Hide hint once user has scrolled (JS toggles this class) */
.jump-nav-wrap.has-scrolled::after {
    opacity: 0;
    animation: none;
    transform: translate(8px, -50%);
    transition: opacity 0.25s ease, transform 0.25s ease;
}


/* ================================================================
   17. LIST GROUP HEADER — section header within scrolling list
================================================================ */

/* 🆕 v3.1.0 Phase T §2 redesign — day header that reads as a day header,
   not a tiny caption. Earlier 64px version left too much whitespace below
   a tiny 11px label. User call: "ยังแปลก, ไม่เอา totals". So: bigger text
   (14px/700, mixed-case), tighter height (~48px), subtle date-chip on left
   with a soft-blue tint tying it to the brand language. */
.list-group__header {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 48px;
    padding: 10px var(--space-4);
    background: var(--surface-1, #fff);
    position: sticky;
    top: 0;
    z-index: 5;
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
    font-family: inherit;
    color: var(--text-primary, #1e293b);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
}
/* Little dot in front of the date adds visual anchor without the day-of-week
   dependency — purely decorative, cheap to render. */
.list-group__header::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: var(--brand-500, #3b82f6);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
    flex-shrink: 0;
}


/* ================================================================
   18. LIST COUNTER — sticky progress display
================================================================ */

/* 🆕 v3.1.0 Phase G14 — Accounts page jump-scroll offset for sticky nav+counter.
   scroll-padding-top makes anchor navigation land BELOW the sticky elements
   instead of behind them. Value updated dynamically by accounts.php JS
   (measures jumpNav + list-counter heights), fallback 110px covers most cases. */
body.page-accounts {
    scroll-padding-top: var(--acc-sticky-offset, 110px);
}

.list-counter {
    position: sticky;
    top: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    margin: 0 calc(var(--space-4) * -1) var(--space-2);
    background: var(--surface-1, #fff);
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
    font-size: var(--fs-caption, 0.875rem);
    color: var(--text-secondary);
}

.list-counter strong {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.list-counter__progress {
    flex: 1;
    height: 4px;
    background: var(--surface-3, #e2e8f0);
    border-radius: var(--r-full);
    overflow: hidden;
}

.list-counter__progress-bar {
    height: 100%;
    background: linear-gradient(90deg, #3b82f6, #06b6d4);
    border-radius: var(--r-full);
    transition: width 0.25s ease;
}

/* Emoji marker inside chip — slightly smaller for visual balance */
.jump-nav__emoji {
    font-size: 14px;
    line-height: 1;
}


/* ================================================================
   19. RECEIPT SLOTS — 3 photo upload buttons in form
================================================================ */

.tx-field__hint {
    color: var(--text-secondary, #64748b);
    font-weight: var(--fw-normal, 400);
    font-size: 11px;
    text-transform: none;
    letter-spacing: 0;
    margin-left: var(--space-1);
}

/* 🆕 v3.1.0 Phase G4e — Receipt strip matches draft §5 line 628/646/705.
   Fixed 62×62 flex row · filled=solid border · empty=dashed border · × outside corner.
   Horizontal overflow scroll if user attaches many. */
.receipt-slots {
    display: flex;
    flex-direction: row;
    gap: 8px;
    padding: 4px 6px 4px 0;   /* padding-top gives room for × button that sticks out */
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;    /* Firefox: hide */
}
.receipt-slots::-webkit-scrollbar { display: none; }   /* WebKit: hide */

.receipt-slot {
    position: relative;
    width: 62px;
    height: 62px;
    flex-shrink: 0;                    /* fixed size — no shrinking in flex row */
    border-radius: 12px;
    background: #f5f6f9;
    cursor: pointer;
    overflow: visible;                 /* ← allow × to stick out of the tile */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
    color: var(--pf-muted-2, #8a94a3);
    font-family: inherit;
    padding: 0;
    border: 1.5px solid var(--pf-line, #eaedf1);   /* base: solid — draft distinguishes filled vs empty by border STYLE */
}

/* Empty ("+") tile — dashed border per draft §5 */
.receipt-slot.is-empty {
    border-style: dashed;
    border-color: #c4ccd6;
    background: #f5f6f9;
}
/* 🆕 v3.1.0 Phase Z §3a Round 6 — empty "+" tile hover gets brand glow +
   gentle lift so attaching a receipt feels inviting. */
.receipt-slot.is-empty:hover {
    border-color: var(--brand-500, #3b82f6);
    background: rgba(59, 130, 246, 0.08);
    color: var(--brand-600, #2563eb);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px -4px rgba(59, 130, 246, 0.26);
}
.receipt-slot.is-empty:hover .receipt-slot__plus { transform: scale(1.1) rotate(90deg); }
.receipt-slot.is-empty:active { transform: scale(0.95); }
.receipt-slot__plus { transition: transform .22s cubic-bezier(0.34, 1.56, 0.64, 1); }

.receipt-slot__plus {
    font-size: 22px;
    line-height: 1;
}
.receipt-slot__hint {
    display: none;   /* draft has no text label — just + icon inside tile */
}

/* Filled tile — solid border, image fill.
   NOTE: overflow stays 'visible' (inherited from .receipt-slot) so the × button can
   stick out at top:-6px right:-6px per draft §5. Image gets its own border-radius
   ~10.5px (slightly less than container 12px + 1.5px border) to render rounded. */
.receipt-slot.is-filled {
    border-style: solid;
    border-color: #c4ccd6;
    background: #dde2e9;
    cursor: zoom-in;
    box-shadow: none;
}
.receipt-slot.is-filled:hover  { border-color: #93c5fd; }
.receipt-slot.is-filled:active { transform: scale(0.97); }

.receipt-slot__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 10.5px;      /* ← image clips to rounded corners inside the border */
    display: block;
    color: transparent;
    font-size: 0;
    text-indent: -9999px;
}

.receipt-slot.is-filled:active {
    transform: scale(0.98);
}

/* 🆕 v3.1.0 Phase G4e — legacy .receipt-slot__img rule superseded by the new one
   above (with border-radius for corner clipping). Left as a no-op placeholder to
   avoid confusion. Delete during Phase O cleanup. */

/* Error state — shown when JS detects image load failure */
.receipt-slot.is-broken {
    background: rgba(239, 68, 68, 0.05);
    border-color: rgba(239, 68, 68, 0.4);
}

.receipt-slot.is-broken .receipt-slot__img {
    display: none;
}

.receipt-slot__broken {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    color: #dc2626;
    font-size: 11px;
    font-weight: 500;
    pointer-events: none;
}

.receipt-slot__broken i { font-size: 22px; }

/* 🆕 v3.1.0 Phase G4e — Remove (×) button per draft §5 line 628/646/705:
   18×18 white circle OUTSIDE the tile's top-right corner (top:-6px, right:-6px).
   Requires .receipt-slot { overflow: visible } (set above). */
.receipt-slot__remove {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 18px;
    height: 18px;
    border: 1.5px solid #c4ccd6;
    border-radius: 50%;
    background: #ffffff;
    color: #7a8494;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    padding: 0;
    z-index: 2;
    transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}
.receipt-slot__remove:hover  { background: var(--pf-danger, #dc2626); color: #fff; border-color: var(--pf-danger, #dc2626); }
.receipt-slot__remove:active { transform: scale(0.9); }

/* Uploading state — progress overlay */
.receipt-slot.is-uploading {
    cursor: wait;
}

.receipt-slot.is-uploading::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    z-index: 1;
}

.receipt-slot__spinner {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 28px;
    height: 28px;
    border: 3px solid rgba(255, 255, 255, 0.3);
    border-top-color: #fff;
    border-radius: 50%;
    animation: receiptSpin 0.7s linear infinite;
    z-index: 2;
}

@keyframes receiptSpin {
    to { transform: rotate(360deg); }
}

/* Error state */
.receipt-slot.is-error {
    border-color: #dc2626;
    background: rgba(239, 68, 68, 0.05);
    color: #dc2626;
}

.receipt-help {
    margin: var(--space-2) 0 0;
    font-size: 11px;
    color: var(--text-secondary, #64748b);
    text-align: center;
}

/* 🆕 v3.1.0 Phase G6b — DATE row with calendar icon prefix (draft §5 line 625).
   Wraps native <input type="date"> · icon-only (no functional replacement).
   Native picker preserved · picker indicator hidden via CSS. */
.tx-date-row {
    display: flex;
    align-items: center;
    gap: 10px;
    /* 🆕 v3.1.0 Phase G6c — 48px height matches .combobox__trigger (uniform form rows) */
    min-height: 48px;
    padding: 0 14px;
    background: var(--pf-card, #ffffff);
    border: 1px solid var(--pf-line, #eaedf1);
    border-radius: 12px;
    transition: border-color 140ms, box-shadow 140ms;
    position: relative;
}
.tx-date-row:focus-within {
    border-color: var(--accent-blue, #3b82f6);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
.tx-date-row__icon {
    font-size: 18px;
    color: var(--pf-muted-2, #8a94a3);
    line-height: 1;
    pointer-events: none;
    flex-shrink: 0;
}
/* Native input inside date-row — strip its own border/bg since row provides them */
#txDate.tx-date-input,
#txDate.tx-date-input:focus,
#txDate.tx-date-input:focus-visible,
#txDate.tx-date-input.is-kb-active {
    flex: 1;
    -webkit-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
    padding: 0 !important;
    font-size: 16px;
    color: var(--pf-text, #0f172a);
    font-family: inherit;
}
/* Hide native calendar picker indicator (desktop Chrome/Edge) — we show our own icon on the left.
   Chromium can reserve horizontal space even with display:none, so we also zero out
   background/width/padding. Our .tx-date-row JS click handler opens showPicker() instead. */
#txDate.tx-date-input::-webkit-calendar-picker-indicator,
input[type="date"]#txDate::-webkit-calendar-picker-indicator {
    display: none !important;
    -webkit-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-image: none !important;
    color: transparent !important;
    opacity: 0 !important;
    width: 0 !important;
    height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    pointer-events: none !important;
}
/* Some Chromium builds render an inner indicator via ::-webkit-inner-spin-button too */
#txDate.tx-date-input::-webkit-inner-spin-button,
#txDate.tx-date-input::-webkit-clear-button {
    display: none !important;
    -webkit-appearance: none !important;
}
.tx-date-row { cursor: pointer; }

/* 🆕 v3.1.0 Phase G6a fix8 — Receipt EMPTY state: large wf-box per draft §5 line 725
   (dashed border box with camera icon + text "Attach receipt / slip"). Filled state
   still uses 62×62 strip below. Selected in fix8: 1B / 2B / 3A / 4A. */
.receipt-empty-box {
    /* Override .receipt-slot 62×62 sizing → full-width row */
    width: auto !important;
    height: auto !important;
    flex: 1 0 100% !important;
    flex-direction: row !important;
    gap: 8px !important;
    /* 🆕 v3.1.0 Phase G6c — 48px height matches .combobox__trigger (uniform form rows) */
    min-height: 48px !important;
    padding: 0 12px !important;
    background: #f7f8fa !important;
    border: 1.5px dashed #c4ccd6 !important;
    border-radius: 12px !important;
    color: #8a94a3 !important;
    cursor: pointer;
}
.receipt-empty-box i    { font-size: 16px; line-height: 1; }
.receipt-empty-box span { font-size: 12px; }
.receipt-empty-box:hover {
    border-color: var(--pf-primary, #2563eb) !important;
    background: rgba(59, 130, 246, 0.05) !important;
    color: var(--pf-primary, #2563eb) !important;
}
.receipt-empty-box:active { transform: scale(0.99) !important; }

/* 2B — hide "JPG · PNG · WebP · max 5 MB each" hint when empty box is the sole content.
   The empty box is CTA enough; hint reappears once user attaches a receipt. */
.receipt-slots:has(.receipt-empty-box) + .receipt-help {
    display: none;
}

/* ================================================================
   20. REVIEW SCREEN — receipt thumbnails preview
================================================================ */

.review-receipts {
    display: flex;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.review-receipt-thumb {
    width: 80px;
    height: 80px;
    border-radius: var(--r-md);
    overflow: hidden;
    border: 1px solid var(--border-soft, #e2e8f0);
    background: #000;
    cursor: zoom-in;
    flex-shrink: 0;
    padding: 0;
}

.review-receipt-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ================================================================
   21. LIGHTBOX — full-screen image viewer
================================================================ */

.lightbox {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 9999;
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
}

.lightbox.is-open {
    display: flex;
    animation: lightboxFadeIn 0.2s ease;
}

@keyframes lightboxFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.lightbox__img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--r-md);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.lightbox__close {
    position: absolute;
    top: max(env(safe-area-inset-top, 0), 12px);
    right: 12px;
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    cursor: pointer;
    font-size: 28px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(8px);
    transition: background 0.15s ease;
}

.lightbox__close:hover {
    background: rgba(255, 255, 255, 0.32);
}

/* ================================================================
   22. TX LIST — paperclip indicator for transactions with receipts
================================================================ */

.list-item__receipt-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-right: 4px;
    color: var(--accent-blue, #3b82f6);
    font-size: 16px;
}

/* 🆕 v3.1.0 Phase T §2 — Receipt slot (Activity list, Option B).
   Always reserves fixed width AFTER the amount so columns stay aligned
   across rows. Filled with a brand-blue camera icon when the tx has an
   attached receipt; empty (invisible but space-reserving) otherwise. */
.list-item__receipt-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin-left: 8px;        /* breathing room between amount and slot */
    vertical-align: middle;
    flex-shrink: 0;
}
.list-item__receipt-slot.has-receipt {
    color: var(--brand-600, #2563eb);
}
.list-item__receipt-slot.has-receipt i {
    font-size: 16px;
    line-height: 1;
}


/* ================================================================
   23. SESSION WARNING MODAL — shown 30 sec before auto-signout
================================================================ */

.session-modal {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
}

.session-modal.is-open {
    display: flex;
    animation: sessionModalFadeIn 0.18s ease;
}

@keyframes sessionModalFadeIn {
    from { opacity: 0; transform: translateY(0); }
    to   { opacity: 1; }
}

.session-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.6);
    backdrop-filter: blur(2px);
}

.session-modal__dialog {
    position: relative;
    width: 100%;
    max-width: 380px;
    padding: var(--space-5) var(--space-4) var(--space-4);
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    box-shadow: 0 20px 60px rgba(15, 23, 42, 0.35);
    text-align: center;
    animation: sessionDialogSlide 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

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

.session-modal__icon {
    width: 64px;
    height: 64px;
    margin: 0 auto var(--space-3);
    border-radius: 50%;
    background: rgba(251, 191, 36, 0.15);
    color: #d97706;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 36px;
}

.session-modal__title {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-h2, 1.25rem);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
}

.session-modal__body {
    margin: 0 0 var(--space-4);
    color: var(--text-secondary);
    font-size: var(--fs-body);
    line-height: 1.5;
}

.session-modal__countdown {
    display: inline-block;
    margin-left: 4px;
    color: var(--text-primary);
    font-weight: var(--fw-bold, 700);
    font-size: 1.4em;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.5px;
}

.session-modal__actions {
    display: flex;
    gap: var(--space-2);
}

.session-modal__actions .btn--primary,
.session-modal__actions .btn--secondary {
    flex: 1;
    height: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    border-radius: var(--r-md);
    font-size: var(--fs-body);
    font-weight: var(--fw-semi, 600);
    font-family: inherit;
    cursor: pointer;
    border: none;
    transition: transform 0.12s ease, box-shadow 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}

.session-modal__actions .btn--primary {
    background: var(--brand-gradient);
    color: #fff;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
}

.session-modal__actions .btn--primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(59, 130, 246, 0.38);
}

.session-modal__actions .btn--secondary {
    background: var(--surface-2, #f1f5f9);
    color: var(--text-primary);
    border: 1px solid var(--border-soft, #e2e8f0);
}

.session-modal__actions .btn--secondary:hover {
    background: var(--surface-3, #e2e8f0);
}

.session-modal__actions .btn--primary i,
.session-modal__actions .btn--secondary i {
    font-size: 18px;
}


/* ================================================================
   24. PWA INSTALL BANNER — slides up from bottom
================================================================ */

.install-banner,
.update-banner {
    position: fixed;
    left: var(--space-3);
    right: var(--space-3);
    bottom: calc(env(safe-area-inset-bottom, 0px) + 84px); /* above tab bar */
    z-index: 9000;
    display: none;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
    border: 1px solid var(--border-soft, #e2e8f0);
}

.install-banner.is-open,
.update-banner.is-open {
    display: flex;
    animation: bannerSlideUp 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes bannerSlideUp {
    from { transform: translateY(120%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

.install-banner__icon img,
.update-banner__icon {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: var(--r-md);
    display: flex;
    align-items: center;
    justify-content: center;
}

.update-banner__icon {
    background: var(--brand-gradient);
    color: #fff;
    font-size: 24px;
}

.install-banner__body,
.update-banner__body {
    flex: 1;
    min-width: 0;
}

.install-banner__title,
.update-banner__title {
    margin: 0 0 2px;
    font-size: var(--fs-body, 0.875rem);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
    line-height: 1.3;
}

.install-banner__msg,
.update-banner__msg {
    margin: 0;
    font-size: var(--fs-caption, 0.75rem);
    color: var(--text-secondary);
    line-height: 1.3;
}

.install-banner__actions,
.update-banner__actions {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex-shrink: 0;
}

.install-banner__install,
.update-banner__reload {
    height: 36px;
    padding: 0 14px;
    border-radius: var(--r-md);
    background: var(--brand-gradient);
    color: #fff;
    border: none;
    font-size: var(--fs-caption, 0.75rem);
    font-weight: var(--fw-semi, 600);
    font-family: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.12s ease, box-shadow 0.15s ease;
}

.install-banner__install:hover,
.update-banner__reload:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 14px rgba(59, 130, 246, 0.4);
}

.install-banner__install i,
.update-banner__reload i {
    font-size: 14px;
}

.install-banner__dismiss,
.update-banner__dismiss {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-size: 11px;
    cursor: pointer;
    padding: 4px 8px;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
}

.install-banner__dismiss:hover,
.update-banner__dismiss:hover {
    color: var(--text-primary);
}

/* Desktop: banner has more room, place differently */
@media (min-width: 768px) {
    .install-banner,
    .update-banner {
        left: auto;
        right: var(--space-5);
        bottom: var(--space-5);
        max-width: 420px;
    }
}


/* ================================================================
   25. WEBAUTHN SETTINGS — Face ID / Touch ID enrollment UI
================================================================ */

.section-title {
    margin: var(--space-5) 0 var(--space-2);
    font-size: 11px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    padding: 0 var(--space-2);
}

.webauthn-section {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    padding: var(--space-4);
    margin-bottom: var(--space-4);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
}

.webauthn-section__header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
}

.webauthn-section__icon {
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    border-radius: 12px;
    background: var(--brand-gradient);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.25);
}

.webauthn-section__heading { flex: 1; min-width: 0; }

.webauthn-section__title {
    margin: 0;
    font-size: var(--fs-body, 0.875rem);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
}

.webauthn-section__status {
    margin: 2px 0 0;
    font-size: var(--fs-caption, 0.75rem);
    color: var(--text-secondary);
}

.webauthn-section__status strong {
    color: var(--text-primary);
    font-weight: var(--fw-semi, 600);
}

/* Device list */
.webauthn-list {
    list-style: none;
    padding: 0;
    margin: var(--space-3) 0 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* v3.1.2+ · The entire .webauthn-card / .webauthn-cta / .webauthn-empty /
   .webauthn-unsupported block was removed. Those classes belonged to the
   old visible Face ID / PIN cards that duplicated #authMethodsList, and to
   the two "Set up Face ID" / "Add another device" CTAs below the list.
   The DOM elements they styled no longer exist; the unified list uses
   .auth-method* classes and the add-method chooser-sheet uses
   .auth-add-sheet* classes.
   The bx-spin keyframe stays — other icons across the app still spin. */
@keyframes bx-spin {
    to { transform: rotate(360deg); }
}
.bx-spin { animation: bx-spin 0.8s linear infinite; display: inline-block; }

/* ================================================================
   26. CONFIRM POPUP — custom replacement for native confirm()
================================================================ */

.confirm-popup {
    position: fixed;
    inset: 0;
    z-index: 10001;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    animation: confirmFade 0.16s ease;
}

@keyframes confirmFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.confirm-popup__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(2px);
}

/* 🆕 v3.1.0 Phase AD confirm-popup Round 1 — dialog: deeper 2-layer shadow
   + spring entrance for premium modal feel. */
.confirm-popup__dialog {
    position: relative;
    max-width: 380px;
    width: 100%;
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    padding: var(--space-5);
    box-shadow: 0 24px 60px -16px rgba(15, 23, 42, 0.50),
                0 8px 24px -8px rgba(15, 23, 42, 0.30),
                inset 0 1px 0 rgba(255, 255, 255, 0.5);
    animation: confirmSlide 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes confirmSlide {
    from { transform: scale(0.92); opacity: 0; }
    to   { transform: scale(1);    opacity: 1; }
}

.confirm-popup__title {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-h3, 1rem);
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary);
}

.confirm-popup__body {
    margin: 0 0 var(--space-4);
    font-size: var(--fs-body, 0.875rem);
    color: var(--text-secondary);
    line-height: 1.5;
}

.confirm-popup__actions {
    display: flex;
    gap: var(--space-2);
}

.confirm-popup__actions button {
    flex: 1;
    height: 44px;
    border: none;
    border-radius: var(--r-md);
    font-size: var(--fs-body);
    font-weight: var(--fw-semi, 600);
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.12s ease, opacity 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}

/* 🆕 v3.1.0 Phase AD confirm-popup Round 1 — Cancel + OK buttons polish */
.confirm-popup__cancel {
    background: var(--surface-2, #f1f5f9);
    color: var(--text-primary);
    border: 1.5px solid var(--border-soft, #eef1f5);
    transition: background .15s ease, border-color .15s ease, transform .08s ease;
}
.confirm-popup__cancel:hover {
    background: var(--surface-3, #e2e8f0);
    border-color: var(--border-light, #cbd5e1);
}
.confirm-popup__ok {
    transition: filter .18s ease, box-shadow .22s ease, transform .08s ease;
}
.confirm-popup__ok:hover {
    filter: brightness(1.08) saturate(1.08);
    transform: translateY(-1px);
}
.confirm-popup button:active { transform: scale(0.97); }

/* 🆕 v3.1.0 Phase AD Round 1 — Icon circle: gradient fill + bounce-in + glow */
.confirm-popup__icon {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 4px auto 16px;
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    color: #fff;
    box-shadow: 0 8px 20px -4px rgba(220, 38, 38, 0.40),
                0 2px 6px -1px rgba(15, 23, 42, 0.10);
    animation: confirmIconPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.confirm-popup__icon i { font-size: 32px; }
.confirm-popup__icon--warning {
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
    box-shadow: 0 8px 20px -4px rgba(245, 158, 11, 0.40),
                0 2px 6px -1px rgba(15, 23, 42, 0.10);
}
.confirm-popup__icon--info {
    background: var(--brand-gradient);
    box-shadow: 0 8px 20px -4px rgba(37, 99, 235, 0.42),
                0 2px 6px -1px rgba(15, 23, 42, 0.10);
}
@keyframes confirmIconPop {
    0%   { opacity: 0; transform: scale(0.3) rotate(-20deg); }
    60%  { opacity: 1; transform: scale(1.15) rotate(5deg); }
    100% { opacity: 1; transform: scale(1) rotate(0); }
}
@media (prefers-reduced-motion: reduce) {
    .confirm-popup__dialog, .confirm-popup__icon { animation: none; }
}

.confirm-popup--centered .confirm-popup__title,
.confirm-popup--centered .confirm-popup__body { text-align: center; }

/* Branded OK variants — used by appConfirm({okVariant: 'danger' | 'warning'}) */
.confirm-popup__ok {
    color: #fff;
    border: none;
    background: var(--brand-gradient);
}
.confirm-popup__ok--danger {
    background: linear-gradient(135deg, #ef4444, #dc2626);
    box-shadow: 0 4px 14px rgba(220, 38, 38, 0.32);
}
.confirm-popup__ok--warning {
    background: linear-gradient(135deg, #f59e0b, #d97706);
    box-shadow: 0 4px 14px rgba(217, 119, 6, 0.30);
}

/* Detail block (transaction ID + amount + receipt info shown inside dialog) */
.confirm-popup__detail {
    margin: -8px 0 16px;
    padding: 12px 14px;
    background: var(--surface-2, #f1f5f9);
    border-radius: var(--r-md);
    font-size: 13px;
    color: var(--text-primary);
}
.confirm-popup__detail strong {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 600;
    color: #0f172a;
}
.confirm-popup__detail-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 2px 0;
}


/* ================================================================
   27. ACCOUNTS PAGE HEADER — Add button + Show inactive toggle
================================================================ */

.acct-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
    flex-wrap: wrap;
}

.acct-page-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

.acct-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    cursor: pointer;
    user-select: none;
}

.acct-toggle input { accent-color: #3b82f6; cursor: pointer; }

.acct-add-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 36px;
    padding: 0 14px;
    border-radius: var(--r-full);
    background: var(--brand-gradient);
    color: #fff;
    border: none;
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
    transition: transform 0.12s ease, box-shadow 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}

.acct-add-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(59, 130, 246, 0.38);
}

.acct-add-btn:active { transform: translateY(0) scale(0.97); }
.acct-add-btn i { font-size: 18px; }

/* ================================================================
   28. ACCOUNT LIST ITEM — clickable + inactive state
================================================================ */

.list-item--clickable { cursor: pointer; transition: background 0.15s ease; }
.list-item--clickable:hover { background: var(--surface-2); }
.list-item--clickable:active { background: var(--surface-3); }

.list-item--inactive {
    opacity: 0.55;
}
.list-item--inactive .list-item__title { color: var(--text-secondary); }

.acct-badge-inactive {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-size: 9px;
    font-weight: var(--fw-bold, 700);
    background: rgba(220, 38, 38, 0.12);
    color: #b91c1c;
    border-radius: var(--r-sm);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    vertical-align: middle;
}

/* ================================================================
   29. ACCOUNT FORM — segmented types + ID readonly + active switch
================================================================ */

.segmented--types {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    padding: 4px;
    gap: 2px;
}

.segmented--types .segmented__option {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 2px;
    border-radius: var(--r-sm);
    font-size: 11px;
    font-weight: var(--fw-medium, 500);
    line-height: 1.2;
    min-height: 48px;
}

.segmented--types .seg-emoji { font-size: 16px; line-height: 1; }
.segmented--types .seg-label { font-size: 10px; }

.acct-id-readonly {
    display: inline-block;
    padding: 8px 12px;
    background: var(--surface-2, #f1f5f9);
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: var(--r-md);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: var(--fw-semi, 600);
    font-size: var(--fs-body);
    color: var(--accent-blue, #1d4ed8);
    letter-spacing: 1px;
}

.acct-active-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.acct-switch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}

.acct-switch input { display: none; }

.acct-switch__track {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 26px;
    background: var(--surface-3, #e2e8f0);
    border-radius: 99px;
    transition: background 0.15s ease;
}

.acct-switch__track::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.25);
    transition: transform 0.18s ease;
}

.acct-switch input:checked + .acct-switch__track {
    background: var(--brand-gradient);
}
.acct-switch input:checked + .acct-switch__track::after {
    transform: translateX(18px);
}

.acct-switch__label {
    font-size: var(--fs-body);
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary);
}

.acct-deactivate-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 12px;
    background: rgba(220, 38, 38, 0.08);
    color: #b91c1c;
    border: 1px solid rgba(220, 38, 38, 0.25);
    border-radius: var(--r-md);
    font-family: inherit;
    font-size: 12px;
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease;
}

.acct-deactivate-btn:hover {
    background: rgba(220, 38, 38, 0.15);
}

.acct-deactivate-btn i { font-size: 14px; }


/* ================================================================
   30. TX EDIT MODE — Delete bar + receipts banner
================================================================ */

/* Delete-only footer below the normal Edit/Confirm bar */
.tx-screen__delete-bar {
    flex: 0 0 auto;
    padding: var(--space-2) var(--space-4) var(--space-4);
    background: var(--surface-1, #fff);
    border-top: 1px solid var(--border-soft, #e2e8f0);
}

/* 🆕 UNIFIED with .pw-btn--danger — solid red gradient (was outlined red).
   All Delete buttons app-wide now share the same visual language. */
.btn--danger {
    width: 100%;
    height: 44px;
    border: none;
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    color: #fff;
    border-radius: var(--r-md);
    font-family: inherit;
    font-size: var(--fs-body);
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    box-shadow: 0 2px 8px rgba(220, 38, 38, 0.32);
    transition: box-shadow 0.18s ease, transform 0.12s ease, filter 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}

.btn--danger:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(220, 38, 38, 0.44);
    filter: brightness(1.04);
}

.btn--danger:active:not(:disabled) {
    transform: scale(0.98);
}

.btn--danger:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.btn--danger i { font-size: 16px; color: #fff; }

/* Existing receipts banner shown at top of Advanced panel in edit mode */
.edit-receipts-banner {
    margin-bottom: var(--space-3);
    padding: var(--space-3);
    background: rgba(59, 130, 246, 0.06);
    border: 1px solid rgba(59, 130, 246, 0.2);
    border-radius: var(--r-md);
}

.edit-receipts-banner__title {
    margin: 0 0 var(--space-2);
    font-size: 11px;
    font-weight: var(--fw-semi, 600);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #1d4ed8;
    display: flex;
    align-items: center;
    gap: 6px;
}

.edit-receipts-banner__title i { font-size: 14px; }

.edit-receipts-banner__thumbs {
    display: flex;
    gap: var(--space-2);
}

.edit-receipts-banner__thumb {
    width: 56px;
    height: 56px;
    border-radius: var(--r-md);
    overflow: hidden;
    border: 1px solid var(--border-soft, #e2e8f0);
    background: #f8fafc;
    cursor: zoom-in;
    padding: 0;
}

.edit-receipts-banner__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}


/* ================================================================
   31. SEGMENTED — 4-chip variant (Expense/Income/Transfer/Custom)
================================================================ */

.segmented--4 .segmented__option {
    font-size: 12px;
    padding: var(--space-2) 6px;
}

/* 🆕 v3.1.0 Phase G2b — 2-chip variant (Pay Debt: Repay | Borrow) */
.segmented--2 .segmented__option {
    font-size: 13px;
    padding: 10px 8px;
    flex: 1;
}

.segmented__option--custom {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
}

/* 🆕 v3.1.0 Phase G2b — Pay Debt Repay/Borrow toggle wrapper */
.tx-field--paydebt-toggle { margin-bottom: 12px; }

/* 🆕 v3.1.0 Phase G8 rev2 — Pay Debt (Repay) INTEREST row uses .tx-fee-row style
   (own row after AMOUNT · blue ฿ · 22px mono · 48px). ID override defeats .is-kb-active. */
#txPayDebtInterest,
#txPayDebtInterest:focus,
#txPayDebtInterest.is-kb-active,
#txPayDebtInterest:focus-visible {
    -webkit-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
}

/* 🆕 v3.1.0 Phase G6e — Top-up FEE row: match .tx-amount-row style (draft §5 line 641)
   Same 48px height, blue ฿ prefix, IBM Plex Mono 22px right-aligned input,
   focus-within accent, ID-based UA reset. */
.tx-fee-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 48px;
    padding: 0 14px;
    border: 1px solid var(--pf-line, #eaedf1);
    border-radius: 12px;
    background: var(--pf-card, #ffffff);
    transition: border-color 140ms;
}
.tx-fee-row:focus-within {
    border-color: var(--pf-primary, #2563eb);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.08);
}
.tx-fee-row__currency {
    font-size: 15px;
    font-weight: 700;
    color: var(--pf-primary, #2563eb);
    flex-shrink: 0;
}
.tx-fee-input {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    border: none;
    outline: none;
    box-shadow: none;
    color: var(--pf-ink, #0e1f44);
    font-family: 'IBM Plex Mono', monospace;
    font-size: 22px;
    font-weight: 700;
    text-align: right;
    padding: 0;
    font-variant-numeric: tabular-nums;
    min-width: 0;
}
.tx-fee-input::placeholder { color: #cbd5e1; font-weight: 500; }
.tx-fee-input:focus::placeholder { color: transparent; }

/* ID-based override — defeats shared .is-kb-active rule (numpad open state)
   the same way #txAmount does. Keeps FEE input transparent + borderless in all states. */
#txFee,
#txFee:focus,
#txFee.is-kb-active,
#txFee:focus-visible {
    -webkit-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
}

.tx-fee-hint {
    margin: 6px 2px 0;
    font-size: 11.5px;
    color: var(--pf-muted-2, #64748b);
    line-height: 1.4;
}
.tx-fee-hint strong { color: var(--pf-primary, #2563eb); }

/* ============================================
   🆕 v3.1.0 Phase G7 — Custom sheet (Advanced) polish (draft §5 line 825-870)
   Compact single-row lines · running total top · inline add · min 2 lines lock
   ============================================ */

/* Running total box (top of #txAdvanced) — 🆕 G7 rev — CENTERED per draft §5 line 833.
   Label small caption top · big 22px value below centered. */
.tx-adv-running {
    display: flex; flex-direction: column; align-items: center;
    padding: 14px;
    background: #f5f6f9;
    border: 1px solid #eaedf1;
    border-radius: 10px;
    margin-bottom: 12px;
    text-align: center;
    gap: 4px;
}
.tx-adv-running__label {
    margin: 0;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--pf-muted-2, #8a94a3);
}
.tx-adv-running__value {
    margin: 0;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 22px;
    font-weight: 700;
    color: var(--pf-ink-2, #3a4250);
}
.tx-adv-running__value--pos { color: var(--pf-success, #16a34a); }
.tx-adv-running__value--neg { color: var(--pf-danger,  #dc2626); }

/* Lines section header */
.tx-adv-lines-head {
    display: flex; justify-content: space-between; align-items: center;
    padding: 0 2px;
    margin-bottom: 8px;
}
.tx-adv-lines-title {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--pf-muted-1, #5a6472);
}
.tx-adv-lines-hint {
    font-size: 11px;
    color: var(--pf-muted-2, #94a3b8);
    font-style: italic;
}

/* Compact lines container — draft §5 line 838 pattern */
.tx-lines--compact {
    display: flex; flex-direction: column;
    background: var(--pf-card, #fff);
    border: 1px solid var(--pf-line, #eaedf1);
    border-radius: 10px;
    overflow: hidden;
}
.tx-lines--compact .tx-line {
    display: grid;
    grid-template-columns: 26px 1fr 100px 28px;   /* 🆕 G7c — delete 28 to balance with amount */
    gap: 10px;
    align-items: center;
    padding: 10px 12px;
    /* Reset legacy styles */
    background: transparent;
    border: none;
    border-radius: 0;
    margin: 0;
    flex-direction: unset;
}
.tx-lines--compact .tx-line + .tx-line {
    border-top: 1.5px solid var(--pf-line, #eaedf1);
}

/* Dr/Cr toggle circle — 🆕 G7 rev — 26×26 per draft §5 line 840/854 */
.tx-lines--compact .tx-line__hint {
    width: 26px; height: 26px;
    min-width: unset;
    padding: 0;
    border-radius: 50%;
    background: #f5f6f9;                /* default (—) grey */
    color: #8a94a3;
    border: 1.5px solid #e2e8f0;
    display: grid; place-items: center;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0;
    cursor: pointer;
    transition: transform 140ms, background 140ms, border-color 140ms, color 140ms;
}
.tx-lines--compact .tx-line__hint.is-dr {
    background: var(--pf-primary, #2563eb);
    color: #ffffff;
    border-color: var(--pf-primary, #2563eb);
}
.tx-lines--compact .tx-line__hint.is-cr {
    background: transparent;
    color: var(--pf-primary, #2563eb);
    border-color: #93c5fd;
}
.tx-lines--compact .tx-line__hint:active { transform: scale(0.92); }

/* Combobox slot — flex-friendly (overrides existing .tx-line__cb) */
.tx-lines--compact .tx-line__cb {
    min-width: 0;    /* enables ellipsis in flex/grid children */
}
.tx-lines--compact .tx-line .combobox__trigger {
    padding: 4px 8px;
    height: auto;
    min-height: unset;
    background: transparent;
    border: none;
    box-shadow: none;
}
.tx-lines--compact .tx-line .combobox__display { gap: 8px; }
.tx-lines--compact .tx-line .combobox__caret   { display: none; }   /* row is single-line — chevron redundant */

/* Amount input — right-align mono, borderless (matches Payslip pattern) */
.tx-lines--compact .tx-line__amount {
    height: auto;
    padding: 6px 4px;
    border: none;
    background: transparent;
    text-align: right;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 13px;
    font-weight: 600;
    color: var(--pf-ink, #0e1f44);
    border-radius: 6px;
    outline: none;
    box-shadow: none;
}
.tx-lines--compact .tx-line__amount:hover:not(:focus) { background: rgba(0, 0, 0, 0.04); }
.tx-lines--compact .tx-line__amount:focus             { background: rgba(31, 95, 230, 0.08); }
.tx-lines--compact .tx-line__amount::placeholder      { color: #cbd5e1; font-weight: 400; }

/* 🆕 G7 rev — Draft §5 line 857 pattern: Cr amount rendered in a lighter grey
   to visually distinguish "credit / negative side" from Dr (dark). Applied
   via data-entry-id attribute set on .tx-line by toggleEntry(). */
.tx-lines--compact .tx-line[data-entry-id="1"] .tx-line__amount {
    color: #7a8494;    /* Cr = greyed */
    font-weight: 500;
}
.tx-lines--compact .tx-line[data-entry-id="2"] .tx-line__amount {
    color: var(--pf-ink-2, #3a4250);   /* Dr = dark */
    font-weight: 700;
}

/* Delete button — 🆕 G7c — SQUARE (rounded rectangle 6px) per user preference.
   Size 28×28 to visually balance with .tx-line__amount (~28px effective height).
   Matches Payslip .tx-payslip__row-del pattern for consistency. Dark icon (#3a4250)
   matches amount active state · soft red hover. */
.tx-lines--compact .tx-line__remove {
    width: 28px; height: 28px;
    padding: 0;
    background: transparent;
    color: #3a4250;                       /* dark — matches amount active */
    border: none;
    border-radius: 6px;                    /* square rounded */
    display: grid; place-items: center;
    font-size: 18px;                       /* proportional to 28×28 size */
    cursor: pointer;
    transition: background 140ms, color 140ms, transform 140ms;
}
.tx-lines--compact .tx-line__remove:hover:not(:disabled) {
    background: rgba(220, 38, 38, 0.10);   /* subtle red tint (was solid red) */
    color: var(--pf-danger, #dc2626);
}
.tx-lines--compact .tx-line__remove:active:not(:disabled) { transform: scale(0.9); }
.tx-lines--compact .tx-line__remove:disabled,
.tx-lines--compact .tx-line__remove.is-locked {
    opacity: 0.3;
    cursor: not-allowed;
    background: transparent;
    color: #3a4250;                        /* stay dark but faded via opacity */
}

/* Inline add-line row inside .tx-lines--compact — 🆕 G7 rev2 — restored divider
   above (was removed but felt too empty per user feedback). Matches Payslip pattern
   for visual consistency. :first-child override for the (unlikely) empty case. */
.tx-lines--compact .tx-add-inline {
    display: flex; align-items: center; gap: 9px;
    padding: 10px 12px;
    background: transparent;
    border: 0;
    border-top: 1.5px solid var(--pf-line, #eaedf1);   /* divider from row above */
    color: var(--pf-muted-2, #8a94a3);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    width: 100%;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    transition: color 140ms, background 140ms;
}
.tx-lines--compact .tx-add-inline:first-child { border-top: 0; }
.tx-lines--compact .tx-add-inline i { font-size: 16px; }
.tx-lines--compact .tx-add-inline:hover  { color: var(--pf-primary, #2563eb); background: #f0f7ff; }
.tx-lines--compact .tx-add-inline:active { background: rgba(37, 99, 235, 0.08); }

/* Balance status pill — 🆕 G7 rev — draft §5 line 862: single-line combined
   "✓ Balanced — Dr = Cr (฿3,200 = ฿3,200)". Values embedded IN the status string
   (via JS) so it reads as one message rather than 2 columns. */
.tx-adv-balance {
    display: flex; align-items: center; justify-content: center;
    padding: 8px 11px;
    margin-top: 11px;
    background: #f5f6f9;
    border: 1.5px solid #eaedf1;
    border-radius: 8px;
}
.tx-adv-balance__status {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px;
    font-weight: 600;
}
.tx-adv-balance__status i { font-size: 14px; }
.tx-adv-balance__status--ok    { color: var(--pf-success, #16a34a); }
.tx-adv-balance__status--warn  { color: var(--pf-muted-2, #64748b); }
.tx-adv-balance__status--error { color: var(--pf-warning, #b26a00); }
/* 🆕 G7 rev — Legacy .tx-adv-balance__totals hidden (values merged into status text) */
.tx-adv-balance__totals { display: none; }

/* ============================================
   🆕 v3.1.0 Phase G5a — Form Component Library
   Reusable atoms for Add Transaction forms + other sheets (Account form, Setup, etc.).
   Draft §5 defines a consistent visual grammar — this library codifies it as classes.
   ============================================ */

/* Icon box — colored tint square with icon inside (used inline in fields/rows) */
.tx-icon-box {
    width: 26px; height: 26px;
    border-radius: 8px;
    display: grid; place-items: center;
    font-size: 15px;
    flex-shrink: 0;
}
.tx-icon-box--asset   { background: #eef2ff; color: var(--pf-primary, #2563eb); }
.tx-icon-box--liab    { background: #fef2f2; color: var(--pf-danger,  #dc2626); }
.tx-icon-box--expense { background: #fef2f2; color: var(--pf-danger,  #dc2626); }
.tx-icon-box--revenue { background: #f0fdf4; color: var(--pf-success, #16a34a); }
.tx-icon-box--equity  { background: #f5f3ff; color: #7c3aed; }
.tx-icon-box--cash    { background: #f8fafc; color: #64748b; }
.tx-icon-box--muted   { background: #f8fafc; color: #64748b; }

/* Type badge pill — inline label showing account type (ASSET/EXPENSE/LIABILITY/…) */
.tx-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.03em;
    white-space: nowrap;
    text-transform: uppercase;
    line-height: 1.4;
}
.tx-badge--asset   { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
.tx-badge--liab    { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.tx-badge--expense { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.tx-badge--revenue { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
.tx-badge--equity  { background: #f5f3ff; color: #6d28d9; border: 1px solid #ddd6fe; }
.tx-badge--cash    { background: #f8fafc; color: #475569; border: 1px solid #e2e8f0; }

/* Sticky balance hint box — draft §5 line 629/743/767 pattern.
   Shown near the footer to remind user of the relevant account's balance. */
.tx-balance-hint {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 11px;
    background: #f5f6f9;
    border: 1px solid #eaedf1;
    border-radius: 8px;
    margin: 6px 0;
    font-size: 12px;
    color: var(--pf-muted-2, #64748b);
}
.tx-balance-hint__label {
    display: flex; align-items: center; gap: 6px;
    font-weight: 500;
}
.tx-balance-hint__label i { font-size: 13px; color: #94a3b8; }
.tx-balance-hint__value {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--pf-ink-2, #3a4250);
}
.tx-balance-hint--warn .tx-balance-hint__value {
    color: var(--pf-danger, #dc2626);
}

/* Gradient primary button — 🆕 v3.1.0 Phase G5a rev — restored to app's original
   blue→cyan gradient (`#3b82f6 → #06b6d4`) per user preference. Disabled state uses
   opacity fade (kept from original .btn--primary:disabled) so the button reads as
   "light blue" when inactive instead of grey. Draft §5's dark-blue variant is
   deferred as an alternate reference — user preference wins. */
.btn--gradient {
    background: var(--brand-gradient);
    color: #ffffff;
    border: none;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
    font-weight: 700;
    transition: transform 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1)),
                box-shadow 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1)),
                opacity   140ms;
}
.btn--gradient:hover:not(:disabled)  { transform: translateY(-1px); box-shadow: 0 8px 20px rgba(59, 130, 246, 0.38); }
.btn--gradient:active:not(:disabled) { transform: translateY(0) scale(0.99); box-shadow: 0 2px 6px rgba(59, 130, 246, 0.32); }
.btn--gradient:disabled,
.btn--gradient[disabled] {
    opacity: 0.5;
    box-shadow: none;
    cursor: not-allowed;
    transform: none;
}

/* ============================================
   🆕 v3.1.0 Phase G4b — Compound title wrap (draft §5 header pattern)
   Allows subtype icon + title + flag to appear inline in tx-screen__header
   ============================================ */
.tx-screen__title-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}
.tx-screen__subtype-icon {
    width: 28px; height: 28px;
    border-radius: 9px;
    background: #eef2ff;
    color: var(--pf-primary, #2563eb);
    display: grid;
    place-items: center;
    font-size: 16px;
    flex-shrink: 0;
}
.tx-screen__title-wrap .tx-screen__title { margin: 0; flex-shrink: 0; }
.tx-screen__subtype-flag {
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--pf-primary-tint, #E8EEFB);
    color: var(--pf-primary, #2563eb);
    font-size: 10.5px;
    font-weight: 600;
    white-space: nowrap;
    letter-spacing: 0.02em;
}
/* Dark navy sheet variant — invert subtype icon/flag colors */
.app-sheet--full .tx-screen__subtype-icon {
    background: rgba(59, 130, 246, 0.2);
    color: #93c5fd;
}
.app-sheet--full .tx-screen__subtype-flag {
    background: rgba(59, 130, 246, 0.15);
    color: #bfdbfe;
}

/* ============================================
   🆕 v3.1.0 Phase G4 — Payslip Wizard (draft §5 line 651-707)
   Multi-row: Earnings / Deductions / Custom Dr-Cr · Net summary · Balance status
   ============================================ */
/* 🆕 v3.1.0 Phase G4d — padding-top adds breathing room between the sheet header
   (where subtype icon+title live) and the template chip below. Matches draft §5
   spacing (~10-12px). */
#txPayslip {
    display: flex; flex-direction: column;
    gap: 14px;
    padding-top: 12px;
}

/* 🆕 v3.1.0 Phase G4b — Template chip layout matches draft §5 line 657-662
   {bookmark icon + template-name placeholder + spacer + "Use template" action}
   Disabled state until backend integration (G4c). */
.tx-payslip__template-chip {
    display: flex; align-items: center; gap: 9px;
    padding: 9px 12px;
    background: #f5f6f9;
    border: 1.5px dashed #c4ccd6;
    border-radius: 9px;
    color: var(--pf-muted-1, #5a6472);
    font-size: 12.5px;
    opacity: 0.75;      /* disabled visual hint */
    cursor: not-allowed;
}
.tx-payslip__template-icon {
    color: #8a94a3;
    font-size: 16px;
    flex-shrink: 0;
}
.tx-payslip__template-name {
    flex: 1;
    min-width: 0;
    font-weight: 500;
    color: #94a3b8;
    font-style: italic;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tx-payslip__template-action {
    flex-shrink: 0;
    font-weight: 600;
    color: var(--pf-muted-1, #5a6472);
    font-size: 11.5px;
}

/* Section blocks — Earnings / Deductions / Custom */
.tx-payslip__section { display: flex; flex-direction: column; gap: 8px; }
.tx-payslip__section-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 2px;
}
.tx-payslip__section-title {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--pf-muted-1, #5a6472);
}
.tx-payslip__section-hint {
    font-weight: 500;
    text-transform: none;
    color: #c4ccd6;
    letter-spacing: 0;
    font-size: 11px;
}
.tx-payslip__section-total {
    font-size: 12px;
    font-weight: 700;
    color: var(--pf-ink, #0e1f44);
}
.tx-payslip__section-total--neg { color: var(--pf-danger, #dc2626); }

/* Row list container — 🆕 v3.1.0 Phase G4h — REVERTED from Direction 1.
   User wants dividers preserved with container box (as in G4d state).
   Amount input frame handled separately below. */
.tx-payslip__rows {
    display: flex; flex-direction: column;
    background: var(--pf-card, #fff);
    border: 1px solid var(--pf-line, #eaedf1);
    border-radius: 10px;
    overflow: hidden;
}
.tx-payslip__rows:empty { display: none; }

/* 🆕 v3.1.0 Phase G4d rev2 — Explicit divider per element (source-order safe).
   Previous `> * + *` approach was silently overridden by button's `border: none`
   shorthand in .tx-payslip__add-inline (later in file wins with equal specificity).
   New approach: each element declares its own border-top; :first-child override
   handles the "empty section" case where add-inline stands alone. */

/* Individual row — 🆕 v3.1.0 Phase G4h — REVERTED to G4d padding (10x12).
   Divider between siblings via `.row + .row` (row-to-row); add-inline handles
   its own top border. */
.tx-payslip__row {
    display: grid;
    grid-template-columns: 32px 1fr 88px 28px;
    gap: 9px;
    align-items: center;
    padding: 10px 12px;
}
.tx-payslip__row + .tx-payslip__row {
    border-top: 1px solid var(--pf-line, #eaedf1);
}

/* Row icon (Earnings green trending-up · Deductions grey receipt · Custom Dr/Cr circle) */
.tx-payslip__row-icon {
    width: 28px; height: 28px;
    border-radius: 9px;
    display: grid; place-items: center;
    font-size: 15px;
}
.tx-payslip__row-icon--earn   { background: #f0fdf4; color: #16a34a; }
.tx-payslip__row-icon--ded    { background: #f8fafc; color: #64748b; }
.tx-payslip__row-icon--liab   { background: #fef2f2; color: #dc2626; }
.tx-payslip__row-icon--muted  { background: #f8fafc; color: #64748b; }

/* Dr/Cr toggle circle (Custom section) — matches Custom sheet draft */
.tx-payslip__drcr {
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--pf-primary, #2563eb);
    color: #fff;
    border: 1.5px solid transparent;
    display: grid; place-items: center;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 10.5px;
    font-weight: 700;
    cursor: pointer;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    transition: transform 140ms;
}
.tx-payslip__drcr:active { transform: scale(0.95); }
/* Cr variant — outlined instead of solid (matches Custom sheet toggle draft) */
.tx-payslip__drcr--cr {
    background: transparent;
    border-color: #93c5fd;
    color: var(--pf-primary, #2563eb);
}

/* Row account picker button */
.tx-payslip__row-account {
    display: flex; align-items: center; gap: 6px;
    padding: 6px 4px;
    border: none;
    background: transparent;
    cursor: pointer;
    color: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    min-width: 0;
}
.tx-payslip__row-account.is-empty .tx-payslip__row-name { color: #94a3b8; font-style: italic; }
.tx-payslip__row-name {
    flex: 1; min-width: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--pf-ink, #0e1f44);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tx-payslip__row-account i { color: #cbd5e1; font-size: 16px; flex-shrink: 0; }

/* Row amount input — 🆕 v3.1.0 Phase G4f — Option A (borderless + focus tint).
   Idle: pure text look (no border, transparent bg) matching draft §5 minimal
   aesthetic. Hover: subtle grey wash hints at editability. Focus: blue wash
   confirms active editing. Removes visual "box noise" that came from stacking
   many bordered inputs down the row list. */
.tx-payslip__row-amount {
    text-align: right;
    padding: 6px 4px;
    border: none;
    border-radius: 6px;
    background: transparent;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 13px;
    font-weight: 500;
    color: var(--pf-ink, #0e1f44);
    width: 100%;
    min-width: 0;
    outline: none;
    transition: background 140ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.tx-payslip__row-amount:hover:not(:focus) { background: rgba(0, 0, 0, 0.04); }
.tx-payslip__row-amount:focus             { background: rgba(31, 95, 230, 0.08); }
.tx-payslip__row-amount::placeholder      { color: #cbd5e1; font-weight: 400; }

/* 🆕 v3.1.0 Phase G4g — Amount color by direction of money flow:
     Earnings (received) → green
     Deductions (paid out) → red
     Customs Cr (received)  → green (via data-entry="1")
     Customs Dr (paid out)  → red   (via data-entry="2")
   Placeholder color stays grey so empty rows don't shout red/green. */
.tx-payslip__row[data-row-section="earnings"]   .tx-payslip__row-amount,
.tx-payslip__row[data-row-section="customs"][data-entry="1"] .tx-payslip__row-amount {
    color: var(--pf-success, #16a34a);
    font-weight: 600;
}
.tx-payslip__row[data-row-section="deductions"] .tx-payslip__row-amount,
.tx-payslip__row[data-row-section="customs"][data-entry="2"] .tx-payslip__row-amount {
    color: var(--pf-danger, #dc2626);
    font-weight: 600;
}

/* Row delete button — 🆕 v3.1.0 Phase G7c — SQUARE per user preference (was circle).
   Transparent bg · dark icon (#3a4250) matches amount active · soft red hover. */
.tx-payslip__row-del {
    width: 28px; height: 28px;
    border-radius: 6px;                        /* square rounded (was 50% circle) */
    background: transparent;                   /* was #f5f6f9 grey fill */
    color: #3a4250;                            /* dark — matches .tx-line__amount */
    border: none;
    display: grid; place-items: center;
    font-size: 18px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 140ms, background 140ms, transform 140ms;
}
.tx-payslip__row-del:hover  {
    background: rgba(220, 38, 38, 0.10);      /* subtle red tint (was solid red fill) */
    color: var(--pf-danger, #dc2626);
}
.tx-payslip__row-del:active { transform: scale(0.9); }

/* 🆕 v3.1.0 Phase G4b — Add-row rendered INSIDE the .tx-payslip__rows container
   (matches draft §5 line 669/678/689). No dashed border — plain row-styled text
   that visually belongs with the other rows above it.
   🆕 v3.1.0 Phase G4d rev2 — explicit `border-top` for divider from row above.
   `:first-child` override handles the empty-section case where add-inline is alone.
   Note: `border-top` declared LAST after `border: 0` so it takes effect. */
.tx-payslip__add-inline {
    display: flex; align-items: center; gap: 9px;
    padding: 10px 12px;
    background: transparent;
    border: 0;   /* reset button native (all sides) */
    border-top: 1px solid var(--pf-line, #eaedf1);   /* divider from row above */
    color: var(--pf-muted-2, #8a94a3);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    width: 100%;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    transition: color 140ms, background 140ms;
}
.tx-payslip__add-inline:first-child { border-top: 0; }   /* empty section — no divider needed */
.tx-payslip__add-inline i { font-size: 16px; }
.tx-payslip__add-inline:hover  { color: var(--pf-primary, #2563eb); background: #f0f7ff; }
.tx-payslip__add-inline:active { background: rgba(37, 99, 235, 0.08); }

/* Legacy add-row (kept in case any callers still use it — no-op unless present) */
.tx-payslip__add-row { display: none; }

/* Net summary box */
.tx-payslip__summary {
    padding: 14px;
    background: #f5f6f9;
    border: 1px solid var(--pf-line, #eaedf1);
    border-radius: 10px;
    display: flex; flex-direction: column; gap: 6px;
}
.tx-payslip__summary-row {
    display: flex; justify-content: space-between; align-items: baseline;
    font-size: 12.5px;
    color: var(--pf-muted-2, #8a94a3);
}
.tx-payslip__summary-lbl { }
.tx-payslip__summary-val {
    font-family: 'IBM Plex Mono', monospace;
    font-weight: 600;
    color: var(--pf-ink-2, #2b3242);
}
.tx-payslip__summary-val--neg { color: var(--pf-danger, #dc2626); }
.tx-payslip__summary-row--net {
    padding-top: 8px;
    border-top: 1.5px solid #dde2e9;
    margin-top: 2px;
}
.tx-payslip__summary-row--net .tx-payslip__summary-lbl {
    font-size: 13px; font-weight: 700; color: var(--pf-ink, #0e1f44);
}
.tx-payslip__summary-val--net {
    font-size: 15px; font-weight: 700; color: var(--pf-ink, #0e1f44);
}

/* 🆕 v3.1.0 Phase G4b — Balance status embedded INSIDE summary box (draft §5 line 693-697)
   White inner box on the grey summary background — visual "card in a card" pattern. */
.tx-payslip__summary .tx-payslip__balance {
    display: flex; justify-content: space-between; align-items: center;
    padding: 9px 11px;
    margin-top: 10px;
    border: 1.5px solid #d3d9e0;
    border-radius: 8px;
    background: #ffffff;
    font-size: 12px;
}
.tx-payslip__balance-lbl { color: var(--pf-muted-2, #8a94a3); font-weight: 500; }
.tx-payslip__balance-status {
    display: inline-flex; align-items: center; gap: 6px;
    font-weight: 600;
}
.tx-payslip__balance-status i { font-size: 14px; }
.tx-payslip__balance-status--ok    { color: var(--pf-success, #16a34a); }
.tx-payslip__balance-status--error { color: var(--pf-warning, #b26a00); }

.segmented__option--custom i {
    font-size: 14px;
}

/* When Custom is active, give it a hint of the gradient brand color */
.segmented__option--custom.is-active {
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(6, 182, 212, 0.2)) !important;
    color: #1d4ed8 !important;
    border-color: rgba(59, 130, 246, 0.4) !important;
}


/* ================================================================
   32. REPORTS PAGE — summary cards + chart sections + legend
================================================================ */

/* .reports-page__header removed — Reports now uses .security-page-head
   (shared with Security / Budget). */

.reports-periods {
    margin-bottom: var(--space-3);
}

/* Summary cards (3 in a row) — responsive font, no break-all */
.report-summary {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));  /* allow shrink */
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.report-card {
    padding: var(--space-2) 10px;        /* tighter padding for small phones */
    background: var(--surface-1, #fff);
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: var(--r-md);
    text-align: left;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    min-width: 0;                         /* allow grid item to shrink */
    overflow: hidden;
}

.report-card__label {
    margin: 0;
    font-size: 10px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.report-card__value {
    margin: 4px 0 2px;
    /* Responsive: shrinks on narrow phones, grows on tablets */
    font-size: clamp(13px, 3.6vw, 18px);
    font-weight: var(--fw-bold, 700);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
    /* Allow wrap only if absolutely necessary — prefer single line */
    overflow-wrap: anywhere;
    word-break: normal;
}

/* Larger padding back on tablets / wide screens */
@media (min-width: 480px) {
    .report-card { padding: var(--space-3); }
}

/* Super narrow phones — go single column to avoid cramped 3-up */
@media (max-width: 340px) {
    .report-summary { grid-template-columns: 1fr 1fr; }
    .report-summary .report-card:last-child { grid-column: 1 / -1; }
}

.report-card__delta {
    margin: 0;
    font-size: 10px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

.report-card__delta .is-up   { color: #059669; font-weight: 600; }
.report-card__delta .is-down { color: #dc2626; font-weight: 600; }

.report-card--income .report-card__value  { color: #059669; }
.report-card--expense .report-card__value { color: #dc2626; }
/* 🆕 v3.1.0 Phase R Round 1 — Net value in brand blue per draft §9 line 1991 */
.report-card--net     .report-card__value { color: var(--brand-600, #2563eb); }

/* Chart section */
/* 🆕 v3.1.0 Phase R Round 1 — upgraded to brand-tinted lift matching .card
   and .auth-methods-card for a consistent card language across all pages. */
.report-section {
    margin-bottom: var(--space-5);
    padding: var(--space-3);
    background: var(--surface-1, #fff);
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: var(--r-xl, 16px);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}

/* 🆕 v3.1.0 Phase R Round 3 — section header refined per draft §9 lines
   1995/2031 pattern: no divider line (whitespace does the job), title +
   right-aligned subtitle in a muted pill. Tighter line-height. */
.report-section__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    padding-bottom: 0;
    border-bottom: none;
}

.report-section__title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    letter-spacing: -0.005em;
}

/* Subtitle (right side) as a small muted pill — e.g. "Last 6 months",
   "฿29,400 total". */
.report-section__sub {
    font-size: 11.5px;
    color: var(--text-muted, #94a3b8);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--surface-2, #f1f5f9);
    white-space: nowrap;
}

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

/* Doughnut + legend layout */
/* 🆕 v3.1.0 Phase R Round 5 — tightened side-by-side layout for wider
   phones; cleaner stack behavior on narrow phones (see @480 breakpoint). */
.report-donut-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    justify-content: flex-start;
}

.report-donut-wrap {
    flex: 0 0 160px;        /* 🆕 R5: 180 → 160 to let legend get more room */
    max-width: 160px;
    aspect-ratio: 1 / 1;
}

.report-donut-wrap canvas {
    width: 100% !important;
    height: 100% !important;
}

/* ============================================
   Report legend — card row + mini progress bar (2026-07-04 redesign)
   Used by Reports (Expense/Income) AND Balance Sheet (Assets/Liabs).
   Requires matching JS markup: __row wrapping swatch+name+meta, and
   __bar > __bar-fill row below. See assets/js/reports.js.
   ============================================ */
.report-legend {
    flex: 1 1 220px;
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.report-legend__item {
    display: block;                        /* stack of row + bar */
    padding: 10px 12px;
    border-radius: var(--r-md, 10px);
    background: var(--surface-1, #ffffff);
    border: 1px solid var(--border-subtle, rgba(148, 163, 184, 0.18));
    transition: background 0.15s ease, transform 0.12s ease, border-color 0.15s ease;
}

.report-legend__item:hover {
    background: var(--surface-2, rgba(148, 163, 184, 0.06));
    border-color: var(--border-strong, rgba(148, 163, 184, 0.28));
    transform: translateY(-1px);
}

/* 🆕 v3.1.0 Phase N §12 rev — "Other" row expandable detail
   Tap row → nested list reveals the rolled-up categories.
   Chevron rotates 180° on expand. */
.report-legend__item.is-other .report-legend__row {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.report-legend__chevron {
    margin-left: 6px;
    font-size: 16px;
    color: #94a3b8;
    transition: transform 180ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.report-legend__item.is-expanded .report-legend__chevron {
    transform: rotate(180deg);
    color: #2563eb;
}
.report-legend__nested {
    list-style: none;
    margin: 10px 0 0;
    padding: 10px 0 0;
    border-top: 1px dashed var(--border-soft, #eaedf1);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.report-legend__nested[hidden] { display: none; }
.report-legend__nested-item {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 4px 8px 4px 20px;    /* indent — visually "nested under" Other */
    position: relative;
    font-size: 12px;
    color: #64748b;
}
.report-legend__nested-item::before {
    /* little dot indicator */
    content: '';
    position: absolute;
    left: 8px;
    top: 50%;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #cbd5e1;
    transform: translateY(-50%);
}
.report-legend__nested-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #475569;
    font-weight: 500;
}
.report-legend__nested-meta {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    font-variant-numeric: tabular-nums;
}

.report-legend__row {
    display: grid;
    grid-template-columns: 10px 1fr auto;   /* 🆕 R2: swatch is 10px square (was 12px dot) */
    align-items: center;
    gap: 10px;
    min-width: 0;
}

/* 🆕 v3.1.0 Phase R Round 2 — rounded-square swatch per draft §9 line 2039:
   `width:9px;height:9px;border-radius:2px`. Reads as a legend marker (not a
   bullet point) and visually distinguishes from the circular donut arcs. */
.report-legend__swatch {
    width: 10px;
    height: 10px;
    border-radius: 2.5px;
    flex-shrink: 0;
}

.report-legend__name {
    color: var(--text-primary);
    font-weight: var(--fw-semi, 600);
    font-size: 14px;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.report-legend__meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    line-height: 1.15;
    flex-shrink: 0;
}

.report-legend__amount {
    color: var(--text-primary);
    font-weight: var(--fw-semi, 600);
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

.report-legend__pct {
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    text-align: right;
    white-space: nowrap;
}

/* Mini progress bar echoes the doughnut slice colour + magnitude */
/* 🆕 v3.1.0 Phase R Round 2 — height 4→5 and radius 999→3 to match
   draft §9 line 2040 (`height:5px;border-radius:3px`). Reads crisper
   under the row name and makes the magnitude easier to compare. */
.report-legend__bar {
    height: 5px;
    background: #e6eaef;
    border-radius: 3px;
    margin-top: 8px;
    overflow: hidden;
}

.report-legend__bar-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

.report-empty {
    text-align: center;
    padding: var(--space-6) var(--space-3);
    color: var(--text-secondary);
    font-size: var(--fs-caption);
    margin: 0;
}

.report-empty i {
    display: block;
    font-size: 32px;
    color: rgba(100, 116, 139, 0.5);
    margin-bottom: 8px;
}

/* Mobile: stack donut + legend vertically */
/* 🆕 v3.1.0 Phase R Round 5 — donut 220→180 on mobile so legend gets more
   vertical room and small-phone users don't scroll past a dominating ring. */
@media (max-width: 480px) {
    .report-donut-row {
        flex-direction: column;
        align-items: center;
        gap: var(--space-3);
    }
    .report-donut-wrap {
        flex-basis: 180px;
        max-width: 180px;
    }
    .report-legend {
        flex-basis: auto;
        width: 100%;
    }
}
@media (max-width: 360px) {
    .report-donut-wrap {
        flex-basis: 150px;
        max-width: 150px;
    }
}

/* Compact summary cards on narrow screens */
@media (max-width: 360px) {
    .report-card__value { font-size: 14px; }
}


/* ================================================================
   33. CUSTOM NUMPAD — mobile-only on-screen numeric keypad
================================================================ */

/* ----- iOS-style numpad (bigger keys + brand accent) ----- */
.numpad {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9500;
    transform: translateY(100%);
    transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
    pointer-events: none;
}

.numpad.is-open {
    transform: translateY(0);
    pointer-events: auto;
}

.numpad__backdrop { display: none; }

/* iOS keyboard tray: subtle slate so white keys pop, brand-aligned */
.numpad__sheet {
    position: relative;
    width: 100%;
    background: #dbe1e8;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    box-shadow: 0 -6px 24px rgba(15, 23, 42, 0.10);
    /* 🆕 v3.1.1 rev4 — lift numpad keys above home-indicator chin
       (was: + 10px, now: + 22px). */
    padding: 8px 6px calc(env(safe-area-inset-bottom, 0px) + 22px);
}

/* Drag grip — iOS-style hint at top of sheet */
.numpad__grip {
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: rgba(15, 23, 42, 0.22);
    margin: 2px auto 8px;
}

/* Grid: 3 cols × 4 rows — big keys */
.numpad__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    padding: 0 4px;
}

.numpad__key {
    height: 58px;
    border: none;
    border-radius: 10px;
    background: #ffffff;
    color: var(--text-primary, #0f172a);
    font-family: inherit;
    /* VKB Premium Polish (v3.1.2+ · owner choice) —
       slightly bigger digit, lighter weight, tight tracking for the
       modern iOS-17 feel. */
    font-size: 28px;
    font-weight: 400;
    letter-spacing: -0.5px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Spring-ease on press/release gives a tiny bounce without feeling slow. */
    transition:
        background 0.12s ease,
        box-shadow 0.12s ease,
        transform 0.08s cubic-bezier(0.34, 1.56, 0.64, 1);
    -webkit-tap-highlight-color: transparent;
    /* Three-layer shadow for a glossy physical key:
         1. hairline bottom edge (depth)
         2. soft diffuse drop
         3. inset top highlight (makes the top rim catch light) */
    box-shadow:
        0 1px 0  rgba(15, 23, 42, 0.14),
        0 2px 4px rgba(15, 23, 42, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    font-variant-numeric: tabular-nums;
    user-select: none;
}

.numpad__key:active,
.numpad__key.is-pressed {
    /* Soft brand-blue gradient fill + inner ring on press. */
    background: linear-gradient(135deg,
        rgba(59, 130, 246, 0.16),
        rgba(29, 78, 216, 0.08));
    transform: translateY(1px) scale(0.98);
    box-shadow:
        inset 0 0 0 1px rgba(59, 130, 246, 0.30),
        0 0 0 rgba(15, 23, 42, 0);
}

.numpad__key--dot {
    font-size: 32px;
    /* Dot sits a hair above center visually at this size — nudge down 2px */
    line-height: 1;
    padding-bottom: 2px;
}

/* Backspace — semantic red tint (clearly "destructive" without shouting).
   Previously slate gray (#c1c8d2); the new tint makes the delete action
   recognizable at a glance while keeping contrast with the digit keys. */
.numpad__key--back {
    background: rgba(239, 68, 68, 0.08);
    color: #dc2626;
    box-shadow:
        0 1px 0  rgba(220, 38, 38, 0.14),
        0 2px 4px rgba(239, 68, 68, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

.numpad__key--back:active {
    background: linear-gradient(135deg,
        rgba(239, 68, 68, 0.22),
        rgba(220, 38, 38, 0.12));
    color: #991b1b;
    box-shadow:
        inset 0 0 0 1px rgba(220, 38, 38, 0.35),
        0 0 0 rgba(15, 23, 42, 0);
}

.numpad__key--back svg,
.numpad__key--back i { font-size: 26px; }

/* 🆕 Done — compact 1-column button, anchored top-right of the sheet.
   Sized to match a single key column so the touch target is smaller and
   well-separated from the digit grid — prevents the previous frequent
   mis-taps where users hit the big bar while reaching for "0". */
.numpad__topbar {
    display: flex;
    justify-content: flex-end;
    padding: 0 4px 8px;
}
.numpad__done {
    /* Match a single key cell width exactly: (100% − 4px outer padding × 2 − gap × 2) ÷ 3 */
    width: calc((100% - 24px) / 3);
    height: 38px;
    border: none;
    border-radius: 10px;
    background: var(--brand-gradient);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    box-shadow: 0 2px 6px rgba(59, 130, 246, 0.30);
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.08s ease, box-shadow 0.15s ease;
    letter-spacing: 0.2px;
}
.numpad__done:active {
    transform: scale(0.95);
    box-shadow: 0 1px 3px rgba(59, 130, 246, 0.24);
}
.numpad__done i { font-size: 16px; }

/* Lock body scroll when numpad open */
body.numpad-open { overflow: hidden; }

/* 🔒 Body scroll lock — applied when ANY full-screen sheet is open.
   Combined with JS position:fixed/top:-scrollY, this fully freezes the page beneath.
   Touch-action: none prevents iOS rubber-band / elastic scroll. */
body.has-sheet {
    overflow: hidden;
    touch-action: none;
    -webkit-overflow-scrolling: auto;
    overscroll-behavior: none;
}


/* ================================================================
   34. TEXT INPUT POLISH — better font/contrast/focus on mobile
        Uses native keyboard but with nicer field styling.
================================================================ */

/* Prevent iOS auto-zoom: input font-size must be ≥ 16px when not focused */
.tx-input,
.tx-textarea,
.picker-search {
    font-size: 16px;
    /* Apple's default focus glow is heavy — replace with custom */
    -webkit-tap-highlight-color: transparent;
}

.tx-input:focus,
.tx-textarea:focus {
    outline: none;
    border-color: var(--accent-blue, #3b82f6);
    background: var(--surface-1, #fff);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}

/* Bigger touch target for textarea */
.tx-textarea {
    min-height: 64px;
    line-height: 1.5;
    padding: 12px 14px;
    resize: vertical;
}

/* Date input — fix iOS rendering inconsistency */
input[type="date"].tx-input {
    font-size: 16px;
}

/* Smooth caret + selection color */
.tx-input,
.tx-textarea,
.picker-search {
    caret-color: var(--accent-blue, #3b82f6);
}

.tx-input::selection,
.tx-textarea::selection,
.picker-search::selection {
    background: rgba(59, 130, 246, 0.2);
}


/* ================================================================
   35. EDIT MODE — help text restyled for edit context
================================================================ */

.tx-help--edit {
    background: rgba(59, 130, 246, 0.08);
    border: 1px solid rgba(59, 130, 246, 0.2);
    color: #1d4ed8;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--r-md);
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: var(--space-3);
}

.tx-help--edit i {
    font-size: 16px;
    color: #1d4ed8;
    flex-shrink: 0;
}


/* ================================================================
   36. VIRTUAL KEYBOARD — mobile-only on-screen QWERTY
================================================================ */

/* ----- iOS-style VKB (bigger keys, brand-themed) ----- */
.vkb {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9600;
    transform: translateY(100%);
    transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
    pointer-events: none;
}

.vkb.is-open {
    transform: translateY(0);
    pointer-events: auto;
}

/* 🆕 v3.1.0 Phase O §14 Phase B fix — when a .confirm-popup opens an input
   (password prompt), the popup's z-index (10001) sits above the VKB/numpad
   (9500/9600), making keys unclickable. Raise the keyboards above the popup
   whenever they're open, so the user can actually type. The popup backdrop
   above the keyboard area still works as cancel-on-tap. */
body.vkb-open    .vkb    { z-index: 10100 !important; }
body.numpad-open .numpad { z-index: 10100 !important; }

/* 🆕 v3.1.0 Phase O §14 Phase B fix — when VKB/numpad is open and a
   confirm-popup is also showing (password prompt flow), align the dialog
   to the top of the viewport so the keyboard doesn't cover the input.
   Also pad the bottom to leave room for the ~260px tall keyboard. */
body.vkb-open    .confirm-popup,
body.numpad-open .confirm-popup {
    align-items: flex-start;
    padding-top: 32px;
    padding-bottom: 280px;  /* clear the keyboard tray */
}

.vkb__backdrop { display: none; }

/* iOS keyboard tray look */
.vkb__sheet {
    position: relative;
    width: 100%;
    background: #dbe1e8;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    box-shadow: 0 -6px 24px rgba(15, 23, 42, 0.10);
    /* 🆕 v3.1.1 rev4 — lift VKB keys above home-indicator chin
       (was: + 8px, now: + 20px). */
    padding: 8px 4px calc(env(safe-area-inset-bottom, 0px) + 20px);
}

.vkb__grip {
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: rgba(15, 23, 42, 0.22);
    margin: 2px auto 8px;
}

/* Keys layout */
.vkb__keys {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 0 4px;
}

.vkb__row {
    display: flex;
    gap: 6px;
    justify-content: center;
}

/* ============================================================
   EN VKB Premium Polish (v3.1.2+ · owner choice: Option 1+2+3)
   Three-pronged visual upgrade — CSS only, no JS/HTML change:
     1. Parity with numpad — glossy inset highlight, gradient
        press feedback, spring ease, modern typography.
     2. Semantic colors on special keys — backspace reads red
        (destructive), Shift active stays brand, Space is a
        proper main input (not a muted sliver), modifier keys
        (123/ABC) stay neutral slate.
     3. Section gaps — tiny margin breaks between the letter
        block, the space row, and the Done button so the
        hierarchy reads at a glance.
   ============================================================ */

/* Standard letter key — glossy iOS-style physical cap */
.vkb__key {
    flex: 1 1 0;
    min-width: 0;
    height: 50px;
    border: none;
    border-radius: 8px;
    background: #ffffff;
    color: var(--text-primary, #0f172a);
    font-family: inherit;
    /* Modern iOS letter cap: slightly bigger, lighter weight, tight tracking */
    font-size: 22px;
    font-weight: 400;
    letter-spacing: -0.3px;
    cursor: pointer;
    /* Three-layer shadow (depth + diffuse + top rim highlight) */
    box-shadow:
        0 1px 0  rgba(15, 23, 42, 0.14),
        0 2px 4px rgba(15, 23, 42, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    transition:
        background 0.12s ease,
        box-shadow 0.12s ease,
        transform 0.08s cubic-bezier(0.34, 1.56, 0.64, 1);
    -webkit-tap-highlight-color: transparent;
    padding: 0 2px;
    user-select: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}

.vkb__key:active,
.vkb__key.is-pressed {
    background: linear-gradient(135deg,
        rgba(59, 130, 246, 0.16),
        rgba(29, 78, 216, 0.08));
    transform: translateY(1px) scale(0.97);
    box-shadow:
        inset 0 0 0 1px rgba(59, 130, 246, 0.30),
        0 0 0 rgba(15, 23, 42, 0);
}

/* ------------------------------------------------------------
   Special keys — generic slate base (shift, 123/ABC switch).
   Backspace overrides this with a red tint below.
   ------------------------------------------------------------ */
.vkb__key--special {
    background: #c1c8d2;
    color: var(--text-primary, #0f172a);
    font-size: 15px;
    font-weight: var(--fw-semi, 600);
    box-shadow:
        0 1px 0  rgba(15, 23, 42, 0.16),
        0 2px 4px rgba(15, 23, 42, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

.vkb__key--special:active {
    background: linear-gradient(135deg,
        rgba(59, 130, 246, 0.20),
        rgba(29, 78, 216, 0.10));
    transform: translateY(1px) scale(0.97);
    box-shadow:
        inset 0 0 0 1px rgba(59, 130, 246, 0.35),
        0 0 0 rgba(15, 23, 42, 0);
}

/* Shift in caps-lock state — brand accent (unchanged, works well) */
.vkb__key--special.is-active {
    background: var(--brand-gradient);
    color: #fff;
    box-shadow:
        0 1px 0 rgba(15, 23, 42, 0.22),
        0 2px 6px rgba(59, 130, 246, 0.28),
        inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

/* Backspace — semantic red (matches numpad backspace) */
.vkb__key--special[data-action="back"],
.vkb__key[data-action="back"] {
    background: rgba(239, 68, 68, 0.08);
    color: #dc2626;
    box-shadow:
        0 1px 0  rgba(220, 38, 38, 0.14),
        0 2px 4px rgba(239, 68, 68, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.vkb__key--special[data-action="back"]:active,
.vkb__key[data-action="back"]:active {
    background: linear-gradient(135deg,
        rgba(239, 68, 68, 0.22),
        rgba(220, 38, 38, 0.12));
    color: #991b1b;
    box-shadow:
        inset 0 0 0 1px rgba(220, 38, 38, 0.35),
        0 0 0 rgba(15, 23, 42, 0);
}

/* Done key — brand gradient + separation gap so it doesn't melt
   into the Space key beside it. */
.vkb__key[data-action="done"] {
    background: var(--brand-gradient);
    color: #fff;
    font-size: 15px;
    font-weight: var(--fw-semi, 600);
    letter-spacing: 0.2px;
    margin-left: 4px;                       /* visual break from Space */
    box-shadow:
        0 1px 0 rgba(15, 23, 42, 0.22),
        0 3px 10px rgba(59, 130, 246, 0.32),
        inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.vkb__key[data-action="done"]:active {
    background: var(--brand-gradient);
    transform: translateY(1px) scale(0.97);
    filter: brightness(1.06);
    box-shadow:
        0 1px 3px rgba(59, 130, 246, 0.24),
        inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* Space key — proper main input, not a muted sliver.
   Keeps the white face (matches letter keys semantically — "typing")
   but with a readable label and consistent polish. */
.vkb__key[data-action="space"] {
    background: #ffffff;
    font-size: 15px;
    color: var(--text-secondary, #64748b);
    font-weight: var(--fw-semi, 600);
    text-transform: lowercase;
    letter-spacing: 1px;
}

/* Section gap — small breathing room between the last letter row
   and the space row so the hierarchy reads as "typing | commit". */
.vkb__row:last-child {
    margin-top: 2px;
}

body.vkb-open { overflow: hidden; }


/* ================================================================
   37. PREVENT DOUBLE-TAP ZOOM — UX fix for rapid tapping
        (esp. backspace key on NumPad / VKB, repeated chip taps)
================================================================ */

/* Body-wide: short-circuit gesture for double-tap zoom on all elements */
html, body {
    touch-action: manipulation;
}

/* Interactive elements explicitly opt out of native zoom gestures */
button,
[role="button"],
a,
input,
textarea,
select,
label,
.numpad__key,
.vkb__key,
.segmented__option,
.jump-nav__item,
.fab,
.tx-line__hint,
.tx-line__remove,
.tx-add-line,
.bottom-tab-bar__item,
.list-item,
.list-item--clickable,
.receipt-slot,
.picker-item,
.combobox__trigger,
.tx-screen__back,
.tx-screen__close,
.btn--primary,
.btn--secondary,
.btn--danger {
    touch-action: manipulation;     /* allow pan + pinch, block double-tap zoom */
    -webkit-tap-highlight-color: transparent;
}

/* Critical surfaces that user taps repeatedly — keep gesture window very tight */
.numpad__key,
.vkb__key {
    user-select: none;
    -webkit-user-select: none;
    /* Disable iOS callout (long-press menu) so rapid back-tap can't trigger it */
    -webkit-touch-callout: none;
    /* ⚡ touch-action: none disables ALL native gestures (scroll/zoom/pan) for keys
       — this is what enables true multi-touch typing without browser interference */
    touch-action: none;
}

/* The sheet itself blocks scroll/pinch so multi-finger typing doesn't trigger
   the underlying page to scroll */
.numpad__sheet,
.vkb__sheet {
    touch-action: none;
}

/* Prevent double-tap zoom from rapid backspace on numpad */
.numpad__key--back,
.vkb__key[data-action="back"] {
    touch-action: manipulation;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}


/* ================================================================
   38. FOCUSED INPUT HIGHLIGHT — visible while keyboard is open
================================================================ */

/* When numpad/vkb is open, the readonly input doesn't show native caret,
   so add a glow ring to indicate which field is being edited. */
body.numpad-open input[data-numpad-locked],
body.vkb-open    input[data-vkb-locked],
body.vkb-open    textarea[data-vkb-locked] {
    border-color: var(--accent-blue, #3b82f6) !important;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18) !important;
    background: var(--surface-1, #fff) !important;
}


/* ================================================================
   39. TRANSACTIONS — SEARCH + FILTER UI
================================================================ */

/* Toolbar: search input + filter button side-by-side */
.tx-toolbar {
    display: flex;
    align-items: stretch;
    gap: 8px;
    margin: 0 0 var(--space-2);
}

.tx-search {
    position: relative;
    flex: 1;
    display: flex;
    align-items: center;
}

.tx-search__icon {
    position: absolute;
    left: 12px;
    font-size: 20px;
    color: var(--text-secondary, #64748b);
    pointer-events: none;
}

.tx-search__input {
    width: 100%;
    height: 44px;
    padding: 0 40px 0 38px;
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: 10px;
    background: var(--surface-1, #fff);
    font-size: 15px;
    font-family: inherit;
    color: var(--text-primary, #0f172a);
    -webkit-appearance: none;
    appearance: none;
}

.tx-search__input::-webkit-search-cancel-button { display: none; }
.tx-search__input::-webkit-search-decoration    { display: none; }

.tx-search__input:focus {
    outline: none;
    border-color: var(--accent-blue, #3b82f6);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}

.tx-search__clear {
    position: absolute;
    right: 6px;
    width: 32px; height: 32px;
    border: none;
    background: transparent;
    color: var(--text-secondary, #64748b);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    -webkit-tap-highlight-color: transparent;
}
.tx-search__clear:active { background: rgba(15, 23, 42, 0.08); }
.tx-search__clear i { font-size: 20px; }

.tx-filter-btn {
    position: relative;
    flex-shrink: 0;
    width: 44px; height: 44px;
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: 10px;
    background: var(--surface-1, #fff);
    color: var(--text-primary, #0f172a);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.1s ease;
}
.tx-filter-btn:active { background: var(--surface-2, #f1f5f9); }
.tx-filter-btn i { font-size: 22px; }

.tx-filter-btn__badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 11px;
    font-weight: var(--fw-bold, 700);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(59, 130, 246, 0.35);
}

/* ---- Active filters bar ---- */
.active-filters {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    margin: 0 0 var(--space-2);
    background: rgba(59, 130, 246, 0.06);
    border: 1px solid rgba(59, 130, 246, 0.15);
    border-radius: 10px;
    flex-wrap: wrap;
}

.active-filters__label {
    font-size: 12px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.active-filters__list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    flex: 1;
}

.chip--active-filter {
    height: 28px;
    padding: 0 4px 0 10px;
    background: rgba(59, 130, 246, 0.15);
    color: #1d4ed8;
    border-radius: var(--r-full);
    font-size: 13px;
    font-weight: var(--fw-medium, 500);
    border: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.chip--active-filter i {
    font-size: 18px;
    padding: 2px;
    border-radius: 50%;
}
.chip--active-filter:active i { background: rgba(29, 78, 216, 0.15); }

.active-filters__clear {
    flex-shrink: 0;
    border: none;
    background: transparent;
    color: var(--accent-blue, #3b82f6);
    font-size: 13px;
    font-weight: var(--fw-semi, 600);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    padding: 4px 6px;
}
.active-filters__clear:active { opacity: 0.6; }

/* ---- Filter sheet sections ---- */
.filter-section {
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.filter-section:last-child { border-bottom: none; }

.filter-section__title {
    margin: 0 0 var(--space-2);
    font-size: 13px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.filter-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.filter-field {
    flex-direction: column;
    gap: 4px;
}
.filter-field > span {
    font-size: 12px;
    color: var(--text-secondary, #64748b);
    font-weight: var(--fw-medium, 500);
}

/* Allow chip-row to wrap inside filter sheet */
.chip-row--wrap {
    flex-wrap: wrap;
    overflow-x: visible;
    padding: 0;
    margin: 0;
}

.chip--toggle.is-active {
    background: var(--brand-gradient);
    color: #fff;
    border-color: transparent;
}


/* ================================================================
   40. PAGE LAYOUT & UTILITY CLASSES
        Semantic classes that replace scattered inline `style="..."`
        across PHP files. Keep all styling in CSS — never inline.
================================================================ */

/* ---- Page header (h1 + caption/subtitle pattern) ----
   🆕 v3.1.0 Phase A (G2): Unified header — one component to replace 4 legacy
   variants (.page-header base, .page-header--tight, .acct-page-header,
   .security-page-head). Pages migrate in Phase B.

   Structure:
     <header class="page-header">
       <a class="page-header__back">                  ← optional (drill-in pages)
         <i class="bx bx-chevron-left"></i>
       </a>
       <div class="page-header__text">                ← wrapper (needed if caption)
         <h1 class="page-header__title">Title</h1>
         <p  class="page-header__caption">Sub</p>     ← optional
       </div>
       <div class="page-header__actions">             ← optional (right-side buttons/bell)
         ...
       </div>
     </header>

   Modifiers:
     .page-header--tight   → less bottom margin
     .page-header--wrap    → flex-wrap for narrow screens with many actions
*/
.page-header {
    display: flex;
    align-items: center;
    gap: var(--space-3, 12px);
    margin-bottom: var(--space-5, 20px);
    padding: var(--space-1, 4px) 0 var(--space-2, 8px);
}
.page-header--tight           { margin-bottom: var(--space-3, 12px); }
.page-header--wrap            { flex-wrap: wrap; }

/* 🆕 v3.1.0 Phase U Round 6 — back button lift + brand hover tint. Shared
   across every page using .page-header (Budget, Reports, Health, Security,
   Settings, Account Detail, Security method, …). */
.page-header__back {
    width: 40px; height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    color: var(--pf-muted-1, #475569);
    font-size: 28px;
    text-decoration: none;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.14s ease,
                color 0.14s ease,
                transform 0.08s ease,
                box-shadow 0.18s ease;
}
.page-header__back:hover  {
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.14);
}
.page-header__back:active { transform: scale(0.92); }

.page-header__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.page-header__title {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    color: var(--pf-ink, #0E1F44);
    line-height: 1.2;
}
.page-header__caption {
    margin: var(--space-1, 4px) 0 0;
    font-size: 13px;
    color: var(--pf-muted-2, #64748b);
    font-weight: 500;
}

/* Dashboard greeting (small text above name) */
.greeting                     { margin: 0; }
.greeting + .text-h1          { margin: 2px 0 0; }

/* ---- Card variants for list containers ---- */
.card--list                   {
    padding: var(--space-2);
    /* 🔴 backdrop-filter on parent creates a containing block that BREAKS
       position: sticky on children. Disable it so .list-group__header
       can pin to the viewport top when the list scrolls. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* 🆕 v3.1.0 Phase S §11 Round 5 — row divider + hover state per draft §11
   lines 2662-2665 (`border-bottom:1px solid #eef1f5` between rows, no border
   on the last row). Hover gives desktop users a clean affordance; `:active`
   stays for touch feedback. */
.card--list > .list-item {
    border-bottom: 1px solid var(--border-soft, #eef1f5);
    border-radius: 0;
}
.card--list > .list-item:last-child { border-bottom: none; }
.card--list > .list-item:first-child {
    border-top-left-radius: calc(var(--r-xl, 16px) - var(--space-2));
    border-top-right-radius: calc(var(--r-xl, 16px) - var(--space-2));
}
.card--list > .list-item:last-child {
    border-bottom-left-radius: calc(var(--r-xl, 16px) - var(--space-2));
    border-bottom-right-radius: calc(var(--r-xl, 16px) - var(--space-2));
}
.card--list > .list-item:hover:not(:active) {
    background: var(--surface-2, #f8fafc);
}
.card--list-top-gap           {
    padding: var(--space-2);
    margin-top: var(--space-3);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* ---- Empty state padding sizes ---- */
.empty-state--lg              { padding: var(--space-10) var(--space-4); }
.empty-state--md              { padding: var(--space-8)  var(--space-4); }

/* ---- Dashboard 2-column stats grid ---- */
.dashboard-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}
.dashboard-stats__money       { margin: var(--space-1) 0 0; }
.dashboard-stats__caption     { margin: var(--space-1) 0 0; }

/* 🆕 v3.1.1 rev4 — Premium polish on Income / Expense cards.
   Matches the Net Worth hero refresh: left-edge accent stripe keyed to
   each card's semantic colour (green / red), tinted lift shadow, matte
   dot texture, and a tiny trend icon in the top-right. Overflow is
   clipped so the ::after dot pattern and the ::before stripe don't
   bleed outside the card. */
.dashboard-stats__card {
    position: relative;
    overflow: hidden;
    border: 1px solid rgba(148, 163, 184, 0.18);
    /* subtle inner highlight to match the Net Worth hero */
    box-shadow:
        0 10px 24px -10px rgba(15, 23, 42, 0.14),
        0 2px 6px -1px rgba(15, 23, 42, 0.06),
        inset 0 0 0 1px rgba(255, 255, 255, 0.6);
    transition: transform 0.12s ease, box-shadow 0.18s ease;
}
/* Left accent stripe — 3px, keyed to income/expense */
.dashboard-stats__card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    z-index: 0;
}
.dashboard-stats__card--income::before  { background: #16a34a; }
.dashboard-stats__card--expense::before { background: #dc2626; }

/* Matte dot pattern — very subtle, 8px grid. Keeps the premium texture
   feel from the Net Worth hero but at a much lower contrast against the
   white I/E card bg so it doesn't visually compete. */
.dashboard-stats__card::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: radial-gradient(rgba(15, 23, 42, 0.03) 1px, transparent 0);
    background-size: 8px 8px;
    pointer-events: none;
    z-index: 0;
}

/* Lift real content above the stripe + pattern layers. */
.dashboard-stats__card > * { position: relative; z-index: 1; }

/* Pseudo trend icon via CSS content on the card__label — a tiny ↑ / ↓
   next to the "INCOME" / "EXPENSE" word. Uses the card variant class so
   each side gets its own glyph + colour. */
.dashboard-stats__card--income  .card__label::after,
.dashboard-stats__card--expense .card__label::after {
    display: inline-block;
    margin-left: 6px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    vertical-align: middle;
}
.dashboard-stats__card--income  .card__label::after { content: '↑'; color: #16a34a; }
.dashboard-stats__card--expense .card__label::after { content: '↓'; color: #dc2626; }

/* Severity-tinted lift shadow when pressed/hovered — matches the Health
   page pattern so the home dashboard feels cross-page consistent. */
.dashboard-stats__card--income:hover {
    box-shadow:
        0 14px 28px -10px rgba(22, 163, 74, 0.22),
        0 2px 8px -2px rgba(15, 23, 42, 0.08),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}
.dashboard-stats__card--expense:hover {
    box-shadow:
        0 14px 28px -10px rgba(220, 38, 38, 0.22),
        0 2px 8px -2px rgba(15, 23, 42, 0.08),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

/* Tabular-nums on the money row so a changing balance doesn't shift the
   bar underneath (same technique used on the Net Worth hero). */
.dashboard-stats__money {
    font-feature-settings: "tnum" 1;
    letter-spacing: -0.015em;
}

/* ============================================
   🆕 v3.1.0 Phase F.1 — I/E card mini bars (draft 1a pin 3)
   Bar 5px tall sits BETWEEN the money number and the caption inside
   each Income/Expense card. Income = 100% green baseline. Expense =
   proportional red fill (capped at 100% but caption shows real %).
   Replaces the earlier standalone .ie-compare section.
   ============================================ */
.dashboard-stats__bar {
    height: 5px;
    border-radius: 3px;
    background: var(--pf-line, #eef1f5);
    margin: 10px 0 0;
    overflow: hidden;
}
.dashboard-stats__bar-fill {
    display: block;
    height: 100%;
    border-radius: 3px;
    transition: width 320ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.dashboard-stats__bar-fill--income  { background: var(--pf-success, #16a34a); }
.dashboard-stats__bar-fill--expense { background: var(--pf-danger,  #dc2626); }

/* 🆕 v3.1.1 rev4 — Phase α — Assets vs Liabilities colour language.
   Blue theme per the user's brief: ASSETS use brand blue (positive/wealth),
   LIABILITIES use slate (neutral debt tone instead of alarm red — rose
   accent in the stripe keeps the "owed" semantic without screaming). */
.dashboard-stats__bar-fill--asset     { background: var(--brand-500, #3b82f6); }
.dashboard-stats__bar-fill--liability { background: #94a3b8; }

/* Variant-specific accent stripe + hover shadow for the A vs L cards. */
.dashboard-stats__card--asset::before    { background: var(--brand-500, #3b82f6); }
.dashboard-stats__card--liability::before { background: #fb7185; }

/* Trend arrow glyphs after the labels — upward for assets, flat for debt. */
.dashboard-stats__card--asset .card__label::after,
.dashboard-stats__card--liability .card__label::after {
    display: inline-block;
    margin-left: 6px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    vertical-align: middle;
}
.dashboard-stats__card--asset     .card__label::after { content: '↑';   color: var(--brand-600, #2563eb); }
.dashboard-stats__card--liability .card__label::after { content: '•';   color: #fb7185; }

.dashboard-stats__card--asset:hover {
    box-shadow:
        0 14px 28px -10px rgba(37, 99, 235, 0.22),
        0 2px 8px -2px rgba(15, 23, 42, 0.08),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}
.dashboard-stats__card--liability:hover {
    box-shadow:
        0 14px 28px -10px rgba(251, 113, 133, 0.20),
        0 2px 8px -2px rgba(15, 23, 42, 0.08),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

/* ============================================
   🆕 v3.1.1 rev4 — Phase α — 6-month sparkline inside the Net Worth hero.
   Drawn as a tiny white-on-brand-blue SVG line + fill under the balance
   delta chip. Sits above the "As of {date}" timestamp. All colours are
   pure RGB values (no backdrop-filter) so iOS PWA composite stays clean.
   ============================================ */
.networth-sparkline {
    margin: var(--space-3) 0 var(--space-2);
    padding-top: var(--space-3);
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.networth-sparkline__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 10.5px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.65);
    margin-bottom: 6px;
}
.networth-sparkline__ytd {
    /* 🆕 v3.1.1 rev4b — green badge for the "+X.X% last 6M" to visually
       anchor the green trend line. Soft green-300 keeps it readable
       against the brand-blue card without screaming. */
    color: #86efac;
    font-weight: 600;
    font-feature-settings: "tnum" 1;
    letter-spacing: 0;
    text-transform: none;
}
.networth-sparkline__svg {
    display: block;
    width: 100%;
    height: 44px;
    margin: 2px 0;
}
.networth-sparkline__labels {
    display: flex;
    justify-content: space-between;
    font-size: 9px;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.55);
    margin-top: 2px;
    font-feature-settings: "tnum" 1;
}

/* 🆕 Push the "As of" timestamp a touch lower so the sparkline + labels
   above it have room to breathe without clipping the chip. */
.card--summary:has(.networth-sparkline) .card__timestamp {
    position: static;
    text-align: right;
    margin-top: var(--space-2);
}

/* ---- Section title row (h2 + "See all" link) ---- */
.section-head {
    padding: 0 var(--space-1);
    margin-bottom: var(--space-2);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.section-head__title          { margin: 0; }
/* 🆕 v3.1.0 Phase Q Round 2 — "See all ›" link in brand blue per draft §1a line 404.
   Also tightens font size, weight, and chevron rhythm. */
.section-head__link {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    text-decoration: none;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--brand-600, #2563eb);
    -webkit-tap-highlight-color: transparent;
    transition: color .12s ease, transform .08s ease;
}
.section-head__link:hover   { color: var(--brand-700, #1d4ed8); }
.section-head__link:active  { transform: scale(0.97); }
.section-head__link i       { font-size: 16px; }

/* ---- Net Worth summary card (white text on gradient) ---- */
.card--summary                { margin-bottom: var(--space-4); }
.card--summary .card__label   { color: rgba(255, 255, 255, 0.85); }
.card--summary .money--xl     { margin: var(--space-1) 0 var(--space-2); color: #fff; }

/* ---- Profile avatar circle (header top-right on dashboard) ---- */
/* 🆕 v3.1.0 Phase Q Round 4 — gradient brand blue (per draft §1a line 391).
   Was flat grey; now matches the Net Worth hero + Setup Wizard icons for a
   consistent brand gradient language across the app. */
.profile-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    /* Round 1 — brand-gradient token (was hard-coded #3b82f6, #1d4ed8) */
    background: var(--brand-gradient);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    text-decoration: none;
    box-shadow: var(--brand-shadow-sm);
    -webkit-tap-highlight-color: transparent;
    transition: transform .12s ease, box-shadow .18s ease, filter .18s ease;
}
.profile-avatar:hover {
    transform: translateY(-1px);
    box-shadow: var(--brand-shadow-md);
    filter: brightness(1.04);
}
.profile-avatar:active { transform: translateY(0) scale(0.96); }
.profile-avatar i      { font-size: 22px; color: #fff; }

/* ---- User profile card (More page header) ---- */
/* 🆕 v3.1.0 Phase S §11 Round 1 — profile card is now a brand-gradient hero
   matching draft §11 line 2659 (bg #2563eb → #1d3fae, white semi-transparent
   avatar). Pairs with Dashboard Net Worth hero + Balance Sheet hero.
   🔧 Specificity note: light-theme.css loads AFTER mobile.css and has
      `.card { background: #fff }`. We bump specificity via `.card.profile-card`
      (0,2,0) so our gradient actually wins. */
.card.profile-card,
.profile-card {
    margin-bottom: var(--space-5);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 16px;
    border-radius: var(--r-xl, 16px);
    border: none;
    background: var(--brand-gradient-deep);
    color: #fff;
    box-shadow: 0 6px 16px -2px rgba(37, 99, 235, 0.28),
                0 2px 6px -1px rgba(15, 23, 42, 0.08);
}
.profile-card__avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 22px;
    flex-shrink: 0;
    /* 🆕 v3.1.1 rev3 — backdrop-filter removed (iOS first-paint fuzzy fix).
       The avatar sits inside the solid gradient More profile hero card
       so blur had nothing translucent to work on. */
}
.profile-card .list-item__body { flex: 1; min-width: 0; }
.profile-card .list-item__title {
    color: #fff;
    font-weight: 700;
    font-size: 15px;
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.profile-card .list-item__subtitle {
    color: rgba(255, 255, 255, 0.82);
    font-size: 12px;
    margin: 2px 0 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- Plain link (no underline + inherit color) ---- */
.link-plain {
    text-decoration: none;
    color: inherit;
}

/* ---- Danger / destructive list-item (Sign Out) ---- */
/* 🆕 v3.1.0 Phase S §11 Round 2 — Sign-out danger card per draft §11 line 2680.
   Soft-red tint bg + 1.5px red border reads as DANGER on first glance (as
   opposed to just red-tinted text). Overrides .card's white bg + brand shadow. */
.list-item--danger {
    /* F12 (v3.1.2+) — Signout became a <form><button>, so button-reset:
       strip native UA styles and go full-width inside the form. */
    display: flex;
    width: 100%;
    text-align: left;
    font: inherit;
    cursor: pointer;
    text-decoration: none;
    padding: var(--space-4);
    background: #fef2f2 !important;
    border: 1.5px solid #fecaca !important;
    box-shadow: none !important;
    color: #dc2626;
    transition: background .15s ease, transform .08s ease;
}
/* F12 — signout form wrappers: strip default <form> margin.
   .signout-form (More page) must span full width to match the old <a>.
   .sidebar__signout-form sits inline next to the user row, auto-width. */
.signout-form {
    display: block;
    margin: 0;
    width: 100%;
}
.sidebar__signout-form {
    display: inline-flex;
    margin: 0;
}
.list-item--danger:hover  { background: #fee2e2 !important; }
.list-item--danger:active { transform: scale(0.99); }
.list-item--danger .list-item__icon {
    background: #fee2e2;
    color: #dc2626;
}
.list-item--danger .list-item__title { color: #dc2626; font-weight: 700; }

/* ---- Chevron icon (right-pointing arrow inside list items) ---- */
.list-item__chevron           { font-size: 18px; }
.list-item__chevron--gap      { font-size: 18px; margin-left: 4px; }

/* ---- "more" page section spacing ---- */
.section-mb-4                 { margin-bottom: var(--space-4); }

/* ---- LOGIN PAGE — Passkey-first layout ---- */
/* Primary action block: big Face ID button + toggle to expand password form */
.login-primary {
    margin-bottom: var(--space-3, 16px);
}

/* 🆕 v3.1.0 Phase X Login Round 2 — Face ID / Touch ID button polish:
   - height bumped to 60 (weightier CTA)
   - 2-layer shadow (brand blue + cyan accent) for depth
   - hover: lift + saturate + icon scale
   - active: tactile press
   - respects reduced-motion */
.login-faceid-btn {
    width: 100%;
    min-height: 60px;
    padding: 14px 20px;
    border: none;
    border-radius: 14px;
    background: var(--brand-gradient);
    color: #fff;
    font-family: inherit;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    box-shadow: 0 10px 28px -4px rgba(59, 130, 246, 0.42),
                0 4px 10px -2px rgba(6, 182, 212, 0.26);
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.22s ease,
                filter 0.18s ease,
                opacity 0.15s ease;
    letter-spacing: 0.2px;
}
.login-faceid-btn:hover:not(:disabled) {
    transform: translateY(-2px);
    filter: brightness(1.08) saturate(1.08);
    box-shadow: 0 14px 36px -4px rgba(59, 130, 246, 0.52),
                0 6px 14px -2px rgba(6, 182, 212, 0.32);
}
.login-faceid-btn:active:not(:disabled) {
    transform: translateY(0) scale(0.97);
    filter: brightness(0.96);
    box-shadow: 0 4px 12px -2px rgba(59, 130, 246, 0.36);
}
.login-faceid-btn:disabled { opacity: 0.55; cursor: wait; box-shadow: none; }
.login-faceid-btn i {
    font-size: 28px;
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.login-faceid-btn:hover:not(:disabled) i { transform: scale(1.1); }
@media (prefers-reduced-motion: reduce) {
    .login-faceid-btn, .login-faceid-btn i { transition: none; }
    .login-faceid-btn:hover:not(:disabled) i { transform: none; }
}

/* "or use username & password" toggle link */
/* 🆕 v3.1.0 Phase X Login Round 4 — "or use username & password" link polish:
   icon nudge + text color intensity on hover, press feedback on active. */
.login-toggle {
    width: 100%;
    margin-top: 14px;
    padding: 12px 8px;
    background: transparent;
    border: none;
    color: #64748b;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.18s ease, opacity 0.2s ease, transform 0.1s ease;
}
.login-toggle:hover  { color: var(--brand-500, #3b82f6); }
.login-toggle:active { transform: scale(0.98); opacity: 0.6; }
.login-toggle i      {
    font-size: 18px;
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.login-toggle:hover i { transform: translateX(-3px); }
@media (prefers-reduced-motion: reduce) {
    .login-toggle, .login-toggle i { transition: none; }
    .login-toggle:hover i { transform: none; }
}
.login-toggle.is-hidden {
    opacity: 0;
    pointer-events: none;
    max-height: 0;
    margin-top: 0;
    padding-top: 0;
    padding-bottom: 0;
    overflow: hidden;
}

/* Password form — collapsed by default, smooth expand on .is-open */
.login-password-form {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.35s ease, opacity 0.25s ease, margin-top 0.25s ease;
    margin-top: 0;
}
.login-password-form.is-open {
    max-height: 700px;
    opacity: 1;
    margin-top: 8px;
}


/* ================================================================
   41. LOGIN — Split Hero design (modern, mobile-first)
        Top: gradient hero with logo. Below: white form panel.
================================================================ */

.login-body {
    /* Lock to viewport — no body scrollbar on mobile */
    margin: 0;
    height: 100vh;
    height: 100dvh;              /* dynamic viewport — iOS URL-bar aware */
    overflow: hidden;
    background: #f1f5f9;
    display: flex;
    align-items: stretch;
    justify-content: center;
    font-family: 'Poppins', system-ui, -apple-system, sans-serif;
}

.login-card {
    width: 100%;
    max-width: 440px;
    background: #ffffff;
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;              /* exact viewport */
    overflow: hidden;
}

/* ---- HERO (top gradient section) ---- */
.login-hero {
    position: relative;
    /* 🆕 personfin. brand gradient — matches logo (indigo → dark navy) */
    background: var(--brand-gradient-deep);
    color: #fff;
    padding: 36px 24px 36px;     /* tighter — saves ~40px vertical */
    overflow: hidden;
    flex: 0 0 auto;
}

/* Decorative blur bubbles — tuned to brand palette */
.login-hero__bubble {
    position: absolute;
    border-radius: 50%;
    filter: blur(40px);
    opacity: 0.55;
    pointer-events: none;
}
.login-hero__bubble--a {
    top: -50px;
    left: -50px;
    width: 200px;
    height: 200px;
    background: rgba(59, 130, 246, 0.55);    /* lighter indigo bubble */
}
.login-hero__bubble--b {
    bottom: -60px;
    right: -50px;
    width: 220px;
    height: 220px;
    background: rgba(125, 200, 247, 0.5);    /* sky bubble */
}

.login-hero__inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* 🆕 personfin. lockup logo for login hero (replaces old icon + title).
       Uses logo-white.svg which is designed for dark backgrounds — already
       contains "personfin." brand mark + "PERSONAL FINANCE" subtitle.
       The lockup SVG has 3.5:1 aspect ratio (420×120). At 280px width the
       rendered height is ~80px, which sits well above the form panel. */
.login-hero__lockup {
    display: block;
    width: 280px;
    max-width: 78vw;
    height: auto;
    margin: 0 0 8px;
    user-select: none;
    -webkit-user-drag: none;
    filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.18));
}

/* Legacy classes — kept in case any cached page still emits them */
.login-hero__logo,
.login-hero__title { display: none; }

.login-hero__tagline {
    margin: 4px 0 0;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.88);
    letter-spacing: 0.4px;
}

/* ---- FORM PANEL (below hero) ---- */
.login-form-wrap {
    flex: 1 1 auto;
    min-height: 0;               /* allow flex child to shrink */
    background: #ffffff;
    padding: 24px 26px 16px;
    /* Lift the form panel slightly to overlap hero — "card peek" effect */
    margin-top: -20px;
    border-radius: 24px 24px 0 0;
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    /* Internal scroll if form is too tall for small phones (e.g. iPhone SE),
       but with hidden scrollbar so the page looks clean. */
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.login-form-wrap::-webkit-scrollbar { display: none; }

.login-form-wrap > form {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* ---- FOOTER ---- */
.login-footer {
    flex: 0 0 auto;
    text-align: center;
    padding: 8px 16px 12px;
    color: #94a3b8;
    font-size: 11px;
}

/* ---- DESKTOP — center the card with side breathing room ---- */
@media (min-width: 768px) {
    .login-body {
        align-items: center;
        padding: 32px 16px;
        background: #f1f5f9;
        height: 100vh;
        height: 100dvh;
        overflow: hidden;
    }
    .login-card {
        height: auto;
        max-height: calc(100vh - 64px);
        max-height: calc(100dvh - 64px);
        border-radius: 28px;
        box-shadow: 0 24px 64px -16px rgba(15, 23, 42, 0.22),
                    0 8px 16px -4px  rgba(15, 23, 42, 0.10);
    }
}

/* NOTE: defensive override for .login-body .container/.wrapper/.login-wrapper
   removed June 2026 cleanup — those classes don't exist anywhere in login.php's
   actual markup (body uses .login-body > .login-card), and their style.css
   definitions were deleted in the same cleanup pass. Dead on both ends. */


/* ================================================================
   42. LOGIN — override legacy dark-on-image input styles
        Force readable dark text + visible borders on white form panel
================================================================ */

/* ---- Inputs (Username / Password) ---- */
.login-card .input-box {
    position: relative;
    margin-bottom: 12px;
}

.login-card .input-box input {
    width: 100%;
    height: 50px;
    padding: 0 44px 0 16px;
    background: #f8fafc;
    border: 1.5px solid #e2e8f0;
    border-radius: 12px;
    font-size: 15px;
    font-family: inherit;
    color: #0f172a;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.login-card .input-box input::placeholder {
    color: #94a3b8;
    opacity: 1;
}
.login-card .input-box input:focus {
    border-color: #3b82f6;
    background: #ffffff;
    box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);
}
.login-card .input-box input:focus::placeholder {
    color: #cbd5e1;
}

.login-card .input-box > i {
    position: absolute;
    right: 16px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 20px;
    color: #94a3b8;
    pointer-events: none;
}

/* Password eye-toggle button */
.login-card .input-box--password .password-toggle {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    background: transparent;
    border: none;
    color: #94a3b8;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    -webkit-tap-highlight-color: transparent;
}
.login-card .input-box--password .password-toggle:hover  { color: #475569; background: #f1f5f9; }
.login-card .input-box--password .password-toggle:active { color: #1d4ed8; }
.login-card .input-box--password .password-toggle i      { font-size: 20px; }
.login-card .input-box--password input { padding-right: 48px; }

/* ---- Reset password row (F02 revisit v3.1.2+ — "Remember me" removed) ---- */
.login-card .remember-forgot {
    display: flex;
    justify-content: flex-end;    /* right-align — only the reset link remains */
    align-items: center;
    margin: 6px 0 14px;
    font-size: 13px;
    color: #64748b;
}
.login-card .remember-forgot a {
    color: #1d4ed8;
    text-decoration: none;
    font-weight: 500;
}
.login-card .remember-forgot a:hover { text-decoration: underline; }

/* ---- Caps Lock warning ---- */
.login-card .caps-lock-warning {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: -4px 0 12px;
    padding: 8px 12px;
    background: #fef3c7;
    border: 1px solid #fde68a;
    color: #92400e;
    font-size: 12px;
    border-radius: 8px;
}
.login-card .caps-lock-warning i { font-size: 16px; }

/* Ensure [hidden] attribute wins over the display: flex rule above
   (legacy style.css `.caps-lock-warning[hidden]` got beaten by specificity) */
.login-card .caps-lock-warning[hidden] {
    display: none !important;
}

/* ---- Form error message ---- */
.login-card .form-error {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 4px 0 14px;
    padding: 10px 12px;
    background: #fee2e2;
    border: 1px solid #fecaca;
    color: #991b1b;
    font-size: 13px;
    border-radius: 10px;
    line-height: 1.4;
}
.login-card .form-error i { font-size: 18px; flex-shrink: 0; margin-top: 1px; }

/* ---- Sign In button (override legacy white-on-white) ---- */
.login-card .btn--primary {
    width: 100%;
    height: 52px;
    border: none;
    border-radius: 12px;
    background: var(--brand-gradient);
    color: #ffffff;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    box-shadow: 0 6px 18px rgba(59, 130, 246, 0.28);
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.1s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.login-card .btn--primary:hover  { box-shadow: 0 8px 22px rgba(59, 130, 246, 0.38); }
.login-card .btn--primary:active { transform: scale(0.98); }
.login-card .btn--primary:disabled { opacity: 0.6; cursor: wait; }
.login-card .btn--primary .btn__label { color: #ffffff; }

/* ---- Register link below form ---- */
.login-card .register-link {
    margin-top: auto;            /* push to bottom of form panel */
    padding-top: 14px;
    text-align: center;
    color: #64748b;
    font-size: 13px;
}
.login-card .register-link a {
    color: #1d4ed8;
    text-decoration: none;
    font-weight: 600;
    margin-left: 4px;
}
.login-card .register-link a:hover { text-decoration: underline; }


/* ================================================================
   43. EDIT FORM FOOTER — Delete (left) + Review & Save (right)
        UNIFIED with .pw-btn--danger — solid red gradient + 44px height
        to match .tx-screen__footer--view (Delete CTA in View screen).
        Inherits the gradient look from the base .btn--danger rule.
================================================================ */
.tx-screen__footer .btn--danger {
    height: 44px;
    padding: 0 20px;
    gap: 8px;
    border-radius: 12px;
}
.tx-screen__footer .btn--danger i {
    font-size: 17px;
}

/* When delete button is visible, footer becomes split layout */
.tx-screen__footer:has(.tx-screen__footer-secondary:not([hidden])) {
    display: flex;
    gap: var(--space-3);
    align-items: stretch;
}
.tx-screen__footer:has(.tx-screen__footer-secondary:not([hidden])) .tx-screen__footer-secondary {
    flex: 0 0 38%;       /* Delete takes ~38% — smaller, less prominent */
}
.tx-screen__footer:has(.tx-screen__footer-secondary:not([hidden])) .tx-screen__footer-primary {
    flex: 1 1 auto;      /* Review & Save takes the rest */
}

/* Fallback for browsers without :has — JS adds .is-split class */
.tx-screen__footer.is-split {
    display: flex;
    gap: var(--space-3);
    align-items: stretch;
}
.tx-screen__footer.is-split .tx-screen__footer-secondary { flex: 0 0 38%; }
.tx-screen__footer.is-split .tx-screen__footer-primary   { flex: 1 1 auto; }


/* ================================================================
   44. SCROLL TO TOP — floating circle button (appears after 400px scroll)
================================================================ */
.scroll-to-top {
    position: fixed;
    right: 20px;
    /* Above the bottom tab bar on mobile (~64px) + safe-area */
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: none;
    background: var(--brand-gradient);
    color: #ffffff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 8px 22px rgba(59, 130, 246, 0.35),
        0 2px 6px rgba(15, 23, 42, 0.18);
    -webkit-tap-highlight-color: transparent;
    z-index: var(--z-fab, 8800);
    /* Hidden by default, smoothly fades in */
    opacity: 0;
    transform: translateY(20px) scale(0.85);
    pointer-events: none;
    transition: opacity 0.22s ease, transform 0.22s ease, box-shadow 0.18s ease;
}

.scroll-to-top.is-visible {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}

/* 🆕 v3.1.0 Phase AE scroll-to-top Round 1 — spring entrance + arrow bounce */
.scroll-to-top.is-visible {
    animation: scrollToTopPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes scrollToTopPop {
    0%   { transform: translateY(20px) scale(0.4); }
    60%  { transform: translateY(-4px) scale(1.1); }
    100% { transform: translateY(0) scale(1); }
}
.scroll-to-top:hover {
    box-shadow: 0 12px 30px -4px rgba(59, 130, 246, 0.52),
                0 6px 14px -2px rgba(6, 182, 212, 0.32);
    transform: translateY(-3px) scale(1);
    filter: brightness(1.06) saturate(1.08);
}
.scroll-to-top:active {
    transform: scale(0.92);
    box-shadow: 0 4px 10px rgba(59, 130, 246, 0.30);
}
.scroll-to-top i {
    font-size: 24px;
    line-height: 1;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Arrow bounces up on hover — invites the user to scroll up */
.scroll-to-top:hover i { transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) {
    .scroll-to-top.is-visible { animation: none; }
    .scroll-to-top i { transition: none; }
    .scroll-to-top:hover i { transform: none; }
}

/* Desktop — no tab bar, button sits lower-right corner */
@media (min-width: 768px) {
    .scroll-to-top {
        right: 32px;
        bottom: 32px;
        width: 48px;
        height: 48px;
    }
    .scroll-to-top i { font-size: 26px; }
}


/* ================================================================
   45. PERIOD TABS — segmented-control filter (iOS Photos style)
        Used on Transactions page to switch Today/Week/Month/30d/All
================================================================ */
.period-tabs {
    display: flex;
    padding: 4px;
    background: var(--surface-2, #f1f5f9);
    border-radius: 12px;
    gap: 0;
    margin: 0 0 var(--space-2);
    overflow: hidden;
    position: relative;
}

.period-tabs__btn {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    padding: 8px 4px;
    background: transparent;
    border: none;
    border-radius: 8px;
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-secondary, #64748b);
    cursor: pointer;
    transition: color 0.12s ease, background 0.18s ease, box-shadow 0.18s ease, transform 0.08s ease;
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
    line-height: 1.2;
    /* Reset <a> defaults so anchor tabs look identical to button tabs */
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.period-tabs__btn:visited,
.period-tabs__btn:link {
    color: var(--text-secondary, #64748b);
    text-decoration: none;
}
.period-tabs__btn.is-active:visited,
.period-tabs__btn.is-active:link {
    color: #ffffff;
}

.period-tabs__btn:hover {
    color: var(--text-primary, #0f172a);
}

.period-tabs__btn:active {
    transform: scale(0.97);
}

/* Active tab — brand gradient fill, white text, soft glow */
.period-tabs__btn.is-active {
    background: var(--brand-gradient);
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.32);
    font-weight: var(--fw-semi, 600);
    cursor: default;
}

/* Very small phones — compact text to ensure all 5 fit */
@media (max-width: 360px) {
    .period-tabs__btn {
        font-size: 12px;
        padding: 7px 2px;
    }
}

/* Desktop — slightly more breathing room */
@media (min-width: 768px) {
    .period-tabs__btn {
        font-size: 14px;
        padding: 10px 8px;
    }
}


/* ================================================================
   46. DASHBOARD — money overflow fix + Hide Balance toggle
================================================================ */

/* ---- Header actions (toggle + profile avatar side by side) ---- */
.page-header__actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

/* Eye toggle button (matches profile-avatar size for visual rhythm) */
.balance-toggle {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: none;
    background: var(--surface-2, #f1f5f9);
    color: var(--text-secondary, #64748b);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease, color 0.15s ease, transform 0.08s ease;
}
.balance-toggle:hover  { background: var(--surface-3, #e2e8f0); color: var(--text-primary, #0f172a); }
.balance-toggle:active { transform: scale(0.94); }
.balance-toggle i      { font-size: 22px; }

/* ---- Fix money overflow on dashboard cards ---- */
/* Net Worth card — large hero number */
.card--summary {
    overflow: hidden;
}
.card--summary .money--xl {
    font-size: clamp(22px, 7vw, 32px);
    line-height: 1.2;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* Income / Expense 2-col grid — prevent grid items from forcing overflow */
.dashboard-stats {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.dashboard-stats .card {
    min-width: 0;
    overflow: hidden;
}
/* 🆕 v3.1.0 Phase Q Round 3 — I/E card polish per draft §1a line 400-402.
   Flatter than the global .card (no brand-tinted lift) so it reads as
   subordinate to the Net Worth hero above. Tighter 14/16 padding. */
.dashboard-stats__card {
    padding: 14px 16px !important;
    border: 1px solid var(--border-soft, #eef1f5) !important;
    box-shadow: none !important;      /* flat — no card lift here */
    border-radius: 14px !important;
}
.dashboard-stats__card .card__label {
    margin: 0 0 8px;
    font-size: 11px;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--text-muted, #94a3b8);
    text-transform: uppercase;
}
.dashboard-stats__caption {
    margin: 6px 0 0;
    font-size: 11px;
    color: var(--text-muted, #94a3b8);
    font-weight: 500;
}
.dashboard-stats__money {
    font-size: clamp(16px, 4.6vw, 22px);
    line-height: 1.25;
    word-break: break-word;
    overflow-wrap: anywhere;
    white-space: normal;
}

/* Even tighter on very small phones */
@media (max-width: 360px) {
     .dashboard-stats { gap: 8px; }
    .dashboard-stats__money { font-size: 16px; }
    .card--summary .money--xl { font-size: 22px; }
}


/* ================================================================
   47. HIDE BALANCE — bank-style dot mask
================================================================ */
.balance-value.is-masked {
    letter-spacing: 0.18em;
    cursor: default;
    user-select: none;
}

html.balance-hidden .balance-value:not(.is-masked) {
    visibility: hidden;
}

html.balance-hidden .balance-toggle,
body.balance-hidden .balance-toggle {
    background: rgba(59, 130, 246, 0.10);
    color: #1d4ed8;
}


/* ================================================================
   48. TEMPLATES / FAVORITES — Chip strip + Save-as toggle
================================================================ */

/* Strip wrapper at top of Add Transaction form */
.tx-templates {
    margin: 0 0 16px;
    padding: 12px 0 4px;
    border-bottom: 1px solid var(--border-light, #eef2f6);
}

.tx-templates__header {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px;
    padding: 0 4px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-secondary, #64748b);
}
.tx-templates__header i {
    font-size: 14px;
    color: #f59e0b;     /* amber star */
}

.tx-templates__strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 2px 4px 6px;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
}
.tx-templates__strip::-webkit-scrollbar { display: none; }
.tx-templates__strip { scrollbar-width: none; }

/* 🆕 v3.1.0 Phase Z §3a Round 6 — template chip (favorites strip on form):
   brand-tinted lift on default + hover reveal + icon scale on tap. */
.tpl-chip {
    position: relative;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 32px 8px 10px;     /* extra right pad for X */
    background: #ffffff;
    border: 1.5px solid var(--border-soft, #eef1f5);
    border-radius: 12px;
    box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.10);
    font: inherit;
    color: var(--text-primary, #0f172a);
    cursor: pointer;
    scroll-snap-align: start;
    transition: transform .14s ease, box-shadow .18s ease, border-color .14s ease;
    -webkit-tap-highlight-color: transparent;
}
.tpl-chip:hover {
    transform: translateY(-1px);
    border-color: #93c5fd;
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.20),
                0 2px 6px -1px rgba(15, 23, 42, 0.06);
}
.tpl-chip:hover .tpl-chip__icon { transform: scale(1.08); }
.tpl-chip:active {
    transform: scale(0.97);
    border-color: var(--brand-500, #3b82f6);
    box-shadow: 0 2px 6px rgba(59, 130, 246, 0.15);
}
.tpl-chip__icon {
    transition: transform .18s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.tpl-chip__icon {
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 15px;
}

.tpl-chip__body {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.1;
    text-align: left;
}
.tpl-chip__name {
    font-size: 13px;
    font-weight: 600;
    max-width: 130px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tpl-chip__amt {
    margin-top: 2px;
    font-size: 11px;
    font-weight: 500;
    color: var(--text-secondary, #64748b);
}

/* Tiny X button on chip */
.tpl-chip__del {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.04);
    color: var(--text-secondary, #64748b);
    font-size: 14px;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.tpl-chip__del:hover,
.tpl-chip__del:active {
    background: rgba(239, 68, 68, 0.12);
    color: #dc2626;
}

/* 🆕 v3.1.0 Phase Z §3a Round 5 — Save-as-template toggle row:
   amber-tinted lift + hover shadow + border intensify on check. */
.tx-star-row {
    margin-top: 20px;
    padding: 14px;
    background: linear-gradient(135deg, #fff7ed 0%, #fffbeb 100%);
    border: 1.5px solid #fde68a;
    border-radius: 14px;
    box-shadow: 0 4px 14px -4px rgba(245, 158, 11, 0.18),
                0 1px 4px -1px rgba(245, 158, 11, 0.08);
    transition: border-color .18s ease, box-shadow .18s ease;
}
.tx-star-row:has(.tx-star-toggle__input:checked) {
    border-color: #fbbf24;
    box-shadow: 0 8px 22px -4px rgba(245, 158, 11, 0.28),
                0 2px 8px -2px rgba(245, 158, 11, 0.14);
}

.tx-star-toggle {
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}

.tx-star-toggle__input {
    /* Custom-styled checkbox — hide native, style via :checked + icon */
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* 🆕 v3.1.0 Phase Z §3a Round 5 — star icon tile:
   checked state picks up a soft amber glow + spring scale, filled star
   rotates in briefly for a satisfying flip. */
.tx-star-toggle__icon {
    position: relative;
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 11px;
    background: #fff;
    border: 1.5px solid #fbbf24;
    color: #f59e0b;
    font-size: 22px;
    transition: background 0.2s ease, color 0.2s ease,
                transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.2s ease;
}
.tx-star-toggle__icon .bx { position: absolute; transition: opacity 0.2s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); }
.tx-star-toggle__icon .bxs-star { opacity: 0; transform: scale(0.4) rotate(-120deg); }
.tx-star-toggle__input:checked + .tx-star-toggle__icon {
    background: linear-gradient(135deg, #f59e0b 0%, #f97316 100%);
    color: #fff;
    transform: scale(1.08);
    box-shadow: 0 6px 18px rgba(245, 158, 11, 0.42),
                0 0 0 3px rgba(245, 158, 11, 0.18);
}
.tx-star-toggle__input:checked + .tx-star-toggle__icon .bx-star  { opacity: 0; transform: scale(0.4) rotate(120deg); }
.tx-star-toggle__input:checked + .tx-star-toggle__icon .bxs-star { opacity: 1; transform: scale(1) rotate(0); }
.tx-star-toggle:hover .tx-star-toggle__icon {
    transform: scale(1.03);
}
.tx-star-toggle__input:checked ~ .tx-star-toggle__icon,
.tx-star-toggle__input:checked + .tx-star-toggle__icon {
    /* keep checked scale even on hover */
    transform: scale(1.08);
}

.tx-star-toggle__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.25;
}
.tx-star-toggle__text strong {
    font-size: 14px;
    font-weight: 600;
    color: #92400e;
}
.tx-star-toggle__text small {
    font-size: 12px;
    color: #b45309;
}

/* Name input revealed below toggle when checked */
.tx-star-name {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed #fde68a;
}
.tx-star-name .tx-field__label {
    color: #92400e;
}
.tx-star-name .tx-input {
    background: #ffffff;
    border-color: #fbbf24;
}
.tx-star-name .tx-input:focus {
    border-color: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18);
}

/* Hidden helper */
.tx-star-row[hidden],
.tx-templates[hidden],
.tx-star-name[hidden] { display: none !important; }


/* ================================================================
   49. QUICK ADD — Dashboard Templates widget
================================================================ */
.quick-add {
    margin: 0 0 20px;
}

.quick-add .section-head__title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.quick-add__star {
    color: #f59e0b;
    font-size: 18px;
}

/* 🆕 Option A — Grouped category cards (June 16, 2026) */
.qa-cats {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
}
@media (max-width: 480px) {
    .qa-cats { grid-template-columns: repeat(2, 1fr); }
}

.qa-cat {
    position: relative;
    appearance: none;
    border: none;
    background: #fff;
    border-radius: 14px;
    padding: 12px 8px 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
    -webkit-tap-highlight-color: transparent;
    width: 100%;
}
.qa-cat:active {
    transform: scale(0.96);
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.20);
}

.qa-cat__icon {
    width: 36px; height: 36px;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 20px;
}
.qa-cat__name {
    font-size: 12px;
    font-weight: 600;
    color: #0f172a;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
    text-align: center;
}
.qa-cat__count {
    position: absolute;
    top: 6px;
    right: 6px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
    font-size: 11px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}

.quick-add[hidden] { display: none !important; }

/* ---- Picker bottom sheet contents ---- */
.qa-picker-list {
    list-style: none;
    margin: 0 0 14px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.qa-picker-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 12px;
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.06);
    cursor: pointer;
    transition: background 0.12s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}
.qa-picker-item:active {
    transform: scale(0.99);
    background: rgba(59, 130, 246, 0.05);
}
.qa-picker-item__icon {
    width: 32px; height: 32px;
    border-radius: 10px;
    background: rgba(59, 130, 246, 0.10);
    color: #2563eb;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    flex-shrink: 0;
}
.qa-picker-item__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.qa-picker-item__name {
    font-size: 14px;
    font-weight: 600;
    color: #0f172a;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.qa-picker-item__sub {
    font-size: 12px;
    color: #64748b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.qa-picker-item__amt {
    font-size: 13px;
    font-weight: 700;
    color: #2563eb;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
.qa-picker-item__del {
    appearance: none;
    border: none;
    background: rgba(15, 23, 42, 0.05);
    color: #64748b;
    width: 28px; height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.12s ease, color 0.12s ease;
}
.qa-picker-item__del:hover,
.qa-picker-item__del:active {
    background: rgba(239, 68, 68, 0.14);
    color: #dc2626;
}

.qa-picker__hint {
    margin: 14px 4px 0;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(59, 130, 246, 0.06);
    color: #475569;
    font-size: 12.5px;
    line-height: 1.5;
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.qa-picker__hint i {
    color: #2563eb;
    font-size: 16px;
    flex-shrink: 0;
    margin-top: 1px;
}
/* Wrap the text in a single flex item so <strong> doesn't break the flow.
   Without this, each text node becomes a separate flex child and wraps weird. */
.qa-picker__hint > span {
    flex: 1;
    min-width: 0;
}
.qa-picker__hint strong { color: #0f172a; font-weight: 700; }


/* ================================================================
   50. KEYBOARD ICONS — inline SVG sizing
================================================================ */
.vkb__key-icon,
.numpad__key-icon {
    display: inline-block;
    vertical-align: middle;
    width: 22px;
    height: 22px;
    color: inherit;
    pointer-events: none;
}
.numpad__key-icon { width: 24px; height: 24px; }

/* Active shift / caps-lock — fill icon highlighted */
.vkb__key.is-active .vkb__key-icon {
    color: #3b82f6;     /* brand blue — signals caps engaged */
}


/* ================================================================
   51. CHANGE PASSWORD — collapsible card on More page
================================================================ */
.pw-change-card {
    margin-bottom: 16px;
    overflow: hidden;
}

.pw-change-card__header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
    cursor: pointer;
    user-select: none;
}
.pw-change-card__icon {
    width: 40px; height: 40px;
    flex: 0 0 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 20px;
}
.pw-change-card__heading { flex: 1; min-width: 0; }
.pw-change-card__title { font-size: 15px; font-weight: 600; color: var(--text-primary, #0f172a); margin: 0; }
.pw-change-card__hint  { font-size: 12px; color: var(--text-muted, #94a3b8); margin: 2px 0 0; }

.pw-change-card__toggle {
    background: none;
    border: none;
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    color: var(--text-secondary, #64748b);
    font-size: 22px;
    cursor: pointer;
    transition: transform 0.18s ease, background 0.18s ease;
}
.pw-change-card__toggle:hover { background: rgba(15,23,42,0.05); }
.pw-change-card__toggle.is-open { transform: rotate(180deg); }

/* Form (revealed when toggle.is-open) */
.pw-change-form {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-light, #e2e8f0);
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.pw-change-form[hidden] { display: none !important; }

.pw-change-field { display: flex; flex-direction: column; gap: 6px; }
.pw-change-field label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-secondary, #475569);
}
.pw-change-field input[type="password"] {
    height: 44px;
    padding: 0 14px;
    background: #f8fafc;
    border: 1.5px solid var(--border-light, #e2e8f0);
    border-radius: 10px;
    font: inherit;
    font-size: 15px;
    color: var(--text-primary, #0f172a);
    transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.pw-change-field input[type="password"]:focus {
    outline: none;
    background: #fff;
    border-color: #06b6d4;
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15);
}

/* Strength meter */
.pw-strength {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    font-size: 12px;
}
.pw-strength__bar {
    flex: 1;
    height: 6px;
    background: #e2e8f0;
    border-radius: 4px;
    overflow: hidden;
}
.pw-strength__fill {
    display: block;
    height: 100%;
    width: 0%;
    background: #94a3b8;
    transition: width 0.2s ease, background 0.2s ease;
}
.pw-strength__label {
    flex: 0 0 auto;
    font-weight: 600;
    min-width: 70px;
    text-align: right;
}

/* Inline error/success message */
.pw-change-msg {
    padding: 10px 12px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.4;
}
.pw-change-msg--error {
    background: rgba(225, 29, 72, 0.08);
    border: 1px solid rgba(225, 29, 72, 0.20);
    color: #be123c;
}
.pw-change-msg--success {
    background: rgba(5, 150, 105, 0.08);
    border: 1px solid rgba(5, 150, 105, 0.20);
    color: #065f46;
}
.pw-change-msg[hidden] { display: none !important; }

/* Footer buttons — branded, matching app style */
.pw-change-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    align-items: center;
    margin-top: 8px;
    padding-top: 14px;
    border-top: 1px solid var(--border-light, #f1f5f9);
    flex-wrap: wrap;
}

.pw-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 44px;
    padding: 0 20px;
    border-radius: 12px;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    border: none;
    transition: transform 0.12s ease, box-shadow 0.18s ease,
                background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
}
.pw-btn i { font-size: 17px; line-height: 1; }
.pw-btn:active { transform: scale(0.97); }
.pw-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    transform: none;
}

.pw-btn--primary {
    background: var(--brand-gradient);
    color: #ffffff;
    box-shadow: 0 6px 16px -4px rgba(59, 130, 246, 0.40),
                0 2px 4px -1px rgba(6, 182, 212, 0.20);
    min-width: 160px;
}
.pw-btn--primary:hover:not(:disabled) {
    box-shadow: 0 10px 22px -6px rgba(59, 130, 246, 0.50),
                0 4px 8px -2px rgba(6, 182, 212, 0.30);
    filter: brightness(1.04);
}

.pw-btn--ghost {
    background: #f1f5f9;
    color: var(--text-secondary, #475569);
    border: 1px solid transparent;
}
.pw-btn--ghost:hover:not(:disabled) {
    background: #e2e8f0;
    color: var(--text-primary, #0f172a);
    border-color: var(--border-light, #cbd5e1);
}

@media (max-width: 380px) {
    .pw-change-actions {
        flex-direction: column-reverse;
        align-items: stretch;
    }
    .pw-btn { width: 100%; }
}


/* ================================================================
   52. FILTERS SHEET — redesigned (presets + search-only + sticky)
================================================================ */

/* Header badge */
.flt-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.flt-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 22px; height: 22px;
    padding: 0 7px;
    background: var(--brand-gradient);
    color: #fff;
    border-radius: 11px;
    font-size: 11px;
    font-weight: 700;
    margin-left: 8px;
    vertical-align: middle;
}
.flt-badge[hidden] { display: none !important; }

/* Body — must take remaining flex space + own its scroll */
.flt-body {
    padding: 8px 16px 24px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;                  /* required so flex child can shrink */
    -webkit-overflow-scrolling: touch;
}

/* Section */
.flt-section { margin-bottom: 18px; }
.flt-section__title {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-secondary, #64748b);
    margin: 0 0 8px;
}

/* Collapsible section header */
.flt-section--collapsible .flt-section__head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 0;
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}
.flt-section--collapsible .flt-section__head .flt-section__title { margin: 0; flex: 0 0 auto; }
.flt-section__hint {
    flex: 1;
    font-size: 13px;
    color: var(--text-muted, #94a3b8);
    text-align: right;
}
.flt-section__chev {
    font-size: 20px;
    color: var(--text-muted, #94a3b8);
    transition: transform 0.2s ease;
}
.flt-section__head[aria-expanded="true"] .flt-section__chev { transform: rotate(180deg); }

/* Grid */
.flt-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 10px;
}
.flt-field { display: flex; flex-direction: column; gap: 4px; }
.flt-field > span {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted, #94a3b8);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Preset chip row */
.flt-presets {
    margin-bottom: 4px;
}

/* Search input + dropdown */
.flt-search {
    position: relative;
    display: flex;
    align-items: center;
    background: #f8fafc;
    border: 1.5px solid var(--border-light, #e2e8f0);
    border-radius: 12px;
    padding: 0 10px;
    height: 44px;
    transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.flt-search:focus-within {
    background: #fff;
    border-color: #06b6d4;
    box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15);
}
.flt-search__icon {
    font-size: 18px;
    color: var(--text-muted, #94a3b8);
    margin-right: 8px;
    flex: 0 0 18px;
}
.flt-search__input {
    flex: 1;
    height: 100%;
    background: transparent;
    border: none;
    outline: none;
    font: inherit;
    font-size: 14px;
    color: var(--text-primary, #0f172a);
}
.flt-search__input::placeholder { color: var(--text-muted, #94a3b8); }

/* Dropdown */
.flt-search__dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    list-style: none;
    margin: 0;
    padding: 4px;
    max-height: 240px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--border-light, #e2e8f0);
    border-radius: 10px;
    box-shadow: 0 10px 30px -8px rgba(15, 23, 42, 0.18);
}
.flt-search__dropdown[hidden] { display: none !important; }
.flt-search__dropdown li {
    padding: 9px 12px;
    border-radius: 7px;
    font-size: 14px;
    color: var(--text-primary, #0f172a);
    cursor: pointer;
    user-select: none;
}
.flt-search__dropdown li:hover,
.flt-search__dropdown li:active {
    background: rgba(6, 182, 212, 0.10);
    color: #0891b2;
}

/* Selected tags below search */
.flt-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}
.flt-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 4px 5px 10px;
    background: linear-gradient(135deg, rgba(59,130,246,0.10), rgba(6,182,212,0.10));
    border: 1px solid rgba(6,182,212,0.30);
    color: #0c4a6e;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
}
.flt-tag__rm {
    width: 20px; height: 20px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: rgba(0,0,0,0.06);
    border: none;
    color: inherit;
    font-size: 14px;
    cursor: pointer;
    transition: background 0.12s ease;
}
.flt-tag__rm:hover { background: rgba(225,29,72,0.20); color: #be123c; }

/* Sticky footer + scrollable body
   (.flt-sheet__panel removed — handled by .app-sheet__panel + .app-sheet--slide) */
.flt-footer {
    position: sticky;
    bottom: 0;
    z-index: 5;
    background: #ffffff;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-light, #e2e8f0);
    box-shadow: 0 -4px 12px -4px rgba(15, 23, 42, 0.06);
}
.flt-live-count {
    margin: 0 0 8px;
    text-align: center;
    font-size: 12px;
    color: var(--text-secondary, #64748b);
    font-weight: 500;
}
.flt-actions {
    display: flex;
    gap: 10px;
}
.flt-actions .pw-btn { flex: 1; height: 46px; }

/* Mobile narrow — full-screen sheet pattern */
@media (max-width: 768px) {
    .flt-grid { grid-template-columns: 1fr 1fr; }
}


/* ================================================================
   53. PERIOD-TABS WRAP — multi-row variant for Filter sheet
================================================================ */
/* When too many tabs to fit (e.g. 7 date presets), allow row wrap */
.period-tabs--wrap {
    flex-wrap: wrap;
    row-gap: 4px;
}
.period-tabs--wrap .period-tabs__btn {
    flex: 1 1 calc(33.333% - 2px);  /* 3 per row on narrow screens */
    min-width: 70px;
    font-size: 12px;
    padding: 7px 4px;
}
/* Smaller chips on very narrow screens */
@media (max-width: 380px) {
    .period-tabs--wrap .period-tabs__btn {
        flex: 1 1 calc(50% - 2px);    /* 2 per row */
        font-size: 12px;
    }
}
/* Wider screens — try 4 per row */
@media (min-width: 480px) {
    .period-tabs--wrap .period-tabs__btn {
        flex: 1 1 calc(25% - 2px);
    }
}


/* ================================================================
   54. FILTER PICKER LIST — always-visible scrollable list (multi-select)
================================================================ */
.flt-pick {
    list-style: none;
    margin: 8px 0 0;
    padding: 4px;
    /* 🆕 Reduced from 240 → 180 + overscroll-behavior to keep scroll from chaining to body unexpectedly */
    max-height: 180px;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    background: #ffffff;
    border: 1px solid var(--border-light, #e2e8f0);
    border-radius: 12px;
    /* Subtle scrollbar */
    scrollbar-width: thin;
}
.flt-pick::-webkit-scrollbar { width: 6px; }
.flt-pick::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.15);
    border-radius: 3px;
}

.flt-pick__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    font-size: 14px;
    color: var(--text-primary, #0f172a);
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.12s ease, color 0.12s ease;
}
.flt-pick__row:hover {
    background: rgba(6, 182, 212, 0.06);
}
.flt-pick__row:active {
    background: rgba(6, 182, 212, 0.12);
}
.flt-pick__row.is-selected {
    background: linear-gradient(135deg, rgba(59,130,246,0.10), rgba(6,182,212,0.10));
    color: #0c4a6e;
    font-weight: 600;
}

.flt-pick__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.flt-pick__check {
    flex: 0 0 22px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: transparent;
    color: transparent;
    font-size: 16px;
    transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.flt-pick__row.is-selected .flt-pick__check {
    background: var(--brand-gradient);
    color: #ffffff;
    transform: scale(1);
}

.flt-pick__empty {
    padding: 16px 12px;
    text-align: center;
    font-size: 13px;
    color: var(--text-muted, #94a3b8);
    font-style: italic;
}


/* ================================================================
   55. CLEAR FILTERS PILL — shows below period tabs when filters active
================================================================ */
.tx-clear-bar {
    margin: 6px 0 10px;
    display: flex;
    justify-content: center;
}
.tx-clear-bar[hidden] { display: none !important; }

.tx-clear-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px 7px 12px;
    background: linear-gradient(135deg, rgba(59,130,246,0.10), rgba(6,182,212,0.10));
    border: 1px solid rgba(6,182,212,0.30);
    border-radius: 999px;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    color: #0c4a6e;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.15s ease, background 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.tx-clear-pill > i:first-of-type {
    font-size: 15px;
    color: #06b6d4;
}
.tx-clear-pill:hover {
    background: linear-gradient(135deg, rgba(59,130,246,0.15), rgba(6,182,212,0.15));
    box-shadow: 0 2px 8px -2px rgba(6, 182, 212, 0.25);
}
.tx-clear-pill:active {
    transform: scale(0.97);
}

.tx-clear-pill__x {
    margin-left: 4px;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    font-size: 13px;
    color: var(--text-secondary, #475569);
    transition: background 0.12s ease, color 0.12s ease;
}
.tx-clear-pill:hover .tx-clear-pill__x {
    background: rgba(225, 29, 72, 0.18);
    color: #be123c;
}


/* ============================================
 * 56. PIN — login button + bottom sheet (June 14, 2026)
 * ============================================ */

/* ----- Login: secondary PIN button ----- */
.login-pin-btn {
    width: 100%;
    margin-top: 10px;
    height: 48px;
    padding: 0 18px;
    border-radius: 12px;
    border: 1.5px solid rgba(59, 130, 246, 0.28);
    background: rgba(59, 130, 246, 0.06);
    color: #1e40af;
    font-weight: 600;
    font-size: 15px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    cursor: pointer;
    transition: background 0.15s, transform 0.08s;
}
.login-pin-btn:hover  { background: rgba(59, 130, 246, 0.12); }
.login-pin-btn:active { transform: scale(0.98); }
.login-pin-btn > i    { font-size: 20px; color: #2563eb; }

/* ----- PIN-only variant of the big Face-ID-style primary button ----- */
.login-faceid-btn--pin { background: var(--brand-gradient); }

/* ----- Bottom sheet ----- */
.pin-sheet {
    position: fixed; inset: 0;
    z-index: 1200;
    pointer-events: none;
}
.pin-sheet.is-open { pointer-events: auto; }

.pin-sheet__backdrop {
    position: absolute; inset: 0;
    background: rgba(15, 23, 42, 0.55);
    opacity: 0;
    transition: opacity 0.18s ease;
}
.pin-sheet.is-open .pin-sheet__backdrop { opacity: 1; }

.pin-sheet__panel {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    background: #fff;
    border-radius: 20px 20px 0 0;
    padding: 22px 22px calc(28px + env(safe-area-inset-bottom));
    transform: translateY(100%);
    transition: transform 0.22s cubic-bezier(.2,.7,.2,1);
    max-width: 540px;
    margin: 0 auto;
    box-shadow: 0 -8px 32px rgba(15, 23, 42, 0.15);
}
.pin-sheet.is-open .pin-sheet__panel { transform: translateY(0); }

.pin-sheet__close {
    position: absolute;
    top: 12px; right: 12px;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    border: none;
    color: #475569;
    font-size: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.pin-sheet__head { text-align: center; margin: 4px 0 14px; }
.pin-sheet__title {
    margin: 0;
    font-size: 18px;
    font-weight: 700;
    color: #0f172a;
}
.pin-sheet__subtitle {
    margin: 4px 0 0;
    font-size: 13px;
    color: #64748b;
}
.pin-sheet__error {
    text-align: center;
    color: #be123c;
    font-size: 13px;
    margin: 4px 0 -2px;
}

/* ----- 6 dots ----- */
.pin-dots {
    display: flex;
    justify-content: center;
    gap: 14px;
    margin: 12px 0 20px;
}
.pin-dot {
    width: 14px; height: 14px;
    border-radius: 50%;
    background: transparent;
    border: 2px solid rgba(15, 23, 42, 0.22);
    transition: transform 0.12s, background 0.12s, border-color 0.12s;
}
.pin-dot.is-filled {
    background: var(--brand-gradient);
    border-color: transparent;
    transform: scale(1.1);
}

/* Shake animation for wrong PIN */
@keyframes pinShake {
    0%,100% { transform: translateX(0); }
    20% { transform: translateX(-8px); }
    40% { transform: translateX(8px); }
    60% { transform: translateX(-6px); }
    80% { transform: translateX(6px); }
}
.pin-dots.is-shake { animation: pinShake 0.4s ease; }
.pin-dots.is-shake .pin-dot {
    border-color: #fb7185;
    background: rgba(253, 164, 175, 0.4);
}

/* ----- Inline keypad ----- */
/* PIN Login keypad — polish matched to numpad / EN VKB
   (v3.1.2+ · owner feedback: digits were too bold at weight 600).
   Thinner typeface, bigger glyph, subtle inner highlight,
   gradient press feedback with a spring bounce. */
.pin-keypad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    max-width: 320px;
    margin: 0 auto;
}
.pin-keypad__key {
    height: 56px;
    border-radius: 14px;
    border: none;
    background: rgba(15, 23, 42, 0.04);
    color: #0f172a;
    /* Lighter weight + larger glyph + tight tracking = modern iOS */
    font-size: 26px;
    font-weight: 400;
    letter-spacing: -0.5px;
    font-variant-numeric: tabular-nums;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    /* Three-layer shadow for a glossy physical key feel */
    box-shadow:
        0 1px 0  rgba(15, 23, 42, 0.10),
        0 2px 4px rgba(15, 23, 42, 0.04),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    transition:
        background 0.12s ease,
        box-shadow 0.12s ease,
        transform 0.08s cubic-bezier(0.34, 1.56, 0.64, 1);
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}
.pin-keypad__key:active {
    background: linear-gradient(135deg,
        rgba(59, 130, 246, 0.16),
        rgba(29, 78, 216, 0.08));
    transform: translateY(1px) scale(0.95);
    box-shadow:
        inset 0 0 0 1px rgba(59, 130, 246, 0.30),
        0 0 0 rgba(15, 23, 42, 0);
}
.pin-keypad__key--blank {
    background: transparent;
    box-shadow: none;
    cursor: default;
    pointer-events: none;
}
.pin-keypad__key--back {
    background: transparent;
    color: #dc2626;
    box-shadow: none;
}
.pin-keypad__key--back:active {
    background: linear-gradient(135deg,
        rgba(239, 68, 68, 0.18),
        rgba(220, 38, 38, 0.10));
    color: #991b1b;
    transform: translateY(1px) scale(0.95);
    box-shadow:
        inset 0 0 0 1px rgba(220, 38, 38, 0.35),
        0 0 0 rgba(15, 23, 42, 0);
}

body.pin-sheet-active { overflow: hidden; }

/* ============================================================
   TOTP (Authenticator) — v3.1.3
   Enrol sheet + challenge sheet styling.
   ============================================================ */
.auth-method__icon--totp {
    background: rgba(99, 102, 241, 0.12);
    color: #4f46e5;
}

.totp-sheet .app-sheet__content {
    padding: 20px 16px 24px;
    display: flex;
    flex-direction: column;
}

/* Scope close button absolute to top-right (title no longer competes for space) */
.totp-sheet .app-sheet__header {
    position: relative;
    padding: 16px 56px 16px 20px;
}
.totp-sheet .app-sheet__close {
    position: absolute;
    top: 10px;
    right: 10px;
}

/* Each step is a full-height flex column so primary button can be pinned
   to the bottom via margin-top: auto on the button itself. */
.totp-step {
    display: flex;
    flex-direction: column;
    gap: 18px;
    flex: 1 1 auto;
    min-height: 100%;
}
/* Primary button sits last → push to bottom edge */
.totp-step > .totp-wide:last-child {
    margin-top: auto;
}

/* ---- Step header (counter chip + title + sub) ---- */
.totp-stephead {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-bottom: 14px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.totp-stephead__counter {
    align-self: flex-start;
    padding: 3px 10px;
    background: var(--brand-gradient, linear-gradient(135deg, #3b82f6, #1d4ed8));
    color: #fff;
    border-radius: 999px;
    font-size: 11px;
    font-weight: var(--fw-semi, 600);
    letter-spacing: 0.3px;
    text-transform: uppercase;
}
.totp-stephead__title {
    margin: 0;
    font-size: 17px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-primary, #0f172a);
    line-height: 1.3;
}
.totp-stephead__sub {
    margin: 0;
    font-size: 13.5px;
    color: var(--text-secondary, #64748b);
    line-height: 1.5;
}

/* ---- QR card wrapper · full-width card holding a large square QR ---- */
.totp-card {
    width: 100%;
    padding: 20px;
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.08);
    border-radius: var(--r-lg, 14px);
    box-shadow: var(--brand-shadow-sm, 0 3px 10px rgba(37, 99, 235, 0.08));
}
.totp-card .totp-qr {
    width: 100%;
    height: auto;
    max-width: 320px;
    aspect-ratio: 1 / 1;
    margin: 0 auto;
    padding: 0;
    box-shadow: none;
    background: transparent;
}
.totp-card .totp-qr svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* ---- Field group wrapper (Step 2 code input + enrol manual mode) ---- */
.totp-field {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.totp-field__label {
    font-size: 12.5px;
    font-weight: var(--fw-semi, 600);
    color: var(--text-secondary, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.totp-field__box {
    padding: 12px 14px;
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.1);
    border-radius: var(--r-md, 10px);
    font-size: 15px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-primary, #0f172a);
    user-select: all;
    word-break: break-all;
}

/* Enrol Step 1 · mode wrappers (scan / manual) share spacing */
.totp-mode {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Manual entry info hint */
.totp-manual__hint {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 0;
    padding: 10px 12px;
    background: rgba(37, 99, 235, 0.06);
    border: 1px solid rgba(37, 99, 235, 0.15);
    border-radius: var(--r-md, 10px);
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-secondary, #475569);
}
.totp-manual__hint i {
    font-size: 16px;
    color: var(--brand-700, #1d4ed8);
    flex-shrink: 0;
    margin-top: 1px;
}
.totp-step__prompt {
    margin: 0;
    font-size: 14px;
    color: var(--text-primary, #0f172a);
    line-height: 1.5;
}
.totp-step__prompt--warn {
    display: flex; gap: 8px;
    padding: 10px 12px;
    background: rgba(251, 191, 36, 0.08);
    border: 1px solid rgba(251, 191, 36, 0.3);
    border-radius: var(--r-md, 10px);
    color: #92400e;
}
.totp-step__prompt--warn i { font-size: 18px; flex-shrink: 0; }

.totp-step__sub {
    margin: 0;
    font-size: 12px;
    color: var(--text-secondary, #64748b);
    text-align: center;
}

.totp-step__lost {
    margin: 8px 0 0;
    font-size: 13px;
    color: var(--text-secondary, #64748b);
    text-align: center;
}
.totp-step__lost a { color: var(--brand-700, #1d4ed8); text-decoration: underline; cursor: pointer; }

.totp-qr {
    width: 240px;
    height: 240px;
    margin: 0 auto;
    background: #fff;
    padding: 10px;
    border-radius: var(--r-md, 10px);
    box-shadow: var(--brand-shadow-sm, 0 3px 10px rgba(37, 99, 235, 0.14));
}
.totp-qr svg { width: 100%; height: 100%; display: block; }

/* Secret key box · full-width grid of 4-char chunks (no overlay button) */
.totp-manual-key {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px 10px;
    width: 100%;
    padding: 14px 16px;
    background: #ffffff;
    border: 1.5px solid rgba(15, 23, 42, 0.12);
    border-radius: var(--r-md, 10px);
    user-select: all;
    cursor: text;
}
.totp-manual-key__chunk {
    display: inline-block;
    padding: 6px 0;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 17px;
    font-weight: 700;
    letter-spacing: 2px;
    text-align: center;
    color: var(--brand-700, #1d4ed8);
    background: rgba(37, 99, 235, 0.05);
    border-radius: var(--r-sm, 6px);
    user-select: all;
}

/* Copy-key action chip · below the key box · morphs to success state */
.totp-copy-chip {
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border: none;
    border-radius: 999px;
    background: var(--brand-gradient, linear-gradient(135deg, #3b82f6, #1d4ed8));
    color: #fff;
    font-size: 14px;
    font-weight: var(--fw-semi, 600);
    letter-spacing: 0.2px;
    cursor: pointer;
    box-shadow: 0 4px 12px -4px rgba(37, 99, 235, 0.45),
                inset 0 1px 0 rgba(255, 255, 255, 0.2);
    transition: transform 0.12s cubic-bezier(.4,.0,.2,1),
                box-shadow 0.2s ease,
                background 0.25s ease;
    -webkit-tap-highlight-color: transparent;
}
.totp-copy-chip:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.55),
                inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.totp-copy-chip:active {
    transform: translateY(0) scale(0.96);
    box-shadow: 0 2px 6px -2px rgba(37, 99, 235, 0.45),
                inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.totp-copy-chip:focus-visible {
    outline: 3px solid rgba(37, 99, 235, 0.35);
    outline-offset: 2px;
}
.totp-copy-chip__icon  { font-size: 18px; }
.totp-copy-chip__label { line-height: 1; }

/* Success morph · green gradient + ✓ icon, held 1.5s then reverts */
.totp-copy-chip.is-success {
    background: linear-gradient(135deg, #22c55e, #15803d);
    box-shadow: 0 4px 12px -4px rgba(21, 128, 61, 0.5),
                inset 0 1px 0 rgba(255, 255, 255, 0.22);
    animation: totp-copy-pop 0.28s cubic-bezier(.34,1.56,.64,1);
}
@keyframes totp-copy-pop {
    0%   { transform: scale(0.94); }
    60%  { transform: scale(1.06); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .totp-copy-chip,
    .totp-copy-chip.is-success { transition: background 0.1s ease; animation: none; }
    .totp-copy-chip:hover { transform: none; }
}

.totp-code-input {
    width: 100%;
    height: 56px;
    text-align: center;
    font-size: 28px;
    letter-spacing: 10px;
    font-family: 'IBM Plex Mono', monospace;
    font-weight: 500;
    border: 2px solid rgba(15, 23, 42, 0.1);
    border-radius: var(--r-md, 10px);
    background: #fff;
    color: var(--text-primary, #0f172a);
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.totp-code-input:focus {
    border-color: var(--brand-600, #2563eb);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

.totp-backup-input {
    width: 100%;
    height: 48px;
    text-align: center;
    font-size: 20px;
    letter-spacing: 4px;
    font-family: 'IBM Plex Mono', monospace;
    text-transform: uppercase;
    border: 2px solid rgba(15, 23, 42, 0.1);
    border-radius: var(--r-md, 10px);
    background: #fff;
    outline: none;
    transition: border-color 0.15s ease;
}
.totp-backup-input:focus { border-color: var(--brand-600, #2563eb); }

.totp-err {
    padding: 8px 12px;
    background: rgba(239, 68, 68, 0.08);
    color: #dc2626;
    border-radius: var(--r-sm, 8px);
    font-size: 13px;
    text-align: center;
}

.totp-wide { width: 100%; }

.totp-backup-list {
    list-style: none;
    margin: 0;
    padding: 12px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    background: rgba(15, 23, 42, 0.04);
    border-radius: var(--r-md, 10px);
    font-family: 'IBM Plex Mono', monospace;
    font-size: 14px;
    letter-spacing: 1px;
    text-align: center;
}
.totp-backup-list li {
    padding: 6px 8px;
    background: #fff;
    border-radius: var(--r-sm, 6px);
    user-select: all;
}

.totp-backup-actions {
    display: flex;
    gap: 8px;
}
.totp-backup-actions .pw-btn { flex: 1; }

.totp-saved-check {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 10px 12px;
    background: rgba(37, 99, 235, 0.05);
    border-radius: var(--r-md, 10px);
    font-size: 14px;
    cursor: pointer;
}
.totp-saved-check input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--brand-600, #2563eb); }

/* ----- confirm-popup input (used by Set up PIN password prompt) ----- */
.confirm-popup__input-wrap { margin: 12px 0 8px; }
.confirm-popup__input {
    width: 100%;
    height: 44px;
    padding: 0 14px;
    border-radius: 10px;
    border: 1.5px solid rgba(15, 23, 42, 0.14);
    background: #fff;
    font-size: 15px;
    color: #0f172a;
    transition: border-color 0.15s, box-shadow 0.15s;
}
/* 🆕 v3.1.0 Phase AD confirm-popup Round 1 — 2-tone focus glow (match
   login + tx-input focus patterns). */
.confirm-popup__input:focus {
    outline: none;
    border-color: var(--brand-500, #3b82f6);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14),
                0 4px 12px -4px rgba(37, 99, 235, 0.22);
}



/* ============================================
 * 57. LOGIN KEYPAD-FIRST LAYOUT (June 14, 2026)
 *      • 6-dot PIN indicator
 *      • 4×3 keypad with Face ID button in bottom-left slot
 *      • "Trouble signing in?" tucked link
 * ============================================ */

.login-keypad-mode {
    padding: 4px 0 0;
    text-align: center;
}

/* 6 PIN dots */
.login-dots {
    display: flex;
    justify-content: center;
    gap: 14px;
    margin: 6px 0 14px;
}
.login-dot {
    width: 14px; height: 14px;
    border-radius: 50%;
    background: transparent;
    border: 2px solid rgba(15, 23, 42, 0.22);
    transition: transform 0.12s, background 0.12s, border-color 0.12s;
}
.login-dot.is-filled {
    background: var(--brand-gradient);
    border-color: transparent;
    transform: scale(1.1);
}
@keyframes loginShake {
    0%,100% { transform: translateX(0); }
    20% { transform: translateX(-8px); }
    40% { transform: translateX(8px); }
    60% { transform: translateX(-6px); }
    80% { transform: translateX(6px); }
}
.login-dots.is-shake { animation: loginShake 0.4s ease; }
.login-dots.is-shake .login-dot {
    border-color: #fb7185;
    background: rgba(253, 164, 175, 0.4);
}

.login-keypad-hint {
    text-align: center;
    color: #64748b;
    font-size: 14px;
    margin: 2px 0 10px;
}
.login-keypad-error {
    text-align: center;
    color: #be123c;
    font-size: 13px;
    margin: 0 0 8px;
    min-height: 18px;
}

/* 🆕 Forgot-PIN / use-password fallback (subtle by default, prominent when locked) */
.login-keypad-fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin: 6px auto 14px;
    padding: 8px 14px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    color: #64748b;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    width: auto;
    align-self: center;
    transition: all 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}
.login-keypad-fallback i { font-size: 16px; }
.login-keypad-fallback:hover {
    color: #334155;
    background: rgba(15, 23, 42, 0.04);
}
.login-keypad-fallback:active {
    background: rgba(15, 23, 42, 0.08);
    transform: scale(0.98);
}

/* Locked state — grab attention */
.login-keypad-fallback.is-locked {
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
    color: #fff;
    font-weight: 600;
    border-color: #d97706;
    box-shadow: 0 4px 12px rgba(217, 119, 6, 0.30);
    animation: pulseLock 1.4s ease-in-out infinite;
}
.login-keypad-fallback.is-locked:hover {
    color: #fff;
    background: linear-gradient(135deg, #f59e0b 0%, #b45309 100%);
}
@keyframes pulseLock {
    0%, 100% { box-shadow: 0 4px 12px rgba(217, 119, 6, 0.30); }
    50%      { box-shadow: 0 4px 16px rgba(217, 119, 6, 0.55); }
}

/* 4×3 grid */
.login-keypad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    max-width: 340px;
    margin: 4px auto 0;
}

/* 🆕 v3.1.0 Phase X Login Round 2 — PIN keypad buttons:
   - hover state (soft brand hint for pointer-devices)
   - spring press scale down + bounce back
   - subtle inset shadow on active for tactile depth */
.login-key {
    height: 64px;
    border-radius: 16px;
    border: none;
    background: rgba(15, 23, 42, 0.06);
    color: #0f172a;
    font-size: 24px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.14s ease,
                color 0.14s ease,
                transform 0.14s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.14s ease;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    font-family: inherit;
}
.login-key:hover {
    background: rgba(37, 99, 235, 0.08);
    color: var(--brand-600, #2563eb);
}
.login-key:active {
    background: rgba(37, 99, 235, 0.16);
    color: var(--brand-700, #1d4ed8);
    transform: scale(0.92);
    box-shadow: inset 0 2px 6px rgba(15, 23, 42, 0.10);
}
.login-key--back {
    background: transparent;
    color: #475569;
}
.login-key--back:active {
    background: rgba(15, 23, 42, 0.08);
}

/* Empty placeholder when Face ID slot is hidden */
.login-key--blank {
    background: transparent;
    cursor: default;
    pointer-events: none;
}

/* Face ID button — gradient with white icon to make it the visual primary */
.login-key--faceid {
    background: var(--brand-gradient);
    color: #fff;
    box-shadow: 0 6px 20px -8px rgba(6, 182, 212, 0.5);
    position: relative;
}
.login-key--faceid:active {
    background: var(--brand-gradient);
    transform: scale(0.94);
}
.login-key--faceid > i {
    font-size: 30px;
}
.login-key--faceid.is-loading > i {
    animation: spin 0.8s linear infinite;
}
@keyframes spin {
    from { transform: rotate(0); }
    to   { transform: rotate(360deg); }
}

/* "Trouble signing in?" link */
.login-trouble-link {
    display: block;
    margin: 22px auto 0;
    background: transparent;
    border: none;
    color: #64748b;
    font-size: 13px;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
    padding: 6px 12px;
    font-family: inherit;
}
.login-trouble-link:hover { color: #334155; }
.login-trouble-link:active { color: #1e293b; }

/* When Trouble link expands password form, hide keypad to clean the view */
.login-password-form.is-open ~ .login-keypad-mode,
.login-password-form.is-open ~ .login-primary {
    display: none;
}



/* ============================================
 * 58. DESKTOP LOGIN — Face ID + password coexist (June 14, 2026)
 *      Show Face ID button above expanded password form,
 *      with a thin "or" divider between them.
 *      Threshold: lg = 1024px AND pointer:fine (mouse primary).
 *      iPad landscape (touch, ≥1024px) stays mobile/tablet flow.
 * ============================================ */

@media (pointer: fine) and (min-width: 1024px) {
    /* Both Face ID + password form shown together on desktop */
    .login-primary {
        margin-bottom: 18px;
    }
    /* Add an "or" divider between Face ID button and password form */
    .login-primary:not([hidden]) + .login-trouble-link[hidden] + .login-password-form.is-open::before {
        content: "or";
        display: block;
        text-align: center;
        font-size: 12px;
        color: #94a3b8;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        margin: 6px 0 16px;
        position: relative;
    }
    .login-primary:not([hidden]) + .login-trouble-link[hidden] + .login-password-form.is-open::before::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 0; right: 0;
        height: 1px;
        background: rgba(15, 23, 42, 0.08);
        z-index: -1;
    }
    /* On desktop the Trouble link should hide entirely (form is already visible) */
    .login-trouble-link {
        display: none !important;
    }
    /* Tighten the desktop layout — login card shouldn't be too wide */
    .login-form-wrap {
        max-width: 420px;
        margin: 0 auto;
    }
}



/* ============================================
 * 59. SECURITY PAGE (June 14, 2026)
 *      Dedicated security.php — page head with back button,
 *      mobile/tablet notice banner, and per-device-class
 *      visibility of delete (trash) buttons.
 * ============================================ */

/* ----- Page header with back button ----- */
.security-page-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 4px 12px;
    margin-bottom: 4px;
}
.security-page-head__back {
    width: 40px; height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
    font-size: 28px;
    text-decoration: none;
    transition: background 0.12s, transform 0.06s;
}
.security-page-head__back:hover  { background: rgba(15, 23, 42, 0.10); }
.security-page-head__back:active { transform: scale(0.92); }
.security-page-head__title {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    color: #0f172a;
}

/* 🆕 Optional text wrapper — used when a page has a subtitle/caption
   under the title (e.g. Reports' "This month" indicator). Pages that
   only need a title (Security, Budget) can keep the flat structure. */
.security-page-head__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.security-page-head__caption {
    margin: 2px 0 0;
    font-size: 13px;
    color: #64748b;
    font-weight: 500;
}

/* ----- Mobile/tablet notice banner -----
 *   By default HIDDEN on desktop. Shown only on touch/narrow viewports.
 */
.security-mobile-notice {
    display: none;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 16px;
    margin: 0 0 16px;
    border-radius: 14px;
    background: linear-gradient(135deg, rgba(245, 158, 11, 0.10), rgba(251, 191, 36, 0.06));
    border: 1px solid rgba(245, 158, 11, 0.25);
}
.security-mobile-notice__icon {
    font-size: 22px;
    color: #d97706;
    flex-shrink: 0;
    margin-top: 1px;
}
.security-mobile-notice__title {
    margin: 0 0 4px;
    font-size: 14px;
    font-weight: 600;
    color: #92400e;
}
.security-mobile-notice__body {
    margin: 0;
    font-size: 13px;
    color: #78350f;
    line-height: 1.5;
}

/* ----- Show "use a computer" notice + hide delete buttons ONLY when
 *       the device has NO fine pointer (i.e. touch-only — phones/tablets
 *       without a mouse).
 *
 *  🐛 BUG-FIX (2026-06-28): previously used `(max-width: 1023px)` which
 *     misfired whenever a desktop user opened DevTools narrowing the
 *     viewport. Also used `(pointer: coarse)` which misfired on touch-
 *     screen laptops (Surface, MacBook with touch bar). Both incorrectly
 *     hid the delete button from desktop users.
 *
 *     The correct signal is `any-pointer: fine` — does this device have
 *     ANY fine pointer available (mouse/trackpad)? If yes → it's safe to
 *     enable delete regardless of viewport width or primary input method.
 ----- */
@media (not (any-pointer: fine)) {
    .security-mobile-notice {
        display: flex;
    }
}

/* v3.1.2+ · trashcan button rules for .webauthn-card__rm removed; the
   card itself is gone (DOM-less refactor). Device removal now lives on
   security-method.php, which has its own buttons. */



/* ============================================
 * 60. BUDGET PAGE — Phase 1 (June 14, 2026)
 *      Spending Budget UI (Goals tab placeholder).
 * ============================================ */

/* ---- Tabs ---- */
/* 🆕 v3.1.0 Phase P §11 Round 4 — tightened to match draft §7 line 1561
   (padding 6, radius 12, lighter grey track, active tab text in brand blue). */
.budget-tabs {
    display: flex;
    gap: 4px;
    background: var(--surface-2, #eef1f5);
    padding: 6px;
    border-radius: 12px;
    margin-bottom: 14px;
}
.budget-tab {
    flex: 1;
    height: 36px;
    padding: 0 10px;
    border-radius: 8px;
    border: none;
    background: transparent;
    color: var(--text-muted, #8a93a3);
    font-size: 12.5px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    cursor: pointer;
    position: relative;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: background .14s ease, color .14s ease, box-shadow .14s ease;
}
.budget-tab > i { font-size: 16px; }
.budget-tab.is-active {
    background: #fff;
    color: var(--brand-600, #2563eb);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.10);
}
.budget-tab.is-active > i { color: var(--brand-600, #2563eb); }
.budget-tab:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.budget-tab__soon {
    position: absolute;
    top: -4px; right: 6px;
    font-size: 9px;
    background: var(--brand-gradient);
    color: #fff;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* ---- Period header ---- */
.budget-period {
    display: flex;
    justify-content: space-between;
    align-items: center;        /* 🆕 Round 3 — center-align now that __remain is a chip */
    padding: 0 4px 12px;
    gap: 10px;
}
.budget-period__month {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-secondary, #4a5260);  /* 🆕 Round 3 — matches draft §7 line 1562 "July 2026" */
}
/* 🆕 v3.1.0 Phase P §11 Round 3 — "เหลือ ฿X" chip per draft §7 line 1562 */
.budget-period__remain {
    font-size: 12px;
    color: var(--text-muted, #64748b);
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--surface-2, #f1f5f9);
    border: 1px solid var(--border-soft, #e2e8f0);
    white-space: nowrap;
}

/* ---- Totals card ---- */
.budget-totals {
    padding: 18px 18px 16px;
    margin-bottom: 16px;
    background: linear-gradient(135deg, rgba(59,130,246,0.05), rgba(6,182,212,0.03));
    border: 1px solid rgba(59,130,246,0.12);
}
.budget-totals__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 10px;
}
.budget-totals__label {
    margin: 0 0 4px;
    font-size: 12px;
    color: #64748b;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.budget-totals__numbers {
    margin: 0;
    font-size: 20px;
    font-weight: 700;
    color: #0f172a;
}
.budget-totals__sep { color: #94a3b8; margin: 0 4px; font-weight: 500; }
/* 🆕 v3.1.0 Phase P §11 Round 6 — plan amount visually subordinate per draft */
.budget-totals__plan {
    color: var(--text-muted, #64748b);
    font-weight: 500;
    font-size: 14px;
}
/* 🆕 v3.1.0 Phase P §11 Round 6 — pct right-aligned, slightly smaller to let
   the amounts breathe; matches draft §7 line 1565 (20px/700, muted dark). */
.budget-totals__pct {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-secondary, #5a6472);
    font-variant-numeric: tabular-nums;
}
.budget-totals__status {
    margin: 10px 0 0;
    font-size: 13px;
    font-weight: 600;
}
.budget-totals__status--warn { color: #d97706; }
.budget-totals__status--over { color: #be123c; }

/* ---- Progress bar (shared) ---- */
.budget-bar {
    height: 8px;
    background: rgba(15, 23, 42, 0.08);
    border-radius: 999px;
    overflow: hidden;
    position: relative;
}
.budget-bar__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--brand-gradient);
    transition: width 0.4s cubic-bezier(.2,.7,.2,1);
}
.budget-bar__fill--warn { background: linear-gradient(135deg, #f59e0b, #fbbf24); }
.budget-bar__fill--over { background: linear-gradient(135deg, #ef4444, #fb7185); }

/* 🆕 v3.1.0 Phase P §11 Round 6 — size hierarchy per draft §7:
   totals card has a *hero* 10px bar; per-line items use a 7px bar; goal cards
   use the 7px bar too (unified). All share pill radius. */
.budget-totals .budget-bar { height: 10px; }
.budget-line  .budget-bar  { height: 7px; }
.goal-bar                  { height: 7px; }

/* ---- Lines list ---- */
.budget-lines {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.budget-line {
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.08);
    border-radius: 14px;
    padding: 14px 14px 10px;
}
.budget-line--over { border-color: rgba(239, 68, 68, 0.32); }
.budget-line--warn { border-color: rgba(245, 158, 11, 0.32); }

.budget-line__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 8px;
    gap: 12px;
}
.budget-line__name {
    font-size: 15px;
    font-weight: 600;
    color: #0f172a;
}
.budget-line__nums { font-size: 13px; color: #475569; font-weight: 500; }
.budget-line__spent { color: #0f172a; font-weight: 700; }
.budget-line__sep   { color: #cbd5e1; margin: 0 4px; }
.budget-line__plan  { color: #64748b; }
.budget-line__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 6px;
}
.budget-line__pct {
    font-size: 12px;
    font-weight: 700;
    color: #475569;
}
.budget-line--warn .budget-line__pct { color: #d97706; }
.budget-line--over .budget-line__pct { color: #be123c; }

/* 🆕 v3.1.0 Phase P §11 Round 2 — status chip per draft §7 Hi-Fi line 1572.
   Compact rounded pill colored by status, sits between name and amount in head row. */
.budget-line__chip {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 99px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: lowercase;
    white-space: nowrap;
    flex-shrink: 0;
    margin-left: auto;      /* push to right side of head row, before __nums */
}
.budget-line__chip--ok {
    background: #f0fdf4;
    color: #16a34a;
}
.budget-line__chip--warn {
    background: #fffbeb;
    color: #b45309;
}
.budget-line__chip--over {
    background: #fef2f2;
    color: #dc2626;
}

/* Head row re-arranged to fit chip: name | chip | nums (right) */
.budget-line__head {
    flex-wrap: wrap;
    row-gap: 6px;
}
.budget-line__head .budget-line__name { flex: 1 1 auto; min-width: 0; }
.budget-line__head .budget-line__nums { flex: 0 0 auto; margin-left: 0; }
.budget-line__note {
    flex: 1;
    font-size: 12px;
    color: #64748b;
    font-style: italic;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.budget-line__edit {
    background: rgba(15, 23, 42, 0.05);
    border: none;
    width: 30px; height: 30px;
    border-radius: 50%;
    color: #475569;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.budget-line__edit:active { transform: scale(0.92); }
.budget-line__edit > i { font-size: 16px; }

/* ---- Empty state (upgraded Phase P §11 Round 3 — matches draft §7 line 1634) ---- */
.budget-empty,
.goal-empty {
    text-align: center;
    padding: 48px 24px;
    margin-bottom: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}
/* The icon <i> is styled as a 56px blue circle wrapper around itself —
   no HTML change needed. */
.budget-empty__icon,
.goal-empty__icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
    font-size: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 4px;
}
.budget-empty__title,
.goal-empty__title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary, #1e293b);
}
.budget-empty__body,
.goal-empty__body {
    margin: 0;
    max-width: 240px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-muted, #64748b);
}

/* ---- Add button ---- */
.budget-add-btn {
    width: 100%;
    height: 52px;
    border-radius: 14px;
    border: 1.5px dashed rgba(59, 130, 246, 0.4);
    background: rgba(59, 130, 246, 0.04);
    color: #2563eb;
    font-weight: 600;
    font-size: 15px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    cursor: pointer;
    font-family: inherit;
}

/* 🆕 v3.1.0 Phase P §11 — Header-right gradient pill matching draft §7
   Hi-Fi (height 36px, 16px padding, rounded 99px, blue→dark-blue gradient). */
.budget-header-add {
    height: 36px;
    padding: 0 14px;
    border: none;
    border-radius: 99px;
    background: var(--brand-gradient);
    color: #fff;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 3px 8px rgba(37, 99, 235, 0.25);
    transition: transform .12s ease, box-shadow .18s ease, filter .18s ease;
    white-space: nowrap;
}
.budget-header-add i { font-size: 16px; }
.budget-header-add:hover  { transform: translateY(-1px); box-shadow: 0 6px 14px rgba(37, 99, 235, 0.32); }
.budget-header-add:active { transform: translateY(0) scale(0.97); }

/* Mobile tiny-screen compaction — hide label, keep just "+" icon */
@media (max-width: 360px) {
    .budget-header-add span { display: none; }
    .budget-header-add {
        padding: 0;
        width: 36px;
        justify-content: center;
    }
}
.budget-add-btn:hover  { background: rgba(59, 130, 246, 0.10); }
.budget-add-btn:active { transform: scale(0.99); }
.budget-add-btn > i    { font-size: 22px; }

/* ============================================
 * Add/Edit bottom sheet
 *   The .budget-sheet* class set was removed June 14, 2026.
 *   Budget + Goal sheets now use .app-sheet--slide (see section 71).
 * ============================================ */

/* ---- Category picker (radio list) ---- */
.budget-cat-picker {
    max-height: 200px;
    overflow-y: auto;
    border-radius: 10px;
    border: 1px solid rgba(15, 23, 42, 0.10);
    background: rgba(15, 23, 42, 0.02);
}
.budget-cat-picker__loading,
.budget-cat-picker__empty {
    text-align: center;
    color: #94a3b8;
    font-size: 13px;
    padding: 16px;
    margin: 0;
}
.budget-cat-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
    cursor: pointer;
}
.budget-cat-item:last-child { border-bottom: none; }
.budget-cat-item input { accent-color: #3b82f6; }
.budget-cat-item span { font-size: 14px; color: #0f172a; }

body.sheet-open { overflow: hidden; }



/* ============================================
 * 61. ACCOUNTS PAGE — Search + view-first edit (June 14, 2026)
 * ============================================ */

/* ---- Search box ---- */
.acct-search {
    position: relative;
    margin: 0 0 12px;
}
.acct-search__icon {
    position: absolute;
    left: 12px; top: 50%;
    transform: translateY(-50%);
    color: #94a3b8;
    font-size: 20px;
    pointer-events: none;
}
.acct-search__input {
    width: 100%;
    height: 44px;
    padding: 0 40px 0 40px;
    border-radius: 12px;
    border: 1.5px solid rgba(15, 23, 42, 0.10);
    background: #fff;
    font-size: 15px;
    color: #0f172a;
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
}
.acct-search__input:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
}
.acct-search__input::-webkit-search-cancel-button { display: none; }
.acct-search__clear {
    position: absolute;
    right: 6px; top: 50%;
    transform: translateY(-50%);
    width: 30px; height: 30px;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.08);
    color: #475569;
    border: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.acct-search__clear > i { font-size: 18px; }

/* 🆕 v3.1.0 Phase AB account-form Round 1 — header Edit button:
   soft brand lift + hover intensify + icon rotate. */
.acct-edit-btn {
    margin-right: 6px;
    padding: 7px 16px;
    border-radius: 999px;
    border: 1.5px solid rgba(59, 130, 246, 0.4);
    background: rgba(59, 130, 246, 0.06);
    color: var(--brand-600, #2563eb);
    font-weight: 700;
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    font-family: inherit;
    box-shadow: 0 2px 6px -2px rgba(37, 99, 235, 0.14);
    transition: background .18s ease, box-shadow .18s ease,
                transform .08s ease, border-color .18s ease;
}
.acct-edit-btn:hover {
    background: rgba(37, 99, 235, 0.14);
    border-color: rgba(59, 130, 246, 0.6);
    box-shadow: 0 4px 10px -2px rgba(37, 99, 235, 0.22);
}
.acct-edit-btn:active { transform: scale(0.96); }
.acct-edit-btn > i { font-size: 16px; transition: transform .2s cubic-bezier(0.34, 1.56, 0.64, 1); }
.acct-edit-btn:hover > i { transform: rotate(-14deg) scale(1.1); }

/* ---- View-mode styling (read-only appearance) ---- */
.app-sheet.is-view-mode .tx-input,
.app-sheet.is-view-mode .tx-textarea {
    background: rgba(15, 23, 42, 0.03);
    color: #0f172a;
    border-color: rgba(15, 23, 42, 0.08);
    cursor: default;
}
.app-sheet.is-view-mode .tx-input:focus,
.app-sheet.is-view-mode .tx-textarea:focus {
    outline: none;
    box-shadow: none;
    border-color: rgba(15, 23, 42, 0.08);
}
.app-sheet.is-view-mode .segmented__option {
    opacity: 0.55;
}
.app-sheet.is-view-mode .segmented__option.is-active {
    opacity: 1;
}
.app-sheet.is-view-mode .acct-deactivate-btn,
.app-sheet.is-view-mode .acct-switch {
    opacity: 0.5;
    pointer-events: none;
}
.app-sheet.is-view-mode .tx-textarea__count {
    visibility: hidden;
}



/* ============================================
 * 62. ACCOUNT DESCRIPTION — justified text (June 14, 2026)
 *      Spread the wrapped lines edge-to-edge so the right margin
 *      isn't ragged. Scoped to the description textarea only.
 * ============================================ */
#acctDesc {
    text-align: justify;
    text-justify: inter-word;
    /* Slightly relax line-height so justification doesn't look cramped */
    line-height: 1.55;
    /* Hyphenation is OFF by default — turning it on can over-break Thai words.
       Uncomment if you want softer breaks for long English words:
    -webkit-hyphens: auto;
    hyphens: auto;
    */
}



/* ============================================
 * 63. ACCOUNT SHEET — Profile Card view + Compact edit (June 14, 2026)
 * ============================================ */

/* ----- View block — Profile Card ----- */
.acct-view {
    padding: 4px 2px 0;
}
.acct-view__name {
    margin: 4px 0 12px;
    font-size: 22px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.25;
    word-break: break-word;
}
.acct-view__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 18px;
}
/* 🆕 v3.1.0 Phase AB account-form Round 1 — meta chips: brand lift,
   subtle shadow, hover affordance (even though they're read-only). */
.acct-meta-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 12px;
    border-radius: 999px;
    background: var(--surface-2, #f1f5f9);
    color: var(--text-primary, #334155);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.01em;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
    transition: box-shadow .14s ease, transform .08s ease;
}
.acct-meta-chip:hover {
    box-shadow: 0 3px 8px -1px rgba(15, 23, 42, 0.10);
    transform: translateY(-1px);
}
.acct-meta-chip--id {
    font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
    color: #1e40af;
    background: rgba(59, 130, 246, 0.10);
    letter-spacing: 0.04em;
}
.acct-meta-chip--type {
    background: rgba(6, 182, 212, 0.10);
    color: #0e7490;
}
.acct-meta-chip--type .chip-emoji { font-size: 14px; }
.acct-meta-chip--status {
    background: rgba(34, 197, 94, 0.12);
    color: #15803d;
}
.acct-meta-chip--status.acct-meta-chip--inactive {
    background: rgba(15, 23, 42, 0.06);
    color: #64748b;
}
.status-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: #22c55e;
    display: inline-block;
}
.status-dot--on  { background: #22c55e; }
.status-dot--off { background: #94a3b8; }

.acct-view__divider {
    border: none;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    margin: 4px 0 16px;
}
.acct-view__about-label {
    margin: 0 0 6px;
    font-size: 11px;
    font-weight: 600;
    color: #64748b;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.acct-view__about {
    margin: 0;
    font-size: 14.5px;
    color: #1e293b;
    line-height: 1.6;
    text-align: justify;
    text-justify: inter-word;
    word-break: break-word;
}
.acct-view__about--empty {
    color: #94a3b8;
    font-style: italic;
    text-align: left;
}

/* ----- Edit block — tighter spacing + title-case labels ----- */
.acct-edit .tx-field {
    margin-bottom: 14px;            /* was ~20-24px */
}
.acct-edit .tx-field__label {
    font-size: 12px;
    font-weight: 600;
    color: #475569;
    text-transform: none;            /* was UPPERCASE — friendlier */
    letter-spacing: 0;
    margin-bottom: 6px;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}
.acct-edit .tx-field__hint {
    font-size: 11px;
    font-weight: 500;
    color: #94a3b8;
    text-transform: none;
}

/* Compact segmented type buttons */
.segmented--compact .segmented__option {
    min-height: 40px;                /* was 48-52px */
    padding: 4px 2px;
}
.segmented--compact .seg-emoji {
    font-size: 14px;
}
.segmented--compact .seg-label {
    font-size: 11px;
}

/* Inline ID strip (kept for future use) */
.acct-id-type-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0 12px;
    margin-bottom: 4px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
}
.acct-id-group {
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.acct-mini-label {
    font-size: 11px;
    font-weight: 600;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.acct-id-type-row .acct-id-readonly {
    font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
    font-size: 14px;
    font-weight: 700;
    color: #1e40af;
    letter-spacing: 0.04em;
}

/* Compact status row (inline toggle + deactivate button) */
.acct-edit .acct-active-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 12px;
    border-radius: 12px;
    background: rgba(15, 23, 42, 0.03);
}



/* ============================================
 * 64. ACCOUNT VIEW — 3 Stat Cards + Type Colors (June 14, 2026)
 *      Replaces the chip strip with a 3-column card grid.
 *      Type card is colour-coded; ID card is tappable to copy.
 * ============================================ */

/* ---- Grid ---- */
.acct-view__stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    margin: 4px 0 18px;
}

/* ---- Base stat card ----
   NOTE: consolidated June 2026 cleanup. This used to be 4 stacked
   sections (64: base column layout, 65: compact icon-left override,
   66: modern polish override, 67: indigo accent override) that each
   redeclared the same selectors. Merged into final cascade-resolved
   values here — same computed result, no dead/overridden rules. */
.acct-view__stats {
    gap: 8px;
    margin: 4px 0 14px;
}

.acct-stat {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-width: 0;                    /* allow truncation in flex/grid */
    min-height: 0;
    text-align: center;
    padding: 9px 6px;
    border-radius: 14px;
    background: rgba(15, 23, 42, 0.04);
    border: 1.5px solid rgba(15, 23, 42, 0.07);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
    transition: background 0.15s, transform 0.08s, box-shadow 0.15s;
}
@media (pointer: fine) {
    .acct-stat:hover { box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08); }
    .acct-stat--id:hover { transform: translateY(-1px); }
}
.acct-stat__icon {
    font-size: 16px;
    line-height: 1;
    margin-bottom: 0;
    height: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.acct-stat__value {
    font-size: 13px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.2;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Labels removed from HTML; rule kept hidden as a safety net */
.acct-stat__label {
    display: none;
    font-size: 10px;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}

/* ---- ID card: tappable, monospace value, indigo accent ---- */
.acct-stat--id {
    cursor: pointer;
    appearance: none;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
    background: rgba(99, 102, 241, 0.12);     /* indigo-500 at 12% */
    border-color: rgba(99, 102, 241, 0.30);   /* indigo-500 at 30% */
}
.acct-stat--id:active {
    transform: scale(0.96);
    background: rgba(99, 102, 241, 0.20) !important;
}
.acct-stat--id .acct-stat__value {
    font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
    font-size: 15px;
    font-weight: 800;
    color: #4338ca;                            /* indigo-700 — strong contrast */
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums lining-nums;
}
.acct-stat--id .acct-stat__icon {
    color: #6366f1;                            /* indigo-500 — softer */
    font-weight: 700;
    font-size: 15px;
    opacity: 0.95;
}
/* "Copied!" flash */
.acct-stat--copied {
    background: rgba(34, 197, 94, 0.22) !important;
    border-color: rgba(34, 197, 94, 0.55) !important;
    transform: scale(1.02);
}

/* ---- Status card ---- */
.acct-stat--status:not(.acct-stat--inactive) {
    background: rgba(34, 197, 94, 0.14);
    border-color: rgba(34, 197, 94, 0.30);
}
.acct-stat--status:not(.acct-stat--inactive) .acct-stat__value {
    color: #15803d;
    font-weight: 700;
}

/* Pulse animation — concentric ring expanding from the dot */
.acct-stat__icon--active {
    position: relative;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #22c55e;
    color: transparent;             /* hide the ● character; the bg IS the dot */
    font-size: 0;
    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55);
    animation: acctStatusPulse 2.2s ease-out infinite;
}
.acct-stat__icon--inactive {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #94a3b8;
    color: transparent;
    font-size: 0;
}

@keyframes acctStatusPulse {
    0%   { box-shadow: 0 0 0 0   rgba(34, 197, 94, 0.55); }
    70%  { box-shadow: 0 0 0 10px rgba(34, 197, 94, 0); }
    100% { box-shadow: 0 0 0 0   rgba(34, 197, 94, 0); }
}
/* Respect Reduced Motion — disable pulse for users who opt out */
@media (prefers-reduced-motion: reduce) {
    .acct-stat__icon--active { animation: none; }
}

/* ---- Per-type colour variants (applied to .acct-stat--type) ---- */
.acct-type-asset {
    background: rgba(59, 130, 246, 0.14);
    border-color: rgba(59, 130, 246, 0.30);
}
.acct-type-asset .acct-stat__value { color: #1e40af; }

.acct-type-liab {
    background: rgba(249, 115, 22, 0.14);
    border-color: rgba(249, 115, 22, 0.30);
}
.acct-type-liab .acct-stat__value { color: #c2410c; }

.acct-type-equity {
    background: rgba(168, 85, 247, 0.14);
    border-color: rgba(168, 85, 247, 0.30);
}
.acct-type-equity .acct-stat__value { color: #7e22ce; }

.acct-type-revenue {
    background: rgba(34, 197, 94, 0.14);
    border-color: rgba(34, 197, 94, 0.30);
}
.acct-type-revenue .acct-stat__value { color: #15803d; }

.acct-type-expense {
    background: rgba(239, 68, 68, 0.14);
    border-color: rgba(239, 68, 68, 0.30);
}
.acct-type-expense .acct-stat__value { color: #b91c1c; }

/* Type card text — bolder + same colour */
.acct-stat--type .acct-stat__value { font-weight: 700; }



/* ============================================
 * 68. DESCRIPTION TEXT — Left-align + pretty wrap (June 14, 2026)
 *      Override the earlier justified rules (sections 62 + 63).
 *      Justify on narrow mobile widths produced ugly word-spacing gaps;
 *      left-align with text-wrap:pretty gives natural reading + balanced
 *      line lengths in supporting browsers (Safari 17.4+, Chrome 117+).
 * ============================================ */

/* View-mode "About" paragraph */
.acct-view__about {
    text-align: left;
    text-justify: auto;
    text-wrap: pretty;            /* progressive enhancement */
    hyphens: none;                /* don't break Thai words */
    word-break: normal;
    overflow-wrap: break-word;    /* still wrap unbreakable long tokens */
}

/* Edit-mode description textarea */
#acctDesc {
    text-align: left;
    text-justify: auto;
}


/* ============================================
 * 69. GOALS UI — Budget Tab 2 (June 14, 2026)
 *      Earmark-model goals: cards with progress bars,
 *      per-account breakdown, add/edit sheet, icon picker.
 *      Designed to feel native + modern next to Spending tab.
 * ============================================ */

/* ---------- Goals empty state ---------- */
.goal-empty {
    text-align: center;
    padding: 32px 16px;
    color: var(--text-muted, #6b7280);
}
.goal-empty__icon {
    font-size: 44px;
    color: var(--accent, #3b82f6);
    opacity: 0.55;
    margin-bottom: 8px;
}
.goal-empty__title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text, #111827);
    margin: 0 0 4px;
}
.goal-empty__sub {
    font-size: 13px;
    line-height: 1.45;
    margin: 0;
}

/* ---------- Goals list ---------- */
.goal-list {
    list-style: none;
    margin: 0 0 16px;           /* breathing room before next section (breakdown or button) */
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.goal-list:empty { margin-bottom: 0; }
.goal-card {
    background: var(--card, #fff);
    border: 1px solid var(--card-border, rgba(0, 0, 0, 0.06));
    border-radius: 14px;
    padding: 14px 14px 12px;
    position: relative;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.goal-card:active {
    transform: scale(0.995);
}
.goal-card__head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
}
.goal-card__icon {
    width: 38px;
    height: 38px;
    border-radius: 11px;
    display: grid;
    place-items: center;
    background: color-mix(in srgb, var(--goal-color, #3b82f6) 14%, transparent);
    color: var(--goal-color, #3b82f6);
    font-size: 20px;
    flex-shrink: 0;
}

/* 🆕 v3.1.0 Phase P §11 Round 2 — progress ring around goal icon per draft §7 Hi-Fi.
   Uses conic-gradient + radial-gradient mask to make a hollow ring.
   --ring-pct comes from inline style on parent .goal-card. */
.goal-ring {
    position: relative;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    background:
        conic-gradient(
            var(--goal-color, #2563eb)   0 calc(var(--ring-pct, 0) * 1%),
            rgba(37, 99, 235, 0.12)     calc(var(--ring-pct, 0) * 1%) 100%
        );
    transition: background .3s ease;
}
/* Hollow out the center so only the ring shows (icon tile sits inside) */
.goal-ring::before {
    content: '';
    position: absolute;
    inset: 5px;
    border-radius: 50%;
    background: var(--surface-1, #fff);
}
.goal-ring .goal-card__icon {
    position: relative;
    z-index: 1;
    width: 38px;
    height: 38px;
    border-radius: 10px;
}
/* Status color override for the ring arc (behind, way_behind) */
.goal-card--behind       .goal-ring { background: conic-gradient(#f59e0b 0 calc(var(--ring-pct, 0) * 1%), rgba(245, 158, 11, 0.12) calc(var(--ring-pct, 0) * 1%) 100%); }
.goal-card--way_behind   .goal-ring { background: conic-gradient(#dc2626 0 calc(var(--ring-pct, 0) * 1%), rgba(220, 38, 38, 0.12) calc(var(--ring-pct, 0) * 1%) 100%); }
.goal-card--on_track     .goal-ring { background: conic-gradient(#2563eb 0 calc(var(--ring-pct, 0) * 1%), rgba(37, 99, 235, 0.12) calc(var(--ring-pct, 0) * 1%) 100%); }
.goal-card--completed    .goal-ring { background: conic-gradient(#059669 0 100%, rgba(5, 150, 105, 0.12) 100% 100%); }
.goal-card__title-wrap { flex: 1; min-width: 0; }
.goal-card__title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text, #111827);
    margin: 0;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.goal-card__sub {
    font-size: 12px;
    color: var(--text-muted, #6b7280);
    margin: 2px 0 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* 🆕 Creation date line (and completed_at on archived). Subtle, slightly
   smaller than sub line, with calendar icon inline. */
.goal-card__meta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: #94a3b8;
    margin: 3px 0 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 500;
}
.goal-card__meta i {
    font-size: 13px;
    color: #94a3b8;
    line-height: 1;
}
.goal-card--archive .goal-card__meta { color: #cbd5e1; }
.goal-card--archive .goal-card__meta i { color: #cbd5e1; }
.goal-card__edit {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--text-muted, #6b7280);
    font-size: 18px;
    padding: 6px;
    cursor: pointer;
    border-radius: 8px;
    transition: background 0.15s ease, color 0.15s ease;
}
.goal-card__edit:active {
    background: rgba(0, 0, 0, 0.05);
    color: var(--text, #111827);
}
.goal-card__nums {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 6px;
    font-variant-numeric: tabular-nums;
}
.goal-card__current {
    font-size: 16px;
    font-weight: 700;
    color: var(--text, #111827);
}
.goal-card__sep {
    color: var(--text-muted, #9ca3af);
    font-weight: 400;
}
.goal-card__target {
    font-size: 13px;
    color: var(--text-muted, #6b7280);
}
.goal-card__pct {
    margin-left: auto;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted, #6b7280);
}
.goal-bar {
    width: 100%;
    height: 6px;
    background: rgba(0, 0, 0, 0.06);
    border-radius: 999px;
    overflow: hidden;
}
.goal-bar__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    background: var(--goal-color, #3b82f6);
}
.goal-bar__fill--on_track   { background: #10b981; }
.goal-bar__fill--no_deadline{ background: #6366f1; }
.goal-bar__fill--behind     { background: #f59e0b; }
.goal-bar__fill--way_behind { background: #ef4444; }
.goal-bar__fill--completed  { background: #16a34a; }

.goal-card--completed { background: linear-gradient(180deg, #ecfdf5 0%, #fff 100%); }

/* 🆕 Phase A — SHORT modifier (earmark > account balance after spending) */
.goal-card--short {
    border-left: 4px solid #f59e0b;
    background: linear-gradient(180deg, rgba(245, 158, 11, 0.06) 0%, #fff 100%);
}
.goal-card__short {
    margin: 10px 0 0;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.30);
    color: #78350f;
    font-size: 12.5px;
    line-height: 1.45;
    display: flex;
    gap: 8px;
    align-items: flex-start;
}
.goal-card__short i {
    color: #b45309;
    font-size: 16px;
    flex-shrink: 0;
    margin-top: 1px;
}
.goal-card__short strong { color: #92400e; }

.goal-card__tip {
    margin: 8px 0 0;
    font-size: 12px;
    color: var(--text-muted, #6b7280);
    line-height: 1.4;
}

/* ---- Way-behind warning button (replaces the old ::after ⚠ marker) ---- */
.goal-warn-btn {
    appearance: none;
    border: none;
    background: rgba(239, 68, 68, 0.12);
    color: #dc2626;
    width: 22px; height: 22px;
    border-radius: 50%;
    margin-left: 6px;
    padding: 0;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    vertical-align: -3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, transform 0.15s ease;
}
.goal-warn-btn:active { transform: scale(0.92); }
.goal-warn-btn:hover  { background: rgba(239, 68, 68, 0.20); }
.goal-warn-btn[aria-expanded="true"] { background: #dc2626; color: #fff; }

/* Explanation block — collapsed by default, expands when ⚠ tapped */
.goal-warn-tip {
    margin-top: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.18);
    color: #b91c1c;
    font-size: 12.5px;
    line-height: 1.5;
    animation: goalWarnFadeIn 0.18s ease;
}
.goal-warn-tip strong { color: #991b1b; }
@keyframes goalWarnFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Per-account earmark breakdown ----------
   The HTML uses .goal-breakdown (section) + .goal-breakdown__title (h3),
   then a list of .goal-break cards — one per account. */

.goal-breakdown {
    margin-top: 28px;
    margin-bottom: 24px;        /* gap before "New goal" button (matches Spending pattern) */
    padding-top: 18px;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
}
.goal-breakdown__title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px;
    padding: 0 2px;
    font-size: 14px;
    font-weight: 700;
    color: #475569;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.goal-breakdown__title i {
    font-size: 18px;
    color: var(--accent, #3b82f6);
}

/* Each account = its own card */
.goal-break {
    background: var(--card, #fff);
    border: 1px solid rgba(15, 23, 42, 0.06);
    border-radius: 14px;
    padding: 14px 16px;
    margin-bottom: 12px;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
}
.goal-break:last-child { margin-bottom: 0; }

/* Account header (name + total balance) */
.goal-break__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px dashed rgba(15, 23, 42, 0.10);
}
.goal-break__name {
    font-size: 14px;
    font-weight: 700;
    color: #0f172a;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
}
.goal-break__bal {
    font-size: 14px;
    color: var(--accent, #3b82f6);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    flex: none;
}

/* Goal rows under each account */
.goal-break__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.goal-break__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    padding: 5px 0;
    color: var(--text, #111827);
    font-variant-numeric: tabular-nums;
}
.goal-break__row > span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.goal-break__row > strong { flex: none; font-weight: 600; }
.goal-break__row i { font-size: 14px; margin-right: 6px; vertical-align: -1px; }

/* "Unallocated" row — visually distinct, separated */
.goal-break__row--free {
    color: #6b7280;
    font-style: italic;
    border-top: 1px dashed rgba(15, 23, 42, 0.08);
    padding-top: 8px;
    margin-top: 4px;
}

/* 🆕 Phase A — Account-level over-commit styles */
.goal-break--short {
    border-color: rgba(245, 158, 11, 0.40);
    box-shadow: 0 1px 3px rgba(245, 158, 11, 0.10);
}
.goal-break--short .goal-break__bal {
    color: #dc2626;
}
/* Total shortage row at the bottom of an over-committed account */
.goal-break__row--short {
    color: #b45309;
    font-weight: 700;
    border-top: 1px solid rgba(245, 158, 11, 0.30);
    padding-top: 8px;
    margin-top: 4px;
}
.goal-break__row--short i {
    color: #b45309;
    font-size: 15px;
}
.goal-break__row--short strong { color: #b91c1c; }

/* Individual goal that's short on an over-committed account */
.goal-break__row--goal-short {
    background: rgba(245, 158, 11, 0.06);
    border-radius: 6px;
    padding: 5px 8px;
    margin: 0 -8px;
}
.goal-break__short-pill {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: rgba(239, 68, 68, 0.12);
    color: #b91c1c;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    vertical-align: 1px;
}

/* ---------- Add Goal floating button ---------- */
.goal-add-btn {
    position: fixed;
    right: 16px;
    bottom: calc(80px + env(safe-area-inset-bottom));
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--accent, #3b82f6);
    color: #fff;
    border: none;
    box-shadow: 0 6px 16px rgba(59, 130, 246, 0.35);
    font-size: 24px;
    display: grid;
    place-items: center;
    z-index: 30;
    cursor: pointer;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.goal-add-btn:active {
    transform: scale(0.94);
    box-shadow: 0 3px 10px rgba(59, 130, 246, 0.4);
}

/* ---------- Goal sheet form ---------- */
.goal-icon-picker {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
    margin: 4px 0 10px;
}
.goal-icon-opt {
    appearance: none;
    border: 1.5px solid rgba(0, 0, 0, 0.08);
    background: #fff;
    border-radius: 10px;
    aspect-ratio: 1;
    display: grid;
    place-items: center;
    font-size: 20px;
    color: var(--text-muted, #6b7280);
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.goal-icon-opt:active { transform: scale(0.92); }
.goal-icon-opt.is-active {
    border-color: var(--accent, #3b82f6);
    background: rgba(59, 130, 246, 0.08);
    color: var(--accent, #3b82f6);
}

.goal-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.goal-grid-2 .field { margin: 0; }

.goal-account-hint,
.goal-monthly-hint {
    display: block;
    margin-top: 4px;
    font-size: 11.5px;
    color: var(--text-muted, #6b7280);
    line-height: 1.4;
}

/* 🆕 UNIFIED with .pw-btn--danger — solid red gradient (was outlined). */
.goal-delete-btn {
    appearance: none;
    width: 100%;
    margin-top: 12px;
    padding: 0 20px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    color: #fff;
    border: none;
    border-radius: 12px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(220, 38, 38, 0.32);
    transition: box-shadow 0.18s ease, transform 0.12s ease, filter 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}
.goal-delete-btn:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(220, 38, 38, 0.44);
    filter: brightness(1.04);
}
.goal-delete-btn:active:not(:disabled) {
    transform: scale(0.98);
}
.goal-delete-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}
.goal-delete-btn i { color: #fff; font-size: 17px; }

.goal-sheet-error {
    background: rgba(239, 68, 68, 0.08);
    color: #b91c1c;
    border: 1px solid rgba(239, 68, 68, 0.25);
    padding: 8px 12px;
    border-radius: 8px;
    font-size: 13px;
    margin: 0 0 10px;
}


/* ============================================
 * 71. APP-SHEET — Unified bottom-sheet system  (June 14, 2026)
 *
 *   The single source of truth for all modal sheets in the app.
 *   Replaces .bottom-sheet (dark, fullscreen) and .budget-sheet
 *   (white, slide-up) — both will be removed in Phase 4.
 *
 *   Structure:
 *     <div class="app-sheet app-sheet--<variant>">
 *       <div class="app-sheet__backdrop"></div>
 *       <div class="app-sheet__panel">
 *         <div class="app-sheet__handle"></div>          (mobile-hidden)
 *         <header class="app-sheet__header">
 *           <div class="app-sheet__header-text">
 *             <h2 class="app-sheet__title">…</h2>
 *             <p  class="app-sheet__subtitle">…</p>
 *           </div>
 *           <button class="app-sheet__close">×</button>
 *         </header>
 *         <div class="app-sheet__content">
 *           <div class="app-sheet__body">… fields …</div>
 *           <div class="app-sheet__error">…</div>
 *         </div>
 *         <footer class="app-sheet__footer">
 *           <button>Cancel</button> <button>Save</button>
 *         </footer>
 *       </div>
 *     </div>
 *
 *   Variants:
 *     --slide  : Light card, fullscreen on mobile, centered on desktop
 *                (Budget, Goal, future light-themed forms)
 *     --full   : Dark navy fullscreen
 *                (Add Transaction, Edit Account, multi-step flows)
 *     --compact: Bottom slide-up that hugs content height (popups,
 *                confirm dialogs — not used yet, reserved)
 * ============================================ */

/* ---------- Root ---------- */
.app-sheet {
    position: fixed; inset: 0;
    z-index: var(--z-sheet, 1200);
    pointer-events: none;
    /* No visibility toggle — the panel hides itself via transform:translateY(100%).
       Using visibility here caused the sheet to stay invisible on certain mobile
       browsers even after .is-open was added. */
}
.app-sheet.is-open {
    pointer-events: auto;
}

/* ---------- Backdrop ---------- */
.app-sheet__backdrop {
    position: absolute; inset: 0;
    background: rgba(15, 23, 42, 0.55);
    opacity: 0;
    transition: opacity 0.18s ease;
}
.app-sheet.is-open .app-sheet__backdrop { opacity: 1; }

/* ---------- Panel (shared base) ---------- */
.app-sheet__panel {
    position: absolute;
    background: #fff;
    display: flex;
    flex-direction: column;
    transform: translateY(100%);
    transition: transform 0.22s cubic-bezier(.2, .7, .2, 1);
    overflow: hidden;
    box-shadow: 0 -8px 32px rgba(15, 23, 42, 0.15);
}
.app-sheet.is-open .app-sheet__panel { transform: translateY(0); }

/* ---------- Drag handle ---------- */
.app-sheet__handle {
    flex: none;
    width: 44px; height: 5px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.18);
    margin: 8px auto 4px;
    align-self: center;
}

/* ---------- Header ---------- */
.app-sheet__header {
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 22px 14px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
    background: inherit;
    position: relative;
    z-index: 2;
}
.app-sheet__header-text { flex: 1; min-width: 0; }
.app-sheet__title {
    margin: 2px 0;
    font-size: 18px;
    font-weight: 700;
    color: #0f172a;
}
.app-sheet__subtitle {
    margin: 0;
    font-size: 13px;
    color: #64748b;
}
.app-sheet__close,
.app-sheet__back {
    flex: none;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    border: none;
    color: #475569;
    font-size: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.app-sheet__close:hover,
.app-sheet__back:hover  { background: rgba(15, 23, 42, 0.10); }
.app-sheet__close:active,
.app-sheet__back:active { background: rgba(15, 23, 42, 0.14); transform: scale(0.92); }

/* ---------- Scrollable content ---------- */
.app-sheet__content {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 16px 22px 12px;
}

/* ---------- Form helpers (used inside __content) ---------- */
.app-sheet__field { margin-bottom: 14px; }
.app-sheet__label {
    display: block;
    margin-bottom: 6px;
    font-size: 12px;
    font-weight: 600;
    color: #475569;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.app-sheet__hint {
    margin-left: 6px;
    font-size: 11px;
    font-weight: 500;
    color: #94a3b8;
    text-transform: none;
    letter-spacing: 0;
}
.app-sheet__input {
    width: 100%;
    height: 46px;
    padding: 0 14px;
    border-radius: 10px;
    border: 1.5px solid rgba(15, 23, 42, 0.14);
    background: #fff;
    font-size: 16px;
    color: #0f172a;
    font-family: inherit;
    /* 🐛 BUG-FIX: without box-sizing, width:100% + 28px horizontal padding
       overflows the parent by 28px. Most visible on <input type="date">
       (Target Date) because its native formatted display + calendar icon
       have a fixed intrinsic width that doesn't shrink. */
    box-sizing: border-box;
}

/* 🆕 Same fix for textarea variant (Goal note, Account description, etc.) */
textarea.app-sheet__input {
    box-sizing: border-box;
    height: auto;
    min-height: 80px;
    padding: 12px 14px;
    line-height: 1.4;
    resize: vertical;
}

/* 🆕 <input type="date"> in app-sheet — make the native rendering behave:
   left-align text, hide the native calendar-icon indicator (our custom
   calendar-grid date picker opens on focus instead), and keep box-sizing
   so the input doesn't expand beyond its container. */
input[type="date"].app-sheet__input {
    appearance: none;
    -webkit-appearance: none;
    text-align: left;
    line-height: 46px;
    box-sizing: border-box;
    /* Hide iOS spinner overlap if the date display tries to expand */
    overflow: hidden;
}
input[type="date"].app-sheet__input::-webkit-calendar-picker-indicator {
    /* Hidden — our custom picker handles input/click. The icon would only
       open the native popover which we already suppress via JS. */
    display: none;
    -webkit-appearance: none;
}
input[type="date"].app-sheet__input::-webkit-date-and-time-value {
    text-align: left;
    font-family: inherit;
    font-size: inherit;
    line-height: 46px;
}
.app-sheet__input:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
.app-sheet__error {
    margin: 8px 0 0;
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(239, 68, 68, 0.10);
    color: #be123c;
    font-size: 13px;
    font-weight: 500;
}

/* ---------- Footer ---------- */
.app-sheet__footer {
    flex: none;
    display: flex;
    gap: 10px;
    padding: 12px 22px calc(16px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(15, 23, 42, 0.06);
    background: inherit;
    box-shadow: 0 -4px 12px rgba(15, 23, 42, 0.04);
    position: relative;
    z-index: 2;
}
.app-sheet__footer > .pw-btn,
.app-sheet__footer > button { flex: 1; }


/* ============================================================
 *   VARIANT: --slide  (light card, fullscreen mobile, centered desktop)
 * ============================================================ */
.app-sheet--slide .app-sheet__panel {
    left: 0; right: 0; bottom: 0;
    background: #fff;
    border-radius: 0;
    height: 100vh;
    height: 100dvh;
    max-height: 100dvh;
    padding-top: env(safe-area-inset-top, 0px);
}

@media (max-width: 767px) {
    .app-sheet--slide .app-sheet__handle { display: none; }
}

@media (min-width: 768px) {
    .app-sheet--slide .app-sheet__panel {
        left: 50%;
        right: auto;
        transform: translate(-50%, 100%);
        width: 100%;
        max-width: 560px;
        height: min(90vh, 800px);
        max-height: 90vh;
        border-radius: 24px 24px 0 0;
        padding-top: 0;
    }
    .app-sheet--slide.is-open .app-sheet__panel { transform: translate(-50%, 0); }
}


/* ============================================================
 *   VARIANT: --full  (dark navy fullscreen — Transaction / Account)
 * ============================================================ */
.app-sheet--full .app-sheet__panel {
    inset: 0;
    background: #0f172a;
    color: #fff;
    border-radius: 0;
    height: auto;
    max-height: none;
    padding-top: env(safe-area-inset-top, 0px);
    /* 🐛 BUG-FIX: removed `padding-bottom: env(safe-area-inset-bottom)` here.
       The footer (.tx-screen__footer / .app-sheet__footer) already pads its
       own safe-area-inset-bottom. Adding the same to the panel created a
       DOUBLE pad — footer floated ~34px above the home-indicator on iPhone.
       Compare to .app-sheet--slide (Budget) which never had panel pad-bottom
       and looks correct. The mobile footer keeps the safe-area pad; desktop
       (≥768px) variant below keeps it on the panel since the desktop footer
       has no safe-area pad and panel-bottom flush to the rounded card edge. */
}
.app-sheet--full .app-sheet__title    { color: #fff; }
.app-sheet--full .app-sheet__subtitle { color: rgba(255, 255, 255, 0.65); }
.app-sheet--full .app-sheet__header   { border-bottom-color: rgba(255, 255, 255, 0.08); }
.app-sheet--full .app-sheet__footer   { border-top-color: rgba(255, 255, 255, 0.08); background: rgba(15, 23, 42, 0.95); }
.app-sheet--full .app-sheet__close,
.app-sheet--full .app-sheet__back {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.85);
}
.app-sheet--full .app-sheet__close:active,
.app-sheet--full .app-sheet__back:active { background: rgba(255, 255, 255, 0.16); }

@media (max-width: 767px) {
    .app-sheet--full .app-sheet__handle { display: none; }
}

@media (min-width: 768px) {
    .app-sheet--full .app-sheet__panel {
        inset: auto;
        bottom: 0;
        left: 50%;
        right: auto;
        transform: translate(-50%, 100%);
        width: 100%;
        max-width: 560px;
        height: min(90vh, 800px);
        max-height: 90vh;
        border-radius: var(--r-2xl, 20px) var(--r-2xl, 20px) 0 0;
        padding-top: 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        box-shadow:
            0 24px 48px -12px rgba(15, 23, 42, 0.28),
            0 8px 16px -4px  rgba(15, 23, 42, 0.12);
    }
    .app-sheet--full.is-open .app-sheet__panel { transform: translate(-50%, -2vh); }
}


/* ============================================================
 *   KEYBOARD-AWARE PANEL POSITIONING
 *   When the virtual keyboard (NumPad or VKB) is open, lift the panel
 *   above it. --kb-h is published by numpad.js / text-keyboard.js.
 * ============================================================ */
body.vkb-open    .app-sheet--slide .app-sheet__panel,
body.numpad-open .app-sheet--slide .app-sheet__panel {
    top: 0;
    bottom: var(--kb-h, 300px);
    height: auto;
    max-height: none;
    border-radius: 0;
    padding-top: env(safe-area-inset-top, 0px);
}
body.vkb-open    .app-sheet--full .app-sheet__panel,
body.numpad-open .app-sheet--full .app-sheet__panel {
    top: 0;
    bottom: var(--kb-h, 300px);
    height: auto;
    max-height: none;
}

/* Focus mode — hide footers + dim non-active fields when keyboard is open.
   !important needed because the Edit Transaction footer adds `.is-split`
   class with its own `display: flex`, which has equal specificity. */
body.vkb-open    .app-sheet__footer,
body.numpad-open .app-sheet__footer,
body.vkb-open    .tx-screen__footer,
body.numpad-open .tx-screen__footer,
body.vkb-open    .flt-footer,
body.numpad-open .flt-footer {
    display: none !important;
}
body.vkb-open    .app-sheet__field:not(.is-kb-active),
body.numpad-open .app-sheet__field:not(.is-kb-active),
body.vkb-open    .tx-field:not(.is-kb-active),
body.numpad-open .tx-field:not(.is-kb-active),
body.vkb-open    .tx-amount-wrap:not(.is-kb-active),
body.numpad-open .tx-amount-wrap:not(.is-kb-active),
body.vkb-open    .flt-section:not(.is-kb-active),
body.numpad-open .flt-section:not(.is-kb-active),
body.vkb-open    .flt-field:not(.is-kb-active),
body.numpad-open .flt-field:not(.is-kb-active) {
    opacity: 0.45;
    transition: opacity 0.18s ease;
}
.is-kb-active.app-sheet__input,
.is-kb-active.tx-input,
.is-kb-active.tx-amount-input,
.is-kb-active.tx-search__input,
.is-kb-active.tx-textarea {
    border-color: #3b82f6;
    box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.18);
    background: #fff;
}


/* ============================================
 * 73. EDIT TX — Mode switch button
 *      Toggle between Simple <-> Custom while editing.
 *      Hidden during new-transaction flow.
 * ============================================ */
.tx-edit-mode-switch {
    appearance: none;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin: 10px 0 14px;
    padding: 10px 14px;
    border: 1.5px dashed rgba(59, 130, 246, 0.35);
    background: rgba(59, 130, 246, 0.05);
    border-radius: 12px;
    color: #2563eb;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.12s ease, border-color 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.tx-edit-mode-switch:hover    { background: rgba(59, 130, 246, 0.10); }
.tx-edit-mode-switch:active   { transform: scale(0.99); }
.tx-edit-mode-switch:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    border-style: solid;
}
.tx-edit-mode-switch > span    { flex: 1; text-align: left; }
.tx-edit-mode-switch > i:first-child { font-size: 16px; }
.tx-edit-mode-switch > i:last-child  { font-size: 18px; }

.tx-edit-mode-switch--back {
    border-color: rgba(16, 185, 129, 0.40);
    background: rgba(16, 185, 129, 0.05);
    color: #059669;
}
.tx-edit-mode-switch--back:hover { background: rgba(16, 185, 129, 0.10); }


/* ============================================
 * 72. REPORTS — Balance Sheet + Ratios tabs (June 15, 2026)
 *      Sub-tab navigation + Balance Sheet cards + ratio gauges
 * ============================================ */

/* ---------- Sub-tabs (Flow / Balance / Ratios) ---------- */
.report-tabs {
    display: flex;
    gap: 6px;
    width: 100%;
    margin: 0 0 18px;
    padding: 5px;
    background: rgba(15, 23, 42, 0.06);
    border-radius: 14px;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.03);
}
.report-tabs__btn {
    flex: 1 1 0;
    min-width: 0;
    appearance: none;
    border: none;
    background: transparent;
    padding: 10px 8px;
    border-radius: 10px;
    color: #64748b;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
}
.report-tabs__btn i {
    font-size: 17px;
    line-height: 1;
}
.report-tabs__btn:hover {
    color: #334155;
}
.report-tabs__btn:active {
    transform: scale(0.97);
}
.report-tabs__btn.is-active {
    background: #fff;
    color: #2563eb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.10),
                0 2px 6px rgba(37, 99, 235, 0.08);
}
.report-tabs__btn.is-active i {
    color: #2563eb;
}

/* Pane visibility */
.report-pane         { display: none; }
.report-pane.is-active { display: block; }


/* ---------- Balance Sheet — headline ---------- */
/* 🆕 v3.1.0 Phase R Round 6 — hero shadow uplifted to match the Net Worth
   card on Dashboard. Same brand-blue tilt + deeper vertical lift. */
.bs-headline {
    text-align: center;
    padding: 22px 16px;
    margin-bottom: 16px;
    background: var(--brand-gradient-hero);
    border-radius: 16px;
    color: #fff;
    box-shadow: 0 6px 20px -4px rgba(37, 99, 235, 0.35),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}
.bs-headline__label {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.10em;
    opacity: 0.85;
}
.bs-headline__value {
    margin: 6px 0 4px;
    font-size: 28px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.bs-headline__value.is-negative { color: #fecaca; }
.bs-headline__caption {
    margin: 0;
    font-size: 12px;
    opacity: 0.80;
}

/* ---------- Balance Sheet — Asset / Liability summary cards ---------- */
.bs-summary {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 18px;
}
/* 🆕 v3.1.0 Phase R Round 6 — flat border card, no lift (same hierarchy
   trick as .dashboard-stats__card). Keeps the bs-headline above as the
   clear hero; summary pair reads as subordinate. */
.bs-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px;
    border-radius: 14px;
    background: #fff;
    border: 1px solid var(--border-soft, #eef1f5);
    box-shadow: none;
}
.bs-card__icon {
    width: 38px; height: 38px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-size: 22px;
    flex-shrink: 0;
}
.bs-card--asset .bs-card__icon { background: rgba(16, 185, 129, 0.14); color: #059669; }
.bs-card--liab  .bs-card__icon { background: rgba(239, 68, 68, 0.14); color: #dc2626; }
.bs-card__body { min-width: 0; }
.bs-card__label {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    color: #64748b;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.bs-card__value {
    margin: 2px 0 0;
    font-size: 15px;
    font-weight: 700;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* On narrow screens, stack the summary cards vertically */
@media (max-width: 360px) {
    .bs-summary { grid-template-columns: 1fr; }
}


/* ---------- Ratios — gauge cards ---------- */
.ratio-list {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.ratio-card {
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.06);
    border-radius: 14px;
    padding: 14px;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
    transition: border-color 0.18s ease;
}
.ratio-card--healthy  { border-left: 4px solid #10b981; }
.ratio-card--warning  { border-left: 4px solid #f59e0b; }
.ratio-card--critical { border-left: 4px solid #ef4444; }

.ratio-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
}
.ratio-card__label {
    font-size: 13px;
    font-weight: 700;
    color: #0f172a;
    letter-spacing: 0.02em;
}
.ratio-card__badge {
    flex-shrink: 0;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.ratio-card--healthy  .ratio-card__badge { background: rgba(16, 185, 129, 0.14); color: #059669; }
.ratio-card--warning  .ratio-card__badge { background: rgba(245, 158, 11, 0.16); color: #b45309; }
.ratio-card--critical .ratio-card__badge { background: rgba(239, 68, 68, 0.14); color: #dc2626; }

.ratio-card__value {
    margin: 4px 0 6px;
    font-size: 26px;
    font-weight: 800;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.ratio-card__caption {
    margin: 0 0 10px;
    font-size: 12px;
    color: #64748b;
    line-height: 1.4;
}
.ratio-card__bar {
    width: 100%;
    height: 6px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.06);
    overflow: hidden;
}
.ratio-card__bar-fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.ratio-card--healthy  .ratio-card__bar-fill { background: #10b981; }
.ratio-card--warning  .ratio-card__bar-fill { background: #f59e0b; }
.ratio-card--critical .ratio-card__bar-fill { background: #ef4444; }

/* Context — 6-month average panel */
.ratio-context {
    background: rgba(15, 23, 42, 0.03);
    border-radius: 14px;
    padding: 14px;
}
.ratio-context__title {
    margin: 0 0 10px;
    font-size: 11px;
    font-weight: 700;
    color: #64748b;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.ratio-context__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}
.ratio-context__grid > div {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ratio-context__lbl {
    font-size: 11px;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}
.ratio-context__grid strong {
    font-size: 14px;
    font-weight: 700;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
}
/* Cleanup: duplicate @media (min-width 768px) block for .app-sheet--full
   was here, plus an orphaned comment-close fragment. The canonical rule
   lives in section 71 (around line 8548). */


/* ============================================
 * 74. ACCOUNT HEALTH (June 16, 2026)
 *      Dashboard badge + /health.php page styling.
 * ============================================ */

/* ---------- Dashboard badge — Option A + C combo ----------
   Pattern: wrapper span guarantees positioning context.
            Icon swaps per status (outline → filled → filled-with-X).

   Layout: <a.health-badge> outer hit area (40x40 round, matches profile).
           <span.health-badge__inner> ← THIS is position:relative.
             <i> shield icon (swappable bx-class)
             <span.health-badge__count> top-right count chip
*/
.health-badge {
    flex: none;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
    text-decoration: none;
    transition: background 0.15s ease, transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}
.health-badge:active { transform: scale(0.92); }

/* Status colors — also swap icon via JS (bx-shield → bxs-shield → bxs-shield-x) */
.health-badge--warning  { color: #b45309; background: rgba(245, 158, 11, 0.14); }
.health-badge--critical { color: #dc2626; background: rgba(239, 68, 68, 0.14); animation: hbPulse 2s ease-in-out infinite; }
@keyframes hbPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.35); }
    50%      { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
}

/* INNER SPAN — bullet-proof positioning context for the count chip.
   By moving position:relative onto a <span> (which always honours
   display:inline-block + position:relative without weird browser
   resets), the absolute child can never escape upwards. */
.health-badge__inner {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}
.health-badge__inner > i {
    font-size: 22px;
    line-height: 1;
}

/* Count "badge" — classic notification dot overlaying the shield icon. */
.health-badge__count {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #dc2626;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #fff;
    box-sizing: border-box;
    font-variant-numeric: tabular-nums;
    z-index: 2;
    pointer-events: none;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.18);
}
.health-badge--warning .health-badge__count { background: #f59e0b; }

/* ---------- Health page headline ---------- */
/* 🆕 v3.1.0 Phase V §13 Round 1 — hero shadow upgraded to 2-layer lift
   matching Dashboard Net Worth, Balance Sheet NW, More profile. */
.health-headline {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px;
    margin-bottom: 16px;
    border-radius: 16px;
    background: linear-gradient(135deg, #64748b 0%, #475569 100%);
    color: #fff;
    box-shadow: 0 6px 20px -4px rgba(15, 23, 42, 0.25),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}
/* 🆕 v3.1.0 Phase V §13 Round 3 — frosted-glass icon badge on the headline
   hero. backdrop-filter blur gives subtle depth over the gradient. */
.health-headline__icon {
    width: 52px; height: 52px;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.18);
    display: grid;
    place-items: center;
    font-size: 28px;
    flex-shrink: 0;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.health-headline__body { flex: 1; min-width: 0; }
.health-headline__status {
    margin: 0;
    font-size: 16px;
    font-weight: 800;
    letter-spacing: 0.02em;
}
.health-headline__sub {
    margin: 4px 0 0;
    font-size: 12.5px;
    opacity: 0.85;
}

/* 🆕 v3.1.0 Phase V §13 Round 1 — severity-tinted shadows match brand hero pattern. */
.health-headline--healthy  {
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    box-shadow: 0 6px 20px -4px rgba(16, 185, 129, 0.35),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}
.health-headline--warning  {
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
    box-shadow: 0 6px 20px -4px rgba(245, 158, 11, 0.38),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}
.health-headline--critical {
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    box-shadow: 0 6px 24px -4px rgba(239, 68, 68, 0.42),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}

/* ---------- Summary chips ---------- */
.health-summary {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    gap: 8px;
}
.health-summary__chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 999px;
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.08);
    font-size: 13px;
    font-weight: 600;
    color: #475569;
}
.health-summary__chip strong { font-variant-numeric: tabular-nums; }
.health-summary__chip--critical { color: #dc2626; }
.health-summary__chip--critical i { color: #dc2626; }
.health-summary__chip--warning  { color: #b45309; }
.health-summary__chip--warning  i { color: #b45309; }

/* 🆕 v3.1.0 Phase Y §15 Round 5 — 3-tile summary layout used by
   notifications.php (via .health-summary--v2). Each tile shows a big count
   number stacked over an icon + severity label. */
.health-summary--v2 {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
}
.health-summary__tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 14px 10px 12px;
    border-radius: var(--r-md, 12px);
    background: var(--surface-1, #fff);
    border: 1px solid var(--border-soft, #eef1f5);
    text-align: center;
    transition: transform .12s ease, box-shadow .18s ease, border-color .15s ease;
}
.health-summary__tile:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.14);
}
.health-summary__num {
    font-size: 26px;
    font-weight: 800;
    color: var(--text-primary, #0f172a);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
.health-summary__cap {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted, #64748b);
}
.health-summary__cap i { font-size: 13px; }

/* Severity tints */
.health-summary__tile--critical { background: #fef2f2; border-color: #fecaca; }
.health-summary__tile--critical .health-summary__num { color: #dc2626; }
.health-summary__tile--critical .health-summary__cap { color: #991b1b; }
.health-summary__tile--critical .health-summary__cap i { color: #dc2626; }

.health-summary__tile--warning  { background: #fffbeb; border-color: #fde68a; }
.health-summary__tile--warning  .health-summary__num { color: #b45309; }
.health-summary__tile--warning  .health-summary__cap { color: #78350f; }
.health-summary__tile--warning  .health-summary__cap i { color: #d97706; }

.health-summary__tile--info     { background: #eff6ff; border-color: #bfdbfe; }
.health-summary__tile--info     .health-summary__num { color: #2563eb; }
.health-summary__tile--info     .health-summary__cap { color: #1e40af; }
.health-summary__tile--info     .health-summary__cap i { color: #3b82f6; }

/* ---------- Issues list ---------- */
.health-issues__heading {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 700;
    color: #475569;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.health-issues__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* 🆕 v3.1.0 Phase V §13 Round 2 — card lift + hover state matching the
   global .card primitive. Draws attention when scanning a long issues list. */
.health-issue {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px;
    background: #fff;
    border-radius: 12px;
    border: 1px solid var(--border-soft, #eef1f5);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
    transition: transform .12s ease, box-shadow .18s ease;
}
.health-issue:hover {
    transform: translateY(-1px);
    box-shadow: 0 14px 30px -8px rgba(37, 99, 235, 0.20),
                0 4px 10px -2px rgba(15, 23, 42, 0.08);
}
.health-issue--critical { border-left: 4px solid #ef4444; }
.health-issue--warning  { border-left: 4px solid #f59e0b; }
.health-issue--info     { border-left: 4px solid #3b82f6; }
.health-issue__icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-size: 18px;
    flex-shrink: 0;
}
.health-issue--critical .health-issue__icon { background: rgba(239, 68, 68, 0.12); color: #dc2626; }
.health-issue--warning  .health-issue__icon { background: rgba(245, 158, 11, 0.14); color: #b45309; }
.health-issue--info     .health-issue__icon { background: rgba(59, 130, 246, 0.12); color: #2563eb; }
.health-issue__body { flex: 1; min-width: 0; }
.health-issue__msg {
    margin: 0 0 6px;
    font-size: 13.5px;
    color: #0f172a;
    line-height: 1.4;
}
/* 🆕 v3.1.0 Phase V §13 Round 2 — action link with chevron nudge on hover
   (same pattern as .section-head__link + .list-item chevron). Animated
   underline via ::after for extra feedback. */
.health-issue__action {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--brand-600, #2563eb);
    text-decoration: none;
    position: relative;
    transition: color .14s ease;
}
.health-issue__action i { transition: transform .14s ease; }
.health-issue__action:hover {
    color: var(--brand-700, #1d4ed8);
    text-decoration: none;
}
.health-issue__action:hover i { transform: translateX(2px); }
.health-issue__action::after {
    content: '';
    position: absolute;
    left: 0;
    right: 100%;
    bottom: -1px;
    height: 1.5px;
    background: var(--brand-500, #3b82f6);
    transition: right .22s cubic-bezier(0.16, 1, 0.3, 1);
}
.health-issue__action:hover::after { right: 18px; }  /* leaves room for the chevron icon */
.health-issue__action i { font-size: 14px; }
.health-issue__action--info {
    color: #64748b;
    font-style: italic;
    pointer-events: none;
}

/* 🆕 v3.1.0 Phase O §13 — Severity group section (draft §14).
   Each severity (CRITICAL · WARNING · INFO) has its own colored heading
   above the issues of that severity. */
.health-group {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
}
.health-group__heading {
    display: flex;
    align-items: center;
    gap: 10px;              /* 🆕 R4: more room for the glow-dot */
    margin: 0 2px 10px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
/* 🆕 v3.1.0 Phase V §13 Round 4 — glowing severity dot per group heading.
   Each dot has a 3px soft outer glow in its own severity color so the eye
   latches onto group boundaries while scanning. Pulse animation on the
   critical dot adds urgency without being distracting. */
.health-group__dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}
.health-group--critical .health-group__heading { color: #dc2626; }
.health-group--critical .health-group__dot     {
    background: #dc2626;
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15);
    animation: healthDotPulse 1.6s ease-in-out infinite;
}
.health-group--warning  .health-group__heading { color: #b45309; }
.health-group--warning  .health-group__dot     {
    background: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18);
}
.health-group--info     .health-group__heading { color: #2563eb; }
.health-group--info     .health-group__dot     {
    background: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
@keyframes healthDotPulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15); }
    50%      { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0.08); }
}
@media (prefers-reduced-motion: reduce) {
    .health-group--critical .health-group__dot { animation: none; }
}
.health-group__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* 🆕 Critical issues get the prominent "red card" treatment per draft §14.
   Phase V Round 5: deeper red-tinted shadow + hover emphasizes severity. */
.health-group--critical .health-issue--critical {
    background: #fef2f2;
    border: 1.5px solid #fecaca;
    border-left: 1.5px solid #fecaca;   /* reset the left-accent — the whole card is red */
    box-shadow: 0 6px 20px -4px rgba(220, 38, 38, 0.18),
                0 2px 6px -1px rgba(220, 38, 38, 0.10);
}
.health-group--critical .health-issue--critical:hover {
    transform: translateY(-1px);
    box-shadow: 0 10px 28px -4px rgba(220, 38, 38, 0.26),
                0 4px 10px -2px rgba(220, 38, 38, 0.14);
    border-color: #fca5a5;
}
.health-group--critical .health-issue--critical .health-issue__action {
    color: #dc2626;
}
.health-group--critical .health-issue--critical .health-issue__action::after {
    background: #dc2626;
}
.health-group--critical .health-issue--critical .health-issue__action:hover {
    color: #991b1b;
}

/* 🆕 v3.1.0 Phase V §13 Round 6 — subtle severity tint for warning & info
   cards. Lighter than the critical treatment so they read as "noteworthy"
   not "urgent". Keeps the 4px left-border accent as the quick-scan signal. */
.health-group--warning .health-issue--warning {
    background: #fffbeb;
    border: 1.5px solid #fde68a;
    border-left: 4px solid #f59e0b;
    box-shadow: 0 4px 14px -4px rgba(245, 158, 11, 0.14),
                0 1px 4px -1px rgba(245, 158, 11, 0.08);
}
.health-group--warning .health-issue--warning:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px -4px rgba(245, 158, 11, 0.22),
                0 3px 8px -2px rgba(245, 158, 11, 0.12);
    border-color: #fcd34d;
    border-left-color: #d97706;
}
.health-group--warning .health-issue--warning .health-issue__action {
    color: #b45309;
}
.health-group--warning .health-issue--warning .health-issue__action::after {
    background: #d97706;
}
.health-group--warning .health-issue--warning .health-issue__action:hover {
    color: #92400e;
}

.health-group--info .health-issue--info {
    background: #eff6ff;
    border: 1.5px solid #bfdbfe;
    border-left: 4px solid #3b82f6;
    box-shadow: 0 4px 14px -4px rgba(59, 130, 246, 0.14),
                0 1px 4px -1px rgba(59, 130, 246, 0.08);
}
.health-group--info .health-issue--info:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px -4px rgba(59, 130, 246, 0.22),
                0 3px 8px -2px rgba(59, 130, 246, 0.12);
    border-color: #93c5fd;
    border-left-color: #2563eb;
}

/* Tighter breathing room between severity groups per draft §14. */
.health-group + .health-group { margin-top: 20px; }

/* ---------- Empty state (All clear) ---------- */
.health-empty {
    text-align: center;
    padding: 48px 24px 36px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}
/* 🆕 v3.1.0 Phase V §13 Round 3 — all-clear illustration upgraded to the
   same gradient-circle + glow pattern as the Setup Wizard "Done" icon.
   White checkmark on green gradient reads unambiguously as "all good". */
.health-empty__icon {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    border: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 42px;
    color: #fff;
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    box-shadow: 0 8px 24px -4px rgba(16, 185, 129, 0.45),
                0 2px 6px -1px rgba(15, 23, 42, 0.10);
    animation: healthEmptyPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes healthEmptyPop {
    0%   { opacity: 0; transform: scale(0.6); }
    60%  { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .health-empty__icon { animation: none; }
}
.health-empty__title {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: #0f172a;
}
.health-empty__msg {
    margin: 0;
    font-size: 13px;
    color: #64748b;
    line-height: 1.5;
    max-width: 260px;
}


/* ============================================
 * 75. OPENING ENTRY WIZARD (June 16, 2026)
 *      5-screen flow inside .app-sheet--full
 * ============================================ */

/* ---------- Welcome screen ---------- */
.setup-welcome {
    text-align: center;
    padding: 20px 8px;
}
.setup-welcome__icon {
    /* 🆕 v3.1.0 Phase O §17 — gradient-filled per draft §21 Hi-Fi Welcome screen */
    width: 68px; height: 68px;
    margin: 0 auto 14px;
    border-radius: 20px;
    display: grid;
    place-items: center;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 32px;
    box-shadow: 0 6px 16px rgba(37, 99, 235, 0.28);
}
.setup-welcome__title {
    margin: 0 0 8px;
    font-size: 20px;
    font-weight: 800;
    color: var(--text-primary, #0f172a);
}
.setup-welcome__body {
    margin: 0 0 20px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-secondary, #64748b);
}
.setup-welcome__steps {
    list-style: none;
    margin: 0 0 20px;
    padding: 0;
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* 🆕 v3.1.0 Phase AA §21 Setup Wizard Round 1 — welcome steps lift + hover.
   Reads like a lightweight preview of what the user will do. */
.setup-welcome__steps li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px;
    background: var(--surface-1, #fff);
    border: 1px solid var(--border-soft, #eef1f5);
    border-radius: 12px;
    font-size: 14px;
    color: var(--text-primary, #0f172a);
    box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.10);
    transition: transform .14s ease, box-shadow .18s ease, border-color .15s ease;
}
.setup-welcome__steps li:hover {
    transform: translateY(-1px);
    border-color: #93c5fd;
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.20);
}
/* 🆕 Body wrapper — stacks title + description vertically */
.setup-welcome__step-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.setup-welcome__step-title {
    font-size: 14.5px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.3;
}
.setup-welcome__step-desc {
    font-size: 12.5px;
    color: #64748b;
    line-height: 1.4;
}
/* 🆕 v3.1.0 Phase AA §21 Round 1 — step number gets gradient fill + glow
   matching the Welcome icon pattern. */
.setup-welcome__step-num {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 13px;
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    margin-top: 1px;
    justify-content: center;
    box-shadow: 0 3px 8px rgba(37, 99, 235, 0.32),
                inset 0 1px 0 rgba(255, 255, 255, 0.18);
    transition: transform .18s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.setup-welcome__steps li:hover .setup-welcome__step-num {
    transform: scale(1.08);
}
@media (prefers-reduced-motion: reduce) {
    .setup-welcome__step-num { transition: none; }
    .setup-welcome__steps li:hover .setup-welcome__step-num { transform: none; }
}
.setup-welcome__hint {
    margin: 14px 0 0;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(59, 130, 246, 0.06);
    color: #475569;
    font-size: 12.5px;
    line-height: 1.5;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    text-align: left;
}
.setup-welcome__hint i {
    color: #2563eb;
    font-size: 16px;
    flex-shrink: 0;
    margin-top: 1px;
}
/* 🆕 Locked variant — red/amber accent for "required" copy */
.setup-welcome__hint--locked {
    background: rgba(245, 158, 11, 0.10);
    color: #78350f;
    border: 1px solid rgba(245, 158, 11, 0.30);
}
.setup-welcome__hint--locked i { color: #b45309; }
.setup-welcome__hint--locked strong { color: #92400e; }

/* 🆕 Done indicator in the More menu — replaces the Account Setup link
 *    once the wizard has been completed. Non-interactive. */
.list-item--done {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    cursor: default;
    user-select: none;
    opacity: 0.85;
}
.list-item__icon--done {
    background: rgba(16, 185, 129, 0.14);
    color: #047857;
}
/* 🆕 v3.1.0 Phase S §11 Round 3 — per-section tile colors matching draft §11
   lines 2663-2678. More page uses --brand (money/security), --neutral (settings),
   --success (status/completed). Reusable across any list-item context. */
.list-item__icon--brand   { background: rgba(37, 99, 235, 0.10); color: #2563eb; }
.list-item__icon--neutral { background: var(--surface-2, #f8fafc); color: #64748b; }
.list-item__icon--success { background: rgba(16, 185, 129, 0.12); color: #16a34a; }
/* 🆕 v3.1.0 Phase S §11 Round 4 — badge chips per draft §11 lines 2670/2671.
   `done` pill: soft green bg, 10px/700, 99px radius.
   `new` chip:  soft blue bg, 9.5px/700, 6px radius (not pill — distinguishes
                future features from status pills). */
.list-item__badge--done {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 3px 9px;
    border-radius: 999px;
    background: #f0fdf4;
    color: #16a34a;
    text-transform: uppercase;
}

.list-item__badge--new {
    display: inline-block;
    margin-left: 6px;
    vertical-align: middle;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.4px;
    padding: 1px 6px;
    border-radius: 6px;                         /* 🆕 R4: square chip (was pill) */
    background: #eef2ff;
    color: var(--brand-600, #2563eb);
    text-transform: uppercase;
    line-height: 1.5;
}

/* ---------- Step intro paragraph ---------- */
.setup-step__intro {
    margin: 0 0 16px;
    font-size: 13.5px;
    color: var(--text-secondary, #64748b);
    line-height: 1.5;
}
.setup-step__intro em {
    color: var(--text-primary, #0f172a);
    font-style: normal;
    font-weight: 600;
}

/* ---------- Account list (assets / liabs input) ---------- */
.setup-list {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* 🆕 v3.1.0 Phase AA §21 Round 2 — setup-row cards: brand lift + stronger
   focus glow + filled-state tint retained. */
.setup-row {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: #fff;
    border: 1.5px solid var(--border-soft, #eef1f5);
    border-radius: 14px;
    box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.10);
    transition: border-color 0.18s, box-shadow 0.22s, transform 0.18s, background 0.18s;
    position: relative;
}
.setup-row:hover {
    border-color: #93c5fd;
    box-shadow: 0 6px 18px -4px rgba(37, 99, 235, 0.18),
                0 2px 6px -1px rgba(15, 23, 42, 0.06);
    transform: translateY(-1px);
}
.setup-row.is-focus {
    border-color: var(--brand-500, #3b82f6);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14),
                0 6px 18px -4px rgba(37, 99, 235, 0.22);
    transform: translateY(-1px);
}
.setup-row.is-filled {
    border-color: rgba(16, 185, 129, 0.40);
    background: linear-gradient(180deg, #fff 0%, rgba(16, 185, 129, 0.04) 100%);
}
.setup-row.is-filled.setup-row--liab {
    border-color: rgba(239, 68, 68, 0.40);
    background: linear-gradient(180deg, #fff 0%, rgba(239, 68, 68, 0.04) 100%);
}
.setup-row.is-focus.is-filled {
    border-color: #3b82f6;
}

/* Icon column — soft tinted circle */
.setup-row__icon {
    width: 40px; height: 40px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-size: 20px;
    background: rgba(59, 130, 246, 0.10);
    color: #2563eb;
    flex-shrink: 0;
}
.setup-row--liab .setup-row__icon {
    background: rgba(239, 68, 68, 0.10);
    color: #dc2626;
}
.setup-row.is-filled .setup-row__icon {
    background: rgba(16, 185, 129, 0.16);
    color: #047857;
}
.setup-row.is-filled.setup-row--liab .setup-row__icon {
    background: rgba(239, 68, 68, 0.18);
    color: #b91c1c;
}

/* Info column — name + small subtitle */
.setup-row__info {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.setup-row__name {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text-primary, #0f172a);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}
.setup-row__sub {
    font-size: 11px;
    font-weight: 600;
    color: #94a3b8;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
}

/* Amount column — pill-shaped input */
.setup-row__amt-wrap {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    background: rgba(15, 23, 42, 0.05);
    border-radius: 10px;
    padding: 8px 12px;
    transition: background 0.18s, color 0.18s;
}
.setup-row.is-focus .setup-row__amt-wrap {
    background: rgba(59, 130, 246, 0.10);
}
.setup-row.is-filled .setup-row__amt-wrap {
    background: rgba(16, 185, 129, 0.12);
}
.setup-row.is-filled.setup-row--liab .setup-row__amt-wrap {
    background: rgba(239, 68, 68, 0.12);
}
.setup-row__currency {
    font-size: 13px;
    color: #64748b;
    font-weight: 700;
}
.setup-row.is-filled .setup-row__currency {
    color: #047857;
}
.setup-row.is-filled.setup-row--liab .setup-row__currency {
    color: #b91c1c;
}
.setup-row__input {
    width: 110px;
    border: none;
    background: transparent;
    text-align: right;
    font-size: 15.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary, #0f172a);
    font-family: inherit;
    padding: 0;
    min-width: 0;
}
.setup-row__input:focus { outline: none; }
.setup-row__input::placeholder { color: #cbd5e1; font-weight: 500; }
.setup-row.is-filled .setup-row__input { color: #047857; }
.setup-row.is-filled.setup-row--liab .setup-row__input { color: #b91c1c; }

/* 🆕 v3.1.0 Phase AA §21 Round 3 — Section total card: brand gradient hero
   with white text, matching .budget-totals + review hero language. */
.setup-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 18px;
    padding: 16px 18px;
    background: var(--brand-gradient-deep);
    border: none;
    border-radius: 14px;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.85);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    box-shadow: 0 8px 20px -4px rgba(37, 99, 235, 0.32),
                0 2px 6px -1px rgba(15, 23, 42, 0.14);
}
.setup-total strong {
    font-size: 20px;
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    text-transform: none;
}
/* Liab variant — red gradient for "amount owed" */
.setup-list--liab + .setup-total {
    background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
    box-shadow: 0 8px 20px -4px rgba(220, 38, 38, 0.32),
                0 2px 6px -1px rgba(15, 23, 42, 0.14);
}
.setup-list--liab + .setup-total strong {
    color: #fff;
}

/* 🆕 v3.1.0 Phase AA §21 Round 6 — list-empty hint: softer dashed card
   with icon tile for cohesion with other empty-state patterns. */
.setup-list-empty {
    margin: 16px 0;
    padding: 22px 16px;
    text-align: center;
    background: var(--surface-2, #f8fafc);
    border: 1.5px dashed var(--border-light, #cbd5e1);
    border-radius: 14px;
    color: var(--text-muted, #94a3b8);
    font-size: 13px;
    line-height: 1.5;
}
.setup-list-empty i {
    display: inline-flex;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
    font-size: 24px;
    margin: 0 auto 8px;
    align-items: center;
    justify-content: center;
}

/* 🆕 Search filter at top of Assets/Liabs list — with "+ New" button on the right */
.setup-search {
    position: relative;
    margin: 0 0 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.setup-search__icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: #94a3b8;
    font-size: 18px;
    pointer-events: none;
}
/* 🆕 v3.1.0 Phase AA §21 Round 4 — setup-search input: 1→1.5 border +
   deeper brand glow on focus matching login + tx-input focus patterns. */
.setup-search__input {
    flex: 1;
    min-width: 0;
    height: 42px;
    padding: 0 14px 0 40px;
    border-radius: 10px;
    border: 1.5px solid var(--border-soft, #eef1f5);
    background: #fff;
    font-size: 14px;
    font-family: inherit;
    color: #0f172a;
    transition: border-color 0.18s ease, box-shadow 0.22s ease, background 0.18s ease;
    box-sizing: border-box;
    appearance: none;
    -webkit-appearance: none;
}
.setup-search__input:focus {
    outline: none;
    border-color: var(--brand-500, #3b82f6);
    background: #fff;
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14),
                0 4px 12px -4px rgba(37, 99, 235, 0.22);
}
.setup-search__input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* 🆕 "+ New" button — opens AccountForm.openAdd() from wizard.
   Round 4: 2-layer brand+cyan shadow + hover lift + icon rotate. */
.setup-search__add {
    flex-shrink: 0;
    height: 42px;
    padding: 0 16px;
    border: none;
    border-radius: 10px;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 13.5px;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 4px 12px -2px rgba(59, 130, 246, 0.32),
                0 2px 6px -1px rgba(6, 182, 212, 0.18);
    transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.18s ease, filter 0.18s ease;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
}
.setup-search__add:hover {
    transform: translateY(-1px);
    filter: brightness(1.06) saturate(1.08);
    box-shadow: 0 8px 20px -4px rgba(59, 130, 246, 0.42),
                0 3px 8px -2px rgba(6, 182, 212, 0.26);
}
.setup-search__add:active { transform: translateY(0) scale(0.96); }
.setup-search__add i {
    font-size: 18px;
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.setup-search__add:hover i { transform: rotate(90deg); }
/* Remove the native search clear "X" — UI is busy enough */
.setup-search__input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* 🆕 No-match row inside the list (created by JS) */
.setup-list-no-match {
    list-style: none;
    text-align: center;
    padding: 14px;
    color: #94a3b8;
    font-size: 13px;
    font-style: italic;
}
.setup-list-no-match i { margin-right: 6px; }

/* 🆕 "Missing an account?" hint below the list.
   Round 6: upgraded to info-banner pattern (soft brand bg + icon tile color). */
.setup-missing-hint {
    margin: 14px 0 0;
    padding: 12px 14px;
    border-radius: 10px;
    background: #eff6ff;
    border: 1.5px solid #bfdbfe;
    border-left: 4px solid #3b82f6;
    color: #1e40af;
    font-size: 12.5px;
    line-height: 1.5;
    display: flex;
    gap: 10px;
    align-items: flex-start;
    box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.14);
}
.setup-missing-hint i {
    color: #2563eb;
    font-size: 18px;
    flex-shrink: 0;
    margin-top: 1px;
}
.setup-missing-hint strong { color: #1e3a8a; }

/* ---------- 🆕 Phase O §17 — step progress dots (Assets / Liabs / Review) ---------- */
.setup-stepper {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    padding: 4px 16px 10px;
    margin-top: -6px;        /* snug under header */
}
.setup-stepper__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border-soft, #e2e8f0);
    transition: background .18s ease, transform .18s ease, width .18s ease;
}
.setup-stepper__dot.is-done {
    background: var(--brand-500, #3b82f6);
    opacity: 0.65;
}
.setup-stepper__dot.is-active {
    width: 22px;
    border-radius: 999px;
    background: var(--brand-gradient);
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.35);
    transform: scale(1);
}

/* ---------- Review screen ---------- */
/* 🆕 v3.1.0 Phase AA §21 Round 5 — Net Worth hero: deeper lift + bounce-in */
.setup-review {
    text-align: center;
    padding: 24px 16px;
    margin-bottom: 18px;
    background: var(--brand-gradient-hero);
    border-radius: 16px;
    color: #fff;
    box-shadow: 0 10px 28px -4px rgba(37, 99, 235, 0.42),
                0 3px 8px -2px rgba(15, 23, 42, 0.14);
    animation: setupReviewHeroPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes setupReviewHeroPop {
    0%   { opacity: 0; transform: scale(0.9) translateY(10px); }
    60%  { opacity: 1; transform: scale(1.02) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .setup-review { animation: none; }
}
.setup-review__label {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.10em;
    opacity: 0.85;
}
.setup-review__value {
    margin: 6px 0 4px;
    font-size: 30px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.setup-review__value.is-negative { color: #fecaca; }
.setup-review__sub {
    margin: 0;
    font-size: 12.5px;
    opacity: 0.86;
}
.setup-review__heading {
    margin: 0 0 6px;
    font-size: 13px;
    font-weight: 700;
    color: var(--text-secondary, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.setup-review__note {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-secondary, #64748b);
}
.setup-review__note em {
    font-style: normal;
    font-weight: 700;
    color: #2563eb;
}
.setup-review__lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.setup-review__line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 8px 12px;
    background: rgba(16, 185, 129, 0.06);
    border-radius: 10px;
    font-size: 13px;
}
.setup-review__line--neg { background: rgba(239, 68, 68, 0.06); }
.setup-review__line-name {
    color: var(--text-primary, #0f172a);
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.setup-review__line-name i { font-size: 14px; opacity: 0.7; }
.setup-review__line-amt {
    color: #059669;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.setup-review__line--neg .setup-review__line-amt { color: #dc2626; }

/* ---------- Done screen ---------- */
.setup-done {
    text-align: center;
    padding: 32px 14px;
}
.setup-done__icon {
    /* 🆕 v3.1.0 Phase O §17 — gradient-filled circle per draft §21 Hi-Fi Done screen */
    width: 76px; height: 76px;
    margin: 0 auto 14px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 38px;
    box-shadow: 0 6px 16px rgba(37, 99, 235, 0.28);
    animation: setupDonePop 0.5s ease-out;
}
.setup-done__icon i { font-size: 38px; line-height: 1; }
@keyframes setupDonePop {
    0%   { opacity: 0; transform: scale(0.6); }
    60%  { opacity: 1; transform: scale(1.12); }
    100% { opacity: 1; transform: scale(1); }
}
.setup-done__title {
    margin: 0 0 8px;
    font-size: 20px;
    font-weight: 800;
    color: var(--text-primary, #0f172a);
}
.setup-done__body {
    margin: 0 0 16px;
    font-size: 14px;
    color: var(--text-secondary, #64748b);
    line-height: 1.5;
}
.setup-done__txid {
    margin: 0;
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(15, 23, 42, 0.04);
    color: #475569;
    font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
    font-size: 12.5px;
}


/* ============================================
 * 76. TRANSACTION LIST — Type-specific styling (June 16, 2026)
 *      Tints the row icon background per type so users can scan the
 *      list visually (income/expense/transfer/opening/other).
 * ============================================ */
.list-item--transfer .list-item__icon {
    background: rgba(37, 99, 235, 0.12);
    color: #2563eb;
}
.list-item--opening .list-item__icon {
    background: rgba(100, 116, 139, 0.14);
    color: #475569;
}
.list-item--income .list-item__icon {
    background: rgba(16, 185, 129, 0.12);
    color: #059669;
}
.list-item--expense .list-item__icon {
    background: rgba(239, 68, 68, 0.10);
    color: #dc2626;
}
.list-item--other .list-item__icon {
    background: rgba(100, 116, 139, 0.10);
    color: #64748b;
}


/* ============================================
 * 77. ADD TX — Available balance hint + error state (June 17, 2026)
 *      Inline "Available: ฿X" under the FROM account picker, and
 *      a low/zero state for the hint.
 * ============================================ */
.tx-account-hint {
    margin: 6px 0 0;
    padding: 0;
    font-size: 12px;
    color: #475569;
    font-weight: 600;
    letter-spacing: 0.01em;
}
.tx-account-hint::before {
    content: '\1F4B0';      /* 💰 */
    margin-right: 4px;
}
.tx-account-hint--low {
    color: #dc2626;
}
.tx-account-hint--low::before {
    content: '\26A0';       /* ⚠ */
}


/* ============================================
 * 78. NOTIFICATION BELL + ALERT SHEET (June 19, 2026)
 *      Bell sits fixed top-right of viewport. Sheet uses the same
 *      .app-sheet/.app-sheet--slide system as the rest of the app.
 * ============================================ */

/* ---------- Bell button (inline inside .page-header__actions) ----------
   Now scoped to the dashboard only. Sits next to the health badge and
   profile avatar — no longer fixed-positioned, so it can't collide with
   page-level + buttons on other pages. */
.notif-bell {
    position: relative;
    appearance: none;
    border: none;
    width: 38px; height: 38px;
    border-radius: 50%;
    background: #fff;
    color: #475569;
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12),
                0 0 0 1px rgba(15, 23, 42, 0.06);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
    flex-shrink: 0;
}
.notif-bell:active { transform: scale(0.92); }
.notif-bell:hover {
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.16),
                0 0 0 1px rgba(15, 23, 42, 0.08);
    transform: translateY(-1px);
}
/* 🆕 v3.1.0 Phase Y §15 Round 6 — subtle bell icon jiggle on hover for a
   tactile cue. Spring curve, 0.3s one-shot (CSS re-triggers on re-hover). */
.notif-bell > i,
.notif-bell > .bx {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.notif-bell:hover > i,
.notif-bell:hover > .bx {
    transform: rotate(-10deg);
}

/* 🆕 v3.1.0 Phase B: subdued state when no alerts (bell stays visible for
   discoverability per draft §15). Grey icon + softer shadow + no badge. */
.notif-bell.is-empty {
    color: var(--pf-muted-2, #94a3b8);
    background: var(--pf-card, #fff);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06),
                0 0 0 1px rgba(15, 23, 42, 0.04);
}
.notif-bell.is-empty:hover {
    color: var(--pf-muted-1, #64748b);
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.10),
                0 0 0 1px rgba(15, 23, 42, 0.06);
}
.notif-bell__count[hidden] { display: none !important; }

/* Severity-tinted bell when there are alerts */
.notif-bell--warning {
    background: #fffbeb;
    color: #b45309;
    box-shadow: 0 2px 8px rgba(245, 158, 11, 0.30),
                0 0 0 1px rgba(245, 158, 11, 0.35);
}
.notif-bell--critical {
    background: #fef2f2;
    color: #dc2626;
    box-shadow: 0 2px 8px rgba(239, 68, 68, 0.30),
                0 0 0 1px rgba(239, 68, 68, 0.40);
    animation: notifBellPulse 1.8s ease-in-out infinite;
}
@keyframes notifBellPulse {
    0%, 100% { box-shadow: 0 2px 8px rgba(239, 68, 68, 0.30), 0 0 0 1px rgba(239, 68, 68, 0.40); }
    50%      { box-shadow: 0 2px 14px rgba(239, 68, 68, 0.55), 0 0 0 2px rgba(239, 68, 68, 0.55); }
}

/* Count badge — sits top-right of the bell.
   🆕 v3.1.0 Phase Y §15 Round 6 — bounce-in animation when count appears
   (the user just got a new alert) + soft outer glow matching severity. */
.notif-bell__count {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #dc2626;
    color: #fff;
    font-size: 10.5px;
    font-weight: 800;
    line-height: 18px;
    text-align: center;
    border: 2px solid #fff;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.20);
    animation: notifBellCountPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes notifBellCountPop {
    0%   { opacity: 0; transform: scale(0.3); }
    60%  { opacity: 1; transform: scale(1.2); }
    100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .notif-bell__count { animation: none; }
}
.notif-bell--warning .notif-bell__count {
    background: #d97706;
    box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.22);
}

/* 🆕 Hide the dashboard banner whenever a sheet is open (no visual
   clash with sheet's own X close button at the top of the viewport).
   Bell is inline now so it scrolls with the page header — no clash. */
body.has-sheet  .notif-banner,
body.sheet-open .notif-banner {
    display: none !important;
}

/* ---------- Notification sheet content ---------- */
.notif-sheet__content { padding: 12px 14px 24px; }
.notif-sheet__count {
    display: inline-block;
    margin-left: 8px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.03em;
    vertical-align: 2px;
}

/* ---------- Empty / loading state ---------- */
.notif-empty {
    margin: 24px 0;
    text-align: center;
    color: #64748b;
    font-size: 13.5px;
    line-height: 1.5;
}
.notif-empty i {
    display: block;
    font-size: 36px;
    margin-bottom: 8px;
    color: #16a34a;
}
.notif-empty--loading {
    color: #94a3b8;
    font-style: italic;
}

/* ---------- Items list ---------- */
.notif-list {
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* 🆕 v3.1.0 Phase Y §15 Notifications Round 1 — card lift + hover state
   mirror the health-issue card so notifications feel like part of the same
   severity-aware card family. */
.notif-item {
    display: grid;
    grid-template-columns: 40px 1fr;
    gap: 12px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--border-soft, #eef1f5);
    border-radius: 14px;
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
    transition: transform .12s ease, box-shadow .18s ease, border-color .15s ease;
    cursor: pointer;
}
.notif-item:hover {
    transform: translateY(-1px);
    box-shadow: 0 14px 30px -8px rgba(37, 99, 235, 0.20),
                0 4px 10px -2px rgba(15, 23, 42, 0.08);
    border-color: var(--border-light, #cbd5e1);
}
.notif-item--critical { border-left: 4px solid #ef4444; }
.notif-item--warning  { border-left: 4px solid #f59e0b; }
.notif-item--info     { border-left: 4px solid #3b82f6; }

/* Severity-tinted hover for critical */
.notif-item--critical:hover {
    border-color: #fca5a5;
    border-left-color: #dc2626;
    box-shadow: 0 10px 28px -4px rgba(220, 38, 38, 0.26),
                0 4px 10px -2px rgba(220, 38, 38, 0.14);
}
.notif-item--warning:hover {
    border-color: #fcd34d;
    border-left-color: #d97706;
    box-shadow: 0 10px 28px -4px rgba(245, 158, 11, 0.22),
                0 4px 10px -2px rgba(245, 158, 11, 0.12);
}
.notif-item--info:hover {
    border-color: #93c5fd;
    border-left-color: #2563eb;
    box-shadow: 0 10px 28px -4px rgba(59, 130, 246, 0.22),
                0 4px 10px -2px rgba(59, 130, 246, 0.12);
}

.notif-item__icon {
    width: 40px; height: 40px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-size: 20px;
}
.notif-item--critical .notif-item__icon { background: rgba(239, 68, 68, 0.12); color: #dc2626; }
.notif-item--warning  .notif-item__icon { background: rgba(245, 158, 11, 0.14); color: #b45309; }
.notif-item--info     .notif-item__icon { background: rgba(59, 130, 246, 0.12); color: #2563eb; }

.notif-item__body { min-width: 0; }
.notif-item__title {
    margin: 0 0 4px;
    font-size: 14px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.3;
}
.notif-item__msg {
    margin: 0 0 8px;
    font-size: 12.5px;
    line-height: 1.45;
    color: #475569;
}
.notif-item__action {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 12px;
    border-radius: 999px;
    background: rgba(59, 130, 246, 0.10);
    color: #2563eb;
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
    transition: background 0.15s ease;
}
.notif-item__action:hover  { background: rgba(59, 130, 246, 0.18); }
.notif-item__action:active { transform: scale(0.96); }

/* Footer link to /health.php */
.notif-footer-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-radius: 14px;
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(6, 182, 212, 0.06) 100%);
    border: 1px solid rgba(59, 130, 246, 0.18);
    color: #1e3a8a;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.15s ease;
}
.notif-footer-link i:first-child { font-size: 18px; color: #2563eb; }
.notif-footer-link span { flex: 1; }
.notif-footer-link i:last-child  { font-size: 16px; color: #64748b; }
.notif-footer-link:hover { background: linear-gradient(135deg, rgba(59, 130, 246, 0.12) 0%, rgba(6, 182, 212, 0.10) 100%); }

/* 🆕 v3.1.0 Phase E — primary "See all notifications" variant (replaces
   removed "Open Account Health" link per draft §15) */
.notif-footer-link--primary {
    background: linear-gradient(135deg, rgba(31, 95, 230, 0.10) 0%, rgba(59, 130, 246, 0.10) 100%);
    border-color: rgba(31, 95, 230, 0.28);
    color: var(--pf-primary, #1F5FE6);
    font-weight: 700;
}
.notif-footer-link--primary i:first-child,
.notif-footer-link--primary i:last-child { color: var(--pf-primary, #1F5FE6); }
.notif-footer-link--primary:hover {
    background: linear-gradient(135deg, rgba(31, 95, 230, 0.16) 0%, rgba(59, 130, 246, 0.14) 100%);
}

/* ============================================
   🆕 v3.1.0 Phase E — Notification Center page (notifications.php)
   Full-page alert list · draft §15
   ============================================ */

/* Summary tiles reuse .health-summary layout — nudge margin/gap on this page */
.notif-summary { margin: 16px 0 20px; }

/* 🆕 v3.1.0 Phase Y §15 Round 3 — "Mark all read" header action button.
   Soft brand pill + check-icon slide-in on hover for tactile feedback. */
.notif-clear-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 999px;
    background: #eef2ff;
    color: var(--brand-600, #2563eb);
    border: none;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    transition: background .18s ease, color .18s ease, transform .08s ease, box-shadow .18s ease;
    -webkit-tap-highlight-color: transparent;
}
.notif-clear-btn i {
    font-size: 15px;
    transition: transform .18s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.notif-clear-btn:hover {
    background: rgba(37, 99, 235, 0.18);
    color: var(--brand-700, #1d4ed8);
    box-shadow: 0 3px 8px rgba(37, 99, 235, 0.18);
}
.notif-clear-btn:hover i { transform: rotate(-6deg) scale(1.1); }
.notif-clear-btn:active { transform: scale(0.97); }

/* Severity group */
.notif-group { margin: 0 0 20px; }
.notif-group__heading {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 4px 10px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--pf-muted-2, #64748b);
}
.notif-group__heading i {
    font-size: 15px;
    line-height: 1;
}
/* 🆕 v3.1.0 Phase Y §15 Round 3 — count chip:
   soft brand base + severity override, slightly bolder + wider for easier read. */
.notif-group__count {
    margin-left: auto;
    min-width: 22px;
    padding: 2px 9px;
    border-radius: 999px;
    background: #eef2ff;
    color: var(--brand-600, #2563eb);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.notif-group--critical .notif-group__heading i    { color: #dc2626; }
.notif-group--critical .notif-group__count        { background: rgba(239, 68, 68, 0.14); color: #b91c1c; }
.notif-group--warning  .notif-group__heading i    { color: #b45309; }
.notif-group--warning  .notif-group__count        { background: rgba(245, 158, 11, 0.18); color: #92400e; }
.notif-group--info     .notif-group__heading i    { color: #2563eb; }
.notif-group--info     .notif-group__count        { background: rgba(59, 130, 246, 0.14); color: #1d4ed8; }

.notif-group__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Individual alert row — richer than bottom-sheet variant, with unread dot + CTA */
.notif-group .notif-item {
    position: relative;
    display: grid;
    grid-template-columns: 40px 1fr auto;
    gap: 12px;
    align-items: start;
    padding: 14px;
    margin: 0;
    background: var(--pf-card, #ffffff);
    border: 1px solid var(--pf-line, #e2e8f0);
    border-radius: var(--pf-radius-card, 16px);
    box-shadow: var(--pf-shadow-sm, 0 1px 2px rgba(15, 23, 42, 0.06));
    transition: background 160ms var(--pf-ease-out, ease-out);
}
.notif-group--critical .notif-item { border-left: 4px solid #ef4444; }
.notif-group--warning  .notif-item { border-left: 4px solid #f59e0b; }
.notif-group--info     .notif-item { border-left: 4px solid #3b82f6; }

.notif-group .notif-item__icon {
    width: 40px; height: 40px;
    border-radius: 12px;
    display: grid; place-items: center;
    font-size: 20px;
    flex-shrink: 0;
}
.notif-group--critical .notif-item__icon { background: rgba(239, 68, 68, 0.12); color: #dc2626; }
.notif-group--warning  .notif-item__icon { background: rgba(245, 158, 11, 0.14); color: #b45309; }
.notif-group--info     .notif-item__icon { background: rgba(59, 130, 246, 0.12); color: #2563eb; }

.notif-group .notif-item__body { min-width: 0; }
.notif-group .notif-item__title {
    margin: 0 0 4px;
    font-size: 14.5px;
    font-weight: 700;
    color: var(--pf-ink, #0E1F44);
    line-height: 1.35;
}
.notif-item__body-text {
    margin: 0 0 8px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--pf-muted-1, #475569);
}
/* 🆕 v3.1.0 Phase Y §15 Round 2 — CTA pill polish:
   soft brand bg + chevron nudge + scale press (matches .section-head__link
   + .list-item chevron pattern). */
.notif-item__cta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 12px 5px 12px;
    border-radius: 999px;
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    transition: background .14s ease,
                color .14s ease,
                transform .08s ease;
}
.notif-item__cta i {
    font-size: 15px;
    line-height: 1;
    transition: transform .14s ease;
}
.notif-item__cta:hover {
    background: rgba(37, 99, 235, 0.18);
    color: var(--brand-700, #1d4ed8);
}
.notif-item__cta:hover i { transform: translateX(2px); }
.notif-item__cta:active { transform: scale(0.97); }

/* Unread dot (top-right) */
/* 🆕 v3.1.0 Phase Y §15 Round 2 — pulse animation on critical unread so
   urgent new alerts catch the eye. Non-critical unread stays static. */
.notif-item__dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--brand-600, #2563eb);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
    align-self: start;
    margin-top: 8px;
}
.notif-item--critical .notif-item__dot {
    background: #dc2626;
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.18);
    animation: notifDotPulse 1.6s ease-in-out infinite;
}
.notif-item--warning .notif-item__dot {
    background: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18);
}
@keyframes notifDotPulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.18); }
    50%      { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0.08); }
}
@media (prefers-reduced-motion: reduce) {
    .notif-item--critical .notif-item__dot { animation: none; }
}

/* Read state: subtler — slightly muted bg, reduced opacity, smaller icon */
/* 🆕 v3.1.0 Phase Y §15 Round 2 — read-state tuned: softer bg, muted body,
   NO lift shadow (so unread rows pop out when scanning). */
.notif-item--read {
    background: #fafbfc;
    opacity: 0.75;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.notif-item--read:hover {
    opacity: 0.95;
    box-shadow: 0 6px 16px -4px rgba(15, 23, 42, 0.10);
}
.notif-item--read .notif-item__title {
    font-weight: 600;
    color: var(--text-secondary, #475569);
}
.notif-item--read .notif-item__body-text {
    color: var(--text-muted, #94a3b8);
}

/* Success variant for empty-state icon (used by "You're all caught up") */
/* 🆕 v3.1.0 Phase Y §15 Round 4 — success empty-state icon upgraded to
   the gradient-circle treatment used by Health all-clear and Setup Wizard
   Done. Reads unambiguously as "all good" with a celebratory bounce. */
.empty-state__icon--success {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    color: #fff;
    font-size: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 24px -4px rgba(16, 185, 129, 0.45),
                0 2px 6px -1px rgba(15, 23, 42, 0.10);
    animation: emptyStateSuccessPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
    margin: 0 auto var(--space-3);
}
@keyframes emptyStateSuccessPop {
    0%   { opacity: 0; transform: scale(0.6); }
    60%  { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .empty-state__icon--success { animation: none; }
}

/* ---------- Dashboard banner (critical-only) ----------
   🆕 v3.1.0 Phase Y §15 Round 5 — banner polish: deeper red lift, hover
   translateY + chevron slide, icon pulse for urgency. */
.notif-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 18px;
    padding: 14px 16px;
    border-radius: 14px;
    background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
    border: 1.5px solid rgba(239, 68, 68, 0.30);
    border-left: 4px solid #dc2626;
    color: #991b1b;
    text-decoration: none;
    box-shadow: 0 6px 20px -4px rgba(220, 38, 38, 0.18),
                0 2px 6px -1px rgba(220, 38, 38, 0.10);
    animation: notifBannerSlide 0.25s ease-out;
    transition: transform .12s ease, box-shadow .18s ease, border-color .15s ease;
}
.notif-banner:hover {
    transform: translateY(-1px);
    border-color: #fca5a5;
    box-shadow: 0 10px 28px -4px rgba(220, 38, 38, 0.26),
                0 4px 10px -2px rgba(220, 38, 38, 0.14);
}
@keyframes notifBannerSlide {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.notif-banner__icon {
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(239, 68, 68, 0.16);
    color: #dc2626;
    display: grid;
    place-items: center;
    font-size: 20px;
    flex-shrink: 0;
    animation: notifBannerIconPulse 1.6s ease-in-out infinite;
}
@keyframes notifBannerIconPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.35); }
    50%      { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .notif-banner__icon { animation: none; }
}
.notif-banner__chev {
    transition: transform .14s ease;
}
.notif-banner:hover .notif-banner__chev {
    transform: translateX(3px);
}
.notif-banner__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.notif-banner__title { font-size: 14px; font-weight: 800; color: #991b1b; }
.notif-banner__sub   { font-size: 12px; color: #b91c1c; font-weight: 600; }
.notif-banner__chev  { font-size: 22px; color: #b91c1c; flex-shrink: 0; }
.notif-banner:active { transform: scale(0.99); }


/* ============================================
 * 79. SLOT-SPIN DATE PICKER  (June 20, 2026)
 *      Replaces native <input type="date"> with 3 scroll wheels.
 *      Wired by assets/js/date-picker.js — auto-attaches on page load.
 * ============================================ */

/* 🆕 Date picker is a SECONDARY sheet — opens on top of any primary sheet
   (Goal / Budget / Transaction). All sheets share z-index 210 by default,
   so DOM order decides stacking. The date picker partial is included in
   the global head, before page-specific sheets, meaning Goal/Budget would
   stack ABOVE it without this override. Bump z-index so the date picker
   always wins regardless of DOM order. */
#datePickerSheet { z-index: 240 !important; }

.dp { padding: 12px 14px 8px; }

/* 🆕 v3.1.0 Phase AF date-picker Round 1 — display preview as brand gradient
   hero (match budget-totals + setup-total hero pattern). */
.dp__display {
    text-align: center;
    font-size: 17px;
    font-weight: 800;
    color: #fff;
    background: var(--brand-gradient-deep);
    border: none;
    border-radius: 12px;
    padding: 14px 16px;
    margin: 0 0 14px;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    box-shadow: 0 6px 16px -4px rgba(37, 99, 235, 0.32),
                0 2px 6px -1px rgba(15, 23, 42, 0.12);
}

/* ===== MONTH / YEAR NAV ROW ===== */
.dp__nav {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
}
/* 🆕 v3.1.0 Phase AF date-picker Round 1 — month nav arrows: brand hover tint */
.dp__nav-btn {
    flex-shrink: 0;
    width: 38px; height: 38px;
    border: none;
    border-radius: 50%;
    background: var(--surface-2, #f1f5f9);
    color: var(--text-secondary, #475569);
    font-size: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background .18s ease, color .18s ease, transform .1s ease;
    -webkit-tap-highlight-color: transparent;
}
.dp__nav-btn:hover {
    background: rgba(37, 99, 235, 0.10);
    color: var(--brand-600, #2563eb);
}
.dp__nav-btn:active {
    background: rgba(37, 99, 235, 0.16);
    transform: scale(0.92);
}

.dp__nav-title {
    flex: 1;
    height: 38px;
    border: none;
    background: transparent;
    border-radius: 10px;
    font: inherit;
    font-size: 15px;
    font-weight: 700;
    color: #0f172a;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    cursor: pointer;
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.dp__nav-title:hover { background: rgba(15, 23, 42, 0.05); }
.dp__nav-title.is-active { background: rgba(59, 130, 246, 0.10); color: #2563eb; }
.dp__nav-title-caret { font-size: 18px; transition: transform 0.18s; }
.dp__nav-title.is-active .dp__nav-title-caret { transform: rotate(180deg); }

/* ===== CALENDAR VIEW ===== */
.dp__cal-view { /* default visible */ }

.dp__dow-row {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    margin-bottom: 4px;
}
.dp__dow {
    text-align: center;
    font-size: 11px;
    font-weight: 700;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 4px 0;
}

.dp__grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}
.dp__day {
    appearance: none;
    border: none;
    background: transparent;
    border-radius: 10px;
    aspect-ratio: 1;
    padding: 0;
    font: inherit;
    font-size: 14.5px;
    font-weight: 600;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
    transition: background 0.12s, color 0.12s, transform 0.12s;
    -webkit-tap-highlight-color: transparent;
}
/* 🆕 v3.1.0 Phase G13 — Hover only on real pointer devices (mouse/trackpad).
   Mobile browsers keep :hover state after tap, which overrode
   .dp__day--selected background → white text on light-grey = invisible. */
@media (hover: hover) {
    .dp__day:hover:not(.dp__day--selected) { background: rgba(15, 23, 42, 0.05); }
}
/* 🆕 v3.1.0 Phase AF date-picker Round 1 — day cells polish */
.dp__day:active { transform: scale(0.9); }
.dp__day--out { color: var(--border-light, #cbd5e1); font-weight: 500; }
.dp__day--today {
    color: var(--brand-600, #2563eb);
    font-weight: 800;
    background: rgba(37, 99, 235, 0.08);
}
.dp__day--today::after {
    content: '';
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    width: 5px; height: 5px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.14);
}
.dp__day--selected {
    background: var(--brand-gradient);
    color: #fff !important;
    font-weight: 800;
    box-shadow: 0 4px 14px rgba(37, 99, 235, 0.40),
                0 0 0 2px rgba(59, 130, 246, 0.22);
    animation: dpDaySelectPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.dp__day--selected.dp__day--today::after { background: #fff; box-shadow: none; }
@keyframes dpDaySelectPop {
    0%   { transform: scale(0.7); }
    60%  { transform: scale(1.12); }
    100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .dp__day--selected { animation: none; }
}

/* ===== YEAR PICKER VIEW (toggle) ===== */
.dp__year-view {
    max-height: 260px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    border-radius: 10px;
    background: rgba(15, 23, 42, 0.02);
    padding: 8px;
}
.dp__year-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}
.dp__year-btn {
    appearance: none;
    border: 1px solid transparent;
    background: #fff;
    border-radius: 10px;
    height: 44px;
    font: inherit;
    font-size: 15px;
    font-weight: 600;
    color: #0f172a;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, transform 0.12s;
    -webkit-tap-highlight-color: transparent;
}
.dp__year-btn:hover {
    background: rgba(59, 130, 246, 0.06);
    border-color: rgba(59, 130, 246, 0.30);
}
.dp__year-btn:active { transform: scale(0.96); }
.dp__year-btn.is-selected {
    background: var(--brand-gradient);
    color: #fff;
    font-weight: 800;
    border-color: transparent;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.30);
}

/* Shortcut chips */
.dp__shortcuts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    margin-top: 14px;
}
.dp__shortcut {
    appearance: none;
    border: 1px solid rgba(15, 23, 42, 0.10);
    background: #fff;
    color: #475569;
    font-size: 12.5px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    font-family: inherit;
}
.dp__shortcut:hover {
    background: rgba(59, 130, 246, 0.08);
    border-color: rgba(59, 130, 246, 0.30);
    color: #2563eb;
}
.dp__shortcut:active { transform: scale(0.96); }

@media (max-width: 380px) {
    .dp__day { font-size: 13.5px; }
    .dp__nav-title { font-size: 14px; }
    .dp__shortcut { padding: 5px 10px; font-size: 12px; }
}


/* ============================================
 * 80. GOAL — From-account search + list (June 20, 2026)
 *     Replaces native dropdown with search-filterable visible list.
 * ============================================ */
.goal-account-search {
    position: relative;
    margin-bottom: 8px;
}
.goal-account-search__icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: #94a3b8;
    font-size: 16px;
    pointer-events: none;
}
.goal-account-search__input {
    width: 100%;
    height: 36px;
    padding: 0 12px 0 36px;
    border-radius: 8px;
    border: 1px solid rgba(15, 23, 42, 0.10);
    background: #fff;
    font-size: 13.5px;
    font-family: inherit;
    color: #0f172a;
    transition: border-color 0.15s, box-shadow 0.15s;
    box-sizing: border-box;
    appearance: none;
    -webkit-appearance: none;
}
.goal-account-search__input:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.10);
}
.goal-account-search__input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* 🆕 Div-based account listbox — replaces <select size="6"> which iOS
   Safari renders as a single-line button (the `size` attribute is
   ignored when `appearance: none` is set). Guaranteed visible 6-row
   list on every platform. */
.goal-account-list {
    border: 1px solid rgba(15, 23, 42, 0.10);
    border-radius: 10px;
    background: #fff;
    padding: 4px;
    max-height: 240px;          /* ~6 items at 40px each */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}
.goal-account-list__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    margin: 0;
    border: none;
    background: transparent;
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
    color: #0f172a;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.12s ease;
}
.goal-account-list__item:hover {
    background: rgba(15, 23, 42, 0.04);
}
.goal-account-list__item:active {
    background: rgba(15, 23, 42, 0.08);
}
.goal-account-list__item.is-selected {
    background: #3b82f6;
    color: #fff;
    font-weight: 600;
}
.goal-account-list__item.is-selected:hover,
.goal-account-list__item.is-selected:active {
    background: #2563eb;
}
.goal-account-list__check {
    flex-shrink: 0;
    width: 18px;
    font-size: 18px;
    color: #fff;
    opacity: 0;            /* hidden unless selected */
}
.goal-account-list__item.is-selected .goal-account-list__check {
    opacity: 1;
}
.goal-account-list__name {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.goal-account-list__empty {
    padding: 18px;
    text-align: center;
    color: #94a3b8;
    font-style: italic;
    font-size: 13px;
}


/* ============================================
 * 81. GOAL ARCHIVE (completed + abandoned)
 *     Phase 2 — "Goal Completion Tracker" remark
 *     Shows completed/abandoned goals with drift verification.
 * ============================================ */

/* Toggle row above goal list */
.goal-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    margin: 8px 0;
    font-size: 12.5px;
    color: #64748b;
    user-select: none;
    cursor: pointer;
}
.goal-toggle input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: #3b82f6;
}
.goal-toggle:hover { color: #0f172a; }

/* 🆕 v3.1.0 Phase P §11 Round 5 — "Completed & abandoned (N) [›]" link row
   per draft §7 line 1616. Replaces the Phase C checkbox UX. */
.goal-archive-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    margin: 18px 0 10px;
    border: 1px solid var(--border-soft, #e2e8f0);
    border-radius: var(--r-md, 12px);
    background: var(--surface-1, #fff);
    color: var(--text-secondary, #5a6472);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.goal-archive-toggle:hover,
.goal-archive-toggle:focus-visible {
    background: var(--surface-2, #f8fafc);
    border-color: var(--border-light, #cbd5e1);
    color: var(--text-primary, #0f172a);
    outline: none;
}
.goal-archive-toggle__label { flex: 1; text-align: left; }
.goal-archive-toggle__count {
    min-width: 22px;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--brand-50, #eef2ff);
    color: var(--brand-600, #2563eb);
    font-size: 11.5px;
    font-weight: 700;
    text-align: center;
}
.goal-archive-toggle__chev {
    font-size: 20px;
    color: var(--text-muted, #b8c0cc);
    transition: transform .22s ease;
}
.goal-archive-toggle[aria-expanded="true"] .goal-archive-toggle__chev {
    transform: rotate(90deg);
}

/* Archive list — dim, separated visually */
.goal-list--archive {
    margin-top: 8px;
    opacity: 0.85;
}
.goal-card--archive {
    background: rgba(15, 23, 42, 0.025);
    border-color: rgba(15, 23, 42, 0.06);
}
.goal-card--archive .goal-card__title { color: #475569; }
.goal-card--archive .goal-card__sub { color: #94a3b8; }

/* COMPLETED / ABANDONED tag */
.goal-archive-tag {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    border: 1px solid currentColor;
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: 0.06em;
    vertical-align: 1px;
    background: rgba(255, 255, 255, 0.6);
}

/* Inline empty state for archive */
.goal-empty--inline {
    list-style: none;
    text-align: center;
    padding: 18px;
    color: #94a3b8;
    font-size: 13px;
    font-style: italic;
}


/* ============================================
 * 82. LOGIN HISTORY (Security page) — June 20, 2026
 *     Shows recent sign-ins/outs with IP + device.
 *     Warns when IP looks like Docker NAT (proxy misconfig).
 * ============================================ */

.login-history {
    margin: 8px 0 24px;
    padding: 12px;
}

/* 🆕 v3.1.0 Phase W §14 Security Round 2 — "Your current IP" banner.
   Icon lifted into its own 40px rounded-square tile (matches .list-item__icon)
   with a subtle brand glow. Banner itself stays airy with soft brand-tint. */
.login-history__current {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(6, 182, 212, 0.06) 100%);
    border: 1px solid rgba(59, 130, 246, 0.18);
    border-radius: 12px;
    margin-bottom: 12px;
    box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.10);
}
.login-history__current i {
    width: 40px;
    height: 40px;
    border-radius: 11px;
    background: var(--brand-50, #eef2ff);
    color: var(--brand-600, #2563eb);
    font-size: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.14);
}
.login-history__current-label {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-secondary, #475569);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.login-history__current-ip {
    margin: 2px 0 0;
    font-family: 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary, #0f172a);
    font-variant-numeric: tabular-nums;
}
.login-history__current-ip--warn { color: #dc2626; }

/* 🆕 v3.1.0 Phase W §14 Security Round 2 — proxy warning banner uses the
   same amber-tint palette as Health warning cards for severity consistency. */
.login-history__proxy-warn {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    background: #fffbeb;
    border: 1.5px solid #fde68a;
    border-left: 4px solid #f59e0b;
    border-radius: 10px;
    color: #78350f;
    font-size: 12.5px;
    line-height: 1.5;
    margin-bottom: 12px;
    box-shadow: 0 2px 8px -2px rgba(245, 158, 11, 0.14);
}
.login-history__proxy-warn i {
    font-size: 20px;
    color: #d97706;
    flex-shrink: 0;
    margin-top: 1px;
}
.login-history__proxy-warn code {
    background: rgba(120, 53, 15, 0.08);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 12px;
    font-family: 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace;
}

/* 🆕 v3.1.0 Phase W §14 Round 7 — Recent login activity redesign.
   User call: cards felt "thick"; want smoother/airier look. Switched to
   borderless rows with hairline dividers (list-item primitive), tiny
   round status icons on the left, type-tinted — reads as a quick timeline. */
.login-history__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0;
}
.login-history__row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    border-bottom: 1px solid var(--border-soft, #eef1f5);
    transition: background .14s ease;
}
.login-history__row:last-child { border-bottom: 0; }
.login-history__row:hover      { background: var(--surface-2, #f8fafc); }

/* The login/logout icon on the left becomes a tiny status pill (28×28) so
   the row reads lighter but still carries the color-coded cue. */
.login-history__icon {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 14px;
    background: rgba(16, 185, 129, 0.12);     /* default = login (green) */
    color: #059669;
    margin-top: 2px;
}
/* Logout rows: grey (JS attaches .bx-log-out-circle on the <i> element) */
.login-history__row .bx-log-out-circle.login-history__icon,
.login-history__row .bx-log-out.login-history__icon {
    background: var(--surface-2, #f1f5f9);
    color: var(--text-muted, #64748b);
}
/* Failed login rows: red */
.login-history__row--fail {
    background: transparent;
    border-color: var(--border-soft, #eef1f5);
}
.login-history__row--fail .login-history__icon {
    background: rgba(239, 68, 68, 0.12);
    color: #dc2626;
}
.login-history__row--fail:hover { background: #fef2f2; }

/* 🆕 v3.1.0 Phase W §14 Round 7 — body text styling (airy, timeline-like). */
.login-history__body { flex: 1; min-width: 0; }
.login-history__line {
    margin: 0;
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-primary, #1e293b);
}
.login-history__line strong { font-weight: 700; }
.login-history__line--sub {
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--text-muted, #64748b);
    font-weight: 500;
}
.login-history__line--time {
    margin-top: 3px;
    font-size: 11px;
    color: var(--text-muted, #94a3b8);
    font-variant-numeric: tabular-nums;
}
.login-history__ip {
    font-family: 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace;
    font-size: 11px;
    color: var(--text-secondary, #475569);
    font-variant-numeric: tabular-nums;
}
.login-history__ip--private {
    color: #b45309;
    font-style: italic;
}
.login-history__fail-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 6px;
    background: #fef2f2;
    color: #dc2626;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    vertical-align: middle;
}


/* ============================================
 * 83. WIZARD — "Just added" highlight pulse
 *     Briefly tints + pulses a newly-added row so user spots it
 *     after creating an account inside the wizard.
 * ============================================ */
.setup-row--just-added {
    animation: setupRowAdded 2.2s ease-out;
    position: relative;
    z-index: 1;
}
@keyframes setupRowAdded {
    0%   { background: rgba(59, 130, 246, 0.20); box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.30); border-color: #3b82f6; transform: scale(1.02); }
    20%  { background: rgba(59, 130, 246, 0.12); box-shadow: 0 0 0 6px rgba(59, 130, 246, 0.18); transform: scale(1); }
    100% { background: #fff;                     box-shadow: 0 0 0 0   rgba(59, 130, 246, 0); }
}


/* ============================================
 * 84. EDIT ACCOUNT — Status hint (Option A single-source-of-truth)
 *     Deactivate button removed; Status toggle owns soft-delete.
 *     Hint text tints amber when toggle is OFF.
 * ============================================ */
.acct-active-hint {
    margin: 8px 0 0;
    font-size: 12px;
    color: #94a3b8;
    line-height: 1.5;
}
.acct-active-hint--warn {
    color: #b45309;
    background: rgba(245, 158, 11, 0.10);
    border-left: 3px solid #f59e0b;
    padding: 6px 10px;
    border-radius: 6px;
}


/* ============================================
 * 85. APP-SHEET FOOTER — Budget variant (Delete + Save only)
 *     Cancel was removed (✕ at top-right of sheet replaces it).
 *
 *     Edit mode: Delete (red, 1fr) | Save (blue, 1fr)
 *     Add mode:  Delete[hidden] → Save spans full width
 * ============================================ */
.app-sheet__footer.app-sheet__footer--budget {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;     /* equal halves */
    grid-template-areas: "del save" !important;
    gap: 10px !important;
    padding-top: 12px;
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
}

/* Place each visible button in its grid cell — override base "> button { flex:1 }" */
.app-sheet__footer.app-sheet__footer--budget > #budgetDelete,
.app-sheet__footer.app-sheet__footer--budget > #budgetCancel {
    grid-area: del !important;
    flex: none !important;
    width: auto !important;
}
.app-sheet__footer.app-sheet__footer--budget > #budgetSave {
    grid-area: save !important;
    flex: none !important;
    width: auto !important;
}

/* 🆕 EDIT mode — Delete visible, Cancel hidden */
.app-sheet__footer.app-sheet__footer--budget:has(> #budgetDelete:not([hidden])) > #budgetCancel {
    display: none !important;
}

/* 🆕 ADD mode — Delete hidden, Cancel visible → grid still 2-col (Cancel | Save) */
.app-sheet__footer.app-sheet__footer--budget:has(> #budgetDelete[hidden]) > #budgetCancel {
    display: inline-flex !important;
}

/* 🔴 SOLID RED Delete button — was missing from CSS earlier (file truncated).
   .pw-btn--danger has no definition anywhere else in the stylesheet, so we
   declare BOTH a generic .pw-btn--danger (any future use) AND the high-spec
   selector inside the budget footer. */
.pw-btn--danger {
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    color: #fff;
    border: none;
    box-shadow: 0 2px 8px rgba(220, 38, 38, 0.32);
}
.pw-btn--danger:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(220, 38, 38, 0.44);
}
.pw-btn--danger:active:not(:disabled) { transform: scale(0.98); }
.pw-btn--danger i { color: #fff; }

/* Higher-specificity duplicate to win over any future override inside footer */
.app-sheet__footer.app-sheet__footer--budget > .pw-btn--danger {
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important;
    color: #fff !important;
    border: none !important;
    box-shadow: 0 2px 8px rgba(220, 38, 38, 0.32) !important;
}
.app-sheet__footer.app-sheet__footer--budget > .pw-btn--danger:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(220, 38, 38, 0.44) !important;
}
.app-sheet__footer.app-sheet__footer--budget > .pw-btn--danger:active:not(:disabled) {
    transform: scale(0.98);
}

/* ============================================
 * 86. TX VIEW SCREEN — read-only display in Edit Tx sheet
 *     Shown FIRST when opening an existing tx; Edit button navigates
 *     to the form screen. Mirrors the Edit Account view-mode pattern.
 * ============================================ */

/* 🆕 VIEW-FIRST MODE — when #addSheet has .is-edit-view, hide every other
   screen and force the view screen to be the only visible one. This is a
   simple class-toggle approach that sidesteps screen-stack quirks (race
   conditions on push, leftover is-prev/is-active classes, transition
   timing, etc.). The class is added in openEditTransaction() and removed
   either when the user taps Edit (revealing the form) or when the sheet
   closes (for the next Add Tx flow). */
.app-sheet.is-edit-view .tx-screen:not(.tx-screen--view) {
    display: none !important;
}
.app-sheet.is-edit-view .tx-screen--view {
    display: flex !important;
    position: absolute !important;
    inset: 0 !important;
    visibility: visible !important;
    background: #ffffff !important;
    z-index: 5;
}

/* 🆕 PURE RIGHT-TO-LEFT SLIDE for view-first entry.
   The sheet itself appears WITHOUT its usual bottom-up animation
   (translateY skip) so only the View slides horizontally → user perceives
   a clean right-to-left page push instead of a diagonal corner motion. */
.app-sheet.is-edit-view.is-open .app-sheet__panel {
    /* Skip the bottom-up slide — panel jumps straight to translateY(0)
       so the only motion the user sees is the View screen sliding in. */
    transform: translateY(0) !important;
    transition: none !important;
}

/* View starts off-screen right, slides to center in 0.28s — the only
   visible entry animation. */
.app-sheet.is-edit-view .tx-screen--view {
    transform: translateX(100%);
    transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}
.app-sheet.is-edit-view.is-open .tx-screen--view {
    transform: translateX(0) !important;
}

/* Default state: view screen hidden (only shown via .is-edit-view) */
.tx-screen--view {
    background: #ffffff;
}

/* HERO band — type chip + big amount + date */
.tx-view__hero {
    text-align: center;
    padding: 20px 8px 18px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
    margin-bottom: 16px;
}
.tx-view__type-chip {
    display: inline-block;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.10em;
    margin-bottom: 8px;
    background: rgba(15, 23, 42, 0.06);
    color: #475569;
}
.tx-view__type-chip--expense  { background: rgba(239, 68, 68, 0.12); color: #b91c1c; }
.tx-view__type-chip--income   { background: rgba(16, 185, 129, 0.14); color: #047857; }
.tx-view__type-chip--transfer { background: rgba(59, 130, 246, 0.12); color: #1d4ed8; }
.tx-view__type-chip--custom   { background: rgba(168, 85, 247, 0.12); color: #6b21a8; }
.tx-view__type-chip--opening  { background: rgba(245, 158, 11, 0.14); color: #92400e; }

.tx-view__amount {
    margin: 4px 0;
    font-size: 32px;
    font-weight: 800;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.tx-view__date {
    margin: 0;
    font-size: 13px;
    color: #64748b;
    font-weight: 500;
}

/* Sections */
.tx-view__section { margin-bottom: 16px; padding: 0 4px; }
.tx-view__section-label {
    margin: 0 0 8px;
    font-size: 11px;
    font-weight: 700;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* Note text */
.tx-view__note {
    margin: 0;
    padding: 12px 14px;
    background: rgba(15, 23, 42, 0.03);
    border-radius: 10px;
    font-size: 14px;
    line-height: 1.5;
    color: #0f172a;
    white-space: pre-wrap;
}

/* Per-line breakdown — each line = account + Dr/Cr + amount */
.tx-view__lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.tx-view__line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid rgba(15, 23, 42, 0.08);
    border-radius: 12px;
}
.tx-view__line-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tx-view__line-name {
    font-size: 14px;
    font-weight: 600;
    color: #0f172a;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tx-view__line-sub {
    font-size: 11.5px;
    color: #94a3b8;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.tx-view__line-amt {
    font-size: 14.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
.tx-view__line-amt--dr { color: #047857; }
.tx-view__line-amt--cr { color: #b45309; }

/* Receipts */
.tx-view__receipts {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
.tx-view__receipt {
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 10px;
    background: #f1f5f9;
    border: 1px solid rgba(15, 23, 42, 0.06);
    transition: transform 0.15s, box-shadow 0.15s;
    padding: 0;                    /* reset <button> padding */
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.tx-view__receipt img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
}
.tx-view__receipt:hover {
    transform: scale(1.02);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.12);
}
.tx-view__receipt:active {
    transform: scale(0.98);
}

/* Reference/meta footer row */
.tx-view__meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 18px;
    padding: 12px 14px;
    background: rgba(15, 23, 42, 0.03);
    border-radius: 10px;
}
.tx-view__meta-label {
    font-size: 11px;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
}
.tx-view__meta-value {
    font-family: 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace;
    font-size: 12.5px;
    color: #475569;
    font-weight: 600;
}

/* Footer for view screen — Delete (left, red) + Close (right, ghost).
   2-column grid, equal split, 12px gap. Padding inherited from base
   .tx-screen__footer (12 / 22 / 16 + safe-area). */
.tx-screen__footer--view {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    align-items: stretch;
}
.tx-screen__footer--view .pw-btn {
    width: 100%;
    min-width: 0;     /* override .pw-btn--primary's min-width:160px just in case */
}

/* ================================================================
   🆕 v3.1.0 Phase I §8 — Account Detail page (account-detail.php)
   Draft §8 Hi-Fi 2a/2b · drill-in from accounts list
   Header: title + Edit pill + close X · body: name/badge/about/tx-month-list
================================================================ */
.acct-detail {
    /* 🆕 Phase I §8 fix — same tab-bar safe padding as other pages
       (previous `padding: 0` overrode .app-main's default, hiding last TX
       behind the tab bar) */
    padding: 0 0 var(--tab-bar-safe);
}
.acct-detail__header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 18px 10px;
    border-bottom: 1.5px solid #eaedf1;
    background: var(--surface-1, #fff);
    position: sticky;
    top: 0;
    z-index: 10;
}
.acct-detail__title {
    flex: 1;
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: #3a4250;
    line-height: 1.2;
}
.acct-detail__edit-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 36px;
    padding: 0 16px;
    border: 1.5px solid #d3d9e0;
    border-radius: 99px;
    background: var(--surface-1, #fff);
    color: #5a6472;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s;
}
.acct-detail__edit-btn:hover  { background: #f1f5f9; border-color: #94a3b8; }
.acct-detail__edit-btn:active { transform: scale(0.98); }
.acct-detail__edit-btn i      { font-size: 15px; }

.acct-detail__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: #f8fafc;
    color: #64748b;
    text-decoration: none;
    font-size: 20px;
    cursor: pointer;
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.acct-detail__close:hover  { background: #e2e8f0; color: #0f172a; }
.acct-detail__close:active { transform: scale(0.95); }

.acct-detail__body {
    padding: 14px 18px 24px;
}

.acct-detail__name {
    margin: 0 0 6px;
    font-size: 19px;
    font-weight: 700;
    color: #1e293b;
    line-height: 1.3;
}
.acct-detail__id {
    margin: 0 0 12px;
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: 11px;
    color: #94a3b8;
    letter-spacing: 0.02em;
}

.acct-detail__badges {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.acct-detail__badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 99px;
    font-size: 11.5px;
    font-weight: 700;
}
.acct-detail__badge i { font-size: 13px; }
.acct-detail__badge.badge--asset   { background: #eef2ff; color: #2563eb; }
.acct-detail__badge.badge--liab    { background: #fef2f2; color: #dc2626; }
.acct-detail__badge.badge--equity  { background: #f5f3ff; color: #7c3aed; }
.acct-detail__badge.badge--revenue { background: #f0fdf4; color: #16a34a; }
.acct-detail__badge.badge--expense { background: #fef2f2; color: #dc2626; }
.acct-detail__badge-sep {
    display: inline-block;
    width: 1px;
    height: 11px;
    background: currentColor;
    opacity: 0.35;
}
.acct-detail__status-dot        { font-size: 6px; }
.acct-detail__status-dot.is-active   { color: #16a34a; }
.acct-detail__status-dot.is-inactive { color: #94a3b8; }

.acct-detail__balance {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: 15px;
    font-weight: 700;
    color: #1e293b;
    letter-spacing: 0.01em;
    font-variant-numeric: tabular-nums;
}

.acct-detail__section-label {
    margin: 0 0 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--pf-muted-2, #94a3b8);
    text-transform: uppercase;
    letter-spacing: 0.6px;
}

/* About — clamp 2 lines + "แสดงเพิ่มเติม" button */
.acct-detail__about {
    margin-bottom: 16px;
}
.acct-detail__about-text {
    margin: 0 0 4px;
    font-size: 13px;
    line-height: 1.5;
    color: #4a5260;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* Fully expanded */
.acct-detail__about[data-expanded="true"] .acct-detail__about-text {
    -webkit-line-clamp: unset;
    display: block;
}
/* Measurement helper (JS removes after reading scrollHeight) */
.acct-detail__about-text.is-measuring {
    -webkit-line-clamp: unset;
    display: block;
}
.acct-detail__about-more {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 0;
    background: transparent;
    border: none;
    color: #5a6472;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.acct-detail__about-more i { font-size: 16px; }
.acct-detail__about-more:hover { color: #0f172a; }

.acct-detail__divider {
    border-top: 1.5px solid #eaedf1;
    margin: 14px 0;
}

/* Month pager — 4 months visible + prev/next chevrons */
.acct-detail__month-pager {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 12px;
}
.acct-detail__month-nav {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: none;
    color: #8a94a3;
    font-size: 20px;
    cursor: pointer;
    border-radius: 6px;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.acct-detail__month-nav:hover:not(:disabled)  { background: #f1f5f9; color: #0f172a; }
.acct-detail__month-nav:active:not(:disabled) { transform: scale(0.95); }
.acct-detail__month-nav:disabled { opacity: 0.4; cursor: not-allowed; }

.acct-detail__month-row {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
}
.acct-detail__month {
    padding: 6px 0;
    border: 1.5px solid #d3d9e0;
    border-radius: 8px;
    background: var(--surface-1, #fff);
    color: #8a94a3;
    font-size: 12.5px;
    font-weight: 600;
    text-align: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.acct-detail__month:hover  { border-color: #94a3b8; color: #4a5260; }
.acct-detail__month:active { transform: scale(0.98); }
.acct-detail__month.is-active {
    background: #2563eb;
    border-color: #2563eb;
    color: #fff;
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.2);
}

/* 🆕 v3.1.0 Phase I §8 rev — TX list reuses .card.card--list + .list-item structure
   (same as transactions.php / Activity page). Date header + items share one bordered
   container → "same box" feel · negative amount red via .money--expense.
   Scoped tweaks on this page: darker date header + spacing + smooth entrance. */
.acct-detail .acct-detail__tx-list {
    margin-top: 4px;
    /* Smooth fade when switching months (JS toggles .is-switching) */
    transition: opacity 180ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.acct-detail .acct-detail__tx-list.is-switching {
    opacity: 0;
}
/* ================================================================
   🆕 v3.1.0 Phase M §10 — Accounts page polish (draft §8)
   - Group header pill (count + subtotal for Asset/Liability/Equity)
   - Icon color tint per account type
   - Compact row · scoped to body.page-accounts
================================================================ */
/* 🆕 v3.1.0 Phase T §2 — flush edge-to-edge like #txList .list-group__header
   (user call: pill with rounded corners + border looked out of place vs the
   Activity day-pill). Keeps the subtotal content on the right because that's
   the information value Accounts has over Activity. */
.page-accounts .acct-group-header {
    display: flex;
    align-items: center;
    gap: 10px;                     /* 🆕 anchors label close to the dot on the left */
    padding: 8px 14px;
    background: #f1f5f9;           /* 🆕 soft slate — same as Activity day-pill */
    border: none;                  /* 🆕 border removed */
    border-radius: 0;              /* 🆕 flush edges */
    border-bottom: 1px solid var(--border-soft, #e2e8f0);
    margin: 0 0 0 0;               /* no top/bottom gap — flush with rows */
    position: static;              /* override sticky inherited from .list-group__header */
    text-transform: none;
    letter-spacing: 0;
    min-height: 48px;              /* match Activity day-pill height */
}
/* 🆕 Phase T §2 — brand-blue dot anchor on the left (mirrors Activity's
   .list-group__header::before). Gives the label a clear "left anchor"
   instead of looking centered inside its padding. */
.page-accounts .acct-group-header::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: var(--brand-500, #3b82f6);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
    flex-shrink: 0;
}
/* The total (right side) uses auto-margin so the dot+label stay on the left
   and the subtotal is pushed to the far right. Cleaner than space-between
   because the ::before pseudo-element is now part of the flex row. */
.page-accounts .acct-group-header__total {
    margin-left: auto;
}
.page-accounts > .card--list .acct-group-header:first-child { margin-top: 0; }
.page-accounts .acct-group-header__label {
    font-size: 11px;
    font-weight: 600;
    color: #64748b;
    letter-spacing: 0.04em;
}
.page-accounts .acct-group-header__total {
    font-size: 12.5px;
    font-weight: 700;
    color: #1e293b;
    font-variant-numeric: tabular-nums;
}
.page-accounts .acct-group-header__total.is-liability { color: #dc2626; }

/* Icon color tint per type (scoped to accounts page only) */
.page-accounts .list-item[data-type="1"] .list-item__icon { background: #eef2ff; color: #2563eb; } /* Asset */
.page-accounts .list-item[data-type="2"] .list-item__icon { background: #fef2f2; color: #dc2626; } /* Liability */
.page-accounts .list-item[data-type="3"] .list-item__icon { background: #f5f3ff; color: #8b5cf6; } /* Equity */
.page-accounts .list-item[data-type="4"] .list-item__icon { background: #f0fdf4; color: #16a34a; } /* Revenue */
.page-accounts .list-item[data-type="5"] .list-item__icon { background: #fef2f2; color: #dc2626; } /* Expense */

/* Compact row — match Account Detail style */
.page-accounts .list-item { gap: 12px; padding: 10px 14px; }
.page-accounts .list-item__icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    font-size: 18px;
}
.page-accounts .list-item__title {
    font-size: 14px;
    font-weight: 600;
    color: #1e293b;
}
.page-accounts .list-item__subtitle {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: 11px;
    color: #94a3b8;
    margin-top: 2px;
}
/* 🆕 v3.1.0 Phase T §2 — divider removed. Phase S Round 5's
   `.card--list > .list-item { border-bottom: 1px }` already draws the single
   hairline we need between accounts rows; keeping this border-top was
   stacking (2px thick, didn't look smooth). */

/* Scoped card--list polish — flush edges + softer radius (same as TX lists) */
#accList.card--list {
    padding: 0;
    border-radius: 16px;
    overflow: hidden;
}

/* 🆕 v3.1.0 Phase N §12 rev — Reports two-row period widget
   Row 1: Month pager (4 visible · chevron nav)
   Row 2: Scope chips (Month · 3M · 6M · All) */
.rpt-period-wrap {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: var(--space-3);
}
.rpt-month-pager {
    display: flex;
    align-items: center;
    gap: 6px;
}
.rpt-month-nav {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: transparent;
    border: none;
    color: #8a94a3;
    font-size: 20px;
    cursor: pointer;
    border-radius: 6px;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms, color 140ms;
}
.rpt-month-nav:hover:not(:disabled)  { background: #f1f5f9; color: #0f172a; }
.rpt-month-nav:active:not(:disabled) { transform: scale(0.95); }
.rpt-month-nav:disabled              { opacity: 0.3; cursor: not-allowed; }
.rpt-month-row {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
}
.rpt-month {
    padding: 6px 0;
    border: 1.5px solid #d3d9e0;
    border-radius: 8px;
    background: var(--surface-1, #fff);
    color: #8a94a3;
    font-size: 12.5px;
    font-weight: 600;
    text-align: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms, color 140ms, border-color 140ms, opacity 140ms;
}
/* 🆕 2026-10-23 — add :not(.is-active) so hover doesn't repaint the
   selected chip's white text to gray. Hover selector was more specific
   (3 classes) than .rpt-month.is-active (2 classes), so hovering the
   current month flipped it to the hover color. */
.rpt-month:hover:not(.is-disabled):not(.is-active)  { border-color: #94a3b8; color: #4a5260; }
.rpt-month:active:not(.is-disabled) { transform: scale(0.98); }
/* 🆕 v3.1.0 Phase R Round 4 — active month chip uses the same brand gradient
   + glow as .period-tabs__btn.is-active for a consistent "selected" language
   across every tab/chip surface. Subtle pop-in animation on first render so
   switching months feels responsive. */
.rpt-month.is-active {
    background: var(--brand-gradient);
    border-color: transparent;
    color: #fff;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.32);
    animation: rptMonthPop 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes rptMonthPop {
    from { transform: scale(0.94); }
    to   { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .rpt-month.is-active { animation: none; }
}
.rpt-month.is-disabled {
    opacity: 0.45;
    cursor: default;
}

/* Scope row (uses .period-tabs base · just resets any sticky from Phase G14) */
.rpt-scope { position: static !important; }

/* 🆕 Phase M §10 — Jump nav pager (3 chips visible · 5 total · chevrons + swipe) */
.page-accounts .acct-jump-wrap {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: var(--space-3);
}
.page-accounts .acct-jump-nav {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: transparent;
    border: none;
    color: #8a94a3;
    font-size: 20px;
    cursor: pointer;
    border-radius: 6px;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms, color 140ms;
}
.page-accounts .acct-jump-nav:hover:not(:disabled)  { background: #f1f5f9; color: #0f172a; }
.page-accounts .acct-jump-nav:active:not(:disabled) { transform: scale(0.95); }
.page-accounts .acct-jump-nav:disabled              { opacity: 0.3; cursor: not-allowed; }

.page-accounts .period-tabs--pager {
    flex: 1;
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding: 2px 0;   /* room for focus ring */
}
.page-accounts .period-tabs--pager::-webkit-scrollbar { display: none; }
.page-accounts .period-tabs--pager > .period-tabs__btn {
    /* 3 chips visible at a time (minus 2 gaps of 6px) */
    flex: 0 0 calc((100% - 12px) / 3);
    scroll-snap-align: start;
    white-space: nowrap;
    text-align: center;
}

/* ================================================================
   🆕 v3.1.0 Phase L §16 — Placeholder page (forgot-password, signup)
   Minimal info page with icon · title · body · hint box · back link
================================================================ */
.placeholder-page {
    text-align: center;
    padding: 32px 24px 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}
.placeholder-page__icon {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: #eef2ff;
    color: #2563eb;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 2px;
}
.placeholder-page__icon i { font-size: 36px; }
.placeholder-page__title {
    margin: 0;
    font-size: 20px;
    font-weight: 700;
    color: #0f172a;
}
.placeholder-page__text {
    margin: 0;
    font-size: 13.5px;
    color: #4a5260;
    line-height: 1.55;
    max-width: 320px;
}
.placeholder-page__hint {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 14px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    color: #64748b;
    font-size: 12px;
    line-height: 1.45;
    text-align: left;
    max-width: 320px;
    width: 100%;
}
.placeholder-page__hint i { font-size: 16px; color: #94a3b8; flex-shrink: 0; margin-top: 1px; }
.placeholder-page__back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    min-width: 200px;
    justify-content: center;
    text-decoration: none;
}
.placeholder-page__back i { font-size: 18px; }

/* ================================================================
   🆕 v3.1.0 Phase K §18 — Biometric-on-Open Lock overlay
   Full-screen overlay shown by assets/js/bio-lock.js when idle expired.
================================================================ */
.bio-lock-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(248, 250, 252, 0.92);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    animation: bioLockFadeIn 180ms ease-out;
}
@keyframes bioLockFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.bio-lock-overlay[hidden] { display: none !important; }

/* Prevent background scrolling while overlay is up */
body.bio-lock-active {
    overflow: hidden;
}

/* iOS task-switcher screenshot guard — hide all content when tab hidden.
   🆕 v3.1.1 rev3 — switched from `filter: blur(16px)` to `visibility: hidden`.
   `filter: blur` promoted the body to a GPU composite layer that iOS Safari
   mis-sampled on first paint — causing the "fuzzy top on every page" the
   user reported for a week. The composite layer stayed around even after
   bio-lock.js removed the class, so the fuzz persisted until a modal/sheet
   forced a recomposite. `visibility: hidden` achieves the same security
   goal (iOS task-switcher screenshot shows blank, not account data) with
   zero rendering overhead — same pattern Facebook / mobile banking apps
   use. */
body.bio-lock-blur > *:not(#bioLockOverlay) {
    visibility: hidden;
}

.bio-lock__card {
    width: 100%;
    max-width: 320px;
    text-align: center;
    padding: 32px 28px 24px;
    background: var(--surface-1, #fff);
    border: 1px solid #eef1f5;
    border-radius: 20px;
    box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
}

.bio-lock__icon-wrap {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    margin: 0 auto 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #eef2ff;
    color: #2563eb;
    animation: bioLockPulse 2s ease-in-out infinite;
}
.bio-lock__icon-wrap i { font-size: 36px; }
@keyframes bioLockPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.25); }
    50%      { box-shadow: 0 0 0 14px rgba(37, 99, 235, 0); }
}

.bio-lock__title {
    margin: 0 0 6px;
    font-size: 18px;
    font-weight: 700;
    color: #0f172a;
}
.bio-lock__sub {
    margin: 0 0 20px;
    font-size: 13px;
    color: #64748b;
    line-height: 1.5;
}
.bio-lock__error {
    margin: 0 0 14px;
    padding: 8px 12px;
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.25);
    border-radius: 10px;
    color: #b91c1c;
    font-size: 12.5px;
    line-height: 1.4;
}

.bio-lock__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    height: 46px;
    padding: 0 20px;
    border: none;
    border-radius: 12px;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
    transition: transform 120ms, box-shadow 160ms, filter 160ms;
    -webkit-tap-highlight-color: transparent;
}
.bio-lock__btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(59, 130, 246, 0.38);
}
.bio-lock__btn:active:not(:disabled) { transform: translateY(0) scale(0.99); }
.bio-lock__btn:disabled              { opacity: 0.6; cursor: not-allowed; }
.bio-lock__btn i { font-size: 18px; }

.bio-lock__link {
    display: inline-block;
    margin-top: 14px;
    padding: 6px 10px;
    background: transparent;
    border: none;
    color: #64748b;
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
    -webkit-tap-highlight-color: transparent;
}
.bio-lock__link:hover { color: #dc2626; }

/* ================================================================
   🆕 v3.1.0 Phase J §15 — Settings page (settings.php)
   Draft §16 Hi-Fi · 5 sections (General · Privacy · Notifications · Data · About)
================================================================ */
.settings-page {
    /* 🆕 Phase J §15 fix — include tab-bar height so last row isn't hidden under tab bar */
    padding: 0 18px calc(var(--tab-bar-safe) + var(--space-6));
}
.settings-page .page-header {
    padding: 16px 0 10px;
    border-bottom: none;
    margin-bottom: 8px;
}

/* Section title — "GENERAL" / "PRIVACY & SECURITY" / etc. */
.settings-section-title {
    margin: 18px 2px 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: #94a3b8;
    text-transform: uppercase;
}
.settings-section-title:first-of-type {
    margin-top: 4px;
}

/* Section card — groups related rows */
/* 🆕 v3.1.0 Phase U settings polish — brand-tinted lift matching .card primitive. */
.settings-card {
    background: var(--surface-1, #fff);
    border: 1px solid var(--border-soft, #eef1f5);
    border-radius: var(--r-xl, 16px);
    overflow: hidden;
    margin-bottom: 16px;
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}

/* Row — one preference per row */
.settings-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid #eef1f5;
    text-decoration: none;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: background 140ms;
}
.settings-row:last-child {
    border-bottom: none;
}
/* 🆕 v3.1.0 Phase U Round 4 — tappable row affordance (hover bg + chevron
   nudge + a11y focus ring). Mirrors the .list-item hover pattern from
   Phase S Round 6 so Settings and the global list-item primitive feel like
   one family. */
.settings-row--link {
    cursor: pointer;
}
.settings-row--link:hover  { background: #f8fafc; }
.settings-row--link:active { background: #f1f5f9; }
.settings-row--link:focus-visible {
    outline: 2px solid var(--brand-500, #3b82f6);
    outline-offset: -2px;
    border-radius: 10px;
}
.settings-row--link .settings-row__chevron {
    transition: color .14s ease, transform .14s ease;
}
.settings-row--link:hover .settings-row__chevron {
    color: var(--text-muted, #94a3b8);
    transform: translateX(2px);
}
.settings-row--disabled {
    opacity: 0.6;
    pointer-events: none;
}
/* 🆕 v3.1.0 Phase U Round 5 — settings-row--danger strengthened to full
   danger affordance (soft-red bg + red icon tile + bold red title). Matches
   the Sign-out card pattern on More (Phase S Round 2) so destructive rows
   read the same way wherever they appear. */
.settings-row--danger {
    background: #fef2f2;
}
.settings-row--danger:hover { background: #fee2e2; }
.settings-row--danger .settings-row__title {
    color: #dc2626;
    font-weight: 700;
}
.settings-row--danger .settings-row__sub { color: #ef4444; opacity: 0.75; }
.settings-row--danger .settings-row__icon,
.settings-row--danger .settings-row__icon--red,
.settings-row--danger .settings-row__icon--grey {
    background: #fee2e2;
    color: #dc2626;
}
.settings-row--danger .settings-row__chevron { color: #fca5a5; }

/* 🆕 Phase K §18 — row with disabled toggle (eg bio-lock needs WebAuthn first) */
.settings-row--guard .pf-switch { opacity: 0.5; cursor: not-allowed; }
.settings-row--guard .pf-switch:hover { background: #e2e8f0; }   /* no color on hover */
/* 🆕 v3.1.0 Phase U Round 5 — inline brand link with animated underline grow. */
.settings-link {
    color: var(--brand-600, #2563eb);
    text-decoration: none;
    font-weight: 600;
    position: relative;
    transition: color .14s ease;
}
.settings-link::after {
    content: '';
    position: absolute;
    left: 0;
    right: 100%;
    bottom: -1px;
    height: 1.5px;
    background: var(--brand-500, #3b82f6);
    transition: right .22s cubic-bezier(0.16, 1, 0.3, 1);
}
.settings-link:hover::after { right: 0; }
.settings-link:hover       { color: var(--brand-700, #1d4ed8); }

/* Row icon box — 🆕 Phase U — bumped 32→36 to match .list-item__icon global
   tile size, so Settings rows feel part of the same primitive family. */
.settings-row__icon {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 18px;
    background: var(--surface-2, #f1f5f9);
    color: #64748b;
}
.settings-row__icon--blue   { background: #eef2ff; color: #2563eb; }
.settings-row__icon--green  { background: #f0fdf4; color: #16a34a; }
.settings-row__icon--amber  { background: #fffbeb; color: #d97706; }
.settings-row__icon--purple { background: #f5f3ff; color: #7c3aed; }
.settings-row__icon--red    { background: #fef2f2; color: #dc2626; }
.settings-row__icon--grey   { background: #f8fafc; color: #64748b; }

/* Row body — stacked title + subtitle */
.settings-row__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.settings-row__title {
    margin: 0;
    font-size: 13.5px;
    font-weight: 600;
    color: #1e293b;
    display: flex;
    align-items: center;
    gap: 6px;
}
.settings-row__sub {
    margin: 0;
    font-size: 11.5px;
    color: #94a3b8;
    line-height: 1.35;
}

/* Trailing text (e.g., version number on right).
   🆕 v3.1.0 Phase U Round 6 — rendered as a soft brand chip so the version
   actually reads as a label (`v3.1.0`) rather than drifting grey text. */
.settings-row__trail {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--brand-600, #2563eb);
    background: #eef2ff;
    padding: 3px 10px;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
    white-space: nowrap;
}
.settings-row__chevron {
    font-size: 20px;
    color: #cbd5e1;
    flex-shrink: 0;
}

/* Chip — small label (NEW, Coming soon) */
.settings-chip {
    background: #eef2ff;
    color: #2563eb;
    border-radius: 6px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
.settings-chip--soon {
    background: #f1f5f9;
    color: #64748b;
    text-transform: none;
    font-weight: 600;
    letter-spacing: 0;
}

/* 🆕 v3.1.0 Phase U Round 3 — EN|TH pill switch:
   - Container becomes a soft slate track (matches .budget-tabs / .report-tabs
     segmented-pill pattern) so this control reads as part of the same family.
   - Active option: brand gradient + soft glow (matches .pf-switch ON state).
   - Padding + font nudged for taller touch target. */
.settings-lang-switch {
    display: inline-flex;
    align-items: stretch;
    background: var(--surface-2, #f1f5f9);
    border: none;
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
    flex-shrink: 0;
}
.settings-lang-switch__option {
    padding: 6px 12px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--text-muted, #64748b);
    background: transparent;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 160ms ease, color 160ms ease, box-shadow 180ms ease, transform 0.08s ease;
}
.settings-lang-switch__option:hover:not(.is-active) {
    color: var(--text-primary, #0f172a);
}
.settings-lang-switch__option:active:not(.is-active) { transform: scale(0.96); }
.settings-lang-switch__option.is-active {
    background: var(--brand-gradient);
    color: #fff;
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.28);
}

/* 🆕 v3.1.0 Phase U Round 2 — iOS-style switch polished with brand gradient
   fill when ON + a glow for extra "lit" feedback. Knob picks up a slightly
   deeper shadow for depth. */
.pf-switch {
    -webkit-appearance: none;
    appearance: none;
    width: 44px;
    height: 26px;
    border-radius: 999px;
    background: #e2e8f0;
    border: none;
    padding: 0;
    position: relative;
    cursor: pointer;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 180ms cubic-bezier(0.16, 1, 0.3, 1),
                box-shadow 180ms ease;
}
.pf-switch__knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.25),
                0 0 0 0.5px rgba(15, 23, 42, 0.04);
    transition: transform 180ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.pf-switch[aria-checked="true"],
.pf-switch.is-on {
    background: var(--brand-gradient);
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08),
                0 0 0 2px rgba(37, 99, 235, 0.12);
}
.pf-switch[aria-checked="true"] .pf-switch__knob,
.pf-switch.is-on .pf-switch__knob {
    transform: translateX(18px);
}
.pf-switch:active:not([disabled]) .pf-switch__knob {
    width: 26px;         /* slight stretch on press for tactile feel */
}
.pf-switch:focus-visible {
    outline: 2px solid var(--brand-500, #3b82f6);
    outline-offset: 2px;
}
.pf-switch[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* 🆕 Phase I §8 rev6 (Option A / Scope 1) — flush-edge + softer card for TX lists only.
   Scope: #txList (Activity) and .acct-detail__tx-list (Account Detail) only — does
   NOT affect accounts.php or dashboard cards. Fixes: (a) white strip above the
   first date header (card's inner padding was pushing content away from edges),
   (b) sharp 12px corners that felt harsh — bumped to 16px soft radius. */
#txList.card--list,
.acct-detail .acct-detail__tx-list.card--list {
    padding: 0;
    border-radius: 16px;
    overflow: hidden;
}

/* 🆕 Phase I §8 rev3 — section separator feel (not pill/chip).
   slate-600 color = "darker but soft" · 600 weight · subtle tint bg · no radius.
   🆕 rev5: applied to Activity (#txList) too for consistency. */
/* Note: #accList intentionally NOT in this selector — the Accounts page
   uses .acct-group-header (type-group pill with totals), a different design
   from Activity's day-pill. See `.page-accounts .acct-group-header` below. */
.acct-detail .acct-detail__tx-list .list-group__header,
#txList .list-group__header {
    color: #475569;
    font-weight: 600;
    /* 🆕 v3.1.0 Phase T §2 — soft slate (was #f8fafc blending into page bg
       top stop; brief trial of #eef2ff felt too blue). Neutral grey sits
       clearly between page bg #f8fafc and the stronger #e2e8f0 line below. */
    background: #f1f5f9;
    border-radius: 0;
    padding: 8px 14px;
    /* margin-top removed — new header carries enough visual weight on its own. */
    margin-top: 0;
}
.acct-detail .acct-detail__tx-list > .list-group__header:first-child,
#txList > .list-group__header:first-child {
    margin-top: 0;
}
/* 🆕 v3.1.0 Phase T §2 — border-top divider removed. Phase S Round 5 already
   adds border-bottom to every .card--list > .list-item (both #txList and
   .acct-detail__tx-list wrap their lists in .card--list), so keeping the
   border-top here was double-stacking (2px looked chunky, not smooth). */
.acct-detail .acct-detail__tx-list .list-group__header + .list-item,
#txList .list-group__header + .list-item {
    border-top: none;
}

/* 🆕 Phase I §8 rev4/rev5 — Compact TX rows (Option A/A1).
   Applied to Account Detail + Activity (transactions.php) + Dashboard recent
   list (Phase T §2). Accounts list is covered separately by `.page-accounts`
   scoped rules higher in this file. */
.acct-detail .acct-detail__tx-list .list-item,
#txList .list-item,
.page-home .card--list .list-item {
    gap: 12px;
    padding: 10px 14px;
}
.acct-detail .acct-detail__tx-list .list-item__icon,
#txList .list-item__icon,
.page-home .card--list .list-item__icon {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    font-size: 18px;
    background: #f1f5f9;
    color: #64748b;
}
.acct-detail .acct-detail__tx-list .list-item__title,
#txList .list-item__title,
.page-home .card--list .list-item__title {
    font-size: 14px;
    font-weight: 600;
    color: #1e293b;
}
.acct-detail .acct-detail__tx-list .list-item__subtitle,
#txList .list-item__subtitle,
.page-home .card--list .list-item__subtitle {
    margin-top: 2px;
    font-size: 11.5px;
    color: #94a3b8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Type-based icon tint — mirrors transaction direction. Scoped to Activity,
   Account Detail, AND Dashboard recent list (Phase T §2) for brighter solid
   hex colors (vs. the muted rgba fallbacks in the global type rules). */
.acct-detail .acct-detail__tx-list .list-item--expense  .list-item__icon,
#txList .list-item--expense  .list-item__icon,
.page-home .card--list .list-item--expense  .list-item__icon { background: #fef2f2; color: #dc2626; }
.acct-detail .acct-detail__tx-list .list-item--income   .list-item__icon,
#txList .list-item--income   .list-item__icon,
.page-home .card--list .list-item--income   .list-item__icon { background: #f0fdf4; color: #16a34a; }
.acct-detail .acct-detail__tx-list .list-item--transfer .list-item__icon,
#txList .list-item--transfer .list-item__icon,
.page-home .card--list .list-item--transfer .list-item__icon { background: #eef2ff; color: #2563eb; }
.acct-detail .acct-detail__tx-list .list-item--opening  .list-item__icon,
#txList .list-item--opening  .list-item__icon,
.page-home .card--list .list-item--opening  .list-item__icon { background: #f5f3ff; color: #7c3aed; }
/* First group header has no top margin (flush with top of card) */
.acct-detail .acct-detail__tx-list > .list-group__header:first-child {
    margin-top: 0;
}
/* 🆕 v3.1.0 Phase T §2 — border-top divider removed here too (duplicate of
   the block above; Phase S Round 5's .card--list > .list-item border-bottom
   already draws every needed hairline). */
.acct-detail .acct-detail__tx-list .list-group__header + .list-item {
    border-top: none;
}

/* Staggered fade-in — items appear with a soft upward reveal.
   Up to 15 items get a visible delay; beyond that they just fade without stagger. */
@keyframes acctFadeInUp {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.acct-detail .acct-detail__tx-list > * {
    animation: acctFadeInUp 260ms var(--pf-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
}
.acct-detail .acct-detail__tx-list > :nth-child(1)  { animation-delay:   0ms; }
.acct-detail .acct-detail__tx-list > :nth-child(2)  { animation-delay:  25ms; }
.acct-detail .acct-detail__tx-list > :nth-child(3)  { animation-delay:  50ms; }
.acct-detail .acct-detail__tx-list > :nth-child(4)  { animation-delay:  75ms; }
.acct-detail .acct-detail__tx-list > :nth-child(5)  { animation-delay: 100ms; }
.acct-detail .acct-detail__tx-list > :nth-child(6)  { animation-delay: 125ms; }
.acct-detail .acct-detail__tx-list > :nth-child(7)  { animation-delay: 150ms; }
.acct-detail .acct-detail__tx-list > :nth-child(8)  { animation-delay: 170ms; }
.acct-detail .acct-detail__tx-list > :nth-child(9)  { animation-delay: 190ms; }
.acct-detail .acct-detail__tx-list > :nth-child(10) { animation-delay: 205ms; }
.acct-detail .acct-detail__tx-list > :nth-child(n+11) { animation-delay: 220ms; }

/* Respect motion preference */
@media (prefers-reduced-motion: reduce) {
    .acct-detail .acct-detail__tx-list,
    .acct-detail .acct-detail__tx-list > * {
        transition: none !important;
        animation: none !important;
    }
}

/* Empty / loading states */
.acct-detail__empty,
.acct-detail__loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 40px 20px;
    color: #94a3b8;
    text-align: center;
}
.acct-detail__empty i   { font-size: 32px; }
.acct-detail__loading i { font-size: 24px; color: #2563eb; }
.acct-detail__empty p   { margin: 0; font-size: 13px; }
.acct-detail__loading span { font-size: 12px; }

/* Match the body.page-accounts scroll-padding so this page also respects
   the sticky header when anchor-navigating. */
body.page-account-detail {
    scroll-padding-top: 70px;
}

/* ================================================================
   v3.1.0 Phase O §14 — Security REDESIGN (Phase A: unified list)
   ----------------------------------------------------------------
   Replaces three separate cards (Change password / Face ID / PIN)
   with a single flat "Ways to sign in" list per draft Hi-Fi §14.
   Icon differs by method type (lock / key / dialpad).
   Old .webauthn-section / .webauthn-card / .pw-change-card styles
   are kept earlier in the file for backward compat but unused here.
================================================================ */

/* "+" button in the page header right-side actions */
.auth-add-btn {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: var(--surface-2, #f1f5f9);
    color: var(--brand-600, #2563eb);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    -webkit-tap-highlight-color: transparent;
    transition: background .15s ease, transform .08s ease;
}
.auth-add-btn:hover  { background: var(--surface-3, #e2e8f0); }
.auth-add-btn:active { transform: scale(.92); }
.auth-add-btn i      { font-size: 22px; }

/* Unified card wrapping the list + notice */
.auth-methods-card {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    overflow: hidden;
    margin-bottom: var(--space-4, 16px);
    /* 🆕 Phase O polish — brand-tinted lift matching .card */
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}

/* The unified list */
.auth-methods {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* One row = Password | Passkey | PIN; identical layout, icon differs */
.auth-method {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1.5px solid var(--border-soft, #eaedf1);
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background .12s ease;
}
.auth-method:last-child { border-bottom: 0; }
.auth-method:hover,
.auth-method:focus-visible { background: var(--surface-2, #f8fafc); outline: none; }

.auth-method__icon {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: var(--brand-50, #eef2ff);
    color: var(--brand-600, #2563eb);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 18px;
}
.auth-method__icon i { font-size: 18px; }

.auth-method__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.auth-method__name {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text-primary, #0f172a);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.auth-method__meta {
    font-size: 12px;
    color: var(--text-muted, #94a3b8);
    margin: 0;
}

.auth-method__chev {
    color: var(--text-muted, #b8c0cc);
    font-size: 20px;
    flex-shrink: 0;
    transition: color .14s ease, transform .18s ease;
}
/* 🆕 v3.1.0 Phase W §14 Round 4 — chevron nudges right on hover (matches
   .list-item chevron pattern). Expand state still rotates 90° via the
   `aria-expanded="true"` rule below — the rules don't conflict because
   expand replaces the rotation, which trumps hover translate. */
.auth-method:hover .auth-method__chev {
    color: var(--brand-600, #2563eb);
    transform: translateX(3px);
}
.auth-method[aria-expanded="true"] .auth-method__chev {
    transform: rotate(90deg);
    color: var(--brand-600, #2563eb);
}

/* Remove button on passkey / pin rows */
.auth-method__rm {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    border: none;
    background: transparent;
    color: var(--text-muted, #94a3b8);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background .12s ease, color .12s ease;
}
.auth-method__rm:hover  { background: #fee2e2; color: #dc2626; }
.auth-method__rm:active { transform: scale(.92); }
.auth-method__rm i      { font-size: 18px; }

/* 🆕 v3.1.0 Phase W §14 Round 4 — Current-device highlight expanded from
   icon-only to full-row treatment: soft green bg + brand-green left-accent
   stripe so "this is the device you're on right now" is scannable at a glance. */
.auth-method--pin.is-current {
    background: #f0fdf4;
    border-left: 3px solid #059669;
    padding-left: 13px;         /* 16 − 3 so icon tile position doesn't shift */
}
.auth-method--pin.is-current .auth-method__icon {
    background: #dcfce7;
    color: #047857;
    box-shadow: 0 2px 6px rgba(5, 150, 105, 0.18);
}
.auth-method--pin.is-current .auth-method__name {
    color: #065f46;
}
.auth-method--pin.is-current:hover {
    background: #dcfce7;
}
.auth-method--pin.is-current:hover .auth-method__chev {
    color: #059669;
}

/* Loading row inside the card (before the first API response lands) */
.auth-methods__loading {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    font-size: 12.5px;
    color: var(--text-muted, #94a3b8);
    margin: 0;
    border-top: 1.5px solid var(--border-soft, #eaedf1);
    background: var(--surface-2, #f8fafc);
}
.auth-methods__loading i { font-size: 16px; }

/* 🆕 v3.1.0 Phase W §14 Round 3 — Removal notice reads as a soft info banner
   (lock icon via ::before, blue tint bg) so the "safety" tone is unmistakable. */
.auth-methods__notice {
    position: relative;
    font-size: 12px;
    line-height: 1.55;
    color: var(--text-muted, #64748b);
    padding: 12px 16px 14px 42px;
    margin: 0;
    border-top: 1.5px solid var(--border-soft, #eaedf1);
    background: #eff6ff;
}
.auth-methods__notice::before {
    content: '🔒';           /* unicode lock keeps zero-dependency; swap for <i.bx> if preferred */
    position: absolute;
    left: 16px;
    top: 12px;
    font-size: 14px;
    line-height: 1.4;
    color: var(--brand-600, #2563eb);
}
.auth-methods__notice strong {
    font-weight: 700;
    color: var(--brand-700, #1d4ed8);
}

/* v3.1.2+ · .auth-methods__ctas removed — the two "Setup Face ID" and
   "Set up PIN" buttons it wrapped are gone (DOM-less refactor, owner choice B).
   Users add methods via the "+" chooser-sheet (.auth-add-sheet*) in the header. */

/* Standalone (not nested in a card) change-password form */
.pw-change-form--standalone {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    padding: var(--space-4, 16px);
    margin: calc(var(--space-3, 12px) * -1) 0 var(--space-4, 16px);
}

/* ---------- Add-method chooser bottom sheet ---------- */
.auth-add-sheet {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: authAddFade .18s ease;
}
@keyframes authAddFade { from { opacity: 0; } to { opacity: 1; } }
.auth-add-sheet__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, .45);
}
.auth-add-sheet__panel {
    position: relative;
    width: 100%;
    max-width: 480px;
    background: var(--surface-1, #fff);
    border-radius: 20px 20px 0 0;
    padding: 10px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -8px 24px rgba(15, 23, 42, .12);
    animation: authAddSlide .22s ease;
}
@keyframes authAddSlide { from { transform: translateY(100%); } to { transform: translateY(0); } }
.auth-add-sheet__handle {
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: var(--border-soft, #e2e8f0);
    margin: 0 auto 10px;
}
.auth-add-sheet__title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary, #0f172a);
    margin: 0 0 12px;
    text-align: center;
}
.auth-add-sheet__list { list-style: none; margin: 0; padding: 0; }
.auth-add-sheet__item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 10px;
    border-radius: 12px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background .12s ease, transform .08s ease;
}
.auth-add-sheet__item:hover,
.auth-add-sheet__item:focus-visible { background: var(--surface-2, #f1f5f9); outline: none; }
.auth-add-sheet__item:active { transform: scale(0.98); }
/* 🆕 v3.1.0 Phase W §14 Round 3 — chevron nudge on hover (matches
   .list-item chevron + .section-head__link pattern). */
.auth-add-sheet__item .auth-add-sheet__chev,
.auth-add-sheet__item .bx-chevron-right {
    transition: color .14s ease, transform .14s ease;
}
.auth-add-sheet__item:hover .auth-add-sheet__chev,
.auth-add-sheet__item:hover .bx-chevron-right {
    color: var(--brand-600, #2563eb);
    transform: translateX(3px);
}
.auth-add-sheet__icon {
    width: 40px;
    height: 40px;
    border-radius: 11px;
    background: var(--brand-50, #eef2ff);
    color: var(--brand-600, #2563eb);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.auth-add-sheet__icon i { font-size: 20px; }
.auth-add-sheet__body { flex: 1; min-width: 0; }
.auth-add-sheet__name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary, #0f172a);
    margin: 0 0 2px;
}
.auth-add-sheet__desc {
    font-size: 12px;
    color: var(--text-muted, #94a3b8);
    margin: 0;
}
.auth-add-sheet__chev { color: var(--text-muted, #b8c0cc); font-size: 20px; }
.auth-add-sheet__cancel {
    width: 100%;
    margin-top: 8px;
    padding: 12px;
    border: none;
    border-radius: 12px;
    background: var(--surface-2, #f1f5f9);
    color: var(--text-secondary, #475569);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.auth-add-sheet__cancel:hover { background: var(--surface-3, #e2e8f0); }

/* ================================================================
   v3.1.0 Phase O §14 Phase B — Security method detail page
   security-method.php?type=passkey|pin&id=<id>
================================================================ */

.auth-method-detail-card {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    padding: 24px 16px 20px;
    text-align: center;
    margin-bottom: var(--space-4, 16px);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}
/* 🆕 v3.1.0 Phase W §14 Round 5 — hero icon gets a bounce-in on page load
   (same spring curve as Setup Wizard Done icon) so the detail page feels
   responsive the moment it opens. */
.auth-method-detail__icon {
    width: 68px;
    height: 68px;
    margin: 0 auto 14px;
    border-radius: 20px;
    display: grid;
    place-items: center;
    background: var(--brand-gradient);
    color: #fff;
    font-size: 32px;
    box-shadow: 0 6px 16px rgba(37, 99, 235, 0.28),
                0 2px 6px rgba(15, 23, 42, 0.08);
    animation: authMethodHeroPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes authMethodHeroPop {
    0%   { opacity: 0; transform: scale(0.6); }
    60%  { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .auth-method-detail__icon { animation: none; }
}
.auth-method-detail__icon i { font-size: 32px; line-height: 1; }
.auth-method-detail__name {
    margin: 0 0 6px;
    font-size: 18px;
    font-weight: 700;
    color: var(--text-primary, #0f172a);
    word-break: break-word;
}
.auth-method-detail__sub {
    margin: 0;
    font-size: 13px;
    color: var(--text-muted, #94a3b8);
}

/* Info rows (Device / Added / Last used / Transports) */
.auth-method-info-card {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    overflow: hidden;
    margin-bottom: var(--space-4, 16px);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}
.auth-method-info {
    list-style: none;
    margin: 0;
    padding: 0;
}
.auth-method-info__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1.5px solid var(--border-soft, #eaedf1);
}
.auth-method-info__row:last-child { border-bottom: 0; }
.auth-method-info__label {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted, #94a3b8);
}
.auth-method-info__value {
    text-align: right;
    font-size: 13.5px;
    color: var(--text-primary, #0f172a);
    word-break: break-word;
}
.auth-method-info__value strong {
    font-weight: 700;
    color: var(--brand-600, #2563eb);
}

/* Danger zone — Remove button */
.auth-method-danger {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: var(--space-4, 16px);
}
/* 🆕 v3.1.0 Phase W §14 Round 6 — Remove button strengthened:
   - Default: red-tinted lift (matches Health critical-card)
   - Hover: deeper red lift + border intensifies
   - Pressed: scale 0.98 (unchanged) */
.auth-method-remove {
    width: 100%;
    height: 48px;
    border: 1.5px solid #fecaca;
    border-radius: var(--r-md, 12px);
    background: #fef2f2;
    color: #dc2626;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 2px 6px -1px rgba(220, 38, 38, 0.12);
    transition: background .15s ease, transform .08s ease, box-shadow .18s ease, border-color .15s ease;
}
.auth-method-remove:hover:not(:disabled) {
    background: #fee2e2;
    border-color: #fca5a5;
    box-shadow: 0 8px 20px -4px rgba(220, 38, 38, 0.26),
                0 3px 8px -2px rgba(220, 38, 38, 0.14);
    transform: translateY(-1px);
}
.auth-method-remove:active:not(:disabled) {
    transform: translateY(0) scale(.98);
    box-shadow: 0 2px 6px -1px rgba(220, 38, 38, 0.14);
}
.auth-method-remove:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    box-shadow: none;
}
.auth-method-remove i { font-size: 18px; }
/* 🆕 v3.1.0 Phase W §14 Round 6 — danger-zone hint upgraded to a soft info
   banner with info icon (matches Removal notice pattern on security.php). */
.auth-method-danger__hint {
    position: relative;
    margin: 0;
    padding: 10px 12px 10px 36px;
    background: rgba(100, 116, 139, 0.08);
    border-radius: 10px;
    font-size: 12px;
    line-height: 1.55;
    color: var(--text-muted, #64748b);
}
.auth-method-danger__hint::before {
    content: 'ⓘ';
    position: absolute;
    left: 12px;
    top: 9px;
    font-size: 14px;
    color: var(--text-secondary, #64748b);
    font-weight: 700;
}

/* 🆕 v3.1.0 Phase O §14 Phase C — Rename card on security-method.php */
.auth-method-rename-card {
    background: var(--surface-1, #fff);
    border-radius: var(--r-xl, 16px);
    border: 1px solid var(--border-soft, #e2e8f0);
    padding: 16px;
    margin-bottom: var(--space-4, 16px);
    box-shadow: var(--shadow-card-brand,
                0 10px 24px -8px rgba(37, 99, 235, 0.14),
                0 2px 8px -2px rgba(15, 23, 42, 0.06));
}
.auth-method-rename__label {
    display: block;
    font-size: 12px;
    color: var(--text-muted, #64748b);
    margin: 0 0 8px;
}
.auth-method-rename__row {
    display: flex;
    gap: 8px;
    align-items: stretch;
}
.auth-method-rename__input {
    flex: 1;
    min-width: 0;
    height: 44px;
    padding: 0 12px;
    border: 1px solid var(--border-light, #cbd5e1);
    border-radius: var(--r-md, 12px);
    background: var(--surface-2, #f8fafc);
    color: var(--text-primary, #0f172a);
    font: inherit;
    font-size: 14px;
    transition: border-color .15s ease, background .15s ease;
}
/* 🆕 v3.1.0 Phase W §14 Round 5 — soft brand glow around focused input
   (modern form-field pattern). */
.auth-method-rename__input:focus {
    outline: none;
    border-color: var(--brand-500, #3b82f6);
    background: var(--surface-1, #fff);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.14);
}
.auth-method-rename__input:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}
.auth-method-rename__save {
    flex-shrink: 0;
    padding: 0 16px;
    height: 44px;
    border: none;
    border-radius: var(--r-md, 12px);
    background: var(--brand-gradient);
    color: #fff;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.28);
    transition: transform .12s ease, box-shadow .18s ease, opacity .18s ease;
    -webkit-tap-highlight-color: transparent;
}
.auth-method-rename__save i { font-size: 17px; }
.auth-method-rename__save:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(59, 130, 246, 0.38);
}
.auth-method-rename__save:active:not(:disabled) { transform: translateY(0) scale(0.99); }
.auth-method-rename__save:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    box-shadow: none;
}
.auth-method-rename__hint {
    margin: 8px 2px 0;
    font-size: 11px;
    color: var(--text-muted, #94a3b8);
}
