/* smart-me ZERO — brand base layer over MudBlazor (smart-me 2026 CI, dashboard token set dash-*).
   Loaded after MudBlazor.min.css so equal-specificity rules win by source order.
   Palette, type scale, radius and elevation live in Theme/SmartMeTheme.cs; the few CI tokens
   MudBlazor has no slot for (mono family, icon tile, focus ring, ease) are the custom properties
   below. Rules of the system: one accent (#2563EB in both modes), surfaces and hairlines instead of
   shadows, radii only from 6 · 8 · 10 · 12 · 16 · 20 · 28, hover = colour change (never scale). */

:root {
    --sm-font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
    --sm-ease: cubic-bezier(.16, 1, .3, 1);
    --sm-blue: #2563EB;
    --sm-blue-hover: #1D4ED8;
    --sm-focus-ring: 0 0 0 3px rgba(37, 99, 235, .15);
    --sm-icbg: #E8EFFF;
    --sm-soft: #EDF1F7;
    --sm-chip: #F5F7FA;
    --sm-card2: #FFFFFF;
    --sm-tip: #15171C;
    --sm-tip-text: #FFFFFF;
    --sm-card-shadow: none;
    --sm-menu-shadow: 0 24px 48px -16px rgba(21, 23, 28, .22), 0 2px 6px rgba(21, 23, 28, .06);
    --sm-r-badge: 6px;
    --sm-r-nav: 8px;
    --sm-r-sm: 10px;
    --sm-r-md: 12px;
    --sm-r-lg: 16px;
    --sm-r-xl: 20px;
}

:root[data-theme="dark"] {
    --sm-icbg: rgba(143, 176, 255, .10);
    --sm-soft: #1D2027;
    --sm-chip: rgba(255, 255, 255, .07);
    --sm-card2: #1A1D23;
    --sm-tip: #F2F3F5;
    --sm-tip-text: #15171C;
    /* The CI's blue glow (dash-card-shadow) only on what floats (dialogs): under every card of a
       grid it reads as blotches between the cards. */
    --sm-glow: 0 30px 70px -40px rgba(37, 99, 235, .7);
    --sm-menu-shadow: 0 24px 48px -16px rgba(0, 0, 0, .7);
}

