@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

:root {
    --transition-speed-hover: 0.1s;
    --nxs-warning: #b13600;
    --nxs-surface-radius: 1rem;

    /* ── Design tokens (single source of truth; see docs/plans/design-tokens-retrofit.md) ──
       The MudTheme in MainLayout references these; component CSS must use them, not literals. */

    /* Radius — flat scale */
    --nxs-radius-sm: 4px;    /* chips (non-pill), small/inset controls */
    --nxs-radius-md: 6px;    /* default — buttons, inputs, cards */
    --nxs-radius-lg: 8px;    /* panels, grids, modals, large surfaces */
    --nxs-radius-pill: 999px;

    /* Spacing — 4px-based scale for margin / padding / gap. Token number = pixel value;
       value is rem for accessibility (assumes 16px root). Round raw spacing to the nearest
       step. Structural values (vh/vw, calc(), grid track sizes) are NOT spacing — leave them. */
    --nxs-space-2:  0.125rem; /* 2px  — hairline gaps */
    --nxs-space-4:  0.25rem;  /* 4px  */
    --nxs-space-6:  0.375rem; /* 6px  */
    --nxs-space-8:  0.5rem;   /* 8px  */
    --nxs-space-12: 0.75rem;  /* 12px */
    --nxs-space-16: 1rem;     /* 16px — base rhythm */
    --nxs-space-20: 1.25rem;  /* 20px */
    --nxs-space-24: 1.5rem;   /* 24px */
    --nxs-space-32: 2rem;     /* 32px */
    --nxs-space-48: 3rem;     /* 48px — section spacing */

    /* Type size — font-size scale (see docs/plans/chip-size-tokens.md; broader Pass 9 extends
       it site-wide). Named -size to avoid colliding with the --nxs-text* colour family. */
    --nxs-text-size-xs: 0.75rem;   /* 12px — dense chips / micro-labels */
    --nxs-text-size-sm: 0.8125rem; /* 13px — compact chips / labels */
    --nxs-text-size-md: 0.875rem;  /* 14px — standard chips / base component text */

    /* Control height — fixed heights for small controls. Chip slice only for now; broader
       Pass 9 adds the sm/lg/touch steps for inputs and buttons. */
    --nxs-control-h-chip: 20px; /* dense data badge (e.g. dimension-matrix conformance pill) */
    --nxs-control-h-md: 32px;   /* standard interactive pill (removable / helper chips) */

    /* Layout — page width policy (see docs/plans/page-width-layout.md). Content is full-width
       by default (data grids use the space); form/detail pages opt into a capped reading
       column via <NxsReadingColumn>. */
    --nxs-content-gutter: 1.5rem; /* horizontal page padding (replaces the old global px-4) */
    --nxs-reading-max: 1100px;    /* max line length for form/detail reading columns */
    --nxs-chart-height-sm: clamp(320px, 42vh, 440px);
    --nxs-chart-height-md: clamp(420px, 58vh, 560px);
    --nxs-chart-height-lg: clamp(510px, 70vh, 640px);
    --nxs-chart-height-xl: clamp(510px, 78vh, 780px);
    --nxs-grid-fill-min-height: 320px; /* floor for FillViewport grids — 100vh shrinks in CSS px under browser zoom, so without a floor calc(100vh - offset) collapses the grid to nothing */

    /* Surfaces — neutral dark ladder (tinted darks are NOT surfaces — handled as status tokens) */
    --nxs-bg: #222222;            /* page background */
    --nxs-surface: #121212;       /* primary panel/card surface */
    --nxs-surface-inset: #101010; /* wells/insets (absorbs #0f0f0f/#0d0d0d/#141414/#151515) */
    --nxs-surface-raised: #1a1a1a;/* raised panels (absorbs #161616/#181818/#191919/#1b1b1b/#1d1d1d/#1e1e1e/#1f1f1f) */
    --nxs-surface-40: color-mix(in srgb, var(--nxs-surface) 40%, transparent);
    --nxs-surface-80: color-mix(in srgb, var(--nxs-surface) 80%, transparent);
    --nxs-geometry-surface: var(--nxs-surface-raised); /* canonical geometry viewer / thumbnail surface */
    --nxs-surface-2: #2a2a2a;     /* secondary fills (absorbs #232323/#242424/#262626/#272727/#2b2b2b) */
    --nxs-surface-3: #383838;     /* raised/hover fills (absorbs #333333/#353535/#3a3a3a/#444444) */

    /* Borders / lines */
    --nxs-border: #363636;
    --nxs-border-60: color-mix(in srgb, var(--nxs-border) 60%, transparent);
    --nxs-border-strong: #4f4f4f; /* absorbs #3a3a3a/#5f5f5f */
    --nxs-divider: var(--nxs-overlay-12); /* = white 12% overlay step (see ladder below) */

    /* Text */
    --nxs-text: #ffffff;          /* headings / primary */
    --nxs-text-body: #e6e6e6;     /* body */
    --nxs-text-muted: #9aa3ad;    /* labels / secondary */
    --nxs-text-subtle: #b8c3cf;   /* absorbs #aeb7c2/#cfd6de/#9aa0a6 */

    /* Accent / status */
    --nxs-accent: #00bcd4;
    --nxs-accent-bright: #00d4ee; /* absorbs #00c8ff/#74edff — hover/glow */
    --nxs-danger: #f05252;        /* fail / out-of-tolerance fill */
    --nxs-danger-strong: #d71920; /* strong error */
    --nxs-danger-bg: #3f1014;     /* error background tint */
    --nxs-success: #2e9e5f;       /* in-tolerance / pass fill */
    --nxs-success-bg: #0f3f25;    /* dark green fill */
    --nxs-info-bg: #0f1720;       /* info/note panels (absorbs #101114/#05070b/#0d1117) */

    /* Status foreground/border — light variants for pass/fail chips on the *-bg fills above
       (the dark --nxs-danger/-success can't be used as foreground text; they're fills). */
    --nxs-success-text: #86f7ae;   /* pass chip text/icon */
    --nxs-success-border: #2fbf6a; /* pass chip border */
    --nxs-danger-text: #ff7f7f;    /* fail chip text/icon */
    --nxs-danger-border: #bf4248;  /* fail chip border */

    /* Info / highlight — bright sky-blue foreground (pairs with --nxs-info-bg); absorbs the
       drifting #67d5ff/#7dc9ff/#54d8e6 highlight blues. Tints via color-mix, like the accent. */
    --nxs-info: #67d5ff;
    --nxs-info-8:  color-mix(in srgb, var(--nxs-info) 8%, transparent);
    --nxs-info-20: color-mix(in srgb, var(--nxs-info) 20%, transparent);

    /* White overlays — fixed opacity ladder. Round any raw rgba(255,255,255,a) to the nearest
       step. NOTE: higher white-alphas (>=~0.42) are muted/near-opaque TEXT, not overlays —
       use the --nxs-text-* ladder for those, not these tokens. */
    --nxs-overlay-3:  rgba(255, 255, 255, 0.03); /* faintest fills / zebra (absorbs 0.02–0.04) */
    --nxs-overlay-8:  rgba(255, 255, 255, 0.08); /* hover / active fill (absorbs 0.06–0.10) */
    --nxs-overlay-12: rgba(255, 255, 255, 0.12); /* dividers / hairlines */
    --nxs-overlay-20: rgba(255, 255, 255, 0.20); /* visible borders (absorbs 0.16–0.24) */
    --nxs-overlay-32: rgba(255, 255, 255, 0.32); /* strong borders / emphasis (absorbs 0.28–0.35) */

    /* Back-compat aliases — existing names now map onto the ladder steps */
    --nxs-overlay-subtle: var(--nxs-overlay-3);
    --nxs-overlay-hover:  var(--nxs-overlay-8);

    /* Accent tints — brand accent at low alpha, derived from --nxs-accent so they stay in sync.
       Same step numbers as the white ladder. */
    --nxs-accent-8:  color-mix(in srgb, var(--nxs-accent) 8%, transparent);  /* faint wash (absorbs 0.08–0.12) */
    --nxs-accent-20: color-mix(in srgb, var(--nxs-accent) 20%, transparent); /* chip / selected-row fill (absorbs 0.15–0.18) */
    --nxs-accent-30: color-mix(in srgb, var(--nxs-accent) 30%, transparent); /* chip border / strong tint (absorbs 0.30–0.35) */

    /* Row selection — the house selected-row treatment (see .nxs-grid__row--selected):
       accent tint + white hairline seams. An accent HUE (not a neutral lift) so the
       selected row stays visible on any housing surface and never reads as the hover
       state; the hairlines keep it crisp rather than a flat wash. */
    --nxs-row-selected-bg: var(--nxs-accent-20);
    --nxs-row-selected-line: rgba(255, 255, 255, 0.75);

    /* Scrims / shadow — black-alpha axis */
    --nxs-scrim:  rgba(0, 0, 0, 0.6);  /* modal / backdrop scrim (absorbs 0.35–0.72) */
    --nxs-shadow: rgba(0, 0, 0, 0.22); /* drop shadows (absorbs 0.2/0.24) */
    --nxs-surface-veil: rgba(18, 18, 18, 0.35); /* translucent dark veil for in-content loading/disabled overlays (absorbs 0.28–0.38) */

}

