/* ============================================================================
   Klar - the Asset Db Manager UI layer
   ============================================================================

   This file carries the *structure* of the design: flatness, hairlines, radius,
   density, typography and motion. It carries almost no colour of its own -
   everything is read from --mud-palette-*, so the layer composes with whatever
   theme the user has selected (see installer/themes/Klar.scss for the palette
   this was designed against).

   Two things to know before editing:

   1. Load order. This stylesheet comes after MudBlazor.min.css in the host page
      (see frontend/Components/FrontendApp.razor and desktop/wwwroot/index.html;
      only the workspace sheets klar/*.css follow it), so for equal specificity it
      beats MudBlazor. Do not add !important just to win - check the specificity
      first.

   2. MudThemeProvider writes its custom properties into a <style> element in
      the BODY, i.e. after this file. Plain ":root" here would lose to it, which
      is why the token block below uses ":root:root" - same element, one extra
      pseudo-class of specificity, so it wins regardless of source order.

   Sections
     1. tokens
     2. type
     3. app shell - appbar
     4. app shell - drawer and nav
     5. surfaces
     6. buttons
     7. inputs and focus
     8. tables and data
     9. chips, badges, alerts
    10. overlays - menu, dialog, tooltip, snackbar
    11. motion
    12. explorer tree rows (Products, tree view)
    14. primary as ink
    15. command palette (Ctrl+K)
    16. page patterns (Components/Klar: identity header, facts, cards,
        chips, timeline, save bar, danger zone, empty state, confirm)
    17. shared parts of the workspaces (Phase 7: the rules of the replaced pages
        are gone; the workspaces have their own sheets in klar/*.css)
   ========================================================================= */

/* == 1. tokens ============================================================ */

:root:root {
    /* 10px on controls reads softer than MudBlazor's 4px without going pill.
       .mud-button-root and .mud-paper both derive from this one variable. */
    --mud-default-borderradius: 10px;

    /* The appbar is a thin band, not a header. Safe to change: .mud-main-content
       derives its padding-top from this variable, so content follows. */
    --mud-appbar-height: 56px;

    /* Deliberately NOT setting --mud-drawer-width-*: MudBlazor assigns those at
       runtime from the drawer's actual width (they are consumed but never
       declared in MudBlazor.min.css). Overriding them here would offset
       .mud-main-content by a width the drawer does not actually have. Change the
       drawer width via MudDrawer's Width parameter instead. */

    /* Klar's own tokens. Colour-free apart from deriving the brand accent from
       the palette, so a different theme restyles the whole layer for free. */
    --klar-accent: var(--mud-palette-tertiary);
    --klar-hairline: var(--mud-palette-lines-default);

    /* Primary used as TEXT (links, text/outlined buttons, focused labels, active
       tabs, highlights) rather than as a fill. It is the primary itself unless a
       theme overrides it: a theme file may declare any --klar-* token, e.g.
       $--klar-primary-ink or $--klar-accent (ThemeService collects them,
       ThemeTokens.razor writes them). Purple-dark sets the ink because it keeps
       the brand #a51482 for fills while that colour reads at only 2:1 as text
       on its dark canvas (see section 14); both Purple themes and Nucera set
       the accent apart from Tertiary. */
    --klar-primary-ink: var(--mud-palette-primary);
    --klar-radius-card: 12px;
    --klar-radius-control: 10px;

    /* On the dark drawer, palette lines/dividers would draw a bright band, so
       the rail gets alpha-white separators and alpha-white hover states. A
       theme whose shell is not an ink (Nucera's is the brand magenta) retunes
       all three from its theme file.

       --klar-rail-accent is the accent ON the drawer: the active item's leading
       rail and icon, and keyboard focus inside the drawer. It is the accent
       itself unless a theme sets it - which a theme has to do when its drawer
       is too light or too saturated for one colour to be both a focus ring on
       the white canvas and a mark on the drawer (Nucera.scss). */
    --klar-rail-hover: rgba(255, 255, 255, .06);
    --klar-rail-active: rgba(255, 255, 255, .10);
    --klar-rail-line: rgba(255, 255, 255, .07);
    --klar-rail-accent: var(--klar-accent);

    --klar-ease: cubic-bezier(.2, .7, .3, 1);
    --klar-micro: 120ms;
    --klar-standard: 240ms;
}

/* == 2. type ============================================================== */

/* Segoe UI Variable is present on Windows 11 and is what the WebView renders
   with natively; the fallbacks cover Linux containers and older Windows. The
   Display/Text optical sizes give hierarchy without a second family. */
:root:root {
    --klar-font-ui: "Segoe UI Variable Text", "Segoe UI", -apple-system, system-ui, "Roboto", "Helvetica Neue", Arial, sans-serif;
    --klar-font-display: "Segoe UI Variable Display", "Segoe UI Variable Text", "Segoe UI", system-ui, "Roboto", sans-serif;
    --klar-font-mono: "Cascadia Code", "Cascadia Mono", ui-monospace, Consolas, "SF Mono", monospace;

    --mud-typography-default-family: var(--klar-font-ui);
    --mud-typography-body1-family: var(--klar-font-ui);
    --mud-typography-body2-family: var(--klar-font-ui);
    --mud-typography-button-family: var(--klar-font-ui);
    --mud-typography-caption-family: var(--klar-font-ui);
    --mud-typography-overline-family: var(--klar-font-ui);
    --mud-typography-subtitle1-family: var(--klar-font-ui);
    --mud-typography-subtitle2-family: var(--klar-font-ui);
    --mud-typography-h1-family: var(--klar-font-display);
    --mud-typography-h2-family: var(--klar-font-display);
    --mud-typography-h3-family: var(--klar-font-display);
    --mud-typography-h4-family: var(--klar-font-display);
    --mud-typography-h5-family: var(--klar-font-display);
    --mud-typography-h6-family: var(--klar-font-display);

    /* SHOUTING BUTTONS are the single most dated thing about stock Material. */
    --mud-typography-button-text-transform: none;
    --mud-typography-button-weight: 600;
    --mud-typography-button-letterspacing: .01em;
}

/* Headings: tighter tracking and balanced wrapping. MudBlazor's h1-h3 are very
   large; we pull them in so a page title sits in the layout instead of over it. */
.mud-typography-h1,
.mud-typography-h2,
.mud-typography-h3,
.mud-typography-h4,
.mud-typography-h5,
.mud-typography-h6 {
    letter-spacing: -.015em;
    text-wrap: balance;
}

.mud-typography-h3 {
    font-size: 1.75rem;
    font-weight: 650;
    line-height: 1.2;
}

.mud-typography-h4 {
    font-size: 1.5rem;
    font-weight: 650;
    line-height: 1.25;
}

.mud-typography-h5 {
    font-size: 1.25rem;
    font-weight: 650;
}

.mud-typography-h6 {
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: -.005em;
}