html, body {
    font-family: "Noto Sans", system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* Headlines are ink (dash-tx) with tight tracking and balanced wrapping — blue is the accent, not
   the headline colour. */
.mud-main-content .mud-typography-h1,
.mud-main-content .mud-typography-h2,
.mud-main-content .mud-typography-h3,
.mud-main-content .mud-typography-h4,
.mud-main-content .mud-typography-h5,
.mud-main-content .mud-typography-h6 {
    color: var(--mud-palette-text-primary);
    text-wrap: balance;
}

/* Buttons are rounded rectangles, never pills (CI): R10 like the compact CI buttons, sentence
   case, hover only changes the fill. */
.mud-button-root:not(.mud-icon-button):not(.mud-table-pagination-button) {
    border-radius: var(--sm-r-sm);
    transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}

.mud-button-filled,
.mud-button-filled:hover,
.mud-button-filled:active,
.mud-button-filled:focus-visible {
    box-shadow: none;
}

.mud-button-filled.mud-button-filled-primary:hover {
    background-color: var(--sm-blue-hover);
}

/* Keyboard focus: the CI's 3px blue outline on buttons and links. */
.mud-button-root:focus-visible,
.mud-nav-link:focus-visible,
a:focus-visible {
    outline: 3px solid var(--sm-blue);
    outline-offset: 2px;
}

/* Cards / surfaces: dash-card on a 1px dash-bd hairline instead of a shadow, R16 (inner cards).
   Square papers (tables flush in a card, the app bar) stay square; popovers and dialogs float. */
.mud-paper:not(.mud-paper-square) {
    border-radius: var(--sm-r-lg);
}

.mud-main-content .mud-paper:not(.mud-paper-outlined):not(.mud-paper-square):not(.mud-popover):not(.sm-filter-sheet) {
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: var(--sm-card-shadow);
}

/* Tables and cards nested inside a card do not get a second frame. */
.mud-main-content .mud-paper .mud-paper:not(.mud-paper-outlined):not(.mud-popover) {
    border: 0;
    box-shadow: none;
}

/* Floating layers: menus and popovers on dash-card2 with a hairline, R12. */
.mud-popover {
    border-radius: var(--sm-r-md);
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: var(--sm-menu-shadow);
}

.mud-popover.mud-paper,
.mud-popover .mud-list {
    background-color: var(--sm-card2);
}

.mud-popover.mud-paper:not(.mud-paper-square) {
    border-radius: var(--sm-r-md);
}

.mud-list-item {
    border-radius: var(--sm-r-nav);
}

/* Tooltips: dash-tip (ink on light, light on dark). */
.mud-tooltip.mud-tooltip-default {
    background-color: var(--sm-tip);
    color: var(--sm-tip-text);
    border-radius: var(--sm-r-nav);
    font-size: 12.5px;
    font-weight: 500;
}

/* Chips are badges: R6, 600, no pill. */
.mud-chip {
    border-radius: var(--sm-r-badge);
    font-weight: 600;
}

/* Switch thumbs lose their elevation with the flat theme; a hairline shadow keeps the white thumb
   visible on its light track. */
.mud-switch-thumb-small,
.mud-switch-thumb-medium,
.mud-switch-thumb-large {
    box-shadow: 0 1px 3px rgba(21, 23, 28, .28);
}

/* Dialogs: one R20 container (CI form radius) on dash-card2, a plain title over a hairline. */
.mud-dialog:not(.mud-dialog-fullscreen) {
    border-radius: var(--sm-r-xl);
}

.mud-dialog {
    background-color: var(--sm-card2);
    border: 1px solid var(--mud-palette-lines-default);
}

.mud-dialog:not(.mud-dialog-fullscreen) .mud-dialog-title {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    padding: 20px 24px 18px;
}

.mud-dialog:not(.mud-dialog-fullscreen) .mud-dialog-actions {
    padding: 12px 24px 20px;
}

/* Links are blue and underlined in body copy. */
.mud-main-content a:not(.mud-nav-link):not(.mud-button-root),
.mud-typography a {
    color: var(--sm-blue);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.mud-main-content a:not(.mud-nav-link):not(.mud-button-root):hover {
    color: var(--sm-blue-hover);
}

/* Form fields: R10 (theme radius), blue border plus the CI focus ring when focused. */
.mud-input.mud-input-outlined.mud-focused .mud-input-outlined-border {
    box-shadow: var(--sm-focus-ring);
}

/* ---------- App bar & brand ---------- */

/* White top bar (dash-side) with a hairline at the bottom — no gradient, no shadow. The height is
   the theme's AppbarHeight (SmartMeTheme.cs), which also drives MudMainContent's top padding. */
.sm-appbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    box-shadow: none;
    height: var(--mud-appbar-height);
    min-height: var(--mud-appbar-height);
}

/* The toolbar drives the visual bar height. */
.sm-appbar .mud-toolbar {
    height: var(--mud-appbar-height);
    min-height: var(--mud-appbar-height);
    gap: 2px;
}

.sm-appbar .mud-icon-button {
    color: var(--mud-palette-text-secondary);
}

.sm-appbar .mud-icon-button:hover {
    color: var(--mud-palette-text-primary);
    background-color: var(--sm-soft);
}

.sm-appbar .mud-button-root.sm-appbar-menu,
.sm-appbar-menu .mud-button-root {
    font-size: 14px;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
}

.sm-appbar .mud-button-root.sm-appbar-menu:hover,
.sm-appbar-menu .mud-button-root:hover {
    background-color: var(--sm-soft);
}

/* On a phone the tenant and user menus shrink to their icons (the names stay in the menus'
   aria-labels), so the bar's controls fit 360px without pushing the page sideways. */
@media (max-width: 599.98px) {
    .sm-appbar-menu .mud-button-label {
        font-size: 0;
    }

    .sm-appbar-menu .mud-button-icon-start {
        margin: 0;
    }

    .sm-appbar-menu .mud-button-icon-end {
        display: none;
    }

    .sm-appbar-product {
        display: none;
    }

    .sm-appbar .mud-button-root.sm-appbar-menu,
    .sm-appbar-menu .mud-button-root {
        min-width: 0;
        padding: 6px;
    }
}

/* smart-me wordmark (logo colours: blue "smart-" + green "me"), header width ~120px. On dark it is
   rendered white with the CI's filter instead of a second file. */
.sm-brand-logo {
    height: 22px;
    width: auto;
    display: block;
    flex: none;
    align-self: center;
}

:root[data-theme="dark"] .sm-brand-logo,
:root[data-theme="dark"] .sm-login-logo,
:root[data-theme="dark"] .sm-splash-logo {
    filter: brightness(0) invert(1);
}

/* Product name next to the wordmark: a blue mono label, separated by a hairline. */
.sm-appbar-product {
    display: flex;
    align-items: center;
    align-self: center;
    height: 22px;
    margin-left: 14px;
    padding-left: 14px;
    border-left: 1px solid var(--mud-palette-lines-default);
    font-family: var(--sm-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--sm-blue);
}

/* Two-tone wordmark on the light Login card. */
.sm-login-logo {
    height: 30px;
    width: auto;
    display: block;
}

/* ---------- Side bar (DashSidebar): 236px, mono group labels, soft active fill ---------- */

.sm-drawer {
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sm-drawer .mud-navmenu {
    padding: 14px 0;
}

.sm-drawer .mud-nav-link {
    margin: 1px 12px;
    padding: 9px 12px;
    border-radius: var(--sm-r-md);
    width: auto;
    color: var(--mud-palette-drawer-text);
    transition: background-color .18s ease, color .18s ease;
}

.sm-drawer .mud-nav-link .mud-nav-link-text {
    font-size: 14px;
    font-weight: 500;
}

.sm-drawer .mud-nav-link .mud-nav-link-icon {
    color: inherit;
    font-size: 20px;
}

.sm-drawer .mud-nav-link:hover:not(.mud-nav-link-disabled) {
    background-color: var(--sm-soft);
    color: var(--mud-palette-text-primary);
}

/* Nav links are wrapped in tooltips (used in mini mode); the wrapper must not shrink the
   link to content width when the drawer is expanded. */
.sm-drawer .mud-tooltip-root {
    display: block;
}

/* Each entry fills its row: MudBlazor's .mud-nav-item is a flex container, so without this the link
   shrinks to its content — the active fill became a small blob and the rail icons sat off-centre. */
.sm-drawer .mud-nav-item > .mud-nav-link {
    flex: 1 1 auto;
    min-width: 0;
}

/* Icon rail (collapsed mini drawer): labels live in the tooltips; a group header shrinks to a short
   hairline, so the five areas stay apart. (.mud-typography lifts this above the group-label rule
   below.) The first group needs no separator. */
.sm-drawer-mini .sm-nav-section.mud-typography {
    height: 1px;
    margin: 10px 16px;
    padding: 0;
    overflow: hidden;
    font-size: 0;
    background-color: var(--mud-palette-lines-default);
}

.sm-drawer-mini .mud-navmenu > .sm-nav-section.mud-typography:first-child {
    display: none;
}

.sm-drawer-mini .mud-nav-link {
    margin: 2px 6px;
    padding: 9px 0;
    justify-content: center;
}

.sm-drawer-mini .mud-nav-link .mud-nav-link-text {
    display: none;
}

.sm-drawer-mini .mud-nav-link .mud-icon-root {
    margin: 0;
}

/* Active: dash-soft fill, ink label, Brand Blue icon. The navmenu classes out-rank MudBlazor's own
   ".mud-navmenu.mud-navmenu-default .mud-nav-link.active" (which would paint the label blue). */
.sm-drawer .mud-navmenu.mud-navmenu-default .mud-nav-link.active:not(.mud-nav-link-disabled),
.sm-drawer .mud-navmenu.mud-navmenu-default .mud-nav-link.active:hover:not(.mud-nav-link-disabled) {
    background-color: var(--sm-soft);
    color: var(--mud-palette-text-primary);
}

.sm-drawer .mud-nav-link.active .mud-nav-link-text {
    font-weight: 600;
}

.sm-drawer .mud-nav-link.active .mud-icon-root {
    color: var(--sm-blue);
}

/* Group label: JetBrains Mono 10px, .16em, muted. */
.sm-nav-section.mud-typography {
    display: block;
    padding: 18px 24px 8px;
    font-family: var(--sm-font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: .16em;
    line-height: 1.2;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.sm-drawer .mud-navmenu > .sm-nav-section:first-child {
    padding-top: 6px;
}

/* ---------- Reusable brand components ---------- */

/* Section label (filters, dialog sections): the CI's muted mono kicker. */
.sm-overline {
    display: block;
    font-family: var(--sm-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Kicker above a section or page title: JetBrains Mono, uppercase, Brand Blue. */
.sm-kicker {
    display: block;
    font-family: var(--sm-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--sm-blue);
}

/* Filter sidebar (Devices): the panel chrome (heading, checkbox labels) stays a notch smaller than
   the table it filters. The outlined fields inside use the global form-field look below. */
.sm-filter-panel .mud-typography-h6 {
    font-size: 16px;
}

.sm-filter-panel .mud-typography-body1 {
    font-size: 13px;
}

/* ---------- Form fields (one look everywhere) ---------- */

/* Every form field across the app reads the same compact outlined style — filter rail, dialogs and
   form pages alike. MudGlobal.InputDefaults makes every field Outlined + Dense (see Program.cs), so
   these global rules reach them all; the 8px corner is set with the brand base layer above. The
   selectors mirror MudBlazor's own specificity (app.css loads after MudBlazor.min.css) so they win.

   .mud-input font-size is `inherit` in MudBlazor, so this wins by source order while leaving the
   more-specific table/pagination inputs at their own size. */
.mud-input {
    font-size: 14px;
}

/* Slimmer dense padding: default is 10.5px (≈40px tall) — 7px ≈ 31px. Covers the single-line input,
   the value slot of selects/date-pickers, and multi-line textareas. */
.mud-input > input.mud-input-root-outlined.mud-input-root-margin-dense,
div.mud-input-slot.mud-input-root-outlined.mud-input-root-margin-dense,
.mud-input > textarea.mud-input-root-outlined.mud-input-root-margin-dense {
    padding-top: 7px;
    padding-bottom: 7px;
}

/* Multi-line textareas fade their top edge with a mask pinned to the old 10.5px padding; re-pin it
   to the new 7px so the first line isn't ghosted under the fade. */
.mud-input > textarea.mud-input-root-outlined.mud-input-root-margin-dense {
    -webkit-mask-image: linear-gradient(to bottom, transparent 7px, black 7px);
    mask-image: linear-gradient(to bottom, transparent 7px, black 7px);
}

/* CI Field: the label stands ABOVE the field (13px / 600, ink), not floating inside the outline —
   MudBlazor's shrunk dense label is ~9px and sits on the border. Every labelled outlined field
   (text, select, date, numeric) reserves room on top for it; the outline loses its notch. */
.mud-input-control.mud-input-outlined-with-label,
.mud-input-control.mud-input-control-margin-dense.mud-input-outlined-with-label,
.mud-input-control.mud-input-control-margin-normal.mud-input-outlined-with-label {
    /* The dense/normal selectors match MudBlazor's own (margin-top: 8px), which otherwise wins and
       lets the raised label overlap whatever stands above the field. 28px = the label's 21px lift
       plus air, which also holds when this margin collapses with a paragraph's margin above. */
    margin-top: 28px;
    margin-bottom: 0;
}

.mud-input-control > .mud-input-control-input-container > .mud-input-label-outlined.mud-input-label-inputcontrol {
    transform: translate(0, -21px) scale(1) !important;
    font-size: 13px;
    font-weight: 600;
    line-height: 18px;
    color: var(--mud-palette-text-primary);
    background: transparent;
    padding: 0;
    max-width: 100%;
    pointer-events: auto;
}

.mud-input-outlined-with-label .mud-input-outlined-border legend {
    display: none;
}

/* The label sits above even when the field is empty, so its placeholder may show inside. */
.mud-input-outlined-with-label input::placeholder,
.mud-input-outlined-with-label textarea::placeholder {
    opacity: 1;
    color: var(--mud-palette-text-disabled);
}

/* KPI stat card: icon tile + big number. Hover is a colour change only (CI: never lift or scale):
   the hairline turns blue. */
.sm-stat-card {
    padding: 20px;
    display: flex;
    align-items: center;
    gap: 16px;
    height: 100%;
    transition: border-color .18s ease;
}

.mud-main-content .mud-paper.sm-stat-card:hover {
    border-color: var(--sm-blue);
}

/* Icon tile (CI IconTile): R12, dash-icbg, blue icon. */
.sm-stat-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--sm-r-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

/* Tinted icon tiles per semantic role (color-mix keeps them dark-mode aware). */
.sm-tint-primary {
    background: var(--sm-icbg);
    color: var(--sm-blue);
}

.sm-tint-success {
    background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent);
    color: var(--mud-palette-success);
}

.sm-tint-warning {
    background: color-mix(in srgb, var(--mud-palette-warning) 16%, transparent);
    color: var(--mud-palette-warning-darken);
}

.sm-tint-error {
    background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
}

/* Key/value status rows (device dialog); two columns when the dialog is wide enough. */
.sm-kv-grid {
    display: grid;
    grid-template-columns: 1fr;
}

@media (min-width: 600px) {
    .sm-kv-grid {
        grid-template-columns: 1fr 1fr;
        column-gap: 32px;
    }

    .sm-kv-grid .sm-kv:nth-last-child(-n+2) {
        border-bottom: none;
    }
}

.sm-kv {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-bottom: 1px solid var(--mud-palette-divider);
}

.sm-kv:last-child {
    border-bottom: none;
}

.sm-kv .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

.sm-kv-label {
    flex: 1;
    font-size: 14px;
    color: var(--mud-palette-text-secondary);
}

.sm-kv-value {
    font-size: 14px;
    font-weight: 500;
}

/* ---------- Tabs ---------- */

/* Tab headers are chrome, not content: smaller than MudBlazor's 1rem / 48px default so they
   don't outweigh the table headers below them. */
.mud-tabs .mud-tab {
    font-size: 14px;
    font-weight: 500;
    min-height: 44px;
    /* Sentence case, like every button — MudBlazor's tabs default to ALL CAPS. */
    text-transform: none;
    letter-spacing: normal;
}

.mud-tabs .mud-tab .mud-icon-root {
    font-size: 18px;
}

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

/* The head belongs to its card: card surface with a hairline below (on the page grey it read as
   a strip detached from the rows). */
.mud-table-head .mud-table-cell {
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-surface);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sm-clickable-rows .mud-table-body .mud-table-row {
    cursor: pointer;
}

/* A load that finishes quickly must not flash the table's progress bar — even a manual
   filter/sort/refresh produces an ugly few-ms blip otherwise. Reveal it only after 400 ms of
   continuous loading, so only genuinely slow queries get the indicator. MudTable inserts the bar
   fresh on each server load, which restarts the reveal delay. */
.mud-table-loading-progress {
    opacity: 0;
    animation: sm-loading-reveal 0s linear 400ms forwards;
}

@keyframes sm-loading-reveal {
    to {
        opacity: 1;
    }
}

/* Tables that refresh in the background (Devices) show the loading bar for the initial fill
   only: the page adds this class once the first load completed, and every later reload —
   background poll, sort, filter — runs without any loading indicator. */
.sm-hide-loading-bar .mud-table-loading-progress {
    display: none;
}

/* ---------- Dense tables (UniFi-inspired density, shared by every table) ---------- */

/* Compact rows: smaller type, tight padding, and (on desktop) no line breaks — long values
   truncate with an ellipsis instead of wrapping. */
.sm-dense-table .mud-table-cell {
    font-size: 14px;
    padding: 5px 12px;
}

.sm-dense-table th.mud-table-cell {
    font-size: 12.5px;
    line-height: 1.3;
}

/* Below MudTable's Sm breakpoint the stacked card layout needs wrapping, so nowrap only
   applies from 600px up. */
@media (min-width: 600px) {
    .sm-dense-table .mud-table-cell {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* Chips inside dense rows slim down so chip-bearing rows stay as flat as plain ones. */
.sm-dense-table .mud-table-body .mud-chip {
    height: 20px;
    font-size: 11px;
    margin: 0;
}

/* ---------- Devices grid (on top of sm-dense-table) ---------- */

/* Columns are manually resizable; fixed layout makes the header widths authoritative so
   truncation and resizing behave predictably. */
.sm-device-grid .mud-table-root {
    table-layout: fixed;
    min-width: 960px; /* below this the container scrolls horizontally instead of squeezing */
}

.sm-device-grid .mud-table-container {
    overflow-x: auto;
}

/* Pinned identity columns — (checkbox,) state and serial stay put while the rest scrolls
   horizontally. MudBlazor pins every StickyLeft cell at left:0, which would stack them on top
   of each other; offset each by the summed widths of the pinned columns before it (42px
   checkbox, 64px state — the columns are non-resizable so these stay true). */
.sm-device-grid:not(.sm-grid-selectable) .mud-table-cell.sticky-left:nth-child(2) {
    left: 64px;
}

.sm-grid-selectable .mud-table-cell.sticky-left:nth-child(2) {
    left: 42px;
}

.sm-grid-selectable .mud-table-cell.sticky-left:nth-child(3) {
    left: 106px;
}

/* MudBlazor gives sticky cells a gray background; match the row surface instead, keep the
   hover tint in sync with the row, and mark the pinned edge with a hairline seam. */
.sm-device-grid .mud-table-cell.sticky-left {
    background-color: var(--mud-palette-surface);
}

.sm-device-grid .mud-table-head .mud-table-cell.sticky-left {
    background-color: var(--mud-palette-surface);
}

.sm-device-grid .mud-table-body .mud-table-row:hover .mud-table-cell.sticky-left {
    background-color: var(--mud-palette-table-hover);
}

.sm-device-grid:not(.sm-grid-selectable) .mud-table-cell.sticky-left:nth-child(2),
.sm-grid-selectable .mud-table-cell.sticky-left:nth-child(3) {
    box-shadow: inset -1px 0 0 var(--mud-palette-lines-default);
}

/* Connection state as a small status dot (label + last-seen live on its tooltip). */
.sm-state-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    vertical-align: middle;
}

.sm-dot-online {
    background: var(--mud-palette-success);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mud-palette-success) 22%, transparent);
}

.sm-dot-offline {
    background: var(--mud-palette-error);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mud-palette-error) 18%, transparent);
}

.sm-dot-temp {
    background: var(--mud-palette-warning);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mud-palette-warning) 22%, transparent);
}

