/* =============================================================================
   Income-Expense Manager - shared design system.
   Loaded by every host (Blazor Web and the MAUI Hybrid WebView), so it owns the
   theme tokens, the application shell and every reusable component. No web fonts
   or CDN assets are referenced: the app is installable as a PWA and must look
   identical with no network.
   ============================================================================= */

:root {
    /* Brand ---------------------------------------------------------------- */
    --iem-accent: #f97316;
    --iem-accent-strong: #ea580c;
    --iem-accent-soft: #fff2e8;
    --iem-accent-ring: rgba(249, 115, 22, 0.25);

    /* Neutrals ------------------------------------------------------------- */
    --iem-ink: #16181d;
    --iem-ink-soft: #3f434d;
    --iem-muted: #8a9099;
    --iem-line: #ececef;
    --iem-line-strong: #dcdde1;
    --iem-surface: #ffffff;
    --iem-canvas: #f4f4f2;
    --iem-hover: #faf9f7;

    /* Semantics ------------------------------------------------------------ */
    --iem-income: #0f9d58;
    --iem-income-soft: #e7f6ee;
    --iem-expense: #e04b2a;
    --iem-expense-soft: #fdeee9;

    /* Shape ---------------------------------------------------------------- */
    --iem-radius: 14px;
    --iem-radius-sm: 9px;
    --iem-radius-pill: 999px;
    --iem-shadow: 0 1px 2px rgba(19, 20, 24, 0.04), 0 1px 3px rgba(19, 20, 24, 0.03);
    --iem-shadow-lg: 0 10px 30px rgba(19, 20, 24, 0.08);

    --iem-sidebar-width: 248px;
}

html, body {
    background: var(--iem-canvas);
    color: var(--iem-ink);
    /* System stack only, so nothing has to be fetched before the first paint. */
    font-family: "Segoe UI Variable Display", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto,
                 "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

body {
    font-size: 0.9rem;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--iem-ink);
    letter-spacing: -0.011em;
}

/* Bootstrap's default heading scale is far too large for a dense finance UI, where h2/h3 are
   section labels inside a card rather than page titles. */
h2 {
    font-size: 1.05rem;
    font-weight: 650;
}

h3 {
    font-size: 0.94rem;
    font-weight: 650;
}

h4, h5, h6 {
    font-size: 0.88rem;
    font-weight: 650;
}

a {
    color: var(--iem-accent-strong);
    text-decoration: none;
}

a:hover {
    color: var(--iem-accent-strong);
    text-decoration: underline;
}

::selection {
    background: var(--iem-accent-ring);
}

/* =============================================================================
   Application shell
   ============================================================================= */

.app-shell {
    display: flex;
    min-height: 100vh;
    background: var(--iem-canvas);
}

.app-sidebar {
    width: var(--iem-sidebar-width);
    flex: 0 0 var(--iem-sidebar-width);
    background: var(--iem-surface);
    border-right: 1px solid var(--iem-line);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.app-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.app-content {
    padding: 1.35rem 1.6rem 2.5rem;
    flex: 1 1 auto;
}

/* --- Brand ------------------------------------------------------------------ */
.app-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 1.15rem 1.15rem 0.9rem;
    font-weight: 650;
    font-size: 1rem;
    color: var(--iem-ink);
}

.app-brand:hover {
    text-decoration: none;
    color: var(--iem-ink);
}

.app-brand-mark {
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: linear-gradient(140deg, var(--iem-accent) 0%, var(--iem-accent-strong) 100%);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    box-shadow: 0 2px 6px rgba(249, 115, 22, 0.35);
}

.app-brand-mark svg {
    width: 16px;
    height: 16px;
}

/* --- Navigation ------------------------------------------------------------- */
.app-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.25rem 0.7rem 1rem;
}

.app-nav-section {
    padding: 0.9rem 0.55rem 0.35rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--iem-muted);
}

.app-nav .nav-link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.6rem;
    margin-bottom: 0.12rem;
    border-radius: var(--iem-radius-sm);
    color: var(--iem-ink-soft);
    font-size: 0.86rem;
    font-weight: 500;
    line-height: 1.25;
    transition: background-color 0.14s ease, color 0.14s ease;
}

.app-nav .nav-link:hover {
    background: var(--iem-hover);
    color: var(--iem-ink);
    text-decoration: none;
}

.app-nav .nav-link.active {
    background: var(--iem-accent-soft);
    color: var(--iem-accent-strong);
    font-weight: 600;
}

.app-nav .nav-link svg {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    opacity: 0.75;
}

.app-nav .nav-link.active svg {
    opacity: 1;
}