/* Uppercase micro-labels get tracking, otherwise they set too tight. */
.mud-typography-overline {
    letter-spacing: .09em;
    font-weight: 650;
}

/* == 3. app shell - appbar ================================================ */

/* Flat band with a hairline instead of a drop shadow. In the Klar themes the
   appbar is petrol in BOTH light and dark, so together with the drawer it forms
   one continuous dark shell around a light content canvas (see the note in
   Klar.scss for why it is not white). The separator therefore uses the
   alpha-white rail line, not the light-surface hairline, which would draw a
   bright band across a dark bar.

   Nothing here hardcodes a text colour: anything inside the appbar that must be
   legible reads var(--mud-palette-appbar-text), so a theme is free to invert
   the bar without edits to this file. */
.mud-appbar {
    box-shadow: none !important;
    border-bottom: 1px solid var(--klar-rail-line);
}

.mud-appbar .mud-toolbar-appbar {
    gap: .5rem;
}

/* Icon buttons in the appbar inherit the appbar text colour rather than the
   palette default, so they stay visible on both a light and a dark appbar. */
.mud-appbar .mud-button-root.mud-icon-button,
.mud-appbar .mud-icon-root {
    color: var(--mud-palette-appbar-text);
}

/* Alpha-white rather than a primary tint: primary is a deep cyan tuned for
   contrast against white and barely registers on the petrol bar. */
.mud-appbar .mud-button-root.mud-icon-button:hover {
    background-color: var(--klar-rail-hover);
}

/* The search in the appbar is the command palette's trigger (section 15). It
   only derives tints from --mud-palette-appbar-text, so unlike the search box it
   replaced it reads on a light appbar too (KLAR-DESIGN-NOTES.md 1.3). */

/* The logo/title links in the appbar. */
.mud-appbar a {
    color: var(--mud-palette-appbar-text);
    text-decoration: none;
    border-radius: var(--klar-radius-control);
    transition: opacity var(--klar-micro) ease;
}

.mud-appbar a:hover {
    opacity: .82;
}

/* The content well. This class owns the appbar offset AND the gutter together,
   which is not merely tidier - it is the fix for a real trap.

   .mud-main-content clears the fixed appbar with
       padding-top: var(--mud-appbar-height)
   but every MudBlazor spacing utility is !important, so the previous
   Class="mt-16 pa-4" had pa-4's `padding: 16px !important` silently overwrite
   that reservation, and mt-16 (a hardcoded `margin-top: 64px !important`) was
   the patch that pushed the content back down. Remove one without the other and
   the first element on every page slides under the appbar.

   Keeping both values in one declaration means no utility can clobber half of
   it. The breakpoints mirror MudBlazor's own toolbar-height calc so the content
   sits just below the bar at every width. */
.mud-main-content.klar-main {
    padding: calc(var(--mud-appbar-height) - var(--mud-appbar-height) / 8 + 1rem) 1rem 1rem;
}

@media (min-width: 600px) {
    .mud-main-content.klar-main {
        padding-top: calc(var(--mud-appbar-height) + 1rem);
    }
}

/* == 4. app shell - drawer and nav ======================================== */

/* The drawer is the design's one bold surface: petrol ink, full height, no
   shadow. It is where the brand colour lives. */
.mud-drawer {
    box-shadow: none !important;
    border-right: 1px solid var(--klar-rail-line);
}

.mud-drawer .mud-drawer-content {
    padding: .5rem .5rem 1rem;
}

/* Section separators inside the rail: palette dividers are tuned for light
   surfaces and would draw a bright line here. */
.mud-drawer .mud-divider {
    border-color: var(--klar-rail-line);
    margin: .5rem .25rem;
}

.mud-drawer .mud-nav-link,
.mud-drawer .mud-nav-group > .mud-nav-link {
    border-radius: var(--klar-radius-control);
    margin: 1px 0;
    padding: 7px 12px;
    font-size: .875rem;
    font-weight: 450;
    color: var(--mud-palette-drawer-text);
    transition: background-color var(--klar-micro) ease, color var(--klar-micro) ease;
    /* MudBlazor aligns nav content to flex-start, which reads as top-aligned the
       moment a label takes two lines (see the wrapping rules below). min-height
       keeps a one-line item exactly as tall as it was before wrapping existed. */
    align-items: center;
    min-height: 34px;
}

.mud-drawer .mud-nav-link .mud-nav-link-icon {
    color: var(--mud-palette-drawer-icon);
    min-width: 34px;
    transition: color var(--klar-micro) ease;
}

/* Rail labels wrap. They do not scroll sideways, and they do not get cut off.

   Worth knowing before editing: MudBlazor does NOT set white-space:nowrap on
   drawer nav labels. The only rule that does is
     .page-content-navigation .page-content-navigation-navlink .mud-nav-link .mud-nav-link-text
   which is scoped to MudBlazor's own documentation site and never matches here,
   and this file has never set it either - so a label containing spaces has
   always wrapped. What overflowed is the single unbreakable token this domain
   names almost everything with (ElementAssembly, AnodeFrame,
   Zellenrahmen_Beschichtungscharge): overflow-wrap defaults to `normal`, the
   browser refuses to break inside a word, the label overruns the 240px rail and
   the drawer clips whatever sticks out. Blocking horizontal scroll did not cause
   that truncation, it only removed the way to see past it.

   So `anywhere` is the floor, and <TextWithBreaks> (see NavMenu.razor) supplies
   <wbr> hints at CamelCase / underscore / digit boundaries so breaks land on
   word parts rather than arbitrary characters. Two lines is the cap on purpose:
   a rail of three- and four-line items stops being scannable, which is the thing
   truncation was costing us to begin with. Anything longer is ellipsised here
   and carried in full by the title attribute.

   The .mud-typography rule below is insurance rather than a no-op. TextWithBreaks
   wraps its output in a MudText, which at the default Typo.inherit renders
   <span class="mud-typography mud-typography-inherit"> - already inline, so today
   the rule changes nothing. It matters the moment someone passes a block Typo
   (Operations/Edit.razor already does that elsewhere: Typo="Typo.body1"): the
   legacy -webkit-line-clamp path counts line boxes of INLINE content, so with a
   block child the clamp lands on a ragged 50px / 2.78 lines instead of a clean
   36px / 2. Measured in Chrome against this markup, not assumed.

   One measuring gotcha for whoever verifies this next: on Chrome 138+ an active
   -webkit-line-clamp reports `display: flow-root` rather than `-webkit-box`, even
   when the declaration is forced inline. That is the clamp working, not a rule
   being overridden. `display: -webkit-box` still has to stay for the older
   engines - notably whatever WebView2 runtime the desktop host happens to have. */
.mud-drawer .mud-nav-link .mud-nav-link-text .mud-typography {
    display: inline;
}

.mud-drawer .mud-nav-link .mud-nav-link-text {
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    line-height: 1.28;
}

.mud-drawer .mud-nav-link:hover:not(.mud-nav-link-disabled) {
    background-color: var(--klar-rail-hover);
    color: var(--mud-palette-white);
}