/* NxsChip<T> — the site's standard chip primitive. Semantic wrappers such as
   NxsResultChip and NxsValueChip compose this, so the baseline chrome lives here. */
.nxs-chip.mud-chip {
    border: 1px solid var(--nxs-border-strong);
    border-radius: var(--nxs-radius-pill);
    background: var(--nxs-overlay-8);
    color: var(--nxs-text-body);
    font-weight: 700;
}

/* NxsChip<T> selected state — neutral selectable pills use MudChip's built-in Selected
   property plus this shared visual treatment on the whole chip. */
.nxs-chip.is-selected.mud-chip {
    border-color: var(--nxs-accent);
    color: var(--nxs-text);
    opacity: 1;
}

.nxs-chip.mud-chip-color-success {
    border-color: var(--nxs-success-border);
    background: color-mix(in srgb, var(--nxs-success-text) 20%, transparent);
    color: var(--nxs-success-text);
}

.nxs-chip.mud-chip-color-error {
    border-color: var(--nxs-danger-border);
    background: color-mix(in srgb, var(--nxs-danger-text) 20%, transparent);
    color: var(--nxs-danger-text);
}

.nxs-chip.mud-chip-color-warning {
    border-color: var(--nxs-warning);
    background: color-mix(in srgb, var(--nxs-warning) 24%, transparent);
    color: color-mix(in srgb, var(--nxs-warning) 45%, var(--nxs-text));
}

.nxs-chip.mud-chip-color-info {
    border-color: var(--nxs-info);
    background: var(--nxs-info-20);
    color: var(--nxs-info);
}