.sm-dot-unknown {
    background: var(--mud-palette-text-disabled);
}

/* Slim tag pills — half the height of a MudChip, so tagged rows stay as flat as untagged ones. */
.sm-tag {
    display: inline-block;
    max-width: 110px;
    padding: 0 7px;
    border-radius: var(--sm-r-badge);
    border: 1px solid var(--mud-palette-lines-default);
    font-size: 11px;
    font-weight: 500;
    line-height: 17px;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
}

.sm-tag + .sm-tag {
    margin-left: 4px;
}

/* "Planned" is not the same state as "unmapped": the installation is scheduled, it just has not
   happened yet. Tinted so the two read differently at a glance in a long list. */
.sm-tag-planned {
    max-width: 150px;
    border-color: var(--mud-palette-info);
    color: var(--mud-palette-info);
    background: color-mix(in srgb, var(--mud-palette-info) 8%, transparent);
}

/* The import dialog's column mapping: as many selects per row as fit, one per row on a phone. */
.sm-import-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px;
}

/* De-emphasized cell text (family, firmware, installed) keeps the eye on identity and state. */
.sm-cell-secondary,
.sm-text-secondary {
    color: var(--mud-palette-text-secondary);
}

/* ---------- Utilities (instead of inline Style attributes) ---------- */