.mud-drawer .mud-nav-link:hover:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: var(--mud-palette-white);
}

/* Active state. MudBlazor's default paints the label with
   --mud-palette-primary and draws a border on the INLINE-END edge. Primary is a
   deep cyan chosen for contrast against white, so on the petrol rail it is
   nearly invisible - hence the explicit override to white text plus a bright
   accent rail on the leading edge.

   SPECIFICITY: the rule being overridden is
     .mud-navmenu.mud-navmenu-default .mud-nav-link.active:not(.mud-nav-link-disabled)
   which is five classes. `.mud-drawer .mud-nav-link.active:not(...)` is only four
   and loses no matter how late this file loads, so `.mud-navmenu` is part of the
   selector below to get to six. Do not "simplify" it away - the active label
   silently reverts to an unreadable deep cyan on the petrol rail. */
.mud-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
    color: var(--mud-palette-white);
    font-weight: 600;
    background-color: var(--klar-rail-active);
    border-inline-end-width: 0;
    position: relative;
}

.mud-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled)::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background-color: var(--klar-rail-accent);
}

.mud-drawer .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: var(--klar-rail-accent);
}

/* Six classes, to match MudBlazor's own active+hover rule. */
.mud-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled):hover:not(.mud-nav-link-disabled) {
    background-color: var(--klar-rail-active);
}

/* Nested links sit quieter than their group header. */
.mud-drawer .mud-nav-group .mud-nav-group .mud-nav-link {
    font-size: .8125rem;
}

/* The expand chevron. MudBlazor colours the *expanded* one with
     .mud-navmenu.mud-navmenu-default .mud-nav-link-expand-icon.mud-transform { fill: primary }
   - note `fill`, not `color`, so setting colour alone leaves an expanded group's
   chevron in deep cyan, which is close to unreadable on the petrol rail. Both
   properties are set here, and the selector carries .mud-navmenu to outrank it. */
.mud-drawer .mud-nav-group-header-expanded,
.mud-drawer .mud-nav-link-expand-icon {
    color: var(--mud-palette-drawer-icon);
    fill: var(--mud-palette-drawer-icon);
}

.mud-drawer .mud-navmenu .mud-nav-link-expand-icon.mud-transform {
    fill: var(--mud-palette-white);
}

/* == 5. surfaces ========================================================== */

/* Hairline, not shadow. Cards are separated by a 1px line and their own
   background; elevation is reserved for things that genuinely float (menus,
   dialogs, snackbars) - see section 10. */
.mud-paper {
    border-radius: var(--klar-radius-card);
    background-image: none;
}

.mud-paper.mud-elevation-0,
.mud-paper.mud-elevation-1,
.mud-paper.mud-elevation-2 {
    box-shadow: none !important;
    border: 1px solid var(--klar-hairline);
}

/* Papers that are only a positioning context (the layout root, drawer, appbar)
   must not pick up the card border. */
.mud-drawer.mud-paper,
.mud-appbar.mud-paper,
.mud-layout > .mud-paper:not(.mud-card) {
    border: 0;
}

.mud-drawer.mud-paper {
    border-right: 1px solid var(--klar-rail-line);
}

.mud-appbar.mud-paper {
    border-bottom: 1px solid var(--klar-rail-line);
}

.mud-card {
    border-radius: var(--klar-radius-card);
}

.mud-card-header {
    padding: 1rem 1.0625rem .5rem;
}

/* Expansion panels: stock MudBlazor stacks them with hard shadows. */
.mud-expansion-panels .mud-expand-panel {
    border: 1px solid var(--klar-hairline);
    box-shadow: none !important;
    background-image: none;
}

.mud-expansion-panels .mud-expand-panel:not(:first-child) {
    border-top: 0;
}

.mud-expansion-panels .mud-expand-panel:first-child {
    border-top-left-radius: var(--klar-radius-card);
    border-top-right-radius: var(--klar-radius-card);
}

.mud-expansion-panels .mud-expand-panel:last-child {
    border-bottom-left-radius: var(--klar-radius-card);
    border-bottom-right-radius: var(--klar-radius-card);
}

.mud-expand-panel .mud-expand-panel-header {
    transition: background-color var(--klar-micro) ease;
}

.mud-expand-panel .mud-expand-panel-header:hover {
    background-color: rgba(var(--mud-palette-primary-rgb), .04);
}

.mud-divider {
    border-color: var(--klar-hairline);
}

/* == 6. buttons =========================================================== */

/* One filled button per view is the rule the design asks for; everything else
   is outlined or text. That is a markup decision, but the styling here makes
   the quiet variants look deliberate rather than unfinished. */
.mud-button-root {
    text-transform: none;
    letter-spacing: .01em;
    transition: background-color var(--klar-micro) ease,
                border-color var(--klar-micro) ease,
                color var(--klar-micro) ease,
                transform var(--klar-micro) ease;
}

.mud-button-root:active {
    transform: translateY(1px);
}

/* Flat fills. MudBlazor gives filled buttons a 3-layer Material shadow; the
   markup mostly passes DropShadow="false" already, this covers the rest. */
.mud-button-filled {
    box-shadow: none !important;
}

.mud-button-filled:hover {
    box-shadow: none !important;
}

/* Color.Default filled buttons are painted with action-default-hover, which is a
   near-invisible tint on a flat surface - next to a real filled button they read
   as plain text, so they get an edge to still look pressable. */
.mud-button-filled.mud-button-filled-default {
    border: 1px solid var(--mud-palette-lines-default);
}

.mud-button-outlined {
    border-color: var(--mud-palette-lines-inputs);
}

.mud-button-outlined:hover {
    border-color: var(--klar-primary-ink);
    color: var(--klar-primary-ink);
    background-color: rgba(var(--mud-palette-primary-rgb), .06);
}

/* FABs are round by definition, but the huge default shadow is not. */
.mud-button-fab {
    box-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 6px 16px -8px rgba(0, 0, 0, .25) !important;
}

.mud-icon-button {
    border-radius: var(--klar-radius-control);
}

.mud-toggle-group {
    border-radius: var(--klar-radius-control);
    border-color: var(--klar-hairline);
}

/* == 7. inputs and focus ================================================== */

.mud-input.mud-input-outlined .mud-input-outlined-border {
    border-radius: var(--klar-radius-control);
    border-color: var(--mud-palette-lines-inputs);
    transition: border-color var(--klar-micro) ease, box-shadow var(--klar-micro) ease;
}

.mud-input.mud-input-outlined:hover .mud-input-outlined-border {
    border-color: var(--klar-primary-ink);
}

/* A visible ring on the focused field, in the accent. The accent is used here
   rather than a neutral because focus is the one place the brand colour is
   genuinely useful, and at 3px it clears the 3:1 non-text contrast bar. */
.mud-input.mud-focused.mud-input-outlined .mud-input-outlined-border {
    border-width: 1px;
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), .18);
}

