/* === Design tokens (theme-driven) ===
 *
 * All theme-sensitive values must be expressed in terms of these
 * custom properties. Dark mode is a token-override at
 * :root[data-theme="dark"] in Task 10. Adding a third theme is a
 * matter of adding another [data-theme="<name>"] block.
 */
:root {
  --c-bg:           #f8fafc;
  --c-surface:      #ffffff;
  --c-surface-alt:  #f9fafb;   /* slightly-off-white inside cards (table headers, zebra) */
  --c-border:       #e2e8f0;
  --c-text:         #0f172a;
  --c-muted:        #64748b;

  --c-side-bg:      #0f172a;
  --c-side-text:    #e2e8f0;
  --c-side-muted:   #94a3b8;
  --c-side-divider: #1e293b;
  --c-side-active:  #1d4ed8;

  --c-accent:       #1d4ed8;
  --c-footer-bg:    #f1f5f9;
}

:root[data-theme="dark"] {
  --c-bg:           #0b1220;
  --c-surface:      #111a2e;
  --c-surface-alt:  #0f1a30;
  --c-border:       #1f2a44;
  --c-text:         #e2e8f0;
  --c-muted:        #94a3b8;

  --c-side-bg:      #070c1a;
  --c-side-text:    #cbd5e1;
  --c-side-muted:   #94a3b8;
  --c-side-divider: #1f2a44;
  --c-side-active:  #3b82f6;

  --c-accent:       #3b82f6;
  --c-footer-bg:    #0f1a30;
}

/* Confidential chip needs theme-specific values (not pure tokens). */
:root[data-theme="dark"] .chip-confidential {
  background: #78350f; color: #fde68a;
}

/* === Reset & base === */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--c-bg);
  color: var(--c-text);
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
a { color: var(--c-accent); }

/* Form controls do not inherit the page font. Left alone they render in the
   browser's default face (Arial) at its default size, which reads as a
   different font wherever a control sits beside body text — most visibly in a
   table cell. .event-form patched this locally for one page; this is the same
   fix for all of them. Buttons keep their own sizing from .btn / .btn-small,
   so only the face is normalised for them. */
input, select, textarea, button { font-family: inherit; }
input, select, textarea { font-size: inherit; }

:root {
  /* Legacy tokens aliased to the new --c-* tokens so dark mode
     (Task 10) flows through to the report-card / KPI / table CSS
     that still references these names. */
  --bg:          var(--c-bg);
  --card-bg:     var(--c-surface);
  --text:        var(--c-text);
  --text-muted:  var(--c-muted);
  --border:      var(--c-border);
  --accent:      var(--c-accent);

  /* Semantic / theme-neutral — keep as literals. */
  --green:       #22c55e;
  --red:         #ef4444;
  --gray:        #6b7280;
  --shadow:      0 1px 3px rgba(0,0,0,0.1);
  --radius:      8px;
}

/* === Container === */
.container {
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 1.5rem;
}

/* === Main Content === */
main.container {
    padding-top: 1.5rem;
    padding-bottom: 2rem;
}

/* .container centres with `margin: 0 auto`, but main.page-body is a flex item
   inside the column-flex .app-main — and auto cross-axis margins stop a flex
   item stretching, so it shrink-to-fits its content instead. The result was
   that a page filled the width only if it happened to contain something wide
   (the ledger's table), while a page of cards or a narrow table collapsed and
   floated in the middle. Fill the column; max-width above still caps it. */
main.page-body.container {
    margin-left: 0;
    margin-right: 0;
    width: 100%;
}

h1 {
    font-size: 1.75rem;
    margin-bottom: 1.5rem;
    font-weight: 700;
}

h3 {
    font-size: 1.1rem;
    margin-bottom: 1rem;
    font-weight: 600;
}