/* Numbers line up: right-aligned with tabular figures, for amounts, counts and kWh columns. */
.sm-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Identifiers (metering point IDs, hashes, device ids) and live values: JetBrains Mono. */
.sm-mono {
    font-family: var(--sm-font-mono);
    font-size: 0.92em;
}

/* An input whose VALUE is an identifier: only the typed text is monospace, not label or helper. */
.sm-mono-input input {
    font-family: var(--sm-font-mono);
}

.sm-grow {
    flex: 1;
    min-width: 0;
}

.sm-tight {
    line-height: 1.2;
}

.sm-strong {
    font-weight: 600;
}

.sm-pointer {
    cursor: pointer;
}

.sm-spin {
    animation: sm-spin 1.6s linear infinite;
}

@keyframes sm-spin {
    to {
        transform: rotate(360deg);
    }
}

/* ---------- Motion & chrome ---------- */

/* Page content fades up once on load — subtle, not distracting. */
.mud-main-content > div {
    animation: sm-fade-up .5s var(--sm-ease) both;
}

@keyframes sm-fade-up {
    from {
        opacity: 0;
        transform: translateY(6px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* Thin brand scrollbars. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--mud-palette-lines-default) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-thumb {
    background: var(--mud-palette-lines-default);
    border-radius: 5px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

/* ---------- Loading splash (index.html, before Blazor boots) ---------- */

/* Wordmark, a blue mono product label, the caption and a thin Brand Blue progress line on the
   dash-bg ground — no gradients, no logo tile (CI: no blue squares). */
.sm-splash {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    gap: 14px;
    background: #F1F3F6;
    font-family: "Noto Sans", system-ui, sans-serif;
    color: #15171C;
}

.sm-splash-logo {
    width: 160px;
    height: auto;
    display: block;
}

.sm-splash-title {
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: #2563EB;
}

.sm-splash-caption {
    font-size: 13px;
    color: #6B7079;
}

.sm-splash-bar {
    width: 160px;
    height: 3px;
    margin-top: 6px;
    border-radius: 2px;
    background: #DBEAFE;
    overflow: hidden;
}

.sm-splash-bar::after {
    content: "";
    display: block;
    width: 40%;
    height: 100%;
    border-radius: 2px;
    background: #2563EB;
    animation: sm-loading 1.2s cubic-bezier(.16, 1, .3, 1) infinite;
}

@keyframes sm-loading {
    from {
        transform: translateX(-100%);
    }

    to {
        transform: translateX(350%);
    }
}

/* index.html sets data-theme before Blazor boots (saved choice, else the OS setting), so the
   splash already matches the theme the app is about to render in. Blue stays #2563EB. */
:root[data-theme="dark"] .sm-splash {
    background: #0A0B0E;
    color: #F2F3F5;
}

:root[data-theme="dark"] .sm-splash-caption {
    color: #8A8F98;
}

:root[data-theme="dark"] .sm-splash-bar {
    background: #1D2027;
}

/* ---------- Device status visualization (DeviceStatusOverview) ---------- */

/* The status flow needs the full width; the dialog's other tabs keep MaxWidth.Small. Higher
   specificity than .mud-dialog-width-sm, so no !important. */
.mud-dialog.sm-dialog-wide {
    max-width: min(1120px, calc(100vw - 32px));
    width: calc(100vw - 32px);
}

.sm-status-viz {
    position: relative;
    background: var(--mud-palette-background);
    border-radius: var(--sm-r-lg);
    padding: 8px 16px 4px;
}

/* Cap the height so the whole flow fits on screen without scrolling — a replaced element with a
   viewBox keeps its aspect ratio, so the width shrinks along with it. */
.sm-status-viz svg {
    display: block;
    width: 100%;
    max-height: min(58vh, 420px);
    margin: 0 auto;
}

.sm-status-viz svg text {
    font-family: inherit;
    fill: var(--mud-palette-text-primary);
}

/* Node circles / branch cards: white on the grey stage with a hairline edge — no shadow (CI). */
.sm-status-node,
.sm-status-card {
    fill: var(--mud-palette-surface);
    stroke: var(--mud-palette-lines-default);
    stroke-width: 1;
}

/* Not-configured placeholder: dashed outline, no elevation — visibly "empty slot". */
.sm-status-card-none {
    fill: var(--mud-palette-background);
    filter: none;
    stroke: var(--mud-palette-lines-default);
    stroke-dasharray: 6 5;
}

.sm-status-lbl {
    font-size: 12px;
    letter-spacing: 3px;
    fill: var(--mud-palette-text-secondary);
    text-anchor: middle;
}

.sm-status-big {
    font-size: 16px;
    font-weight: 700;
    text-anchor: middle;
}

.sm-status-sub {
    font-size: 12px;
    fill: var(--mud-palette-text-secondary);
    text-anchor: middle;
}

.sm-status-cardtitle {
    font-size: 10.5px;
    letter-spacing: 1.5px;
    fill: var(--mud-palette-text-secondary);
}

.sm-status-l1 {
    font-size: 13px;
    font-weight: 600;
}

.sm-status-l1-muted {
    font-weight: 400;
    fill: var(--mud-palette-text-secondary);
}

.sm-status-l2 {
    font-size: 12px;
    fill: var(--mud-palette-text-secondary);
}

.sm-status-line {
    stroke: var(--mud-palette-lines-default);
    stroke-width: 3;
    fill: none;
    stroke-linecap: round;
}

/* A stopped flow keeps its rail but dashed — the "pipe" exists, nothing moves through it. */
.sm-status-line-off {
    stroke-dasharray: 2 7;
}

/* Fired when TimestampLastSeen advances: one expanding ring around the device node. */
.sm-status-pulse {
    animation: sm-status-pulse 1.1s ease-out forwards;
    transform-box: fill-box;
    transform-origin: center;
}

@keyframes sm-status-pulse {
    from {
        opacity: 0.75;
        transform: scale(1);
    }

    to {
        opacity: 0;
        transform: scale(1.32);
    }
}

.sm-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--sm-r-sm);
    padding: 6px 14px 6px 10px;
    font-size: 13px;
    font-weight: 600;
}

.sm-status-badge-dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    flex: none;
}