.mud-input-filled,
.mud-input-filled.mud-input-filled-with-label {
    border-radius: var(--klar-radius-control) var(--klar-radius-control) 0 0;
}

/* Keyboard focus must always be visible. MudBlazor relies on ripple and
   background tints, which vanish on flat surfaces. */
.mud-button-root:focus-visible,
.mud-nav-link:focus-visible,
.mud-icon-button:focus-visible,
.mud-chip:focus-visible,
.mud-table-row:focus-visible {
    outline: 2px solid var(--klar-accent);
    outline-offset: 2px;
}

/* Inside the drawer the ring sits on the drawer, so it takes the on-drawer
   accent (the accent itself unless a theme splits the two). */
.mud-drawer .mud-nav-link:focus-visible {
    outline-color: var(--klar-rail-accent);
    outline-offset: -2px;
}

/* In the appbar the accent can sit on a coloured bar (Purple's is the brand
   magenta, where its orchid accent measures 2:1). The bar's own text colour is
   legible there by definition. */
.mud-appbar .mud-button-root:focus-visible,
.mud-appbar .mud-icon-button:focus-visible {
    outline-color: var(--mud-palette-appbar-text);
}

/* == 8. tables and data =================================================== */

/* Column heads become quiet labels on a tinted band, so the eye goes to the
   data and not the chrome.

   Deliberately NO text-transform here (the mockup had uppercase): column titles
   include camelCase identifiers like "TagChangeId" on the edit-history grid,
   which uppercase mangles into "TAGCHANGEID", and long localized German titles
   that all-caps makes wider still. The quietness comes from size, weight and
   the tinted band instead. */
.mud-table-head .mud-table-cell,
.mud-table .mud-table-head .mud-table-cell {
    font-size: .75rem;
    font-weight: 650;
    letter-spacing: .01em;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-background-gray);
    border-bottom: 1px solid var(--klar-hairline);
    white-space: nowrap;
}

.mud-table-cell {
    border-bottom-color: var(--mud-palette-table-lines);
}

.mud-table-container .mud-table-row {
    transition: background-color var(--klar-micro) ease;
}

.mud-table-toolbar {
    border-bottom: 1px solid var(--klar-hairline);
}

/* Digits that sit in a column must not wobble between rows. Applied to table
   cells and to the numeric/data helpers, not globally - proportional figures
   are better in running prose. */
.mud-table-cell,
.mud-table-pagination,
.klar-num {
    font-variant-numeric: tabular-nums;
}

/* Identifiers, serials and paths read as data, not prose. Opt in per element
   with Class="klar-mono". */
.klar-mono {
    font-family: var(--klar-font-mono);
    font-size: .9em;
    letter-spacing: 0;
}

/* BlazorDatasheet and the diagram surfaces sit inside cards; keep their own
   chrome from doubling up on ours. */
.sheet-container,
.diagram-canvas {
    border-radius: var(--klar-radius-card);
}

/* == 9. chips, badges, alerts ============================================= */

/* Status must never be colour alone - the markup supplies an icon and a label,
   this just makes the pill quiet enough to sit in a dense table. */
.mud-chip {
    font-weight: 600;
    font-size: .75rem;
    border-radius: 999px;
    transition: background-color var(--klar-micro) ease, border-color var(--klar-micro) ease;
}

.mud-chip.mud-chip-size-small {
    font-size: .6875rem;
}

.mud-alert {
    border-radius: var(--klar-radius-card);
    box-shadow: none !important;
    border: 1px solid var(--klar-hairline);
}

.mud-badge.mud-badge-dot {
    border: 2px solid var(--mud-palette-surface);
}

.mud-progress-linear {
    border-radius: 999px;
    overflow: hidden;
}

/* == 10. overlays - menu, dialog, tooltip, snackbar ======================= */

/* Things that genuinely float keep a shadow - but a soft two-layer one, not
   Material's three-layer stack. */
.mud-popover,
.mud-menu-popover,
.mud-picker-popover {
    border-radius: var(--klar-radius-card);
    border: 1px solid var(--klar-hairline);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 12px 32px -12px rgba(0, 0, 0, .28) !important;
}

.mud-list-item {
    border-radius: 8px;
    margin: 1px .25rem;
    transition: background-color var(--klar-micro) ease;
}

.mud-dialog {
    border-radius: 14px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, .06), 0 24px 64px -20px rgba(0, 0, 0, .4) !important;
}

.mud-dialog-title {
    font-family: var(--klar-font-display);
    font-weight: 650;
    letter-spacing: -.01em;
}

.mud-tooltip {
    border-radius: 8px;
    font-size: .75rem;
    padding: .375rem .625rem;
}

.mud-snackbar {
    border-radius: var(--klar-radius-card);
}

.mud-tabs .mud-tab {
    text-transform: none;
    font-weight: 600;
    letter-spacing: .01em;
}

.mud-tabs-toolbar {
    border-bottom: 1px solid var(--klar-hairline);
}

/* == 11. motion =========================================================== */

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

/* == 12. explorer tree rows (Products, tree view) ======================= */

/* One hairline per level. Bare indentation is what makes a deep tree unreadable;
   the guides are drawn as a background so they cost no elements per row. The
   gradient is sized to the row's own depth, so depth 0 draws nothing. */
.klar-tree-row {
    display: flex;
    align-items: center;
    gap: .4rem;
    height: 2rem;
    padding-right: .5rem;
    padding-left: calc(var(--klar-tree-depth, 0) * 1.125rem + .375rem);
    cursor: pointer;
    background-repeat: no-repeat;
    background-position: .375rem 0;
    background-size: calc(var(--klar-tree-depth, 0) * 1.125rem) 100%;
    background-image: repeating-linear-gradient(90deg, transparent 0 .5rem, var(--klar-hairline) .5rem calc(.5rem + 1px), transparent calc(.5rem + 1px) 1.125rem);
    transition: background-color var(--klar-micro) ease;
}

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

.klar-tree-row.selected {
    background-color: var(--mud-palette-table-striped);
}

.klar-kv {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: .25rem .625rem;
    margin: 0;
    font-size: .75rem;
}

.klar-kv dt {
    color: var(--mud-palette-text-secondary);
}

