/* ============================================================
   HydraSafe design system — applied to HydraSafeVisu.

   Ported from the "HydraSafe Design System" project on claude.ai/design
   (89a0e0e4-a3c6-4ba7-8acd-5414550d815a). Every value below is the design
   system's own, copied from its tokens/*.css.

   That system was authored against the sibling product (HydraSafe Config, a
   MAUI + MudBlazor app). This is Blazor Server + Microsoft Fluent UI, so its
   React components are not portable; what carries across is the token layer,
   bridged onto the Fluent tokens this app already consumes.

   Naming: tokens that would collide with an existing Fluent token name are
   prefixed --hs- (Fluent already defines --error/--warning/--success/--info,
   and 15 files in this app read them). Everything else keeps the design
   system's own name so the two stay diffable.

   Linked after app.css in App.razor.

   2026-09 near-black rebuild: the dark mode below no longer derives from the
   navy ramp. Fluent's dark neutral ramp is flat, hue-less grey (#272727 page,
   #333333 cards), which beside the navy accent is pulled warm by simultaneous
   contrast and read as brown. Dark mode now sits on a cool near-black scale
   with a small, consistent blue chroma (--hs-n-*), Fluent's ramp is pinned to
   it, and light mode's greys lose their neutrality the same way so the two
   modes are one design at two luminances rather than two designs.
   ============================================================ */

/* Montserrat is the UI face; JetBrains Mono carries checksums, serials, node
   paths and generated JSON. NeoTechIntronik (display/wordmark) already ships
   with this app and is declared in app.css. */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap');

