/* ==========================================================================
   Expense Manager - admin panel styles
   Hand written (no build step) so the app runs with PHP alone.
   ========================================================================== */

:root {
    --bg: #f4f6fb;
    --surface: #ffffff;
    --border: #e2e8f0;
    --text: #0f172a;
    --muted: #64748b;
    --brand: #4f46e5;
    --brand-dark: #4338ca;
    --credit: #059669;
    --credit-soft: #ecfdf5;
    --expense: #dc2626;
    --expense-soft: #fef2f2;
    --warn: #b45309;
    --sidebar: #ffffff;
    --sidebar-muted: #64748b;
    --sidebar-label: #94a3b8;
    --sidebar-hover: #f1f5f9;
    --radius: 10px;
    --radius-sm: 7px;
    --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 8px 24px rgba(15, 23, 42, .05);
    --field-h: 40px;
    --gap: 20px;
    /* Shared by the sidebar brand and the topbar so their bottom borders
       line up as one continuous rule across the page. */
    --header-h: 72px;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    /* Both elements, not just body: with it on body alone the viewport can
       still scroll sideways, because html's own overflow is what propagates
       to the viewport. */
    overflow-x: hidden;
    max-width: 100%;
}

body {
    background: var(--bg);
    color: var(--text);
    font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* Nothing may exceed its container. Desktop is unaffected - no image or
   media here is wider than its box already - but it stops an oversized
   upload preview from pushing the page sideways on a phone. */
img, svg, video, canvas { max-width: 100%; }

/* Long titles, emails and pasted URLs wrap instead of widening the layout. */
.topbar__title h1,
.card__head h2,
.stat__value,
.dl__row dd,
.attachment__meta,
.empty p { overflow-wrap: break-word; }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
h1 { font-size: 1.4rem; }
h2 { font-size: 1.05rem; }
h3 { font-size: .95rem; }

/* ---------- Layout ---------- */

.layout { display: flex; min-height: 100vh; }

.sidebar {
    width: 248px;
    flex: 0 0 248px;
    background: var(--sidebar);
    color: var(--text);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    gap: 10px;
    height: var(--header-h);
    flex: 0 0 var(--header-h);
    padding: 0 20px;
    font-weight: 700;
    font-size: 1.02rem;
    color: var(--text);
    border-bottom: 1px solid var(--border);
}

.sidebar__brand .mark {
    display: grid;
    place-items: center;
    width: 30px; height: 30px;
    border-radius: 8px;
    background: var(--brand);
    color: #fff;
    font-size: .95rem;
}

/* Desktop never shows the drawer's close button. */
.sidebar__close { display: none; }

/* flex:1 + overflow-y means a short screen scrolls the menu, not the page,
   and the brand stays pinned at the top. */
.sidebar__nav { padding: 12px 12px 24px; overflow-y: auto; flex: 1; }

.sidebar__label {
    padding: 14px 10px 6px;
    font-size: .68rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sidebar-label);
}

.navlink {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 11px;
    margin-bottom: 2px;
    border-radius: var(--radius-sm);
    color: var(--sidebar-muted);
    font-size: .9rem;
    font-weight: 500;
}
.navlink:hover { background: var(--sidebar-hover); color: var(--text); text-decoration: none; }
.navlink--active { background: var(--brand); color: #fff; }
/* Must restate the colour: .navlink:hover outranks .navlink--active, so
   without this the active link's text goes dark on hover. */
.navlink--active:hover { background: var(--brand-dark); color: #fff; }
.navlink svg { width: 17px; height: 17px; flex: 0 0 17px; }

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

/* Top progress bar for AJAX navigation. */
#nav-progress {
    position: fixed;
    top: 0; left: 0;
    height: 3px;
    width: 0;
    z-index: 400;
    /* Never intercept a click, however briefly it overlaps something. */
    pointer-events: none;
    background: var(--brand);
    opacity: 0;
    transition: width .25s ease, opacity .2s ease;
}
#nav-progress.is-active {
    width: 85%;
    opacity: 1;
    /* Creeps toward 85% while waiting, then the swap removes it. */
    transition: width 1.6s cubic-bezier(.1, .8, .2, 1), opacity .1s;
}

.topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    height: var(--header-h);
    padding: 0 24px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar__title { flex: 1; min-width: 0; }
.topbar__title h1 { font-size: 1.12rem; }

.breadcrumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    font-size: .78rem;
    color: var(--muted);
    margin-top: 2px;
}
.breadcrumbs span + span::before { content: "/"; margin-right: 6px; color: #cbd5e1; }

.hamburger {
    display: none;
    width: 38px; height: 38px;
    align-items: center; justify-content: center;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    cursor: pointer;
    flex: 0 0 auto;
}

.avatar {
    display: grid; place-items: center;
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--brand);
    color: #fff;
    font-size: .82rem;
    font-weight: 650;
    flex: 0 0 auto;
}

.content { padding: var(--gap) 24px 48px; flex: 1; }

/* ---------- Cards ---------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.card__head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 15px 18px;
    border-bottom: 1px solid var(--border);
}
.card__head h2 { flex: 1; min-width: 140px; }
.card__body { padding: 18px; }
.card__body--flush { padding: 0; }

.grid { display: grid; gap: var(--gap); }
.grid--stats { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.grid--halves { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.stack { display: grid; gap: var(--gap); }

.stat { padding: 17px 18px; }
.stat__label {
    font-size: .74rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
    font-weight: 600;
}
.stat__value { font-size: 1.55rem; font-weight: 700; margin-top: 7px; letter-spacing: -.02em; word-break: break-word; }
.stat__meta { font-size: .8rem; color: var(--muted); margin-top: 5px; }
.stat--credit .stat__value { color: var(--credit); }
.stat--expense .stat__value { color: var(--expense); }
.stat--balance .stat__value { color: var(--brand); }
.stat--negative .stat__value { color: var(--expense); }

/* ---------- Tables ---------- */

.table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.data { width: 100%; border-collapse: collapse; font-size: .88rem; min-width: 720px; }
/* Fewer columns need less room before the wrapper has to scroll. These are
   classes, not inline styles - an inline min-width would outrank the mobile
   card layout and force the page to scroll sideways. */
