/* Assets page — migrated from Assets.razor.css; scoped under .page-assets. */
.page-assets { display: flex; flex-direction: column; gap: 34px; }

/* ── Component kit (scoped to this page): tables, modals, key/value
   rows, risk tags — ported from the old global portal.css. Colour
   tokens (--surface, --line, --accent…) inherit from .shell on the
   layout. Scoped here so they can't collide with Bootstrap globals. ── */

/* Data table */
.page-assets .data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.page-assets .data-table thead th {
    text-align: left; padding: 12px 16px;
    font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
    text-transform: uppercase; color: var(--faint);
    border-bottom: 1px solid var(--line); white-space: nowrap;
}
.page-assets .data-table tbody td { padding: 13px 16px; border-bottom: 1px solid var(--line-soft); color: var(--text); vertical-align: middle; }
.page-assets .data-table tbody tr:last-child td { border-bottom: none; }
.page-assets .data-table tbody tr.row-click { cursor: pointer; transition: background .14s ease; }
.page-assets .data-table tbody tr.row-click:hover { background: var(--surface-2); }
.page-assets .cell-strong { font-weight: 600; }
.page-assets .cell-mono { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 12px; color: var(--muted); }
.page-assets .cell-muted { color: var(--faint); }
.page-assets .live-count { font-size: 12.5px; color: var(--muted); padding: 12px 16px 0; }

/* Empty / loading / error */
.page-assets .empty { padding: 40px 24px; text-align: center; color: var(--muted); }
.page-assets .empty-title { font-size: 14.5px; font-weight: 600; color: var(--text); margin: 0 0 6px; }
.page-assets .empty-detail { font-size: 13px; color: var(--faint); margin: 0; }
.page-assets .loading { padding: 28px 24px; text-align: center; color: var(--muted); font-size: 13px; }
.page-assets .error-box { margin: 0 0 12px; padding: 11px 14px; border: 1px solid rgba(255,107,107,.3); background: rgba(255,107,107,.08); color: #ffb3b3; font-size: 12.5px; }

/* Modal overlay + card (centred, faded backdrop) */
.page-assets .modal-overlay {
    position: fixed; inset: 0; z-index: 1000;
    display: flex; align-items: center; justify-content: center; padding: 24px;
    background: rgba(7,9,10,.66); backdrop-filter: blur(3px);
    animation: modal-fade .18s ease both;
}
.page-assets .modal {
    display: block; position: relative; inset: auto; height: auto; overflow-x: hidden;
    width: 100%; max-width: 560px; max-height: calc(100vh - 64px); overflow-y: auto;
    background: var(--surface); border: 1px solid var(--line);
    box-shadow: 0 24px 60px rgba(0,0,0,.5); padding: 22px 24px 26px;
    animation: modal-rise .22s cubic-bezier(.22,.9,.3,1) both;
}
.page-assets .modal-lg { max-width: 720px; }
.page-assets .modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 18px; }
.page-assets .modal-title { margin: 0; font-family: var(--font-display); font-size: 18px; font-weight: 600; }
.page-assets .modal-eyebrow { margin: 0 0 3px; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }
.page-assets .modal-close {
    flex: none; width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); background: transparent; color: var(--muted);
    font-size: 15px; cursor: pointer; transition: border-color .15s, color .15s;
}
.page-assets .modal-close:hover { border-color: var(--accent-line); color: var(--text); }

/* Section label + key/value meta rows */
.page-assets .block-label { font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--accent); margin: 18px 0 8px; display: flex; align-items: center; gap: 8px; }
.page-assets .meta-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; margin: 4px 0 18px; }
.page-assets .meta-row { display: flex; flex-direction: column; gap: 3px; }
.page-assets .meta-label { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); }
.page-assets .meta-value { font-size: 13.5px; color: var(--text); }
.page-assets .kv-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--line-soft); }
.page-assets .kv-row:last-child { border-bottom: none; }

