/* ==========================================================================
   SnitchOS portal redesign — design-system foundation (Wave R1)
   Loaded AFTER app.min.css + brand.css so it layers over Bootstrap/Tabler.
   Implements the shared REDESIGN_SPEC.md tokens and restyles the app shell
   into the "operations console" look: dark grouped left rail + light canvas
   + card surfaces. Existing pages keep working; this only re-skins.
   ========================================================================== */

:root {
    /* Left rail (dark) */
    --sn-rail: #161a23;
    --sn-rail-2: #1e232f;
    --sn-rail-text: #9aa3b4;
    --sn-rail-active: #ffffff;

    /* Canvas + surfaces */
    --sn-canvas: #f6f7f9;
    --sn-card: #ffffff;
    --sn-line: #e7e9ef;
    --sn-ink: #12151b;
    --sn-muted: #6b7280;

    /* Interactive / brand — use sparingly */
    --sn-accent: #2e5be6;
    --sn-accent-soft: rgba(46, 91, 230, .10);

    /* Productivity semantics — use EVERYWHERE for data viz (not brand).
       The base hues are tuned as FILLS (bars, stripes, dots). For small text
       on their soft backgrounds the fills are too light for WCAG AA, so each
       band also has a darker *-text variant (>=4.5:1) — use those for labels,
       pills, deltas. Never swap the fills for text; never use text vars as fills. */
    --sn-prod: #4c9a6b;
    --sn-neut: #cf9a3d;
    --sn-unprod: #c6493b;
    --sn-prod-text: #37744f;   /* on --sn-prod-soft, ~4.9:1 */
    --sn-neut-text: #8a6420;   /* on --sn-neut-soft, ~4.8:1 (fill is only ~2.5:1) */
    --sn-unprod-text: #b3392c; /* on --sn-unprod-soft, ~4.7:1 */
    --sn-idle: #9aa3b2;
    --sn-offline: #d7dbe3;
    --sn-prod-soft: #e7f0ea;
    --sn-neut-soft: #f7eeda;
    --sn-unprod-soft: #f6e2df;

    /* Shape */
    --sn-radius: 11px;
    --sn-shadow: 0 1px 2px rgba(18, 21, 27, .04), 0 6px 18px rgba(18, 21, 27, .05);

    /* Rail geometry — mirror the theme's --theme-sidenav-width (245px). */
    --sn-rail-width: 245px;
}

/* --------------------------------------------------------------------------
   Dark mode — remap the surface/ink/line tokens onto the theme's own dark
   palette (app.min.css [data-bs-theme=dark]: body-bg #17181e, secondary-bg
   #1e1f27, tertiary-bg #272832, border #293036, body-color #aab8c5,
   secondary-color #8391a2) so our console layer sits *with* Tabler's dark
   theme instead of punching light holes in it. The rail was already dark, so
   it barely shifts; canvas/card/line/ink/muted flip. Soft band backgrounds
   become low-alpha tints of their hue (readable dark chips), and each band
   text var brightens for legible small text on those tints. Everything else
   (accent, radius, geometry) is theme-neutral and inherited from :root.
   -------------------------------------------------------------------------- */
[data-bs-theme="dark"] {
    --sn-rail: #1a1d27;
    --sn-rail-2: #262a37;
    --sn-rail-text: #8495ab;
    --sn-rail-active: #ffffff;

    --sn-canvas: #17181e;
    --sn-card: #1e1f27;
    --sn-line: #293036;
    --sn-ink: #d3dae2;
    --sn-muted: #8391a2;

    --sn-accent: #6f7ff2;              /* brighter accent for dark contrast */
    --sn-accent-soft: rgba(111, 127, 242, .16);

    /* Fills brighten slightly so they read against the dark card surface. */
    --sn-prod: #5cb37f;
    --sn-neut: #dcab52;
    --sn-unprod: #e06456;
    --sn-prod-text: #7ecb9a;
    --sn-neut-text: #e6bd6e;
    --sn-unprod-text: #f0938a;
    --sn-idle: #59606e;
    --sn-offline: #2b3038;
    --sn-prod-soft: rgba(92, 179, 127, .16);
    --sn-neut-soft: rgba(220, 171, 82, .16);
    --sn-unprod-soft: rgba(224, 100, 86, .16);

    --sn-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 18px rgba(0, 0, 0, .35);
}

/* --------------------------------------------------------------------------
   Canvas — drive the body off the tokens so it follows the active theme.
   (Previously a bare `body` rule hard-pinned the light canvas even in dark
   mode.) The tokens above already remap per data-bs-theme, so one rule works.
   -------------------------------------------------------------------------- */
