/* ==========================================================================
   THERMONOM cloud portal — design system
   Companion to ThermonomTheme.cs. The theme owns MudBlazor's palette and
   typography; this file owns the things a MudTheme cannot express: webfonts,
   the chrome (primary rail + white app bar), borders-instead-of-shadows, and
   the handful of components the redesign introduces (band bar, channel tile,
   status pill, readout, channel strip).

   Every colour here resolves through --mud-palette-*, so the manual dark-mode
   toggle switches this file for free. The six status hues ride MudBlazor's own
   slots:  success = at setpoint · warning = warning · error = alarm
           info    = ramping     · tertiary = held  · gray-default = off
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Webfonts — self-hosted. No Google Fonts CDN: this portal serves German
      customers and a CDN font request hands the visitor's IP to a third party.
   -------------------------------------------------------------------------- */

/* Oswald ships in the repo. Same file as the legacy 'thermonom' face in
   app.css, under the name the theme asks for. Variable weight 200–700. */
@font-face {
    font-family: 'Oswald';
    src: url('Fonts/Oswald-VariableFont_wght.ttf') format('truetype');
    font-weight: 200 700;
    font-style: normal;
    font-display: swap;
}

/* Open Sans is NOT in the repo yet. Drop OpenSans-Variable.woff2 into
   wwwroot/Fonts and uncomment this block to get the real face; until then the
   stack in ThermonomTheme.Ui falls through to Segoe UI / system-ui, which is
   also what the portal renders today (Montserrat was named in the old theme
   but never actually loaded). Left commented so there is no 404 per page load.

@font-face {
    font-family: 'Open Sans';
    src: url('Fonts/OpenSans-Variable.woff2') format('woff2-variations');
    font-weight: 300 800;
    font-style: normal;
    font-display: swap;
}
*/

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
    /* -- surfaces & ink: aliases so component CSS never reaches for a hex -- */
    --tn-canvas: var(--mud-palette-background);
    --tn-surface: var(--mud-palette-surface);
    --tn-sunken: var(--mud-palette-background-gray);
    --tn-line: var(--mud-palette-lines-default);
    --tn-line-strong: var(--mud-palette-lines-inputs);
    --tn-line-light: var(--mud-palette-divider-light);
    --tn-ink: var(--mud-palette-text-primary);
    --tn-ink-muted: var(--mud-palette-text-secondary);

    /* -- brand -- */
    --tn-primary: var(--mud-palette-primary);
    --tn-accent: var(--mud-palette-info);

    /* The locked primary as a literal, for the few places that sit on a surface which is
       white in BOTH themes (highlight blocks inside the hero). --tn-primary is the palette
       value and deliberately lightens in dark mode, which would fail there. */
    --tn-primary-fixed: #095776;
    --tn-alarm-fixed: #C62828;

    /* A large brand-coloured SURFACE — the hero band, the LIVE badge. This must not use
       --mud-palette-primary: in dark mode that is the lightened #3FA9D1 intended for text and
       buttons, and painting a whole band with it produces a glaring cyan slab. Derived from
       the drawer background so it tracks the theme: #095776 in light, a deep brand blue in
       dark that still reads as a surface against the near-black canvas. */
    --tn-brand-surface: #095776;
    --tn-brand-surface: color-mix(in srgb, var(--mud-palette-drawer-background) 70%, var(--mud-palette-primary));

    /* Text on that surface — one value that clears 5:1 against both variants. */
    --tn-on-brand: #C3D8E2;
    --tn-on-brand-line: rgba(255, 255, 255, .16);
    /* Signal yellow is a fixed brand value in both themes. Brand only — never a
       status, because amber already means warning. Only used on the primary
       surface, exactly as on thermonom.de. */
    --tn-signal: #F3FF3B;

    /* -- the six status hues -- */
    --tn-ok: var(--mud-palette-success);
    --tn-warn: var(--mud-palette-warning);
    --tn-alarm: var(--mud-palette-error);
    --tn-ramp: var(--mud-palette-info);
    --tn-held: var(--mud-palette-tertiary);
    --tn-off: var(--mud-palette-gray-default);

    /* -- status tints. Hex first as a fallback, then mixed against the live
          surface so light and dark both get a correct tint from one rule. -- */
    --tn-ok-bg: #E7F5ED;
    --tn-ok-bg: color-mix(in srgb, var(--tn-ok) 12%, var(--tn-surface));
    --tn-warn-bg: #FBF0DF;
    --tn-warn-bg: color-mix(in srgb, var(--tn-warn) 14%, var(--tn-surface));
    --tn-alarm-bg: #FBEAEA;
    --tn-alarm-bg: color-mix(in srgb, var(--tn-alarm) 12%, var(--tn-surface));
    --tn-ramp-bg: #E4F1F7;
    --tn-ramp-bg: color-mix(in srgb, var(--tn-ramp) 12%, var(--tn-surface));
    --tn-held-bg: #EFEDF8;
    --tn-held-bg: color-mix(in srgb, var(--tn-held) 12%, var(--tn-surface));
    --tn-off-bg: #EDF1F3;
    --tn-off-bg: color-mix(in srgb, var(--tn-off) 14%, var(--tn-surface));

    /* An alarming card gets a barely-there wash, not a red block. */
    --tn-alarm-wash: #FEF7F7;
    --tn-alarm-wash: color-mix(in srgb, var(--tn-alarm) 5%, var(--tn-surface));
    --tn-alarm-edge: #F0C9C9;
    --tn-alarm-edge: color-mix(in srgb, var(--tn-alarm) 28%, var(--tn-surface));

    /* -- the rail, derived from whatever the drawer background currently is -- */
    --tn-rail: var(--mud-palette-drawer-background);
    --tn-rail-text: var(--mud-palette-drawer-text);
    --tn-rail-selected: #0A6A8F;
    --tn-rail-selected: color-mix(in srgb, #fff 13%, var(--tn-rail));
    --tn-rail-line: #1D6A8D;
    --tn-rail-line: color-mix(in srgb, #fff 17%, var(--tn-rail));
    --tn-rail-meta: #B8CEDA;
    --tn-rail-meta: color-mix(in srgb, var(--tn-rail-text) 82%, #fff);

    /* -- geometry: 4px cards, 2px chips. The marketing site is square; 4px
          keeps the corner honest without going brutalist. -- */
    --tn-radius: var(--mud-default-borderradius);
    --tn-radius-chip: 2px;
    --tn-space: 4px;

    /* Shadows are for things that float, nothing else. */
    --tn-shadow-float: 0 10px 28px -10px rgba(9, 87, 118, .34);
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */

/* Was hard-coded to Helvetica Neue in app.css, which quietly beat the theme
   for every element MudBlazor does not type itself. */
html, body {
    font-family: var(--mud-typography-default-family);
}

body {
    background-color: var(--tn-canvas);
}

/* Numbers that refresh every second must not jitter. */
.tn-num,
.mud-table-cell,
.mud-datagrid .mud-table-cell,
.mud-input-slot,
.mud-input > input {
    font-variant-numeric: tabular-nums;
}

/* Condensed headline face, for readouts that are not headings. */
.tn-osw {
    font-family: var(--mud-typography-h4-family);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.01em;
}

/* --------------------------------------------------------------------------
   4. Borders, not shadows

   Elevation 1–15 scattered through the Razor is what makes the portal look
   soft; a hairline grid holds a 48-channel screen together far better. Only
   things that genuinely float above the page keep a shadow.
   -------------------------------------------------------------------------- */

.mud-paper:not(.mud-popover):not(.mud-dialog):not(.mud-tooltip):not(.mud-snackbar):not(.mud-menu-popover) {
    box-shadow: none;
    border: 1px solid var(--tn-line);
}

/* Elevation 0 means "no chrome at all" — respect that. */
.mud-paper.mud-elevation-0 {
    border: 0;
}

.mud-popover, .mud-dialog {
    box-shadow: var(--tn-shadow-float);
}

/* --------------------------------------------------------------------------
   5. Chrome — white app bar, primary rail
   -------------------------------------------------------------------------- */

.mud-appbar {
    box-shadow: none;
    border-bottom: 1px solid var(--tn-line);
}

/* The app bar used to be primary-filled, so the account avatar was set to
   Color.Secondary (white) with primary initials. On a white bar that would
   vanish — invert it here rather than touching 37 Color.Secondary call sites. */
.mud-appbar .mud-avatar.mud-avatar-filled-secondary,
.mud-appbar .mud-avatar.mud-avatar-secondary {
    background-color: var(--tn-primary);
    color: var(--mud-palette-primary-text);
}

.mud-appbar .mud-avatar .mud-typography {
    color: var(--mud-palette-primary-text) !important;
}

.mud-drawer {
    box-shadow: none;
    border-inline-end: 0;
}

/* Rail items. MudNavMenu is rendered with Color.Primary, which paints the
   active item primary-on-primary — invisible once the drawer carries the brand
   colour. Selected sits one step lighter than the rail so it reads as raised,
   and picks up the signal-yellow marker from the mockups. */
.mud-drawer .mud-navmenu .mud-nav-link {
    color: var(--tn-rail-text);
    border-radius: 0;
    position: relative;
    font-weight: 600;
}

.mud-drawer .mud-navmenu .mud-nav-link:hover:not(.mud-nav-link-disabled) {
    background-color: var(--tn-rail-selected);
    color: #fff;
}

.mud-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
    background-color: var(--tn-rail-selected);
    color: #fff;
}

.mud-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled)::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--tn-signal);
}