/* Risk / status colour helpers */
.page-assets .tag-risk { display: inline-flex; padding: 3px 10px; font-size: 11.5px; font-weight: 600; border: 1px solid transparent; }
.page-assets .tag-risk--low      { color: var(--good); background: rgba(61,220,151,.10); border-color: rgba(61,220,151,.25); }
.page-assets .tag-risk--medium   { color: var(--warn); background: rgba(255,180,84,.11); border-color: rgba(255,180,84,.28); }
.page-assets .tag-risk--high     { color: var(--bad);  background: rgba(255,107,107,.11); border-color: rgba(255,107,107,.28); }
.page-assets .tag-risk--critical { color: var(--crit); background: rgba(185,138,255,.12); border-color: rgba(185,138,255,.30); }
.page-assets .tag-risk--unknown  { color: var(--faint); background: var(--surface-2); border-color: var(--line); }
.page-assets .badge-good { color: var(--good); font-weight: 600; }
.page-assets .badge-bad  { color: var(--bad);  font-weight: 600; }

@media (max-width: 960px) { .page-assets .meta-grid { grid-template-columns: 1fr; } }

/* ── Log ingestion: period selector ── */
.page-assets .range-select { margin-left: auto; display: inline-flex; border: 1px solid var(--line); overflow: hidden; }
.page-assets .range-btn {
    padding: 6px 12px; font-size: 12px; font-weight: 600;
    background: transparent; color: var(--muted); border: none;
    border-left: 1px solid var(--line); cursor: pointer; transition: background .14s, color .14s;
}
.page-assets .range-btn:first-child { border-left: none; }
.page-assets .range-btn:hover { color: var(--text); }
.page-assets .range-btn.is-active { background: var(--accent); color: #04110e; }
.page-assets .range-btn:disabled { cursor: default; }

/* Period-change refresh indicator: spins beside the range buttons while the new
   period loads, so the chart stays in place instead of blanking to its skeleton
   (mirrors the Incidents toolbar Refresh). It takes the auto margin that would
   otherwise sit on .range-select, keeping both pinned to the right together. */
.page-assets .ingest-spin {
    margin-left: auto; align-self: center; flex: none;
    width: 15px; height: 15px; color: var(--accent);
    transform-box: fill-box; transform-origin: center;
    animation: tb-spin .7s linear infinite;
}
.page-assets .card--ingest .ingest-spin + .range-select { margin-left: 0; }
@media (prefers-reduced-motion: reduce) { .page-assets .ingest-spin { animation: none; } }

/* ── Log ingestion: compact summary figures (inside the ingestion card) ── */
.page-assets .ingest-summary { display: flex; flex-wrap: wrap; gap: 14px 30px; margin: 2px 0 18px; }
.page-assets .ingest-summary .is-val {
    display: block;
    font-family: var(--font-display);
    font-size: 21px; font-weight: 700; line-height: 1;
    color: var(--text); font-variant-numeric: tabular-nums;
}
.page-assets .ingest-summary .is-val small { font-size: 13px; font-weight: 600; color: var(--muted); }
.page-assets .ingest-summary .is-lab {
    display: block; margin-top: 5px;
    font-size: 11px; font-weight: 600; letter-spacing: .04em;
    text-transform: uppercase; color: var(--faint);
}

/* ── Log ingestion: see-more / see-less toggle ── */
/* Sits 14px under the last bar row (the padding — an auto margin collapses to nothing once
   something else has taken the card's spare height, which the trend chart now does: see
   .vol-chart-wrap). The auto margin is only still here for the degenerate case where there
   is no trend chart to grow — a single day in the period — and it keeps the toggle on the
   card's bottom edge rather than floating mid-card with dead space under it. */
.page-assets .ingest-more {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: auto; padding: 14px 2px 0;
    border: none; background: transparent;
    color: var(--accent); font: 600 12.5px var(--font-body);
    cursor: pointer; transition: color .15s ease;
}
.page-assets .ingest-more:hover { color: var(--text); }
.page-assets .ingest-more svg { width: 13px; height: 13px; }

/* ── Log ingestion: Volume / Cost / Forecast tabs ── */
/* Under the card head rather than in it: the head already carries the title, the refresh spinner and the
   period buttons, and a fourth control in that row pushed the period selector off the edge on a narrow
   card. Underlined rather than boxed so it reads as a view switch inside one card, not as three cards. */
.page-assets .ingest-tabs {
    display: flex; gap: 2px; margin: 0 0 16px;
    border-bottom: 1px solid var(--line);
}
.page-assets .ingest-tab {
    padding: 7px 12px; border: none; background: transparent;
    color: var(--muted); font: 600 12.5px var(--font-body);
    cursor: pointer; border-bottom: 2px solid transparent;
    margin-bottom: -1px; transition: color .14s ease, border-color .14s ease;
}
.page-assets .ingest-tab:hover { color: var(--text); }
.page-assets .ingest-tab.is-active { color: var(--text); border-bottom-color: var(--accent); }

/* Third line on the daily-cost hover card: the volume the money came from, so a reader chasing an
   expensive day does not have to switch tabs to find out how much arrived that day. */
.page-assets .vt-sub { font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ── Log ingestion: forecast rows ── */
/* Fluid tracks with a zero floor and a clamped middle (§26): the note is the one part whose length is
   data, so it is the part that gives way. A pixel minimum here is a floor the grid will not go below,
   which is what pushes a value off the edge of a card that clips. */
.page-assets .fc-rows { display: flex; flex-direction: column; gap: 1px; }
.page-assets .fc-row {
    display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto;
    align-items: baseline; gap: 10px;
    padding: 10px 2px; border-bottom: 1px solid var(--line);
}
.page-assets .fc-row:last-child { border-bottom: none; }
.page-assets .fc-label { min-width: 0; font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-assets .fc-note { min-width: 0; font-size: 11.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-assets .fc-val {
    font-family: var(--font-display); font-size: 15px; font-weight: 700;
    color: var(--text); font-variant-numeric: tabular-nums; text-align: right;
}

/* How far through the month the projection is, so "projected this month" is read with the right amount
   of salt: on the 2nd it is almost all projection, on the 28th almost all measurement. */
.page-assets .fc-month { margin-top: 16px; }
.page-assets .fc-month-track { height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; }
.page-assets .fc-month-fill { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.page-assets .fc-month-lab { display: block; margin-top: 7px; font-size: 11px; color: var(--faint); }

/* ── Log ingestion: what the estimate assumed ── */
/* Pushed to the bottom of the card so it reads as the footnote it is, and never as a lead-in. */
.page-assets .ingest-basis {
    margin: auto 0 0; padding-top: 16px;
    font-size: 11.5px; line-height: 1.55; color: var(--faint);
}
.page-assets .ingest-basis strong { color: var(--muted); font-weight: 600; }
.page-assets .ingest-basis-when { display: block; margin-top: 4px; }

/* NB: the daily-volume chart now uses the shared `.vol-*` bar chart and the by-source
   list uses the shared `.hbar-*` rows — both defined in the dashboard-vocabulary block
   further down this file (scoped to .page-assets). */

/* ── Page-specific: storage bar in the device detail modal ── */
.page-assets .storage-bar {
    width: 100%;
    height: 8px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    overflow: hidden;
    margin: 4px 0 8px;
}

.page-assets .storage-fill {
    height: 100%;
    background: var(--accent);
    transition: width .25s ease;
}

.page-assets .storage-label {
    font-size: 12px;
    color: var(--faint);
    margin-bottom: 4px;
}

/* ════════════════════════════════════════════════════════════════
   Incidents-page scheme (ported, scoped): skeleton shimmer · risk
   stat cards · toolbar · grid list. `.is-skel` is the load-state hook
   (not `.loading`, which is a standalone element here).
   ════════════════════════════════════════════════════════════════ */

.page-assets .is-skel .stat > *,
.page-assets .is-skel .card > *,
.page-assets .is-skel .inc-toolbar > *,
.page-assets .is-skel .panel > * { visibility: hidden; }

.page-assets .is-skel .stat,
.page-assets .is-skel .card,
.page-assets .is-skel .inc-toolbar,
.page-assets .is-skel .panel { position: relative; }

.page-assets .is-skel .stat.is-active {
    border-color: var(--line);
    background: var(--surface);
}

.page-assets .is-skel .inc-toolbar::after { border: 1px solid var(--line); }

.page-assets .is-skel .stat::after,
.page-assets .is-skel .card::after,
.page-assets .is-skel .inc-toolbar::after,
.page-assets .is-skel .panel::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 10;
    background-color: var(--surface-2);
    background-image: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.06) 50%, transparent 70%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: skel-shimmer 1.4s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .page-assets .is-skel .stat::after,
    .page-assets .is-skel .card::after,
    .page-assets .is-skel .inc-toolbar::after,
    .page-assets .is-skel .panel::after { animation: none; }
}

/* Log-ingestion card runs its own async load (Sentinel query) after the device
   list, so it can still be in flight once the page-wide `.is-skel` has cleared.
   Keep it shimmering on its own until its data lands — same overlay as above —
   rather than flashing the plain "Loading…" text out of step with the rest. */
.page-assets .card--ingest.is-loading > * { visibility: hidden; }
.page-assets .card--ingest.is-loading { position: relative; }
.page-assets .card--ingest.is-loading::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 10;
    background-color: var(--surface-2);
    background-image: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.06) 50%, transparent 70%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: skel-shimmer 1.4s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
    .page-assets .card--ingest.is-loading::after { animation: none; }
}

/* Cost / Forecast tab while its own read is in flight (the price list and ARM lookup take several
   seconds on a first open). The markup is the tab's real layout with placeholder text, so each piece is
   drawn as a shimmering bar with its text hidden: unstyled, it rendered as "0 estimated" over an empty
   chart and read as a card with nothing in it. */
.page-assets .ingest-skel { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.page-assets .ingest-skel .is-val,
.page-assets .ingest-skel .is-lab,
.page-assets .ingest-skel .block-label,
.page-assets .ingest-skel .vol-chart {
    color: transparent;
    border-radius: var(--radius-sm);
    background-color: var(--surface-2);
    background-image: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.06) 50%, transparent 70%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: skel-shimmer 1.4s linear infinite;
}
.page-assets .ingest-skel .is-val { width: 72px; }
.page-assets .ingest-skel .is-lab { width: 52px; height: 11px; }
.page-assets .ingest-skel .block-label { width: 96px; height: 12px; }
.page-assets .ingest-skel .vol-chart { padding-top: 0; }
/* A white sweep is invisible on a light surface, so the light theme sweeps in ink instead. */
html[data-theme="light"] .page-assets .ingest-skel .is-val,
html[data-theme="light"] .page-assets .ingest-skel .is-lab,
html[data-theme="light"] .page-assets .ingest-skel .block-label,
html[data-theme="light"] .page-assets .ingest-skel .vol-chart {
    background-image: linear-gradient(100deg, transparent 30%, rgba(16, 24, 32, 0.055) 50%, transparent 70%);
}
@media (prefers-reduced-motion: reduce) {
    .page-assets .ingest-skel .is-val,
    .page-assets .ingest-skel .is-lab,
    .page-assets .ingest-skel .block-label,
    .page-assets .ingest-skel .vol-chart { animation: none; }
}

/* ════════════════════════════════════════════════════════════════
   Dashboard vocabulary (ported from site/pages/soc-dashboard.css and
   re-scoped to .page-assets): the card / stat-tile / donut / volume-bar
   / horizontal-bar system that defines "high quality" across the SOC
   pages. The Environment page reuses it so it reads as a sibling of the
   SOC dashboard rather than a repurposed incidents list.
   ════════════════════════════════════════════════════════════════ */

/* ─── Summary + telemetry grid ────────────────────────────────── */
.page-assets .asset-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 14px; align-items: start; }
.page-assets .card--score  { grid-column: span 4; }
.page-assets .asset-stats  { grid-column: span 8; display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.page-assets .card--ingest { grid-column: span 8; }
.page-assets .asset-side   { grid-column: span 4; display: flex; flex-direction: column; gap: 14px; }

/* Consolidated empty / not-connected panel: takes the stat-block's slot (beside the score hero) when a
   connected tenant has no managed devices, or a staff view-as tenant hasn't connected Defender. The
   posture cards and inventory table are omitted in that state, so this one panel carries the message.
   When it's showing, the log-ingestion card has no right-hand neighbour, so it spans the full row. */
.page-assets .asset-empty-card { grid-column: span 8; align-self: stretch; justify-content: center; }
.page-assets .asset-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 32px 24px; max-width: 460px; margin: 0 auto; }
.page-assets .asset-empty-icon { width: 34px; height: 34px; color: var(--faint); margin-bottom: 10px; }
.page-assets .asset-grid.is-single .card--ingest { grid-column: 1 / -1; }