:root {
	/* ---- Navy: primary brand ramp ---- */
	--navy-900: #0C1D38;
	--navy-800: #112B52;
	--navy-700: #193C6C; /* PRIMARY */
	--navy-600: #234E88;
	--navy-500: #2E62A6;
	--navy-400: #4C7CBF;
	--navy-300: #7BA1D4;
	--navy-200: #AFC7E6;
	--navy-100: #DCE6F3;
	--navy-050: #EEF3FA;

	/* ---- Steelblue: brand accent (favicon gradient, legacy primary) ---- */
	--steel-700: #2A4C68;
	--steel-500: #4682B4;
	--steel-400: #6BA3CE;
	--steel-300: #9BC1DE;
	--steel-100: #D6E7F1;

	/* ---- Intronik green: parent company, attribution only — never a UI accent ---- */
	--intronik-green: #1B9653;
	--intronik-green-dark: #14713F;
	--intronik-green-050: #E7F5EC;

	/* ---- Neutrals ---- */
	--ink: #1A1F24;
	--grey-800: #212529;
	--grey-700: #495057;
	--grey-600: #616161;
	--grey-500: #757575;
	--grey-400: #9E9E9E;
	--grey-300: #BDBDBD;
	--grey-200: #E0E0E0;
	--grey-150: #E9ECEF;
	--grey-100: #F1F3F5;
	--grey-050: #F8F9FA;
	--white: #FFFFFF;

	/* ---- Semantic status colours (--hs- prefixed: Fluent owns the bare names) ---- */
	/* The -darken inks are what a pill or a badge prints in on its tint; the
	   turn-4 light ramp lifts them from the near-black originals so a state
	   word still reads as its hue rather than as black. */
	--hs-success: #43AC6A;
	--hs-success-darken: #146B39;
	--hs-success-bg: #D9EEE1;
	--hs-info: #2E8AB0; /* deepened from #5BC0DE for AA contrast on white */
	--hs-info-accent: #5BC0DE;
	--hs-info-darken: #1F6F8F;
	--hs-info-bg: #DEF2F8;
	--hs-warning: #E99002;
	--hs-warning-darken: #8A5600;
	--hs-warning-bg: #FBE9CC;
	--hs-error: #D64550;
	--hs-error-darken: #B3323C;
	--hs-error-bg: #FBE3E5;

	/* ---- Semantic aliases ---- */
	--color-primary: var(--navy-700);
	--color-primary-hover: var(--navy-600);
	--color-primary-active: var(--navy-800);
	--color-primary-contrast: #FFFFFF;
	--color-accent: var(--steel-500);
	--color-accent-hover: var(--steel-700);

	/* The page and sunken greys carry a trace of blue (were --grey-050 /
	   --grey-100): light mode keeps its palette, only the greys lose their
	   neutrality so they match the cool dark scale below. */
	--surface-page: #F5F7FA;
	--surface-card: var(--white);
	--surface-sunken: #EDF1F6;
	--surface-inverse: var(--navy-700);

	/* The light ink scale (design, turn 4): every value measured against every
	   ground it lands on; the faintest, #5F6E80, is 4.55:1 at worst. The same
	   four steps exist in dark as --hs-ink-1..4, so the component layer can
	   name a step and get the right one in either mode. */
	--hs-ink-1: #16202B;
	--hs-ink-2: #4E5C6C;
	--hs-ink-3: #5F6E80;
	--hs-ink-4: #7B8797;

	--text-primary: var(--hs-ink-1);
	--text-secondary: var(--hs-ink-3);
	--text-disabled: #A9B4C2;
	--text-on-primary: #FFFFFF;
	--text-link: var(--navy-600);
	--text-link-hover: var(--navy-700);

	--border-default: #DBE2EA;
	--border-strong: #C3CDD9;
	--border-focus: var(--steel-500);

	/* ---- Eye-catcher gradients ------------------------------------------
	   Reserved for appbar and hero surfaces only. Defined so they are
	   available, but deliberately not auto-applied to any element: the shell
	   chrome is out of the agreed scope for this pass. */
	--gradient-appbar: linear-gradient(100deg, var(--navy-800) 0%, var(--navy-700) 45%, var(--steel-700) 100%);
	--gradient-hero: linear-gradient(135deg, var(--navy-700) 0%, var(--steel-500) 130%);
	--gradient-brandmark: linear-gradient(90deg, var(--navy-800), var(--steel-500));

	/* ---- Typography ---- */
	--font-sans: 'Montserrat', 'Helvetica Neue', Helvetica, Arial, sans-serif;
	--font-display: 'NeoTechIntronik', 'Montserrat', sans-serif;
	--font-mono: 'JetBrains Mono', 'Consolas', 'SFMono-Regular', monospace;

	--fw-light: 300;
	--fw-regular: 400;
	--fw-medium: 500;
	--fw-semibold: 600;
	--fw-bold: 700;

	--text-display: 2.75rem;
	--text-h4: 2.125rem;
	--text-h5: 1.5rem;
	--text-h6: 1.25rem;
	--text-subtitle1: 1rem;
	--text-body1: 1rem;
	--text-body2: 0.875rem; /* default UI text */
	--text-caption: 0.75rem;
	--text-overline: 0.6875rem;

	--lh-tight: 1.2;
	--lh-heading: 1.334;
	--lh-body: 1.5;
	--lh-relaxed: 1.66;

	--ls-tight: -0.01562em;
	--ls-normal: 0.00938em;
	--ls-wide: 0.02857em;
	--ls-overline: 0.08em;

	/* ---- Spacing (4px grid) ---- */
	--space-0: 0;
	--space-1: 4px;
	--space-2: 8px;
	--space-3: 12px;
	--space-4: 16px;
	--space-5: 20px;
	--space-6: 24px;
	--space-8: 32px;
	--space-10: 40px;
	--space-12: 48px;
	--space-16: 64px;

	/* ---- Radius (9px is the product default) ---- */
	--radius-sm: 4px;
	--radius-md: 6px;
	--radius-lg: 9px;
	--radius-xl: 14px;
	--radius-pill: 999px;

	/* ---- Control sizing ---- */
	--control-height: 42px;
	--appbar-height: 80px;
	--drawer-width: 300px;

	/* ---- Elevation: Material ramp keyed to navy, soft and low-spread ---- */
	--elevation-0: none;
	--elevation-1: 0 2px 1px -1px rgba(12, 29, 56, .10), 0 1px 1px 0 rgba(12, 29, 56, .07), 0 1px 3px 0 rgba(12, 29, 56, .06);
	--elevation-2: 0 3px 3px -2px rgba(12, 29, 56, .12), 0 3px 4px 0 rgba(12, 29, 56, .08), 0 1px 8px 0 rgba(12, 29, 56, .06);
	--elevation-4: 0 2px 4px -1px rgba(12, 29, 56, .14), 0 4px 5px 0 rgba(12, 29, 56, .09), 0 1px 10px 0 rgba(12, 29, 56, .07);
	--elevation-8: 0 5px 5px -3px rgba(12, 29, 56, .16), 0 8px 10px 1px rgba(12, 29, 56, .10), 0 3px 14px 2px rgba(12, 29, 56, .08);
	--shadow-focus-ring: 0 0 0 3px rgba(70, 130, 180, .35);

	/* ---- Motion: purposeful and short ---- */
	--ease-standard: cubic-bezier(.4, 0, .2, 1);
	--ease-decelerate: cubic-bezier(0, 0, .2, 1);
	--ease-accelerate: cubic-bezier(.4, 0, 1, 1);
	--dur-fast: 120ms;
	--dur-base: 200ms;
	--dur-slow: 320ms;
}

/* ---- dark mode: the near-black scale ------------------------------------
   The design system specifies light surfaces only, so this is the app's own
   dark mode. Keyed off the body class MainLayout/SetupLayout mirror from
   Fluent's luminance (see hsApplyTheme) — without it the light values above
   would be forced onto dark mode.

   One scale for everything: page, chrome, cards, borders. Every step keeps the
   same slight blue chroma, so the accent sits ON the surface instead of
   fighting a neutral grey next to it. */