body {
    background-color: var(--sn-canvas);
    color: var(--sn-ink);
}

.content-page .container-fluid {
    color: var(--sn-ink);
}

/* Tabular numerals for any figure that reads as data. */
.sn-num,
.kpi-card .kpi-value,
.score-pill {
    font-variant-numeric: tabular-nums;
}

/* Uppercase eyebrow used by kpi_card / page_head. */
.sn-eyebrow {
    font-size: 10.5px;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: var(--sn-muted);
    font-weight: 600;
    line-height: 1.2;
}

/* --------------------------------------------------------------------------
   Left rail — restyle the theme's .sidenav-menu into the dark grouped rail.
   -------------------------------------------------------------------------- */
.sidenav-menu {
    background: var(--sn-rail) !important;
    border-right: 1px solid rgba(255, 255, 255, .04);
}

/* Only pin our rail width in the DEFAULT layout. The theme drives its own
   width for condensed / offcanvas / on-hover states (data-sidenav-size); a
   flat `width: 245px` here fought those and broke the collapsed rail. Scope
   to the default size and fall back to the theme var so we never override it. */
[data-sidenav-size="default"] .sidenav-menu {
    width: var(--theme-sidenav-width, var(--sn-rail-width));
}

.sidenav-menu .logo {
    border-bottom: 1px solid rgba(255, 255, 255, .05);
}

/* Group section header (label + icon) — a real <button> for a11y (Wave R8),
   reset to look like the original static label. */
.sn-nav-group-title {
    display: flex;
    align-items: center;
    width: 100%;
    gap: .5rem;
    padding: .55rem 1.25rem .3rem;
    margin-top: .35rem;
    /* Rail hierarchy: group headers read LARGER than their submenu links
       (14.5px semibold vs 13px items) — was a 10.5px uppercase eyebrow, which
       made the headers look subordinate to their own children. */
    font-size: 14.5px;
    letter-spacing: .01em;
    /* Lightened from #6b7382 (~3.6:1 on the #161a23 rail) toward the rail's
       body text so the group headers clear AA for non-large text. */
    color: var(--sn-rail-text);
    font-weight: 600;
    background: none;
    border: 0;
    cursor: pointer;
    text-align: left;
}

.sn-nav-group-title .ti {
    font-size: 17px;
    opacity: .8;
}

.sn-nav-group-title:hover {
    color: var(--sn-rail-active);
}

.sn-nav-group-title:focus-visible {
    outline: 2px solid var(--sn-accent);
    outline-offset: -2px;
    border-radius: 4px;
}

/* A group whose active page is inside it gets a subtly brighter label. */
.sn-nav-group.is-active > .sn-nav-group-title {
    color: var(--sn-rail-active);
}

/* Chevron — pushed to the end of the header, rotates on expand/collapse. */
.sn-nav-group-chevron {
    margin-left: auto;
    font-size: 13px !important;
    opacity: .65;
    transition: transform .15s ease;
}

.sn-nav-group-collapsed .sn-nav-group-chevron {
    transform: rotate(-90deg);
}

/* Group body (the items) — smooth height/opacity collapse. grid-template-rows
   1fr->0fr on the OUTER element + min-height:0/overflow:hidden on the single
   INNER wrapper (.sn-nav-group-body-inner, its only grid child) is the modern
   no-JS-measurement way to animate to/from "auto" height. */
.sn-nav-group-body {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows .18s ease;
}

.sn-nav-group-body-inner {
    min-height: 0;
    overflow: hidden;
    opacity: 1;
    transition: opacity .18s ease;
}

.sn-nav-group-collapsed .sn-nav-group-body {
    grid-template-rows: 0fr;
}

.sn-nav-group-collapsed .sn-nav-group-body-inner {
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .sn-nav-group-chevron,
    .sn-nav-group-body {
        transition: none;
    }
}

/* Items */
.sidenav-menu .side-nav .side-nav-item .side-nav-link,
.sn-nav-link {
    display: flex;
    align-items: center;
    gap: .65rem;
    /* Indented under the (larger) group header so sub-items read as children. */
    padding: .45rem 1.25rem .45rem 1.9rem;
    color: var(--sn-rail-text);
    border-left: 3px solid transparent;
    border-radius: 0;
    transition: background-color .12s ease, color .12s ease, border-color .12s ease;
    text-decoration: none;
}

.sn-nav-link .menu-icon,
.sn-nav-link .ti {
    font-size: 18px;
    line-height: 1;
    width: 20px;
    text-align: center;
    flex: 0 0 auto;
}

.sn-nav-link .menu-text {
    /* Kept smaller than the 14.5px group headers (rail hierarchy). */
    font-size: 13px;
    font-weight: 500;
}