/* --- Sidebar footer / user card --------------------------------------------- */
.app-user {
    border-top: 1px solid var(--iem-line);
    padding: 0.8rem 0.9rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.app-avatar {
    width: 32px;
    height: 32px;
    flex: 0 0 auto;
    border-radius: var(--iem-radius-pill);
    background: var(--iem-accent-soft);
    color: var(--iem-accent-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.78rem;
}

.app-user-text {
    min-width: 0;
    flex: 1 1 auto;
    line-height: 1.2;
}

.app-user-name {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--iem-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-user-role {
    display: block;
    font-size: 0.72rem;
    color: var(--iem-muted);
}

.app-signout {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--iem-radius-sm);
    color: var(--iem-muted);
}

.app-signout:hover {
    background: var(--iem-expense-soft);
    color: var(--iem-expense);
}

.app-signout svg {
    width: 16px;
    height: 16px;
}

/* Install button. `.app-nav .nav-link` sets `display: flex`, which outranks the user-agent
   `[hidden] { display: none }` rule, so hiding has to be restated explicitly here. */
.app-nav .app-install {
    width: 100%;
    border: 0;
    background: none;
    text-align: left;
    font-family: inherit;
    cursor: pointer;
    color: var(--iem-accent-strong);
    font-weight: 600;
}

.app-nav .app-install:hover {
    background: var(--iem-accent-soft);
}

.app-nav .app-install svg {
    opacity: 1;
}

.app-nav .app-install[hidden] {
    display: none;
}

/* --- Top bar ---------------------------------------------------------------- */
.app-topbar {
    height: 58px;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0 1.6rem;
    background: rgba(255, 255, 255, 0.86);
    backdrop-filter: saturate(180%) blur(8px);
    border-bottom: 1px solid var(--iem-line);
    position: sticky;
    top: 0;
    z-index: 20;
}

.app-topbar-title {
    font-weight: 600;
    font-size: 0.95rem;
    margin: 0;
}

.app-topbar-spacer {
    flex: 1 1 auto;
}

.app-topbar-date {
    font-size: 0.8rem;
    color: var(--iem-muted);
    white-space: nowrap;
}

/* Mobile drawer toggle: a plain checkbox drives the sidebar so no JS is needed
   (which also means it works during prerender, before the circuit connects). */
.app-nav-toggle {
    display: none;
}

.app-nav-toggle-label {
    display: none;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--iem-radius-sm);
    border: 1px solid var(--iem-line-strong);
    background: var(--iem-surface);
    color: var(--iem-ink-soft);
    cursor: pointer;
    flex: 0 0 auto;
}

.app-nav-toggle-label svg {
    width: 17px;
    height: 17px;
}

.app-scrim {
    display: none;
}

@media (max-width: 900px) {
    :root {
        --iem-sidebar-width: 264px;
    }

    .app-nav-toggle-label {
        display: inline-flex;
    }

    .app-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        z-index: 40;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: var(--iem-shadow-lg);
    }

    .app-nav-toggle:checked ~ .app-shell .app-sidebar {
        transform: translateX(0);
    }

    .app-nav-toggle:checked ~ .app-shell .app-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 30;
        background: rgba(17, 18, 22, 0.35);
    }

    .app-content {
        padding: 1rem 1rem 2.5rem;
    }

    .app-topbar {
        padding: 0 1rem;
    }

    .app-topbar-date {
        display: none;
    }
}

/* =============================================================================
   Page header
   ============================================================================= */

.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.1rem;
}

.page-header h1 {
    font-size: 1.45rem;
    font-weight: 650;
    margin: 0;
}

.page-subtitle {
    margin: 0.2rem 0 0;
    font-size: 0.83rem;
    color: var(--iem-muted);
}

.page-header-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* =============================================================================
   Surfaces
   ============================================================================= */

.panel,
.card {
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
}

.panel {
    padding: 1.05rem 1.15rem;
    margin-bottom: 1.1rem;
}

/* Bootstrap cards are used by a few pages (Quick Add); make them read as panels. */
.card-body {
    padding: 1.05rem 1.15rem;
}

.card-body > h2,
.card-body > h3 {
    font-size: 0.98rem;
    font-weight: 650;
    margin: 0 0 0.75rem;
}

.card {
    margin-bottom: 1.1rem;
}

.panel > .table:last-child,
.panel > .table-responsive:last-child {
    margin-bottom: 0;
}

.panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.85rem;
}

.panel h2 {
    font-size: 0.98rem;
    font-weight: 650;
    margin: 0;
}

.panel-note {
    font-size: 0.76rem;
    color: var(--iem-muted);
    margin: 0.15rem 0 0.75rem;
}

.panel-head + .panel-note {
    margin-top: -0.55rem;
}

/* Keeps previously loaded figures on screen (dimmed) while a new range loads,
   instead of flashing the page back to a loading state on every filter change. */
.is-busy {
    opacity: 0.5;
    transition: opacity 0.15s ease;
    pointer-events: none;
}