table.data--narrow { min-width: 560px; }
table.data--compact { min-width: 420px; }
table.data th, table.data td { padding: 11px 14px; text-align: left; vertical-align: middle; }
table.data thead th {
    background: #f8fafc;
    border-bottom: 1px solid var(--border);
    font-size: .72rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
    font-weight: 650;
    white-space: nowrap;
}
table.data tbody tr + tr td { border-top: 1px solid var(--border); }
table.data tbody tr:hover { background: #fafbff; }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.data th.num { text-align: right; }
table.data .title { font-weight: 600; }
table.data .sub { color: var(--muted); font-size: .8rem; }

th.sortable a { color: inherit; display: inline-flex; gap: 4px; align-items: center; }
th.sortable a:hover { color: var(--text); text-decoration: none; }
th.sortable .arrow { color: var(--brand); }

/* ---------- Badges and pills ---------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: .74rem;
    font-weight: 650;
    white-space: nowrap;
}
.badge--expense { background: var(--expense-soft); color: var(--expense); }
.badge--credit { background: var(--credit-soft); color: var(--credit); }
.badge--muted { background: #f1f5f9; color: var(--muted); }
.badge--on { background: var(--credit-soft); color: var(--credit); }
.badge--off { background: #f1f5f9; color: var(--muted); }
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.amount--credit { color: var(--credit); font-weight: 650; }
.amount--expense { color: var(--expense); font-weight: 650; }

/* ---------- Buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: var(--field-h);
    padding: 0 15px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: .87rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s, border-color .12s;
}
.btn:hover { background: #f8fafc; text-decoration: none; }
.btn--primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn--primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn--danger { background: var(--expense); border-color: var(--expense); color: #fff; }
.btn--danger:hover { background: #b91c1c; border-color: #b91c1c; }
/* Secondary: paired with a primary action (Apply / Reset, Save / Cancel). */
.btn--secondary { background: #f1f5f9; border-color: var(--border); color: #334155; }
.btn--secondary:hover { background: #e2e8f0; border-color: #cbd5e1; color: var(--text); }

.btn--ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn--ghost:hover { background: #f1f5f9; color: var(--text); }
.btn--sm { height: 32px; padding: 0 11px; font-size: .8rem; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .6; cursor: not-allowed; }

.btn-row { display: flex; flex-wrap: wrap; gap: 9px; }
.actions { display: flex; gap: 5px; justify-content: flex-end; }

/* ==========================================================================
   12 column grid (Bootstrap-style class names)
   Breakpoints: xs = base, sm >= 576px, md >= 768px, lg >= 992px.
   Widths are relative to the ROW's container, not the viewport - a col-md-3
   inside a narrow card is a quarter of that card, so keep spans generous in
   modals and half-width panels.
   ========================================================================== */

.row { display: flex; flex-wrap: wrap; margin-left: -8px; margin-right: -8px; }
/* No width here on purpose. `.row > [class*="col-"]` scores 0,2,0, which would
   outrank every `.col-md-*` (0,1,0) and force all columns to full width. The
   base width comes from the col-xs-* class each field already carries. */
.row > [class*="col-"] { padding-left: 8px; padding-right: 8px; min-width: 0; }

.col-xs-1  { width: 8.3333%; }
.col-xs-2  { width: 16.6667%; }
.col-xs-3  { width: 25%; }
.col-xs-4  { width: 33.3333%; }
.col-xs-5  { width: 41.6667%; }
.col-xs-6  { width: 50%; }
.col-xs-7  { width: 58.3333%; }
.col-xs-8  { width: 66.6667%; }
.col-xs-9  { width: 75%; }
.col-xs-10 { width: 83.3333%; }
.col-xs-11 { width: 91.6667%; }
.col-xs-12 { width: 100%; }

@media (min-width: 576px) {
    .col-sm-1  { width: 8.3333%; }
    .col-sm-2  { width: 16.6667%; }
    .col-sm-3  { width: 25%; }
    .col-sm-4  { width: 33.3333%; }
    .col-sm-5  { width: 41.6667%; }
    .col-sm-6  { width: 50%; }
    .col-sm-7  { width: 58.3333%; }
    .col-sm-8  { width: 66.6667%; }
    .col-sm-9  { width: 75%; }
    .col-sm-10 { width: 83.3333%; }
    .col-sm-11 { width: 91.6667%; }
    .col-sm-12 { width: 100%; }
}

@media (min-width: 768px) {
    .col-md-1  { width: 8.3333%; }
    .col-md-2  { width: 16.6667%; }
    .col-md-3  { width: 25%; }
    .col-md-4  { width: 33.3333%; }
    .col-md-5  { width: 41.6667%; }
    .col-md-6  { width: 50%; }
    .col-md-7  { width: 58.3333%; }
    .col-md-8  { width: 66.6667%; }
    .col-md-9  { width: 75%; }
    .col-md-10 { width: 83.3333%; }
    .col-md-11 { width: 91.6667%; }
    .col-md-12 { width: 100%; }
}

@media (min-width: 992px) {
    .col-lg-1  { width: 8.3333%; }
    .col-lg-2  { width: 16.6667%; }
    .col-lg-3  { width: 25%; }
    .col-lg-4  { width: 33.3333%; }
    .col-lg-5  { width: 41.6667%; }
    .col-lg-6  { width: 50%; }
    .col-lg-7  { width: 58.3333%; }
    .col-lg-8  { width: 66.6667%; }
    .col-lg-9  { width: 75%; }
    .col-lg-10 { width: 83.3333%; }
    .col-lg-11 { width: 91.6667%; }
    .col-lg-12 { width: 100%; }
}

/* ---------- Forms ---------- */

.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field--full { grid-column: 1 / -1; }

/* Inside a .row the gap comes from column padding, so fields need their own
   vertical rhythm. */
.row > .field { margin-bottom: 16px; }

.field label { font-size: .82rem; font-weight: 600; color: #334155; }
.field .req { color: var(--expense); }

.input, .select, .textarea {
    width: 100%;
    /* A control can never be wider than the column holding it, whatever the
       browser's intrinsic minimum for the type would be. */
    max-width: 100%;
    height: var(--field-h);
    padding: 0 11px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: .9rem;
}
.textarea { height: auto; min-height: 88px; padding: 9px 11px; resize: vertical; }
.select { appearance: none; padding-right: 32px; }
.input:focus, .select:focus, .textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .14);
}
.input--error, .select--error, .textarea--error { border-color: var(--expense); }
.error { color: var(--expense); font-size: .78rem; }
.hint { color: var(--muted); font-size: .78rem; }

.check { display: inline-flex; align-items: center; gap: 8px; font-size: .87rem; cursor: pointer; }
.check input { width: 16px; height: 16px; accent-color: var(--brand); }

/* File input - the native control has its own height, so let it breathe. */
.input--file { height: auto; padding: 8px 10px; line-height: 1.4; }
.input--file::file-selector-button {
    margin-right: 10px;
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: #f1f5f9;
    color: #334155;
    font: inherit;
    font-size: .84rem;
    font-weight: 600;
    cursor: pointer;
}
.input--file::file-selector-button:hover { background: #e2e8f0; }

/* ---------- Attachments ---------- */

.attachments { display: grid; gap: 9px; }
.attachment {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: #f8fafc;
}
/* Real preview for images, a PDF chip for everything else. */
.attachment__thumb {
    display: grid;
    place-items: center;
    width: var(--thumb, 96px); height: var(--thumb, 96px);
    flex: 0 0 var(--thumb, 96px);
    overflow: hidden;
    border-radius: var(--radius-sm);
    background: var(--surface);
    border: 1px solid var(--border);
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: var(--muted);
    text-decoration: none;
}
.attachment__thumb:hover { border-color: var(--brand); text-decoration: none; }
.attachment__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The receipts column is half width on desktop, so shrink the thumb on
   narrow screens rather than letting it crowd out the filename. */
@media (max-width: 575px) {
    .attachment { --thumb: 68px; }
}
.attachment__meta { display: grid; gap: 2px; flex: 1; min-width: 140px; word-break: break-word; }
.attachment__remove { flex: 0 0 auto; color: var(--muted); font-size: .82rem; }

.input-prefix { position: relative; }
.input-prefix .sym {
    position: absolute; left: 11px; top: 0; height: var(--field-h);
    display: flex; align-items: center; color: var(--muted); font-weight: 600; pointer-events: none;
}
.input-prefix .input { padding-left: 30px; }

/* ---------- Filters ----------
   Filter bars use the same .row / col-* grid as every other form. The only
   special case is the action pair, which sits on one line and is nudged down
   so the buttons align with the inputs that have a label above them. */

.row > .field--actions { flex-direction: row; align-items: center; gap: 8px; }
.row > .field--check { justify-content: center; }

/* Fields with no label of their own (button pairs, standalone checkboxes)
   need the label's height added back, or they float above their neighbours. */
@media (min-width: 768px) {
    .row > .field--actions,
    .row > .field--check { padding-top: 25px; }
}

/* ---------- Alerts and toasts ---------- */

.toasts {
    position: fixed;
    top: 14px; right: 14px;
    z-index: 200;
    display: grid;
    gap: 9px;
    /* Not 100vw - that includes the scrollbar and can overflow by its width. */
    max-width: min(380px, calc(100% - 28px));
}
.toast {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 12px 14px;
    border-radius: var(--radius-sm);
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 4px solid var(--brand);
    box-shadow: var(--shadow);
    font-size: .87rem;
    animation: toast-in .18s ease-out;
}
.toast--success { border-left-color: var(--credit); }
.toast--error { border-left-color: var(--expense); }
.toast button { margin-left: auto; border: 0; background: none; cursor: pointer; color: var(--muted); font-size: 1rem; line-height: 1; }
@keyframes toast-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.alert {
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    font-size: .87rem;
    border: 1px solid;
}
.alert--error { background: var(--expense-soft); border-color: #fecaca; color: #991b1b; }
.alert--warn { background: #fffbeb; border-color: #fde68a; color: var(--warn); }

/* ---------- Empty state ---------- */

.empty { text-align: center; padding: 46px 20px; }
.empty__icon {
    width: 46px; height: 46px; margin: 0 auto 12px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: #f1f5f9;
    color: var(--muted);
}
.empty h3 { margin-bottom: 5px; }
.empty p { color: var(--muted); font-size: .88rem; margin: 0 0 15px; }

/* ---------- Charts ---------- */

.chart-box { position: relative; width: 100%; height: 280px; }
.chart-box canvas { max-width: 100%; }

.legend { display: flex; flex-wrap: wrap; gap: 13px; font-size: .8rem; color: var(--muted); margin-top: 10px; }
.legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; margin-right: 5px; }

.bars { display: grid; gap: 13px; }
.bar__top { display: flex; justify-content: space-between; gap: 12px; font-size: .85rem; margin-bottom: 5px; }
.bar__track { height: 8px; border-radius: 99px; background: #f1f5f9; overflow: hidden; }
.bar__fill { height: 100%; border-radius: 99px; background: var(--brand); }

/* ---------- Pagination (Laravel default markup) ---------- */

.pagination-wrap { padding: 13px 18px; border-top: 1px solid var(--border); }
.pagination-wrap nav { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: space-between; }
.pagination-wrap svg { width: 15px; height: 15px; }
.pagination-wrap .hidden { display: none; }
.pagination-wrap p { margin: 0; font-size: .82rem; color: var(--muted); }
.pagination-wrap span[aria-current="page"] span,
.pagination-wrap a {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 32px; height: 32px; padding: 0 9px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font-size: .83rem; color: var(--muted); background: var(--surface);
}
.pagination-wrap span[aria-current="page"] span { background: var(--brand); border-color: var(--brand); color: #fff; }
.pagination-wrap a:hover { background: #f8fafc; text-decoration: none; }
.pagination-wrap .relative.inline-flex { display: inline-flex; gap: 5px; flex-wrap: wrap; }

/* ---------- Modal ---------- */

.modal[hidden] { display: none; }
.modal {
    position: fixed; inset: 0; z-index: 300;
    display: grid; place-items: center;
    padding: 16px;
    background: rgba(15, 23, 42, .5);
}
.modal__panel {
    /* Wide enough that col-md-3 fields inside are usable, not 130px slivers. */
    width: min(960px, 100%);
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    background: var(--surface);
    border-radius: var(--radius);
    box-shadow: 0 20px 50px rgba(15, 23, 42, .25);
}
.modal__head { padding: 16px 18px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; }
.modal__head h3 { flex: 1; }
.modal__body { padding: 18px; display: grid; gap: 14px; }
.modal__foot { padding: 14px 18px; border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; gap: 9px; justify-content: flex-end; }

/* ---------- Login ---------- */

/* Same light ground as the panel behind it, so signing in is not a jarring
   jump from a dark screen to a light one. */
.login {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 22px;
    background: var(--bg);
}

.login__card {
    width: min(420px, 100%);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 32px 28px;
}

.login__brand {
    display: flex;
    align-items: center;
    gap: 10px;
    justify-content: center;
    margin-bottom: 6px;
    font-weight: 700;
    font-size: 1.05rem;
}
.login__brand .mark {
    display: grid; place-items: center;
    width: 34px; height: 34px;
    border-radius: 9px;
    background: var(--brand);
    color: #fff;
}

.login p.sub { text-align: center; color: var(--muted); font-size: .87rem; margin: 0 0 24px; }

/* The submit sits in the last column - no trailing gap under it. */
.login .row > .field:last-child { margin-bottom: 0; }

/* ---------- Description list ---------- */

.dl { display: grid; gap: 0; }
.dl__row { display: grid; grid-template-columns: 180px 1fr; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--border); }
.dl__row:last-child { border-bottom: 0; }
.dl__row dt { color: var(--muted); font-size: .84rem; }
.dl__row dd { margin: 0; font-size: .9rem; word-break: break-word; }

/* ---------- Utilities ---------- */

.muted { color: var(--muted); }
.small { font-size: .82rem; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.mt { margin-top: var(--gap); }
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.scrim { display: none; }

.spinner {
    width: 15px; height: 15px;
    border: 2px solid rgba(255, 255, 255, .45);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton { background: linear-gradient(90deg, #eef2f7 25%, #f8fafc 50%, #eef2f7 75%); background-size: 200% 100%; animation: shimmer 1.2s infinite; border-radius: 6px; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ==========================================================================
   Responsive - tablet, then mobile. Desktop rules above stay untouched.
   ========================================================================== */

/* ---------- Tablet: 1024px ---------- */

@media (max-width: 1024px) {
    .content { padding: 16px 18px 40px; }
    .topbar { padding: 0 18px; }
    .dl__row { grid-template-columns: 150px 1fr; }
}

/* ---------- Tablet: 991px and below ----------
   The sidebar leaves the flow here, which is what frees the full width for
   the col-md-* grid. Everything from 992px up is untouched. */

@media (max-width: 991px) {
    .hamburger { display: inline-flex; }

    /* Sidebar becomes an off-canvas drawer. */
    .sidebar {
        position: fixed;
        inset: 0 auto 0 0;
        z-index: 120;
        transform: translateX(-100%);
        transition: transform .2s ease;
        box-shadow: 0 0 40px rgba(0, 0, 0, .3);
    }
    body.nav-open .sidebar { transform: none; }
    body.nav-open .scrim { display: block; position: fixed; inset: 0; z-index: 110; background: rgba(15, 23, 42, .45); }
    /* Locking the body stops the page scrolling behind the open drawer. */
    body.nav-open { overflow: hidden; }

    /* The drawer must never be wider than the screen it slides over, and it
       should leave enough of the overlay visible to tap. */
    .sidebar { width: min(280px, 85vw); flex-basis: min(280px, 85vw); }

    /* Close button, alongside the overlay tap and the Escape key. */
    .sidebar__close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 34px; height: 34px;
        margin-left: auto;
        flex: 0 0 34px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: var(--surface);
        color: var(--muted);
        cursor: pointer;
    }
    .sidebar__close:hover { background: var(--sidebar-hover); color: var(--text); }

    /* Comfortable touch target for the hamburger. */
    .hamburger { width: 44px; height: 44px; }

    .grid--stats { grid-template-columns: 1fr 1fr; }
    .grid--halves { grid-template-columns: 1fr; }
    .chart-box { height: 250px; }
}

/* ---------- Tablet forms: 768px - 991px ----------
   The col-md-* spans are tuned for a desktop-width content area. With the
   sidebar gone the area is narrower, so a quarter-width field turns into a
   cramped strip. Two per row reads far better here. Full-width spans
   (textarea, file upload) are left alone. */

@media (min-width: 768px) and (max-width: 991px) {
    .row > .col-md-3,
    .row > .col-md-4,
    .row > .col-md-5,
    .row > .col-md-6 { width: 50%; }
}

/* ---------- Mobile: 767px and below ---------- */

@media (max-width: 767px) {
    .content { padding: 15px 15px 36px; }
    .modal__panel { max-height: calc(100vh - 24px); }
    .modal { padding: 12px; }

    /* One field per row, each filling its column exactly - never wider. */
    .row > [class*="col-"] { width: 100%; max-width: 100%; }

    /* Compact, not oversized: the control height is unchanged from desktop,
       only the textarea's idle height comes down. */
    .textarea { min-height: 72px; }

    /* Long labels wrap instead of forcing the column wider. */
    .field label { overflow-wrap: break-word; }

    .row > .field--actions .btn { flex: 1 1 auto; }

    /* ---------- Tables become cards ----------
       Each row turns into a stacked card with the column header shown beside
       its value, so nothing has to scroll sideways to be read. Only applied
       to tables JS has labelled (.is-stacked); without JS the table keeps its
       horizontal scroll and its real header row. */

    .table-wrap.is-stacked { overflow-x: visible; padding: 12px; }

    table.data.is-stacked { display: block; min-width: 0; }
    table.data.is-stacked thead { display: none; }
    table.data.is-stacked tbody { display: block; }

    table.data.is-stacked tr {
        display: block;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: var(--surface);
        margin-bottom: 10px;
    }
    table.data.is-stacked tr:last-child { margin-bottom: 0; }
    table.data.is-stacked tbody tr:hover { background: var(--surface); }

    table.data.is-stacked td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        width: auto;
        padding: 9px 12px;
        text-align: right;
        border-top: 1px solid var(--border);
        white-space: normal;
        overflow-wrap: break-word;
    }
    table.data.is-stacked tbody tr + tr td { border-top: 1px solid var(--border); }
    table.data.is-stacked tr td:first-child { border-top: 0; }

    /* The header text, carried over by JS. */
    table.data.is-stacked td::before {
        content: attr(data-label);
        flex: 0 0 40%;
        text-align: left;
        font-size: .7rem;
        letter-spacing: .06em;
        text-transform: uppercase;
        font-weight: 650;
        color: var(--muted);
    }

    /* Action buttons wrap under their label rather than being squeezed. */
    table.data.is-stacked td:last-child { flex-wrap: wrap; }
    table.data.is-stacked .actions { justify-content: flex-start; flex-wrap: wrap; }
}

/* ---------- Mobile: 575px and below ---------- */

@media (max-width: 575px) {
    /* Breadcrumbs hide at this width, so the headers can be shorter - but
       both still share the same value and stay aligned. */
    :root { --gap: 14px; --header-h: 60px; }

    .content { padding: 14px 13px 36px; }
    .topbar { padding: 0 13px; }
    .topbar__title h1 { font-size: 1rem; }
    .breadcrumbs { display: none; }

    /* Dashboard cards stack vertically. */
    .grid--stats { grid-template-columns: 1fr; }

    .stat__value { font-size: 1.35rem; }
    .card__body { padding: 14px; }
    .card__head { padding: 13px 14px; }

    /* Buttons fit the viewport rather than overflowing it. */
    .btn-row { width: 100%; }
    .btn-row .btn { flex: 1 1 auto; }
    .card__head .btn-row { width: 100%; }
    .modal__foot .btn { flex: 1 1 auto; }

    .dl__row { grid-template-columns: 1fr; gap: 3px; }
    .chart-box { height: 220px; }
    .toasts { left: 13px; right: 13px; max-width: none; }

    /* Modal becomes a bottom sheet so the action buttons stay in reach. */
    .modal { place-items: end center; padding: 0; }
    .modal__panel { width: 100%; max-height: 88vh; border-radius: 14px 14px 0 0; }

    /* Row actions stack rather than squeezing three buttons into one line. */
    .attachment .actions { width: 100%; justify-content: flex-start; }
    .attachment__remove { width: 100%; }
}

/* ---------- Small mobile: 480px and below ---------- */

@media (max-width: 480px) {
    /* Tighter cells mean less horizontal scrolling inside .table-wrap;
       every column is still there. */
    table.data th, table.data td { padding: 9px 10px; }
    table.data { min-width: 640px; }

    .attachment { --thumb: 60px; }
    .attachment__meta { min-width: 110px; }

    .card__head h2 { min-width: 0; }
    .empty { padding: 34px 14px; }
}

/* ---------- Very small: 375px and below ---------- */

@media (max-width: 375px) {
    .content { padding: 12px 10px 32px; }
    .card__body { padding: 12px; }
    .card__head { padding: 12px; }
    .stat { padding: 14px; }
    .stat__value { font-size: 1.25rem; }

    /* Two buttons per line rather than three cramped ones. */
    .actions { flex-wrap: wrap; }
    .btn--sm { padding: 0 9px; }

    .login { padding: 14px; }
    .login__card { padding: 24px 18px; }
}

@media print {
    .sidebar, .topbar, .btn, .pagination-wrap, .toasts { display: none !important; }
    body { background: #fff; }
    .card { box-shadow: none; border-color: #ddd; break-inside: avoid; }
    .content { padding: 0; }
}