/* ---------- Zero-Touch start page (Pages/Overview) ---------- */

/* Status line: the headline sentence left, the server clock right. */
.sm-headline {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 20px;
}

.sm-headline-title {
    font-size: 30px;
    line-height: 1.15;
    letter-spacing: -.03em;
}

.sm-headline-clock {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--sm-font-mono);
    font-size: 11px;
    letter-spacing: .08em;
    color: var(--mud-palette-text-secondary);
    padding-bottom: 6px;
}

.sm-dot {
    width: 8px;
    height: 8px;
    border-radius: 9999px;
    flex: none;
}

/* Two columns from 1100px: inbox + health left, ledger + autopilot right. */
.sm-overview-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}

/* Two columns: see the container query on #main-content (UI review fixes, end of file). */

.sm-overview-main,
.sm-overview-side {
    display: flex;
    flex-direction: column;
    gap: 24px;
    min-width: 0;
}

.sm-card {
    padding: 20px 24px;
}

.sm-inbox {
    padding-bottom: 12px;
}

.sm-inbox-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 36px 16px 28px;
}

/* "Done" (ledger rows, the all-clear state): the CI's status green on its tint — lime is a
   dashboard object colour, not a status, and turns olive on dark. */
.sm-tint-lime {
    background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent);
    color: var(--mud-palette-success-darken);
}

/* One inbox entry: icon bubble · title/body/meta · actions. */
.sm-decision-card {
    display: flex;
    gap: 16px;
    padding: 18px 4px 18px 0;
    border-top: 1px solid var(--mud-palette-divider);
    animation: sm-fade-up 0.3s ease both;
}

.sm-decision-resolved {
    opacity: 0.8;
}

.sm-decision-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.sm-decision-badge.mud-chip {
    height: 20px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    margin: 0;
}

.sm-decision-proposal {
    display: flex;
    align-items: center;
    color: var(--mud-palette-primary);
    font-weight: 500;
}

.sm-decision-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.sm-decision-deadline {
    font-weight: 600;
    color: var(--mud-palette-warning-darken);
}

.sm-decision-why.mud-button-root {
    min-width: 0;
    padding: 0 6px;
    font-size: 12px;
    text-transform: none;
    height: 22px;
}

.sm-decision-whybox {
    margin-top: 6px;
    padding: 12px 14px;
    border-radius: var(--sm-r-sm);
    background: var(--sm-chip);
    font-size: 13px;
    line-height: 19px;
    color: var(--mud-palette-text-primary);
}

.sm-decision-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex: none;
}

@media (max-width: 700px) {
    .sm-decision-card {
        flex-wrap: wrap;
    }

    .sm-decision-actions {
        flex-direction: row;
        width: 100%;
        justify-content: flex-end;
    }
}

/* Ledger rows and total. */
.sm-ledger-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-top: 1px solid var(--mud-palette-divider);
}

.sm-ledger-value {
    color: var(--sm-blue);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.sm-ledger-total {
    margin-top: 8px;
    padding: 14px 16px 12px;
    border-radius: var(--sm-r-md);
    background: var(--sm-soft);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Segmented control (period switch, autopilot stages) — the CI Segment: a pill track on the soft
   surface (pills are allowed for time-range segments), the active option Brand Blue. */
.sm-seg {
    display: inline-flex;
    flex: none;
    background: var(--sm-soft);
    border-radius: 9999px;
    padding: 3px;
    gap: 2px;
}

.sm-seg-btn {
    height: 24px;
    padding: 0 10px;
    border: 0;
    border-radius: 9999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    line-height: 24px;
    cursor: pointer;
    white-space: nowrap;
}

.sm-seg-btn:hover:not(:disabled) {
    color: var(--mud-palette-text-primary);
}

.sm-seg-btn:disabled {
    cursor: default;
}

.sm-seg-active {
    background: var(--sm-blue);
    color: #FFFFFF;
}

.sm-seg-active:hover:not(:disabled) {
    color: #FFFFFF;
}

.sm-seg-disabled {
    color: var(--mud-palette-text-disabled);
    text-decoration: line-through;
}

/* Label and segmented control side by side while the label keeps ~160px; in the narrow side
   column the control wraps under the label instead of squeezing it into one-word lines (which
   split "Zählerwechsel" mid-word). */
.sm-autopilot-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px 12px;
    padding: 10px 0;
    border-top: 1px solid var(--mud-palette-divider);
}

.sm-autopilot-row > :first-child {
    flex: 1 1 160px;
    min-width: 0;
    hyphens: manual;
    overflow-wrap: break-word;
}

.sm-autopilot-row > .sm-seg {
    flex: none;
}

/* A decision type the product knows but nothing raises yet: visible as a map entry, muted so it
   does not read as a setting that is doing something. */
.sm-autopilot-pending .mud-typography {
    color: var(--mud-palette-text-secondary);
}

/* Health cards: value + inline SVG series. Two columns only when the main column itself is wide
   enough (container query) — at 1100px the side column leaves too little for two. */
.sm-overview-main {
    container-type: inline-size;
}

.sm-health-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
}

