/* =====================================================================
   Orizoe Admin — design system
   Hand-written, no framework/CDN. Brand colors pulled from real assets:
   navy from the mobile app's own button colour (Color(0xFF14284E) in
   home_page_widget.dart), lime green/black from
   assets/images/Orizoe_Services_logo.jpg.
   ===================================================================== */

:root {
    /* Brand */
    --navy-900: #0d1a33;
    --navy-800: #14284e;
    --navy-700: #1c3a6e;
    --green-500: #8dc63f;
    --green-600: #6ea52c;
    --green-100: #eef7e0;

    /* Neutrals */
    --gray-50: #f8fafc;
    --gray-100: #f1f5f9;
    --gray-200: #e2e8f0;
    --gray-300: #cbd5e1;
    --gray-400: #94a3b8;
    --gray-500: #64748b;
    --gray-600: #475569;
    --gray-700: #334155;
    --gray-800: #1e293b;
    --gray-900: #0f172a;

    /* Semantic */
    --success: #16a34a;
    --success-soft: #dcfce7;
    --warning: #d97706;
    --warning-soft: #fef3c7;
    --danger: #dc2626;
    --danger-soft: #fee2e2;

    /* Elevation */
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow-md: 0 6px 16px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 16px 40px rgba(15, 23, 42, 0.14);

    /* Shape & motion */
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 18px;
    --ease: cubic-bezier(0.4, 0, 0.2, 1);
    --fast: 150ms;
    --slow: 260ms;

    --sidebar-width: 252px;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* overflow-x:hidden on both html and body: this is the page-level backstop
   against the exact "gray gutter down the right edge on mobile" bug —
   caused by something on the page (the widest single culprit is
   .table-scroll's table, which is deliberately min-width:640px so its own
   columns don't get crushed) making the *document* wider than the visual
   viewport. .table-scroll already scopes its own overflow-x:auto so that
   table scrolls internally, but without a hard clamp here too, a wider-
   than-viewport document can still leave every 100%-wide element upstream
   (cards, grid, banner) rendering narrower than the actual screen relative
   to that inflated document width — the same content, just not stretched
   all the way to the true right edge, which is what read as a gutter. */
html, body { overflow-x: hidden; }
body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Arial, sans-serif;
    background: var(--gray-50);
    color: var(--gray-800);
    -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; }

/* Global safety net: any free-text field a user can type into — query/
   incident "Details", a pause reason, task instructions — can contain a
   long unbroken token (a URL, a run-on word) with no whitespace for
   white-space:normal to wrap at. Without this, that one field would widen
   its card past the viewport and force the whole page to scroll
   horizontally on a phone. th/td already had their own copy of this before
   .table-scroll existed; this covers every other text container (cards,
   alerts, badges) with one rule instead of chasing each one individually. */
body { overflow-wrap: anywhere; }

/* pointer-events:none is load-bearing, not decorative: an SVG drawn with
   fill="none" (stroke-only, which every icon here is) doesn't register
   clicks in its own unpainted middle in some browsers — clicking the
   visual center of e.g. the sidebar's close (X) icon could miss the
   surrounding <label>/<button> entirely. Forcing clicks through to the
   parent fixes it regardless of the exact browser quirk. */
.icon { display: inline-block; vertical-align: middle; flex-shrink: 0; pointer-events: none; }

/* Any link/label with an icon as a direct child gets it aligned with the
   text next to it — covers table-cell action links, back-links, and
   labels, without needing a wrapper class on every single instance. */
/* :not() exclusions: .sidebar-close/.nav-toggle-button each wrap a single
   bare icon (no text) and have their own display:none/flex rules gating
   them to the sub-960px off-canvas breakpoint — without these exclusions,
   this rule's higher specificity (label:has(...) beats a single class)
   silently overrode that display:none at every width, leaving both
   buttons visible-but-functionless outside the mobile drawer entirely
   (clicking the sidebar's close X did nothing, since the sidebar isn't
   position:fixed/toggleable above 960px in the first place). */
a:has(> .icon), label:has(> .icon):not(.sidebar-close):not(.nav-toggle-button) {
    display: inline-flex; align-items: center; gap: 0.35rem;
}
td a:has(> .icon) { display: inline-flex; }

/* ---------- App shell ---------- */
.nav-toggle-checkbox { display: none; }

.app-shell {
    display: flex;
    min-height: 100vh;
}

/* ---------- Sidebar ---------- */
.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    background: linear-gradient(180deg, var(--navy-900), var(--navy-800) 60%);
    color: #dbe4f5;
    display: flex;
    flex-direction: column;
    padding: 1.1rem 0.9rem;
    gap: 0.25rem;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.4rem 0.5rem 1.4rem;
}
.sidebar-logo {
    height: 34px;
    width: 34px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: #fff;
    padding: 2px;
    box-shadow: var(--shadow-sm);
}
.sidebar-brand-text {
    font-weight: 700;
    font-size: 1.02rem;
    color: #fff;
    letter-spacing: -0.01em;
}
.sidebar-brand-text em {
    font-style: normal;
    font-weight: 400;
    color: var(--green-500);
}
.sidebar-close { display: none; margin-left: auto; color: #cfd8ea; cursor: pointer; }

.sidebar-nav { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; }

.nav-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.62rem 0.75rem;
    border-radius: var(--radius-sm);
    color: #b9c6e0;
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    transition: background var(--fast) var(--ease), color var(--fast) var(--ease), transform var(--fast) var(--ease);
    position: relative;
}
.nav-item .icon { color: #8ea0c4; transition: color var(--fast) var(--ease); }
.nav-item:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
    transform: translateX(2px);
}
.nav-item:hover .icon { color: var(--green-500); }
.nav-item.is-active {
    background: rgba(141, 198, 63, 0.14);
    color: #fff;
}
.nav-item.is-active .icon { color: var(--green-500); }
.nav-item.is-active::before {
    content: "";
    position: absolute;
    left: -0.9rem;
    top: 8%;
    height: 84%;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--green-500);
}