body.theme-dark {
	/* ---- the scale ---- */
	--hs-n-000: #080B0F; /* deepest — rail, wells */
	--hs-n-050: #0A0E13; /* page */
	--hs-n-100: #0C1116; /* content pane */
	--hs-n-150: #0E141B; /* chrome: appbar, toolbars */
	--hs-n-200: #131A22; /* card / tile / input */
	--hs-n-250: #182130; /* raised, pressed, selected */
	--hs-n-300: #1C2530; /* hairline on chrome */
	--hs-n-400: #222D39; /* border */
	--hs-n-500: #2C3846; /* strong border */

	--hs-ink-1: #E6EBF2;
	--hs-ink-2: #93A1B3;
	--hs-ink-3: #8593A4;
	--hs-ink-4: #7C8A9C;

	/* Accent lifted from --navy-400 (#4C7CBF): on #0A0E13 that reads dull, and
	   a filled control needs to clear the surface by more than 3:1. */
	--hs-accent: #5B8FD6;
	--hs-accent-soft: #16243A;

	--color-primary: var(--hs-accent);
	--color-primary-hover: #7BA9E4;
	--color-primary-active: #3F76C2;
	--color-accent: var(--hs-accent);
	--color-accent-hover: #7BA9E4;

	--surface-page: var(--hs-n-050);
	--surface-card: var(--hs-n-200);
	--surface-sunken: var(--hs-n-000);
	--surface-inverse: var(--navy-100);

	--text-primary: var(--hs-ink-1);
	--text-secondary: var(--hs-ink-2);
	--text-disabled: var(--hs-ink-4);
	--text-link: #7FA9E4;
	--text-link-hover: #A9C8F0;

	--border-default: var(--hs-n-400);
	--border-strong: var(--hs-n-500);

	/* Status hues, re-picked for near-black: the light-mode values were too
	   dark to carry a dot or a pill against #0A0E13. Backing tints go with
	   them. The Fluent bridge below re-points --error/--warning/--success/--info
	   at these, so every consumer follows. */
	--hs-error: #E5646F;
	--hs-warning: #E9A23B;
	--hs-success: #4FBF7E;
	--hs-info: #4FA3D1;
	--hs-error-bg: #2A1216;
	--hs-warning-bg: #2A1D08;
	--hs-success-bg: #0E2418;
	--hs-info-bg: #0C1E28;

	/* Elevation on near-black is shadow, not tint — the ramp keyed to navy is
	   invisible here and every card was relying on its border alone. */
	--elevation-1: 0 1px 2px rgba(0, 0, 0, .6);
	--elevation-2: 0 2px 6px rgba(0, 0, 0, .55);
	--elevation-4: 0 6px 16px -4px rgba(0, 0, 0, .7);
	--elevation-8: 0 18px 40px -12px rgba(0, 0, 0, .8);
	--shadow-focus-ring: 0 0 0 3px rgba(91, 143, 214, .45);
}

/* ============================================================
   Brand defaults for Fluent's neutral tokens.

   Note the absence of !important — that is the whole point. Fluent writes its
   real, luminance-correct values inline at runtime, and inline beats a
   stylesheet, so these apply only when Fluent's have not been set: before
   hydration, and in any environment where its JS does not run. Without them
   the app falls back to inherited black text and black borders, because
   Fluent's own stylesheets *declare* several of these tokens empty — and an
   empty declaration defeats a var() fallback (the substitution is invalid
   rather than missing), so per-usage fallbacks cannot fix it.

   Light-mode values only, deliberately: they are a floor, not a theme. Once
   Fluent is up it owns both luminance modes.
   ============================================================ */
:root {
	--neutral-foreground-rest: var(--text-primary);
	--neutral-foreground-hint: var(--text-secondary);
	--neutral-stroke-rest: var(--border-default);
	--neutral-stroke-strong-rest: var(--border-strong);
	--neutral-stroke-divider-rest: var(--grey-150);
	--neutral-layer-1: var(--surface-card);
	--neutral-layer-2: var(--grey-050);
	--neutral-layer-3: var(--grey-100);
	--neutral-layer-4: var(--grey-150);
	--neutral-fill-layer-rest: var(--surface-page);
	--neutral-fill-primary-rest: var(--white);
	--neutral-fill-secondary-rest: var(--grey-100);
	--neutral-fill-stealth-rest: var(--grey-050);
	--neutral-fill-stealth-hover: var(--grey-100);
	--accent-fill-rest: var(--color-primary);
	--accent-foreground-rest: var(--color-primary);
}

/* ============================================================
   Fluent UI bridge.

   The app's markup and app.css are written against Fluent's tokens, so the
   design reaches every page by re-pointing those rather than restyling
   components one at a time. Fluent writes its tokens as inline custom
   properties at runtime, which outranks a stylesheet — hence !important here,
   and only here.

   Deliberately NOT bridged:

   * Focus indication. Fluent computes focus contrast against the accent; the
     design's 3px steel ring is applied to app-owned surfaces via
     --shadow-focus-ring instead of overriding Fluent's a11y behaviour.
   ============================================================ */