.nxs-chip.mud-chip-color-secondary {
    border-color: var(--nxs-overlay-32);
    background: var(--nxs-overlay-12);
    color: var(--nxs-text-subtle);
}

.nxs-chip.mud-chip-color-primary {
    border-color: var(--nxs-accent-30);
    background: var(--nxs-accent-20);
    color: var(--nxs-accent);
}

.nxs-chip.nxs-result-chip--pass {
    border-color: var(--nxs-success-border);
    background: color-mix(in srgb, var(--nxs-success-text) 20%, transparent);
    color: var(--nxs-success-text);
}

.nxs-chip.nxs-result-chip--fail {
    border-color: var(--nxs-danger-border);
    background: color-mix(in srgb, var(--nxs-danger-text) 20%, transparent);
    color: var(--nxs-danger-text);
}

/* NxsRemovableChip — dismissible token pills (applied search filters, saved presets).
   Structure/radius come from .nxs-chip above; these supply the neutral base look and an
   accent variant, plus tame the built-in MudChip close button to the token scale. Colour
   isn't a bespoke prop — it rides MudBlazor's Color: Color.Default = neutral base here,
   Color.Primary adds .mud-chip-color-primary which we repaint with the accent tokens.
   Placed after the .nxs-chip rules so the background/border/colour win on equal specificity. */
.nxs-chip.nxs-removable-chip {
    min-height: var(--nxs-control-h-md);
    height: auto;
    font-size: var(--nxs-text-size-md);
    font-weight: 500;
    border-color: var(--nxs-overlay-20);
    background: var(--nxs-overlay-subtle);
    color: var(--nxs-text);
}

.nxs-chip.nxs-removable-chip.mud-chip-color-primary {
    border-color: var(--nxs-accent-30);
    background: var(--nxs-accent-20);
    color: var(--nxs-accent);
}

.nxs-removable-chip .mud-chip-close-button {
    color: inherit;
    opacity: 0.7;
}

.nxs-removable-chip .mud-chip-close-button:hover {
    opacity: 1;
}

.nxs-removable-chip:not(.mud-chip-color-primary) .mud-chip-close-button:hover {
    color: var(--nxs-danger);
}

/* NxsDataGrid<T> — the site's standard data grid: one cohesive dark rounded panel
   (toolbar + header + rows), matching the metrology grids. Striping off / elevation 0 /
   outlined are forced in the component; the rules here cover what props can't express. */
.nxs-grid.mud-table {
    background: var(--nxs-surface);
    border-radius: var(--nxs-radius-lg);
    overflow: hidden; /* clip the square table to the rounded panel corners */
}

.nxs-grid .mud-table-container,
.nxs-grid .mud-table-body .mud-table-row {
    background: var(--nxs-surface);
}

/* The root panel does ALL the rounding (overflow:hidden clip). Everything inside stays
   square — inner radii draw curved seams where they meet the optional toolbar. Square=true
   in the component disables Mud's normal panel rounding, but FixedHeader grids get a
   SEPARATE rounding from `.mud-table-sticky-header * ... .mud-table-cell:first-child`
   (specificity 0,5,0 — independent of Square), so the sticky-header selectors below must
   carry 0,6,0 to win. */
.nxs-grid .mud-table-container,
.nxs-grid .mud-table-toolbar,
.nxs-grid.mud-table-sticky-header .mud-table-root .mud-table-head .mud-table-cell:first-child,
.nxs-grid.mud-table-sticky-header .mud-table-root .mud-table-head .mud-table-cell:last-child,
.nxs-grid .mud-table-head .mud-table-cell:first-child,
.nxs-grid .mud-table-head .mud-table-cell:last-child {
    border-radius: 0;
}

/* Toolbar geometry is OURS. Mud's .mud-toolbar sets a FIXED height (64px) and gutter
   padding (0 8px 0 16px) — both read unbalanced next to the content. Content-driven
   height, uniform 12/16 padding. */
.nxs-grid .mud-table-toolbar {
    height: auto;
    min-height: 0;
    padding: 12px 16px;
    gap: 12px;
    border-bottom: 1px solid var(--nxs-border);
}

/* Standard search field (NxsSearchField): fixed width WHEREVER it appears — a default
   MudTextField is full-width and stretches edge-to-edge. Pages may override per layout
   (e.g. full-width on narrow screens) via a ::deep rule on their own class. */
.nxs-search {
    flex: 0 1 360px;
    width: 360px;
    min-width: 180px;
}

/* MudSelect popovers render outside the component subtree, so NxsFilterDropdown
   supplies this class via PopoverClass rather than relying on scoped CSS. */
.nxs-filter-dropdown__popover,
.nxs-filter-dropdown__popover .mud-paper,
.nxs-filter-dropdown__popover .mud-list {
    border-top-left-radius: 0 !important;
    min-width: 190px;
    max-width: min(320px, calc(100vw - var(--nxs-space-32)));
}

.nxs-filter-dropdown__popover .mud-list-item,
.nxs-filter-dropdown__popover .mud-list-item-text {
    min-width: 0;
}