/* Summary row: the score card and the 2×2 stat block share one grid row, so give them a
   matched height and let each fill it — otherwise the shorter of the two stops short and
   their bottom edges don't meet (the grid's `align-items: start` top-aligns both at their
   natural height). align-self overrides that; the score card then centres its donut in the
   extra space (donut margin:auto), and the stat block splits its height evenly across its
   rows (grid-auto-rows:1fr) so the tile bottoms line up with the card's bottom edge. */
.page-assets .card--score,
.page-assets .asset-stats { align-self: stretch; }
.page-assets .asset-stats { grid-auto-rows: 1fr; }

/* Telemetry row: the ingestion card fills the row when the right-hand stack is the taller
   side (align-self overrides the grid's `align-items: start`), so their bottom edges meet.
   It is deliberately one-way. The ingestion card's own height is the reader's to change --
   "See all N sources" swaps six rows for sixteen -- and while the right column stretched
   with it, pressing that toggle pulled the donut, the sensor bars and the activity list
   taller too, so a control over one card visibly resized the three beside it. The stack
   keeps its natural height instead: the cards stay put and the extra height is the
   ingestion card's alone. */
.page-assets .card--ingest     { align-self: stretch; }
.page-assets .asset-side       { align-self: start; }
.page-assets .asset-side .card { flex: 0 0 auto; }

