/* ==========================================================================
   TagNet Application Styles
   ========================================================================== */

/* Access scope chip (#948). The one place teal is defined: ScopeChip uses it for every
   scope that is not the shared system scope (that one stays MudBlazor Info blue). Teal-700,
   so white text clears 4.5:1. */
:root {
    --tagnet-scope: #0F766E;
    /* ATR7000 zone hues by zone number, so a zone keeps one colour across features: the Tag
       trail (js/tag-trail.js picks the set by surface luminance) and the zone layout drawing
       (ZebraAtrZoneVisual.razor, light set). The first four pairs pass the
       colour-vision-deficiency separation checks against both surfaces. */
    --tagnet-zone-1: #D97706;
    --tagnet-zone-2: #4F46E5;
    --tagnet-zone-3: #0891B2;
    --tagnet-zone-4: #9333EA;
    --tagnet-zone-5: #BE185D;
    --tagnet-zone-6: #047857;
    --tagnet-zone-1-dark: #EA580C;
    --tagnet-zone-2-dark: #6366F1;
    --tagnet-zone-3-dark: #0891B2;
    --tagnet-zone-4-dark: #A855F7;
    --tagnet-zone-5-dark: #EC4899;
    --tagnet-zone-6-dark: #10B981;
    /* Edit-page section rail: the rail's two widths and the row gap beside it
       (gap-5 on the edit content's flex row). The sticky action bar derives its
       lane from these, so a rail change moves the bar with it. */
    --tagnet-rail-width: 220px;
    --tagnet-rail-collapsed-width: 48px;
    --tagnet-rail-gap: 20px;
}

.mud-chip.mud-chip-filled.tagnet-scope-chip {
    background-color: var(--tagnet-scope);
    color: #fff;
}

.mud-chip.mud-chip-filled.tagnet-scope-chip .mud-chip-icon {
    color: inherit;
}

/* Clickable DataGrid Rows
   Apply this class to MudDataGrid via RowClass="clickable-row" when rows are clickable
   -------------------------------------------------------------------------- */
.clickable-row {
    cursor: pointer;
}

/* Arrangement Select
   The FilterBar's group-by control (Devices, Inventory). A default MudSelect
   reads at 1rem with a medium icon beside a small results chip and small icon
   buttons; this brings it down to the bar's own scale (body-2 text, small icon)
   without touching the row height.
   -------------------------------------------------------------------------- */
.arrangement-select .mud-input.mud-typography-subtitle1,
.arrangement-select input.mud-input-slot {
    font-size: 0.875rem;
}

.arrangement-select .mud-icon-root.mud-icon-size-medium {
    font-size: 1.25rem;
}

/* Setup Progress Bar
   A footer strip at the end of the main content while the installation still has
   core setup steps open. The main content is a flex column at least a viewport tall,
   the page body takes the slack, and the bar sticks to the bottom edge: on a short
   page it sits below the content, on a long one it stays in view while scrolling,
   and at the end of the page it is in the flow, so it never covers a control.
   -------------------------------------------------------------------------- */
.tagnet-main {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.tagnet-main-body {
    flex: 1 1 auto;
}

/* A nav entry's "something is waiting" dot, pushed to the right edge of its row.
   The colour comes from a MudBlazor theme class (mud-theme-warning / mud-theme-error). */
.nav-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-left: auto;
    flex-shrink: 0;
}

/* Text for screen readers only: in the accessibility tree, not on screen
   (the words behind a nav dot badge, for example). */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.setup-progress-bar {
    position: sticky;
    bottom: 0;
    z-index: 10;
    margin: 0 -16px;
    border-radius: 0;
}

/* Import Preview Row Status
   Apply via RowClassFunc on the Quick Import preview grid
   -------------------------------------------------------------------------- */
.import-row-error {
    background-color: rgba(244, 67, 54, 0.08) !important;
}

.import-row-new {
    background-color: rgba(76, 175, 80, 0.06) !important;
}

/* Highlight row for items without a location */
.not-located-row {
    border-left: 3px solid var(--mud-palette-warning);
}

/* Inactive device row — dim all cells except the actions menu so it stays clickable.
   Cell-level opacity (instead of row-level) lets the actions column opt out;
   row-level opacity would cascade into every descendant. */
.device-inactive-row td {
    opacity: 0.55;
}

.device-inactive-row td.device-row-actions {
    opacity: 1;
}

/* Disabled workflow row: muted the same way, keeping its place in the run order (#939). */
.workflow-disabled-row td {
    opacity: 0.55;
}

.workflow-disabled-row td.workflow-row-actions {
    opacity: 1;
}

/* Colored map pins — remove default divIcon background/border */
.tagnet-map-pin {
    background: none !important;
    border: none !important;
}

/* ==========================================================================
   Entity page primitives (FormSection, SectionAnchorRail, detail-page grids)
   ========================================================================== */