.nxs-filter-dropdown__popover .nxs-filter-dropdown__option-text {
    display: block;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Uniform with toolbar + rows; row hover is the only lift. The sticky-header variant must
   carry 0,5,0 specificity: FixedHeader grids get their header background from Mud's
   `.mud-table-sticky-header * .mud-table-root .mud-table-head * .mud-table-cell` (0,4,0),
   which beats a plain 0,3,0 override. Keep this OPAQUE — rows scroll under the sticky head. */
.nxs-grid .mud-table-head .mud-table-cell,
.nxs-grid.mud-table-sticky-header .mud-table-root .mud-table-head .mud-table-cell {
    background: var(--nxs-surface);
}

.nxs-grid .mud-table-body .mud-table-row:hover > .mud-table-cell {
    background: var(--nxs-surface-raised);
}

/* Links in body cells inherit the cell's typography instead of MudLink's body1
   default, so linked and plain values in the same column render at the same size.
   Pages should not set Typo on grid row links. */
.nxs-grid .mud-table-body .mud-table-cell .mud-link {
    font-size: inherit;
    line-height: inherit;
}

/* Master-detail row selection — the house treatment: accent-tint fill + hairline seams
   top and bottom. Both classes are emitted by NxsDataGrid itself: the root
   `nxs-grid--clickable-rows` whenever a RowClick handler is wired, and
   `nxs-grid__row--selected` on rows matching the page's IsRowSelected predicate. Pages
   never write these class names. The :hover variant must be stated (and sit after the
   generic hover lift above) so the selected fill survives hover. */
.nxs-grid.nxs-grid--clickable-rows .mud-table-body .mud-table-row {
    cursor: pointer;
}

.nxs-grid .mud-table-body .nxs-grid__row--selected > .mud-table-cell,
.nxs-grid .mud-table-body .nxs-grid__row--selected:hover > .mud-table-cell {
    background: var(--nxs-row-selected-bg);
    box-shadow: inset 0 1px 0 var(--nxs-row-selected-line), inset 0 -1px 0 var(--nxs-row-selected-line);
}

/* No-records and loading rows: Mud paints both var(--mud-palette-surface) — a lighter
   shade than the grid panel, so they read as a stray band. Pin them to the panel surface.
   The sticky-header loading selector needs 0,5,0 to beat Mud's 0,4,0 (same story as the
   header cells above). */
.nxs-grid .nxs-unit-header,
.nxs-grid .nxs-unit-header * {
    --mud-typography-body2-text-transform: none;
    --mud-typography-button-text-transform: none;
    --mud-typography-subtitle2-text-transform: none;
    text-transform: none !important;
}

.nxs-grid .mud-table-empty-row,
.nxs-grid.mud-table-sticky-header .mud-table-root .mud-table-head .mud-table-loading {
    background-color: var(--nxs-surface);
}

.nxs-grid:has(.mud-table-loading) {
    cursor: wait;
}

.nxs-grid .mud-table-loading {
    display: none !important;
}

.nxs-grid .mud-table-empty-row .mud-table-cell {
    padding-block: var(--nxs-space-24);
}

/* Empty and first-load grids must collapse to their message/spinner instead of reserving a
   viewport/grid footprint. This overrides both NxsDataGrid's FillViewport height and any
   100% shell sizing while the no-records or first-load path is active. */
.nxs-grid:has(.nxs-grid-empty),
.nxs-grid:has(.nxs-grid-loading) {
    height: auto !important;
}

.nxs-grid:has(.nxs-grid-empty) .mud-table-container,
.nxs-grid:has(.nxs-grid-loading) .mud-table-container {
    flex: 0 0 auto;
    min-height: 0;
    height: auto !important;
}

/* MudSwitch unchecked track: Mud paints it var(--mud-palette-black) at 48% opacity — and
   our palette Black IS --nxs-surface, so on surface panels the track is invisible (only the
   thumb shows). Lift it to the raised-fill token, full opacity. Checked state is unaffected:
   Mud's .mud-checked rules out-specify this and keep the accent track. */
.mud-switch-span .mud-switch-track {
    background-color: var(--nxs-surface-3);
    opacity: 1;
}

/* NxsButton — the standard primary action button: accent fill, dark text.
   .mud-button-root included for specificity over Mud's filled-primary colours. */
.mud-button-root.nxs-btn {
    background: var(--nxs-accent);
    color: var(--nxs-surface);
}

.mud-button-root.nxs-btn:hover,
.mud-button-root.nxs-btn:focus-visible {
    background: var(--nxs-accent-bright);
}

/* NxsButton secondary (Kind="Secondary"): outlined accent for actions beside a primary button. */
.mud-button-root.nxs-btn-secondary {
    background: transparent;
    color: var(--nxs-accent);
    border: 1px solid var(--nxs-border-strong);
}

.mud-button-root.nxs-btn-secondary:hover,
.mud-button-root.nxs-btn-secondary:focus-visible {
    background: var(--nxs-accent-8);
    border-color: var(--nxs-accent);
    color: var(--nxs-accent-bright);
}

/* NxsCard — the site's standard content card: outlined, padded, rounded panel with an
   optional titled header (MudText + divider) and an optional divider-anchored footer.
   Chrome is token-driven; lives here (global) so it reaches the MudPaper root without ::deep. */
.mud-paper.nxs-card {
    padding: var(--nxs-space-24);
    background: var(--nxs-surface-raised);
    border: 1px solid var(--nxs-border);
    border-radius: var(--nxs-radius-lg);
}

/* Chart cards keep NxsCard spacing/chrome, but use the same surface as Plotly charts so
   chart margins and surrounding card padding read as one continuous chart surface. */
.mud-paper.nxs-card.nxs-chart-card {
    background: var(--nxs-surface);
}

/* Part-overview timeline card: zero the card padding so the horizontal scrollbar runs edge-to-edge
   along the card's bottom edge. The timeline's inset comes uniformly from .part-overview-flow's
   padding instead, so the spacing reads consistent on all four sides. */
.mud-paper.nxs-card.part-overview-card {
    padding: 0;
}

.nxs-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--nxs-space-16);
    margin-bottom: var(--nxs-space-16);
    padding-bottom: var(--nxs-space-12);
    border-bottom: 1px solid var(--nxs-border);
}