/* =============================================================================
   KPI cards
   ============================================================================= */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.85rem;
    margin-bottom: 1.1rem;
}

.kpi-card {
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
    padding: 0.95rem 1.05rem 1.05rem;
    min-width: 0;
}

.kpi-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.55rem;
}

.kpi-label {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.075em;
    text-transform: uppercase;
    color: var(--iem-muted);
    margin: 0;
}

.kpi-value {
    font-size: 1.5rem;
    font-weight: 650;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    margin: 0;
    color: var(--iem-ink);
    overflow-wrap: anywhere;
}

.kpi-value.is-negative {
    color: var(--iem-expense);
}

.kpi-value.is-positive {
    color: var(--iem-income);
}

.kpi-foot {
    margin: 0.35rem 0 0;
    font-size: 0.74rem;
    color: var(--iem-muted);
}

/* Trend chip: green when the change is good for the user, red when it is not.
   "Good" is direction-dependent, so the caller decides which class to apply. */
.kpi-delta {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.13rem 0.45rem;
    border-radius: var(--iem-radius-pill);
    font-size: 0.72rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.kpi-delta-up {
    background: var(--iem-income-soft);
    color: #0b7a45;
}

.kpi-delta-down {
    background: var(--iem-expense-soft);
    color: #b03a1c;
}

.kpi-delta-flat {
    background: #f2f3f5;
    color: var(--iem-muted);
}

.kpi-delta svg {
    width: 11px;
    height: 11px;
}

/* =============================================================================
   Charts
   ============================================================================= */

.chart-axis {
    font-size: 11px;
    fill: var(--iem-muted);
}

.chart-bars svg {
    width: 100%;
    height: auto;
    display: block;
}

.chart-bar {
    transition: opacity 0.12s ease;
}

.chart-bars:hover .chart-bar {
    opacity: 0.55;
}

.chart-bars .chart-bar:hover {
    opacity: 1;
}

.chart-key {
    display: flex;
    gap: 1rem;
    justify-content: center;
    margin-top: 0.5rem;
    font-size: 0.76rem;
    color: var(--iem-muted);
}

.chart-key span {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.chart-key-dot {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    display: inline-block;
}

.chart-empty {
    color: var(--iem-muted);
    font-size: 0.84rem;
    text-align: center;
    padding: 2.5rem 0;
    margin: 0;
}

/* --- Donut ------------------------------------------------------------------ */
.chart-donut {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    flex-wrap: wrap;
}

.chart-donut-figure {
    flex: 0 0 auto;
    width: 168px;
}

.chart-donut-figure svg {
    width: 100%;
    height: auto;
    display: block;
}

.chart-donut-value {
    font-size: 17px;
    font-weight: 650;
    fill: var(--iem-ink);
}

.chart-donut-caption {
    font-size: 11px;
    fill: var(--iem-muted);
}

.chart-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 1 1 190px;
    min-width: 0;
}

.chart-legend li {
    display: grid;
    grid-template-columns: 10px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.34rem 0;
    font-size: 0.82rem;
    border-bottom: 1px solid var(--iem-line);
}

.chart-legend li:last-child {
    border-bottom: 0;
}

.chart-legend-empty {
    display: block !important;
    color: var(--iem-muted);
    border-bottom: 0 !important;
}

.chart-legend-dot {
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.chart-legend-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--iem-ink-soft);
}

.chart-legend-value {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.chart-legend-share {
    font-size: 0.74rem;
    color: var(--iem-muted);
    font-variant-numeric: tabular-nums;
    min-width: 2.6rem;
    text-align: right;
}

/* =============================================================================
   Layout helpers
   ============================================================================= */

.grid-2 {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: 1.1rem;
    align-items: start;
}

.grid-3 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
    gap: 1.1rem;
    align-items: start;
}

@media (max-width: 1050px) {
    .grid-2 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Retained for pages still using the older three-column arrangement. */
.dashboard-columns {
    display: flex;
    gap: 1.1rem;
    flex-wrap: wrap;
    align-items: flex-start;
}

.dashboard-columns section {
    flex: 1 1 320px;
    min-width: 280px;
}

/* =============================================================================
   Activity list
   ============================================================================= */

.activity {
    list-style: none;
    margin: 0;
    padding: 0;
}

.activity li {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--iem-line);
}

.activity li:last-child {
    border-bottom: 0;
}

.activity-icon {
    width: 32px;
    height: 32px;
    flex: 0 0 auto;
    border-radius: var(--iem-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--iem-expense-soft);
    color: var(--iem-expense);
}

.activity-icon.is-income {
    background: var(--iem-income-soft);
    color: var(--iem-income);
}

.activity-icon svg {
    width: 15px;
    height: 15px;
}

.activity-text {
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.25;
}