/* Rounded icon swatch used in FormSection headers and stat cards */
.tagnet-icon-swatch {
    width: 32px;
    height: 32px;
    border-radius: 6px;
    background-color: rgba(99, 102, 241, 0.10);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Anchor target offset so scrolled-to sections clear the fixed app bar */
.tagnet-form-section {
    scroll-margin-top: calc(var(--mud-appbar-height, 64px) + 16px);
}

/* Live icon+color preview beside the pickers (IconColorPickerField): sized and
   bordered like a dense outlined input so it sits level with the fields. The
   top margin matches the space MudBlazor reserves above outlined inputs for
   the floating label. */
.tagnet-icon-preview {
    width: 40px;
    height: 40px;
    margin-top: 8px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Sticky section-anchor rail on edit/create pages. Hidden below the md
   breakpoint (960px, matching MudBlazor); vertical flex column above it. */
.tagnet-section-rail {
    display: none;
    position: sticky;
    /* Sticky offset clears the fixed app bar so the rail header stays visible */
    top: calc(var(--mud-appbar-height, 64px) + 16px);
    width: var(--tagnet-rail-width);
    flex-shrink: 0;
    flex-direction: column;
    align-self: flex-start;
}

@media (min-width: 960px) {
    .tagnet-section-rail {
        display: flex;
    }
}

.tagnet-section-rail-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-radius: 6px;
    border-left: 2px solid transparent;
    cursor: pointer;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
}

.tagnet-section-rail-item:hover {
    background-color: var(--mud-palette-action-default-hover);
}

.tagnet-section-rail-item:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.tagnet-section-rail-item.active {
    background-color: rgba(99, 102, 241, 0.08);
    border-left-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
    font-weight: 600;
}

.tagnet-section-rail-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tagnet-section-rail-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 4px;
}

.tagnet-section-rail-icon {
    position: relative;
    display: inline-flex;
}

/* Icon-only rail: status marker overlays the icon's top-right corner */
.tagnet-section-rail.collapsed {
    width: var(--tagnet-rail-collapsed-width);
}

.tagnet-section-rail.collapsed .tagnet-section-rail-header {
    justify-content: center;
}

.tagnet-section-rail.collapsed .tagnet-section-rail-item {
    justify-content: center;
    padding: 8px 0;
}

.tagnet-section-rail-badge {
    position: absolute;
    top: -5px;
    right: -7px;
    display: inline-flex;
    line-height: 0;
}

.tagnet-section-rail-badge .mud-icon-root {
    background-color: var(--mud-palette-background);
    border-radius: 50%;
    font-size: 0.75rem !important;
}

.tagnet-status-dot {
    width: 6px;
    height: 6px;
    border-radius: 3px;
    background-color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}

/* Sticky action bar on edit pages: in the same lane as the form sections
   (it starts where they start, to the right of the rail) and 10px narrower
   on each side, so when it floats over a section its edges land between the
   section border and the 20px input inset rather than on top of either. The
   bar renders outside the rail + column row, so it reads the rail's state
   through :has(). The one element on the page that truly floats, so it
   carries a real shadow; floats above the viewport bottom until its natural
   position scrolls into view. */
.tagnet-footer-bar {
    position: sticky;
    bottom: 16px;
    z-index: 10;
    margin-left: 10px;
    margin-right: 10px;
    border-radius: 8px;
}

@media (min-width: 960px) {
    /* rail width + the row gap + the 10px inset */
    .mud-main-content:has(.tagnet-section-rail:not(.collapsed)) .tagnet-footer-bar {
        margin-left: calc(var(--tagnet-rail-width) + var(--tagnet-rail-gap) + 10px);
    }

    .mud-main-content:has(.tagnet-section-rail.collapsed) .tagnet-footer-bar {
        margin-left: calc(var(--tagnet-rail-collapsed-width) + var(--tagnet-rail-gap) + 10px);
    }
}

/* Form column on edit/create pages: fills the row beside the rail. A width
   cap was tried and read as three different widths once the nav or the rail
   collapsed, so the sections match the header's width. */
.tagnet-form-column {
    flex: 1 1 auto;
    min-width: 0;
}

/* Read signature build form (#1195): the form sections, and the self-check beside them,
   sticky below the app bar. Below 960px the panel follows the sections. */
.tagnet-signature-build {
    display: flex;
    gap: 20px;
    align-items: flex-start;
}

.tagnet-signature-build-panel {
    flex: 0 0 320px;
    position: sticky;
    top: calc(var(--mud-appbar-height, 64px) + 16px);
}

@media (max-width: 959.98px) {
    .tagnet-signature-build {
        flex-direction: column;
        align-items: stretch;
    }

    .tagnet-signature-build-panel {
        flex-basis: auto;
        position: static;
    }
}

/* Read signature detail (#1196): one range chart per checked metric. The track spans
   mean ± 4σ; the band is the accepted range; dots are the capture's tags, diamonds this
   week's mismatches. Positions are percentages computed in SignatureBandChart. */
.tagnet-band-track {
    position: relative;
    height: 56px;
    border-radius: 6px;
    background: var(--mud-palette-background-gray);
    border: 1px solid var(--mud-palette-lines-default);
    overflow: hidden;
}

.tagnet-band-accepted {
    position: absolute;
    top: 0;
    bottom: 0;
    background: rgba(var(--mud-palette-success-rgb), 0.18);
    border-left: 1px solid rgba(var(--mud-palette-success-rgb), 0.6);
    border-right: 1px solid rgba(var(--mud-palette-success-rgb), 0.6);
}

.tagnet-band-mean {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 0;
    border-left: 2px dashed var(--mud-palette-success);
}

.tagnet-band-dot {
    position: absolute;
    bottom: 10px;
    width: 7px;
    height: 7px;
    margin-left: -3.5px;
    border-radius: 50%;
    background: var(--mud-palette-text-secondary);
    opacity: 0.5;
}