body {
	/* Type — Fluent components read --body-font internally. */
	--body-font: var(--font-sans) !important;

	/* Shape — the product default is 9px; Fluent ships 4px.
	   These two Fluent tokens are UNITLESS: its stylesheets compute
	   `calc(var(--control-corner-radius) * 1px)`, so passing "9px" here would
	   yield calc(9px * 1px) — invalid, and every radius would collapse to 0.
	   --radius-lg (9px) stays the token app CSS should use directly. */
	--control-corner-radius: 9 !important;
	--layer-corner-radius: 9 !important;

	/* Status hues — mode-independent, and consumed by alarm, event and
	   diagnostic surfaces across 15 files. */
	--error: var(--hs-error) !important;
	--warning: var(--hs-warning) !important;
	--success: var(--hs-success) !important;
	--info: var(--hs-info) !important;
	--presence-available: var(--hs-success) !important;
	--presence-away: var(--hs-warning) !important;
	--presence-busy: var(--hs-error) !important;
}

/* ---- the accent, pinned ------------------------------------------------
   FluentDesignTheme's CustomColor is only a *seed*: Fluent's adaptive-colour
   engine builds a palette from it and then picks the rest/hover/active swatches
   by contrast rule. Seeded with a colour as dark as #193C6C it selects a much
   lighter, desaturated mid-tone — which is why the brand navy came out muted
   even though the seed was correct. Persisted themes (StorageName="theme") can
   also restore an older seed.

   So the accent swatches are set outright. The full state set is covered so
   hover/active still respond, and --foreground-on-accent-* keeps label contrast
   correct on the filled surfaces. Split by luminance via the body class that
   MainLayout/SetupLayout mirror from Fluent (see hsApplyTheme). */