.nxs-card__title {
    margin: 0;
    font-weight: 600;
}

.nxs-card__header-actions {
    display: flex;
    align-items: center;
    gap: var(--nxs-space-8);
    flex-shrink: 0;
}

.nxs-card__actions {
    margin-top: var(--nxs-space-24);
    padding-top: var(--nxs-space-16);
    border-top: 1px solid var(--nxs-border);
    display: flex;
    flex-wrap: wrap;
    gap: var(--nxs-space-12);
}

@media (max-width: 900px) {
    .mud-paper.nxs-card {
        padding: var(--nxs-space-20);
    }
}

/* Standard grid empty state — calm, muted, centered. NxsDataGrid renders this by default;
   pages only override the wording (keep this class on the override). */
.nxs-grid-empty {
    padding: var(--nxs-space-24);
    text-align: center;
    color: var(--nxs-text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* Standard grid first-load state — NxsDataGrid renders this by default when Loading is true
   and there are no rows yet (refreshes with rows visible stay still; the built-in header
   progress bar is suppressed by the .nxs-grid .mud-table-loading rule above). */
.nxs-grid-loading {
    display: grid;
    place-items: center;
    padding: var(--nxs-space-24);
}

/* ── NxsTabs — the site's shared tab strip ─────────────────────────────────────────
   Two variants, one modifier:
     --primary    framed rounded bar; page-level sections.
     --secondary  dense hairline strip; sub-sections inside an already-framed area.
     --contained  (modifier, Contained="true") bar + panel area join into one bordered
                  panel — the bar is the top edge, content shares the raised surface.
                  Tab-bar toolbars go in MudTabs' native Header slot, which renders
                  inline inside the bar (no overlay/reserved-width tricks). */
.nxs-tabs {
    min-width: 0;
}

.nxs-tabs > .mud-tabs-panels > div {
    min-width: 0;
}

/* Header slot (MudTabs Header fragment, HeaderPosition defaults to After): inline
   toolbar at the right end of the bar row. */
.nxs-tabs .mud-tabs-header {
    display: flex;
    align-items: center;
    flex: 1 1 auto;
    justify-content: flex-end;
    min-width: 0;
    gap: 8px;
    padding: 4px 12px 4px 16px;
}

.nxs-tabs--primary > .mud-tabs-tabbar {
    background: var(--nxs-surface-raised);
    border: 1px solid var(--nxs-border);
    border-radius: var(--nxs-radius-lg);
    overflow: hidden;
}

/* Tab cells must fill the bar's FULL height even when Header content (toolbars) makes
   the bar taller than the tabs — the active underline is the cell's bottom edge and has
   to sit on the bar's bottom border. Mud breaks the height-stretch chain in two places:
   .mud-tabs-tabbar-content is inline-block, and each tab sits in a `d-inline-block`
   utility wrapper (display:inline-block !important — hence the !important here). */
.nxs-tabs .mud-tabs-tabbar .mud-tabs-tabbar-inner {
    min-height: 0;
    align-items: stretch;
}

.nxs-tabs .mud-tabs-tabbar-content {
    display: flex;
    align-items: stretch;
}

.nxs-tabs .mud-tabs-tabbar-content .mud-tabs-tabbar-wrapper {
    align-items: stretch;
}

.nxs-tabs .mud-tabs-tabbar-wrapper > div {
    display: inline-flex !important;
    align-items: stretch;
}

.nxs-tabs .mud-tab {
    flex: 0 0 auto;
    min-height: var(--nxs-tabs-tab-min-height, 38px);
    padding: var(--nxs-tabs-tab-padding, 6px 14px);
    font-size: var(--nxs-tabs-tab-font-size, inherit);
    color: var(--nxs-text-subtle);
    transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
                color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
}

/* The active underline is drawn on the tab cell itself (inset shadow), not Mud's
   JS-measured .mud-tab-slider — the slider is positioned from pixel measurements that
   drift out of line with the cell (and with the hover highlight, which IS the cell).
   Same element for highlight and underline = aligned by construction. */
/* Specificity must beat the wrapper-children stretch rule below (also !important, and
   its `> div` type selector adds 0,2,1 — a bare .nxs-tabs .mud-tab-slider at 0,2,0
   LOSES and the slider quietly comes back). */
.nxs-tabs .mud-tabs-tabbar-wrapper > div.mud-tab-slider {
    display: none !important;
}

.nxs-tabs .mud-tab.mud-tab-active {
    color: var(--nxs-text);
    box-shadow: inset 0 -2px 0 var(--nxs-accent);
}

@media (hover: hover) and (pointer: fine) {
    .nxs-tabs .mud-tab:hover {
        background-color: var(--nxs-overlay-hover);
        color: var(--nxs-text);
    }

    .nxs-tabs .mud-tab.mud-tab-active:hover {
        background-color: var(--nxs-overlay-hover);
        box-shadow: inset 0 -2px 0 var(--nxs-accent);
    }
}

/* The bar's children stretch (so tab cells reach the bottom border) — the scroll-button
   wrappers stretch too, so they must centre their fixed-size chevrons themselves. */
.nxs-tabs .mud-tabs-scroll-button {
    display: flex;
    align-items: center;
}

.nxs-tabs .mud-tabs-scroll-button .mud-button-root {
    width: 36px;
    height: 36px;
    border-radius: var(--nxs-radius-pill);
    color: var(--nxs-text-subtle);
}

@media (hover: hover) and (pointer: fine) {
    .nxs-tabs .mud-tabs-scroll-button .mud-button-root:hover {
        background: var(--nxs-overlay-hover);
        color: var(--nxs-text);
    }
}

/* Secondary: dense strip anchored by a hairline so it never reads as floating text. */
.nxs-tabs--secondary > .mud-tabs-tabbar {
    background: transparent;
    border-bottom: 1px solid var(--nxs-divider);
}

.nxs-tabs--secondary .mud-tab {
    font-weight: 600;
}

.nxs-tabs--secondary .mud-tabs-scroll-button .mud-button-root {
    width: 36px;
    height: 36px;
}

/* Contained: bar + panels join into one framed panel. The bar keeps only its top
   corners; the panel area carries the remaining frame and its own padding (the strip's
   pt-* gap utility is suppressed by the component in this mode). */
.nxs-tabs--contained {
    --nxs-tabs-panel-pad: 16px;
}

.nxs-tabs--contained > .mud-tabs-tabbar {
    border-radius: var(--nxs-radius-lg) var(--nxs-radius-lg) 0 0;
}

.nxs-tabs--contained > .mud-tabs-panels {
    padding: var(--nxs-tabs-panel-pad);
    background: var(--nxs-surface-raised);
    border: 1px solid var(--nxs-border);
    border-top: 0;
    border-radius: 0 0 var(--nxs-radius-lg) var(--nxs-radius-lg);
}

/* A secondary strip LEADING a contained panel (Docked="true") sits flush under the
   parent's tab bar while keeping its divider aligned to the same inset as the content
   below. The pad var inherits from the containing .nxs-tabs--contained. */
.nxs-tabs--docked > .mud-tabs-tabbar {
    margin-block: calc(-1 * var(--nxs-tabs-panel-pad, 16px)) var(--nxs-tabs-panel-pad, 16px);
    margin-inline: 0;
    padding: 0;
}

/* ── NxsTabHeader — one frame for a two-row tab header ────────────────────────────
   NxsTabs still owns tab selection; rows render strip-only (their empty Mud panel
   areas are hidden). Page content lives OUTSIDE the stack.

   Geometry: deliberately simple. The whole stack is ONE bordered rounded panel on
   the raised surface; the rows are separated by a hairline divider. Active tabs use
   the standard .nxs-tabs accent underline in both rows — same indicator as the rest
   of the app. Grouping is communicated by containment, not per-tab borders. */
.nxs-tab-header {
    min-width: 0;
    background: var(--nxs-surface-raised);
    border: 1px solid var(--nxs-border);
    border-radius: var(--nxs-radius-lg);
    overflow: hidden; /* clip row hover overlays to the rounded corners */
}

.nxs-tab-header__row {
    display: flex;
    align-items: stretch;
    min-width: 0;
}

.nxs-tab-header__tabs {
    flex: 1 1 auto;
    min-width: 0;
}

/* Rows host bare strips: the stack owns the chrome, so strip chrome comes off and
   the (empty) panel areas are hidden. */
.nxs-tab-header__tabs > .nxs-tabs,
.nxs-tab-header__tabs > .nxs-tabs > .mud-tabs-tabbar {
    height: 100%;
    min-width: 0;
}

.nxs-tab-header__tabs > .nxs-tabs > .mud-tabs-tabbar {
    background: transparent;
    border: 0;
    border-radius: 0;
}

.nxs-tab-header__tabs > .nxs-tabs > .mud-tabs-panels {
    display: none;
}

/* With a child row present, the parent's selection is shown by the shared highlight
   alone (active tab + sub row share the same fill) — the accent underline belongs to
   the child row only, so it comes OFF the parent here, including on hover (the shared
   .nxs-tabs :hover rule would otherwise re-add it). */
.nxs-tab-header--has-subtabs .nxs-tabs--primary .mud-tab.mud-tab-active {
    background-color: var(--nxs-surface-2);
    box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
    .nxs-tab-header--has-subtabs .nxs-tabs--primary .mud-tab.mud-tab-active:hover {
        background-color: var(--nxs-surface-2);
        box-shadow: none;
    }
}

/* No divider between the rows: the sub row's lighter fill separates them tonally, and
   a hairline would cut through the active tab's connection to its sub row (they share
   the same fill so the selection reads as one region). */
.nxs-tab-header__row--subtabs {
    background-color: var(--nxs-surface-2);
}

html, body {
    font-family: Roboto, serif;
    /* Lock the window so the only vertical scrollbar is the content area's (article.content),
       not a full-height window scrollbar running behind the fixed app bar. */
    height: 100%;
    overflow: hidden;
}

/* Opt-in reading column for form/detail content — caps line length and centres within the
   full-width page. Grids/tables stay full-width (the page default) and must not use this. */
.nxs-reading-column {
    width: 100%;
    max-width: var(--nxs-reading-max);
    margin-inline: auto;
}

/* NxsFormSections / NxsFormSection — grouped form sections on create/detail pages: an
   accordion whose sections are all expanded by default. Each section is its own rounded
   house panel; selectors carry the .mud-expansion-panels/.mud-expand-panel prefixes to
   out-specify MudBlazor's stock rules (joined panels, 16px expand margins, 24px gutters). */
.nxs-form-sections.mud-expansion-panels {
    display: flex;
    flex-direction: column;
    gap: var(--nxs-space-16);
}

.nxs-form-sections.mud-expansion-panels .mud-expand-panel {
    background: var(--nxs-surface);
    border: 1px solid var(--nxs-border);
    border-radius: var(--nxs-radius-lg);
    overflow: hidden; /* the panel owns its rounding; everything inside stays square */
}

/* Sections keep a fixed gap; Mud's expand/collapse margin choreography and the
   joined-panel border/radius juggling would make the list jump and seam. */
.nxs-form-sections.mud-expansion-panels .mud-expand-panel.mud-panel-expanded {
    margin: 0;
}

.nxs-form-sections.mud-expansion-panels .mud-expand-panel:last-child,
.nxs-form-sections.mud-expansion-panels .mud-expand-panel.mud-panel-next-expanded {
    border-bottom: 1px solid var(--nxs-border);
}

.nxs-form-sections.mud-expansion-panels .mud-expand-panel-header {
    min-height: 3rem;
    padding: var(--nxs-space-12) var(--nxs-space-16);
    font-size: var(--nxs-text-size-md);
    font-weight: 700;
}

/* Chevron leads the section title (same reading order as the heater-plate accordion) */
.nxs-form-sections.mud-expansion-panels .mud-expand-panel-header .mud-expand-panel-icon {
    order: -1;
    margin-left: 0;
    margin-right: var(--nxs-space-8);
}

.nxs-form-sections.mud-expansion-panels .mud-expand-panel-header .mud-expand-panel-text {
    flex: 0 1 auto;
}

.nxs-form-sections.mud-expansion-panels .mud-expand-panel .mud-expand-panel-content {
    padding: var(--nxs-space-4) var(--nxs-space-16) var(--nxs-space-16);
    /* Floating field labels inside the panel mask the outline against the panel fill. */
    --nxs-field-backdrop: var(--nxs-surface);
}

table {
    width: auto;
    border-collapse: collapse;
}

td {
    vertical-align: middle;
    border: none;
}

input {
    width: 100%;
    height: 100%;
    padding-left: 1em;
    
    background-color: var(--bs-secondary-bg);
    border: none;
}

select {
    background-color: var(--bs-secondary-bg);
    border: none;
}

input[type="file"] {
    padding: 0;
    border: 2px solid #444444;
    border-radius: var(--nxs-radius-lg);

    &:hover {
        cursor: pointer;
    }

    &::file-selector-button {
        margin-right: 1em;
        padding: 0.75em;
        border: none;

        color: var(--nxs-text);
        background-color: var(--nxs-surface-3);
    }

    &::file-selector-button:hover {
        cursor: pointer;
    }
}

ul, .submenu{
    list-style: none;
}

textarea {
    height: 10em;
    min-height: 10em;
    max-height: 25em;

    padding: 0.5em;
    border: none;
    background-color: var(--bs-secondary-bg);
}

select {
    padding-left: 1em;
}

h1:focus {
    outline: none;
}

a, .btn-link {
    text-decoration: none;
    color: var(--nxs-accent);
}

.warning{
    color: orange;
}

.nxs-button {
    width: 100%;
}

.nxs-section {
    padding: 3em;
    border-radius: var(--nxs-radius-lg);

    background-color: var(--bs-tertiary-bg);
    box-shadow: 0 0 5px var(--bs-box-shadow);
    /*border: 1px var(--bs-emphasis-color) solid;*/

    transition: box-shadow 0.1s;
    margin-bottom: 4em;
}

.nxs-section-label {
    padding-left: 0.5em;
    font-weight: bold;
    margin-bottom: 0.5em;
}

.nxs-section-as-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3em;
}

.nxs-section-as-flex {
    display: flex;
    flex-direction: column;
    gap: 3em;
}

.nxs-section-as-grid-triple {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
    row-gap: 3em;
    column-gap: 3em;
}

.nxs-section-as-grid-quad {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
    row-gap: 3em;
    column-gap: 2em;
}

.nxs-section-item {
    flex: auto;
    display: flex;
    flex-direction: column;
    row-gap: 0.5em;
    max-width: 100%;
}

.airtable-source-selector {
    width: 100%;
}

.airtable-source-selector__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1em;
    width: 100%;
}