.tagnet-band-mismatch {
    position: absolute;
    top: 10px;
    width: 11px;
    height: 11px;
    margin-left: -5.5px;
    border-radius: 2px;
    background: var(--mud-palette-error);
    transform: rotate(45deg);
}

.tagnet-band-axis {
    position: relative;
    display: flex;
    justify-content: space-between;
    margin-top: 4px;
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* The mean's label sits under the mean line, which a bounded track moves off centre. */
.tagnet-band-axis-mean {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
}

.tagnet-band-row {
    display: grid;
    grid-template-columns: minmax(180px, 260px) minmax(0, 1fr) 110px;
    gap: 20px;
    align-items: center;
}

@media (max-width: 959.98px) {
    .tagnet-band-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 8px;
    }
}

/* Amber unsaved-changes indicator in the edit footer */
.tagnet-dirty-dot {
    width: 8px;
    height: 8px;
    border-radius: 4px;
    background-color: var(--mud-palette-warning);
    flex-shrink: 0;
}

/* Detail page: auto-fit field grid inside DetailSection cards (SectionField items) */
.tagnet-field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px 24px;
}

/* Full-width field (e.g. Description) inside a field grid */
.tagnet-field-span {
    grid-column: 1 / -1;
}

/* Nav drawer: tinted a shade darker than the canvas (theme DrawerBackground)
   with a hairline edge instead of a shadow, so it reads as chrome. */
.tagnet-nav-drawer {
    border-right: 1px solid var(--mud-palette-divider);
}

/* Outlined alerts are surfaces (ui-design-system.md, The surface rule): a white
   fill so they read on the tinted canvas. Outline, text and icon stay MudBlazor's. */
.mud-alert.mud-alert-outlined-info,
.mud-alert.mud-alert-outlined-success,
.mud-alert.mud-alert-outlined-warning,
.mud-alert.mud-alert-outlined-error,
.mud-alert.mud-alert-outlined-normal {
    background-color: var(--mud-palette-surface);
}

/* Hub tab strip docked to the bottom edge of a PageHeader card: the header
   and its tabs become one surface instead of two stacked cards. The negative
   margins cancel the header's pa-4. */
.tagnet-header-tabs {
    margin: 12px -16px -16px;
    border-top: 1px solid var(--mud-palette-lines-default);
    border-radius: 0 0 var(--mud-default-borderradius) var(--mud-default-borderradius);
    overflow: hidden;
}

/* Selected hub tab: a light primary wash under the text + slider, the same
   tint the section rail uses for its active item, so the current view is
   obvious at a glance and not only by the 2px slider. */
.tagnet-hub-tab-active {
    background-color: rgba(99, 102, 241, 0.08);
}

/* List surface: filter bar + grid share one card; the bar's bottom rule
   separates them instead of a 16px gap of canvas. */
/* Retention results table (job run detail): each policy's group of rows opens
   with a card-edge rule, a step darker than the row rules inside the group. */