.sn-nav-link:hover {
    color: var(--sn-rail-active);
    background: var(--sn-rail-2);
}

/* Active item: colored left border + tinted background + white text. */
.sn-nav-link.is-active {
    color: var(--sn-rail-active);
    background: var(--sn-rail-2);
    border-left-color: var(--sn-accent);
    font-weight: 600;
}

.sn-nav-link.is-active .menu-text {
    font-weight: 600;
}

/* Beta pill in the rail. */
.sn-nav-badge {
    margin-left: auto;
    font-size: 9.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: .1rem .35rem;
    border-radius: 5px;
    background: rgba(255, 255, 255, .08);
    color: var(--sn-rail-text);
}

/* Tenant picker inside the rail (top-level super-admin surface). */
.sn-rail-tenant {
    color: var(--sn-rail-text);
    padding: .35rem 1.25rem;
    display: block;
    font-size: 13px;
    text-decoration: none;
}

.sn-rail-tenant:hover,
.sn-rail-tenant.is-current {
    color: var(--sn-rail-active);
    background: var(--sn-rail-2);
}

/* --------------------------------------------------------------------------
   Topbar — keep the theme's chrome but flatten to the console look + host the
   breadcrumb.
   -------------------------------------------------------------------------- */
.app-topbar {
    background: var(--sn-card);
    border-bottom: 1px solid var(--sn-line);
}

.sn-breadcrumb {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: 13px;
    color: var(--sn-muted);
    min-width: 0;
}

.sn-breadcrumb .sn-crumb-group {
    color: var(--sn-muted);
}

.sn-breadcrumb .sn-crumb-sep {
    color: var(--sn-line);
}

.sn-breadcrumb .sn-crumb-page {
    color: var(--sn-ink);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sn-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    background: var(--sn-idle);
}

.sn-status-dot.is-live {
    background: var(--sn-prod);
    box-shadow: 0 0 0 3px var(--sn-prod-soft);
}

/* --------------------------------------------------------------------------
   Cards — soften into the spec's surface look without ripping out Bootstrap.
   -------------------------------------------------------------------------- */
.content-page .card {
    background: var(--sn-card);
    border: 1px solid var(--sn-line);
    border-radius: var(--sn-radius);
    box-shadow: var(--sn-shadow);
}

.content-page .card .card-header {
    background: transparent;
    border-bottom: 1px solid var(--sn-line);
}

/* --------------------------------------------------------------------------
   R1 macro components (kpi_card / ratio_bar / score_pill / page_head).
   Kept here so later waves can use them without further shell edits.
   -------------------------------------------------------------------------- */

/* page_head */
.sn-page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: .75rem;
    margin-bottom: 1rem;
}

.sn-page-head .sn-page-title {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--sn-ink);
    margin: 0;
    line-height: 1.15;
}

.sn-page-head .sn-page-subtitle {
    font-size: .85rem;
    color: var(--sn-muted);
    margin: .2rem 0 0;
}

/* kpi_card */
.kpi-card {
    position: relative;
    background: var(--sn-card);
    border: 1px solid var(--sn-line);
    border-radius: var(--sn-radius);
    box-shadow: var(--sn-shadow);
    padding: 1rem 1.1rem;
    overflow: hidden;
    height: 100%;
}

.kpi-card .kpi-stripe {
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: var(--sn-idle);
}

.kpi-card.band-prod .kpi-stripe {
    background: var(--sn-prod);
}

.kpi-card.band-neut .kpi-stripe {
    background: var(--sn-neut);
}

.kpi-card.band-unprod .kpi-stripe {
    background: var(--sn-unprod);
}

.kpi-card.band-accent .kpi-stripe {
    background: var(--sn-accent);
}

.kpi-card .kpi-value {
    font-size: 1.7rem;
    font-weight: 700;
    color: var(--sn-ink);
    line-height: 1.1;
}

.kpi-card .kpi-unit {
    font-size: .8rem;
    color: var(--sn-muted);
    font-weight: 500;
}

.kpi-card .kpi-delta {
    font-size: .78rem;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    margin-top: .3rem;
}

.kpi-card .kpi-delta.up {
    color: var(--sn-prod-text);
}

.kpi-card .kpi-delta.down {
    color: var(--sn-unprod-text);
}

.kpi-card .kpi-delta.flat {
    color: var(--sn-muted);
}

/* ratio_bar — stacked productivity ratio with an offline remainder track. */
.ratio-bar {
    display: flex;
    width: 100%;
    height: 10px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--sn-offline);
}

.ratio-bar .ratio-seg {
    height: 100%;
}

.ratio-bar .ratio-prod {
    background: var(--sn-prod);
}