/* ─── Card shell ──────────────────────────────────────────────── */
.page-assets .card {
    display: flex; flex-direction: column;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--surface); padding: 14px 16px 16px;
}
.page-assets .card-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; }
.page-assets .card-head h3 { margin: 0; font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--text); }
.page-assets .card--ingest .range-select { margin-left: auto; }

/* Export, pinned to the right of the range buttons it exports the period of. The card head aligns on
   the baseline, which would hang a button with an icon in it off the baseline of its own label, so it
   centres itself against the range buttons beside it instead. */
.page-assets .card--ingest .ingest-export { align-self: center; padding: 6px 10px; }
.page-assets .card--ingest .ingest-export:disabled { color: var(--muted); background: transparent; cursor: default; }

/* ─── Stat tiles (posture tiles double as device-list filters) ── */
.page-assets .stat {
    display: flex; flex-direction: column; gap: 3px;
    padding: 14px 16px; min-height: 92px;
    border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.page-assets .stat-label { font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.page-assets .stat-value { font-family: var(--font-display); font-size: 32px; font-weight: 700; line-height: 1.05; color: var(--text); font-variant-numeric: tabular-nums; }
/* The headline's asterisk and the line that explains it (the count leaves out stale records). */
.page-assets .stat-mark { font-size: 18px; vertical-align: super; margin-left: 2px; color: var(--muted); }
.page-assets .stat-note { font-size: 11.5px; line-height: 1.3; color: var(--muted); }

.page-assets .stat-btn {
    text-align: left; font: inherit; cursor: pointer;
    transition: border-color .18s ease, background .18s ease;
}
.page-assets .stat-btn:hover { border-color: rgba(255, 255, 255, 0.20); background: var(--surface-2); }
.page-assets .stat-btn.is-active { border-color: var(--accent-line); background: var(--accent-soft); }

/* ─── Tone helpers ────────────────────────────────────────────── */
.page-assets .tone-good { color: var(--good); }
.page-assets .tone-warn { color: var(--warn); }
.page-assets .tone-bad  { color: var(--bad); }
.page-assets .tone-crit { color: var(--crit); }

/* ─── Arrow-segment donut (secure-score gauge + OS mix) ───────────
   The same chevron-boundary ring the SOC dashboard uses (see
   site/pages/soc.css). Segment geometry comes from ArrowSegs in the
   code-behind; the track ring + centre text are styled here. */
.page-assets .donut { width: 176px; height: 176px; display: block; margin: 4px auto 12px; }
/* Score gauge sits alone in its card; size it to sit level with the 2×2 stat block beside it. */
.page-assets .card--score .donut { width: 150px; height: 150px; margin: auto; }
.page-assets .donut-track { fill: none; stroke: rgba(255, 255, 255, 0.08); stroke-width: 15; }
.page-assets .donut-seg {
    /* stroke matches fill (set inline) to cover the anti-aliased seam between sectors;
       the ring sweeps in via geometry + the count-up ticker, so no CSS entrance here. */
    stroke-width: 1;
    stroke-linejoin: round;
    transition: filter .2s ease;
}
.page-assets .donut-seg:hover,
.page-assets .donut-seg.is-hot { filter: brightness(1.15); }
.page-assets .donut-total { fill: var(--text); font: 700 34px var(--font-display); text-anchor: middle; }
.page-assets .donut-caption { fill: var(--faint); font: 500 11px var(--font-body); letter-spacing: .06em; text-transform: uppercase; text-anchor: middle; }

/* Legend under the OS-mix donut. */
.page-assets .donut-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.page-assets .donut-legend li { display: grid; grid-template-columns: 11px 1fr auto; align-items: center; gap: 9px; font-size: 12.5px; }
.page-assets .donut-legend .dot { width: 11px; height: 11px; border-radius: 2px; transition: filter .2s ease; }
.page-assets .lg-label { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: color .2s ease; }
/* Lit with its ring sector (is-hot is set from either side), in the sector's own brightening. */
.page-assets .donut-legend li.is-hot .dot { filter: brightness(1.15); }
.page-assets .donut-legend li.is-hot .lg-label { color: var(--text); }
.page-assets .lg-count { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ─── Volume bars (daily ingestion) ───────────────────────────── */
/* Wrapper hosts a y-axis gutter + gridlines behind the bars. The scale overlay is
   anchored to the plot area: top offset = .vol-chart padding-top (8px); bottom offset
   = the x-axis label row (.vol-label height 12px + margin-top 5px = 17px). Keep these
   offsets in sync with .vol-chart / .vol-label below. */
/* The wrapper is the card's flexible region: the ingestion card stretches to the height of
   the right-hand stack (`align-self: stretch` above), and that slack has to land somewhere.
   Giving it to the trend chart turns dead space into plot height and keeps the see-more
   toggle attached to the list it controls — before this it was the toggle's `margin-top: auto`
   that soaked the slack up, stranding the button on the card's bottom edge with a void above it. */
.page-assets .vol-chart-wrap { position: relative; padding-left: 50px; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.page-assets .vol-scale { position: absolute; left: 0; right: 0; top: 8px; bottom: 17px; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
.page-assets .vol-grid-row { display: flex; align-items: center; height: 0; }
.page-assets .vol-tick { flex: none; width: 50px; padding-right: 8px; text-align: right; font-size: 10px; line-height: 1; color: var(--faint); white-space: nowrap; }
.page-assets .vol-grid-line { flex: 1; border-top: 1px dashed var(--line); }
/* 150px is the floor, not the height — the chart grows into whatever the card has spare (see
   .vol-chart-wrap). Bar heights are percentages of the plot and the y-axis overlay is anchored
   to it, so both follow. Expanding the source list to all 25 makes the card the taller column
   and the chart settles back to the floor. */
.page-assets .vol-chart { display: flex; align-items: flex-end; gap: 4px; flex: 1 1 auto; min-height: 150px; padding-top: 8px; }
.page-assets .vol-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; height: 100%; }
.page-assets .vol-bar-wrap { position: relative; flex: 1; width: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; }
/* Bars grow from the baseline on mount rather than transitioning `height`. A height
   transition only animates a bar that was already on screen, so a range change drew
   the days the old and new range share and left every extra bar static; the columns
   are keyed on the payload (Assets.razor) so all of them mount together and run this.
   `both` holds each bar at zero through its stagger delay, giving the left-to-right
   sweep — the delay is set inline per bar and normalised to a fixed total. */
.page-assets .vol-bar { width: 64%; min-height: 2px; background: linear-gradient(180deg, var(--accent), var(--accent-line)); border-radius: 2px 2px 0 0; transform-origin: bottom; animation: vol-grow .42s cubic-bezier(.22, .68, .36, 1) both; }
.page-assets .vol-col:hover .vol-bar { filter: brightness(1.12); }
/* Hover readout — the day and its own figure, so a bar with no x-axis label underneath (only ~12 of
   90 get one) still says what it is. Positioned against .vol-bar-wrap, whose height IS the plot, so
   the inline `bottom` can be the bar's own height percentage plus a gap and land just above it. */
.page-assets .vol-tip { position: absolute; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; flex-direction: column; gap: 1px; padding: 6px 9px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); box-shadow: 0 8px 22px rgba(0, 0, 0, .45); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity .12s ease; }
.page-assets .vol-col:hover .vol-tip { opacity: 1; }
/* The end columns anchor their card inwards — a centred one there overflows the card, which clips. */
.page-assets .vol-tip.is-start { left: 0; transform: none; }
.page-assets .vol-tip.is-end { left: auto; right: 0; transform: none; }
.page-assets .vt-when { font-size: 10.5px; color: var(--faint); }
.page-assets .vt-val { font-size: 13px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
@keyframes vol-grow { from { transform: scaleY(0); opacity: .4; } to { transform: scaleY(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .page-assets .vol-bar { animation: none; } }
.page-assets .vol-label { font-size: 10px; color: var(--faint); margin-top: 5px; white-space: nowrap; height: 12px; }

/* ─── Horizontal bars (ingestion by source) ───────────────────── */
/* One grid for the whole list, not one per row: the rows are `display: contents` so every
   row's cells land in the same four columns. Sizing each row independently made the two
   value columns (`max-content`) as wide as that row's own text, so the track column soaked
   up the difference and bars ended at a different x on every row. */
.page-assets .hbars {
    display: grid;
    grid-template-columns: minmax(110px, 1.3fr) 3fr max-content max-content;
    align-items: center;
    column-gap: 10px; row-gap: 11px;
    margin-top: 4px; font-size: 12.5px;
}
.page-assets .hbar-row { display: contents; }
.page-assets .hbar-label { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-assets .hbar-track { height: 9px; background: var(--surface-2); border: 1px solid var(--line); overflow: hidden; }
.page-assets .hbar-fill { display: block; height: 100%; background: var(--accent); transition: width .4s ease; }
.page-assets .hbar-fill.tone-neutral { background: var(--accent); }
.page-assets .hbar-fill.tone-good { background: var(--good); }
.page-assets .hbar-fill.tone-warn { background: var(--warn); }
.page-assets .hbar-fill.tone-bad  { background: var(--bad); }
.page-assets .hbar-count { text-align: right; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.page-assets .hbar-pct { text-align: right; color: var(--faint); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ─── Toolbar (only .inc-toolbar remains local; controls are global) ── */

.page-assets .inc-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 4px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--line-soft);
}

/* ─── Menus-open stacking context ─────────────────────────────── */

.page-assets .section.menus-open { position: relative; z-index: 50; }

/* ─── Inventory scroll anchor ─────────────────────────────────────
   The posture tiles scroll this section into view (panopticonScroll),
   so keep a little headroom above its heading rather than butting it
   against the top edge of the viewport. */
.page-assets #device-inventory { scroll-margin-top: 20px; }

/* ─── Filter row ──────────────────────────────────────────────── */

.page-assets .inc-filterbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 14px; }

/* Bucket dot, shared by the posture options in the Add-filter menu and the active-posture chip.
   Same colour as the stat tile the filter came from, so the two read as one control. Both parents
   (.pop-item, .filter-chip) are flex, so the <i> sizes as a flex item. */
.page-assets .pop-dot { width: 9px; height: 9px; flex: none; border-radius: 50%; }

/* ─── Pagination (in the list footer) ─────────────────────────── */

.page-assets .pager { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.page-assets .pager-size { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--faint); }
.page-assets .pager-size select {
    padding: 5px 8px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--text);
    font: 500 12.5px var(--font-body);
    cursor: pointer;
    color-scheme: dark;
}

.page-assets .pager-nav { display: inline-flex; align-items: center; gap: 10px; }
.page-assets .pager-page { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

.page-assets .pager-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--muted);
    font: 500 12.5px var(--font-body);
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}
.page-assets .pager-btn:hover:not(:disabled) { color: var(--text); border-color: rgba(255, 255, 255, 0.2); }
.page-assets .pager-btn:disabled { opacity: 0.4; cursor: default; }
.page-assets .pager-btn svg { width: 13px; height: 13px; flex: none; }

/* ─── Device list (grid rows) ─────────────────────────────────── */

.page-assets .inc-head,
.page-assets .inc-row {
    display: grid;
    gap: 16px;
    align-items: center;
}

.page-assets .inc-head {
    padding: 12px 22px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--line-soft);
}

.page-assets .inc-head span {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--faint);
}

.page-assets .inc-row {
    position: relative;
    padding: 16px 22px;
    border-bottom: 1px solid var(--line-soft);
    cursor: pointer;
    transition: background .18s ease;
}

.page-assets .inc-row::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--c);
    opacity: 0;
    transition: opacity .18s ease;
}