.tagnet-retention-group:not(:first-child) td {
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* Rows that did work stand out; the zero rows (most of them on a quiet night) recede.
   Scoped under .mud-simple-table to outrank MudBlazor's own cell alignment and colour. */
.mud-simple-table td.tagnet-retention-count {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.mud-simple-table td.tagnet-retention-count.zero {
    font-weight: 400;
    color: var(--mud-palette-text-disabled);
}

.tagnet-attached-filter {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius) var(--mud-default-borderradius) 0 0;
}

/* Selectable option card (the API key role picker): flat and outlined at rest,
   the hover tint on hover, a primary edge and the hub tab's primary wash when
   chosen. Never a lift: cards on the canvas don't float. */
.tagnet-choice-card {
    position: relative; /* anchors the visually hidden radio inside the card */
    cursor: pointer;
    border: 2px solid var(--mud-palette-lines-default);
    transition: border-color 0.2s ease, background-color 0.2s ease;
}

.tagnet-choice-card:hover {
    background-color: var(--mud-palette-action-default-hover);
}

.tagnet-choice-card-selected,
.tagnet-choice-card-selected:hover {
    border-color: var(--mud-palette-primary);
    background-color: rgba(99, 102, 241, 0.08);
}

.tagnet-choice-card:has(input:focus-visible) {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.tagnet-field-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 2px;
}

/* Group heading inside a section card (the reader configuration's Antennas,
   Tag ID filtering, ...): one step under the section title, in text-primary
   and sentence case. Small grey caps were the hardest text on the device
   pages to read. */
.tagnet-group-title {
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.5;
    color: var(--mud-palette-text-primary);
    margin: 2px 0 6px;
}

/* A button beside a dense outlined input (blazor-page-patterns.md, Buttons
   beside an input): the input's 40px box and 8px top margin, top-aligned in a
   MudStack Row AlignItems.Start so a helper or error line under the field does
   not move it. */
.tagnet-input-action {
    height: 40px;
    margin-top: 8px;
    white-space: nowrap;
    flex-shrink: 0;
}

.tagnet-field-value {
    font-size: 0.875rem; /* matches Typo.body2 */
    color: var(--mud-palette-text-primary);
    overflow-wrap: break-word;
}

.tagnet-field-value.empty {
    color: var(--mud-palette-text-disabled);
}

/* ATR7000 Zone layout (#1278): one field per row in a narrow column beside the
   live drawing of the zone map, which takes the rest of the card; the drawing
   wraps under the fields when the card is narrow. The drawing is server-rendered
   SVG (ZebraAtrZoneVisual) that scales with its column. */
.tagnet-zone-layout {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 24px;
    align-items: flex-start;
}

.tagnet-zone-layout-fields {
    flex: 0 1 320px;
    min-width: 0;
}

.tagnet-zone-layout-visual {
    flex: 1 1 440px;
    min-width: 0;
    max-width: 640px;
}

.tagnet-zone-visual {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.tagnet-zone-visual svg {
    display: block;
    width: 100%;
    height: auto;
}

.tagnet-zone-visual svg text {
    font-family: inherit;
}

/* Hero stat cards (HeroStatCard.razor) */

/* Drill-through wrapper: the whole card is a link to the collection it summarizes */
.tagnet-stat-card-link {
    display: block;
    height: 100%;
    text-decoration: none;
    color: inherit;
}

/* A card that opens something here rather than going elsewhere: a button stripped to the card */
.tagnet-stat-card-button {
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    text-align: inherit;
    cursor: pointer;
}

/* Reader Analytics tab (ReaderDeviceOverview.razor). The plot stretches; the axes are HTML so their
   text does not stretch with it. 44px is the y axis, which the legend and the By antenna list line up under. */
.tagnet-analytics-chart {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr);
    grid-template-rows: 168px 24px;
    margin-top: 8px;
}

.tagnet-analytics-plot {
    display: block;
    width: 100%;
    height: 100%;
}

.tagnet-analytics-y,
.tagnet-analytics-x {
    position: relative;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.tagnet-analytics-y span {
    position: absolute;
    right: 8px;
    transform: translateY(-50%);
    white-space: nowrap;
}

.tagnet-analytics-x {
    grid-column: 2;
}

.tagnet-analytics-x span {
    position: absolute;
    top: 6px;
    transform: translateX(-50%);
    white-space: nowrap;
}

.tagnet-analytics-indent {
    margin-left: 44px;
}

.tagnet-analytics-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    align-items: center;
    margin: 4px 0 4px 44px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.tagnet-analytics-legend > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.tagnet-analytics-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 2px;
}

.tagnet-analytics-swatch-previous {
    display: inline-block;
    width: 18px;
    border-top: 2px dashed var(--mud-palette-text-secondary);
    opacity: 0.75;
}

/* The Online tile opens its check's popup, anchored in the tile's corner */
.tagnet-analytics-popup-host {
    position: relative;
    height: 100%;
}

.tagnet-analytics-popup-anchor {
    position: absolute;
    right: 12px;
    bottom: 12px;
}

/* By antenna: each port's share of the reads chart above, as rows of bars rather than more
   charts, set off by a rule so it reads as a breakdown. A port with no reads keeps its row. */
.tagnet-antenna-shares {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* One grid for every row, so the name column fits the longest name and the bars still line up */
.tagnet-antenna-share-rows {
    display: grid;
    grid-template-columns: minmax(88px, max-content) minmax(0, 1fr) minmax(96px, 150px);
    column-gap: 12px;
}

.tagnet-antenna-share {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    gap: 12px;
    align-items: center;
    min-height: 28px;
    font-size: 0.8125rem;
}

.tagnet-antenna-share-track {
    height: 8px;
    border-radius: 4px;
    background: var(--mud-palette-background-gray);
    overflow: hidden;
}

.tagnet-antenna-share-fill {
    display: block;
    height: 100%;
    min-width: 2px;
    border-radius: 4px;
}

.tagnet-antenna-share-name,
.tagnet-antenna-share-figure {
    white-space: nowrap;
}

/* A configured port name can be long; past 200px it is cut off, and the row's hover text has it whole */
.tagnet-antenna-share-name {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* On a phone the bar takes its own line under the name and figure */
@media (max-width: 599.98px) {
    .tagnet-antenna-share-rows {
        grid-template-columns: minmax(0, 1fr);
    }

    .tagnet-antenna-share {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "name figure" "track track";
        gap: 2px 12px;
        padding: 4px 0;
    }

    .tagnet-antenna-share-name { grid-area: name; }
    .tagnet-antenna-share-track { grid-area: track; }
    .tagnet-antenna-share-figure { grid-area: figure; }
}

/* Notification body (NotificationDetailContent.razor): rendered markdown,
   including the fenced code blocks that Text/JSON/XML workflow templates
   arrive wrapped in */

.notification-body pre {
    background-color: var(--mud-palette-background-grey);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    padding: 12px 16px;
    overflow-x: auto;
    font-size: 0.85rem;
    line-height: 1.5;
}

.notification-body p code {
    background-color: var(--mud-palette-background-grey);
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.85em;
}

.notification-body h1,
.notification-body h2,
.notification-body h3 {
    margin: 0.75em 0 0.35em;
    line-height: 1.3;
}

.notification-body h1 { font-size: 1.25rem; }
.notification-body h2 { font-size: 1.1rem; }
.notification-body h3 { font-size: 1rem; }

.notification-body p {
    margin: 0.5em 0;
}

.notification-body ul,
.notification-body ol {
    margin: 0.5em 0;
    padding-left: 1.5em;
}

.notification-body hr {
    border: none;
    border-top: 1px solid var(--mud-palette-lines-default);
    margin: 0.75em 0;
}

.notification-body table {
    border-collapse: collapse;
    margin: 0.5em 0;
}

.notification-body th,
.notification-body td {
    border: 1px solid var(--mud-palette-lines-default);
    padding: 4px 10px;
    text-align: left;
}

.notification-body th {
    background-color: var(--mud-palette-background-grey);
}

/* Type pickers with rich item templates (TransactionTypeSelect): MudSelect
   re-renders the selected item's template inside the input slot, whose height
   is tuned for text — a chip's height + margins push the row off-center. Hide
   chips in the selected-value presenter only; the dropdown list renders in the
   body-level popover and keeps them. */
.tagnet-type-select .mud-input .mud-chip {
    display: none;
}

.tagnet-stat-card-link:hover .tagnet-stat-card {
    background-color: var(--mud-palette-action-default-hover);
}

/* height 100% keeps every card in a hero row the same height regardless of
   whether it renders a delta/sub caption line. The card is a size container so
   the header can adapt to the card's own width (see the @container rule). */
.tagnet-stat-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
    min-height: 100px;
    container-type: inline-size;
}

/* Header never wraps: a two-line label would push that card's value below its
   neighbours'. The label keeps its width; the arrow chip is the part that
   gives, shrinking to an ellipsis rather than spilling into the next card. */
.tagnet-stat-card-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

.tagnet-stat-card-header .mud-typography-overline {
    white-space: nowrap;
    flex-shrink: 0;
}

.tagnet-stat-card-header .mud-chip-container {
    min-width: 0;
}

.tagnet-stat-card-header .mud-chip {
    max-width: 100%;
}

.tagnet-stat-card-header .mud-chip-content {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Narrow cards (four-up tiles in a half-width dashboard widget): the header's
   arrow chip and the value row's status chip drop their text and keep the
   icon; the link's hover title and the status tooltip still carry the words. */
@container (max-width: 239px) {
    .tagnet-stat-card-header .mud-chip-content,
    .tagnet-stat-card-status .mud-chip-content {
        display: none;
    }

    .tagnet-stat-card-header .mud-chip .mud-chip-icon,
    .tagnet-stat-card-status .mud-chip-icon {
        margin-right: 0;
    }
}

/* KPI value: one size per variant, in text-primary whether or not the card
   links (the hover tint and arrow chip say "link"; indigo numerals did not
   read well). Sized above Typo.h5 / h6 so the figure carries the card. */
.tagnet-stat-card-value {
    font-size: 1.75rem;
    line-height: 1.25;
}

.tagnet-stat-card-dense .tagnet-stat-card-value {
    font-size: 1.5rem;
}

/* Value row at the bottom of the card, sub-line beneath it. Rows mix cards
   with and without a sub-line only on the dashboard, where the conditional
   message is a status chip on the value row instead (HeroStatCard.Status). */
.tagnet-stat-card-body {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    flex: 1;
}
/* A pin width saved on a wide desktop must never crush a narrow window:
   cap both drawers at 88vw (the content margin uses the matching min()). */
.help-drawer,
.ai-chat-drawer {
    max-width: 88vw;
}

/* Resize handle on the inner edge of a pinned (docked) help / AI chat drawer */
.tagnet-drawer-resize-handle {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 6px;
    cursor: ew-resize;
    z-index: 10;
    touch-action: none;
}

.tagnet-drawer-resize-handle:hover,
.tagnet-drawer-resize-handle:active {
    background: var(--mud-palette-primary);
    opacity: 0.35;
}

/* ==========================================================================
   Workflow action steps: a circled step number on a rail joining the steps,
   then a card headed by the tinted type icon and the name. Shared by
   ActionCard (workflow edit + detail) and the execution timeline, so an
   action reads the same everywhere.
   ========================================================================== */
.tagnet-step { display: flex; gap: 12px; }
.tagnet-step-rail { display: flex; flex-direction: column; align-items: center; width: 28px; flex-shrink: 0; }
.tagnet-step-number {
    width: 28px; height: 28px; border-radius: 50%; margin-top: 14px; flex-shrink: 0;
    border: 1.5px solid var(--mud-palette-primary); color: var(--mud-palette-primary);
    background: var(--mud-palette-surface);
    display: flex; align-items: center; justify-content: center;
    font-size: .8rem; font-weight: 600;
}
.tagnet-step-line { flex: 1; width: 2px; background: var(--mud-palette-lines-default); margin: 4px 0 -14px; }
.tagnet-step-card { flex: 1; min-width: 0; margin-bottom: 12px; overflow: hidden; }
.tagnet-step-top { display: flex; align-items: center; gap: 12px; padding: 10px 12px; }
.tagnet-step-icon {
    width: 34px; height: 34px; border-radius: 8px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--mud-palette-primary);
    background: rgba(var(--mud-palette-primary-rgb), .1);
}

/* Execution timeline: the step number takes the step's outcome color in the
   same light tint as the card's status chip (Variant.Text), so the rail reads
   as the run's result without outweighing the cards. Default (skipped) stays
   hollow grey. */
.tagnet-step-number-success { background: rgba(var(--mud-palette-success-rgb), .06); border-color: var(--mud-palette-success); color: var(--mud-palette-success); }
.tagnet-step-number-info { background: rgba(var(--mud-palette-info-rgb), .06); border-color: var(--mud-palette-info); color: var(--mud-palette-info); }
.tagnet-step-number-warning { background: rgba(var(--mud-palette-warning-rgb), .06); border-color: var(--mud-palette-warning); color: var(--mud-palette-warning); }
.tagnet-step-number-error { background: rgba(var(--mud-palette-error-rgb), .06); border-color: var(--mud-palette-error); color: var(--mud-palette-error); }
.tagnet-step-number-default { border-color: var(--mud-palette-lines-inputs); color: var(--mud-palette-text-secondary); }

/* Body lines up under the name (12px pad + 34px icon + 12px gap). */
.tagnet-run-body {
    display: flex; flex-direction: column; gap: 6px;
    padding: 8px 12px 6px 58px;
    border-top: 1px solid var(--mud-palette-lines-default);
}
.tagnet-run-meta {
    display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px;
    min-height: 30px;
    font-size: .75rem; color: var(--mud-palette-text-secondary);
}
.tagnet-run-meta-sep { opacity: .6; }

/* ==========================================================================
   Trees (Locations, the Devices grouped view): a row click opens the entity
   (as a row does everywhere else); the chevron is the one control that
   expands. It gets a full-height square hit area with its own primary hover
   so it reads as separate from the row, and the name underlines on row hover
   as a link would. A row with nothing to open toggles instead, and its name
   leaves off tagnet-tree-name so it never looks like a link.
   ========================================================================== */
.tagnet-tree .mud-treeview-item-arrow { align-self: stretch; display: flex; align-items: center; }
.tagnet-tree .mud-treeview-item-expand-button { width: 32px; height: 32px; padding: 4px; border-radius: 6px; }
.tagnet-tree .mud-treeview-item-expand-button:hover {
    background: rgba(var(--mud-palette-primary-rgb), .12);
    color: var(--mud-palette-primary);
}
.tagnet-tree-row {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 2px 8px 2px 0; cursor: pointer;
}
.tagnet-tree-row:hover .tagnet-tree-name { text-decoration: underline; }
.tagnet-location-children { display: inline-flex; align-items: center; gap: 2px; }

/* ==========================================================================
   Tag trail (#1279) in the Tag Read Details dialog: the location and zone
   history on an ATR7000 TIMED_OUT read. js/tag-trail.js builds this markup
   inside the host; every color is a palette variable so both themes work.
   ========================================================================== */
.tagnet-trail-host { position: relative; }
.tagnet-trail { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 16px; }
@media (max-width: 900px) { .tagnet-trail { grid-template-columns: 1fr; } }
.tagnet-trail.single { grid-template-columns: 1fr; }
.tagnet-trail.single .tagnet-trail-rail { max-width: 640px; }
.tagnet-trail-map, .tagnet-trail-rail { min-width: 0; }
.tagnet-trail-rail { display: grid; gap: 14px; align-content: start; }
.tagnet-trail-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.tagnet-trail-seg { display: inline-flex; border: 1px solid var(--mud-palette-lines-default); border-radius: var(--mud-default-borderradius); overflow: hidden; }
.tagnet-trail-seg button, .tagnet-trail-btn {
    background: transparent; border: 0; color: var(--mud-palette-text-secondary);
    font: inherit; font-size: 12.5px; padding: 5px 11px; cursor: pointer;
}
.tagnet-trail-seg button + button { border-left: 1px solid var(--mud-palette-lines-default); }
.tagnet-trail-seg button[aria-pressed="true"] { background: var(--mud-palette-primary); color: var(--mud-palette-primary-text); }
.tagnet-trail-seg button:focus-visible, .tagnet-trail-btn:focus-visible, .tagnet-trail-scrub input:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: 2px; }
.tagnet-trail-btn { border: 1px solid var(--mud-palette-lines-default); border-radius: var(--mud-default-borderradius); min-width: 64px; }
.tagnet-trail-hint, .tagnet-trail-stats, .tagnet-trail-legend { font-size: 12px; color: var(--mud-palette-text-secondary); }
.tagnet-trail-hint { margin-left: auto; }
.tagnet-trail-svg {
    width: 100%; height: auto; display: block; touch-action: none;
    border: 1px solid var(--mud-palette-divider); border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-surface);
}
.tagnet-trail-legend { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
.tagnet-trail-legend .sw { display: inline-block; width: 26px; height: 8px; border-radius: 4px; vertical-align: middle; margin-right: 5px; }
.tagnet-trail-legend .mk { display: inline-block; width: 10px; height: 10px; border-radius: 50%; vertical-align: middle; margin-right: 5px; box-sizing: border-box; }
.tagnet-trail-stats { margin-top: 8px; font-variant-numeric: tabular-nums; }
.tagnet-trail-panel { border: 1px solid var(--mud-palette-divider); border-radius: var(--mud-default-borderradius); padding: 12px; }
.tagnet-trail-panel h4 { margin: 0 0 8px; font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 8px; color: var(--mud-palette-text-primary); }
.tagnet-trail-panel h4 .sub { margin-left: auto; font-weight: 400; color: var(--mud-palette-text-secondary); font-size: 12px; }
.tagnet-trail-scrub { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: center; }
.tagnet-trail-scrub input[type=range] { width: 100%; accent-color: var(--mud-palette-primary); margin: 0; }
.tagnet-trail-readout { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 8px 14px; margin-top: 10px; font-variant-numeric: tabular-nums; }
.tagnet-trail-readout label { display: block; font-size: 11px; color: var(--mud-palette-text-secondary); text-transform: uppercase; letter-spacing: .04em; }
.tagnet-trail-readout .v { font-size: 14px; font-weight: 500; display: flex; align-items: center; }
.tagnet-trail-zone-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; margin-right: 5px; flex: none; }
.tagnet-trail-strip { width: 100%; height: auto; display: block; }
.tagnet-trail svg text { font-family: inherit; }
.tagnet-trail-tip {
    position: absolute; pointer-events: none; z-index: 10; max-width: 240px;
    background: var(--mud-palette-text-primary); color: var(--mud-palette-surface);
    border-radius: 6px; padding: 7px 10px; font-size: 12px; line-height: 1.4;
    font-variant-numeric: tabular-nums; box-shadow: var(--mud-elevation-4);
}
.tagnet-trail-tip b { font-weight: 500; }
.tagnet-trail-table { margin-top: 12px; }
.tagnet-trail-table summary { cursor: pointer; font-size: 13px; color: var(--mud-palette-text-secondary); padding: 4px 0; }
.tagnet-trail-table .wrap { overflow: auto; margin-top: 8px; max-height: 320px; border: 1px solid var(--mud-palette-divider); border-radius: var(--mud-default-borderradius); }
.tagnet-trail-table table { border-collapse: collapse; width: 100%; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.tagnet-trail-table th, .tagnet-trail-table td { text-align: right; padding: 5px 10px; border-bottom: 1px solid var(--mud-palette-divider); white-space: nowrap; }
.tagnet-trail-table th:first-child, .tagnet-trail-table td:first-child,
.tagnet-trail-table th:nth-child(2), .tagnet-trail-table td:nth-child(2),
.tagnet-trail-table th:last-child, .tagnet-trail-table td:last-child { text-align: left; }
.tagnet-trail-table thead th {
    position: sticky; top: 0; background: var(--mud-palette-surface); color: var(--mud-palette-text-secondary);
    font-weight: 500; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
}

/* A health check row that opens a popup (#1489). */
.tagnet-check-row-opens { cursor: pointer; }

/* The row's arrow stays on screen however far a narrow table scrolls: a popover whose anchor has
   scrolled out of the table is placed off screen with it. */
.tagnet-check-table th:last-child,
.tagnet-check-table td:last-child {
    position: sticky;
    right: 0;
    background-color: var(--mud-palette-surface);
}
@media (min-width: 600px) {
    .tagnet-check-table tbody tr:hover td:last-child {
        background-image: linear-gradient(var(--mud-palette-table-hover), var(--mud-palette-table-hover));
    }
}

/* On a phone the table has no room for columns: Details goes under the check's name, so the reason
   stays readable with nothing to scroll. The columns are icon, Check, Details, arrow (#1523). */
@media (max-width: 599.98px) {
    .tagnet-check-table.mud-simple-table table thead { display: none; }
    .tagnet-check-table.mud-simple-table table,
    .tagnet-check-table.mud-simple-table table tbody { display: block; }
    .tagnet-check-table.mud-simple-table table tbody tr {
        display: grid;
        grid-template-columns: 24px minmax(0, 1fr) 32px;
        column-gap: 8px;
        align-items: center;
        padding: 8px;
        border-bottom: 1px solid var(--mud-palette-table-lines);
    }
    .tagnet-check-table.mud-simple-table table tbody tr > td {
        position: static;
        padding: 0;
        border: 0;
        background-color: transparent;
    }
    .tagnet-check-table.mud-simple-table table tbody tr > td:nth-child(3) { grid-column: 2; grid-row: 2; }
    .tagnet-check-table.mud-simple-table table tbody tr > td:nth-child(4) { grid-column: 3; grid-row: 1 / span 2; }
}

/* ==========================================================================
   The status band and the Reader control strip on a device's Overview (#1523;
   docs/internal/ui-design-system.md, "Status band")
   ========================================================================== */

/* The band: the status icon in a filled circle, the word, the reasons and notes, and both
   clocks on the right. The surface stays white; the icon and the reason carry the colour. */
.tagnet-status-band {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px 24px;
}
.tagnet-status-band-main {
    display: flex;
    gap: 14px;
    flex: 1 1 320px;
    min-width: 0;
}
.tagnet-status-badge {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-color: var(--mud-palette-gray-light);
    color: var(--mud-palette-text-secondary);
}
.tagnet-status-badge--success { background-color: var(--mud-palette-success); color: var(--mud-palette-success-text); }
.tagnet-status-badge--warning { background-color: var(--mud-palette-warning); color: var(--mud-palette-warning-text); }
.tagnet-status-badge--error { background-color: var(--mud-palette-error); color: var(--mud-palette-error-text); }
.tagnet-status-badge--info { background-color: var(--mud-palette-info); color: var(--mud-palette-info-text); }
/* The word at the hero value's dense size (.tagnet-stat-card-dense .tagnet-stat-card-value). */
.tagnet-status-word { font-size: 1.5rem; line-height: 1.25; }
.tagnet-status-clocks {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    gap: 2px;
    flex: 0 0 auto;
}
/* A text button, so it weighs the same as the captions above it; pulled right by its own
   padding so its label lines up with the clocks' right edge. */
.tagnet-status-actions {
    display: flex;
    align-items: center;
    gap: 0;
    margin-top: 2px;
    margin-right: -8px;
}
/* On a phone the clocks fold under the band's notes. */
@media (max-width: 599.98px) {
    .tagnet-status-clocks { align-items: flex-start; text-align: left; flex-basis: 100%; }
}

/* The band's foot: verdicts left of the divider (one icon per check), readouts right of it
   (numbered dots). The readouts wrap under the icons when the row is narrow. */
.tagnet-status-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-divider);
}
.tagnet-status-checks {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0;
}
.tagnet-status-check-static {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
}
.tagnet-status-divider {
    width: 1px;
    align-self: stretch;
    min-height: 28px;
    background-color: var(--mud-palette-divider);
}
/* On a phone the readouts wrap under the icons, where a vertical divider is a stray tick. */
@media (max-width: 599.98px) {
    .tagnet-status-divider { display: none; }
}
.tagnet-status-readouts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 14px;
}
.tagnet-status-readout {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* A numbered readout dot (a port, a GPI or GPO line): state, not a verdict. */
.tagnet-dot { display: block; }
.tagnet-dot circle { fill: var(--mud-palette-gray-default); }
.tagnet-dot text { fill: var(--mud-palette-primary-text); }
.tagnet-dot--success circle { fill: var(--mud-palette-success); }
.tagnet-dot--warning circle { fill: var(--mud-palette-warning); }
.tagnet-dot--unused circle { fill: var(--mud-palette-gray-lighter); }
.tagnet-dot--unused text { fill: var(--mud-palette-text-primary); }
.tagnet-dot--hold circle { fill: var(--mud-palette-gray-lighter); }
.tagnet-dot--hold text { fill: var(--mud-palette-text-secondary); }

/* The Reader control strip: equal button cells, 2 by 2 once the strip is too narrow for four,
   with the last or current operation on one line under them. */
.tagnet-control-cells {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 8px;
}
.tagnet-control-cells .mud-button-root { white-space: nowrap; }
.tagnet-control-split { display: flex; width: 100%; }
.tagnet-control-split > .mud-button-root:first-child { flex: 1 1 auto; }
.tagnet-control-split > .mud-menu { flex: 0 0 auto; display: inline-flex; }
.tagnet-control-cells > .mud-menu { display: block; width: 100%; }
/* One operation on a line (OperationRun): label, icon or spinner, name, when, how long, who, links.
   Under the Reader control cells, and on the create wizard's Identify and Deploy screens. */
.tagnet-operation-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    line-height: 1.5;
}
.tagnet-operation-line .mud-icon-root { font-size: 1.125rem; }