.ratio-bar .ratio-neut {
    background: var(--sn-neut);
}

.ratio-bar .ratio-unprod {
    background: var(--sn-unprod);
}

/* score_pill — 0..100 productivity score, band-colored. */
.score-pill {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .12rem .5rem;
    border-radius: 999px;
    font-weight: 700;
    font-size: .82rem;
    line-height: 1;
}

/* Pills are small text on soft backgrounds — use the AA text variants, not the
   fills (the amber fill is only ~2.5:1 on its soft chip). */
.score-pill.band-prod {
    background: var(--sn-prod-soft);
    color: var(--sn-prod-text);
}

.score-pill.band-neut {
    background: var(--sn-neut-soft);
    color: var(--sn-neut-text);
}

.score-pill.band-unprod {
    background: var(--sn-unprod-soft);
    color: var(--sn-unprod-text);
}

/* --------------------------------------------------------------------------
   R2 landing components (mini_toplist / trend_bars / deep-link chevron).
   -------------------------------------------------------------------------- */

/* Deep-link chevron on a card header — subtle until hover. */
.sn-card-link {
    font-size: .78rem;
    font-weight: 600;
    color: var(--sn-accent);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    white-space: nowrap;
}

.sn-card-link .ti {
    font-size: 15px;
    transition: transform .12s ease;
}

.sn-card-link:hover {
    color: var(--sn-accent);
}

.sn-card-link:hover .ti {
    transform: translateX(2px);
}

/* mini_toplist — ranked top-5 rows. */
.sn-toplist-rows {
    list-style: none;
    margin: 0;
    padding: 0;
}

.sn-toplist-row {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .5rem .9rem;
    border-top: 1px solid var(--sn-line);
    font-size: .86rem;
    min-width: 0;
}

.sn-toplist-row:first-child {
    border-top: 0;
}

.sn-toplist-rank {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border-radius: 6px;
    background: var(--sn-accent-soft);
    color: var(--sn-accent);
    font-size: .72rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.sn-toplist-name {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--sn-ink);
}

.sn-toplist-value {
    flex: 0 0 auto;
    font-weight: 600;
    color: var(--sn-ink);
}

.sn-toplist-unit {
    font-size: .72rem;
    color: var(--sn-muted);
    font-weight: 500;
    margin-left: .12rem;
}

/* trend_bars — compact 7-day stacked sparkline. */
.sn-trend {
    display: flex;
    align-items: flex-end;
    gap: .4rem;
    height: 92px;
}

.sn-trend-col {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
    min-width: 0;
}

.sn-trend-stack {
    width: 100%;
    max-width: 26px;
    display: flex;
    flex-direction: column;
    border-radius: 4px 4px 0 0;
    overflow: hidden;
    background: var(--sn-offline);
    min-height: 2px;
}

.sn-trend-seg {
    width: 100%;
    flex-basis: 0;
}

.sn-trend-seg.sn-seg-prod {
    background: var(--sn-prod);
}

.sn-trend-seg.sn-seg-neut {
    background: var(--sn-neut);
}

.sn-trend-seg.sn-seg-unprod {
    background: var(--sn-unprod);
}

.sn-trend-seg.sn-seg-idle {
    background: var(--sn-idle);
}

.sn-trend-label {
    font-size: 10px;
    color: var(--sn-muted);
    margin-top: .3rem;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Accessibility — keep focus visible over the darker rail + accent surfaces.
   -------------------------------------------------------------------------- */
.sn-nav-link:focus-visible,
.sn-rail-tenant:focus-visible {
    outline: 2px solid var(--sn-accent);
    outline-offset: -2px;
}

a:focus-visible,
.btn:focus-visible {
    outline: 2px solid var(--sn-accent);
    outline-offset: 2px;
}

/* Skip-to-content link — off-screen until focused, then pinned top-left over
   everything so keyboard/AT users can jump past the rail + topbar. */
.sn-skip-link {
    position: fixed;
    top: -60px;
    left: .75rem;
    z-index: 1100;
    padding: .5rem .9rem;
    background: var(--sn-card);
    color: var(--sn-ink);
    border: 1px solid var(--sn-accent);
    border-radius: 8px;
    box-shadow: var(--sn-shadow);
    font-size: .9rem;
    font-weight: 600;
    text-decoration: none;
    transition: top .12s ease;
}
.sn-skip-link:focus {
    top: .75rem;
    outline: 2px solid var(--sn-accent);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   usage_master_detail — shared Applications / Websites / Categories layout.
   Left ranked list + HTMX-swapped right detail panel (Users + Usage tabs).
   -------------------------------------------------------------------------- */

/* Shared productivity fills (bars) — reused by list rows, user bars, chart. */
.sn-fill-productive { background: var(--sn-prod); }
.sn-fill-neutral { background: var(--sn-neut); }
.sn-fill-unproductive { background: var(--sn-unprod); }
.sn-fill-ignore { background: var(--sn-idle); }

/* Classification badge (icon-only) in the master list + detail head. */
.sn-class-badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    font-size: 14px;
}
.sn-class-prod { color: var(--sn-prod); background: var(--sn-prod-soft); }
.sn-class-neut { color: var(--sn-neut); background: var(--sn-neut-soft); }
.sn-class-unprod { color: var(--sn-unprod); background: var(--sn-unprod-soft); }
.sn-class-undef { color: var(--sn-muted); background: rgba(107, 114, 128, .12); }

.sn-md-list, .sn-md-detail-card { border: 1px solid var(--sn-line); }

/* Left toolbar: search + date/mode/productivity filters. */
.sn-md-toolbar {
    border-bottom: 1px solid var(--sn-line);
    display: flex;
    flex-direction: column;
    gap: .5rem;
}
.sn-md-search { position: relative; }
.sn-md-search .ti {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--sn-muted);
}
.sn-md-search input { padding-left: 30px; }
.sn-md-filters {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: center;
}
.sn-md-prod-filter { width: auto; }