.klar-kv dd {
    margin: 0;
    color: var(--mud-palette-text-primary);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

/* == 14. primary as ink =================================================== */

/* MudBlazor paints primary TEXT with --mud-palette-primary, the same token as
   primary FILLS. Every theme but one wants that. Purple-dark keeps the brand
   #a51482 as its fill colour (buttons, switches, selection) but, at 2:1 on its
   dark canvas, it cannot be text there - so these are the places where primary
   is read as text or as a thin line, rerouted through --klar-primary-ink, which a
   theme may lighten (section 1). Themes that do not set it render exactly as
   before: the token defaults to the primary itself.

   The selectors are MudBlazor's own; this file loads after MudBlazor.min.css, so
   equal specificity is enough (and equal !important for .mud-primary-text). */
.mud-primary-text {
    color: var(--klar-primary-ink) !important;
    --mud-ripple-color: var(--klar-primary-ink) !important;
}

.mud-button-text.mud-button-text-primary,
.mud-button-outlined.mud-button-outlined-primary,
.mud-button-group-text.mud-button-group-override-styles.mud-button-group-text-primary .mud-button-root,
.mud-chip-outlined.mud-chip-color-primary,
.mud-chip-text.mud-chip-color-primary,
.mud-avatar-outlined.mud-avatar-outlined-primary,
.mud-alert-text-primary .mud-alert-icon,
.mud-alert-outlined-primary .mud-alert-icon,
.mud-treeview.mud-treeview-selected-primary .mud-treeview-item-content.mud-treeview-item-selected,
.mud-treeview.mud-treeview-checked-primary .mud-treeview-item-checkbox .mud-button-root.mud-icon-button,
.mud-tab.mud-tab-active,
.mud-input:focus-within ~ label.mud-input-label.mud-input-label-inputcontrol {
    color: var(--klar-primary-ink);
    --mud-ripple-color: var(--klar-primary-ink);
}

.mud-input.mud-input-outlined:focus-within > .mud-input-outlined-border,
.mud-input.mud-input-outlined:focus-within .mud-shrink > .mud-input-outlined-border {
    border-color: var(--klar-primary-ink);
}

.mud-input.mud-input-underline::after {
    border-bottom-color: var(--klar-primary-ink);
}

/* == 15. command palette (Ctrl+K) ========================================= */

/* Components/Controls/CommandPalette.razor (app bar trigger) and
   Components/Dialogs/CommandPaletteDialog.razor (the palette). Like the rest of
   this file it only reads palette tokens, so it follows every theme; the trigger
   derives its tints from --mud-palette-appbar-text so it reads on a dark and on
   a coloured bar alike. */

.cp-trigger {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    max-width: 420px;
    height: 36px;
    padding: 0 .375rem 0 .625rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-appbar-text) 22%, transparent);
    border-radius: var(--klar-radius-control);
    background-color: color-mix(in srgb, var(--mud-palette-appbar-text) 9%, transparent);
    color: var(--mud-palette-appbar-text);
    font: inherit;
    font-size: .875rem;
    text-align: start;
    cursor: pointer;
    transition: background-color var(--klar-micro) ease, border-color var(--klar-micro) ease;
}

.cp-trigger:hover {
    background-color: color-mix(in srgb, var(--mud-palette-appbar-text) 15%, transparent);
    border-color: color-mix(in srgb, var(--mud-palette-appbar-text) 34%, transparent);
}

/* the accent may be close to a coloured bar, the bar's own text colour never is */
.cp-trigger:focus-visible {
    outline: 2px solid var(--mud-palette-appbar-text);
    outline-offset: 2px;
}

.mud-appbar .cp-trigger .cp-trigger-icon {
    flex: none;
    color: var(--mud-palette-appbar-text);
}

.cp-trigger-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.cp-kbd {
    display: inline-block;
    min-width: 1.375rem;
    padding: .1875rem .375rem;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-bottom-width: 2px;
    border-radius: 6px;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    font: 600 .6875rem/1 var(--klar-font-ui);
    text-align: center;
    white-space: nowrap;
}

.cp-trigger .cp-trigger-kbd {
    flex: none;
    border-color: color-mix(in srgb, var(--mud-palette-appbar-text) 40%, transparent);
    background-color: transparent;
    color: var(--mud-palette-appbar-text);
}

/* phones: an icon button, the label and the hint would crowd the bar */
@media (max-width: 599.98px) {
    .cp-trigger {
        width: 40px;
        height: 40px;
        justify-content: center;
        padding: 0;
        border-color: transparent;
        background-color: transparent;
    }

    .cp-trigger-label,
    .cp-trigger .cp-trigger-kbd {
        display: none;
    }
}

/* the dialog: top aligned like every palette, so results grow downwards and the
   input never moves while typing */
.mud-dialog-container.mud-dialog-topcenter:has(.cp-dialog) {
    align-items: flex-start;
}

.mud-dialog.cp-dialog {
    width: min(720px, calc(100vw - 2rem));
    max-width: none;
    margin: min(10vh, 88px) 1rem 1rem;
    border: 1px solid var(--klar-hairline);
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 24px 64px -16px rgba(0, 0, 0, .35), 0 2px 8px rgba(0, 0, 0, .08) !important;
}

.mud-dialog.cp-dialog .cp-dialog-content {
    padding: 0;
    overflow: hidden;
}

.cp {
    display: flex;
    flex-direction: column;
    max-height: min(620px, calc(100dvh - min(10vh, 88px) - 2rem));
}

.cp-search {
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: .625rem .875rem .625rem 1rem;
    border-bottom: 1px solid var(--klar-hairline);
}

.cp-search-icon {
    flex: none;
    color: var(--mud-palette-text-secondary);
}

.cp-scope {
    flex: none;
    padding: .125rem .5rem;
    border-radius: 999px;
    background-color: rgba(var(--mud-palette-primary-rgb), .10);
    color: var(--klar-primary-ink);
    font-size: .75rem;
    font-weight: 650;
}

.cp-input {
    flex: 1;
    min-width: 0;
    height: 40px;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: 400 1.0625rem/1.4 var(--klar-font-ui);
}

.cp-input::placeholder {
    color: var(--mud-palette-text-secondary);
    opacity: 1;
}

.cp-spinner {
    flex: none;
}

.cp-results {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: .25rem .5rem .5rem;
}

.cp-group {
    padding-top: .25rem;
}

.cp-group-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .5rem .625rem .25rem;
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
    font-weight: 650;
    letter-spacing: .02em;
}

.cp-group-count {
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.cp-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: .75rem;
    min-height: 44px;
    padding: .3125rem .625rem;
    border-radius: var(--klar-radius-control);
    color: var(--mud-palette-text-primary);
    cursor: pointer;
    user-select: none;
}

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

.cp-item.cp-active {
    background-color: rgba(var(--mud-palette-primary-rgb), .09);
}

/* the leading rail of the active option, the same device as the active nav item */
.cp-item.cp-active::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background-color: var(--klar-primary-ink);
}

.cp-item-icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background-color: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
}

.cp-item.cp-active .cp-item-icon {
    background-color: rgba(var(--mud-palette-primary-rgb), .14);
    color: var(--klar-primary-ink);
}