.activity-title {
    display: block;
    font-size: 0.85rem;
    font-weight: 550;
    color: var(--iem-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.activity-meta {
    display: block;
    font-size: 0.74rem;
    color: var(--iem-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.activity-amount {
    flex: 0 0 auto;
    font-size: 0.86rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    color: var(--iem-expense);
    white-space: nowrap;
}

.activity-amount.is-income {
    color: var(--iem-income);
}

/* =============================================================================
   Filters
   ============================================================================= */

.filter-bar {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.9rem;
    flex-wrap: wrap;
    padding: 0.8rem 0.95rem;
    margin-bottom: 1.1rem;
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
}

.filter-bar-wrap {
    align-items: flex-end;
    justify-content: flex-start;
}

.filter-bar-wrap .form-group {
    min-width: 8.5rem;
}

.filter-presets {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.filter-presets + .filter-bar {
    margin-top: 0.55rem;
}

.filter-range {
    display: flex;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.filter-range .form-control {
    min-width: 9.5rem;
}

/* --- Chips ------------------------------------------------------------------ */
.chip {
    border: 1px solid var(--iem-line-strong);
    background: var(--iem-surface);
    color: var(--iem-ink-soft);
    border-radius: var(--iem-radius-pill);
    padding: 0.3rem 0.8rem;
    font-size: 0.79rem;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color 0.14s ease, color 0.14s ease, border-color 0.14s ease;
}

/* Excludes the active chip: its white label would otherwise sit on the pale hover
   background and become unreadable (the hover selector outranks .chip-active). */
.chip:hover:not(:disabled):not(.chip-active) {
    background: var(--iem-accent-soft);
    border-color: #f8c9a4;
    color: var(--iem-accent-strong);
}

.chip:disabled {
    opacity: 0.55;
    cursor: default;
}

.chip-active,
.chip-active:hover {
    background: var(--iem-ink);
    border-color: var(--iem-ink);
    color: #fff;
    font-weight: 600;
}

/* Compact chip row used inside a panel header (chart range switchers). */
.chip-mini {
    padding: 0.15rem 0.55rem;
    font-size: 0.72rem;
}

/* =============================================================================
   Buttons (overrides Bootstrap so every host matches the theme)
   ============================================================================= */

.btn {
    border-radius: var(--iem-radius-sm);
    font-size: 0.84rem;
    font-weight: 550;
    padding: 0.42rem 0.9rem;
    transition: background-color 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}

.btn-sm {
    font-size: 0.78rem;
    padding: 0.24rem 0.6rem;
    border-radius: 7px;
}

.btn:focus-visible,
.form-control:focus,
.form-select:focus,
.chip:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--iem-accent-ring);
    border-color: var(--iem-accent);
}

.btn-primary {
    background: var(--iem-ink);
    border-color: var(--iem-ink);
    color: #fff;
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    background: #000;
    border-color: #000;
    color: #fff;
}

.btn-primary:disabled {
    background: var(--iem-ink);
    border-color: var(--iem-ink);
    opacity: 0.45;
}

.btn-accent {
    background: var(--iem-accent);
    border-color: var(--iem-accent);
    color: #fff;
}

.btn-accent:hover,
.btn-accent:focus {
    background: var(--iem-accent-strong);
    border-color: var(--iem-accent-strong);
    color: #fff;
}

.btn-outline-primary {
    color: var(--iem-ink);
    border-color: var(--iem-line-strong);
    background: var(--iem-surface);
}

.btn-outline-primary:hover,
.btn-outline-primary:focus {
    background: var(--iem-hover);
    border-color: var(--iem-ink);
    color: var(--iem-ink);
}

.btn-outline-secondary {
    color: var(--iem-ink-soft);
    border-color: var(--iem-line-strong);
    background: var(--iem-surface);
}

.btn-outline-secondary:hover {
    background: var(--iem-hover);
    color: var(--iem-ink);
    border-color: var(--iem-line-strong);
}

.btn-outline-danger {
    color: var(--iem-expense);
    border-color: #f3c7bb;
    background: var(--iem-surface);
}

.btn-outline-danger:hover,
.btn-outline-danger:focus {
    background: var(--iem-expense);
    border-color: var(--iem-expense);
    color: #fff;
}

.btn-danger {
    background: var(--iem-expense);
    border-color: var(--iem-expense);
}

/* Bootstrap's disabled tokens win over the colours above, so they are restated here. Without this
   a disabled outline button reverts to Bootstrap blue and a disabled primary turns flat grey. */
.btn:disabled,
.btn.disabled {
    opacity: 0.45;
    box-shadow: none;
}

.btn-primary:disabled {
    --bs-btn-disabled-bg: var(--iem-ink);
    --bs-btn-disabled-border-color: var(--iem-ink);
    --bs-btn-disabled-color: #fff;
}

.btn-accent:disabled {
    --bs-btn-disabled-bg: var(--iem-accent);
    --bs-btn-disabled-border-color: var(--iem-accent);
    --bs-btn-disabled-color: #fff;
}

.btn-outline-primary:disabled,
.btn-outline-secondary:disabled {
    --bs-btn-disabled-color: var(--iem-ink-soft);
    --bs-btn-disabled-border-color: var(--iem-line-strong);
    --bs-btn-disabled-bg: var(--iem-surface);
}

.btn-outline-danger:disabled {
    --bs-btn-disabled-color: var(--iem-expense);
    --bs-btn-disabled-border-color: #f3c7bb;
    --bs-btn-disabled-bg: var(--iem-surface);
}

/* =============================================================================
   Forms
   ============================================================================= */

.form-control,
.form-select {
    border-radius: var(--iem-radius-sm);
    border: 1px solid var(--iem-line-strong);
    font-size: 0.85rem;
    padding: 0.4rem 0.65rem;
    color: var(--iem-ink);
    background-color: var(--iem-surface);
}

.form-control::placeholder {
    color: #b3b7bd;
}

.form-control:disabled,
.form-select:disabled {
    background-color: #f6f6f7;
}

.form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    align-items: flex-end;
}

.form-group {
    display: flex;
    flex-direction: column;
    min-width: 140px;
}

.form-group-grow {
    flex: 1 1 220px;
}

.form-group-action {
    min-width: auto;
}

.form-group label,
.form-label {
    font-size: 0.76rem;
    font-weight: 550;
    color: var(--iem-ink-soft);
    margin-bottom: 0.22rem;
}

.validation-message {
    color: var(--iem-expense);
    font-size: 0.78rem;
}

.invalid {
    border-color: var(--iem-expense) !important;
}

@media (max-width: 640px) {
    .form-row {
        flex-direction: column;
        align-items: stretch;
    }

    /* flex-basis follows the MAIN axis. Once the row stacks, the 220px that was meant as a
       minimum WIDTH starts acting as a minimum HEIGHT, so every field grew to 220px tall with
       a huge dead gap under each control. Resetting flex restores natural label+input height. */
    .form-group,
    .form-group-grow,
    .form-group-action {
        flex: 0 0 auto;
        min-width: 0;
        width: 100%;
    }
}

/* =============================================================================
   Tables
   ============================================================================= */

.table {
    margin-bottom: 0.5rem;
    --bs-table-bg: transparent;
    color: var(--iem-ink);
}

.table thead th {
    font-size: 0.67rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--iem-muted);
    font-weight: 700;
    border-bottom: 1px solid var(--iem-line);
    padding-top: 0.35rem;
    padding-bottom: 0.45rem;
    background: transparent;
}

.table tbody td {
    vertical-align: middle;
    color: var(--iem-ink-soft);
    border-color: var(--iem-line);
    font-size: 0.85rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}

.table tbody tr:hover > * {
    background: var(--iem-hover);
}

.table > :not(caption) > * > * {
    box-shadow: none;
}

.num {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.table-actions {
    display: flex;
    gap: 0.3rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* =============================================================================
   Collapsible sections (phones only)
   ============================================================================= */

/* Desktop: the summary bar does not exist and the panel is simply always open. */
.collapse-toggle {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.collapse-summary {
    display: none;
}

@media (max-width: 640px) {
    .collapsible {
        margin-bottom: 0.9rem;
        border: 1px solid var(--iem-line);
        border-radius: var(--iem-radius);
        background: var(--iem-surface);
        box-shadow: var(--iem-shadow);
        overflow: hidden;
    }

    .collapse-summary {
        display: flex;
        align-items: center;
        gap: 0.6rem;
        /* Comfortably above the 40px touch floor used elsewhere. */
        min-height: 48px;
        padding: 0.6rem 0.9rem;
        margin: 0;
        cursor: pointer;
        user-select: none;
        font-weight: 650;
        color: var(--iem-ink);
    }

    .collapse-title {
        flex: 1 1 auto;
    }

    .collapse-badge {
        flex: 0 0 auto;
        padding: 0.1rem 0.5rem;
        border-radius: var(--iem-radius-pill);
        background: var(--iem-accent-soft);
        color: var(--iem-accent-strong);
        font-size: 0.72rem;
        font-weight: 700;
    }

    .collapse-chevron {
        flex: 0 0 auto;
        display: inline-flex;
        color: var(--iem-muted);
        transition: transform 0.18s ease;
    }

    .collapse-chevron svg {
        width: 18px;
        height: 18px;
    }

    .collapse-toggle:checked ~ .collapse-summary .collapse-chevron {
        transform: rotate(180deg);
    }

    .collapse-toggle:checked ~ .collapse-summary {
        border-bottom: 1px solid var(--iem-line);
    }

    /* Keyboard users get the same focus ring the checkbox would have had. */
    .collapse-toggle:focus-visible ~ .collapse-summary {
        outline: 2px solid var(--iem-accent);
        outline-offset: -2px;
    }

    .collapse-toggle:not(:checked) ~ .collapse-panel {
        display: none;
    }

    /* The panel already sits inside the collapsible card, so a nested card would
       double the border and padding. */
    .collapse-panel > .card,
    .collapse-panel > .panel,
    .collapse-panel > .filter-bar {
        margin: 0;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    /* The summary bar already states the section name, so the panel's own heading
       would read as a duplicate on phones. */
    .collapse-panel > .card > .card-body > h2:first-child,
    .collapse-panel > .panel > h2:first-child {
        display: none;
    }
}

/* Horizontal scroll container so wide tables never blow out the mobile layout. */
.table-scroll {
    overflow-x: auto;
}

/* --- Stacked table cards on phones -------------------------------------------
   A six or seven column table is unreadable at 390px: the columns that matter
   most (Amount, and the row actions) end up hidden behind a horizontal scroll.
   Below 640px each row is re-flowed into a card and every cell is labelled from
   its own `data-label`, so nothing is hidden and nothing needs side-scrolling.
   Tables opt in with `.table-stack` and every informational <td> must carry a
   `data-label`; the trailing actions cell deliberately has none. */
@media (max-width: 640px) {
    .table-stack,
    .table-stack tbody,
    .table-stack tr,
    .table-stack td {
        display: block;
        width: 100%;
    }

    .table-stack thead {
        display: none;
    }

    .table-stack tr {
        margin-bottom: 0.6rem;
        padding: 0.5rem 0.75rem;
        border: 1px solid var(--iem-line);
        border-radius: var(--iem-radius-sm);
        background: var(--iem-surface);
    }

    /* Bootstrap paints striping and row status on the CELLS. Once the row is a
       card that has to move to the card itself, or the colour is lost. */
    .table-stack.table-striped > tbody > tr:nth-of-type(odd) > * {
        --bs-table-accent-bg: transparent;
        background-color: transparent;
    }

    .table-stack tr.table-danger {
        background: var(--iem-expense-soft);
        border-color: var(--iem-expense);
    }

    .table-stack tr.table-warning {
        background: #fff7e6;
        border-color: #f0a020;
    }

    .table-stack tbody tr:hover > * {
        background: transparent;
    }

    .table-stack td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.9rem;
        padding: 0.3rem 0;
        border: 0;
        text-align: right;
        font-size: 0.9rem;
    }

    .table-stack td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        text-align: left;
        font-size: 0.72rem;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--iem-muted);
    }

    /* The trailing actions cell carries no label and gets the full card width. */
    .table-stack td:not([data-label]) {
        justify-content: flex-end;
        padding-top: 0.5rem;
    }

    .table-stack td:not([data-label])::before {
        content: none;
    }

    /* A cell with no value (blank comment or note) is noise as a card row. */
    .table-stack td:empty {
        display: none;
    }

    .table-stack .table-actions {
        width: 100%;
        justify-content: flex-end;
    }

    /* Controls inside a card row need room rather than a squeezed column. */
    .table-stack td .form-control,
    .table-stack td .form-select,
    .table-stack td .progress {
        flex: 1 1 55%;
        width: auto;
    }
}

/* --- Touch ergonomics ---------------------------------------------------------
   Keyed off `pointer: coarse` rather than width: a small laptop keeps the compact
   desktop sizing, while a large tablet still gets finger-sized targets. The audit
   found 28px buttons and a 30px sign-out; ~40px is the practical floor. */
@media (pointer: coarse) {
    .btn-sm,
    .btn.btn-sm {
        min-height: 40px;
        padding-inline: 0.85rem;
    }

    .chip {
        min-height: 40px;
    }

    .app-signout {
        width: 40px;
        height: 40px;
    }

    .pager-controls .btn-sm {
        min-width: 40px;
    }

    .app-nav .nav-link {
        padding-block: 0.7rem;
    }

    .form-control,
    .form-select,
    select.form-control {
        min-height: 42px;
        /* iOS Safari zooms the entire page when a focused field is under 16px.
           This is the only reliable way to stop it. */
        font-size: 16px;
    }
}

/* Text that is comfortable on a desktop sidebar becomes unreadable on a phone. */
@media (max-width: 640px) {
    .app-nav-section {
        font-size: 0.74rem;
    }

    .table thead th {
        font-size: 0.72rem;
    }

    .kpi-label {
        font-size: 0.74rem;
    }
}

/* =============================================================================
   Share bars / progress
   ============================================================================= */

.cat-name {
    display: block;
    color: var(--iem-ink);
}

.bar {
    display: block;
    height: 5px;
    margin-top: 0.3rem;
    background: #f0f1f3;
    border-radius: var(--iem-radius-pill);
    overflow: hidden;
}

.bar-fill {
    display: block;
    height: 100%;
    background: var(--iem-accent);
    border-radius: var(--iem-radius-pill);
    transition: width 0.25s ease;
}

.bar-fill.bar-income {
    background: var(--iem-income);
}

/* Bootstrap progress bars (budget usage) restyled to match the share bars above. */
.progress {
    background: #f0f1f3;
    border-radius: var(--iem-radius-pill);
    height: 1.05rem !important;
    font-size: 0.68rem;
    overflow: hidden;
}

.progress-bar {
    border-radius: var(--iem-radius-pill);
    font-weight: 650;
}

.progress-bar.bg-success {
    background-color: var(--iem-income) !important;
}

.progress-bar.bg-warning {
    background-color: #f0a020 !important;
    color: #3d2a05;
}

.progress-bar.bg-danger {
    background-color: var(--iem-expense) !important;
}

.table-danger > * {
    --bs-table-bg: var(--iem-expense-soft);
}

.table-warning > * {
    --bs-table-bg: #fff7e6;
}

/* =============================================================================
   Pills and badges
   ============================================================================= */

.pill {
    display: inline-block;
    padding: 0.12rem 0.55rem;
    border-radius: var(--iem-radius-pill);
    font-size: 0.71rem;
    font-weight: 650;
    letter-spacing: 0.015em;
    background: #f2f3f5;
    color: var(--iem-ink-soft);
}

.pill-income {
    background: var(--iem-income-soft);
    color: #0b6b3a;
}

.pill-expense {
    background: var(--iem-expense-soft);
    color: #a63a1c;
}

/* =============================================================================
   Pager
   ============================================================================= */

.pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.65rem 0.95rem;
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
}

.pager-info {
    font-size: 0.82rem;
    color: var(--iem-muted);
    font-variant-numeric: tabular-nums;
}

.pager-controls {
    display: flex;
    gap: 0.3rem;
    flex-wrap: wrap;
}

.pager-size {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.pager-size label {
    font-size: 0.78rem;
    color: var(--iem-muted);
    margin: 0;
}

.pager-size .form-select {
    width: auto;
    min-width: 4.5rem;
    padding-right: 1.8rem;
}

/* =============================================================================
   Alerts
   ============================================================================= */

.alert {
    border-radius: var(--iem-radius-sm);
    font-size: 0.84rem;
    border-width: 1px;
}

.alert-danger {
    background: var(--iem-expense-soft);
    border-color: #f5cec2;
    color: #96331a;
}

.alert-success {
    background: var(--iem-income-soft);
    border-color: #bfe6d1;
    color: #0b6b3a;
}

.alert-warning {
    background: #fff7e6;
    border-color: #f7dfae;
    color: #8a5a09;
}

.alert-info {
    background: #eef6fd;
    border-color: #c9e2f7;
    color: #0f5c8f;
}

.text-muted {
    color: var(--iem-muted) !important;
}

.empty-state {
    text-align: center;
    color: var(--iem-muted);
    font-size: 0.85rem;
    padding: 2rem 1rem;
}

/* =============================================================================
   Loading skeletons
   ============================================================================= */

.skeleton-line {
    display: block;
    height: 12px;
    border-radius: var(--iem-radius-pill);
    background: linear-gradient(90deg, #eceef1 25%, #f6f7f9 37%, #eceef1 63%);
    background-size: 400% 100%;
    animation: skeleton-shimmer 1.3s ease-in-out infinite;
}

@keyframes skeleton-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* A shimmer across the whole screen is a vestibular trigger, so honour the OS setting. */
@media (prefers-reduced-motion: reduce) {
    .skeleton-line {
        animation: none;
        background: #eceef1;
    }
}

.skeleton-line-xs { width: 35%; height: 10px; }
.skeleton-line-sm { width: 45%; }
.skeleton-line-md { width: 65%; height: 14px; }
.skeleton-line-lg { width: 60%; height: 26px; }
.skeleton-line-title { width: 190px; height: 30px; }

.skeleton-line + .skeleton-line {
    margin-top: 0.6rem;
}

/* Mirrors .kpi-grid exactly so the real cards drop straight into the same boxes. */
.skeleton-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.85rem;
    margin-bottom: 1.1rem;
}

.skeleton-card {
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
    padding: 0.9rem 1rem 1.1rem;
}

.skeleton-rows {
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: var(--iem-shadow);
    padding: 0.4rem 1rem;
}

.skeleton-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--iem-line);
}

.skeleton-row:last-child {
    border-bottom: 0;
}

.skeleton-row .skeleton-line {
    margin-top: 0;
}

.skeleton-row .skeleton-line-sm {
    width: 22%;
    flex: 0 0 auto;
}

.skeleton-row .skeleton-line-md {
    flex: 1 1 auto;
    max-width: 55%;
}

/* --- Boot placeholder (shown until the SignalR circuit connects) -------------- */
.app-boot-head {
    margin-bottom: 1.1rem;
}

.app-boot-head .skeleton-line-xs {
    width: 120px;
}

/* Only revealed once the wait stops looking normal, so a fast load never shows it. */
.app-boot-slow-note {
    display: none;
    text-align: center;
    color: var(--iem-muted);
    font-size: 0.82rem;
    margin: 0;
}

.app-boot.is-slow .app-boot-slow-note {
    display: block;
}

/* =============================================================================
   Modal dialog
   ============================================================================= */

.modal-backdrop-iem {
    position: fixed;
    inset: 0;
    z-index: 1080;
    background: rgba(24, 24, 27, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    overflow-y: auto;
}

.modal-iem {
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: var(--iem-radius);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
    width: 100%;
    max-width: 420px;
    /* The dialog itself scrolls, so a long form never pushes its buttons off screen. */
    max-height: calc(100vh - 2rem);
    display: flex;
    flex-direction: column;
    outline: none;
}

.modal-iem-wide {
    max-width: 620px;
}

.modal-iem-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.9rem 1.15rem;
    border-bottom: 1px solid var(--iem-line);
    flex: 0 0 auto;
}

.modal-iem-head h2 {
    font-size: 0.98rem;
    font-weight: 650;
    margin: 0;
}

.modal-iem-close {
    background: none;
    border: 0;
    color: var(--iem-muted);
    padding: 0.3rem;
    line-height: 0;
    border-radius: var(--iem-radius-sm);
    cursor: pointer;
}

.modal-iem-close:hover {
    background: var(--iem-hover);
    color: var(--iem-ink);
}

.modal-iem-close svg {
    width: 18px;
    height: 18px;
}

.modal-iem-body {
    padding: 1.05rem 1.15rem;
    overflow-y: auto;
    flex: 1 1 auto;
}

/* Buttons sit on one row and stay reachable at the bottom of the dialog. */
.modal-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.modal-actions .btn {
    min-width: 96px;
}

.modal-note {
    font-size: 0.82rem;
    color: var(--iem-muted);
    margin: 0.5rem 0 0;
}

.modal-summary {
    background: var(--iem-canvas);
    border-radius: var(--iem-radius-sm);
    padding: 0.6rem 0.75rem;
    font-size: 0.85rem;
    margin: 0.75rem 0 0;
}

.modal-summary dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.2rem 0.75rem;
    margin: 0;
}