/* Ranked list. */
.sn-md-rows {
    max-height: 620px;
    overflow-y: auto;
    /* Thin, themed scrollbar (Firefox + Chromium) so the long ranked list
       doesn't drop a chunky default track into the console look. */
    scrollbar-width: thin;
    scrollbar-color: var(--sn-line) transparent;
}
.sn-md-rows::-webkit-scrollbar { width: 8px; }
.sn-md-rows::-webkit-scrollbar-thumb {
    background: var(--sn-line);
    border-radius: 4px;
}
.sn-md-rows::-webkit-scrollbar-track { background: transparent; }
.sn-md-row {
    width: 100%;
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .5rem .85rem;
    border: 0;
    border-bottom: 1px solid var(--sn-line);
    background: var(--sn-card);
    text-align: left;
    cursor: pointer;
}
.sn-md-row:hover { background: var(--sn-canvas); }
/* Keyboard focus — the row is a <button>; give it a visible ring inset so it
   doesn't get clipped by the list's overflow. */
.sn-md-row:focus-visible {
    outline: 2px solid var(--sn-accent);
    outline-offset: -2px;
}
.sn-md-row.active {
    background: var(--sn-accent-soft);
    box-shadow: inset 3px 0 0 var(--sn-accent);
}
.sn-md-rank {
    flex: 0 0 1.4rem;
    color: var(--sn-muted);
    font-size: .8rem;
    text-align: right;
}
.sn-md-name {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.sn-md-name-main { font-weight: 600; color: var(--sn-ink); }
.sn-md-name-sub { font-size: .75rem; color: var(--sn-muted); }
.sn-md-value {
    flex: 0 0 auto;
    font-weight: 600;
    color: var(--sn-ink);
    white-space: nowrap;
    text-align: right;
}
.sn-md-unit { font-size: .7rem; color: var(--sn-muted); margin-left: 1px; }
.sn-md-delta { font-size: .72rem; margin-left: .35rem; }
.sn-md-delta.up { color: var(--sn-prod-text); }
.sn-md-delta.down { color: var(--sn-unprod-text); }
.sn-md-delta.new { color: var(--sn-muted); }
.sn-md-bar {
    flex: 0 0 84px;
    height: 8px;
    border-radius: 4px;
    background: var(--sn-offline);
    overflow: hidden;
}
.sn-md-fill { display: block; height: 100%; border-radius: 4px; }
/* Summary hides the exe/host sub-label + distribution; Detailed shows all. */
.sn-md-list:not(.sn-md-detailed) .sn-md-bar { display: none; }

/* Right detail panel. */
.sn-md-detail-body { padding: 1rem 1.15rem; }
.sn-md-placeholder { padding: 3rem 1rem; }
.sn-md-detail-head { margin-bottom: .75rem; }
.sn-md-tabs { margin-bottom: .85rem; }
.sn-md-tabs .nav-link { background: none; border: 0; border-bottom: 2px solid transparent; }
.sn-md-tabs .nav-link.active {
    color: var(--sn-accent);
    border-bottom-color: var(--sn-accent);
}

/* Users tab. */
.sn-md-userlist { display: flex; flex-direction: column; gap: .45rem; }
.sn-md-user { display: flex; align-items: center; gap: .6rem; }
.sn-md-user-name { flex: 0 0 34%; min-width: 0; font-size: .85rem; color: var(--sn-ink); }
.sn-md-user-bar {
    flex: 1 1 auto;
    height: 10px;
    border-radius: 5px;
    background: var(--sn-offline);
    overflow: hidden;
}
.sn-md-user-val { flex: 0 0 auto; font-size: .8rem; color: var(--sn-muted); }

/* Usage tab — compact per-day bar chart. */
.sn-md-chart {
    display: flex;
    align-items: flex-end;
    gap: 4px;
    height: 180px;
    padding-top: .5rem;
    overflow-x: auto;
}
.sn-md-chart-col {
    flex: 1 0 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
}
.sn-md-chart-track {
    flex: 1 1 auto;
    width: 60%;
    display: flex;
    align-items: flex-end;
    background: var(--sn-canvas);
    border-radius: 4px 4px 0 0;
    overflow: hidden;
}
.sn-md-chart-fill { width: 100%; border-radius: 4px 4px 0 0; }
.sn-md-chart-label {
    font-size: .65rem;
    color: var(--sn-muted);
    margin-top: 4px;
    white-space: nowrap;
}

/* Reclassify control. */
.sn-md-reclassify {
    margin-top: 1rem;
    padding-top: .85rem;
    border-top: 1px solid var(--sn-line);
}

/* --------------------------------------------------------------------------
   R6 — Classifications tabbed workspace, People roster, Roles matrix.
   -------------------------------------------------------------------------- */

/* Tab strip (Pending / Rules / Categories). Layers over Bootstrap .nav-tabs. */
.sn-tabs {
    border-bottom: 1px solid var(--sn-line);
    gap: .25rem;
}
.sn-tabs .nav-link {
    color: var(--sn-muted);
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: .55rem .9rem;
    font-weight: 600;
    font-size: .9rem;
    display: inline-flex;
    align-items: center;
}
.sn-tabs .nav-link:hover {
    color: var(--sn-ink);
    border-bottom-color: var(--sn-line);
}
.sn-tabs .nav-link.active {
    color: var(--sn-accent);
    background: transparent;
    border-bottom-color: var(--sn-accent);
}

/* Count pill on a tab. */
.sn-tab-badge {
    margin-left: .4rem;
    font-size: .7rem;
    font-weight: 700;
    min-width: 1.25rem;
    padding: .05rem .35rem;
    border-radius: 999px;
    background: var(--sn-accent-soft);
    color: var(--sn-accent);
    font-variant-numeric: tabular-nums;
}

/* Bulk-assign toolbar on the Pending tab. */
.sn-bulk-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    border-bottom: 1px solid var(--sn-line);
    background: var(--sn-canvas);
}