.airtable-source-selector__label-row {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    min-width: 0;
}

.airtable-source-selector__show-all {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    margin-left: auto;
    white-space: nowrap;
    font-weight: normal;
}

.airtable-source-selector__checkbox[type="checkbox"] {
    width: 1rem;
    height: 1rem;
    padding-left: 0;
    margin: 0;
    flex: 0 0 auto;
}

.nxs-section-chart {
    width: 45em;
    height: 45em;
    align-self: center;
}

.nxs-section-item-read-only-value {
    padding: 0.75em;
    background-color: var(--bs-body-bg);

    box-shadow: 0 0 10px var(--bs-box-shadow);
    border-radius: var(--nxs-radius-md);
    user-select: none;

    overflow: hidden;
    text-overflow: ellipsis;

}


.nxs-section-item-read-only-value:hover {
    cursor: pointer;
    box-shadow: 0 0 10px 2px var(--bs-box-shadow);
}

.nxs-section-item-read-only-value:active {
    box-shadow: 0 0 5px 0 var(--bs-box-shadow);
}

.nxs-section-item-read-only-note {
    padding: 0.75em;
    background-color: var(--bs-body-bg);
    box-shadow: 0 0 10px var(--bs-box-shadow);
    border-radius: var(--nxs-radius-md);
    height: 10em;
    white-space: pre-wrap;
    user-select: none;
    overflow: hidden;
    text-overflow: ellipsis;
}
.nxs-section-item-read-only-note:hover {
    cursor: pointer;
    box-shadow: 0 0 10px 2px var(--bs-box-shadow);
}