@container (min-width: 580px) {
    .sm-health-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.sm-health-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.sm-health-value {
    font-size: 30px;
    line-height: 36px;
    font-weight: 600;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}

.sm-spark {
    display: block;
    width: 100%;
    height: 56px;
}

.sm-spark-line {
    fill: none;
    stroke: var(--sm-blue);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.sm-spark-area {
    fill: color-mix(in srgb, var(--sm-blue) 12%, transparent);
    stroke: none;
}

.sm-delivery-bars {
    display: grid;
    gap: 3px;
    align-items: end;
    height: 56px;
    padding-top: 8px;
}

.sm-bar {
    border-radius: 3px;
    min-width: 2px;
}

.sm-bar-ok {
    height: 100%;
    background: var(--mud-palette-secondary);
}

.sm-bar-retry {
    height: 100%;
    background: var(--mud-palette-warning);
}

.sm-bar-late {
    height: 70%;
    background: var(--mud-palette-warning);
}

.sm-bar-fail {
    height: 45%;
    background: var(--mud-palette-error);
}

.sm-bar-none {
    height: 18%;
    background: var(--mud-palette-lines-default);
}

/* ---------- Shared building blocks (Shared/*.razor) ---------- */

/* PageHeader: back arrow · title + subtitle · actions. The actions wrap under the title on a
   narrow screen instead of squeezing it. */
.sm-page-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 16px;
    margin-bottom: 16px;
}

.sm-page-back {
    margin-left: -8px;
}

.sm-page-heading {
    flex: 1 1 320px;
    min-width: 0;
}

.sm-page-title {
    margin: 0;
}

.sm-page-subtitle {
    color: var(--mud-palette-text-secondary);
}

.sm-page-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

/* Blazor's FocusOnNavigate focuses the <h1> so screen readers announce the page; that focus is
   programmatic (tabindex=-1), so no visible ring on a heading nobody tabbed to. */
h1:focus,
h1:focus-visible {
    outline: none;
}

/* EmptyState: tinted icon bubble, title, explanation, actions. */
.sm-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    padding: 40px 16px 32px;
}

.sm-empty-dense {
    padding: 20px 12px 16px;
}

.sm-empty-icon {
    width: 52px;
    height: 52px;
    border-radius: var(--sm-r-md);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
    background: var(--sm-icbg);
    color: var(--sm-blue);
}

.sm-empty-icon .mud-icon-root {
    font-size: 28px;
}

.sm-empty-dense .sm-empty-icon {
    width: 40px;
    height: 40px;
}

.sm-empty-dense .sm-empty-icon .mud-icon-root {
    font-size: 20px;
}

.sm-empty-text {
    max-width: 460px;
    color: var(--mud-palette-text-secondary);
}

.sm-empty-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 8px;
}

/* Dense tables truncate cells with nowrap; an empty state inside one must wrap normally. */
.sm-empty {
    white-space: normal;
}

/* FilterPanel next to a list: <div class="sm-filter-layout"> <FilterPanel/> <div class="sm-filter-main"/> </div>. */
.sm-filter-layout {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.sm-filter-layout > .sm-filter-main {
    flex: 1;
    min-width: 0;
    overflow: hidden;
}

.sm-filter-panel,
.sm-filter-rail {
    position: sticky;
    top: calc(var(--mud-appbar-height) + 12px);
    flex: none;
}

.sm-filter-rail {
    padding: 4px;
}

.sm-filter-panel {
    width: 260px;
    padding: 12px;
    max-height: calc(100vh - var(--mud-appbar-height) - 24px);
    overflow-y: auto;
}

.sm-filter-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}

.sm-filter-title.mud-typography-h6 {
    font-size: 16px;
    margin: 0;
}

.sm-filter-count {
    font-size: 11px;
    font-weight: 600;
    line-height: 18px;
    padding: 0 7px;
    border-radius: var(--sm-r-badge);
    background: var(--sm-icbg);
    color: var(--sm-blue);
}

.sm-filter-more.mud-button-root {
    align-self: flex-start;
    margin-top: 4px;
}

.sm-filter-foot {
    display: flex;
    justify-content: flex-end;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-divider);
}

.sm-filter-panel .mud-typography-body1 {
    font-size: 13px;
}

/* Below 960px there is no room for a side panel: it stacks above the list at full width. */
@media (max-width: 959.98px) {
    .sm-filter-layout {
        flex-direction: column;
        align-items: stretch;
    }

    .sm-filter-panel,
    .sm-filter-rail {
        position: static;
        width: auto;
        max-height: none;
    }

    .sm-filter-rail {
        align-self: flex-start;
    }
}

/* ---------- Accessibility ---------- */

/* Skip link: the first thing a keyboard user tabs to, invisible until focused. */
.sm-skip-link {
    border: 0;
    cursor: pointer;
    font: inherit;
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: 2000;
    padding: 8px 16px;
    border-radius: var(--sm-r-sm);
    background: var(--mud-palette-surface);
    color: var(--sm-blue);
    font-weight: 600;
    box-shadow: var(--mud-elevation-4);
    transform: translateY(-200%);
}

.sm-skip-link:focus {
    transform: none;
}

#main-content:focus {
    outline: none;
}

/* Text only screen readers get (e.g. the state behind a coloured dot). */
.sm-visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Users who asked their OS for less motion get none: no fade-ups, pulses or sliding bars. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ---------- Phase 2 building blocks ---------- */

/* AppDialog header: icon bubble · title + subtitle · chips. */
.sm-dialog-head {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}

.sm-dialog-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--sm-r-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.sm-dialog-heading {
    flex: 1;
    min-width: 0;
}

.sm-dialog-title.mud-typography {
    margin: 0;
    color: var(--mud-palette-text-primary);
    overflow-wrap: anywhere;
}

.sm-dialog-subtitle {
    display: block;
}

.sm-dialog-extras {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    flex: none;
}

/* No actions passed: no empty bar at the bottom. */
.sm-app-dialog .mud-dialog-actions:empty {
    display: none;
}

/* On a phone the header chips go under the title instead of squeezing it. */
@media (max-width: 599.98px) {
    .sm-dialog-head {
        flex-wrap: wrap;
    }

    .sm-dialog-extras {
        flex-basis: 100%;
    }
}

/* StatusChip: soft tinted pill, icon + text. */
.sm-status {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    max-width: 100%;
    height: 24px;
    padding: 0 9px 0 7px;
    border-radius: var(--sm-r-badge);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
    --sm-status-color: var(--mud-palette-text-secondary);
    color: var(--sm-status-color);
    background: color-mix(in srgb, var(--sm-status-color) 13%, transparent);
}

.sm-status-dense {
    height: 20px;
    font-size: 11px;
    padding: 0 8px 0 6px;
}