.sn-pending-status { min-width: 3rem; display: inline-block; }

/* Category taxonomy — the Ignore/system bucket reads muted. */
.sn-cat-ignore { color: var(--sn-muted); }
.sn-cat-ignore code, .sn-cat-ignore .fw-medium { color: var(--sn-muted); }

/* RBAC matrix — keep cells compact + centered. */
.sn-rbac-matrix td, .sn-rbac-matrix th { vertical-align: middle; }
.sn-rbac-matrix .ti { font-size: 17px; }

/* Enriched user roster — tighten the identifier column. */
.sn-roster code { font-size: .78rem; }

/* Compact roster: high-density rows so a big fleet fits on one screen. */
.sn-roster-dense { font-size: .85rem; }
.sn-roster-dense > :not(caption) > * > * { padding: .3rem .6rem; }
.sn-roster-dense td { vertical-align: middle; }
.sn-roster-dense .badge { font-size: .72rem; }
.sn-roster-btn {
    --bs-btn-padding-y: .05rem;
    --bs-btn-padding-x: .4rem;
    --bs-btn-font-size: .72rem;
    margin-left: .35rem;
}
.sn-row-off td { opacity: .6; }
.sn-row-off td:nth-child(2) { opacity: 1; }  /* keep the status cell readable */
.sn-roster-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding-top: .5rem;
    padding-bottom: .5rem;
}
.sn-roster-search { max-width: 280px; }

/* Monitoring Active/Disabled dropdowns in the roster tables. */
.sn-mon-select {
    width: auto;
    display: inline-block;
    padding-top: .1rem;
    padding-bottom: .1rem;
    font-size: .78rem;
}
.sn-mon-on { color: var(--sn-prod); border-color: var(--sn-prod); }
.sn-mon-off { color: var(--sn-muted); }

/* Fleet-health chips in the Devices card header. */
.sn-fleet-chips { display: flex; flex-wrap: wrap; gap: .35rem; }