.nxs-section-item-read-only-note:active {
    box-shadow: 0 0 5px 0 var(--bs-box-shadow);
}



.nxs-center-content-vertically {
    display: flex;
    flex-direction: column;
    justify-content: center;
    
    height: 100%;
}

.nxs-center-content-horizontally {
    margin: auto;
}

.nxs-row-flex {
    display: flex;
    flex-direction: row;
    column-gap: 1em;
}

/* ----- Anemometer Diagram ----- */

.AnemometerDiagram {
    display: grid;
    width: 34em;
    grid-template-rows: 2em 32em;
    align-content: center;
}

.AnemometerDiagram-row {
    display: grid;
    grid-template-columns: 32em 2em;
    align-items: center;
}

/* ------------------------------ */


/* -------- Renderer CSS -------- */

.center-in-container {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

.part-listbox {
    position: absolute;
    margin-left: 1em;
    margin-top: 1em;
    
    max-height: calc(100% - 2.5em) !important;
}



/* ------------------------------ */


.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--nxs-success);
}

.invalid {
    outline: 1px solid var(--nxs-danger);
}

.italic {
    font-style: italic;
}

.validation-message {
    color: var(--nxs-danger);
}

.fill-splitter-pane {
    height: 100% !important;
}

.file-input-zone {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--nxs-accent);
    color: black;
    border-color: black;
    cursor: pointer;
    position: relative;
    text-transform: uppercase;
    font-weight: 500;
    padding-block: 8px;
    padding-inline: 18px;
    font-size: 14px;
    line-height: 1.4285714286;
    box-sizing: border-box;
    border-width: 1px;
    border-style: solid;
    gap: 8px;
    border-radius: var(--nxs-radius-sm);
}

    .file-input-zone:hover {
        background-color: var(--nxs-accent);
    }

    .file-input-zone input[type=file] {
        position: absolute;
        width: 100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
    }