.modal-summary dt {
    color: var(--iem-muted);
    font-weight: 500;
}

.modal-summary dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
    .modal-backdrop-iem {
        padding: 0;
        align-items: flex-end;
    }

    /* Full-width sheet anchored to the bottom - closer to the thumb than a centred box. */
    .modal-iem {
        max-width: none;
        max-height: 92vh;
        border-radius: var(--iem-radius) var(--iem-radius) 0 0;
        border-bottom: 0;
    }

    .modal-actions .btn {
        flex: 1 1 auto;
    }
}

/* Keeps Edit and Delete side by side, and stops them stretching full width inside a stacked card. */
.row-actions {
    display: flex;
    gap: 0.4rem;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.quick-add {
    margin-bottom: 1.1rem;
}

/* =============================================================================
   Anonymous auth pages (AuthLayout: login / register)
   ============================================================================= */

.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: radial-gradient(1200px 600px at 15% -10%, #ffe9d6 0%, transparent 55%),
                radial-gradient(900px 500px at 95% 110%, #ffe2cc 0%, transparent 55%),
                #f7f6f3;
}

.auth-card {
    width: 100%;
    max-width: 25rem;
    background: var(--iem-surface);
    border: 1px solid var(--iem-line);
    border-radius: 18px;
    padding: 2rem 1.9rem;
    box-shadow: 0 18px 44px rgba(24, 20, 16, 0.1);
}

.auth-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--iem-ink);
    margin-bottom: 1.35rem;
}

.auth-card h1 {
    font-size: 1.4rem;
    font-weight: 650;
    margin-bottom: 0.3rem;
    text-align: center;
}

.auth-lede {
    text-align: center;
    font-size: 0.83rem;
    color: var(--iem-muted);
    margin-bottom: 1.3rem;
}

.auth-card .form-group {
    margin-bottom: 0.8rem;
}

.auth-card .form-group label {
    display: block;
}

.auth-card .btn-primary {
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.5rem 0.9rem;
}

.auth-card .auth-alt {
    margin-top: 1.1rem;
    margin-bottom: 0;
    text-align: center;
    font-size: 0.84rem;
    color: var(--iem-muted);
}

/* Configuration/server errors are long and must stay readable rather than overflow the card. */
.auth-card .alert {
    font-size: 0.83rem;
    word-break: break-word;
}