.page-assets .inc-row:hover { background: rgba(255, 255, 255, 0.035); }
.page-assets .inc-row:hover::before { opacity: 0.8; }
.page-assets .inc-row:last-of-type { border-bottom: 0; }

.page-assets .inc-name-cell { min-width: 0; }
.page-assets .inc-name-cell strong {
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
}

.page-assets .inc-plain {
    font-size: 13px;
    color: var(--text);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-assets .inc-sev,
.page-assets .inc-status {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--muted);
    min-width: 0;
}

.page-assets .inc-sq {
    width: 11px;
    height: 11px;
    flex: none;
}

.page-assets .inc-dot2 {
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 50%;
}

.page-assets .inc-time { display: grid; gap: 2px; min-width: 0; }
.page-assets .inc-time > span:first-child { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.page-assets .inc-time-abs { font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; }

.page-assets .inc-empty {
    padding: 36px 22px;
    text-align: center;
    color: var(--faint);
    font-size: 13.5px;
}

.page-assets .inc-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 13px 22px;
    border-top: 1px solid var(--line-soft);
    color: var(--faint);
    font-size: 12.5px;
}

.page-assets .inc-foot strong { color: var(--muted); font-variant-numeric: tabular-nums; }

/* ─── Responsive ──────────────────────────────────────────────── */

@media (max-width: 1250px) {
    /* Score sits above a full-width 4-across stat row; charts stack. */
    .page-assets .card--score  { grid-column: 1 / -1; }
    .page-assets .asset-stats  { grid-column: 1 / -1; grid-template-columns: repeat(4, 1fr); }
    .page-assets .card--ingest,
    .page-assets .asset-empty-card,
    .page-assets .asset-side   { grid-column: 1 / -1; }
}

@media (max-width: 1080px) {
    .page-assets .inc-head { display: none; }
    .page-assets .inc-row {
        grid-template-columns: 1fr auto !important;
        row-gap: 10px;
        column-gap: 14px;
    }
    .page-assets .inc-name-cell { grid-column: 1 / -1; }
    .page-assets .inc-updated { text-align: right; }
}

@media (max-width: 640px) {
    .page-assets .asset-stats { grid-template-columns: repeat(2, 1fr); }
}