/* The running or just-finished operation: the overall progress bar over one segment per step,
   coloured by its outcome; the running segment pulses. Names are in the tooltips and the line below. */
.tagnet-operation-strip { margin-top: 12px; }
/* The step counter: short fixed pills beside the caption, so they cannot be mistaken for the
   full-width progress bar above them. */
.tagnet-operation-steps {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 10px;
    margin-top: 8px;
}
.tagnet-operation-pills {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 3px;
}
.tagnet-operation-pill {
    width: 18px;
    height: 6px;
    border-radius: 3px;
    background-color: var(--mud-palette-gray-lighter);
}
.tagnet-operation-pill--success { background-color: var(--mud-palette-success); }
.tagnet-operation-pill--failed { background-color: var(--mud-palette-error); }
.tagnet-operation-pill--running { background-color: var(--mud-palette-primary); animation: tagnet-operation-pulse 1.2s ease-in-out infinite; }
/* Skipped: hatched, so it reads as "passed over" rather than empty or not yet reached. */
.tagnet-operation-pill--skipped {
    background-image: repeating-linear-gradient(135deg, var(--mud-palette-gray-light) 0 3px, var(--mud-palette-gray-lighter) 3px 6px);
}
@keyframes tagnet-operation-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
.tagnet-operation-spinner { width: 18px !important; height: 18px !important; }