/* === Cards === */
.card {
    background: var(--card-bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

/* === KPI Grid (Dashboard) === */
.kpi-grid-2col {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.kpi-card-wide {
    /* intentionally no special width — flows naturally in 3-col grid */
}

.kpi-dual {
    display: flex;
    gap: 1.5rem;
}

.kpi-dual-item {
    flex: 1;
    min-width: 0;
}

.kpi-card {
    background: var(--card-bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.25rem;
    border-left: 4px solid var(--accent);
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.kpi-label {
    font-size: 0.8rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.25rem;
}

.kpi-value {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 0.25rem;
}

.kpi-change {
    font-size: 0.85rem;
    font-weight: 500;
}

.kpi-sub {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.kpi-change.up, .positive { color: var(--green); }
.kpi-change.down, .negative { color: var(--red); }
.kpi-change.flat { color: var(--gray); }

.sparkline-canvas {
    margin-top: 0.5rem;
}

.country-tags, .country-tags-inline {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.country-tags-inline {
    margin-top: 0.5rem;
}

.country-tag {
    background: var(--c-surface-alt);
    color: var(--accent);
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 500;
}

.table-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.table-header-row h3 {
    margin-bottom: 0;
}

.kpi-new-badge {
    font-size: 0.5em;
    font-weight: 500;
    color: var(--color-positive, #22c55e);
    vertical-align: middle;
}

.sortable-th {
    cursor: pointer;
    user-select: none;
}

.sortable-th:hover {
    background: var(--bg-hover, rgba(0,0,0,0.05));
}

.sort-indicator {
    font-size: 0.75em;
}

.upcoming-payouts-badge {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* === Summary Cards === */
.summary-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.summary-card {
    background: var(--card-bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.25rem;
    border-left: 4px solid var(--accent);
}

.summary-label {
    font-size: 0.8rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.25rem;
}

.summary-value {
    font-size: 1.3rem;
    font-weight: 700;
}

.summary-note {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 0.25rem;
}

/* === Charts === */
.charts-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
    margin-bottom: 1.5rem;
}

.charts-grid .card canvas {
    width: 100% !important;
    max-height: 350px;
}

/* === Tables === */
.tables-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
    margin-bottom: 1.5rem;
}

.table-scroll {
    width: 100%;
    overflow-x: auto;
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.data-table th {
    background: var(--c-surface-alt);
    text-align: left;
    padding: 0.6rem 0.75rem;
    border-bottom: 2px solid var(--border);
    font-weight: 600;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.data-table th:hover {
    background: var(--c-surface-alt);
}

.data-table th .sort-indicator {
    margin-left: 0.25rem;
    opacity: 0.5;
}

.data-table th.sorted .sort-indicator {
    opacity: 1;
}

.data-table td {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--border);
}

.data-table tbody tr:nth-child(even) {
    background: var(--c-surface-alt);
}

.data-table tbody tr:hover {
    background: var(--c-surface-alt);
}

.data-table .numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* === Tier Tree === */
.tier-tree th {
    cursor: default;
}

.tier-tree th:hover {
    background: var(--c-surface-alt);
}

.tier-product-row td {
    font-weight: 600;
    background: var(--c-surface-alt);
}

.tier-child-row td {
    font-weight: 400;
}

.tier-indent {
    padding-left: 2rem !important;
}

.empty-msg {
    text-align: center;
    color: var(--text-muted);
    padding: 2rem !important;
}

/* === Status Badges === */
.status-badge {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: uppercase;
}

.status-paid, .status-active { background: #dcfce7; color: #166534; }
.status-pending { background: #fef3c7; color: #92400e; }
.status-in_transit { background: #dbeafe; color: #1e40af; }
.status-failed { background: #fecaca; color: #991b1b; }
.status-canceled { background: #f3f4f6; color: #374151; }

/* === Category Badges === */
.category-badge {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
}

.category-social_media { background: #ede9fe; color: #6d28d9; }
.category-product_launch { background: #cffafe; color: #0e7490; }
.category-pricing_change { background: #ffedd5; color: #c2410c; }
.category-marketing { background: #fce7f3; color: #be185d; }
.category-press { background: #ccfbf1; color: #0f766e; }
.category-general { background: #f3f4f6; color: #374151; }
.category-event { background: #fef9c3; color: #854d0e; }
.category-conference { background: #dbeafe; color: #1e40af; }

/* === Events configuration page === */
.date-range-sep {
    margin: 0 0.25rem;
    color: var(--text-muted);
}

.data-table.sortable th[data-sortable] {
    user-select: none;
}
.data-table.sortable th.sorted .sort-indicator {
    color: var(--c-accent, currentColor);
    font-weight: 700;
}

/* Modal dialog (used for event edit). Reuses the dialog element's
   built-in backdrop + ESC + focus management. */
.app-modal {
    width: min(640px, 92vw);
    max-height: 86vh;
    padding: 0;
    border: 1px solid var(--border, #cbd5e1);
    border-radius: 8px;
    background: var(--card-bg, #fff);
    color: var(--c-text, inherit);
}
.app-modal::backdrop {
    background: rgba(15, 23, 42, 0.45);
}
.app-modal > form {
    padding: 1rem 1.25rem 1.25rem;
}
.app-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--border, #e2e8f0);
}
.app-modal-header h3 { margin: 0; font-size: 1rem; }
.app-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border, #e2e8f0);
}

/* === Channel Badges === */
.channel-badge {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: uppercase;
}

/* Tabular identifiers (account last4, routing/BIC) — monospace so digit
   groups line up down the column. */
.mono { font-family: 'SF Mono', 'Fira Code', monospace; }

/* Both of these were already used across bank_accounts, bank_upload and the
   settings pages but never defined, so secondary text has been rendering at
   full contrast and card headings at browser-default h3 size. */
.muted { color: var(--text-muted); }

.card-title {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    font-weight: 600;
}

.channel-donations { background: #e0e7ff; color: #3730a3; }
.channel-sales     { background: #ffe4e6; color: #9d174d; }

/* Lets the events table card escape the 1400px .container cap and use
   the full viewport minus the sidebar. The negative margins reach back
   from the container's centered box out to the page body edges. */
.events-table-fullwidth {
    width: calc(100vw - 240px - 44px);
    position: relative;
    left: 50%;
    transform: translateX(-50%);
}
@media (max-width: 1023.98px) {
    /* Below the sidebar breakpoint the sidebar is an off-canvas drawer
       (margin-left: 0 on .app-main), so don't subtract its width. */
    .events-table-fullwidth {
        width: calc(100vw - 44px);
    }
}

/* Slug shown as a subdued secondary chip next to a resolved event title. */
.event-slug-secondary {
    display: inline-block;
    margin-left: 0.4rem;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.event-slug-secondary code {
    background: var(--c-surface-alt);
    padding: 1px 6px;
    border-radius: 4px;
}

/* === Report Controls === */
.report-controls {
    background: var(--card-bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1rem 1.5rem;
    margin-bottom: 1.5rem;
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
}

.controls-form {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    flex: 1;
    flex-wrap: wrap;
}

.controls-form label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.controls-form select,
.controls-form input[type="number"] {
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.9rem;
    background: var(--c-surface);
}

.controls-form input[type="number"] {
    width: 80px;
}

/* === Inline Report Controls (in header row) === */
.report-controls-inline {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.controls-form-inline {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.controls-form-inline select,
.controls-form-inline input[type="number"] {
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.85rem;
    background: var(--c-surface);
}

.controls-form-inline input[type="number"] {
    width: 65px;
}

/* === Buttons === */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 6px;
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s;
}

.btn-primary { background: var(--c-accent); color: #fff; border: 1px solid var(--c-accent); }
.btn-primary:hover { filter: brightness(0.92); }
.btn-secondary { background: var(--c-surface-alt); color: var(--c-text); border: 1px solid var(--c-border); }
.btn-secondary:hover { background: var(--c-surface); border-color: var(--c-muted); }
.btn-danger { background: var(--red); color: #fff; border: 1px solid var(--red); }
.btn-danger:hover { filter: brightness(0.92); }
.btn-small { padding: 0.3rem 0.6rem; font-size: 0.8rem; }

/* Compact icon-only buttons (e.g. Edit/Delete in tables).
   Themed via tokens so both light and dark have visible contrast. */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Also used on <a>, where a glyph child would otherwise be underlined. */
    text-decoration: none;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--c-border);
    border-radius: 4px;
    background: var(--c-surface);
    color: var(--c-text);
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.btn-icon:hover { background: var(--c-surface-alt); }
.btn-icon-danger { color: var(--red); border-color: var(--c-border); }
.btn-icon-danger:hover { background: var(--red); color: #fff; border-color: var(--red); }

/* === CSV Dropdown === */
.csv-dropdown {
    position: relative;
}

.csv-dropdown .dropdown-menu {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 50;
    min-width: 200px;
    margin-top: 0.25rem;
}

.csv-dropdown.open .dropdown-menu {
    display: block;
}

.csv-dropdown .dropdown-menu a {
    display: block;
    padding: 0.6rem 1rem;
    color: var(--text);
    text-decoration: none;
    font-size: 0.9rem;
    border-bottom: 1px solid var(--border);
}

.csv-dropdown .dropdown-menu a:last-child {
    border-bottom: none;
}

.csv-dropdown .dropdown-menu a:hover {
    background: var(--c-surface-alt);
}

/* === Forms === */
.event-form .form-row {
    display: flex;
    gap: 1rem;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.event-form label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.85rem;
    color: var(--text-muted);
    flex: 1;
    min-width: 150px;
}

.event-form label.full-width {
    flex: 100%;
}

.event-form input,
.event-form select,
.event-form textarea {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.9rem;
}

.event-form textarea {
    resize: vertical;
}

.edit-row td {
    background: #fefce8 !important;
}

.inline-edit {
    padding: 0.5rem 0;
}

.actions-cell {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

/* === Sync Page === */
.sync-actions {
    margin-bottom: 1.5rem;
}

.sync-status {
    font-size: 0.85rem;
    margin-left: 0.5rem;
}

.sync-status.success { color: var(--green); }
.sync-status.error { color: var(--red); }

#sync-log {
    margin-top: 1.5rem;
}

#log-output {
    background: #1a1a2e;
    color: #a5f3fc;
    padding: 1rem;
    border-radius: 6px;
    font-family: 'SF Mono', 'Fira Code', monospace;
    font-size: 0.8rem;
    max-height: 300px;
    overflow-y: auto;
    white-space: pre-wrap;
}

/* === Glossary === */
.glossary-section {
    margin-bottom: 1.5rem;
}

.glossary dt {
    font-weight: 600;
    margin-top: 0.75rem;
}

.glossary dd {
    color: var(--text-muted);
    margin-left: 1rem;
}

details summary {
    cursor: pointer;
    padding: 0.5rem 0;
}

/* === Pagination === */
.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem 0 0;
    font-size: 0.9rem;
}

.pagination button {
    padding: 0.4rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--card-bg);
    color: var(--c-text);
    cursor: pointer;
    font-size: 0.85rem;
}

.pagination button:hover:not(:disabled) {
    background: var(--c-surface-alt);
}

.pagination button:disabled {
    opacity: 0.4;
    cursor: default;
}

/* === Responsive === */
@media (max-width: 1024px) {
    .kpi-grid-2col {
        grid-template-columns: repeat(2, 1fr);
    }
    .kpi-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .charts-grid {
        grid-template-columns: 1fr;
    }
    .tables-grid {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 768px) {
    .kpi-grid-2col {
        grid-template-columns: 1fr;
    }
    .kpi-grid {
        grid-template-columns: 1fr;
    }
    .kpi-dual {
        flex-direction: column;
        gap: 0.75rem;
    }
    .report-controls {
        flex-direction: column;
        align-items: stretch;
    }
    .controls-form {
        flex-direction: column;
    }
    .report-controls-inline {
        flex-wrap: wrap;
        width: 100%;
    }
    .controls-form-inline {
        flex-wrap: wrap;
    }
}

/* === Print Styles === */
@media print {
    .no-print {
        display: none !important;
    }

    /* App chrome: only the footer + content survives print. */
    .sidebar,
    .drawer-toggle,
    .drawer-backdrop {
        display: none !important;
    }

    .app-main { display: block; }
    .page-body { padding: 0; }

    body {
        background: #fff !important;
        color: #000 !important;
        font-size: 11pt;
    }

    /* Force the confidential chip to print its yellow background. */
    .chip-confidential {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .report-controls,
    .report-controls-inline,
    .csv-dropdown,
    .pagination,
    .sync-actions,
    #sync-log,
    .actions-cell,
    button {
        display: none !important;
    }

    .container {
        max-width: 100%;
        padding: 0;
    }

    .card {
        box-shadow: none;
        border: 1px solid #ddd;
        break-inside: avoid;
        margin-bottom: 1rem;
    }

    .kpi-card,
    .summary-card {
        box-shadow: none;
        border: 1px solid #ddd;
    }

    .report-section {
        break-before: page;
    }

    .report-section:first-of-type {
        break-before: auto;
    }

    .data-table thead {
        position: static;
    }

    .data-table tr {
        break-inside: avoid;
    }

    .kpi-grid-2col {
        grid-template-columns: repeat(3, 1fr);
    }

    .kpi-grid {
        grid-template-columns: repeat(4, 1fr);
    }

    .charts-grid {
        grid-template-columns: 1fr;
    }

    h1::after {
        content: " - Generated " attr(data-date);
        font-size: 0.6em;
        color: #666;
        font-weight: normal;
    }
}

/* PII redaction transparency notice (shown under viewer-facing maps) */
.redaction-notice {
    font-size: 0.85rem;
    color: #666;
    text-align: center;
    margin: 0.5rem 0 1rem 0;
    font-style: italic;
}

/* === Layout shell === */
/* Sidebar is position:fixed so it stays anchored during overscroll
   rubberband. .app-main therefore needs a manual left margin to make
   room. The mobile media query (<1024px) sets margin-left:0. */
.app-shell { display: flex; min-height: 100vh; }
.app-main  { flex: 1; margin-left: 240px; display: flex; flex-direction: column; min-width: 0; background: var(--c-bg); color: var(--c-text); overflow-x: hidden; }
.page-body { flex: 1; padding: 18px 22px; min-width: 0; max-width: 100%; }

/* === Sidebar === */
.sidebar {
  width: 240px;
  background: var(--c-side-bg);
  color: var(--c-side-text);
  display: flex; flex-direction: column;
  flex-shrink: 0;
  border-right: 1px solid var(--c-side-divider);
  /* Fixed so rubberband / overscroll bounces the page, not the sidebar. */
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 5;
}
.sidebar-brand { padding: 16px 16px 12px; }
.sidebar-brand a { color: var(--c-side-text); text-decoration: none;
                   display: inline-flex; align-items: center; }
/* The SVG ships with --logo-primary defaulting to a Wireshark blue and
   --logo-accent: currentColor. Sidebar is always dark — pin a light
   accent so the secondary strokes read against the navy background. */
.sidebar-logo { height: 44px; width: auto; display: block;
                color: #e2e8f0; /* drives currentColor inside the svg */ }
.sidebar-nav { flex: 1; padding: 4px 8px; overflow-y: auto; }
.sidebar-group { margin-top: 8px; }
.sidebar-group-label { padding: 6px 10px; font-size: 10px;
                       letter-spacing: 0.08em; color: var(--c-side-muted);
                       text-transform: uppercase; }
.sidebar-group-system { margin-top: 16px; border-top: 1px solid var(--c-side-divider);
                        padding-top: 8px; }
.sidebar-link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px 6px 22px;
  color: var(--c-side-text); text-decoration: none; border-radius: 4px;
  font-size: 13px;
}
.sidebar-link.top { padding-left: 10px; font-weight: 500; }
/* One nested level, indented past its parent. */
.sidebar-link.sub { padding-left: 34px; }
.sidebar-link:hover:not(.soon) { background: var(--c-side-divider); }
.sidebar-link.active { background: var(--c-side-active); color: #fff; }
.sidebar-link.soon { color: var(--c-side-muted); cursor: not-allowed; }
.badge-soon {
  font-size: 9px; background: var(--c-side-divider);
  color: var(--c-side-muted); padding: 1px 6px; border-radius: 8px;
  letter-spacing: 0.04em;
}
.sidebar-foot {
  padding: 10px 12px; border-top: 1px solid var(--c-side-divider);
  display: flex; align-items: center; gap: 8px;
}
.sidebar-user { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
                color: inherit; text-decoration: none; }
.sidebar-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--c-accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.sidebar-user-text { display: flex; flex-direction: column; min-width: 0; }
.sidebar-user-name { color: #fff; font-size: 12px; white-space: nowrap;
                     overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-role { color: var(--c-side-muted); font-size: 10px; }
.theme-toggle, .sidebar-logout-btn {
  background: transparent; border: 1px solid var(--c-side-divider);
  color: var(--c-side-text); padding: 3px 8px; border-radius: 4px;
  font-size: 11px; cursor: pointer;
}
.theme-toggle { padding: 3px 6px; line-height: 1; }
.sidebar-logout-form { margin: 0; }

/* === Page header bar === */
.page-header {
  background: var(--c-surface); border-bottom: 1px solid var(--c-border);
  padding: 14px 22px; display: flex; align-items: center;
  justify-content: space-between; gap: 12px;
}
.page-header-titles { min-width: 0; }
.page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--c-text); }
.page-meta  { font-size: 11px; color: var(--c-muted); margin-top: 2px; }
.page-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.page-actions select,
.page-actions input,
.page-actions button {
  font-size: 12px; padding: 4px 10px; border: 1px solid var(--c-border);
  border-radius: 4px; background: var(--c-surface); color: var(--c-text);
  cursor: pointer;
}
.page-actions button.primary,
.page-actions button.btn-primary {
  background: var(--c-accent); color: #fff; border-color: var(--c-accent);
}
.page-actions button.btn-danger {
  background: var(--red); color: #fff; border-color: var(--red);
}

/* === Footer === */
.app-footer {
  background: var(--c-footer-bg); border-top: 1px solid var(--c-border);
  padding: 10px 22px; font-size: 11px; color: var(--c-muted);
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: space-between;
  align-items: center;
}
.app-footer strong { color: var(--c-text); font-weight: 600; }
.app-footer .sep   { opacity: 0.6; }
.app-footer .build,
.app-footer .timestamp { opacity: 0.8; }
.chip-confidential {
  background: #fef3c7; color: #92400e;
  padding: 2px 8px; border-radius: 4px; font-weight: 600;
  letter-spacing: 0.04em; font-size: 10px;
}

/* === Drawer toggle (hidden on desktop; revealed in Task 13) === */
.drawer-toggle { display: none; }

/* === Drawer-mode for narrow viewports === */
@media (max-width: 1023.98px) {
  /* Sidebar is desktop-fixed; on mobile it becomes an off-canvas drawer
     and .app-main must give up its desktop margin-left. */
  .app-main { margin-left: 0; }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: 240px; z-index: 30;
    transform: translateX(-100%); transition: transform 180ms ease-out;
  }
  .sidebar.drawer-open { transform: translateX(0); box-shadow: 6px 0 18px rgba(0,0,0,0.25); }
  .drawer-toggle {
    display: inline-block; background: var(--c-side-bg); color: #fff;
    border: 0; padding: 6px 12px; border-radius: 6px;
    font-size: 12px; font-weight: 600; margin: 12px 12px 0; cursor: pointer;
  }
  .drawer-backdrop {
    position: fixed; inset: 0; background: rgba(15,23,42,0.45);
    z-index: 20;
  }
  .page-header { padding: 10px 14px; }
  .page-actions { gap: 6px; }
  .app-footer  { padding: 8px 12px; font-size: 10px; }
  .app-footer .build, .app-footer .timestamp { display: none; }
}

/* -- Chart event strip ----------------------------------------------------
   Sits beneath each chart canvas as a wrapping row of chips ordered by
   date. The dashed vertical line inside the chart marks the event's
   x position; the chip below names it. */
.chart-events {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    margin: 10px 4px 0;
    padding-top: 8px;
    border-top: 1px solid var(--c-border, rgba(255, 255, 255, 0.06));
}
.chart-event-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    line-height: 1.5;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--chip-color, #64748b);
    color: var(--c-text);
    white-space: nowrap;
}
.chart-event-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--chip-color, #64748b);
    flex: 0 0 7px;
}
.chart-event-title { font-weight: 500; }
.chart-event-date {
    color: var(--c-muted);
    font-variant-numeric: tabular-nums;
}

/* --- Inline status messages -------------------------------------------------
 * Used by the statement upload flow, where a refused parse is a designed
 * outcome rather than an exception and has to read as a page, not a stack
 * trace. Left-border accent instead of a filled panel so the same markup works
 * in both themes without theme-specific overrides.
 */
.msg-error,
.msg-ok {
    border-left: 3px solid;
    padding-left: 1rem;
}

.msg-error { border-left-color: #dc2626; }
.msg-ok    { border-left-color: #16a34a; }

.msg-error strong { color: #dc2626; }
.msg-ok strong    { color: #16a34a; }

/* Wide tables scroll inside their card rather than spilling past it.
 * The bank accounts table is 8 columns and clips its action column below
 * ~1100px of content width; scrolling keeps every column reachable without
 * deciding which data is expendable. */
.table-wrap {
    overflow-x: auto;
}

/* === Statement drop zone === */
.dropzone {
    display: block;
    border: 2px dashed var(--border);
    border-radius: 8px;
    background: var(--card-bg);
    padding: 2rem 1rem;
    margin: 1rem 0;
    text-align: center;
    color: var(--text-muted);
    cursor: pointer;
}

.dropzone:hover,
.dropzone.is-dragover {
    border-color: var(--accent);
    color: var(--accent);
}

.dropzone input[type="file"] {
    margin-top: 0.75rem;
    font-size: 0.85rem;
}

.dropzone-meta {
    display: block;
    margin-top: 0.5rem;
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* === Bank ledger ===
   The Counterparty column replaces a raw description dump: bold who it was,
   subdued what the bank said about it. The full raw string stays as the cell's
   title attribute, and is what search matches. */
.ledger-party {
    font-weight: 600;
}

.ledger-ref {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-top: 0.1rem;
}

.section-badge {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 500;
    background: var(--surface-alt, #f1f5f9);
    color: var(--text-muted);
    border: 1px solid var(--border, #e2e8f0);
    white-space: nowrap;
}

/* A person's note on a line, under the counterparty. Distinguished from the
   machine-derived reference above it by weight and a quote mark rather than
   another colour. */
.ledger-note {
    margin-top: 0.25rem;
    font-size: 0.82rem;
    font-style: italic;
    color: var(--c-text);
}

.ledger-note::before { content: "\201C"; }
.ledger-note::after  { content: "\201D"; }

.note-form { display: flex; gap: 0.5rem; }
.note-form input { flex: 1; min-width: 0; }

/* Regex-assigned tags, under the counterparty. One neutral treatment for every
   tag: seven of them read fine without seven colours, and a per-tag palette is
   a schema column plus a contrast audit for no gain yet. */
.ledger-tags {
    margin-top: 0.25rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.tag-badge {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 500;
    background: #eff6ff;
    color: #1e40af;
    border: 1px solid #bfdbfe;
    white-space: nowrap;
}

:root[data-theme="dark"] .tag-badge {
    background: #16263a;
    color: #b8d0ee;
    border-color: #35506e;
}

/* An expanded row's cell. Page background inside a card surface reads as
   recessed rather than as one more table row, and the accent edge ties it to
   the row it opened from. A cell's own background paints over the row's, so
   this survives the zebra striping and the hover rule. */
.drawer-cell {
    /* Tinted toward the accent rather than just a shade of grey: the page
       background is too close to the card surface to read as a separate
       layer, and the tint matches the accent edge tying it to its row. */
    background: #eef2ff;
    border-left: 3px solid var(--c-accent);
    padding: 1rem;
}

:root[data-theme="dark"] .drawer-cell { background: #1b2c4d; }

/* A grid of cards. Same shape as .kpi-grid but not tied to KPIs, so an index
   of sections can use it without inheriting a name that lies. */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1rem;
}

/* A card that IS the link, rather than a card containing one. */
a.card {
    display: block;
    color: inherit;
    text-decoration: none;
    margin-bottom: 0;
}

a.card:hover { border-color: var(--accent); box-shadow: var(--shadow-lg, var(--shadow)); }

/* Unmatched CREDITS only. A debit has no Stripe counterpart to miss, so
   flagging one would flag every debit. */
.badge-unmatched {
    background: #fef3c7;
    color: #92400e;
    border-color: #fde68a;
}

:root[data-theme="dark"] .badge-unmatched {
    background: #3f2d0a;
    color: #fcd34d;
    border-color: #78500b;
}

/* The sentinel row. It is a real link, so it works with JavaScript disabled;
   the IntersectionObserver merely clicks it when it scrolls into view. */
.ledger-sentinel td {
    text-align: center;
    padding: 0.75rem;
}