.sm-status-text {
    overflow: hidden;
    text-overflow: ellipsis;
}

.sm-status .sm-status-icon.mud-icon-root {
    font-size: 15px;
    width: 15px;
    height: 15px;
}

.sm-status-dense .sm-status-icon.mud-icon-root {
    font-size: 13px;
    width: 13px;
    height: 13px;
}

.sm-status-success {
    --sm-status-color: var(--mud-palette-success-darken);
}

.sm-status-warning {
    /* Orange alone is ~3:1 on white; mixing toward the text colour darkens it in light mode and
       lightens it in dark mode, so the 11px label stays readable in both. */
    --sm-status-color: color-mix(in srgb, var(--mud-palette-warning-darken) 65%, var(--mud-palette-text-primary));
}

.sm-status-error {
    --sm-status-color: var(--mud-palette-error);
}

.sm-status-info {
    --sm-status-color: var(--mud-palette-info-darken);
}

.sm-status-primary {
    --sm-status-color: var(--sm-blue);
}

/* ErrorState: the empty-state layout with an error tint. */
.sm-error-state .sm-empty-icon {
    background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
}

/* ReadOnlyNotice: one quiet line, not an alert. */
.sm-readonly-notice {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    padding: 8px 14px;
    border-radius: var(--sm-r-sm);
    width: fit-content;
    max-width: 100%;
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
    background: var(--sm-chip);
}

/* ---------- Chart tokens (validated with the dataviz palette checker) ---------- */

/* Two series that read apart in light and dark and for colour-vision deficiencies: consumption
   (Bezug) in brand blue, feed-in (Einspeisung) in brand teal. Text never wears these colours —
   labels and values stay in the text tokens; the marks carry the identity. */
:root {
    --sm-chart-import: #2563EB;
    --sm-chart-export: #1BA186;
    --sm-chart-grid: rgba(21, 23, 28, 0.08);
}

:root[data-theme="dark"] {
    --sm-chart-import: #2563EB;
    --sm-chart-export: #1EC8A5;
    --sm-chart-grid: rgba(255, 255, 255, 0.08);
}

/* FilterPanel on a phone: a "Filter" button above the list, the panel as a sheet from the bottom. */
.sm-filter-foot:empty {
    display: none;
}

.sm-filter-sheet-toggle.mud-button-root {
    align-self: flex-start;
}

.sm-filter-sheet-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1300;
    background: rgba(21, 23, 28, 0.40);
    animation: sm-fade-in 0.2s ease both;
}

.sm-filter-panel.sm-filter-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    z-index: 1301;
    width: auto;
    max-height: 80vh;
    overflow-y: auto;
    padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
    border-radius: var(--sm-r-xl) var(--sm-r-xl) 0 0;
    animation: sm-sheet-up .46s var(--sm-ease) both;
}

.sm-filter-sheet .sm-filter-foot {
    position: sticky;
    bottom: -16px;
    margin: 12px -16px -16px;
    padding: 12px 16px;
    gap: 8px;
    background: var(--mud-palette-surface);
}

@keyframes sm-sheet-up {
    from {
        transform: translateY(100%);
    }

    to {
        transform: none;
    }
}

@keyframes sm-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* Command palette: the keyboard-selected hit. */
.sm-search-dialog .mud-list-item.sm-search-active {
    background: var(--sm-soft);
    border-radius: var(--sm-r-nav);
}

/* ---------- Settings pages (TenantSettings, VeeSettings) ---------- */

/* Sections as cards in two columns from 1280px, one below: the page uses the full width like the
   list pages, while each card keeps a readable line length. Full-width rows (hints, the save bar)
   take .sm-settings-span. */
.sm-settings-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

@media (min-width: 1280px) {
    .sm-settings-layout {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.sm-settings-span {
    grid-column: 1 / -1;
}

.sm-settings-col {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
}

.sm-settings-card {
    padding: 20px 24px;
}

.sm-settings-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}

.sm-settings-card-head .mud-typography-h6 {
    margin: 0;
}

/* The save bar stays at the bottom while the sections scroll: a full-width R16 bar on its own
   surface, so it covers a clean strip instead of floating over half a sentence; the layout keeps
   room below the last card so nothing ends up permanently underneath it. */
.sm-settings-layout {
    padding-bottom: 8px;
}

.sm-settings-actions {
    position: sticky;
    bottom: 12px;
    z-index: 2;
    justify-self: stretch;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    padding: 8px 8px 8px 16px;
    border-radius: var(--sm-r-lg);
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--sm-card2);
    box-shadow: var(--sm-menu-shadow);
}

/* A row of numeric settings: as many equal columns as fit, so long labels are never clipped. */
.sm-settings-fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px 16px;
}

/* ---------- UI review fixes (2026-10-15) ---------- */

/* Tabs are always INSIDE one card: the whole MudTabs container (tab bar + panels) is the card, the
   bar sits on its top edge over a hairline. Before, some pages framed only the tab bar and left the
   panel content on the page grey, others framed the content separately. */
.mud-main-content .mud-tabs.mud-tabs-rounded {
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--sm-r-lg);
    box-shadow: var(--sm-card-shadow);
}

.mud-main-content .mud-tabs.mud-tabs-rounded > .mud-tabs-tabbar {
    background-color: transparent;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--sm-r-lg) var(--sm-r-lg) 0 0;
}

/* A tab card inside a card (device page) is not framed twice. */
.mud-main-content .mud-paper .mud-tabs.mud-tabs-rounded {
    border: 0;
    box-shadow: none;
    background-color: transparent;
}

/* Cards and tables inside a tab card are part of it: no second frame, no own margin. */
.mud-main-content .mud-tabs .mud-paper:not(.mud-paper-outlined):not(.mud-popover) {
    border: 0;
    box-shadow: none;
}

.mud-main-content .mud-tabs .mud-table.ma-2 {
    margin: 0 !important;
}

/* Successive cards in one tab panel are separated by a hairline instead of a gap. */
.mud-main-content .mud-tabs .mud-tabs-panels > .mud-tab-panel > .mud-paper + .mud-paper {
    border-top: 1px solid var(--mud-palette-lines-default);
    border-radius: 0;
}

/* Floating layers in dark mode keep the CI's blue glow (cards no longer do). */
:root[data-theme="dark"] .mud-dialog {
    box-shadow: var(--sm-menu-shadow), var(--sm-glow);
}

/* Alerts: body text is ink (CI: no blue running text), only the icon carries the tone. */
.mud-alert.mud-alert-text-info,
.mud-alert.mud-alert-text-success,
.mud-alert.mud-alert-text-warning,
.mud-alert.mud-alert-text-normal {
    color: var(--mud-palette-text-primary);
}

.mud-alert.mud-alert-text-info .mud-alert-icon {
    color: var(--sm-blue);
}

.mud-alert.mud-alert-text-success .mud-alert-icon {
    color: var(--mud-palette-success);
}

.mud-alert.mud-alert-text-warning .mud-alert-icon {
    color: var(--mud-palette-warning-darken);
}

.mud-alert {
    border-radius: var(--sm-r-md);
}