.cp-item-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.cp-item-title,
.cp-item-subtitle {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.cp-item-title {
    font-size: .9375rem;
    font-weight: 500;
    line-height: 1.35;
}

.cp-item-subtitle {
    color: var(--mud-palette-text-secondary);
    font-size: .8125rem;
    line-height: 1.35;
}

.cp-hl {
    background: transparent;
    color: var(--klar-primary-ink);
    font-weight: 700;
}

.cp-item.cp-muted .cp-item-title {
    color: var(--mud-palette-text-secondary);
}

.cp-item.cp-show-all .cp-item-title {
    color: var(--klar-primary-ink);
    font-size: .875rem;
    font-weight: 600;
}

.cp-state {
    padding: 1.75rem 1rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    font-size: .875rem;
}

.cp-state-error {
    color: var(--mud-palette-error);
}

.cp-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .375rem 1.125rem;
    padding: .5rem 1rem;
    border-top: 1px solid var(--klar-hairline);
    background-color: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
}

.cp-footer > span,
.cp-footer-prefixes > span {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
}

.cp-footer-prefixes {
    display: inline-flex;
    gap: 1.125rem;
    margin-inline-start: auto;
}

.cp-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (max-width: 599.98px) {
    .mud-dialog.cp-dialog {
        width: calc(100vw - 1rem);
        margin: .5rem;
    }

    .cp {
        max-height: calc(100dvh - 1rem);
    }

    .cp-footer-optional,
    .cp-search-esc {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .cp-trigger,
    .cp-item {
        transition: none;
    }
}

/* == 16. page patterns ==================================================== */

/* Tones for chips, dots and edges. Derived from the palette with color-mix so
   every theme (light and dark) gets them for free: the text is the tone mixed
   towards text-primary, which keeps it above 4.5:1 on the tinted background in
   Klar light (computed from the palette: neutral 8.2:1, primary 7.0:1,
   success 5.1:1, warning 5.4:1, error 6.3:1) and turns lighter, not darker,
   in the dark themes. */
:root:root {
    --klar-tone-neutral: var(--mud-palette-text-secondary);
    --klar-tone-primary: var(--klar-primary-ink);
    --klar-tone-success: var(--mud-palette-success);
    --klar-tone-warning: var(--mud-palette-warning);
    --klar-tone-error: var(--mud-palette-error);
    --klar-tone-muted: var(--mud-palette-text-disabled);
}

.klar-mono-strong {
    font-family: var(--klar-font-mono);
    letter-spacing: 0;
}

.klar-spacer {
    flex: 1 1 auto;
}

.klar-muted {
    color: var(--mud-palette-text-secondary);
}

.klar-faint {
    color: var(--mud-palette-text-disabled);
}

/* --- chips ------------------------------------------------------------- */

.klar-chip {
    --klar-tone: var(--klar-tone-neutral);
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    max-width: 100%;
    height: 1.5rem;
    padding: 0 .625rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--klar-tone) 32%, transparent);
    background-color: color-mix(in srgb, var(--klar-tone) 11%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--klar-tone) 64%, var(--mud-palette-text-primary));
    font-size: .75rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
}

.klar-chip-primary { --klar-tone: var(--klar-tone-primary); }
.klar-chip-success { --klar-tone: var(--klar-tone-success); }
.klar-chip-warning { --klar-tone: var(--klar-tone-warning); }
.klar-chip-error { --klar-tone: var(--klar-tone-error); }
.klar-chip-muted { --klar-tone: var(--klar-tone-muted); }

.klar-dot {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: currentColor;
}

.klar-count {
    display: inline-block;
    min-width: 1.25rem;
    padding: 0 .4375rem;
    border-radius: 999px;
    background-color: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1.125rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* --- breadcrumb -------------------------------------------------------- */

.klar-crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem .375rem;
    margin: .125rem 0 .75rem;
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
}

.klar-crumbs ol {
    display: contents;
    list-style: none;
}

.klar-crumbs li {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    min-width: 0;
}

.klar-crumbs .klar-crumb-sep {
    color: var(--mud-palette-text-disabled);
}