.nav-item span:not(.nav-badge) { flex: 1; }
.nav-badge {
    background: var(--danger);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    padding: 0.28rem 0.45rem;
    border-radius: 999px;
    min-width: 1.4em;
    text-align: center;
    box-shadow: 0 0 0 2px rgba(13, 26, 51, 0.6);
    animation: badgePop 240ms var(--ease);
}
@keyframes badgePop {
    from { transform: scale(0.5); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

.sidebar-footer {
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding-top: 0.9rem;
    margin-top: 0.5rem;
}
.user-chip { display: flex; align-items: center; gap: 0.65rem; padding: 0.3rem 0.5rem 0.75rem; }
.user-avatar {
    width: 34px; height: 34px; border-radius: 50%;
    background: var(--green-500); color: var(--navy-900);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 0.9rem; flex-shrink: 0;
}
.user-meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.user-meta strong { color: #fff; font-size: 0.86rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-meta small { color: #93a3c4; font-size: 0.75rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item-logout:hover { background: rgba(220, 38, 38, 0.18); }
.nav-item-logout:hover .icon { color: #f87171; }

.sidebar-backdrop { display: none; }

/* ---------- Main area / top bar ---------- */
.main-area { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1.1rem 1.75rem 0.5rem;
}
.nav-toggle-button { display: none; color: var(--gray-700); cursor: pointer; }
.page-title { font-size: 1.3rem; font-weight: 700; letter-spacing: -0.01em; color: var(--gray-900); margin: 0; }

.content {
    padding: 0.5rem 1.75rem 2.5rem;
    max-width: 1180px;
    animation: fadeInUp var(--slow) var(--ease);
}

@keyframes fadeInUp {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ---------- Preview banner ---------- */
.preview-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    background: linear-gradient(90deg, var(--green-100), #fff7e0);
    border-bottom: 1px solid #fde68a;
    color: #7c5a06;
    padding: 0.6rem 1.75rem;
    font-size: 0.85rem;
    animation: slideDown var(--slow) var(--ease);
}
@keyframes slideDown {
    from { opacity: 0; transform: translateY(-8px); }
    to { opacity: 1; transform: translateY(0); }
}
.preview-banner-icon { color: var(--green-600); display: flex; }
.preview-banner-text { flex: 1; min-width: 200px; }
/* flex-wrap here (not just on the outer .preview-banner) matters: without
   it, the 4 persona/exit links are one unbreakable flex row that can run
   wider than a phone screen — the outer banner's own wrap doesn't help
   once this row is already its own overflowing flex item. */
.preview-banner-actions { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
.preview-banner-actions a { color: #7c5a06; text-decoration: underline; font-weight: 600; }
.preview-banner-actions a:hover { color: var(--navy-800); }
.preview-banner-exit { color: var(--danger) !important; }

/* ---------- Cards, tables, alerts ---------- */
.card {
    background: #fff;
    padding: 1.4rem;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--gray-200);
    margin-bottom: 1.25rem;
    transition: box-shadow var(--fast) var(--ease);
}
.card:hover { box-shadow: var(--shadow-md); }
.card p { line-height: 1.7; }

/* ---------- Section rhythm ---------- */
/* Un-tokenized <h2>/<p> section headers and "New X" button wrappers were
   falling back to browser-default margins instead of this scale, which
   made the gap above/below them visibly inconsistent with the
   toolbar/table/pagination rhythm everywhere else. */
.content h2 { font-size: 1.05rem; font-weight: 700; color: var(--gray-900); margin: 0 0 1rem; }
.page-actions { margin: 0 0 1rem; }

/* ---------- List toolbar: search + filters ---------- */
.list-toolbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
    margin-bottom: 1rem;
}
.list-search {
    position: relative; flex: 1; min-width: 200px;
}
.list-search .icon {
    position: absolute; left: 0.7rem; top: 50%; transform: translateY(-50%);
    color: var(--gray-400);
}
.list-search input {
    width: 100%; padding: 0.55rem 0.75rem 0.55rem 2.3rem;
    border: 1px solid var(--gray-300); border-radius: var(--radius-sm);
    font-size: 0.9rem; background: #fff;
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.list-search input:focus {
    outline: none; border-color: var(--green-500); box-shadow: 0 0 0 3px rgba(141, 198, 63, 0.22);
}
.list-filter {
    padding: 0.55rem 0.75rem; border: 1px solid var(--gray-300); border-radius: var(--radius-sm);
    font-size: 0.87rem; background: #fff; color: var(--gray-700);
}
.list-clear {
    font-size: 0.85rem; color: var(--gray-500); text-decoration: none; white-space: nowrap;
}
.list-clear:hover { color: var(--danger); }

/* ---------- Pagination ---------- */
.pagination {
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
    gap: 0.75rem; margin-top: 1rem; padding: 0.25rem 0.1rem;
}
.pagination-info { font-size: 0.82rem; color: var(--gray-500); }
.pagination-links { display: flex; align-items: center; gap: 0.9rem; }
.pagination-current { font-size: 0.82rem; color: var(--gray-600); font-weight: 600; }
.pagination-btn {
    display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.85rem; font-weight: 600; color: var(--navy-700); text-decoration: none;
    padding: 0.35rem 0.6rem; border-radius: var(--radius-sm);
    transition: background var(--fast) var(--ease);
}
.pagination-btn:hover { background: var(--gray-100); }
.pagination-btn.is-disabled { pointer-events: none; opacity: 0.35; }

/* Every module's list.php wraps its <table> in <div class="table-scroll">
   — the scroll container (not the table) carries overflow-x:auto, so the
   card-like radius/shadow/border can live on the wrapper while the table
   underneath stays a single, real CSS table.
   Previous approach forced `display:table` on thead and tbody separately
   (with the outer <table> itself display:block) so the whole thing could
   scroll horizontally. That split thead and tbody into two *independent*
   table-layout contexts — each one only ever saw its own first row when
   computing column widths — so header and body columns weren't guaranteed
   to land on the same grid and could visually overlap depending on content
   (exactly the Employees/Admin Users column-overlap bug). A single real
   <table> (thead+tbody sharing one column grid, the normal browser
   behaviour) can't drift like that; the wrapper div supplies the
   responsive scrolling instead. */
.table-scroll {
    overflow-x: auto;
    background: #fff;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--gray-200);
    margin-bottom: 1.25rem;
}
table {
    width: 100%; min-width: 640px; border-collapse: collapse; background: #fff;
}
/* overflow-wrap so long unbroken tokens (emails, in particular) wrap inside
   their own column instead of overflowing into the next one — white-space:
   normal alone only wraps at whitespace, and an email address has none. */
th, td { text-align: left; padding: 0.75rem 1rem; border-bottom: 1px solid var(--gray-100); font-size: 0.88rem; white-space: normal; overflow-wrap: anywhere; }
th {
    background: var(--gray-50);
    font-weight: 600;
    color: var(--gray-500);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
tbody tr { transition: background var(--fast) var(--ease); }
tbody tr:hover { background: var(--gray-50); }
tbody tr:last-child td { border-bottom: none; }
td a { color: var(--navy-700); font-weight: 600; text-decoration: none; }
td a:hover { color: var(--green-600); text-decoration: underline; }

/* Row-action group (View / Edit / Delete / Archive…): one shared layout so
   every module's actions cell wraps and spaces the same way instead of each
   list.php hand-rolling its own " · " text separators — those didn't wrap
   as a unit on narrow columns, so a line could break right after a bare
   "·" and strand it. A border-left separator styled via CSS instead reflows
   cleanly at any width. */
.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; row-gap: 0.3rem; }
.row-actions > *:not(:first-child) { border-left: 1px solid var(--gray-200); padding-left: 0.5rem; }
/* A <button> made to look like the plain-text row-action links above it
   (td a), for actions that must be a real form POST (CSRF + non-GET)
   rather than a plain <a href>, e.g. Delete. */
.row-action-form { display: inline-flex; align-items: center; }
.link-btn {
    background: none; border: none; padding: 0; margin: 0; font: inherit; cursor: pointer;
    color: var(--navy-700); font-weight: 600; display: inline-flex; align-items: center; gap: 0.35rem;
}
.link-btn:hover { color: var(--green-600); text-decoration: underline; }
.link-btn-danger { color: var(--danger); }
.link-btn-danger:hover { color: #b91c1c; text-decoration: underline; }

.alert {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-sm);
    margin-bottom: 1.1rem;
    font-size: 0.9rem;
    animation: fadeInUp var(--fast) var(--ease);
}
.alert-success { background: var(--success-soft); color: #14532d; border: 1px solid #86efac; }
.alert-success .icon { color: var(--success); }
.alert-danger { background: var(--danger-soft); color: #7f1d1d; border: 1px solid #fca5a5; }
.alert-danger .icon { color: var(--danger); }
.alert-warning { background: var(--warning-soft); color: #7c4a03; border: 1px solid #fcd34d; }
.alert-warning .icon { color: var(--warning); }
.text-muted { color: var(--gray-400); display: inline-flex; align-items: center; gap: 0.35rem; cursor: not-allowed; }
/* Plain informational de-emphasis (a timestamp, an empty-state hint) — unlike
   .text-muted this isn't a disabled action, so no cursor:not-allowed. */
.text-subtle { color: var(--gray-400); font-size: 0.82rem; }

/* ---------- Forms ---------- */
form.stacked label { display: block; font-weight: 600; margin: 0.85rem 0 0.3rem; font-size: 0.85rem; color: var(--gray-700); }
form.stacked input, form.stacked select, form.stacked textarea {
    width: 100%; max-width: 420px; padding: 0.6rem 0.75rem;
    border: 1px solid var(--gray-300); border-radius: var(--radius-sm);
    font-size: 0.92rem; background: #fff; color: var(--gray-900);
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
form.stacked input:focus, form.stacked select:focus, form.stacked textarea:focus {
    outline: none; border-color: var(--green-500); box-shadow: 0 0 0 3px rgba(141, 198, 63, 0.22);
}
form.stacked input[readonly] { background: var(--gray-100); color: var(--gray-500); }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
    padding: 0.6rem 1.2rem; border: none; border-radius: var(--radius-sm);
    background: var(--navy-800); color: #fff; cursor: pointer;
    font-size: 0.9rem; font-weight: 600; text-decoration: none;
    box-shadow: var(--shadow-sm);
    transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease), background var(--fast) var(--ease);
}
.btn:hover { background: var(--navy-700); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn[aria-disabled="true"] { background: var(--gray-300); color: var(--gray-500); cursor: not-allowed; box-shadow: none; }
.btn[aria-disabled="true"]:hover { background: var(--gray-300); box-shadow: none; transform: none; }
.btn-block { width: 100%; max-width: 420px; }
.btn-danger { background: var(--danger); }
.btn-danger:hover { background: #ef4444; }
.btn-preview { background: var(--green-600); }
.btn-preview:hover { background: var(--green-500); color: var(--navy-900); }
.btn-secondary { background: var(--gray-500); }
.btn-secondary:hover { background: var(--gray-600); }

/* ---------- Badges ---------- */
/* clamp() rather than a fixed 0.76rem: the badge shrinks its own font/icon/
   padding together as the viewport narrows (down to a 360px-wide phone's
   worth of shrinking, the clamp's own floor beyond that) so a status/SLA
   pill always fits its column instead of wrapping onto two lines or
   forcing extra horizontal scroll on top of the table's own. gap and
   padding scale on the same curve so the icon and text shrink as one
   proportioned unit, not just the text. justify-content:center (on top of
   align-items:center) keeps icon+text centered as a group even if
   something outside .badge ever stretches it to a fixed width. */
.badge {
    display: inline-flex; align-items: center; justify-content: center;
    gap: clamp(0.2rem, 1vw, 0.3rem);
    padding: clamp(0.15rem, 0.6vw, 0.2rem) clamp(0.45rem, 2vw, 0.65rem);
    border-radius: 999px; font-size: clamp(0.68rem, 2.4vw, 0.76rem); font-weight: 600; color: #fff;
    white-space: nowrap; max-width: 100%;
}
.badge .icon { width: clamp(11px, 2.6vw, 13px); height: clamp(11px, 2.6vw, 13px); }
.badge-green { background: var(--success); }
.badge-amber { background: var(--warning); }
.badge-red { background: var(--danger); }
.badge-grey { background: var(--gray-500); }

/* Utility for table columns that hold a badge (status/SLA/priority/etc.) —
   applied to both the <th> and its <td>s so the header label and the
   centered pill line up in the middle of the column instead of the badge
   sitting flush against the column's left edge. */
.cell-center { text-align: center; }

/* ---------- Dashboard stat cards ---------- */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}
.stat-card {
    background: #fff;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-md);
    padding: 1.1rem 1.25rem;
    box-shadow: var(--shadow-sm);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.6rem;
    transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
/* Stat cards that drill into the underlying records (Dashboard) are real
   <a> elements, styled to look identical to the static ones (the stat-hero
   %-complete card stays a plain div — there's no single record set behind
   an aggregate percentage to drill into). */
a.stat-card { text-decoration: none; color: inherit; cursor: pointer; }
a.stat-card:focus-visible { outline: 2px solid var(--navy-700); outline-offset: 2px; }
.stat-card-icon {
    width: 38px; height: 38px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
}
.stat-card-icon.tone-green { background: var(--success-soft); color: var(--success); }
.stat-card-icon.tone-amber { background: var(--warning-soft); color: var(--warning); }
.stat-card-icon.tone-grey { background: var(--gray-100); color: var(--gray-500); }
.stat-card-icon.tone-red { background: var(--danger-soft); color: var(--danger); }
.stat-card-value { font-size: 1.7rem; font-weight: 800; color: var(--gray-900); line-height: 1; }
.stat-card-label { font-size: 0.8rem; color: var(--gray-500); font-weight: 600; }
.stat-hero {
    background: linear-gradient(135deg, var(--navy-900), var(--navy-700));
    color: #fff; border: none;
}
.stat-hero .stat-card-label { color: #b9c6e0; }
.stat-hero .stat-card-value { color: #fff; font-size: 2.2rem; }

/* =====================================================================
   Login page
   ===================================================================== */
.login-wrap {
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    padding: 1.5rem;
    background:
        radial-gradient(circle at 15% 20%, rgba(141, 198, 63, 0.16), transparent 45%),
        radial-gradient(circle at 85% 80%, rgba(20, 40, 78, 0.18), transparent 45%),
        var(--gray-50);
}
.login-card {
    width: 100%; max-width: 400px; text-align: center;
    background: #fff; border-radius: var(--radius-lg);
    padding: 2.25rem 2rem 1.75rem;
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--gray-200);
    animation: fadeInUp var(--slow) var(--ease);
}
.login-logo { max-width: 170px; margin: 0 auto 0.75rem; }
.login-title { font-size: 1.15rem; font-weight: 700; color: var(--gray-900); margin: 0 0 1.25rem; }
.login-card form.stacked { text-align: left; }
.login-card input, .login-card select { max-width: 100%; }

.input-icon { position: relative; }
.input-icon .icon {
    position: absolute; left: 0.75rem; top: 50%; transform: translateY(-50%);
    color: var(--gray-400); pointer-events: none;
}
.input-icon input { padding-left: 2.4rem; }
.input-icon:has(.input-icon-toggle) input { padding-right: 2.4rem; }
.input-icon-toggle {
    position: absolute; right: 0.6rem; top: 50%; transform: translateY(-50%);
    background: none; border: none; padding: 0.25rem; cursor: pointer;
    color: var(--gray-400); display: flex; border-radius: 6px;
    transition: color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.input-icon-toggle:hover { color: var(--gray-700); background: var(--gray-100); }
.input-icon-toggle[aria-pressed="true"] { color: var(--green-600); }

.preview-divider { display: flex; align-items: center; text-align: center; color: var(--gray-400); margin: 1.4rem 0; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; }
.preview-divider::before, .preview-divider::after { content: ""; flex: 1; border-bottom: 1px solid var(--gray-200); }
.preview-divider span { padding: 0 0.75rem; }
.login-note { font-size: 0.76rem; color: var(--gray-400); margin-top: 1.1rem; line-height: 1.5; }

/* =====================================================================
   Responsive — sidebar becomes an off-canvas drawer under 960px.
   Opening/closing within a page is pure CSS: a checkbox+label hack
   (#nav-toggle + .nav-toggle-button / .sidebar-close / .sidebar-backdrop
   labels) drives it. Every screen here is a full server-rendered page load
   though (not a single-page app) — tapping a nav-item link doesn't uncheck
   #nav-toggle, so on a slow connection the current page keeps showing the
   drawer open for the whole transition to the next page, and a
   browser-cached ("back-forward cache") snapshot of that page can restore
   with the drawer still marked open. render_footer()'s small inline
   <script> closes that one gap — see its comment. */
@media (max-width: 960px) {
    .nav-toggle-button { display: flex; }
    .sidebar-close { display: flex; }
    .sidebar {
        position: fixed; top: 0; left: 0; height: 100vh; z-index: 60;
        transform: translateX(-105%);
        transition: transform var(--slow) var(--ease);
        box-shadow: var(--shadow-lg);
    }
    #nav-toggle:checked ~ .app-shell .sidebar { transform: translateX(0); }
    .sidebar-backdrop {
        display: none;
        position: fixed; inset: 0; background: rgba(13, 26, 51, 0.45);
        z-index: 55; cursor: pointer;
    }
    #nav-toggle:checked ~ .app-shell .sidebar-backdrop { display: block; }

    .topbar { padding: 1rem 1.25rem 0.4rem; }
    .content { padding: 0.5rem 1.25rem 2rem; }
    .preview-banner { padding: 0.6rem 1.25rem; font-size: 0.8rem; }
    form.stacked input, form.stacked select, form.stacked textarea, .btn-block { max-width: 100%; }
}

@media (max-width: 480px) {
    .page-title { font-size: 1.1rem; }
    .card, .login-card { padding: 1.1rem; }
    th, td { padding: 0.55rem 0.6rem; font-size: 0.82rem; }
    .stat-card-value { font-size: 1.4rem; }
    .preview-banner-actions { width: 100%; justify-content: space-between; gap: 0.6rem; }
}

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}