body:not(.theme-dark) {
	--accent-fill-rest: var(--navy-700) !important;
	--accent-fill-hover: var(--navy-600) !important;
	--accent-fill-active: var(--navy-800) !important;
	--accent-fill-focus: var(--navy-700) !important;
	--accent-foreground-rest: var(--navy-700) !important;
	--accent-foreground-hover: var(--navy-600) !important;
	--accent-foreground-active: var(--navy-800) !important;
	--accent-stroke-control-rest: var(--navy-700) !important;
	--foreground-on-accent-rest: #FFFFFF !important;
	--foreground-on-accent-hover: #FFFFFF !important;
	--foreground-on-accent-active: #FFFFFF !important;

	/* ---- the light neutral ramp, pinned ----
	   Same reason as the dark one below, at the other luminance: Fluent's light
	   neutrals are hue-less greys, and the design's are one trace of blue away
	   from them so the two modes read as one design. Page, rail, cards, the
	   header row, the borders and the inks are the design's own values. */
	--neutral-fill-layer-rest: #F5F7FA !important;
	--neutral-layer-floating: #FFFFFF !important;
	--neutral-layer-1: #FFFFFF !important;
	--neutral-layer-2: #FAFBFD !important;
	--neutral-layer-3: #F2F5F9 !important;
	--neutral-layer-4: #EDF1F6 !important;
	--neutral-fill-primary-rest: #FFFFFF !important;
	--neutral-fill-secondary-rest: #F2F5F9 !important;
	--neutral-fill-stealth-rest: #F7F9FC !important;
	--neutral-fill-stealth-hover: #EAF0F9 !important;
	--neutral-fill-stealth-active: #E4EAF1 !important;
	--neutral-fill-rest: #FFFFFF !important;
	--neutral-fill-hover: #F2F5F9 !important;
	--neutral-fill-active: #EDF1F6 !important;
	--neutral-fill-input-rest: #FFFFFF !important;
	--neutral-fill-input-hover: #FFFFFF !important;
	--neutral-fill-input-focus: #FFFFFF !important;
	--neutral-stroke-rest: #C3CDD9 !important;
	--neutral-stroke-hover: #A9B4C2 !important;
	--neutral-stroke-strong-rest: #A9B4C2 !important;
	--neutral-stroke-divider-rest: #DBE2EA !important;
	--neutral-stroke-input-active: #C3CDD9 !important;
	--neutral-stroke-control-rest: linear-gradient(#C3CDD9, #C3CDD9) !important;
	--neutral-stroke-control-hover: linear-gradient(#A9B4C2, #A9B4C2) !important;
	--neutral-foreground-rest: #16202B !important;
	--neutral-foreground-hint: #5F6E80 !important;
}

/* Dark mode: the same swatch set on the near-black accent, one step brighter
   than --navy-400 so a filled control clears the page, and the on-accent
   label flips to near-black. */
body.theme-dark {
	--accent-fill-rest: var(--hs-accent) !important;
	--accent-fill-hover: #7BA9E4 !important;
	--accent-fill-active: #3F76C2 !important;
	--accent-fill-focus: var(--hs-accent) !important;
	--accent-foreground-rest: #8FB4E6 !important;
	--accent-foreground-hover: #B6D0F2 !important;
	--accent-foreground-active: #7BA9E4 !important;
	--accent-stroke-control-rest: #7BA9E4 !important;
	--foreground-on-accent-rest: #061019 !important;
	--foreground-on-accent-hover: #061019 !important;
	--foreground-on-accent-active: #061019 !important;
}

/* ---- the dark neutral ramp, pinned ---------------------------------------
   THE CAUSE OF THE BROWN. In dark mode Fluent derives its neutral ramp from a
   mid-grey base and writes flat, hue-less greys inline:

       --neutral-fill-layer-rest : #272727   (the page)
       --neutral-layer-1         : #333333   (every tile, card, table)
       --neutral-fill-stealth-*  : #272727   (the sidebar)

   Nothing in it is brown by itself. It reads brown because it sits next to
   the navy appbar and the steel accent: a 0-chroma grey beside a strongly
   cool surface is pulled warm by simultaneous contrast, and #333 at that
   lightness is exactly where the effect is strongest. So the ramp is bridged
   after all — onto the near-black scale. !important throughout: Fluent
   writes these as inline custom properties at runtime, and inline beats a
   stylesheet.

   The two control strokes are <image> tokens (Fluent layers them as a
   border-box background, same as the input strokes below), so they are
   flattened to one-colour gradients rather than plain colours. */
body.theme-dark {
	--neutral-fill-layer-rest: var(--hs-n-050) !important;
	--neutral-layer-floating: var(--hs-n-200) !important;
	--neutral-layer-1: var(--hs-n-200) !important;
	--neutral-layer-2: var(--hs-n-100) !important;
	--neutral-layer-3: var(--hs-n-250) !important;
	--neutral-layer-4: var(--hs-n-300) !important;
	--neutral-fill-primary-rest: var(--hs-n-200) !important;
	--neutral-fill-secondary-rest: var(--hs-n-150) !important;
	--neutral-fill-stealth-rest: var(--hs-n-000) !important;
	--neutral-fill-stealth-hover: var(--hs-n-250) !important;
	--neutral-fill-stealth-active: var(--hs-n-300) !important;
	--neutral-fill-rest: var(--hs-n-200) !important;
	--neutral-fill-hover: var(--hs-n-250) !important;
	--neutral-fill-active: var(--hs-n-150) !important;
	--neutral-fill-input-rest: var(--hs-n-200) !important;
	--neutral-fill-input-hover: var(--hs-n-250) !important;
	--neutral-fill-input-focus: var(--hs-n-200) !important;
	--neutral-stroke-rest: var(--hs-n-400) !important;
	--neutral-stroke-hover: var(--hs-n-500) !important;
	--neutral-stroke-strong-rest: var(--hs-n-500) !important;
	--neutral-stroke-divider-rest: var(--hs-n-300) !important;
	--neutral-stroke-input-active: var(--hs-n-400) !important;
	--neutral-stroke-control-rest: linear-gradient(var(--hs-n-400), var(--hs-n-400)) !important;
	--neutral-stroke-control-hover: linear-gradient(var(--hs-n-500), var(--hs-n-500)) !important;
	--neutral-foreground-rest: var(--hs-ink-1) !important;
	--neutral-foreground-hint: var(--hs-ink-2) !important;
}

/* Fluent UI 4 design tokens the app's stylesheets still read (app.css) that nothing defines since
   Fluent UI 5: 4's values. */
body {
	--type-ramp-base-font-size: 14px;
	--type-ramp-base-line-height: 20px;
	--font-weight: 400;
	--fill-color: var(--neutral-layer-1);
	--elevation-shadow-card-rest: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.14);
}

/* 4's reboot.css set the colour scheme from the theme; 5's does not, and without it the scrollbars and
   the native inputs (the time fields) stay light in dark mode. */
body {
	color-scheme: light;
}

body.theme-dark {
	color-scheme: dark;
}

/* ============================================================
   Fluent UI 5 bridge.

   Fluent UI 5's components read Fluent 2's tokens (--colorNeutralBackground1,
   --colorBrandBackground, --borderRadiusMedium, ...), not the ones above. The
   design reaches them the same way it reached 4's: those tokens are pointed at
   the design's values, per mode, from the same palette. Fluent 5 writes its
   theme into an adopted `html {}` sheet, so a declaration on body wins without
   !important. The brand seed (<body data-theme-color>) alone would give a
   generated ramp, not the navy the 4 bridge pinned, and 5's neutrals are
   hue-less greys again.
   ============================================================ */
body {
	--fontFamilyBase: var(--font-sans);

	/* 9px, the product radius 4 had from --control-corner-radius (controls) and
	   --layer-corner-radius (dialogs, menus). */
	--borderRadiusMedium: var(--radius-lg);
	--borderRadiusXLarge: var(--radius-lg);
}

body:not(.theme-dark) {
	--colorBrandBackground: var(--navy-700);
	--colorBrandBackgroundHover: var(--navy-600);
	--colorBrandBackgroundPressed: var(--navy-800);
	--colorBrandBackgroundSelected: var(--navy-700);
	--colorCompoundBrandBackground: var(--navy-700);
	--colorCompoundBrandBackgroundHover: var(--navy-600);
	--colorCompoundBrandBackgroundPressed: var(--navy-800);
	--colorCompoundBrandStroke: var(--navy-700);
	--colorCompoundBrandStrokeHover: var(--navy-600);
	--colorCompoundBrandStrokePressed: var(--navy-800);
	--colorBrandStroke1: var(--navy-700);
	--colorBrandForeground1: var(--navy-700);
	--colorBrandForeground2: var(--navy-600);
	--colorCompoundBrandForeground1: var(--navy-700);
	--colorCompoundBrandForeground1Hover: var(--navy-600);
	--colorCompoundBrandForeground1Pressed: var(--navy-800);
	--colorBrandForegroundLink: var(--navy-700);
	--colorBrandForegroundLinkHover: var(--navy-600);
	--colorBrandForegroundLinkPressed: var(--navy-800);
	--colorNeutralForeground2BrandHover: var(--navy-600);
	--colorNeutralForeground2BrandPressed: var(--navy-800);
	--colorNeutralForeground2BrandSelected: var(--navy-700);
	--colorNeutralForegroundOnBrand: #FFFFFF;

	/* 4 had one ink for text and one for hints; 5's second step (menus, tabs,
	   subtle buttons) takes the first, as those read in 4. */
	--colorNeutralForeground1: #16202B;
	--colorNeutralForeground1Hover: #16202B;
	--colorNeutralForeground1Pressed: #16202B;
	--colorNeutralForeground2: #16202B;
	--colorNeutralForeground2Hover: #16202B;
	--colorNeutralForeground2Pressed: #16202B;
	--colorNeutralForeground2Selected: #16202B;
	--colorNeutralForeground3: #5F6E80;
	--colorNeutralForeground3Hover: #5F6E80;
	--colorNeutralForeground3Pressed: #5F6E80;
	--colorNeutralForeground4: #5F6E80;
	--colorNeutralForegroundDisabled: var(--text-disabled);

	--colorNeutralBackground1: #FFFFFF;
	--colorNeutralBackground1Hover: #F2F5F9;
	--colorNeutralBackground1Pressed: #EDF1F6;
	--colorNeutralBackground1Selected: #EDF1F6;
	--colorNeutralBackground2: #FAFBFD;
	--colorNeutralBackground3: #F2F5F9;
	--colorNeutralBackground4: #EDF1F6;
	--colorSubtleBackgroundHover: #EAF0F9;
	--colorSubtleBackgroundPressed: #E4EAF1;

	--colorNeutralStroke1: #C3CDD9;
	--colorNeutralStroke1Hover: #A9B4C2;
	--colorNeutralStroke1Pressed: #A9B4C2;
	--colorNeutralStroke2: #DBE2EA;
	--colorNeutralStrokeAccessible: #A9B4C2;
	--colorNeutralStrokeAccessibleHover: #A9B4C2;
	--colorNeutralStrokeAccessiblePressed: #A9B4C2;
}

body.theme-dark {
	--colorBrandBackground: var(--hs-accent);
	--colorBrandBackgroundHover: #7BA9E4;
	--colorBrandBackgroundPressed: #3F76C2;
	--colorBrandBackgroundSelected: var(--hs-accent);
	--colorCompoundBrandBackground: var(--hs-accent);
	--colorCompoundBrandBackgroundHover: #7BA9E4;
	--colorCompoundBrandBackgroundPressed: #3F76C2;
	--colorCompoundBrandStroke: #7BA9E4;
	--colorCompoundBrandStrokeHover: #B6D0F2;
	--colorCompoundBrandStrokePressed: #7BA9E4;
	--colorBrandStroke1: var(--hs-accent);
	--colorBrandForeground1: #8FB4E6;
	--colorBrandForeground2: #B6D0F2;
	--colorCompoundBrandForeground1: #8FB4E6;
	--colorCompoundBrandForeground1Hover: #B6D0F2;
	--colorCompoundBrandForeground1Pressed: #7BA9E4;
	--colorBrandForegroundLink: #8FB4E6;
	--colorBrandForegroundLinkHover: #B6D0F2;
	--colorBrandForegroundLinkPressed: #7BA9E4;
	--colorNeutralForeground2BrandHover: #B6D0F2;
	--colorNeutralForeground2BrandPressed: #7BA9E4;
	--colorNeutralForeground2BrandSelected: #8FB4E6;
	--colorNeutralForegroundOnBrand: #061019;

	--colorNeutralForeground1: var(--hs-ink-1);
	--colorNeutralForeground1Hover: var(--hs-ink-1);
	--colorNeutralForeground1Pressed: var(--hs-ink-1);
	--colorNeutralForeground2: var(--hs-ink-1);
	--colorNeutralForeground2Hover: var(--hs-ink-1);
	--colorNeutralForeground2Pressed: var(--hs-ink-1);
	--colorNeutralForeground2Selected: var(--hs-ink-1);
	--colorNeutralForeground3: var(--hs-ink-2);
	--colorNeutralForeground3Hover: var(--hs-ink-2);
	--colorNeutralForeground3Pressed: var(--hs-ink-2);
	--colorNeutralForeground4: var(--hs-ink-2);
	--colorNeutralForegroundDisabled: var(--text-disabled);

	--colorNeutralBackground1: var(--hs-n-200);
	--colorNeutralBackground1Hover: var(--hs-n-250);
	--colorNeutralBackground1Pressed: var(--hs-n-150);
	--colorNeutralBackground1Selected: var(--hs-n-250);
	--colorNeutralBackground2: var(--hs-n-100);
	--colorNeutralBackground3: var(--hs-n-250);
	--colorNeutralBackground4: var(--hs-n-300);
	--colorSubtleBackgroundHover: var(--hs-n-250);
	--colorSubtleBackgroundPressed: var(--hs-n-300);

	--colorNeutralStroke1: var(--hs-n-400);
	--colorNeutralStroke1Hover: var(--hs-n-500);
	--colorNeutralStroke1Pressed: var(--hs-n-500);
	--colorNeutralStroke2: var(--hs-n-300);
	--colorNeutralStrokeAccessible: var(--hs-n-500);
	--colorNeutralStrokeAccessibleHover: var(--hs-n-500);
	--colorNeutralStrokeAccessiblePressed: var(--hs-n-500);
}

/* ---- buttons: 4's shape and appearances ----------------------------------
   5's button is semibold, 12px padded and at least 96px wide; 4's was regular
   weight, 10px padded and as wide as its label. The appearances map 4 → 5 as
   Accent → Primary, Neutral → Default, Outline → Outline, Stealth → Subtle and
   Lightweight → Transparent; 4 filled the last two faintly (the stealth fill),
   printed Lightweight in the accent, and drew the icons of every button but the
   accent one in the accent. A disabled 4 button was the same button at 30%. The
   host is the button in 5 (4's was the control part), and an outer rule on the
   host outranks the component's own :host rules. */
fluent-button,
fluent-anchor-button,
fluent-menu-button {
	font-weight: var(--fontWeightRegular);
	min-width: 0;
	padding: 0 10px;
}

fluent-button:is([appearance='subtle'], [appearance='transparent']),
fluent-anchor-button:is([appearance='subtle'], [appearance='transparent']),
fluent-menu-button:is([appearance='subtle'], [appearance='transparent']) {
	background-color: var(--neutral-fill-stealth-rest);
}

fluent-button:is([appearance='subtle'], [appearance='transparent']):hover,
fluent-anchor-button:is([appearance='subtle'], [appearance='transparent']):hover,
fluent-menu-button:is([appearance='subtle'], [appearance='transparent']):hover {
	background-color: var(--neutral-fill-stealth-hover);
}

fluent-button:is([appearance='subtle'], [appearance='transparent']):active,
fluent-anchor-button:is([appearance='subtle'], [appearance='transparent']):active,
fluent-menu-button:is([appearance='subtle'], [appearance='transparent']):active {
	background-color: var(--neutral-fill-stealth-active);
}

fluent-button[appearance='transparent'],
fluent-anchor-button[appearance='transparent'],
fluent-menu-button[appearance='transparent'] {
	color: var(--colorBrandForeground1);
}

fluent-button[appearance='transparent']:hover,
fluent-anchor-button[appearance='transparent']:hover,
fluent-menu-button[appearance='transparent']:hover {
	color: var(--colorBrandForeground2);
}

/* The icon's fill is an inline currentColor; only !important reaches it. */
fluent-button:not([appearance='primary']) > svg:is([slot='start'], [slot='end']),
fluent-anchor-button:not([appearance='primary']) > svg:is([slot='start'], [slot='end']),
fluent-menu-button:not([appearance='primary']) > svg:is([slot='start'], [slot='end']) {
	fill: var(--colorBrandForeground1) !important;
}

/* Disabled: the enabled look at 30%, whatever the appearance. */
:is(fluent-button, fluent-anchor-button, fluent-menu-button):is([disabled], [disabled-focusable]) {
	opacity: 0.3;
	background-color: var(--colorNeutralBackground1);
	border-color: var(--colorNeutralStroke1);
	color: var(--colorNeutralForeground1);
}

:is(fluent-button, fluent-anchor-button, fluent-menu-button)[appearance='primary']:is([disabled], [disabled-focusable]) {
	background-color: var(--colorBrandBackground);
	border-color: transparent;
	color: var(--colorNeutralForegroundOnBrand);
}

:is(fluent-button, fluent-anchor-button, fluent-menu-button):is([appearance='subtle'], [appearance='transparent']):is([disabled], [disabled-focusable]) {
	background-color: var(--neutral-fill-stealth-rest);
	border-color: transparent;
}

:is(fluent-button, fluent-anchor-button, fluent-menu-button)[appearance='transparent']:is([disabled], [disabled-focusable]) {
	color: var(--colorBrandForeground1);
}

:is(fluent-button, fluent-anchor-button, fluent-menu-button)[appearance='outline']:is([disabled], [disabled-focusable]) {
	background-color: transparent;
}

/* ---- text inputs: 4's flat stroke --------------------------------------
   4's inputs had one flat 1px stroke all round (the gradient trick this file
   used to flatten), and focus turned the whole stroke accent instead of drawing
   an underline. 5 draws a darker bottom edge and a 2px underline on focus (its
   .root::after, coloured by --colorCompoundBrandStroke, cleared here for text
   inputs only). The inset is 4's too: none on the root, 9px on the control, so
   the app's ::part(control) paddings mean what they meant; a start or end
   adornment (the search glyph, a chevron) keeps its own. */
fluent-text-input,
fluent-textarea {
	--colorCompoundBrandStroke: transparent;
	--colorCompoundBrandStrokePressed: transparent;
}

fluent-text-input::part(root),
fluent-textarea::part(root) {
	border-color: var(--colorNeutralStroke1);
}

fluent-text-input::part(root) {
	padding: 0;
}

fluent-text-input::part(control) {
	padding: 0 9px;
}

fluent-text-input > [slot='start'] {
	padding-inline-start: 9px;
}

fluent-text-input > [slot='end'] {
	padding-inline-end: 4px;
}

fluent-text-input:not([disabled]):focus-within::part(root),
fluent-textarea:not([disabled]):focus-within::part(root) {
	border: 1px solid var(--colorBrandBackground);
}

/* ---- field labels: 4's ----------------------------------------------------
   4 rendered a field's Label as a sibling <label for> of the field, so the
   layout around it placed the two: stacked in a block, side by side in a flex
   row. 5 puts label and field into one fluent-field grid, label above, and the
   field's Style onto that wrapper, which sizes the label along with the field.
   Where the markup relies on the side-by-side placement (the Signal Builder's
   rows, the setup's account row, HsNumberInput) it renders the sibling label
   itself, as .hs-input-label; the fields left with a label above take 4's
   label look through 5's. */
.hs-input-label,
fluent-field:has(> :is(fluent-text-input, fluent-textarea, fluent-dropdown)) > label[slot='label'] {
	display: flex;
	margin-bottom: 4px;
	color: var(--neutral-foreground-rest);
	font-family: var(--body-font);
	font-size: 14px;
	line-height: 20px;
	font-weight: var(--fw-regular);
	cursor: pointer;
}

.hs-input-required {
	padding-inline-start: 4px;
	color: var(--error);
	pointer-events: none;
}

/* ---- tabs: 4's 40px row ---------------------------------------------------
   4's tabs were 40px high with 6px of side padding and accent icons; 5's are
   44px with 10px. (5 underlines the whole label where 4 drew a short 20px
   stub under its middle; that stays 5's.) */
fluent-tablist {
	--tabPaddingInline: 6px;
	--tabPaddingBlock: 10px;
}

fluent-tab > svg[slot='start'] {
	width: 18px;
	fill: var(--colorBrandForeground1) !important;
}

/* ---- cards: 4's 20px inset (5: 12px) ------------------------------------ */
:is(fluent-card, .fluent-card) {
	padding: 20px;
}

/* ---- data grids: 4's cell inset ---------------------------------------- */
.fluent-data-grid td[role='gridcell'] {
	padding-inline: 16px;
}

/* ---- checkboxes: 4's 20px box with the product radius ------------------
   5's box is 16px with a 2px radius and a 12px check; zoomed by 5/4 it is 4's
   20px box with a 15px check, and 9px corners. */
fluent-checkbox {
	zoom: 1.25;
	border-radius: calc(var(--radius-lg) / 1.25);
}

/* ---- base element defaults (design system tokens/base.css) ---- */
body {
	font-family: var(--font-sans);
	font-size: var(--text-body2);
	line-height: var(--lh-body);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

::selection {
	background: var(--navy-200);
	color: var(--navy-900);
}

/* Sentence-case headings on the MD ramp. The display face stays reserved for
   the wordmark and hero titles — never body, never section headings. */
h1 {
	font-family: var(--font-sans);
	font-size: var(--text-h4);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-tight);
	font-weight: var(--fw-semibold);
}

h2 {
	font-size: var(--text-h5);
	line-height: var(--lh-heading);
	font-weight: var(--fw-semibold);
}

h3 {
	font-size: var(--text-h6);
	line-height: var(--lh-heading);
	font-weight: var(--fw-semibold);
}

h4 {
	font-size: var(--text-subtitle1);
	line-height: var(--lh-body);
	font-weight: var(--fw-semibold);
}

/* Checksums, serials, node paths, generated JSON. */
code,
kbd,
samp,
pre {
	font-family: var(--font-mono);
}

/* ---- eye-catcher surfaces (opt-in) ----
   Available for the appbar/hero when the shell chrome is taken on; nothing
   applies these automatically today. */
.hs-appbar {
	background: var(--gradient-appbar);
	background-size: 200% 100%;
	color: #FFFFFF;
	animation: hs-appbar-sheen 7s linear infinite;
}

.hs-hero {
	background: var(--gradient-hero);
	color: #FFFFFF;
	border-radius: var(--radius-lg);
}

@keyframes hs-appbar-sheen {
	0% {
		background-position: -140% 0;
	}

	100% {
		background-position: 240% 0;
	}
}

@keyframes hs-pulse {
	0%, 100% {
		opacity: 1;
	}

	50% {
		opacity: .45;
	}
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
	}
}