/* Only the *uncoloured* icon follows the link's text colour. Icons the Razor
   colours per device state (Success / Error) carry .mud-{color}-text and are
   left alone — they are the whole point of the device list in the rail. */
.mud-drawer .mud-navmenu .mud-nav-link.active .mud-nav-link-icon.mud-nav-link-icon-default {
    color: #fff;
}

/* Dividers and the footer links in the drawer were mud-text-primary — also
   primary-on-primary. */
.mud-drawer .mud-divider {
    border-color: var(--tn-rail-line);
}

.mud-drawer a.mud-typography,
.mud-drawer .mud-link,
.mud-drawer a.mud-text-primary {
    color: var(--tn-rail-meta) !important;
}

.mud-drawer a.mud-typography:hover,
.mud-drawer .mud-link:hover {
    color: #fff !important;
}

.mud-drawer .mud-text-secondary,
.mud-drawer .mud-typography-caption {
    color: var(--tn-rail-meta) !important;
}

/* --------------------------------------------------------------------------
   6. Focus & selection
   -------------------------------------------------------------------------- */

:where(a, button, .mud-button-root, .mud-input-control):focus-visible {
    outline: 2px solid var(--tn-accent);
    outline-offset: 2px;
}

::selection {
    background: var(--tn-ramp-bg);
}

/* --------------------------------------------------------------------------
   7. Data density
   -------------------------------------------------------------------------- */

.mud-table-container .mud-table-head .mud-table-cell,
.mud-datagrid .mud-table-head .mud-table-cell {
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    background-color: var(--tn-sunken);
}

.mud-table-row:hover .mud-table-cell {
    background-color: var(--mud-palette-table-hover);
}

/* --------------------------------------------------------------------------
   8. Components introduced by the redesign

   Each is markup-light on purpose: a Razor component sets one class plus
   data-tn-state, and everything else follows from tokens.
   -------------------------------------------------------------------------- */

/* -- state contract ------------------------------------------------------- */
[data-tn-state] { --tn-state: var(--tn-off); --tn-state-bg: var(--tn-off-bg); }
[data-tn-state="ok"] { --tn-state: var(--tn-ok); --tn-state-bg: var(--tn-ok-bg); }
[data-tn-state="warn"] { --tn-state: var(--tn-warn); --tn-state-bg: var(--tn-warn-bg); }
[data-tn-state="alarm"] { --tn-state: var(--tn-alarm); --tn-state-bg: var(--tn-alarm-bg); }
[data-tn-state="ramp"] { --tn-state: var(--tn-ramp); --tn-state-bg: var(--tn-ramp-bg); }
[data-tn-state="held"] { --tn-state: var(--tn-held); --tn-state-bg: var(--tn-held-bg); }
[data-tn-state="off"] { --tn-state: var(--tn-off); --tn-state-bg: var(--tn-off-bg); }

/* -- eyebrow label -------------------------------------------------------- */
.tn-eyebrow {
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* -- status pill ---------------------------------------------------------- */
.tn-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px;
    border-radius: var(--tn-radius-chip);
    font-size: .719rem;
    font-weight: 700;
    line-height: 1.4;
    white-space: nowrap;
    background: var(--tn-state-bg);
    color: var(--tn-state);
}

.tn-pill--solid {
    background: var(--tn-state);
    color: var(--tn-surface);
}

/* -- status dot ----------------------------------------------------------- */
.tn-dot {
    inline-size: 7px;
    block-size: 7px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: var(--tn-state);
}

.tn-dot--lg { inline-size: 9px; block-size: 9px; }

/* -- numeric readout ------------------------------------------------------ */
.tn-readout {
    font-family: var(--mud-typography-h4-family);
    font-weight: 400;
    font-size: 1.9375rem;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--tn-ink);
}

.tn-readout--xl { font-size: 2.75rem; }
.tn-readout--sm { font-size: 1.25rem; }
.tn-readout--state { color: var(--tn-state); }

.tn-readout-unit {
    font-family: var(--mud-typography-default-family);
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

/* -- band bar -------------------------------------------------------------
   The one new component the redesign leans on. Draws warnLow / warnHigh /
   alarmAbs from TempSettings as a track and puts the actual value on it, so
   deviation becomes a shape instead of arithmetic.

   Callers set four percentages inline:
     --band-lo   warnLow      position
     --band-hi   warnHigh     position
     --band-set  setpoint     position
     --band-at   actual value position
   ------------------------------------------------------------------------- */
.tn-band {
    position: relative;
    block-size: 8px;
    background: var(--tn-sunken);
    border-radius: 1px;
    --band-lo: 24%;
    --band-hi: 76%;
    --band-set: 50%;
    --band-at: 50%;
}

/* the in-band window */
.tn-band::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: var(--band-lo);
    inline-size: calc(var(--band-hi) - var(--band-lo));
    background: var(--tn-ok-bg);
}

/* the setpoint tick */
.tn-band::after {
    content: "";
    position: absolute;
    inset-inline-start: var(--band-set);
    inset-block: -3px;
    inline-size: 1px;
    background: var(--tn-off);
}

/* the actual-value marker, coloured by the channel's state */
.tn-band > .tn-band-at {
    position: absolute;
    inset-inline-start: var(--band-at);
    inset-block: -4px;
    inline-size: 4px;
    transform: translateX(-2px);
    border-radius: 1px;
    background: var(--tn-state);
}

/* optional alarm-threshold tick */
.tn-band > .tn-band-alarm {
    position: absolute;
    inset-inline-start: var(--band-alarm, 100%);
    inset-block: 0;
    inline-size: 1px;
    background: var(--tn-alarm);
}

.tn-band--lg { block-size: 12px; }
.tn-band--sm { block-size: 5px; }

/* No setpoint, nothing to show: a flat track that reads as "not in play". */
.tn-band--empty { background: var(--tn-line-light); }
.tn-band--empty::before,
.tn-band--empty::after { content: none; }