/* --- Blazor Overrides --- */

.combo-box-input-text {
    display: inline-block;
    border: none;
    border-radius: var(--nxs-radius-sm) 0 0 var(--nxs-radius-sm);
}

.combo-box-input-text:focus {
    outline: none;
}

/* --- Measurement Grid Scrollbars (match home search style) --- */

.measurement-grid-scroll {
    width: 100%;
    min-width: 0;
}

.measurement-grid-scroll .k-table,
.measurement-grid-scroll .k-grid-table {
    min-width: 100%;
}

.measurement-grid-scroll .k-grid-content,
.measurement-grid-scroll .k-grid-content-locked,
.measurement-grid-scroll .k-grid-header-wrap,
.measurement-grid-scroll .k-grid-footer-wrap,
.measurement-grid-scroll .k-scrollbar {
    scrollbar-color: var(--nxs-overlay-20) var(--nxs-surface);
}

.measurement-grid-scroll .k-grid-content::-webkit-scrollbar-track,
.measurement-grid-scroll .k-grid-content-locked::-webkit-scrollbar-track,
.measurement-grid-scroll .k-grid-header-wrap::-webkit-scrollbar-track,
.measurement-grid-scroll .k-grid-footer-wrap::-webkit-scrollbar-track,
.measurement-grid-scroll .k-scrollbar::-webkit-scrollbar-track {
    background-color: var(--nxs-surface);
}

.measurement-grid-scroll .k-grid-content::-webkit-scrollbar-corner,
.measurement-grid-scroll .k-grid-content-locked::-webkit-scrollbar-corner,
.measurement-grid-scroll .k-grid-header-wrap::-webkit-scrollbar-corner,
.measurement-grid-scroll .k-grid-footer-wrap::-webkit-scrollbar-corner,
.measurement-grid-scroll .k-scrollbar::-webkit-scrollbar-corner {
    background-color: var(--nxs-surface);
}


/* For japanese localization font override */
.lang-ja {
    --bs-font-sans-serif: "Roboto", "Noto Sans JP", sans-serif;
}

.lang-ja,
.lang-ja body,
.lang-ja button,
.lang-ja input,
.lang-ja select,
.lang-ja textarea,
.lang-ja .mud-typography,
.lang-ja .k-widget {
    font-family: "Roboto", "Noto Sans JP", sans-serif !important;
}

/* --- App shell chrome (MudAppBar/MudDrawer are component roots, so scoped
       ::deep rules from MainLayout.razor.css cannot reach them) --- */

.mud-appbar.app-header {
    border-bottom: 1px solid var(--nxs-border);
}

.mud-drawer.app-nav-drawer {
    border-right: 1px solid var(--nxs-border);
}

/* Confine scrolling to the content area below the fixed app bar. The layout fills the viewport;
   main-content fills the layout and keeps MudBlazor's app-bar-height top padding but does NOT
   scroll itself — the inner article (article.content, a plain element that already sits below the
   bar) is the scroll container. So its scrollbar spans only from the bar's bottom edge down. */
.mud-layout {
    height: 100vh;
}

.mud-main-content {
    height: 100%;
    box-sizing: border-box;
    overflow: hidden;
}