/* A request or response body in the operation details dialog. */
.tagnet-operation-body {
    margin: 0;
    padding: 8px;
    font-size: 11px;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 200px;
    overflow: auto;
    background-color: var(--mud-palette-background-gray);
    border-radius: var(--mud-default-borderradius);
}

/* One port in the Antennas popup: name, 24-hour bar, percent, and a line of words under the bar. */
.tagnet-port-row {
    display: grid;
    grid-template-columns: 68px minmax(0, 1fr) 36px;
    column-gap: 8px;
    align-items: center;
    margin-bottom: 4px;
}
.tagnet-port-bar {
    height: 12px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--mud-palette-action-disabled-background);
}
.tagnet-port-sub { grid-column: 2 / -1; }
/* A reader with configured port names: the name over its port number, cut short past the column. */
.tagnet-port-row--named { grid-template-columns: 112px minmax(0, 1fr) 36px; }
.tagnet-port-name { min-width: 0; line-height: 1.2; }
.tagnet-port-name > * {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tagnet-drop-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    column-gap: 8px;
    align-items: center;
    min-height: 26px;
}

/* A grid column that shrinks to its content on a table row. Not on a phone, where MudDataGrid
   stacks each cell as a full-width label and value row and width: 1% would squeeze the value. */
@media (min-width: 600px) {
    .tagnet-fit-column {
        white-space: nowrap;
        width: 1%;
    }
}