.klar-crumbs .klar-crumb-current {
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

/* --- identity header and key facts ------------------------------------- */

.klar-identity {
    overflow: hidden;
}

.klar-identity-main {
    display: flex;
    align-items: flex-start;
    gap: .875rem;
    padding: 1rem;
    flex-wrap: wrap;
}

.klar-typebox {
    display: grid;
    place-items: center;
    flex: none;
    width: 3rem;
    height: 3rem;
    border-radius: var(--klar-radius-card);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    color: var(--klar-primary-ink);
}

.klar-identity-text {
    display: flex;
    flex-direction: column;
    gap: .375rem;
    flex: 1 1 16rem;
    min-width: 0;
}

.klar-identity-title {
    margin: 0;
    font-family: var(--klar-font-display);
    font-size: 1.5rem;
    font-weight: 650;
    line-height: 1.25;
    letter-spacing: -.015em;
    overflow-wrap: anywhere;
}

.klar-identity-title.klar-mono {
    font-family: var(--klar-font-mono);
    font-size: 1.5rem;
    letter-spacing: 0;
}

.klar-identity-chips {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

.klar-identity-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    flex: none;
    max-width: 100%;
}

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

.klar-card-h {
    display: flex;
    align-items: center;
    gap: .625rem;
    min-height: 3rem;
    padding: .5rem 1rem;
    border-bottom: 1px solid var(--klar-hairline);
}

.klar-card-title {
    margin: 0;
    font-family: var(--klar-font-display);
    font-size: .9375rem;
    font-weight: 650;
    letter-spacing: -.005em;
}

.klar-card-b {
    padding: .875rem 1rem;
}

.klar-card-flush > .klar-card-b {
    padding: 0;
}

.klar-danger-zone.mud-paper {
    border-color: color-mix(in srgb, var(--mud-palette-error) 35%, var(--klar-hairline));
}

.klar-danger-zone .klar-card-h {
    border-bottom-color: color-mix(in srgb, var(--mud-palette-error) 35%, var(--klar-hairline));
}

.klar-danger-zone .klar-card-title {
    color: color-mix(in srgb, var(--mud-palette-error) 80%, var(--mud-palette-text-primary));
}

.klar-danger-action {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .5rem;
    font-size: .8125rem;
}

.klar-danger-action + .klar-danger-action {
    margin-top: 1rem;
}

/* --- menus: section titles and destructive entries ------------------------ */

.klar-menu-header {
    padding: .5rem .875rem .25rem;
    font-size: .6875rem;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.klar-menu-header-danger {
    color: color-mix(in srgb, var(--mud-palette-error) 80%, var(--mud-palette-text-primary));
}

.mud-menu-item.klar-menu-danger,
.mud-menu-item.klar-menu-danger .mud-icon-root {
    color: color-mix(in srgb, var(--mud-palette-error) 85%, var(--mud-palette-text-primary));
}

/* --- timeline ------------------------------------------------------------- */

.klar-tl {
    list-style: none;
    margin: 0;
    padding: 0;
}

.klar-tl li {
    display: grid;
    grid-template-columns: .875rem minmax(0, 1fr);
    gap: .625rem;
    padding-bottom: .75rem;
    position: relative;
}

.klar-tl li::before {
    content: "";
    position: absolute;
    left: .375rem;
    top: .875rem;
    bottom: 0;
    width: 1px;
    background-color: var(--klar-hairline);
}

.klar-tl li:last-child::before {
    display: none;
}

.klar-tl-dot {
    --klar-tone: var(--klar-tone-primary);
    width: .8125rem;
    height: .8125rem;
    margin-top: .1875rem;
    border-radius: 50%;
    border: 2px solid var(--klar-tone);
    background-color: var(--mud-palette-surface);
}

.klar-tone-success { --klar-tone: var(--klar-tone-success); }
.klar-tone-warning { --klar-tone: var(--klar-tone-warning); }
.klar-tone-error { --klar-tone: var(--klar-tone-error); }
.klar-tone-neutral,
.klar-tone-muted { --klar-tone: var(--klar-tone-muted); }

.klar-tl-what {
    font-size: .8125rem;
    overflow-wrap: anywhere;
}

.klar-tl-meta {
    font-size: .71875rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* --- sticky save bar --------------------------------------------------------
   Last child of an edit page. It spans the content well (the negative margin
   undoes the klar-main gutter) and sticks to the bottom of the viewport while
   the page is taller than the window. */
.klar-savebar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .625rem;
    margin: 1rem -1rem -1rem;
    padding: .75rem 1rem;
    background-color: var(--mud-palette-surface);
    border-top: 1px solid var(--klar-hairline);
    box-shadow: 0 -8px 24px -18px rgba(0, 0, 0, .4);
}

.klar-savebar-summary {
    min-width: 0;
    flex: 0 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
}

.klar-savebar-spacer {
    flex: 1 1 auto;
}

/* --- empty state ------------------------------------------------------------ */

.klar-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .375rem;
    padding: 2rem 1rem;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

.klar-empty-icon {
    width: 2rem;
    height: 2rem;
    color: var(--mud-palette-text-disabled);
}

.klar-empty-title {
    font-weight: 650;
    color: var(--mud-palette-text-primary);
}

.klar-empty-text {
    max-width: 36rem;
    font-size: .8125rem;
}

.klar-empty-actions {
    display: flex;
    gap: .5rem;
    margin-top: .5rem;
}

/* --- confirm dialog ---------------------------------------------------------- */

.klar-confirm-title {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.klar-confirm-details {
    margin: .5rem 0 0;
    padding-inline-start: 1.125rem;
    max-height: 12rem;
    overflow-y: auto;
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
}

/* --- quiet property/data table (plain <table>, not MudDataGrid) ------------- */

.klar-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: .84375rem;
}

.klar-table th {
    padding: .5625rem .75rem;
    background-color: var(--mud-palette-background-gray);
    border-bottom: 1px solid var(--klar-hairline);
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
    font-weight: 650;
    text-align: start;
    white-space: nowrap;
}

.klar-table td {
    padding: .4375rem .75rem;
    border-bottom: 1px solid var(--mud-palette-table-lines);
    vertical-align: middle;
}

.klar-table tbody tr {
    transition: background-color var(--klar-micro) ease;
}

.klar-table tbody tr:hover > td {
    background-color: var(--mud-palette-table-hover);
}

.klar-table .klar-num {
    text-align: end;
    white-space: nowrap;
}

.klar-table .klar-ghost > td {
    color: var(--mud-palette-text-secondary);
}

.klar-table .klar-row-actions {
    width: 1%;
    white-space: nowrap;
    text-align: end;
}

.klar-prop-name {
    font-weight: 600;
}

.klar-prop-desc {
    font-size: .71875rem;
    color: var(--mud-palette-text-secondary);
}

.klar-empty-cell {
    color: var(--mud-palette-text-disabled);
}

/* --- segmented control (MudToggleGroup) ------------------------------------ */

.klar-seg.mud-toggle-group {
    border-radius: var(--klar-radius-control);
}

/* == 17. shared parts of the workspaces ===================================== */

.klar-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* A hidden label is positioned absolutely: its containing block was the shell, outside the table's scroll container,
   so a label in the last column of a wide table (the "Action" column head) widened the whole page on a phone
   (F-SHELL-21). Its parent is its containing block - the label stays inside whatever scrolls around it. :where keeps
   the specificity at 0: a parent that is positioned otherwise keeps its position. */
:where(:has(> .klar-sr-only)) {
    position: relative;
}

/* focusable menu activators that wrap text (the value cells of the ECMS reports) */
.klar-menu-activator {
    display: inline-block;
    max-width: 100%;
    cursor: pointer;
    border-radius: 4px;
}

.klar-menu-activator:focus-visible {
    outline: 2px solid var(--klar-accent);
    outline-offset: 2px;
}

/* the "Add" of an empty grid cell only shows while the row is hovered or focused */
.klar-cell-add.mud-button-root {
    display: none;
    min-width: 0;
    padding: 0 .375rem;
    height: 1.5rem;
}

tr:hover .klar-cell-add.mud-button-root,
tr:focus-within .klar-cell-add.mud-button-root {
    display: inline-flex;
}

tr:hover .klar-cell-add + .klar-empty-cell,
tr:hover .klar-empty-cell:has(+ .klar-cell-add) {
    display: none;
}

@media (hover: none) {
    .klar-cell-add.mud-button-root {
        display: inline-flex;
    }
}

/* --- menus, tabs and tables of the editors ---------------------------------- */

.klar-primary-menu .mud-button-root,
.klar-primary-menu > .mud-button-filled {
    box-shadow: none;
}

.klar-tabs-tools {
    display: flex;
    align-items: center;
    padding: 0 .75rem;
}

.klar-side-empty {
    font-size: .8125rem;
}

.klar-side-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.klar-side-list li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4375rem 0;
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

.klar-side-list li:last-child {
    border-bottom: 0;
}

.klar-side-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: .8125rem;
}

.klar-table-scroll {
    position: relative;
    overflow-x: auto;
}

.klar-table-foot {
    padding: .375rem .5rem;
}

.klar-props td:first-child {
    min-width: 11rem;
}

.klar-prop-value {
    min-width: 10rem;
    overflow-wrap: anywhere;
}

/* the router focuses the page's h1 after a navigation (FocusOnNavigate); it is not
   an interactive element, so no focus ring */
.mud-main-content h1:focus {
    outline: none;
}

.klar-seg .mud-toggle-item {
    flex: 0 0 auto;
    white-space: nowrap;
    padding-inline: .875rem;
}

/* --- page title (flows) ------------------------------------------------------ */

.klar-page-title {
    margin: 0;
    font-family: var(--klar-font-display);
    font-size: 1.25rem;
    font-weight: 650;
    letter-spacing: -.015em;
}

/* --- filter chips and the pager (list pages) ---------------------------------- */

.klar-filter-chip {
    display: inline-flex;
    align-items: stretch;
    max-width: 30rem;
    height: 1.75rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--klar-primary-ink) 32%, transparent);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--klar-primary-ink) 64%, var(--mud-palette-text-primary));
    font-size: .75rem;
    font-weight: 600;
    overflow: hidden;
}