/* Per-user shift cell: custom shifts read solid, inherited read muted. */
.sn-shift-chip { font-size: .8rem; }
.sn-shift-custom { color: var(--sn-accent); font-weight: 500; }
.sn-shift-form .form-control { font-size: .75rem; }

/* ==========================================================================
   R7 — page-head actions (Print + Favorite star), Favorites strip,
   Screenshot History grid + lightbox, and the @media print block.
   ========================================================================== */

/* page_head action buttons (Print / Favorite). Sit at the right of the head,
   next to any report filters. Unobtrusive, icon-first, accessible focus. */
.sn-page-head-actions {
    display: flex;
    align-items: center;
    gap: .4rem;
}
.sn-head-btn {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    border: 1px solid var(--sn-line);
    background: var(--sn-card);
    color: var(--sn-muted);
    border-radius: 8px;
    padding: .3rem .55rem;
    font-size: .82rem;
    line-height: 1;
    cursor: pointer;
}
.sn-head-btn:hover { color: var(--sn-ink); border-color: var(--sn-muted); }
.sn-head-btn:focus-visible {
    outline: 2px solid var(--sn-accent);
    outline-offset: 1px;
}
.sn-head-btn .ti { font-size: 16px; }
/* Active (favourited) star reads amber/gold, filled. The button LABEL text uses
   the darker amber text var for AA; only the icon keeps the bright fill hue. */
.sn-fav-btn.is-fav { color: var(--sn-neut-text); border-color: var(--sn-neut); }
.sn-fav-btn.is-fav .ti { color: var(--sn-neut); }

/* Favorites strip on the landing dashboard. */
.sn-fav-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin-bottom: 1rem;
}
.sn-fav-strip-label {
    font-size: 10.5px;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: var(--sn-muted);
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}
.sn-fav-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    background: var(--sn-card);
    border: 1px solid var(--sn-line);
    border-radius: 999px;
    padding: .28rem .7rem;
    font-size: .82rem;
    color: var(--sn-ink);
    text-decoration: none;
    box-shadow: var(--sn-shadow);
}
.sn-fav-chip:hover { border-color: var(--sn-accent); color: var(--sn-accent); }
.sn-fav-chip .ti { font-size: 14px; color: var(--sn-neut); }
.sn-fav-empty { font-size: .82rem; color: var(--sn-muted); }

/* Screenshot History grid (reuses the day-view thumbnail idea). */
.sn-shot-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .6rem;
}
.sn-shot-cell {
    display: block;
    border: 1px solid var(--sn-line);
    border-radius: 8px;
    overflow: hidden;
    background: var(--sn-card);
    text-decoration: none;
    cursor: zoom-in;
}
.sn-shot-cell img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    background: var(--sn-offline);
}
.sn-shot-meta {
    padding: .3rem .45rem;
    font-size: .72rem;
    color: var(--sn-muted);
    display: flex;
    justify-content: space-between;
    gap: .3rem;
}
.sn-shot-meta .sn-shot-user { color: var(--sn-ink); font-weight: 600; }

/* Lightbox overlay for the screenshot grid. */
.sn-lightbox {
    position: fixed;
    inset: 0;
    background: rgba(9, 11, 16, .82);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1080;
    padding: 2rem;
}
.sn-lightbox.is-open { display: flex; }
.sn-lightbox img {
    max-width: 96vw;
    max-height: 92vh;
    border-radius: 8px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, .5);
}
.sn-lightbox-close {
    position: absolute;
    top: 1rem;
    right: 1.25rem;
    background: transparent;
    border: 0;
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
}
/* Visible focus ring over the dark overlay (white, not accent, for contrast). */
.sn-lightbox-close:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
    border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Mobile — the master/detail layout stacks (templates put the list above the
   detail on narrow screens). Shorten the ranked list so it doesn't eat the
   whole viewport before the detail panel; template agents add scroll-into-view
   on row tap. Chart/toolbar wrap naturally via their existing flex rules.
   -------------------------------------------------------------------------- */
@media (max-width: 768px) {
    .sn-md-rows {
        max-height: 320px;
    }
    .sn-md-toolbar {
        gap: .4rem;
    }
    /* Let the per-day chart keep its horizontal scroll rather than crushing
       bars below tap size. */
    .sn-md-chart {
        height: 150px;
    }
}

/* --------------------------------------------------------------------------
   htmx integration — indicators + spinner.
   `hx-indicator` targets get .htmx-request added while a request is in flight;
   .htmx-indicator elements are hidden until then. htmx ships baseline rules,
   but we redeclare them here so they survive our cascade and can theme. The
   .sn-spin utility spins any icon (e.g. ti-loader-2) used as a busy indicator.
   -------------------------------------------------------------------------- */