.tn-band-scale {
    display: flex;
    justify-content: space-between;
    font-size: .656rem;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

/* -- power meter ---------------------------------------------------------- */
.tn-meter {
    position: relative;
    block-size: 4px;
    flex: 1;
    background: var(--tn-sunken);
    border-radius: 2px;
    overflow: hidden;
}

.tn-meter > i {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    inline-size: var(--meter, 0%);
    background: var(--tn-state);
    display: block;
}

/* -- channel tile --------------------------------------------------------- */
.tn-tile {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 10px 12px;
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-inline-start: 3px solid var(--tn-state);
    border-radius: var(--tn-radius);
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}

.tn-tile:hover {
    background: var(--mud-palette-table-hover);
}

.tn-tile[data-tn-state="alarm"] {
    background: var(--tn-alarm-wash);
    box-shadow: 0 0 0 1px var(--tn-alarm-edge);
}

/* Disabled / unused channels: present but visibly not in play. */
.tn-tile[data-tn-state="off"] {
    border-style: dashed;
    border-inline-start-style: solid;
}

.tn-tile-no {
    font-size: .656rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    padding: 1px 5px;
    border-radius: var(--tn-radius-chip);
    background: var(--tn-sunken);
    color: var(--mud-palette-text-secondary);
}

.tn-tile-name {
    font-size: .781rem;
    font-weight: 600;
    color: var(--tn-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* -- channel strip: one bar per channel, for the fleet list --------------- */
.tn-strip {
    display: flex;
    gap: 2px;
    align-items: flex-end;
}

.tn-strip > i {
    inline-size: 5px;
    block-size: 20px;
    flex: 0 0 auto;
    display: block;
    background: var(--tn-state);
}

.tn-strip--sm > i { inline-size: 4px; block-size: 16px; }
.tn-strip--offline { opacity: .4; }

/* -- LIVE badge: the one place signal yellow appears in the content area,
      and only ever on the primary surface. --------------------------------- */
.tn-live {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px;
    border-radius: var(--tn-radius-chip);
    background: var(--tn-brand-surface);
}

.tn-live > .tn-live-dot {
    inline-size: 6px;
    block-size: 6px;
    border-radius: 50%;
    background: var(--tn-signal);
}

.tn-live > .tn-live-text {
    font-size: .625rem;
    font-weight: 800;
    letter-spacing: .1em;
    color: var(--tn-signal);
}

/* --------------------------------------------------------------------------
   9. The shell — rail, top bar, alarm bell

   The drawer runs full height with ClipMode.Never, so MudBlazor offsets the app
   bar by --mud-drawer-width-left for us; the bar only ever spans the content.
   -------------------------------------------------------------------------- */

.tn-rail .mud-drawer-content {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.tn-rail-brand {
    padding: 20px 16px 22px;
    flex: 0 0 auto;
}

.tn-rail-wordmark {
    display: block;
    inline-size: 150px;
    max-inline-size: 100%;
}

.tn-rail-product {
    margin-block-start: 7px;
    font-size: .625rem;
    letter-spacing: .22em;
    color: var(--tn-rail-meta);
}

.tn-rail-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.tn-rail-body > .mud-navmenu {
    flex: 0 0 auto;
}

/* The device list is the only part that scrolls: grow 0 so a short list takes just the
   room it needs, shrink 1 so a long one gives way instead of pushing Recipes and
   Downloads off the bottom. */
.tn-rail-devices {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--tn-rail-selected) transparent;
}

.tn-rail-devices::-webkit-scrollbar { inline-size: 6px; }
.tn-rail-devices::-webkit-scrollbar-track { background: transparent; }

.tn-rail-devices::-webkit-scrollbar-thumb {
    background: var(--tn-rail-selected);
    border-radius: 3px;
}

/* Device rows sit one level in from their section header. */
.tn-rail-devices .mud-nav-link {
    padding-inline-start: 40px;
    font-weight: 500;
}

.tn-rail-foot {
    margin-block-start: auto;
    padding: 16px;
    border-block-start: 1px solid var(--tn-rail-line);
    display: flex;
    flex-direction: column;
    gap: 5px;
    flex: 0 0 auto;
}

.tn-rail-note {
    font-size: .688rem;
    color: var(--tn-rail-meta);
}

.tn-rail-links {
    display: flex;
    gap: 14px;
}

/* Group header: title plus the fleet-wide alarm count. */
.tn-rail-group {
    display: flex;
    align-items: center;
    gap: 9px;
    inline-size: 100%;
}

.tn-rail-badge {
    margin-inline-start: auto;
    background: var(--tn-alarm);
    color: #fff;
    font-size: .625rem;
    font-weight: 800;
    border-radius: 9px;
    padding: 1px 7px;
    font-variant-numeric: tabular-nums;
}

/* A device row in the rail: status dot then name. */
.tn-rail-device {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
}

.tn-rail-device-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* -- top bar ------------------------------------------------------------- */

.tn-appbar .mud-toolbar {
    gap: 6px;
}

.tn-appbar-title {
    font-family: var(--mud-typography-h5-family);
    font-size: var(--mud-typography-h5-size);
    font-weight: var(--mud-typography-h5-weight);
    letter-spacing: var(--mud-typography-h5-letterspacing);
    color: var(--mud-palette-appbar-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-bell {
    position: relative;
    inline-size: 40px;
    block-size: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-radius: 50%;
}

.tn-bell:hover {
    background: var(--mud-palette-action-default-hover);
}

.tn-bell-count {
    position: absolute;
    top: 4px;
    inset-inline-end: 3px;
    background: var(--tn-alarm);
    color: #fff;
    font-size: .563rem;
    font-weight: 800;
    line-height: 14px;
    min-inline-size: 14px;
    text-align: center;
    border-radius: 8px;
    padding: 0 4px;
    font-variant-numeric: tabular-nums;
}

.tn-alarm-menu {
    min-inline-size: 320px;
}

.tn-alarm-head {
    padding: 10px 16px;
    border-block-end: 1px solid var(--tn-line);
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-alarm-empty {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 14px 16px;
    font-size: .813rem;
    color: var(--mud-palette-text-secondary);
}

.tn-alarm-row {
    display: flex;
    align-items: center;
    gap: 11px;
    min-width: 0;
}

.tn-alarm-text { min-width: 0; }

.tn-alarm-name {
    font-size: .813rem;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-alarm-detail {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* -- account ------------------------------------------------------------- */

.tn-account { cursor: pointer; display: flex; align-items: center; }

.tn-avatar {
    inline-size: 32px;
    block-size: 32px;
    border-radius: 50%;
    background: var(--tn-primary);
    color: var(--mud-palette-primary-text);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .813rem;
    font-weight: 700;
}

.tn-avatar--anon {
    background: var(--tn-sunken);
    color: var(--mud-palette-text-secondary);
}

/* -- content ------------------------------------------------------------- */

.tn-main {
    background: var(--tn-canvas);
    min-height: 100vh;
}

.tn-page {
    padding: 20px 24px 32px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

@media (max-width: 600px) {
    .tn-page { padding: 14px 12px 24px; }
}

/* --------------------------------------------------------------------------
   10. Page furniture — sections, panels, hero, tiles
   -------------------------------------------------------------------------- */

.tn-section { display: flex; flex-direction: column; gap: 10px; }

.tn-section-head,
.tn-panel-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.tn-section-title,
.tn-panel-title {
    font-family: var(--mud-typography-h6-family);
    font-size: .938rem;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.tn-panel {
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.tn-panel-head {
    padding: 12px 16px;
    border-block-end: 1px solid var(--tn-line);
    background: var(--mud-palette-table-striped);
}

.tn-panel-foot {
    margin-block-start: auto;
    padding: 14px 16px;
    border-block-start: 1px solid var(--tn-line-light);
    background: var(--mud-palette-table-striped);
    display: flex;
    align-items: center;
    gap: 11px;
    font-size: .813rem;
    color: var(--tn-ink-muted);
}

.tn-two-col {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: 16px;
    align-items: stretch;
}

@media (max-width: 1100px) {
    .tn-two-col { grid-template-columns: minmax(0, 1fr); }
}

/* -- hero ---------------------------------------------------------------- */

.tn-hero {
    background: var(--tn-brand-surface);
    border-radius: var(--tn-radius);
    display: flex;
    align-items: stretch;
    overflow: hidden;
    flex-wrap: wrap;
}

.tn-hero-main {
    flex: 1 1 420px;
    padding: 22px 26px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    min-width: 0;
}

.tn-hero-greeting { font-size: .813rem; color: var(--tn-on-brand); }

.tn-hero-head {
    font-family: var(--mud-typography-h3-family);
    font-size: 1.75rem;
    font-weight: 300;
    line-height: 1.18;
    letter-spacing: -.01em;
    color: #fff;
}

/* Highlight blocks sit on the primary field, so they are white with coloured text —
   a cyan block would not separate from the surface behind it. */
.tn-hero-mark {
    background: #fff;
    color: var(--tn-primary-fixed);
    padding: 0 9px;
    white-space: nowrap;
}

.tn-hero-mark--alarm { color: var(--tn-alarm-fixed); }

.tn-hero-sub { font-size: .875rem; color: var(--tn-on-brand); }

.tn-hero-actions { display: flex; gap: 9px; margin-block-start: 6px; flex-wrap: wrap; }

.tn-hero-ghost {
    color: #fff !important;
    border-color: color-mix(in srgb, #fff 34%, transparent) !important;
}

.tn-hero-stats {
    display: flex;
    align-items: center;
    border-inline-start: 1px solid var(--tn-on-brand-line);
    flex-wrap: wrap;
}

.tn-hero-stat {
    padding: 20px 26px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: end;
    border-inline-start: 1px solid var(--tn-on-brand-line);
}

.tn-hero-stat:first-child { border-inline-start: 0; }

.tn-hero-stat-value {
    font-family: var(--mud-typography-h3-family);
    font-size: 2.25rem;
    font-weight: 300;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}

.tn-hero-stat-value--signal { color: var(--tn-signal); }

.tn-hero-stat-label {
    font-size: .688rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--tn-on-brand);
}

.tn-hero--public .tn-hero-head { font-size: 2rem; }

/* -- mini device cards --------------------------------------------------- */

.tn-mini-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 14px;
}

.tn-mini-grid--public { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

.tn-mini {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 13px 14px;
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-block-start: 3px solid var(--tn-state);
    border-radius: var(--tn-radius);
    text-decoration: none;
    color: inherit;
}

.tn-mini:hover { background: var(--mud-palette-table-hover); }

.tn-mini-head { display: flex; align-items: center; gap: 9px; min-width: 0; }

.tn-mini-name {
    font-family: var(--mud-typography-h6-family);
    font-size: 1.063rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-mini-head > .tn-pill { margin-inline-start: auto; }

.tn-mini-meta { font-size: .719rem; color: var(--mud-palette-text-secondary); }

/* -- public tile --------------------------------------------------------- */

.tn-tile-public {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 22px;
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    background: var(--tn-surface);
    min-block-size: 230px;
}

.tn-tile-public-icon {
    inline-size: 42px;
    block-size: 42px;
    border-radius: var(--tn-radius);
    background: var(--tn-ramp-bg);
    display: flex;
    align-items: center;
    justify-content: center;
}

.tn-tile-public-title {
    font-family: var(--mud-typography-h5-family);
    font-size: 1.25rem;
    font-weight: 500;
}

.tn-tile-public-body { font-size: .813rem; color: var(--tn-ink-muted); line-height: 1.55; }

/* -- event rows ---------------------------------------------------------- */

.tn-event-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .813rem;
    min-width: 0;
}

.tn-event-row:last-child { border-block-end: 0; }

.tn-event-time { flex: 0 0 auto; color: var(--mud-palette-text-secondary); }

.tn-event-msg {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-src {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    max-inline-size: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .719rem;
    font-weight: 600;
    color: var(--tn-primary);
    background: var(--tn-ramp-bg);
    border-radius: var(--tn-radius-chip);
    padding: 2px 7px;
    text-decoration: none;
    font-variant-numeric: tabular-nums;
}

.tn-pill--muted { background: var(--tn-off-bg); color: var(--mud-palette-text-secondary); }

/* -- utility rows, empty states ------------------------------------------ */

.tn-utility {
    display: flex;
    gap: 13px;
    padding: 14px 16px;
    border-block-end: 1px solid var(--tn-line-light);
}

.tn-utility:last-of-type { border-block-end: 0; }

.tn-utility-icon {
    inline-size: 32px;
    block-size: 32px;
    flex: 0 0 auto;
    background: var(--tn-ramp-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--tn-radius-chip);
}

.tn-utility-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tn-utility-title { font-size: .844rem; font-weight: 700; }
.tn-utility-body { font-size: .75rem; color: var(--mud-palette-text-secondary); line-height: 1.45; }

.tn-empty {
    border: 1px dashed var(--tn-line-strong);
    border-radius: var(--tn-radius);
    background: var(--mud-palette-table-striped);
    padding: 30px 26px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    max-inline-size: 640px;
}

.tn-empty-title { font-size: .938rem; font-weight: 700; }
.tn-empty-body { font-size: .813rem; color: var(--tn-ink-muted); line-height: 1.55; }

.tn-empty-line {
    padding: 22px 16px;
    text-align: center;
    font-size: .813rem;
    color: var(--mud-palette-text-secondary);
}

/* --------------------------------------------------------------------------
   11. Fleet — toolbar, banner, KPIs, device cards, table
   -------------------------------------------------------------------------- */

.tn-skeleton-stack { display: flex; flex-direction: column; gap: 14px; }

.tn-toolbar {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.tn-toolbar-meta { font-size: .813rem; color: var(--tn-ink-muted); }

.tn-toolbar-actions {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* Segmented control — density / view switches. */
.tn-segment {
    display: inline-flex;
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    overflow: hidden;
    background: var(--tn-surface);
}

.tn-segment button {
    appearance: none;
    border: 0;
    border-inline-start: 1px solid var(--tn-line);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    padding: 7px 11px;
    font: inherit;
    font-size: .781rem;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.tn-segment button:first-child { border-inline-start: 0; }
.tn-segment button:hover { background: var(--mud-palette-table-hover); }

.tn-segment button.on {
    background: var(--tn-primary);
    color: var(--mud-palette-primary-text);
}

/* -- alarm banner -------------------------------------------------------- */

.tn-banner {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 12px 16px;
    border-radius: var(--tn-radius);
    background: var(--tn-state-bg);
    border: 1px solid var(--tn-line);
    border-inline-start: 3px solid var(--tn-state);
    color: var(--tn-state);
}

.tn-banner-text { flex: 1 1 auto; min-width: 0; }
.tn-banner-title { font-size: .813rem; font-weight: 700; }

.tn-banner-detail {
    font-size: .75rem;
    opacity: .82;
    font-variant-numeric: tabular-nums;
}

/* -- KPI strip ----------------------------------------------------------- */

.tn-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px;
}

.tn-kpi {
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.tn-kpi--alarm {
    background: var(--tn-alarm-wash);
    border-color: var(--tn-alarm-edge);
}

.tn-kpi-label {
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-kpi-value {
    display: flex;
    align-items: baseline;
    gap: 7px;
    font-family: var(--mud-typography-h4-family);
    font-size: 1.875rem;
    font-weight: 400;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}

.tn-kpi-value small {
    font-family: var(--mud-typography-default-family);
    font-size: .875rem;
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
}

.tn-kpi-note { font-size: .75rem; color: var(--mud-palette-text-secondary); }

/* -- device cards -------------------------------------------------------- */

.tn-device-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
    gap: 14px;
}

@media (max-width: 900px) {
    .tn-device-grid { grid-template-columns: minmax(0, 1fr); }
}

.tn-device {
    display: flex;
    flex-direction: column;
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    overflow: hidden;
}

.tn-device[data-tn-state="alarm"] {
    border-color: var(--tn-alarm-edge);
    background: var(--tn-alarm-wash);
}

.tn-device-top {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px 14px 12px 18px;
}

.tn-device-id { flex: 1 1 auto; min-width: 0; }

.tn-device-name-row { display: flex; align-items: center; gap: 9px; min-width: 0; }

.tn-device-name {
    font-family: var(--mud-typography-h5-family);
    font-size: 1.313rem;
    font-weight: 500;
    line-height: 1.15;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-device-serial {
    padding-inline-start: 18px;
    font-size: .719rem;
    letter-spacing: .04em;
    color: var(--mud-palette-text-secondary);
}

.tn-device-body {
    padding: 0 18px 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.tn-device-strip { display: flex; flex-direction: column; gap: 7px; }

.tn-device-counts { font-size: .719rem; color: var(--mud-palette-text-secondary); }

.tn-device-note { font-size: .813rem; color: var(--mud-palette-text-secondary); }

.tn-device-stats { display: flex; gap: 26px; flex-wrap: wrap; }

.tn-kv { display: flex; flex-direction: column; gap: 1px; }

.tn-kv-k {
    font-size: .656rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-kv-v { font-size: .813rem; font-weight: 600; font-variant-numeric: tabular-nums; }

.tn-device-foot {
    margin-block-start: auto;
    border-block-start: 1px solid var(--tn-line-light);
    display: flex;
}

.tn-device-foot a {
    flex: 1;
    text-align: center;
    padding: 10px 0;
    font-size: .75rem;
    font-weight: 600;
    color: var(--tn-primary);
    border-inline-end: 1px solid var(--tn-line-light);
    text-decoration: none;
}

.tn-device-foot a:last-child { border-inline-end: 0; }
.tn-device-foot a:hover { background: var(--mud-palette-table-hover); }

/* -- plain table view ---------------------------------------------------- */

.tn-table { display: flex; flex-direction: column; overflow-x: auto; }

.tn-table-row {
    display: grid;
    grid-template-columns: minmax(140px, 1.4fr) minmax(120px, 1fr) 130px minmax(120px, 1fr) 90px 90px 120px 44px;
    gap: 12px;
    align-items: center;
    padding: 9px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .813rem;
    min-inline-size: 900px;
}

.tn-table-row:last-child { border-block-end: 0; }
.tn-table-row:hover { background: var(--mud-palette-table-hover); }

.tn-table-head {
    background: var(--tn-sunken);
    border-block-end: 1px solid var(--tn-line);
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-table-head:hover { background: var(--tn-sunken); }

.tn-table-row[data-tn-state="alarm"] { background: var(--tn-alarm-wash); }

.tn-table-link { font-weight: 600; color: var(--tn-ink); text-decoration: none; }
.tn-table-link:hover { color: var(--tn-primary); }

.ta-end { text-align: end; }
.tn-muted { color: var(--mud-palette-text-secondary); }

/* --------------------------------------------------------------------------
   12. Device page — header, tabs, filters, vitals, channel grid
   -------------------------------------------------------------------------- */

.tn-device-header {
    display: flex;
    align-items: stretch;
    gap: 12px;
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    flex-wrap: wrap;
}

.tn-device-header[data-tn-state="alarm"] {
    border-color: var(--tn-alarm-edge);
    background: var(--tn-alarm-wash);
}

.tn-device-header-main {
    flex: 1 1 420px;
    padding: 15px 20px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    min-width: 0;
}

.tn-device-header-row {
    display: flex;
    align-items: center;
    gap: 11px;
    flex-wrap: wrap;
}

.tn-device-header-meta { font-size: .75rem; color: var(--mud-palette-text-secondary); }

.tn-device-header-actions {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 0 20px;
    border-inline-start: 1px solid var(--tn-line-light);
}

@media (max-width: 800px) {
    .tn-device-header-actions {
        border-inline-start: 0;
        padding: 0 20px 14px;
    }
}

.tn-lamps { display: flex; gap: 14px; margin-inline-start: 6px; flex-wrap: wrap; }

.tn-lamp {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .781rem;
    color: var(--mud-palette-text-secondary);
}

.tn-lamp[data-tn-state="alarm"] { color: var(--tn-alarm); font-weight: 600; }

/* -- tabs ---------------------------------------------------------------- */

.tn-tabs {
    display: flex;
    align-items: center;
    border-block-end: 1px solid var(--tn-line);
    padding-inline: 8px;
    overflow-x: auto;
}

.tn-tab {
    padding: 11px 18px;
    font-size: .844rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    border-block-end: 2px solid transparent;
    text-decoration: none;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.tn-tab:hover { color: var(--tn-ink); }

.tn-tab.on {
    color: var(--tn-primary);
    border-block-end-color: var(--tn-primary);
}

.tn-tab-badge {
    background: var(--tn-alarm-bg);
    color: var(--tn-alarm);
    font-size: .625rem;
    font-weight: 800;
    border-radius: 9px;
    padding: 1px 6px;
    font-variant-numeric: tabular-nums;
}

.tn-tabs-right { margin-inline-start: auto; padding-inline-end: 8px; }

/* -- filter bar ---------------------------------------------------------- */

.tn-filterbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 14px;
    flex-wrap: wrap;
}

.tn-chip {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font: inherit;
    font-size: .75rem;
    font-weight: 600;
    padding: 5px 10px;
    border-radius: var(--tn-radius-chip);
    border: 1px solid var(--tn-line);
    background: var(--tn-surface);
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.tn-chip:hover { background: var(--mud-palette-table-hover); }

.tn-chip.on {
    background: var(--tn-primary);
    border-color: var(--tn-primary);
    color: var(--mud-palette-primary-text);
}

.tn-chip.on .tn-chip-count { opacity: .75; }

.tn-chip-count { font-variant-numeric: tabular-nums; }

.tn-filterbar-right { margin-inline-start: auto; }

.tn-search { inline-size: 230px; }
.tn-range-field { inline-size: 170px; }

/* -- vitals -------------------------------------------------------------- */

.tn-vitals {
    display: flex;
    align-items: stretch;
    background: var(--tn-surface);
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    padding: 12px 0;
    flex-wrap: wrap;
}

.tn-vital {
    padding: 0 20px;
    border-inline-end: 1px solid var(--tn-line-light);
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.tn-vital:last-child { border-inline-end: 0; }

.tn-vital-k {
    font-size: .656rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-vital-v {
    font-family: var(--mud-typography-h5-family);
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}

.tn-vital--boards { margin-inline-start: auto; border-inline-end: 0; }

.tn-boards { display: flex; gap: 5px; flex-wrap: wrap; margin-block-start: 2px; }

.tn-board {
    font-size: .688rem;
    font-weight: 700;
    border-radius: var(--tn-radius-chip);
    padding: 3px 7px;
    background: var(--tn-state-bg);
    color: var(--tn-state);
}

.tn-banner--quiet { color: var(--mud-palette-text-secondary); background: var(--mud-palette-table-striped); }

/* -- groups + channel grid ----------------------------------------------- */

.tn-group { display: flex; flex-direction: column; gap: 9px; }

.tn-group-head { display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap; }

.tn-group-title {
    font-family: var(--mud-typography-h6-family);
    font-size: .875rem;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.tn-group-meta { font-size: .75rem; color: var(--mud-palette-text-secondary); }

.tn-channel-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px;
}

.tn-channel-grid--compact { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

.tn-channel-grid--compact .tn-readout { font-size: 1.375rem; }
.tn-channel-grid--compact .tn-tile { gap: 7px; padding: 8px 10px; }
.tn-channel-grid--compact .tn-tile-meta { display: none; }

/* -- the tile ------------------------------------------------------------ */

.tn-tile-head { display: flex; align-items: center; gap: 7px; min-width: 0; }
.tn-tile-head > .tn-dot { margin-inline-start: auto; }

.tn-tile-value { display: flex; align-items: flex-end; gap: 6px; }

.tn-tile-target {
    margin-inline-start: auto;
    text-align: end;
    font-size: .688rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

.tn-tile-dev { font-weight: 700; }

.tn-tile-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .656rem;
    color: var(--mud-palette-text-secondary);
}

.tn-tile-state { font-weight: 700; white-space: nowrap; }

/* --------------------------------------------------------------------------
   13. The channel sheet — a dialog anchored to the right edge, so the rest of
       the channel grid stays visible behind it.
   -------------------------------------------------------------------------- */

/* Flush against the right edge — MudBlazor's container pads the dialog away from it. */
.mud-dialog-container.mud-dialog-centerright { padding: 0; }

.tn-sheet {
    max-inline-size: 940px !important;
    inline-size: 100%;
    block-size: 100vh;
    max-block-size: 100vh !important;
    margin: 0 !important;
    border-radius: 0 !important;
    display: flex;
    flex-direction: column;
}

.tn-sheet .mud-dialog-content {
    flex: 1 1 auto;
    overflow-y: auto;
    max-block-size: none;
}

.tn-sheet-title {
    padding: 14px 22px !important;
    border-block-end: 1px solid var(--tn-line);
}

.tn-sheet-head { display: flex; align-items: center; gap: 14px; }
.tn-sheet-nav { display: flex; gap: 4px; }
.tn-sheet-id { min-width: 0; flex: 1 1 auto; }
.tn-sheet-name-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.tn-sheet-name {
    font-family: var(--mud-typography-h5-family);
    font-size: 1.375rem;
    font-weight: 500;
}

.tn-sheet-sub { font-size: .75rem; color: var(--mud-palette-text-secondary); }
.tn-sheet-actions { display: flex; align-items: center; gap: 8px; margin-inline-start: auto; }

.tn-sheet-body {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 16px;
    padding: 16px 22px 22px;
    align-items: start;
}

@media (max-width: 1000px) {
    .tn-sheet-body { grid-template-columns: minmax(0, 1fr); }
}

.tn-sheet-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.tn-panel--pad { padding: 16px 18px; gap: 15px; }

.tn-panel--pad[data-tn-state="alarm"] {
    border-color: var(--tn-alarm-edge);
    background: var(--tn-alarm-wash);
}

.tn-readout-row { display: flex; gap: 8px; flex-wrap: wrap; }

.tn-ro { display: flex; flex-direction: column; gap: 2px; flex: 1 1 90px; }

.tn-ro-k {
    font-size: .656rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-ro-v { display: flex; align-items: baseline; gap: 4px; }

.tn-sheet-band { display: flex; flex-direction: column; gap: 7px; }

.tn-band-scale-alarm { color: var(--tn-alarm); font-weight: 700; }

.tn-callout {
    font-size: .781rem;
    line-height: 1.55;
    padding: 9px 12px;
    background: var(--tn-state-bg);
    border-inline-start: 3px solid var(--tn-state);
    color: var(--tn-state);
}

.tn-sheet-chart { padding: 8px; }

.tn-sheet-config-head {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
}

.tn-sheet-config-note { font-size: .688rem; color: var(--mud-palette-text-secondary); }

.tn-raw-switch { margin: 0; }

.tn-sheet-fingerprint {
    font-size: .656rem;
    color: var(--mud-palette-text-disabled);
    padding-inline: 2px;
}

/* -- configuration groups ------------------------------------------------ */

.tn-cfg {
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    background: var(--tn-surface);
}

.tn-cfg-head {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 14px;
    border-block-end: 1px solid var(--tn-line-light);
    background: var(--mud-palette-table-striped);
}

.tn-cfg-title {
    font-family: var(--mud-typography-h6-family);
    font-size: .813rem;
    font-weight: 500;
    letter-spacing: .07em;
    text-transform: uppercase;
}

.tn-cfg-row {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 7px 14px;
    border-block-end: 1px solid var(--tn-line-light);
}

.tn-cfg-row:last-child { border-block-end: 0; }

.tn-cfg-k { flex: 1 1 auto; font-size: .781rem; color: var(--mud-palette-text-secondary); }

.tn-cfg-v {
    font-size: .781rem;
    font-weight: 600;
    text-align: end;
    font-variant-numeric: tabular-nums;
}

.tn-cfg-v--alarm { color: var(--tn-alarm); }

.tn-cfg-raw {
    flex: 0 0 78px;
    text-align: end;
    font-size: .656rem;
    color: var(--mud-palette-text-disabled);
}

/* --------------------------------------------------------------------------
   14. Events
   -------------------------------------------------------------------------- */

.tn-filterbar-divider {
    inline-size: 1px;
    block-size: 22px;
    background: var(--tn-line);
    margin-inline: 4px;
}

.tn-ev-row {
    display: grid;
    grid-template-columns: 112px 92px minmax(120px, 150px) minmax(0, 1fr) 120px 110px 28px;
    gap: 12px;
    align-items: center;
    padding: 9px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .781rem;
    cursor: pointer;
    min-inline-size: 880px;
}

.tn-ev-row:hover { background: var(--mud-palette-table-hover); }

.tn-ev-row[data-tn-state="alarm"] { background: var(--tn-alarm-wash); }
.tn-ev-row[data-tn-state="alarm"]:hover { background: var(--tn-alarm-bg); }

.tn-ev-row--open { border-block-end: 0; }

.tn-ev-head {
    background: var(--tn-sunken);
    border-block-end: 1px solid var(--tn-line);
    cursor: default;
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-ev-head:hover { background: var(--tn-sunken); }

.tn-ev-ago { font-size: .656rem; color: var(--mud-palette-text-disabled); }

.tn-ev-msg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tn-ev-msg--resolved {
    text-decoration: line-through;
    color: var(--mud-palette-text-secondary);
}

.tn-src--plain { color: var(--mud-palette-text-secondary); background: var(--tn-off-bg); }

.tn-ev-day {
    display: flex;
    align-items: baseline;
    gap: 11px;
    padding: 9px 16px;
    background: var(--tn-sunken);
    border-block: 1px solid var(--tn-line);
    position: sticky;
    top: 0;
    z-index: 1;
}

.tn-ev-day-title {
    font-family: var(--mud-typography-h6-family);
    font-size: .875rem;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.tn-ev-day-meta { font-size: .75rem; color: var(--mud-palette-text-secondary); }

.tn-ev-detail {
    display: flex;
    gap: 34px;
    padding: 4px 16px 16px 140px;
    border-block-end: 1px solid var(--tn-line-light);
    background: var(--tn-state-bg);
    flex-wrap: wrap;
}

.tn-ev-detail-main { flex: 1 1 320px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }

.tn-ev-detail-msg {
    font-size: .781rem;
    line-height: 1.55;
    color: var(--tn-ink-muted);
    max-inline-size: 640px;
}

.tn-ev-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.tn-ev-detail-facts { display: flex; gap: 26px; flex-wrap: wrap; }

.tn-ev-flags { display: flex; gap: 5px; flex-wrap: wrap; }

.tn-ev-loading { padding: 26px; display: flex; justify-content: center; }

.tn-ev-foot {
    padding: 11px 16px;
    border-block-start: 1px solid var(--tn-line);
    background: var(--mud-palette-table-striped);
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

/* --------------------------------------------------------------------------
   15. Downloads
   -------------------------------------------------------------------------- */

.tn-crumbs { display: flex; align-items: center; gap: 6px; font-size: .75rem; }
.tn-crumbs a { color: var(--mud-palette-text-secondary); text-decoration: none; }
.tn-crumbs a:not(:last-child)::after { content: " ›"; color: var(--tn-line-strong); }
.tn-crumbs a.on { color: var(--tn-ink); font-weight: 600; }

.tn-folder-row { display: flex; gap: 8px; flex-wrap: wrap; }

.tn-folder-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 11px;
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius-chip);
    background: var(--tn-surface);
    font-size: .75rem;
    font-weight: 600;
    color: var(--tn-ink-muted);
    text-decoration: none;
}

.tn-folder-chip:hover { background: var(--mud-palette-table-hover); }

.tn-release--latest { border-color: color-mix(in srgb, var(--tn-primary) 32%, var(--tn-surface)); }

.tn-release-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    border-block-end: 1px solid var(--tn-line-light);
    background: var(--mud-palette-table-striped);
    flex-wrap: wrap;
}

.tn-release-version {
    font-family: var(--mud-typography-h4-family);
    font-size: 1.5rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.tn-release-version--sm { font-size: 1.063rem; flex: 0 0 auto; min-inline-size: 74px; }

.tn-release-meta { font-size: .75rem; color: var(--mud-palette-text-secondary); }

.tn-release-actions { margin-inline-start: auto; display: flex; gap: 8px; }

.tn-release-body { display: flex; gap: 26px; padding: 14px 18px; flex-wrap: wrap; }

.tn-release-notes { flex: 1 1 320px; display: flex; flex-direction: column; gap: 9px; min-width: 0; }

.tn-release-info {
    margin: 0;
    font-family: var(--mud-typography-default-family);
    font-size: .781rem;
    line-height: 1.55;
    color: var(--tn-ink-muted);
    white-space: pre-wrap;
    word-break: break-word;
    max-block-size: 260px;
    overflow-y: auto;
}

.tn-release-side { flex: 0 0 220px; display: flex; flex-direction: column; gap: 7px; }

.tn-release-hint {
    font-size: .719rem;
    line-height: 1.55;
    color: var(--mud-palette-text-secondary);
}

.tn-release-row {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 11px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    flex-wrap: wrap;
}

.tn-release-row:last-child { border-block-end: 0; }
.tn-release-row:hover { background: var(--mud-palette-table-hover); }

.tn-release-date { flex: 0 0 92px; font-size: .75rem; }

.tn-release-summary {
    flex: 1 1 110px;
    min-width: 0;
    font-size: .781rem;
    color: var(--tn-ink-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-release-link { font-size: .75rem; font-weight: 600; }

.tn-doc {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    border-block-end: 1px solid var(--tn-line-light);
    cursor: pointer;
}

.tn-doc:last-child { border-block-end: 0; }
.tn-doc:hover { background: var(--mud-palette-table-hover); }

.tn-doc-icon {
    inline-size: 30px;
    block-size: 36px;
    flex: 0 0 auto;
    border: 1px solid var(--tn-line);
    border-radius: 2px;
    background: var(--tn-surface);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-block-end: 4px;
    font-size: .5rem;
    font-weight: 800;
    color: var(--tn-alarm);
}

.tn-doc-text { flex: 1 1 auto; min-width: 0; }
.tn-doc-name { font-size: .844rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-doc-meta { font-size: .719rem; color: var(--mud-palette-text-secondary); }

.tn-gate { padding: 16px; gap: 11px; background: var(--mud-palette-table-striped); }
.tn-gate-body { font-size: .781rem; color: var(--tn-ink-muted); line-height: 1.55; }
.tn-gate-form { display: flex; gap: 9px; align-items: flex-start; }
.tn-gate-form > :first-child { flex: 1 1 auto; }

.tn-fw-row {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .781rem;
}

.tn-fw-row:last-of-type { border-block-end: 0; }
.tn-fw-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-fw-version { font-weight: 700; }
.tn-fw-model { font-size: .719rem; }

/* --------------------------------------------------------------------------
   16. Recipes
   -------------------------------------------------------------------------- */

.tn-recipes {
    display: grid;
    grid-template-columns: 264px minmax(0, 1fr);
    min-block-size: calc(100vh - var(--mud-appbar-height));
}

@media (max-width: 900px) {
    .tn-recipes { grid-template-columns: minmax(0, 1fr); }
}

.tn-folder-pane {
    background: var(--tn-surface);
    border-inline-end: 1px solid var(--tn-line);
    display: flex;
    flex-direction: column;
}

.tn-folder-pane-head {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 12px 14px;
    border-block-end: 1px solid var(--tn-line);
}

.tn-folder {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 14px;
    border-block-end: 1px solid var(--tn-line-light);
    border-inline-start: 3px solid transparent;
    text-decoration: none;
    color: inherit;
}

.tn-folder:hover { background: var(--mud-palette-table-hover); }

.tn-folder.on {
    background: var(--mud-palette-table-hover);
    border-inline-start-color: var(--tn-primary);
}

.tn-folder-text { flex: 1 1 auto; min-width: 0; }
.tn-folder-name { font-size: .844rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-folder.on .tn-folder-name { color: var(--tn-primary); }
.tn-folder-meta { font-size: .688rem; color: var(--mud-palette-text-secondary); }

.tn-folder-pane-foot {
    margin-block-start: auto;
    padding: 14px;
    border-block-start: 1px solid var(--tn-line-light);
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.5;
}

.tn-folder-content {
    padding: 18px 24px 28px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.tn-folder-title-row { display: flex; align-items: center; gap: 12px; }

.tn-folder-title {
    font-family: var(--mud-typography-h4-family);
    font-size: 1.5rem;
    font-weight: 500;
}

/* -- folder contents ------------------------------------------------------ */

.tn-folder-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(280px, 1fr);
    gap: 16px;
    align-items: start;
}

@media (max-width: 1100px) {
    .tn-folder-grid { grid-template-columns: minmax(0, 1fr); }
}

.tn-folder-main, .tn-folder-rail { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

.tn-panel-count {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    background: var(--tn-sunken);
    border-radius: var(--tn-radius-chip);
    padding: 1px 7px;
}

/* Appears only when something is selected, rather than three disabled buttons. */
.tn-select-bar {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 14px;
    background: var(--tn-ramp-bg);
    border-block-end: 1px solid color-mix(in srgb, var(--tn-primary) 22%, var(--tn-surface));
    flex-wrap: wrap;
}

.tn-select-count { font-size: .781rem; font-weight: 700; color: var(--tn-primary); }

.tn-rc-row {
    display: grid;
    grid-template-columns: 30px minmax(0, 1.6fr) 74px minmax(0, 1fr) minmax(0, 1.2fr) 132px;
    gap: 12px;
    align-items: center;
    padding: 8px 14px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .781rem;
    cursor: pointer;
    min-inline-size: 700px;
}

.tn-rc-row:last-of-type { border-block-end: 0; }
.tn-rc-row:hover { background: var(--mud-palette-table-hover); }
.tn-rc-row.on { background: var(--tn-ramp-bg); }

.tn-rc-head {
    background: var(--tn-sunken);
    border-block-end: 1px solid var(--tn-line);
    cursor: default;
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-rc-head:hover { background: var(--tn-sunken); }

.tn-rc-name { display: flex; align-items: center; gap: 9px; min-width: 0; font-weight: 600; }
.tn-rc-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tn-rc-comment { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tn-cb {
    inline-size: 15px;
    block-size: 15px;
    border: 1.5px solid var(--tn-line-strong);
    border-radius: 2px;
    display: inline-block;
    cursor: pointer;
    position: relative;
}

.tn-cb.on { border-color: var(--tn-primary); background: var(--tn-primary); }

.tn-cb.on::after {
    content: "";
    position: absolute;
    inset-inline-start: 4px;
    inset-block-start: 1px;
    inline-size: 4px;
    block-size: 8px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.tn-drop-wrap { display: block; margin: 14px; }

.tn-drop {
    border: 1.5px dashed var(--tn-line-strong);
    border-radius: var(--tn-radius);
    background: var(--mud-palette-table-striped);
    padding: 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    cursor: pointer;
}

.tn-drop:hover { border-color: var(--tn-primary); background: var(--tn-ramp-bg); }
.tn-drop-title { font-size: .813rem; font-weight: 600; color: var(--tn-ink-muted); }
.tn-drop-body { font-size: .75rem; color: var(--mud-palette-text-secondary); }

/* -- people and controllers on a folder ----------------------------------- */

.tn-person {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 14px;
    border-block-end: 1px solid var(--tn-line-light);
}

.tn-person:last-of-type { border-block-end: 0; }

.tn-person-text { flex: 1 1 auto; min-width: 0; }
.tn-person-name { font-size: .813rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-person-mail { font-size: .719rem; color: var(--mud-palette-text-secondary); overflow: hidden; text-overflow: ellipsis; }

.tn-avatar--sm { inline-size: 26px; block-size: 26px; font-size: .688rem; }

.tn-access { cursor: pointer; padding-inline-end: 3px; }
.tn-access:hover { filter: brightness(.96); }

/* -- controller details dialog -------------------------------------------- */

.tn-device-dialog { max-inline-size: 760px !important; }

.tn-dlg-head { display: flex; align-items: center; gap: 11px; }
.tn-dlg-id { min-width: 0; }

.tn-dlg-name {
    font-family: var(--mud-typography-h5-family);
    font-size: 1.25rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-dlg-sub { font-size: .719rem; color: var(--mud-palette-text-secondary); }

.tn-dlg-body {
    padding: 16px 20px 20px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 14px;
    align-items: start;
}

/* --------------------------------------------------------------------------
   18. Dialogs

   Most dialogs in the app carried TitleClass="mud-primary …", i.e. a solid
   primary header with white content — which stopped working the moment primary
   became lighter in dark mode, and never matched the redesign. Normalising the
   title bar here fixes every dialog at once, including ones whose header is
   just a title string with no TitleContent of its own.
   -------------------------------------------------------------------------- */

.mud-dialog-title,
.mud-dialog-title.mud-primary {
    background-color: var(--tn-surface);
    color: var(--tn-ink);
    border-block-end: 1px solid var(--tn-line);
    padding: 14px 20px;
    font-family: var(--mud-typography-h6-family);
    font-size: 1.125rem;
    font-weight: 500;
    letter-spacing: .01em;
}

/* Those headers set their text and close button to Color.Secondary, which is
   white — invisible now that the bar is a light surface. */
.mud-dialog-title .mud-secondary-text,
.mud-dialog-title .mud-typography,
.mud-dialog-title .mud-button-root.mud-icon-button {
    color: var(--tn-ink) !important;
}

.mud-dialog-title .mud-button-root.mud-icon-button:hover {
    background-color: var(--mud-palette-action-default-hover);
}

.mud-dialog-content { padding: 20px; }

.mud-dialog-actions {
    border-block-start: 1px solid var(--tn-line-light);
    padding: 12px 20px;
    gap: 8px;
}

/* Sheets and the picker bring their own chrome. */
.tn-sheet .mud-dialog-title,
.tn-device-dialog .mud-dialog-title,
.tn-pick-dialog .mud-dialog-title { font-size: inherit; font-weight: inherit; }

.tn-sheet .mud-dialog-content,
.tn-device-dialog .mud-dialog-content,
.tn-pick-dialog .mud-dialog-content { padding: 0; }

.tn-pick-dialog { max-inline-size: 520px !important; }

.tn-pick-list { max-block-size: 420px; overflow-y: auto; }

.tn-pick {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 18px;
    border-block-end: 1px solid var(--tn-line-light);
    cursor: pointer;
}

.tn-pick:last-child { border-block-end: 0; }
.tn-pick:hover { background: var(--mud-palette-table-hover); }
.tn-pick.on { background: var(--tn-ramp-bg); }

.tn-pick-text { min-width: 0; }
.tn-pick-name { font-size: .844rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-pick-sub { font-size: .719rem; color: var(--mud-palette-text-secondary); }

/* -- admin: requests, devices --------------------------------------------- */

.tn-req {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    flex-wrap: wrap;
}

.tn-req:last-of-type { border-block-end: 0; }
.tn-req-text { flex: 1 1 auto; min-width: 0; }
.tn-req-title { font-size: .844rem; font-weight: 700; }
.tn-req-sub { font-size: .719rem; color: var(--mud-palette-text-secondary); }

.tn-dev-row {
    display: grid;
    grid-template-columns: minmax(130px, 0.9fr) minmax(0, 1fr) minmax(0, 1.3fr) 80px 150px;
    gap: 14px;
    align-items: center;
    padding: 4px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .781rem;
    min-inline-size: 780px;
}

.tn-dev-row:hover { background: var(--mud-palette-table-hover); }

.tn-dev-head {
    background: var(--tn-sunken);
    border-block-end: 1px solid var(--tn-line);
    padding-block: 9px;
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-dev-head:hover { background: var(--tn-sunken); }
.tn-dev-serial { font-weight: 600; }

.tn-inline-edit .mud-input > input { font-size: .781rem; }

.tn-loading {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 26px;
    font-size: .813rem;
    color: var(--mud-palette-text-secondary);
}

/* --------------------------------------------------------------------------
   19. Account sections
   -------------------------------------------------------------------------- */

/* A settings row: what it is and what it is set to on the left, the action on the right. */
.tn-sec-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    flex-wrap: wrap;
}

.tn-sec-row:last-child { border-block-end: 0; }

.tn-sec-text { flex: 1 1 260px; min-width: 0; }
.tn-sec-title-row { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.tn-sec-title { font-size: .875rem; font-weight: 700; }

.tn-sec-body {
    font-size: .781rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.5;
    max-inline-size: 560px;
}

/* Password fields appear only when asked for — three empty boxes are not a resting state. */
.tn-sec-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 4px 16px 18px;
    max-inline-size: 420px;
}

.tn-field { display: flex; flex-direction: column; gap: 4px; }

.tn-cfg-foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 12px 16px;
    border-block-start: 1px solid var(--tn-line-light);
    background: var(--mud-palette-table-striped);
}

.tn-cfg--danger { border-color: color-mix(in srgb, var(--tn-alarm) 26%, var(--tn-line)); }

/* -- recovery codes ------------------------------------------------------- */

.tn-codes-dialog { max-inline-size: 480px !important; }
.tn-codes-body { padding: 18px; display: flex; flex-direction: column; gap: 14px; }

.tn-codes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}

.tn-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .813rem;
    letter-spacing: .06em;
    padding: 7px 10px;
    background: var(--tn-sunken);
    border-radius: var(--tn-radius-chip);
    text-align: center;
}

/* -- invite --------------------------------------------------------------- */

.tn-invite-dialog { max-inline-size: 520px !important; }
.tn-invite-body { padding: 18px; display: flex; flex-direction: column; gap: 16px; }

.tn-invite-hint {
    font-size: .781rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.55;
}

.tn-invite-access { display: flex; flex-direction: column; gap: 7px; }
.tn-invite-options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

/* Access level chosen up front, with what each one means written out. */
.tn-option {
    appearance: none;
    text-align: start;
    font: inherit;
    cursor: pointer;
    padding: 11px 13px;
    border: 1px solid var(--tn-line);
    border-radius: var(--tn-radius);
    background: var(--tn-surface);
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.tn-option:hover { background: var(--mud-palette-table-hover); }

.tn-option.on {
    border-color: var(--tn-primary);
    background: var(--tn-ramp-bg);
    box-shadow: inset 0 0 0 1px var(--tn-primary);
}

.tn-option-title { font-size: .813rem; font-weight: 700; }
.tn-option-body { font-size: .719rem; color: var(--mud-palette-text-secondary); line-height: 1.45; }

/* --------------------------------------------------------------------------
   20. Prompts, folder dialog, pairing
   -------------------------------------------------------------------------- */

.tn-prompt-dialog { max-inline-size: 460px !important; }
.tn-folder-dialog { max-inline-size: 460px !important; }
.tn-folder-dialog-body { padding: 18px; display: flex; flex-direction: column; gap: 14px; }

.tn-pair-dialog { max-inline-size: 560px !important; }
.tn-pair-body { padding: 18px; display: flex; flex-direction: column; gap: 16px; }

/* The two steps, in the order they happen. */
.tn-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 11px;
}

.tn-steps li { display: flex; align-items: flex-start; gap: 11px; }

.tn-step-n {
    inline-size: 22px;
    block-size: 22px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--tn-primary);
    color: var(--mud-palette-primary-text);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .688rem;
    font-weight: 800;
}

.tn-step-text {
    font-size: .781rem;
    line-height: 1.55;
    color: var(--tn-ink-muted);
    padding-block-start: 2px;
}

.tn-pair-empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 11px;
    padding: 18px;
    border: 1px dashed var(--tn-line-strong);
    border-radius: var(--tn-radius);
    background: var(--mud-palette-table-striped);
}

.tn-pair-empty-text { font-size: .781rem; color: var(--mud-palette-text-secondary); line-height: 1.5; }

.tn-codes-list { display: flex; flex-direction: column; gap: 9px; }

/* The code is the point of the dialog, so it is the biggest thing in it. */
.tn-pair-code {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid var(--tn-line);
    border-inline-start: 3px solid var(--tn-state);
    border-radius: var(--tn-radius);
    background: var(--tn-surface);
}

.tn-pair-code-value {
    font-family: var(--mud-typography-h4-family);
    font-size: 1.75rem;
    font-weight: 500;
    letter-spacing: .14em;
    flex: 1 1 auto;
}

.tn-pair-code-meta {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: .75rem;
    color: var(--tn-state);
    font-weight: 600;
}

/* --------------------------------------------------------------------------
   17. Account & administration
   -------------------------------------------------------------------------- */

.tn-account-layout {
    display: grid;
    grid-template-columns: 212px minmax(0, 1fr);
    gap: 22px;
    align-items: start;
}

@media (max-width: 800px) {
    .tn-account-layout { grid-template-columns: minmax(0, 1fr); }
}

.tn-account-aside { display: flex; flex-direction: column; gap: 16px; }

.tn-account-identity { display: flex; align-items: center; gap: 12px; padding-inline: 4px; }

.tn-avatar--lg { inline-size: 46px; block-size: 46px; font-size: 1.063rem; }

.tn-account-identity-text { min-width: 0; }
.tn-account-name { font-size: .875rem; font-weight: 700; }
.tn-account-mail { font-size: .719rem; color: var(--mud-palette-text-secondary); overflow: hidden; text-overflow: ellipsis; }

.tn-account-nav { display: flex; flex-direction: column; gap: 2px; }

.tn-account-nav a {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 12px;
    border-radius: 3px;
    font-size: .813rem;
    font-weight: 600;
    color: var(--tn-ink-muted);
    text-decoration: none;
}

.tn-account-nav a:hover { background: var(--mud-palette-table-hover); }
.tn-account-nav a.on { background: var(--tn-ramp-bg); color: var(--tn-primary); }

.tn-account-note { font-size: .75rem; color: var(--mud-palette-text-secondary); line-height: 1.55; padding-inline: 4px; }

.tn-account-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

.tn-account-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
    padding: 16px;
}

.tn-account-security { padding: 4px 16px 16px; }

.tn-account-device {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .813rem;
}

.tn-account-device:last-of-type { border-block-end: 0; }
.tn-account-device-name { flex: 1 1 auto; font-weight: 600; color: inherit; text-decoration: none; min-width: 0; }
.tn-account-device-name:hover { color: var(--tn-primary); }

.tn-inline-select { text-transform: none; padding-inline: 6px; min-inline-size: 0; }

.tn-segment--sm button { padding: 4px 10px; font-size: .719rem; }

.tn-tab-badge--quiet { background: var(--tn-off-bg); color: var(--mud-palette-text-secondary); }

.tn-admin-body { display: flex; flex-direction: column; gap: 14px; }

/* -- user list ------------------------------------------------------------ */

.tn-user-row {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.4fr) 210px 90px 44px;
    gap: 14px;
    align-items: center;
    padding: 9px 16px;
    border-block-end: 1px solid var(--tn-line-light);
    font-size: .781rem;
    min-inline-size: 820px;
}

.tn-user-row:last-of-type { border-block-end: 0; }
.tn-user-row:hover { background: var(--mud-palette-table-hover); }

.tn-user-head {
    background: var(--tn-sunken);
    border-block-end: 1px solid var(--tn-line);
    font-family: var(--mud-typography-overline-family);
    font-size: var(--mud-typography-overline-size);
    font-weight: var(--mud-typography-overline-weight);
    letter-spacing: var(--mud-typography-overline-letterspacing);
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.tn-user-head:hover { background: var(--tn-sunken); }

.tn-role-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.tn-role-chips .tn-chip { padding: 3px 9px; font-size: .719rem; }

.tn-user-flags { display: flex; gap: 14px; flex-wrap: wrap; }

.tn-flag {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: .719rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.tn-flag .mud-switch { margin: 0; }

.tn-role-new { display: flex; align-items: center; gap: 8px; }
.tn-role-new .mud-input-control { inline-size: 190px; }

/* --------------------------------------------------------------------------
   18. Status utilities, for the odd inline case
   -------------------------------------------------------------------------- */

.tn-text-state { color: var(--tn-state); }
.tn-bg-state { background-color: var(--tn-state-bg); }
.tn-edge-state { border-inline-start: 3px solid var(--tn-state); }

@media (prefers-reduced-motion: reduce) {
    .tn-tile { transition: none; }
}