.klar-filter-chip button {
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.klar-filter-chip-text {
    padding: 0 .375rem 0 .75rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.klar-filter-chip-remove {
    display: inline-grid;
    place-items: center;
    padding: 0 .375rem;
}

.klar-filter-chip button:hover {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
}

.klar-filter-chip button:focus-visible {
    outline: 2px solid var(--klar-accent);
    outline-offset: -2px;
}

.klar-name-link {
    font-weight: 600;
}

.klar-pager {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem;
    width: 100%;
    padding: .5rem .75rem;
    border-top: 1px solid var(--klar-hairline);
    font-size: .8125rem;
}

.klar-pager-size {
    flex: 0 0 5.5rem;
}

.klar-pager-size .mud-input-control,
.klar-pager-size.mud-input-control {
    margin: 0;
}

/* --- forms and choice lists (design editors) ---------------------------------- */

.klar-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: .875rem;
}

.klar-form-grid .mud-input-control {
    margin: 0;
}

.klar-choices td {
    padding-top: .25rem;
    padding-bottom: .25rem;
}

.klar-choices .mud-input-control {
    margin: 0;
    min-width: 8rem;
}

/* --- text that does not wrap ----------------------------------------------------- */

.klar-nowrap,
.klar-nowrap .mud-typography {
    white-space: nowrap;
}

/* --- sign-in card and database chooser ------------------------------------------ */

.klar-login-shell {
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: 1.5rem 1rem;
    background-color: var(--mud-palette-background);
}

.klar-login.mud-paper {
    width: 100%;
    max-width: 27.5rem;
    padding: 1.625rem 1.75rem 1.25rem;
}

.klar-login-brand {
    display: flex;
    align-items: center;
    gap: .625rem;
    margin-bottom: .875rem;
}

.klar-login-logo.klar-typebox {
    width: 2.5rem;
    height: 2.5rem;
}

.klar-login-app {
    font-family: var(--klar-font-display);
    font-size: 1.0625rem;
    font-weight: 650;
}

.klar-login-sub {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.klar-login-title {
    margin: 0 0 .25rem;
    font-family: var(--klar-font-display);
    font-size: 1.25rem;
    font-weight: 650;
    letter-spacing: -.015em;
}

/* the database name in secondary ink (was Tertiary, 2.7:1 on white) */
.klar-login-tenant {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .375rem;
    margin-bottom: .875rem;
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
}

.klar-inline-button.mud-button-root {
    min-width: 0;
    padding: 0 .25rem;
    height: auto;
    font-size: inherit;
    font-weight: 500;
    color: var(--klar-primary-ink);
}

.klar-login-sso {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.klar-login-sso .mud-button-root {
    height: 2.5rem;
}

.klar-login-or {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: .875rem 0 .75rem;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.klar-login-or::before,
.klar-login-or::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background-color: var(--klar-hairline);
}

.klar-login-methods.mud-toggle-group {
    display: flex;
    width: 100%;
    margin-bottom: .75rem;
}

.klar-login-methods .mud-toggle-item {
    flex: 1 1 0;
}

.klar-login-fields {
    display: flex;
    flex-direction: column;
    gap: .625rem;
}

.klar-login-fields .mud-input-control {
    margin: 0;
}

.klar-login-fields .mud-button-root {
    margin-top: .25rem;
}

.klar-login-version {
    margin-top: .875rem;
    text-align: center;
    font-size: .6875rem;
    color: var(--mud-palette-text-secondary);
}

/* --- problem panels: access denied, unexpected error ------------------- */

.klar-problem-shell {
    display: grid;
    place-items: center;
    min-height: calc(100vh - var(--mud-appbar-height) - 6rem);
    padding: 1rem 0;
}

.klar-problem.mud-paper {
    width: min(35rem, 100%);
    padding: 1.75rem;
    text-align: center;
}

.klar-problem-icon.klar-typebox {
    margin: 0 auto .75rem;
}

.klar-problem-icon.klar-tone-warning {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 14%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-warning) 70%, var(--mud-palette-text-primary));
}

.klar-problem-icon.klar-tone-error {
    background-color: color-mix(in srgb, var(--mud-palette-error) 12%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-error) 75%, var(--mud-palette-text-primary));
}

.klar-problem-title {
    margin: 0 0 .5rem;
    font-family: var(--klar-font-display);
    font-size: 1.25rem;
    font-weight: 650;
}

.klar-problem-text {
    font-size: .875rem;
    color: var(--mud-palette-text-secondary);
}

.klar-problem-text p {
    margin: 0 0 .5rem;
}

.klar-problem-text b {
    color: var(--mud-palette-text-primary);
}

.klar-problem-id {
    font-family: var(--klar-font-mono);
    font-size: .75rem;
    /* a request id or an unknown address is one long token: it wraps instead of widening the panel on a phone */
    overflow-wrap: anywhere;
}

.klar-problem-actions {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: 1rem;
}

.klar-problem-details {
    margin-top: 1rem;
    text-align: left;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.klar-problem-details summary {
    cursor: pointer;
}

.klar-problem-details pre {
    margin: .5rem 0 0;
    padding: .5rem;
    border-radius: var(--klar-radius-card);
    background-color: var(--mud-palette-background-gray);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* --- expression editor help (calculated tags) --------------------------- */

.klar-expr-help {
    font-size: .8125rem;
    color: var(--mud-palette-text-primary);
}

.klar-expr-help h3 {
    margin: 1rem 0 .375rem;
    font-size: .875rem;
    font-weight: 650;
}

.klar-expr-help dl {
    display: grid;
    grid-template-columns: minmax(12rem, 20rem) minmax(0, 1fr);
    gap: .25rem 1rem;
    margin: 0;
}

.klar-expr-help dd {
    margin: 0;
    color: var(--mud-palette-text-secondary);
}

.klar-expr-help code {
    font-family: var(--klar-font-mono);
    font-size: .75rem;
    color: var(--mud-palette-text-primary);
    overflow-wrap: anywhere;
}

.klar-expr-help ul {
    margin: 0;
    padding-left: 1.25rem;
    color: var(--mud-palette-text-secondary);
}

.klar-expr-help code.klar-script-sample {
    display: block;
    white-space: pre-wrap;
}

/* code editor of the script job (Monaco, see ScriptCodeEditor.razor) */
.klar-script-editor {
    height: 18rem;
    min-height: 8rem;
    resize: vertical;
    overflow: hidden;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
}

/* the data of a POST step, e.g. the commands of a label */
.klar-script-editor.klar-template-editor {
    height: 12rem;
    min-height: 4rem;
}

/* a formula is usually one line */
.klar-script-editor.klar-formula-editor {
    height: 6rem;
    min-height: 3rem;
}

@media (max-width: 900px) {
    .klar-expr-help dl {
        grid-template-columns: minmax(0, 1fr);
    }

    .klar-expr-help dd {
        margin-bottom: .375rem;
    }
}