.htmx-indicator {
    opacity: 0;
    transition: opacity .15s ease;
}
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
    opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
    .sn-spin {
        animation: sn-spin 0.8s linear infinite;
    }
}
@keyframes sn-spin {
    to { transform: rotate(360deg); }
}

/* Global htmx error toast (wired in base.html). Fixed, dismissible, above the
   lightbox. Hidden until JS reveals it on htmx:responseError/sendError/timeout. */
.sn-htmx-toast {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1090;
    max-width: 360px;
    display: none;
    align-items: flex-start;
    gap: .5rem;
    padding: .7rem .85rem;
    border-radius: var(--sn-radius);
    background: var(--sn-unprod-soft);
    border: 1px solid var(--sn-unprod);
    color: var(--sn-unprod-text);
    box-shadow: var(--sn-shadow);
    font-size: .85rem;
}
.sn-htmx-toast.is-open { display: flex; }
.sn-htmx-toast .sn-htmx-toast-msg { flex: 1 1 auto; min-width: 0; }
.sn-htmx-toast .sn-htmx-toast-close {
    flex: 0 0 auto;
    background: transparent;
    border: 0;
    color: inherit;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.sn-htmx-toast .sn-htmx-toast-close:focus-visible {
    outline: 2px solid var(--sn-unprod-text);
    outline-offset: 2px;
    border-radius: 3px;
}

/* --------------------------------------------------------------------------
   Print — hide the shell chrome (rail, topbar, filters, footer, actions) and
   expand the report content to the full page. Keeps tables/timelines legible.
   -------------------------------------------------------------------------- */
@media print {
    /* Re-pin the LIGHT token set even if the user prints from dark mode —
       otherwise dark canvas/ink tokens carry onto white paper (grey text on
       grey fills). Print is always light-on-white. */
    :root,
    [data-bs-theme="dark"] {
        --sn-canvas: #ffffff;
        --sn-card: #ffffff;
        --sn-line: #e7e9ef;
        --sn-ink: #12151b;
        --sn-muted: #4a5160;
        --sn-prod: #4c9a6b;
        --sn-neut: #cf9a3d;
        --sn-unprod: #c6493b;
        --sn-prod-text: #37744f;
        --sn-neut-text: #8a6420;
        --sn-unprod-text: #b3392c;
        --sn-idle: #9aa3b2;
        --sn-offline: #d7dbe3;
        --sn-prod-soft: #e7f0ea;
        --sn-neut-soft: #f7eeda;
        --sn-unprod-soft: #f6e2df;
    }

    /* Shell chrome — remove entirely from the printed page. */
    .app-topbar,
    .sidenav-menu,
    .footer,
    .sn-page-head-filters,
    .sn-page-head-actions,
    .sn-fav-strip,
    .sn-htmx-toast,
    .sn-lightbox {
        display: none !important;
    }

    /* Reclaim the full page width the rail used to occupy. */
    .content-page,
    .wrapper,
    .container-fluid {
        margin: 0 !important;
        padding: 0 !important;
        width: 100% !important;
        max-width: 100% !important;
    }

    body { background: #fff !important; }

    /* Flatten card surfaces so ink isn't wasted on shadows/borders. */
    .card {
        box-shadow: none !important;
        border: 1px solid #ccc !important;
        break-inside: avoid;
    }

    .sn-page-title { font-size: 1.2rem !important; }

    /* Force browsers to actually ink the data-viz fills. Without exact color
       adjust, background-colored bars/stripes/pills print BLANK (browsers drop
       backgrounds to save toner) — which is exactly the data we're printing. */
    .ratio-bar,
    .ratio-bar .ratio-seg,
    .sn-trend-stack,
    .sn-trend-seg,
    .kpi-stripe,
    .score-pill,
    .sn-class-badge,
    .sn-md-bar,
    .sn-md-fill,
    .sn-md-user-bar,
    .sn-md-chart-track,
    .sn-md-chart-fill,
    .badge-productive,
    .badge-neutral,
    .badge-unproductive,
    /* Machines-page fleet badges (status pills + outdated chip). Subtle-bg
       Bootstrap badges otherwise print blank, dropping the status colour that
       is the point of the column. */
    .sn-fleet-table .badge {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
    }

    /* Let wide tables/timelines print in full instead of scrolling. */
    .table-responsive,
    .sn-md-rows,
    [style*="overflow-x"] {
        overflow: visible !important;
    }

    /* The ranked list caps at 620px on screen; on paper that clips/overlaps
       the following content. Let it flow to its natural height. */
    .sn-md-rows {
        max-height: none !important;
    }

    a[href]::after { content: ""; }  /* don't append raw URLs after links */
}