/* An empty table shows its empty state, not a pager reading "0–0 of 0". */
.mud-table:has(.mud-table-empty-row) .mud-table-pagination,
.mud-table:has(.sm-empty) .mud-table-pagination {
    display: none;
}

/* Overflow-menu entries with a one-line explanation under the label (the tooltip text that used to
   hang on a header button). */
.sm-menu-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-width: 320px;
    white-space: normal;
}

.sm-menu-item-hint {
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--mud-palette-text-secondary);
}

.sm-menu-item-danger,
.sm-menu-item-danger > span:first-child {
    color: var(--mud-palette-error);
}

/* Page title that is an identifier (metering-point ID in groups of four). */
.sm-page-title.sm-page-title-mono {
    font-family: var(--sm-font-mono);
    font-size: 22px;
    font-weight: 500;
    letter-spacing: 0;
    word-spacing: -.15em;
}

/* Identifier cells (metering-point ID column). */
.sm-id-cell {
    font-weight: 500;
    /* A 33-character CH-ID breaks in a phone's stacked table cards instead of pushing every value
       of the card off-screen; grid cells that do not wrap keep their ellipsis. */
    overflow-wrap: anywhere;
}

/* Status flow: the SVG scales with its card; where the card is narrow (device page at ~1100px) the
   labels shrank to ~8px. A container query enlarges the text in place. */
.sm-status-viz {
    container-type: inline-size;
}

@container (max-width: 900px) {
    .sm-status-viz svg text {
        scale: 1.15;
        transform-box: fill-box;
        transform-origin: center;
    }
}

/* Column heads wrap instead of truncating ("Zuletzt gesehe…"); cells keep their one-line rule. */
@media (min-width: 600px) {
    .sm-dense-table th.mud-table-cell {
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        vertical-align: bottom;
    }
}

/* The Overview's two columns follow the room the content area really has (container query on the
   main content) instead of the viewport — next to the open side bar, 1100px is not enough. */
#main-content {
    container-type: inline-size;
    container-name: main;
}

@container main (min-width: 1040px) {
    .sm-overview-grid {
        grid-template-columns: minmax(0, 1fr) 380px;
    }
}

/* Records page: one banner for undecryptable rows instead of a red badge in every row. */
.sm-records-banner {
    margin-bottom: 12px;
}

.sm-inbox-empty-icon {
    width: 52px;
    height: 52px;
}

/* Undecryptable record: muted lock + text, the banner above explains it once. */
.sm-records-locked {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12.5px;
}

/* Wide dense tables scroll sideways inside their card instead of clipping the last column. */
.sm-dense-table .mud-table-container {
    overflow-x: auto;
}

/* Count badges in one row under a page title (Realtime sharing). */
.sm-page-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: -4px 0 16px;
}

/* A list toolbar that wraps: the search box takes the free width, each select keeps its own. */
.sm-toolbar-search {
    flex: 1 1 260px;
    min-width: 0;
}

.sm-toolbar-select {
    flex: 0 0 180px;
}

/* The consent wizard's selection: chips that wrap, scrolling once a tag brings a few hundred. */
/* The consent list: the bulk bar over the selected rows, a bundle's entries under its row. */
.sm-bulk-bar { padding: 8px 12px; border-radius: 8px; background: var(--mud-palette-primary-hover); }
.sm-consent-entries { padding: 4px 8px 12px 48px; }
.sm-expand { margin-top: -4px; }

/* The offer's one-time code and QR (consent wizard). */
.sm-offer-qr { width: 140px; flex-shrink: 0; }
.sm-offer-code { font-size: 1.05rem; letter-spacing: .04em; overflow-wrap: anywhere; }

.sm-wizard-selection {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    max-height: 220px;
    overflow-y: auto;
}

/* Work-queue tiles (AttentionTile): a row of toggle buttons that filter the list below. Two
   columns on a phone, as many as fit on a desktop. */
.sm-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 8px;
    margin: -4px 0 16px;
}

.sm-tile {
    --sm-tile-color: var(--mud-palette-text-secondary);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
    padding: 10px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--sm-r-md);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s var(--sm-ease), background-color .15s var(--sm-ease);
}

.sm-tile:hover {
    border-color: var(--sm-tile-color);
}

.sm-tile:focus-visible {
    outline: none;
    box-shadow: var(--sm-focus-ring);
}

.sm-tile[aria-pressed="true"] {
    border-color: var(--sm-tile-color);
    background: color-mix(in srgb, var(--sm-tile-color) 9%, var(--mud-palette-surface));
}

.sm-tile-head {
    display: flex;
    align-items: center;
    gap: 6px;
}

.sm-tile .sm-tile-icon.mud-icon-root {
    font-size: 18px;
    width: 18px;
    height: 18px;
    color: var(--sm-tile-color);
}

.sm-tile-count {
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.sm-tile-label {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    overflow-wrap: anywhere;
}

.sm-tile-success {
    --sm-tile-color: var(--mud-palette-success-darken);
}

.sm-tile-warning {
    --sm-tile-color: color-mix(in srgb, var(--mud-palette-warning-darken) 65%, var(--mud-palette-text-primary));
}

.sm-tile-error {
    --sm-tile-color: var(--mud-palette-error);
}

.sm-tile-info {
    --sm-tile-color: var(--mud-palette-info-darken);
}

/* A switch in a grid of labelled fields starts at the fields' top edge (labels sit above them). */
@media (min-width: 600px) {
    .sm-switch-cell {
        padding-top: 34px !important;
    }
}

/* Narrow window (600–959px): the expanded menu floats over the content next to the icon rail. */
.sm-drawer.sm-drawer-floating {
    box-shadow: var(--sm-menu-shadow);
}

/* ---------- "ZERO" pulse (app bar) ----------
   The whole label pulses in Brand Blue: a glow swells and fades every 2.8 s and never fully goes
   out, so the word keeps "breathing". Only colour and glow move (no scaling, CI); the global
   prefers-reduced-motion rule stops it on the resting frame. */
.sm-zero-pulse {
    animation: sm-zero-pulse 2.8s ease-in-out infinite;
}

@keyframes sm-zero-pulse {
    0%, 100% {
        color: var(--sm-blue);
        text-shadow: 0 0 3px rgba(37, 99, 235, .35);
    }

    50% {
        color: #5B8CFF;
        text-shadow: 0 0 4px rgba(37, 99, 235, 1), 0 0 12px rgba(37, 99, 235, .9), 0 0 24px rgba(37, 99, 235, .6);
    }
}

:root[data-theme="dark"] .sm-zero-pulse {
    animation-name: sm-zero-pulse-dark;
}

@keyframes sm-zero-pulse-dark {
    0%, 100% {
        color: var(--sm-blue);
        text-shadow: 0 0 4px rgba(37, 99, 235, .5);
    }

    50% {
        color: #FFFFFF;
        text-shadow: 0 0 4px rgba(37, 99, 235, 1), 0 0 14px rgba(37, 99, 235, 1), 0 0 30px rgba(37, 99, 235, .8);
    }
}
