/* =========================================================
   GQL20 Client – Global styles
   MudBlazor handles component styles; this file covers:
   1. Loading spinner
   2. Blazor error UI
   3. Minimal html/body resets (font is set in AppTheme.cs)
   ========================================================= */

/* ── Z-index overrides ───────────────────────────────────────────────────────
   MudBlazor defaults: appbar 1300, dialog 1300, overlay 1200, snackbar 1400.
   The chat FAB must sit above the AppBar; dialogs must sit above the FAB.    */
:root {
    --mud-zindex-overlay: 10000;
    --mud-zindex-dialog:  10001;
    --mud-zindex-snackbar: 10002;
    /* Lift popovers above the app bar (default 1300) so a MudSelect/menu opened inside a Tritium modal window
       (which sits at ~1320, over the drawer + toolbar) still renders on top. Still far below the dialog layer,
       so MudDialog overlays keep covering popovers as before. */
    --mud-zindex-popover: 1400;
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background-color: var(--mud-palette-background) !important;
}



/* ── Social media icon buttons — mono default, brand color on hover ─────────
   .social-btn sets the muted baseline; each network class adds its brand
   color on :hover. X uses the theme text-primary so it stays visible in
   dark mode (X's brand black would vanish on a dark surface). */
.social-btn {
    color: var(--mud-palette-text-disabled) !important;
    transition: color 0.2s ease !important;
}
.social-fb:hover { color: #1877F2 !important; }
.social-yt:hover { color: #FF0000 !important; }
.social-ig:hover { color: #E1306C !important; }
.social-x:hover  { color: var(--mud-palette-text-primary) !important; }
.social-tc:hover { color: #1d020b !important; }

/* ── Font size scale — driven by UserSession.FontSize via JS ─────────────── */
html.fs-small  { font-size: 13px; }
html.fs-normal { font-size: 16px; }
html.fs-large  { font-size: 20px; }

h1:focus {
    outline: none;
}

/* --- Blazor WASM load progress spinner --- */
.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto;
}

.loading-progress circle {
    fill: none;
    stroke: #e0e0e0;
    stroke-width: 0.6rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: #1565C0;
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
}


/* --- Custom splash / loading screen (only visible while Blazor boots) ---------- */
.splash-screen {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    /* ↓↓↓ The loading-only background. Change to any color, gradient, or url("...") image. ↓↓↓ */
    background: radial-gradient(circle at 50% 35%, #fad2ff 0%, #839ef8 70%);
    color: #fff;
}

.splash-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.25rem;
    animation: splash-fade-in .45s ease-out both;
}

.splash-logo {
    max-width: 90vw;   /* natural size; only caps if wider than the viewport */
    height: auto;
    border-radius: 15px;    
    outline-style: solid;
    outline-width: 10px;
    outline-color: white;
}

.dv-info-text-splash-small {
    position: relative;
    bottom: 120px;
    right: -40px;
}

.info-text-splash-small-1 {
    color:rgb(111, 5, 133);
    font-size: 42px;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: bold;
    letter-spacing: -2px;
    opacity: 0.7;
    z-index: 1000;
}

.info-desc-splash-small-1 {
    color:rgb(112, 4, 201);
    font-size: 12px;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: 100;
    letter-spacing: 0.8px;
    opacity: 0.9;
    z-index: 1000;
    margin-left: 10px;
    margin-top: -10px;    
}

.dv-info-text-splash-large {
    position: relative;
    bottom: 100px;
    
}

.info-text-splash-large-1 {
    color:rgb(86, 9, 102);
    font-size: 42px;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: bold;
    letter-spacing: -2px;
    opacity: 0.9;
    z-index: 1000;
}

.info-desc-splash-large-1 {
    color:rgb(0, 0, 0);
    font-size: 11px;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: 100;
    letter-spacing: 1px;
    opacity: 0.8;
    z-index: 1000;
    margin-left: 10px;
    margin-top: -16px;    
}

.splash-title {
    font-family: 'Roboto', sans-serif;
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: .12em;
}

@keyframes splash-fade-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

/* Indeterminate spinner — used after the WASM download, while app services initialise. */
.splash-spinner {
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    border: 0.35rem solid rgba(255, 255, 255, 0.18);
    border-top-color: #4da3ff;
    animation: splash-spin 0.8s linear infinite;
}

@keyframes splash-spin { to { transform: rotate(360deg); } }

/* Re-flow the Blazor load-progress ring + % into the centered splash card. */
.splash-screen .loading-progress {
    position: relative;
    inset: auto;
    width: 5rem;
    height: 5rem;
    margin: 0;
}
.splash-screen .loading-progress circle             { stroke: rgba(255, 255, 255, 0.18); }
.splash-screen .loading-progress circle:last-child  { stroke: #4da3ff; }
.splash-screen .loading-progress-text {
    position: relative;
    inset: auto;
    color: rgba(255, 255, 255, 0.85);
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

.loading-progress-text::after {
    content: var(--blazor-load-percentage-text, "Loading");
}

/* --- Blazor error UI (bottom banner) --- */
#blazor-error-ui {
    background: #ffeb3b;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    color: rgba(0,0,0,0.87);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-error-boundary {
    background: #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* ── MudDataGrid / MudTable — theme-colored column headers ──────────────────
   Uses --mud-palette-primary set by MudThemeProvider, so it follows every
   theme and dark-mode switch automatically. */
.mud-table-head .mud-table-cell {
    color: var(--mud-palette-primary) !important;
    font-weight: 600 !important;
    border-bottom-color: var(--mud-palette-primary) !important;
}

/* ── MudDataGrid / MudTable — striped odd rows ───────────────────────────────
   Replaces MudBlazor's default background-grey stripe with a darker overlay
   that reads clearly in both light and dark mode. */
.mud-table-striped .mud-table-body .mud-table-row:nth-child(odd) {
    background-color: rgba(0, 0, 0, 0.06) !important;
}

.mud-table-striped .mud-table-body .mud-table-row:nth-child(odd) .mud-table-cell {
    background-color: transparent !important;
}

/* ── MudDataGrid / MudTable — theme-tinted row hover ─────────────────────────
   MudThemeProvider exposes --mud-palette-primary for the active theme.
   color-mix blends it at 12% opacity so the tint is subtle in both light/dark. */
.mud-table-hover .mud-table-body .mud-table-row:hover {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent) !important;
}

.mud-table-hover .mud-table-body .mud-table-row:hover .mud-table-cell {
    background-color: transparent !important;
}

/* ── Dashboard panel cards ─────────────────────────────────────────────────
   Panels are the only opaque-ish things on the desktop — the wallpaper shows through everything else.

   🔴 PERFORMANCE: exactly ONE blurred surface per panel — the card. The header's own blur was removed when
   this moved here: nesting a second `backdrop-filter` inside a blurred card pays the GPU cost twice for
   almost no visual gain, since the inner one only blurs the card's own background.
   Blur also lets the fill be *more* transparent while staying readable — it turns whatever is behind into
   low-frequency colour, which is precisely why real frosted glass works. Hence 58% here versus the 76% a
   plain translucent fill needed.
   Blur is switched OFF mid-drag (see .adv-dragging) — dragging is where per-frame compositing cost is
   most visible, and nobody studies a panel's translucency while flinging it across the desktop.

   ⚠ `backdrop-filter` makes an element the CONTAINING BLOCK for `position: fixed` descendants — the same
   trap that broke the taskbar's launcher panels. MudBlazor popovers render at app root so they're fine,
   but a widget that positions something `fixed` inside a panel will now anchor to the panel. */
.dashboard-panel {
    transition: box-shadow .2s ease, opacity .15s ease;
    cursor: default;
    border-radius: 14px;
    /* --tt-panel-tint is set inline per-panel (DashboardPanelCard.CardStyle) when the user picks a panel
       colour; unset, it falls back to the theme surface, which is the DEFAULT — same glass as everywhere
       else. Border and fill share the same tint so a coloured panel reads as one coherent pane of glass,
       not a coloured fill inside a neutral frame. Custom-property fallback, not a second rule: a plain
       inline `background` would lose to background-color's !important below, which is exactly the bug
       this replaced (the old colour picker silently stopped doing anything once the glass fill shipped). */
    border: 1px solid color-mix(in srgb, var(--tt-panel-tint, var(--mud-palette-surface)) 50%, transparent);
    background-color: color-mix(in srgb, var(--tt-panel-tint, var(--mud-palette-surface)) 58%, transparent) !important;
    -webkit-backdrop-filter: blur(16px) saturate(170%);
    backdrop-filter: blur(16px) saturate(170%);
    box-shadow: 0 1px 2px rgba(0,0,0,.05), 0 14px 32px -20px rgba(0,0,0,.5) !important;
}
.dashboard-panel:hover {
    box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 20px 40px -22px rgba(0,0,0,.6) !important;
}

.dashboard-panel.dragging {
    opacity: 0.5;
    box-shadow: 0 8px 24px rgba(0,0,0,0.25) !important;
}

/* No drawn divider — the tint fading into the card body is the separation.
   Deliberately NOT blurred: the card above already is, and a nested backdrop-filter would pay the cost a
   second time to blur its own parent's background. Just a tint. */
.dashboard-panel-header {
    border-bottom: 0;
    background-image: linear-gradient(
        to bottom,
        color-mix(in srgb, var(--mud-palette-primary) 14%, transparent),
        color-mix(in srgb, var(--mud-palette-primary) 4%, transparent));
    /* Advanced (free-floating) mode drags panels from this header via the Pointer Events API — same
       mechanism as the window system's title bar (tritiumWindow.css .tt-win__bar), which needs this
       exact rule to work on touch: without it, iOS/tablets treat the header as pan-scrollable, so the
       browser's own scroll gesture races the drag and cancels it before pointermove ever repositions
       anything. Scoped to the header only (not .floating-panel-wrapper, which is itself the panel's
       scrollable content region — overflow:auto) so touch-scrolling panel content is unaffected. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

/* ── Metric tiles (KPI/Payroll/Profit/Revenue widgets) — frosted, NOT blurred ──────────────────────
   Four widgets, one visual language: .acc-health-tile (Accounting), .pk-card (Payroll), .prk-card
   (Profit), .rk-card (Revenue). Each still computes its own status-colour gradient in C# (red/green for
   balance issues, etc.) — that colour is real information, not decoration, so it survives as
   --tt-tile-c1/--tt-tile-c2 custom properties (see each widget's CardStyle) instead of being replaced by
   a neutral tint the way a plain dashboard panel is.

   🔴 Deliberately NO backdrop-filter here, unlike .dashboard-panel. A panel can hold several of these
   tiles at once (they're fixed-240px and inline-block on purpose, to sit side by side) — each with its
   OWN independent blur would be real per-tile GPU cost, and nesting blur inside a backdrop that is
   ALREADY blurred (the panel's) just looks mushy, not like two panes of glass. Since the panel underneath
   already frosts the wallpaper, a tile only needs to lay a translucent COLOUR wash on top of that
   existing frost — "tinted glass sitting on frosted glass" — which is cheaper and reads better.

   Opacity is higher than a plain panel's 58% (72%) on purpose: these cards carry white text at a fixed
   contrast ratio designed for a solid fill, so keeping them closer to solid protects legibility over a
   bright wallpaper. !important is required — see each widget's CardStyle comment for why the inline
   `background` can't just be left in charge. */
.acc-health-tile,
.pk-card,
.prk-card,
.rk-card {
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--tt-tile-c1, var(--mud-palette-primary)) 72%, transparent),
        color-mix(in srgb, var(--tt-tile-c2, var(--mud-palette-primary-lighten)) 72%, transparent)
    ) !important;
}

.drag-handle:hover {
    color: var(--mud-palette-primary) !important;
    cursor: grab !important;
}

.dashboard-panel.edit-mode {
    outline: 1px dashed color-mix(in srgb, var(--mud-palette-primary) 40%, transparent);
}

/* Hidden panels only render in edit mode — show them faded with a dashed outline so it's clear they
   won't appear on the live dashboard until toggled back on. */
.dashboard-panel.panel-hidden {
    opacity: 0.55;
    outline-style: dashed;
    outline-color: color-mix(in srgb, var(--mud-palette-warning) 55%, transparent);
}

/* Edit-mode per-widget tools (settings + delete) float over the widget's top-right corner instead of
   sitting in-flow beside it — a wide widget can no longer push them past the panel's right border. */
.dash-content-edit {
    position: relative;
}

.dash-content-tools {
    position: absolute;
    top: 2px;
    right: 2px;
    z-index: 4;
    display: flex;
    gap: 1px;
    padding: 1px;
    border-radius: 9px;
    background: color-mix(in srgb, var(--mud-palette-surface) 84%, transparent);
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.18);
    backdrop-filter: blur(2px);
}

/* ── Dashboard page container ──────────────────────────────────────────────
   Fills the viewport minus the fixed chrome and owns its OWN scroll region — the window-maximize rule.

   🔴 The toolbar is NOT `position: sticky` any more, and that is the point. Sticky was pinned at
   `top: var(--mud-appbar-height, 64px)`; once the top bar became off-by-default the container started at
   viewport y≈0, so the bar's natural position was already above that threshold and sticky parked it 64px
   DOWN from where it belonged — directly on top of the first 64px of the canvas. With `z-index: 10` it
   also ate the pointerdown aimed at the panel headers beneath it, so in advanced mode panels looked
   headerless AND refused to drag. Grid placement has no offset to get wrong and no z-index race to lose. */
/* 🔴 The dashboard FILLS ITS PARENT rather than computing a height from the viewport.
   It used to be `height: calc(100dvh - --tt-app-top - --tt-app-bottom)`, which quietly assumed
   `.mud-main-content`'s top padding equals `--mud-appbar-height`. It does not — MudBlazor uses THREE
   different values across breakpoints:
       calc(H - H/8)   ·   calc(H - H/4)   ·   H
   so subtracting the full height over-subtracted by 8px or 16px depending on window width, leaving a gap
   above the AppBar. Replicating that formula would just be a copy waiting to drift.
   A flex chain instead measures whatever space actually exists, so it stays correct through the top bar
   being toggled, breakpoint changes, and any banner that appears above the content.

   The chain has to be unbroken all the way to <html>: html/body are already 100%, but #app had no height,
   so MudBlazor's `.mud-layout { height: 100% }` resolved against `auto` and collapsed. Every link is
   scoped with :has() so only a page showing a dashboard is affected. */
#app:has(.dashboard-page-container) {
    height: 100%;
}
.mud-layout:has(.dashboard-page-container) {
    display: flex;
    flex-direction: column;
}
.mud-main-content:has(.dashboard-page-container) {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.mud-container:has(.dashboard-page-container) {
    /* MainLayout wraps every page in `<MudContainer MaxWidth="ExtraLarge" Class="pa-2 mt-1">`. `:has()`
       releases ONLY the container holding a dashboard; every other page keeps its reading measure. */
    max-width: none !important;
    padding: 0 !important;
    margin-top: 0 !important;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* ── The desktop ────────────────────────────────────────────────────────────
   The dashboard is the app's desktop: a wallpaper with translucent panels floating on it, the way a
   Windows desktop holds icons. The window system, the AppBar-as-taskbar and the Start-menu launcher
   already exist; this is what makes them read as one thing.

   --tt-dash-wallpaper is the seam. It defaults to a CSS-generated gradient — theme-aware, zero bytes, no
   licensing question — and a per-user wallpaper later only has to set it to `url(...)`. That preference
   needs NO schema change: UserLayoutPrefs is a JSON blob, so a DashboardWallpaper property syncs across
   the user's computers for free.

   The first background layer is a scrim, deliberately OUTSIDE the variable, so it keeps applying when a
   user swaps in a photo — MudBlazor's text and divider colours assume an opaque surface and vanish over a
   bright image without it. */
.dashboard-page-container {
    /* One grid cell shared by header and scroller, so content passes UNDER the glass. */
    display: grid;
    grid-template: 1fr / 1fr;
    /* Fills the flex chain above (see .mud-main-content:has(...)) instead of subtracting chrome from the
       viewport. min-height:0 is what lets a flex child shrink below its content so the grid can scroll. */
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;

    background-color: var(--mud-palette-background);
    background-image:
        linear-gradient(color-mix(in srgb, var(--mud-palette-surface) 22%, transparent),
                        color-mix(in srgb, var(--mud-palette-surface) 34%, transparent)),
        var(--tt-dash-wallpaper,
            radial-gradient(1200px 800px at 12% 8%,  color-mix(in srgb, var(--mud-palette-primary)   38%, transparent), transparent 60%),
            radial-gradient(1000px 700px at 88% 18%, color-mix(in srgb, var(--mud-palette-secondary) 32%, transparent), transparent 62%),
            radial-gradient(1100px 900px at 60% 95%, color-mix(in srgb, var(--mud-palette-tertiary)  28%, transparent), transparent 65%),
            linear-gradient(160deg,
                color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-background)),
                var(--mud-palette-background)));
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* Purely cosmetic fade-in for the wallpaper swap (default gradient → the company's uploaded photo,
   applied once per session at :root — see DashboardWallpaperService.ApplyRootWallpaperAsync). Reads a
   SEPARATE variable, --tt-dash-wallpaper-photo — NOT --tt-dash-wallpaper, which the container's own
   background above still reads and which JS never touches any more. That split matters: JS setting
   --tt-dash-wallpaper directly would switch the container's OWN background to the photo INSTANTLY (by
   design — it's the always-correct, no-JS-dependency source of truth), at the exact same moment this
   overlay also switches, so the overlay would just be fading in a duplicate of an already-visible
   identical image — no perceptible change (this was tried and confirmed invisible). With the split, the
   container permanently shows the gradient and ONLY this overlay ever shows the real photo, so its fade
   is an actual gradient→photo transition. Starts invisible; fades to visible once JS adds
   .tt-wallpaper-ready to <html>. If that class is never added for any reason, this stays opacity:0
   forever — a total no-op, never a way to hide real content. Deliberately NOT position:absolute (see
   the grid-area rule below): it shares the same grid cell as every other child, so DOM order alone
   (rendered first = painted behind) keeps it under real content with no z-index guesswork. */
.dashboard-wallpaper-fade {
    grid-area: 1 / 1;
    background-image: var(--tt-dash-wallpaper-photo, none);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    opacity: 0;
    transition: opacity 6s ease;
    pointer-events: none;
}
html.tt-wallpaper-ready .dashboard-wallpaper-fade {
    opacity: 1;
}

/* ── Floating control bubble ───────────────────────────────────────────────
   The desktop's only chrome: a glass pill in the top-right holding the layout and edit toggles. It floats
   in the same grid cell as the content rather than occupying a row, so it costs no vertical space.
   Dimmed at rest so it never competes with the wallpaper; full opacity on hover, on keyboard focus, and
   throughout edit mode (where you are actively using it). */
.dashboard-bubble {
    grid-area: 1 / 1;
    justify-self: end;
    align-self: start;
    /* Above .dash-content-tools (z-index 4), which sits at each PANEL's top-right and can otherwise
       collide with this when a panel is parked in the desktop's top-right corner. */
    z-index: 6;
    /* 50px clear of the right edge, deliberately: flush right put it over the scroll container's
       scrollbar gutter, where the scrollbar appearing under the pointer nudged it and made it shimmer. */
    margin: 10px 50px 10px 12px;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mud-palette-surface) 34%, transparent);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    backdrop-filter: blur(16px) saturate(180%);
    border: 1px solid color-mix(in srgb, var(--mud-palette-surface) 34%, transparent);
    box-shadow: 0 8px 24px -14px rgba(0, 0, 0, .6);
    /* 🔴 NEVER transition `opacity` on a backdrop-filter element. Doing so makes the compositor
       re-resolve the blurred backdrop every frame, which flickers (and is expensive). The rest state is
       expressed as a thinner BACKGROUND instead, and the contents are dimmed on the child buttons —
       they carry no filter, so animating their opacity is free and steady. */
    transition: background .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.dashboard-bubble:hover,
.dashboard-bubble:focus-within,
.dashboard-bubble--edit {
    background: color-mix(in srgb, var(--mud-palette-surface) 66%, transparent);
    border-color: color-mix(in srgb, var(--mud-palette-surface) 66%, transparent);
    box-shadow: 0 12px 30px -14px rgba(0, 0, 0, .7);
}
/* Dim the controls at rest — on the buttons, not on the filtered container. */
.dashboard-bubble .mud-button-root { opacity: .62; transition: opacity .18s ease; }
.dashboard-bubble:hover .mud-button-root,
.dashboard-bubble:focus-within .mud-button-root,
.dashboard-bubble--edit .mud-button-root { opacity: 1; }
.dashboard-bubble__sep {
    width: 1px;
    align-self: stretch;
    margin: 4px 3px;
    background: color-mix(in srgb, var(--mud-palette-divider) 55%, transparent);
}

/* 🔴 EVERY non-bubble, non-wallpaper-fade child shares the cell and scrolls — matched by EXCLUSION,
   never by naming one branch's class. DashboardView has three render branches (empty / basic / advanced)
   and they do not share a wrapper; a rule naming only `.dashboard-content-scroll` dropped the advanced
   canvas into an implicit second row with no height inside this `overflow: hidden` parent, clipping it
   away entirely. .dashboard-wallpaper-fade is excluded too — it's a decorative background layer, not
   scrollable content, and gets its own grid-area placement above. */
.dashboard-page-container > *:not(.dashboard-bubble):not(.dashboard-wallpaper-fade) {
    grid-area: 1 / 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* No header to clear any more — the bubble floats over the content instead of reserving a band, so this
   is just breathing room at the desktop's edges.
   🔴 The padding lives on the WRAPPER, never on .advanced-dashboard-canvas itself: the drag JS computes
   positions from `canvas.getBoundingClientRect().top` (a BORDER-box edge) while absolutely-positioned
   panels resolve against the PADDING box, so padding on the canvas would offset every drag by its size. */
.dashboard-content-scroll {
    padding: 12px;
}

/* ── Advanced (free-floating) dashboard canvas ───────────────────────────── */
.advanced-dashboard-canvas {
    position: relative;
    width: 100%;
}

.floating-panel-wrapper {
    position: absolute;
    min-width: 220px;
    min-height: 80px;
    /* Default height for un-resized panels so content scrolls inside instead of
       growing unbounded and overlapping neighbours. An inline height (set on
       resize) or height:auto (when collapsed) overrides this. */
    height: 300px;
    overflow: auto;
}

/* Custom resize grip — shown only in edit mode */
.panel-resize-handle {
    display: none;
    position: absolute;
    bottom: 16px;
    right: 16px;
    width: 16px;
    height: 16px;
    cursor: se-resize;
    opacity: 0.45;

    transition: opacity 0.15s ease;
    /* Same touch-drag fix as .dashboard-panel-header above, for the resize gesture. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.advanced-dashboard-canvas.edit-mode .panel-resize-handle {
    display: block;
}

.panel-resize-handle:hover {
    opacity: 0.9;
}

.floating-panel-wrapper .adv-panel {
    height: 100%;
}

/* Advanced (fixed-height) panels: clip the card to its box and let the content
   area scroll internally, so multiple stacked widgets never spill out the bottom
   of the panel. The chat/calendar :has() rules below are more specific and win. */
.adv-panel {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.adv-panel > .mud-card-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* While a panel is being dragged by JS, lift it visually.
   🔴 Blur is switched OFF here and the fill made more opaque to compensate. Re-blurring the backdrop on
   every pointermove is the single most expensive thing the desktop can do, and it is the one moment the
   user is guaranteed to notice dropped frames. The swap is invisible in motion. */
.adv-dragging .dashboard-panel,
.adv-dragging.dashboard-panel {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--mud-palette-surface) 88%, transparent) !important;
}
.adv-dragging {
    opacity: 0.85;
    box-shadow: 0 12px 32px rgba(0,0,0,0.28) !important;
    cursor: grabbing !important;
}

/* ── Notes toolbar button + dropdown panel ───────────────────────────────── */
.notes-panel-host {
    position: relative;
    display: inline-flex;
    align-items: center;
}

/* Full-screen transparent layer that captures outside clicks */
.notes-panel-overlay {
    position: fixed;
    inset: 0;
    z-index: 1199;
}

/* The dropdown panel itself */
.notes-panel-dropdown {
    position: fixed;
    top: 48px;          /* dense MudAppBar height */
    right: 8px;
    width: 600px;
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    z-index: 1200;
    border-radius: 0 0 8px 8px;
    background: var(--mud-palette-surface);
}

/* ── NotesManager ────────────────────────────────────────────────────────── */
.notes-manager {
    display: flex;
    flex-direction: column;
    min-height: 120px;
}

.notes-manager-toolbar {
    border-bottom: 1px solid var(--mud-palette-divider);
}

.note-card-header {
    border-bottom: 1px solid var(--mud-palette-divider);
}

/* Color dot in grid view */
.note-color-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    vertical-align: middle;
}

.notes-grid-content-col {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Floating Notes portal ───────────────────────────────────────────────── */
#floating-notes-portal {
    position: fixed;
    inset: 0;
    pointer-events: none;   /* let clicks through to the page */
    z-index: 9900;
}

/* Same frosted-glass treatment as .dashboard-panel (see its comment for the full rationale — one
   blurred surface, tint via a custom property so an inline colour doesn't lose to !important, blur
   switched off while dragging). --tt-note-tint is set inline per-note (FloatingNotes.FloatingNoteStyle)
   when the user picks a note colour; unset, it falls back to the theme surface. */
.floating-note {
    position: absolute;
    pointer-events: all;    /* notes themselves capture events */
    min-width: 200px;
    min-height: 80px;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: box-shadow .2s ease;
    border: 1px solid color-mix(in srgb, var(--tt-note-tint, var(--mud-palette-surface)) 50%, transparent);
    background-color: color-mix(in srgb, var(--tt-note-tint, var(--mud-palette-surface)) 62%, transparent) !important;
    -webkit-backdrop-filter: blur(16px) saturate(170%);
    backdrop-filter: blur(16px) saturate(170%);
    box-shadow: 0 1px 2px rgba(0,0,0,.05), 0 14px 32px -20px rgba(0,0,0,.5);
}
.floating-note:hover {
    box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 20px 40px -22px rgba(0,0,0,.6);
}

.floating-note-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 8px 6px 10px;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-divider) 65%, transparent);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
    cursor: grab;
    user-select: none;
    gap: 6px;
    /* Dragged via the same Pointer Events code path as the dashboard's free-floating panels
       (window.notesFloating in index.html) and the window system's title bar — needs the same fix:
       without this, iOS/tablets treat the header as pan-scrollable, so the browser's own scroll
       gesture races the drag and cancels it before pointermove ever repositions the note. */
    touch-action: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.floating-note-title {
    font-size: 0.8rem;
    font-weight: 600;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.floating-note-close,
.floating-note-hdr-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
    font-size: 0.85rem;
    line-height: 1;
    padding: 0 2px;
    border-radius: 2px;
    transition: color 0.15s ease;
}

.floating-note-close:hover {
    color: var(--mud-palette-error);
}

.floating-note-hdr-btn:hover {
    color: var(--mud-palette-primary);
}

.floating-note-collapse-btn {
    display: flex;
    align-items: center;
    padding: 0;
    margin-right: 2px;
}

.floating-note-collapse-btn .material-icons {
    font-size: 16px;
}

/* Creation date caption below header */
.floating-note-date {
    font-size: 0.68rem;
    color: var(--mud-palette-text-disabled);
    padding: 3px 10px 0;
    user-select: none;
}

.floating-note-color-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

/* Editable content textarea — seamlessly fills the note body area */
.floating-note-body-edit {
    flex: 1;
    display: block;
    width: 100%;
    padding: 8px 10px;
    font-size: 0.82rem;
    font-family: inherit;
    color: inherit;
    background: transparent;
    border: none;
    outline: none;
    resize: none;
    overflow-y: auto;
    box-sizing: border-box;
    white-space: pre-wrap;
    word-break: break-word;
    line-height: 1.5;
}

/* Resize grip — bottom-right corner */
.floating-note-resize-handle {
    position: absolute;
    bottom: 4px;
    right: 4px;
    width: 16px;
    height: 16px;
    cursor: se-resize;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-text-secondary);
    opacity: 0.5;
    transition: opacity 0.15s ease;
    /* Same touch-drag fix as .floating-note-header above, for the resize gesture. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.floating-note-resize-handle:hover {
    opacity: 1;
}

/* Visual feedback while dragging. Blur switched OFF (same reason as .adv-dragging above — re-blurring
   the backdrop on every pointermove is the most expensive thing this UI can do), fill made more opaque
   to compensate; the swap is invisible in motion. */
.floating-note-dragging {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--tt-note-tint, var(--mud-palette-surface)) 88%, transparent) !important;
    opacity: 0.9;
    box-shadow: 0 12px 32px rgba(0,0,0,0.3) !important;
    cursor: grabbing !important;
}


/* ── AI Chat panel ─────────────────────────────────────────────────────────── */

/* Core panel — fills whatever container gives it room.
   min-height is the fallback when the parent has no defined height.            */
.chat-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-height: 350px;
    background: var(--mud-palette-surface);
    border-radius: 4px;
    overflow: hidden;
}

/* Dashboard basic layout: give MudCardContent a defined height so the panel
   can resolve height:100%. Uses CSS :has() (Chrome 105+, Firefox 121+, Safari 15.4+). */
.dashboard-panel:not(.adv-panel):has(.chat-panel) .mud-card-content {
    height: 450px;
    display: flex;
    flex-direction: column;
    padding: 4px !important;
}

/* Dashboard advanced layout: card fills its absolutely-positioned wrapper,
   stretch content area to take remaining height after the header.              */
.adv-panel:has(.chat-panel) .mud-card-content {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 4px !important;
}

/* Edit-mode wrapper (each content item is wrapped in .d-flex + .flex-grow-1).
   Stretch the row so the inner panel fills the content area height.            */
.dashboard-panel:has(.chat-panel) .mud-card-content > .d-flex {
    flex: 1;
    min-height: 0;
    align-items: stretch !important;
    margin-bottom: 0 !important;
}

.dashboard-panel:has(.chat-panel) .mud-card-content > .d-flex > .flex-grow-1 {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* ── Calendar dashboard panels (agenda + day) ──────────────────────────── */
.dashboard-panel:not(.adv-panel):has(.cal-agenda-panel) .mud-card-content,
.dashboard-panel:not(.adv-panel):has(.cal-day-panel)   .mud-card-content {
    height: 480px;
    display: flex;
    flex-direction: column;
    padding: 4px !important;
}
.adv-panel:has(.cal-agenda-panel) .mud-card-content,
.adv-panel:has(.cal-day-panel)   .mud-card-content {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 4px !important;
}
.dashboard-panel:has(.cal-agenda-panel) .mud-card-content > .d-flex,
.dashboard-panel:has(.cal-day-panel)   .mud-card-content > .d-flex {
    flex: 1;
    min-height: 0;
    align-items: stretch !important;
    margin-bottom: 0 !important;
}
.dashboard-panel:has(.cal-agenda-panel) .mud-card-content > .d-flex > .flex-grow-1,
.dashboard-panel:has(.cal-day-panel)   .mud-card-content > .d-flex > .flex-grow-1 {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Messages area: min-height:0 is required for overflow-y:auto inside a flex column */
.chat-messages {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 8px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    scroll-behavior: smooth;
}

.chat-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    color: var(--mud-palette-text-secondary);
    gap: 8px;
    font-size: 0.9rem;
    text-align: center;
}

.chat-bubble-wrap { display: flex; margin-bottom: 2px; }
.wrap-user { justify-content: flex-end; }
.wrap-ai   { justify-content: flex-start; }

.chat-bubble {
    max-width: 75%;
    padding: 7px 12px 5px;
    border-radius: 18px;
    font-size: 0.88rem;
    line-height: 1.4;
    box-shadow: 0 1px 2px rgba(0,0,0,0.10);
}

.bubble-user {
    background: color-mix(in srgb, var(--mud-palette-primary) 30%, var(--mud-palette-surface));
    border-bottom-right-radius: 4px;
}

.bubble-ai {
    border-radius: 18px;
    background: color-mix(in srgb, var(--mud-palette-secondary) 12%, var(--mud-palette-surface));
    border: 1px solid var(--mud-palette-divider);
    box-shadow: 0 2px 6px rgba(0,0,0,0.06);
}

.bubble-text {
    display: block;
    word-break: break-word;
    white-space: pre-wrap;
    color: var(--mud-palette-text-primary);
}

.bubble-time {
    display: block;
    font-size: 0.68rem;
    color: var(--mud-palette-text-secondary);
    text-align: right;
    margin-top: 2px;
}

/* Markdown-rendered AI replies (tables, lists, links, code) */
.bubble-md {
    display: block;
    word-break: break-word;
    color: var(--mud-palette-text-primary);
}
.bubble-md > :first-child { margin-top: 0; }
.bubble-md > :last-child  { margin-bottom: 0; }
.bubble-md p { margin: 0 0 6px; }
.bubble-md ul, .bubble-md ol { margin: 0 0 6px; padding-left: 18px; }
.bubble-md a { color: var(--mud-palette-primary); text-decoration: underline; cursor: pointer; }
.bubble-md code {
    font-family: var(--mud-typography-monospace, monospace);
    font-size: 0.82em;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 10%, transparent);
    padding: 1px 4px;
    border-radius: 4px;
}
.bubble-md pre {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    padding: 8px 10px;
    border-radius: 8px;
    overflow-x: auto;
}
.bubble-md pre code { background: none; padding: 0; }
.bubble-md table {
    border-collapse: collapse;
    margin: 4px 0 8px;
    width: 100%;
    font-size: 0.82rem;
}
.bubble-md th, .bubble-md td {
    border: 1px solid var(--mud-palette-divider);
    padding: 4px 8px;
    text-align: left;
}
.bubble-md th { background: color-mix(in srgb, var(--mud-palette-text-primary) 6%, transparent); font-weight: 600; }

/* Global push-to-talk listening overlay */
.voice-cmd-overlay {
    position: fixed;
    inset: 0;
    z-index: 2100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.45);
    backdrop-filter: blur(2px);
}
.voice-cmd-card {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 16px;
    box-shadow: 0 8px 30px rgba(0,0,0,0.25);
    padding: 24px 28px;
    width: min(92vw, 440px);
    text-align: center;
}
.voice-cmd-mic {
    width: 72px; height: 72px;
    margin: 0 auto;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--mud-palette-error) 12%, var(--mud-palette-surface));
}
.voice-cmd-mic.listening { animation: voicepulse 1.2s ease-in-out infinite; }
@keyframes voicepulse {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mud-palette-error) 45%, transparent); }
    70%  { box-shadow: 0 0 0 16px color-mix(in srgb, var(--mud-palette-error) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mud-palette-error) 0%, transparent); }
}
.voice-cmd-interim { color: var(--mud-palette-text-secondary); min-height: 2.4em; }

.typing-dots { display: flex; gap: 4px; align-items: center; padding: 4px 2px; }
.typing-dots span {
    width: 7px;
    height: 7px;
    background: var(--mud-palette-text-secondary);
    border-radius: 50%;
    animation: typingBounce 1.2s ease-in-out infinite;
}
.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }

@keyframes typingBounce {
    0%, 60%, 100% { transform: translateY(0); }
    30%           { transform: translateY(-6px); }
}

.chat-error-bar {
    flex-shrink: 0;
    text-align: center;
    font-size: 0.8rem;
    color: var(--mud-palette-error);
    padding: 4px 8px;
    background: color-mix(in srgb, var(--mud-palette-error) 10%, var(--mud-palette-surface));
}

.chat-input-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 8px;
    background: var(--mud-palette-surface);
    border-top: 1px solid var(--mud-palette-divider);
    flex-shrink: 0;
}

.chat-input-field { flex: 1; }

/* Toolbar shown inside the panel when embedded in a dashboard card */
.chat-panel-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 10px 4px 10px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--mud-palette-divider);
    background: var(--mud-palette-surface);
}

.chat-panel-toolbar-title {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    display: flex;
    align-items: center;
}

/* ── Floating chat window ──────────────────────────────────────────────────── */
.floating-chat-window {
    position: fixed;
    /* Fallback near the top-left FAB; chatFabDrag.positionWindow sets the real left/top on open. */
    top: 140px;
    left: 12px;
    width: 50vw;
    height: 72vh;
    /* User-resizable; bounds keep it usable. (Size resets to these defaults when reopened.) */
    resize: both;
    min-width: 320px;
    min-height: 360px;
    max-width: 95vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    border-radius: 10px;
    overflow: hidden;
    background: var(--mud-palette-surface);
    box-shadow: 0 8px 32px rgba(0,0,0,0.28);
    /* Just below MudBlazor's dialog layer (--mud-zindex-dialog: 1400) so modal dialogs
       (e.g. the "clear conversations" confirm) and their scrim appear above the chat. */
    z-index: 1390;
}

.floating-chat-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--mud-palette-primary);
    padding: 6px 8px 6px 14px;
    flex-shrink: 0;
}

.floating-chat-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* Inside the floating window the panel fills all remaining height */
.floating-chat-body .chat-panel {
    min-height: 0;
    border-radius: 0;
}

/* "What can I ask?" right drawer — sits above the chat window (z 1400) so it's never hidden behind it. */
.chat-help-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(92vw, 360px);
    background: var(--mud-palette-surface);
    box-shadow: -8px 0 32px rgba(0,0,0,0.28);
    z-index: 1600;
    display: flex;
    flex-direction: column;
    animation: chatHelpSlideIn .18s ease-out;
}
@keyframes chatHelpSlideIn { from { transform: translateX(100%); } to { transform: translateX(0); } }
.chat-help-drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--mud-palette-primary);
    padding: 6px 8px 6px 14px;
    flex-shrink: 0;
}
.chat-help-drawer-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 10px 12px;
}

/* Transient "stop voice" button — sits beside the FAB while read-back is talking (JS anchors it). */
.floating-chat-stop {
    position: fixed;
    top: 86px;
    left: 80px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--mud-palette-error);
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    z-index: 9999;
    animation: voicepulse 1.2s ease-in-out infinite;
}
.floating-chat-stop:hover  { filter: brightness(1.08); }
.floating-chat-stop:active { transform: scale(0.95); }

/* Floating push-to-talk mic — same slot as the stop button, shown when voice is idle + available. */
.floating-chat-mic {
    position: fixed;
    top: 86px;
    left: 80px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--mud-palette-secondary);
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    z-index: 9999;
}
.floating-chat-mic:hover  { background: var(--mud-palette-primary-darken); }
.floating-chat-mic:active { transform: scale(0.95); }

/* ── FAB button ────────────────────────────────────────────────────────────── */
/* Default TOP-LEFT now that the bottom bar is the app's primary chrome — stacked just below the launcher
   FAB (top:12) so the two don't overlap. The chat FAB has no dockClass, so top-left triggers no docking.
   Everything else (window, mic/stop) is positioned relative to this by chatFabDrag, so it follows. A saved
   drag position (localStorage) still overrides this. */
.floating-chat-fab {
    position: fixed;
    top: 80px;
    left: 12px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    border: none;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    z-index: 9999;
    transition: background 0.2s, transform 0.15s;
    touch-action: none;
}
.floating-chat-fab:hover  { background: var(--mud-palette-primary-darken); transform: scale(1.05); }
.floating-chat-fab:active { transform: scale(0.95); }

/* ── Top bar hidden (Preferences → Toolbar) ─────────────────────────────────
   MudBlazor reserves the app-bar band in layout regardless of whether an app bar is rendered, so simply
   not rendering <TopToolBar> would leave a dead ~64px gap at the top and a drawer starting below it.
   Zero those offsets so hiding the bar actually reclaims the space. The window system's own
   --tt-chrome-top is zeroed separately, on .tt-scope (see TritiumWindowHost). */
.tt-no-topbar .mud-main-content { padding-top: 0 !important; }

/* ── App chrome offsets, as inherited variables ──────────────────────────────
   How much of the viewport the fixed chrome eats, top and bottom. Declared here rather than recomputed by
   each full-height page, so "the top bar is off" or "the AppBar is 66px now" is expressed once.
   Inheritance does the work: .tt-no-topbar sits on MudLayout and body.tt-bottombar on <body>, both
   ancestors of every page, so a page just reads the vars. */
:root {
    --tt-app-top: var(--mud-appbar-height, 64px);
    --tt-app-bottom: 0px;
    /* Dashboard desktop wallpaper. Unset it (or point it at a missing file) and .dashboard-page-container
       falls back to a theme-derived gradient, so the desktop can never render broken.
       See wwwroot/resources/wallpapers/README.md for source, licence and how to replace it. */
    /* Swap this line to try another (all in that folder): default.jpg · abstract-gradient.jpg ·
       mountains-night.jpg · misty-forest.jpg */
    --tt-dash-wallpaper: url("../resources/wallpapers/mountains-night.jpg");
    /* --tt-dash-hdr (dashboard glass-header height) is owned by density.css, since it varies with the
       user's density preference. The `var(..., 56px)` fallbacks below cover it never being stamped. */
}
.tt-no-topbar          { --tt-app-top: 0px; }
body.tt-bottombar      { --tt-app-bottom: var(--tt-taskbar-h, 46px); }
.tt-no-topbar .mud-drawer { top: 0 !important; }
.tt-no-topbar .mud-drawer.mud-drawer-fixed { height: 100vh !important; }

/* ── Reserve the fixed orchestrator taskbar's height at the bottom ───────────
   The taskbar is position:fixed and overlays the bottom ~46px, so page content and the nav drawer's last
   items end up hidden behind it — and a page that nearly fits has no overflow to scroll, so the wheel looks
   dead. Reserve the bar's height so content stops above it and short pages stay fully reachable.
   body.tt-bottombar is toggled by TritiumWindowHost from the live taskbar settings (off when the bar is
   auto-hidden or docked to the top). --tt-taskbar-h lives in tritiumWindow.css. */
body.tt-bottombar .mud-main-content { padding-bottom: var(--tt-taskbar-h, 46px); }
/* The nav drawer reserves its bottom with a physical spacer in NavMenuShell instead (padding on
   .mud-drawer-content proved unreliable), so no drawer rule here. */

/* ── Bar-mode AI chat popover (opens upward from the taskbar chat button) ──────
   .tt-chat-host is position:relative so the panel anchors to the BUTTON (absolute), sidestepping the
   taskbar's backdrop-filter containing-block trap. Veil below the panel (like the other launchers). */
.tt-chat-host { position: relative; display: inline-flex; }
.tt-chat-veil { position: fixed; inset: -100vh -100vw; z-index: 1199; }
.tt-chat-panel {
    position: absolute; bottom: calc(100% + 8px); left: 0;
    width: min(440px, 94vw); height: min(70vh, 640px);
    display: flex; flex-direction: column; overflow: hidden;
    border-radius: 12px; z-index: 1200;
    background: var(--mud-palette-surface);
    box-shadow: 0 12px 40px rgba(0,0,0,0.35);
}
.tt-chat-panel__hd {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
    padding: 4px 6px 4px 14px;
    background: var(--mud-palette-primary); color: var(--mud-palette-primary-text);
}
.tt-chat-panel__hd .mud-icon-root, .tt-chat-panel__hd .mud-icon-button { color: var(--mud-palette-primary-text) !important; }
.tt-chat-panel__title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.tt-chat-panel__body { flex: 1 1 auto; min-height: 0; display: flex; }
.tt-chat-panel__body > .chat-panel { flex: 1 1 auto; min-height: 0; width: 100%; }

/* ── TritiumMultiToggle — rounded horizontal segmented selector ─────────────── */
.tt-mtoggle {
    display: inline-flex; align-items: stretch; gap: 2px;
    padding: 3px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: var(--mud-palette-background-grey);
}
.tt-mtoggle__seg {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 5px 14px;
    border: 0; border-radius: 999px; background: transparent;
    font: inherit; font-size: .8rem; font-weight: 600; white-space: nowrap;
    color: var(--mud-palette-text-secondary); cursor: pointer;
    transition: background-color .14s ease, color .14s ease;
}
.tt-mtoggle__seg:hover:not(:disabled):not(.tt-mtoggle__seg--on) {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    color: var(--mud-palette-text-primary);
}
.tt-mtoggle__seg--on {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    box-shadow: 0 1px 3px color-mix(in srgb, var(--mud-palette-primary) 40%, transparent);
}
.tt-mtoggle__seg:disabled { opacity: .3; cursor: not-allowed; }
.tt-mtoggle__seg .mud-icon-root { color: inherit; }

/* While the assistant is working, spin the chat icon itself (instead of a progress circle). */
.chat-fab-spin { animation: chatfabspin 1s linear infinite; }
@keyframes chatfabspin { to { transform: rotate(360deg); } }

/* ── Global voice button: read-back ("speaking") pulse ──────────────────────
   Mirrors the floating voice pill's ring so the two surfaces read as the same system. Applied to a
   wrapper span rather than the button so the ring isn't clipped by the button's own bounds. */
.tt-voice-btn { display: inline-flex; border-radius: 50%; }
.tt-voice-btn--speaking { animation: ttVoiceSpeakPulse 1.6s ease-out infinite; }
@keyframes ttVoiceSpeakPulse {
    0%   { box-shadow: 0 0 0 0    rgba(244, 67, 54, 0.45); }
    70%  { box-shadow: 0 0 0 12px rgba(244, 67, 54, 0); }
    100% { box-shadow: 0 0 0 0    rgba(244, 67, 54, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .chat-fab-spin, .tt-voice-btn--speaking { animation: none; }
}

/* ── App launcher ("Start menu") FAB + floating window ─────────────────────── */
/* FAB defaults to the TOP-LEFT corner (first-run; docks over the toolbar title when the top bar is shown).
   Once dragged, the saved position (localStorage) overrides this. The chat FAB now stacks just below it. */
.launcher-fab {
    position: fixed;
    top: 12px;
    left: 12px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--mud-palette-primary-darken);
    border: none;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    z-index: 9999;
}

.launcher-fab:hover  { background: color-mix(in srgb, var(--mud-palette-primary-darken) 85%, #000); transform: scale(1.05); }
.launcher-fab:active { transform: scale(0.95); }

/* Sticky mode: pin the FAB to the top-left corner and disable dragging (overrides any saved position). */
.launcher-fab--sticky {
    top: 12px !important;
    left: 12px !important;
    right: auto !important;
    bottom: auto !important;
    cursor: pointer;
}

.launcher-window {
    position: fixed;
    bottom: 88px;
    left: 20px;
    width: min(920px, 94vw);
    height: min(640px, 82vh);
    /* User-resizable; bounds keep it usable. (Size resets to these defaults when reopened.) */
    resize: both;
    min-width: 360px;
    min-height: 380px;
    max-width: 96vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 12px 48px rgba(0,0,0,0.35);
    background: var(--mud-palette-surface);
    z-index: 9998;
}

/* Start placement: no FAB to trail, so the window is anchored to the bottom-left corner just above the
   taskbar (Windows Start menu). !important because launcherFabDrag stamps inline top/left on the element
   in floating mode and those can survive a placement switch within the same session. */
.launcher-window--start {
    left: 8px !important;
    top: auto !important;
    right: auto !important;
    bottom: calc(var(--tt-taskbar-h, 46px) + 8px) !important;
    /* The native grip lives at the bottom-right, which is pinned here — .launcher-grip replaces it. */
    resize: none;
}

/* Top-right resize grip (Start placement only). Sits above the header, which is why it needs a z-index:
   the header is a flex row of buttons and would otherwise take the pointer. */
.launcher-grip {
    position: absolute;
    top: 0;
    right: 0;
    width: 18px;
    height: 18px;
    z-index: 2;
    cursor: nesw-resize;
    /* Two hairlines tucked into the corner — the same visual language as a native grip, mirrored. */
    background:
        linear-gradient(to bottom left, transparent 0 42%, rgba(255,255,255,.55) 42% 52%, transparent 52%),
        linear-gradient(to bottom left, transparent 0 62%, rgba(255,255,255,.55) 62% 72%, transparent 72%);
    border-top-right-radius: 12px;
    touch-action: none;   /* let the pointer drag instead of scrolling the page on touch */
}
.launcher-grip:hover { background-color: rgba(255,255,255,.12); }

.launcher-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--mud-palette-primary-darken);
    padding: 6px 8px 6px 14px;
    flex-shrink: 0;
}

.launcher-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* Click-away catcher: sits below the window (9998) but above the app. */
.launcher-catcher {
    position: fixed;
    inset: 0;
    z-index: 9990;
}

/* Optional modal-style scrim: dim + blur the app behind the open launcher (user preference). */
.launcher-catcher.launcher-catcher-blur {
    background: rgba(0, 0, 0, 0.25);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    animation: launcher-scrim-in .15s ease;
}

@keyframes launcher-scrim-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* App-name pill that slides out to the RIGHT from behind the launcher FAB when it's "docked" over
   the toolbar title (top-left). Sits behind the FAB (z 9997) so it appears to emerge from under it.
   JS positions it; body.launcher-docked reveals it. */
.launcher-pill {
    position: fixed;
    z-index: 9997;
    padding: 6px 16px 7px 22px;         /* extra left padding clears the FAB it tucks behind */
    border-radius: 0 16px 16px 0;       /* flat left (under the FAB), rounded right end */
    background: var(--mud-palette-primary-darken);
    color: #fff;
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.15;
    white-space: nowrap;
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.28);
    opacity: 0;
    transform: translateX(-18px);
    pointer-events: none;
    transition: opacity .22s ease, transform .3s cubic-bezier(.2, .8, .2, 1);
}

body.launcher-docked .launcher-pill {
    opacity: 1;
    transform: translateX(0);
}

/* Hide the toolbar app title while the launcher is docked over it, so they don't collide. */
.tt-app-title {
    transition: opacity .2s ease;
}

body.launcher-docked .tt-app-title {
    opacity: 0;
    pointer-events: none;
}

/* ── RAG panel ──────────────────────────────────────────────────────────────── */
.rag-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 8px;
    overflow-y: auto;
    font-size: 0.85rem;
}

.rag-ingest-form {
    flex-shrink: 0;
}

.rag-doc-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.rag-empty-msg {
    color: var(--mud-palette-text-secondary);
    text-align: center;
    padding: 16px 0;
    font-size: 0.82rem;
}

.rag-doc-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 0 4px 4px;
    border-bottom: 1px solid var(--mud-palette-divider);
    gap: 4px;
}

.rag-doc-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.rag-doc-title {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rag-doc-meta {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.mud-input-label {
    color:var(--mud-palette-secondary) !important;
}
.mud-input-control>.mud-input-control-input-container>.mud-input-label-inputcontrol {
    font-size: 0.95em !important;
}

.mud-input-helper-text {
    color:var(--mud-palette-action-default) !important;
}

.label-circle {
    width: 30px;
    height:24px;
    border-radius: 20%;
    cursor:pointer;
}

.label-circle.active {
    
}

.tt-tr-inv-line-row-container{    
}

.tt-td-inv-lineNumber{
    font-size: 0.70rem;
    color:white;
    background-color: silver;
    padding: 2px;
    border-radius: 5px;
    margin: 3px;
    text-align: center;
}



.mud-stepper-actions {
    display: none !important;
}
.tt-adornment-text .mud-input-adornment-text {
    font-size: 0.7em !important;
    background-color: #8c8c8c;
    color:white;
    padding: 2px;
    margin-top: 4px;
    padding-left: 5px;
    padding-right: 5px;
    border-radius: 4px;
}
.tt-adornment-asset .mud-input-adornment-text{
    background-color: #068662 !important;
    color:white !important;      
}
.tt-adornment-revenue .mud-input-adornment-text{
    background-color: #52ab09 !important;
    color:white !important;      
}
.tt-adornment-liability .mud-input-adornment-text{
    background-color: #f26118 !important;
    color:white !important;    
}
.tt-adornment-expense .mud-input-adornment-text{
    background-color: #c60776 !important;
    color:white !important;      
}
.tt-adornment-equity .mud-input-adornment-text{
    background-color: #0982a0 !important;
    color:white !important;      
}

.tritium-bg-info {
    background-color: #1565C0 !important;
}
.tritium-blur  {
    backdrop-filter: blur(10px);
}

.tritium-nodata-box {
    display: flex;
    flex-direction: column;
    padding: 10px;
    justify-content: center;
    align-items: center;
}

.tritium-nodata-icon {
    margin-top: 20px;
    font-size: 4em !important;
    color: var(--mud-palette-text-disabled);
}

.tritium-nodata-text {
    margin-top: 15px;
    margin-bottom: 30px;
    font-size: 1.1em !important;
    font-weight: 200;
    color: var(--mud-palette-text-disabled);
}

.tw-100{
    width: 100% !important;
}
/* Full-width tab-panel content that stacks its children (MudBlazor v9 panel content is flex-row by
   default, which puts siblings side-by-side and shrinks them to content width). */
.tw-col-100{
    width: 100% !important;
    display: flex;
    flex-direction: column;
}
/* Full-width tab-panel content laid out as main area + ~20% aside (e.g. a table + an info note). The
   first child grows to fill; the last child is pinned to 20%. */
.tw-aside{
    width: 100% !important;
    display: flex;
    align-items: flex-start;
    gap: 16px;
}
.tw-aside > :first-child{
    flex: 1 1 auto;
    min-width: 0;
}
.tw-aside > :last-child{
    flex: 0 0 20%;
}

.tt-subtitle {
 color: var(--mud-palette-primary) !important; 
 font-size: 1.3em;
 padding-bottom: 20px;
}

.tt-cursor {
    cursor: pointer;
    user-select: none;    
}

.tt-sub-caption {
    color: var(--mud-palette-primary) !important; 
    font-size: 0.8em;
}
.tt-bold {
    font-weight: bold !important;
}
.tritium.mud-tab {
    text-transform: none !important;
    justify-content: start !important;
    font-weight: normal !important;
    font-size: 0.95em !important;
}
.tritium-center.mud-tab {
    text-transform: none !important;
    justify-content: center !important;
    font-weight: normal !important;
    font-size: 0.95em !important;
}
.mud-tab.mud-tab-active {
    background: color-mix(in srgb, var(--mud-palette-primary) 60%, transparent) !important; /* your color */
    color: white !important; /* optional for contrast */
    border-radius: 2px 4px 0 0; /* optional */
}
.mud-tab-slider.mud-tab-slider-vertical {
    width: 5px !important;
    right: 0;
    transition: top .3s cubic-bezier(0.64, 0.09, 0.08, 1);
    will-change: top;
    background-color: var(--mud-palette-secondary) !important;
}
.mud-tabs.mud-tabs-rounded .mud-tabs-tabbar {
    text-align: left !important;
    border-radius: var(--mud-default-borderradius);
    background: rgb(
        from var(--mud-palette-primary)
        r g b / 0.1
    ) !important; /* your color */
}

/* Vertical (left/right) tab layout — keep tabbar at natural width, panels fill the rest */
.mud-tabs.mud-tabs-vertical > .mud-tabs-tabbar {
    flex-shrink: 0;
}
.mud-tabs.mud-tabs-vertical > .mud-tabs-panels {
    flex: 1;
    min-width: 0;
    overflow: hidden;
}

.mud-nav-link {
    text-decoration: none !important;
}

/* ── Calendar ─────────────────────────────────────────────────────────────── */

.cal-layout {
    display: flex;
    gap: 0;
    height: calc(100vh - 100px);
    overflow: hidden;
    user-select: none;
}

/* Sidebar */
.cal-sidebar {
    width: 240px;
    min-width: 240px;
    padding: 12px;
    border-right: 1px solid var(--mud-palette-divider);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-background);
    color: var(--mud-palette-text-primary);
}

.cal-calendar-row {
    padding: 2px 4px;
    border-radius: 4px;
    transition: background .15s;
}
.cal-calendar-row:hover { background: var(--mud-palette-action-hover); }

/* Main area */
.cal-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Toolbar */
.cal-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px;
    border-bottom: 1px solid var(--mud-palette-divider);
    flex-shrink: 0;
}

/* Mini month picker */
.cal-mini-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 1px;
    text-align: center;
    font-size: 12px;
}
.cal-mini-header { font-weight: 600; color: var(--mud-palette-text-secondary); padding: 2px 0; }
.cal-mini-day {
    padding: 3px 0;
    border-radius: 50%;
    color: var(--mud-palette-text-primary);
    cursor: pointer;
    transition: background .15s;
    line-height: 1.6;
}
.cal-mini-day:hover    { background: var(--mud-palette-action-hover); }
.cal-mini-today        { background: var(--mud-palette-primary); color: #fff; border-radius: 50%; }
.cal-mini-selected     { background: color-mix(in srgb, var(--mud-palette-primary) 25%, transparent); border-radius: 50%; }
.cal-mini-other        { opacity: .35; }

/* ── Month view ─────────────────────────────────────────────────────────── */

.cal-month-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    flex: 1;
    overflow-y: auto;
    border-left: 1px solid var(--mud-palette-divider);
    border-top: 1px solid var(--mud-palette-divider);
}
.cal-month-header {
    text-align: center;
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    padding: 6px 4px;
    border-right: 1px solid var(--mud-palette-divider);
    border-bottom: 1px solid var(--mud-palette-divider);
    background: var(--mud-palette-background-grey);
    text-transform: uppercase;
}
.cal-month-cell {
    min-height: 100px;
    padding: 4px 6px 6px;
    border-right: 1px solid var(--mud-palette-divider);
    border-bottom: 1px solid var(--mud-palette-divider);
    cursor: pointer;
    overflow: hidden;
    transition: background .12s;
}
.cal-month-cell:hover { background: var(--mud-palette-action-hover); }
.cal-other-month { opacity: .45; }
.cal-today-cell  { background: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent); }

.cal-day-number {
    font-size: 13px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 2px;
    width: 24px;
    line-height: 24px;
    text-align: center;
}
.cal-today-number {
    background: var(--mud-palette-primary);
    color: #fff !important;
    border-radius: 50%;
}
.cal-event-chip {
    font-size: 11px;
    padding: 1px 18px 1px 6px;
    border-radius: 10px;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 2px;
    cursor: pointer;
    transition: filter .15s;
    position: relative;
}
.cal-event-chip:hover  { filter: brightness(0.88); }
.cal-event-bullet {
    position: absolute;
    top: 8px;    
    right: 5px;
    transform: translateY(-50%);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    pointer-events: none;
}
.cal-event-time        { font-size: 10px; margin-right: 3px; opacity: .85; }
.cal-more-link         { font-size: 11px; color: var(--mud-palette-primary); cursor: pointer; font-weight: 500; }
.cal-more-link:hover   { text-decoration: underline; }

/* ── Week / Day view ─────────────────────────────────────────────────────── */

.cal-week-container {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
}
.cal-week-header {
    display: grid;
    grid-template-columns: var(--cal-gutter-px) repeat(7, 1fr);
    border-bottom: 1px solid var(--mud-palette-divider);
    flex-shrink: 0;
}
.cal-day-grid .cal-week-header {
    grid-template-columns: var(--cal-gutter-px) 1fr;
}
.cal-week-day-header {
    text-align: center;
    padding: 8px 4px;
    background: color-mix(in srgb, var(--mud-palette-primary) 30%, transparent);
    cursor: pointer;
    border-left: 1px solid var(--mud-palette-divider);
    transition: background .12s;
}
.cal-week-day-header:hover { background: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent); }
.cal-today-header          { background: color-mix(in srgb, var(--mud-palette-primary) 55%, transparent); }
.cal-week-day-name         { font-size: 11px; color: var(--mud-palette-text-primary); font-weight: 600; text-transform: uppercase; opacity: .8; }
.cal-week-day-num          { font-size: 18px; font-weight: 400; line-height: 32px; width: 32px; margin: 0 auto; border-radius: 50%; color: var(--mud-palette-text-primary); }
.cal-time-gutter           { width: var(--cal-gutter-px); min-width: var(--cal-gutter-px); background: color-mix(in srgb, var(--mud-palette-secondary) 5%, transparent); text-align: center; display: flex; align-items: center; justify-content: center; }

/* All-day row */
.cal-allday-row {
    display: grid;
    grid-template-columns: var(--cal-gutter-px) repeat(7, 1fr);
    background: color-mix(in srgb, var(--mud-palette-secondary) 10%, transparent);
    border-bottom: 1px solid var(--mud-palette-divider);
    min-height: 28px;
    flex-shrink: 0;
}
.cal-allday-cell {
    border-left: 1px solid var(--mud-palette-divider);
    padding: 2px 4px;
}
.cal-allday-event {
    font-size: 11px;
    padding: 1px 18px 1px 6px;
    border-radius: 3px;
    color: #fff;
    margin-bottom: 1px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
}

/* Time grid */
:root { --cal-hour-px: 64px; --cal-gutter-px: 72px; }
.cal-week-grid-scroll { flex: 1; overflow-y: auto; }
.cal-time-grid-wrapper { position: relative; }
.cal-week-grid {
    display: grid;
    grid-template-columns: var(--cal-gutter-px) repeat(7, 1fr);
}
.cal-day-grid { grid-template-columns: var(--cal-gutter-px) 1fr; }
.cal-time-label {
    padding: 0 6px;
    border-top: 1px solid var(--mud-palette-divider);
    height: var(--cal-hour-px);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
}
.cal-week-slot {
    border-left: 1px solid var(--mud-palette-divider);
    border-top: 1px solid var(--mud-palette-divider);
    height: var(--cal-hour-px);
    position: relative;
    cursor: pointer;
    transition: background .1s;
}
.cal-week-slot:hover { background: var(--mud-palette-action-hover); }
.cal-today-slot      { background: color-mix(in srgb, var(--mud-palette-primary) 4%, transparent); }

/* Events overlay (sits on top of the background grid) */
.cal-events-overlay {
    position: absolute;
    top: 0; left: 0; right: 0;
    height: calc(var(--cal-hour-px) * 24);
    display: flex;
    pointer-events: none;
}
.cal-events-gutter  { width: var(--cal-gutter-px); min-width: var(--cal-gutter-px); flex-shrink: 0; }
.cal-events-body    { flex: 1; display: flex; height: 100%; }
.cal-events-col     {
    flex: 1;
    position: relative;
    overflow: hidden;
    pointer-events: all;
}

.cal-time-event {
    position: absolute;
    left: 2px;
    right: 2px;
    border-radius: 4px;
    color: #fff;
    padding: 2px 5px;
    font-size: 11px;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    z-index: 1;
    display: flex;
    flex-direction: column;
    pointer-events: all;
    transition: filter .15s, opacity .15s;
}
.cal-time-event:hover    { filter: brightness(0.88); z-index: 2; }
.cal-event-title         { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-event-time          { font-size: 10px; opacity: .85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-event-dragging      { opacity: 0.35 !important; }

/* Resize handle (bottom edge of event) */
.cal-resize-handle {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    height: 8px;
    cursor: s-resize;
    opacity: 0;
    transition: opacity .15s;
    background: rgba(255,255,255,0.25);
    border-radius: 0 0 4px 4px;
}
.cal-time-event:hover .cal-resize-handle { opacity: 1; }

/* Resize ghost */
.cal-resize-ghost {
    position: absolute;
    left: 2px; right: 2px;
    border-radius: 4px;
    border: 2px dashed rgba(255,255,255,0.7);
    pointer-events: none;
    z-index: 10;
}

/* ── Agenda view ─────────────────────────────────────────────────────────── */

.cal-agenda { flex: 1; overflow-y: auto; padding: 8px 16px; }
.cal-agenda-date-row {
    display: flex;
    gap: 16px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--mud-palette-divider);
    padding-bottom: 8px;
}
.cal-agenda-date {
    width: 52px;
    min-width: 52px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: 4px;
}
.cal-agenda-day {
    font-size: 24px;
    font-weight: 300;
    line-height: 1.1;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--mud-palette-text-primary);
}
.cal-agenda-events { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.cal-agenda-event {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    transition: background .12s;
}
.cal-agenda-event:hover { background: var(--mud-palette-action-hover); }
.cal-agenda-color  { width: 4px; min-width: 4px; height: 36px; border-radius: 2px; }
.cal-agenda-info   { flex: 1; color: var(--mud-palette-text-primary); }

/* ── Calendar context menu ─────────────────────────────────────────────── */
.cal-ctx-backdrop {
    position: fixed;
    inset: 0;
    z-index: 9998;
}
.cal-ctx-menu {
    border-radius: 8px;
    overflow: hidden;
    padding: 4px 0;
}
.cal-ctx-item { padding: 6px 16px !important; }
.cal-ctx-item-danger { color: var(--mud-palette-error) !important; }

/* ── DataVault tree — selected item highlight ────────────────────────────── */
.mud-treeview.mud-treeview-selected-primary .mud-treeview-item-content.mud-treeview-item-selected {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 20%, transparent) !important;
}

.mud-table-cell{
    padding-left: 14px !important;
    padding-right: 6px !important;
    padding-top: 4px !important;
    padding-bottom: 4px !important;
}

/* ── MySuitcase toolbar popup (mirrors .notes-panel-*) ─────────────── */
.msc-panel-host { position: relative; display: inline-flex; }
.msc-panel-overlay { position: fixed; inset: 0; z-index: 1199; }
.msc-panel-dropdown {
    position: fixed; top: 48px; right: 8px;
    width: 520px; max-height: calc(100vh - 64px);
    overflow-y: auto; z-index: 1200;
    border-radius: 0 0 8px 8px;
    background: var(--mud-palette-surface);
}

/* ── TritiumDataGrid — standard column-header look ──────────────────────
   Applied via the component's always-on "tritium-grid" class so every grid
   gets the house header (small caps) without repeating HeaderStyle per column.
   Column-level inline HeaderStyle still wins where a page needs to differ. */
.tritium-grid th.mud-table-cell,
.tritium-grid th.mud-table-cell .mud-table-sort-label,
.tritium-grid th.mud-table-cell .column-header {
    font-size: 0.6rem !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.07em;
}

/* Right-aligned columns (HeaderStyle="text-align:right;"): MudBlazor renders the header
   title inside a flex .column-header (justify-content:space-between), so text-align alone
   can't move it — push the flex content to the end whenever the th is right-aligned. */
.tritium-grid th.mud-table-cell[style*="text-align:right"] .column-header {
    justify-content: flex-end;
}
.tritium-grid th.mud-table-cell[style*="text-align:right"] .column-header .sortable-column-header {
    text-align: right;
}

/* Column resizer (only rendered when Resizable="true"). MudBlazor's default resizer is transparent
   until hover, so users can't tell columns are resizable. Make it a persistent, visible grab handle.
   !important + the proven .tritium-grid ancestor selector guarantee it beats MudBlazor's own rule. */
.tritium-grid .mud-resizer {
    top: 0 !important;
    bottom: 0 !important;
    height: 100% !important;
    width: 12px !important;
    border-right: 2px solid var(--mud-palette-lines-default) !important;
    transition: border-color .12s, background-color .12s;
}
.tritium-grid .mud-resizer:hover {
    border-right: 2px solid var(--mud-palette-primary) !important;
    background-color: var(--mud-palette-action-default-hover) !important;
}

/* ── My Company dialog (CompanyInfoDialog): fixed-height tabs — the dialog never scrolls;
      each tab's TritiumCardPanel body is the only scroll container, with the section notes
      pinned inside the card below the scrolled content. ─ */
/* Now a TritiumWindow: the dialog fills the window body and the tab panels do the scrolling,
   so there is no viewport-relative height to guess at any more. */
.cid-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.cid-form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.cid-tabs { flex: 1 1 auto; min-height: 0; }
.cid-panel { height: 100%; padding: 0 !important; }   /* the inner .cid-tab supplies the padding */
.cid-tab { height: 100%; display: flex; flex-direction: column; overflow: hidden; }
.cid-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.cid-fill > .tcp-body {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column;
    overflow: hidden;
    padding: 0 !important;          /* inner .cid-scroll re-adds it, so the scrollbar hugs the card edge */
}
.cid-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.cid-notes  { flex: 0 0 auto; padding: 0 12px 10px; }
/* Full-height grid variant (My Company tab): the grid fills the tab and each column
   becomes a flex column so a cid-fill card inside stretches to the bottom. */
.cid-grid { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.cid-grid > .mud-grid-item.cid-col { display: flex; flex-direction: column; min-height: 0; }

/* ── Section notes (SectionNotesPanel): code/JSON-style monospace text ─ */
.section-notes-input textarea {
    font-family: 'Cascadia Code', Consolas, 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
    font-size: 0.78rem;
    line-height: 1.5;
}

/* ── Pinned icons row (above explorer grids) ────────────────────────── */
.pinned-icons-row {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 6px 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.pinned-icon {
    position: relative;
    display: flex; flex-direction: column; align-items: center;
    width: 64px; cursor: pointer; padding: 4px; border-radius: 8px;
    transition: background 0.15s;
}
.pinned-icon:hover { background: var(--mud-palette-action-hover); }
.pinned-icon-name {
    font-size: 0.6rem; text-align: center; margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    width: 100%; color: var(--mud-palette-text-secondary);
}
.pinned-icon-wrapper {
    position: relative; display: inline-flex;
    align-items: center; justify-content: center;    
}
.pinned-status-badge {
    position: absolute; bottom: -3px; left: -3px;
    font-size: 14px !important; pointer-events: none;
}
.pinned-unpin-wrap {
    position: absolute; top: -6px; right: -6px; z-index: 1;        
}
.pinned-unpin-wrap .mud-icon-button {
    width: 14px; height: 14px; padding: 0;
    opacity: 0.65; transition: opacity 0.15s;
    background-color:rgb(116, 116, 116);
    color:white;    
    border-radius: 50px;    
}
.pinned-unpin-wrap .mud-icon-button:hover { 
    background-color:rgb(184, 0, 0);
    opacity: 1; 
}
.pinned-unpin-wrap .mud-icon-button .mud-icon-root { font-size: 16px; }
.pinned-unpin-wrap .mud-icon-button .mud-icon-root {
    font-size: 10px !important;
}
/* ── MySuitcase manager (inside the dropdown panel) ─────────────────── */
.msc-group { padding: 8px 12px; }
.msc-group-header {
    font-size: 0.65rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--mud-palette-text-secondary);
    margin-bottom: 6px; padding-bottom: 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.msc-icons-row { display: flex; flex-wrap: wrap; gap: 8px; }
.msc-icon {
    position: relative;
    display: flex; flex-direction: column; align-items: center;
    width: 64px; cursor: pointer; padding: 4px; border-radius: 8px;
    transition: background 0.15s;
}
.msc-icon:hover { background: var(--mud-palette-action-hover); }
.msc-icon-name {
    font-size: 0.6rem; text-align: center; margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    width: 100%; color: var(--mud-palette-text-secondary);
}

.bg-shade-primary {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent) !important;
}
.bg-shade-secondary {
    background-color: color-mix(in srgb, var(--mud-palette-secondary) 10%, transparent) !important;
}

.blur {
    backdrop-filter: blur(10px);
}

.dialog-background {
        
}

.dialog-background-title {
    background: rgba(var(--mud-palette-primary-rgb), 0.3) !important;
    /* Use the theme's primary text colour (dark on light themes, light on dark themes) so the
       title stays high-contrast against the translucent primary-tinted bar in every theme.
       (Previously referenced the undefined var --mud-palette-white1, which left the title
       with no reliable colour and effectively invisible on some themes.) */
    color: var(--mud-palette-text-primary) !important;
}

.dialog-background-surface {
    background: rgba(var(--mud-palette-surface-rgb), 0.75);
}

.dialog-action-bar{
    background: rgba(var(--mud-palette-primary-rgb), 0.3) !important;
    color: var(--mud-palette-white);
}

/* ── AIA Construction Billing ─────────────────────────────────────────────── */

/* G702 two-column layout: sidebar + G703 grid */
.aia-g702-layout {
    display: flex;
    gap: 16px;
    min-height: 60vh;
}
.aia-g702-sidebar {
    flex: 0 0 260px;
    min-width: 220px;
    border-right: 1px solid var(--mud-palette-lines-default);
    padding-right: 12px;
    overflow-y: auto;
}
.aia-g703-grid {
    flex: 1 1 0;
    overflow-x: auto;
}

/* G703 table */
.aia-g703-table-wrap { overflow-x: auto; }
.aia-g703-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.75rem;
}
.aia-g703-table th,
.aia-g703-table td {
    padding: 4px 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    vertical-align: middle;
    white-space: nowrap;
}
.aia-g703-table th {
    background: var(--mud-palette-background-grey);
    font-weight: 600;
    text-align: right;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}
.aia-g703-table th.aia-col-item,
.aia-g703-table th.aia-col-desc { text-align: left; }
.aia-col-item  { width: 48px; }
.aia-col-desc  { min-width: 180px; max-width: 260px; white-space: normal; }
.aia-col-num   { text-align: right; min-width: 90px; }
.aia-col-pct   { text-align: right; width: 56px; }
.aia-col-input { width: 120px; }

.aia-row-modified td { background: rgba(var(--mud-palette-warning-rgb), 0.08); }
.aia-totals-row td   { font-weight: 600; background: var(--mud-palette-background-grey); }
.aia-amount-cell     { display: block; text-align: right; font-size: 0.8rem; padding: 4px 2px; }

/* G702 totals sidebar block */
.aia-totals-block { font-size: 0.8rem; }
.aia-total-row {
    display: flex;
    justify-content: space-between;
    padding: 2px 0;
    gap: 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.aia-total-row span:first-child { color: var(--mud-palette-text-secondary); }
.aia-total-earned { color: var(--mud-palette-success-text); font-weight: 600; }
.aia-total-due    { color: var(--mud-palette-primary); font-weight: 700; font-size: 0.85rem; }

/* Contract summary card in application sidebar */
.aia-summary-card {
    background: rgba(var(--mud-palette-primary-rgb), 0.08) !important;
    border-radius: 8px;
    border-left: 3px solid var(--mud-palette-primary);
}

.tt-panel-header{
    display: flex;
    justify-content: space-between;
    width: 100%;    
    align-items: center;
    border-bottom: 1px solid rgb(185, 185, 185);
    padding: 12px;
    margin-bottom: 8px;
}
.tt-panel-header-title{
    color: rgba(var(--mud-palette-primary-rgb), 0.8); 
}

.mud-dialog .mud-dialog-content.mud-dialog-no-side-padding {
    padding: 0px 0px !important;
    margin: 0 !important;
}

.tt_item_container{
    background: rgba(var(--mud-palette-primary-rgb), 0.04) !important;
    /* border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.8);  */
    padding: 4px;
    border-radius: 4px;
}
.tt-item {
    padding: 5px;
    border:1px solid;
    border-color: color-mix(in srgb, var(--mud-palette-dark-darken) 10%, transparent);
    border-radius:var(--mud-default-borderradius);
    background-color:color-mix(in srgb, var(--mud-palette-dark-lighten) 6%, transparent);
}
.tt-border-primary {
    border: 1px solid var(--mud-palette-primary) !important;
}

.tt-nav-menu-wrapper {
    background:linear-gradient(130deg, 
        color-mix(in srgb, var(--mud-palette-secondary-darken) 100%, transparent) 20%, 
        color-mix(in srgb, var(--mud-palette-primary-darken) 100%, transparent) 80%); 
}
.tt-nav-menu-wrapper-dark {
    background:linear-gradient(130deg, 
        color-mix(in srgb, var(--mud-palette-secondary) 40%, black) 50%, 
        color-mix(in srgb, var(--mud-palette-primary-lighten) 40%, black) 80%); 
}

.tt-nav-menu-group{    
    font-weight: lighter !important;            
    color:white !important;
}
.tt-nav-menu-item{    
    font-weight: lighter !important;
    color:white !important;
}

.tt-nav-menu-group .mud-nav-link-text{
    font-weight: 600 !important;
    color: color-mix(in srgb, var(--mud-palette-secondary-lighten) 60%, white) !important;
}
.tt-nav-menu-item .mud-nav-link-text{
    font-weight: 400 !important;
    color:white !important;
}

.tt-nav-menu-item .a {
 
}
.tt-txt-menu{
    color:white !important;
}
.tt-nav-menu-group .mud-nav-link .mud-nav-link-expand-icon{
    color:white !important;
}
.mud-navmenu.mud-navmenu-primary .mud-nav-link-expand-icon.mud-transform {
    fill: white !important;
}
.tt-nav-icon-item .mud-icon-button{
    color:white !important;
}
/* The setup wizard header + the "being configured" wall reuse the toolbar menus
   (ThemeChanger / LanguageSwitcher) but sit on the theme surface, not the always-dark
   app-bar — so their icons must follow the theme text color, or they vanish in light mode. */
.sw-header-actions .tt-nav-icon-item .mud-icon-button,
.sw-gate-actions   .tt-nav-icon-item .mud-icon-button {
    color: var(--mud-palette-text-primary) !important;
}
.tt-nav-menu-group .mud-nav-link-icon {
    color: color-mix(in srgb, var(--mud-palette-primary-lighten) 60%, white) !important;
}
.tt-nav-menu-item .mud-nav-link-icon {
    color: color-mix(in srgb, var(--mud-palette-secondary-lighten) 70%, white) !important;
}
.tt-nav-menu-item .mud-nav-link.active:not(.mud-nav-link-disabled){
    background-color: #000000 !important;
    color:white !important;
    font-weight: 400 !important;
}
.tt-module-name{
    font-size: 1.2rem;
    font-weight: 100;
    color: white;
}
.tt-dialog-tab-page{
    padding: 20px;
    overflow: auto;
    max-height: 75vh;

}

/* ── Product editor in a TritiumWindow (same shape as My Company) ──
   The window sizes the dialog, so the tab strip fills it and the panel scrolls — no viewport-relative
   height, and the panel drops its own padding because .tt-dialog-tab-page already supplies it. */
.pd-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.pd-form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.pd-tabs { flex: 1 1 auto; min-height: 0; }
.pd-panel { height: 100%; padding: 0 !important; }
.pd-panel > .tt-dialog-tab-page { height: 100%; max-height: none; }

/* ── Contact editor in a TritiumWindow ──
   Same shape, with one extra wrinkle: the validation-error rail sits BESIDE the tab strip, so the flex row
   between them has to carry the height down. */
.cd-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.cd-root > .mud-form,
.cd-root > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.cd-root .w-100.d-flex { flex: 1 1 auto; min-height: 0; }
.cd-root .w-100.d-flex > .w-100 { display: flex; flex-direction: column; min-height: 0; }
.cd-tabs { flex: 1 1 auto; min-height: 0; }
.cd-panel { height: 100%; }

/* ── Employee editor in a TritiumWindow (same shape as My Company / Contact) ── */
.ed-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.ed-root > .mud-form, .ed-root > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ed-tabs { flex: 1 1 auto; min-height: 0; }
.ed-panel { height: 100%; }

/* ── Project editor in a TritiumWindow ── */
.pj-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.pj-root > .mud-form, .pj-root > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.pj-tabs { flex: 1 1 auto; min-height: 0; }
.pj-panel { height: 100%; }

/* ── AIA contract editor in a TritiumWindow (spinner-then-tabs, no MudForm wrapper) ── */
.aia-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.aia-root > .aia-tabs { flex: 1 1 auto; min-height: 0; }
.aia-panel { height: 100%; }

/* ── Catalogs (pure container: 8 self-managing panels, no save) ── */
.cat-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.cat-root > .cat-tabs { flex: 1 1 auto; min-height: 0; }
.cat-panel { height: 100%; }

/* ── Branch editor in a TritiumWindow ── */
.br-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.br-root > .mud-form, .br-root > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.br-tabs { flex: 1 1 auto; min-height: 0; }
.br-panel { height: 100%; }

/* ── Edit company (super-user) in a TritiumWindow ── */
.ecd-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.ecd-root > .mud-form, .ecd-root > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ecd-tabs { flex: 1 1 auto; min-height: 0; }
.ecd-panel { height: 100%; }

/* ── Calendar event editor in a TritiumWindow ── */
.cev-root { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.cev-tabs { flex: 1 1 auto; min-height: 0; }
.cev-panel { height: 100%; }

/* ── Product image preview (General tab) ─────────────────────────────────── */
.product-img-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 10px;
    background: var(--mud-palette-background-grey);
    min-height: 160px;
    overflow: hidden;
}
.product-img-preview img {
    max-height: 200px;
    max-width: 100%;
    object-fit: contain;
    border-radius: 4px;
}
.product-img-error,
.product-img-no-url {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
    opacity: 0.45;
    text-align: center;
}

/* ── Help drawer ─────────────────────────────────────────────────────────── */
.help-drawer-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}
.help-drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 8px 6px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    flex-shrink: 0;
}
.help-drawer-search {
    padding: 10px 12px 4px;
    flex-shrink: 0;
}
.help-drawer-content {
    flex: 1;
    overflow-y: auto;
    padding: 8px 16px 24px;
}
.help-topic-item {
    display: flex;
    align-items: center;
    padding: 9px 8px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.15s;
    gap: 10px;
}
.help-topic-item:hover {
    background: var(--mud-palette-action-hover);
}

/* ── Help Markdown content ───────────────────────────────────────────────── */
.help-md h1 {
    font-size: 1.05rem; font-weight: 700;
    margin: 0.2rem 0 0.6rem;
}
.help-md h2 {
    font-size: 0.88rem; font-weight: 700;
    margin: 1.2rem 0 0.35rem;
    padding-bottom: 3px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.help-md h3 {
    font-size: 0.82rem; font-weight: 600;
    margin: 0.8rem 0 0.25rem;
}
.help-md p {
    font-size: 0.8rem; line-height: 1.65;
    margin: 0 0 0.55rem;
    color: var(--mud-palette-text-primary);
}
.help-md ul, .help-md ol {
    font-size: 0.8rem; padding-left: 1.4rem;
    margin: 0 0 0.55rem;
}
.help-md li {
    margin-bottom: 0.22rem;
    line-height: 1.55;
}
.help-md code {
    font-size: 0.74rem;
    background: var(--mud-palette-background-grey);
    padding: 1px 5px; border-radius: 3px;
    font-family: monospace;
}
.help-md strong { font-weight: 700; }
.help-md em     { font-style: italic; }
.help-md a      { color: var(--mud-palette-primary); }
.help-md blockquote {
    border-left: 3px solid var(--mud-palette-primary);
    margin: 0.5rem 0; padding-left: 10px;
    opacity: 0.8;
    font-style: italic;
}
.help-md table {
    width: 100%; border-collapse: collapse;
    font-size: 0.77rem; margin-bottom: 0.6rem;
}
.help-md th {
    font-weight: 700; text-align: left;
    padding: 4px 8px;
    border-bottom: 2px solid var(--mud-palette-lines-default);
}
.help-md td {
    padding: 4px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.help-md hr {
    border: none;
    border-top: 1px solid var(--mud-palette-lines-default);
    margin: 1rem 0;
}

/* ── Internal Messaging ──────────────────────────────────────────────────── */

/* ── Toolbar popup (mirrors notes/suitcase pattern) ─── */
.msg-panel-host { position: relative; display: inline-flex; }
.msg-panel-overlay { position: fixed; inset: 0; z-index: 1199; }
.msg-panel-dropdown {
    position: fixed; top: 48px; right: 8px;
    width: 380px; max-height: calc(100vh - 64px);
    overflow-y: auto; z-index: 1200;
    border-radius: 0 0 8px 8px;
    background: var(--mud-palette-surface);
}
.msg-panel-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    position: sticky; top: 0;
    background: var(--mud-palette-surface); z-index: 1;
}
.msg-panel-item {
    display: flex; flex-direction: column;
    padding: 10px 14px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    cursor: pointer; transition: background 0.15s;
}
.msg-panel-item:hover { background: var(--mud-palette-action-hover); }
.msg-panel-item--unread {
    background: color-mix(in srgb, var(--mud-palette-primary) 5%, var(--mud-palette-surface));
}

/* ── Message Explorer layout ─── */
.msg-explorer-layout {
    display: grid;
    grid-template-columns: 300px 1fr;
    height: calc(100vh - 85px);
    gap: 0;
    overflow: hidden;    
}
.msg-explorer-sidebar {
    border-right: 1px solid var(--mud-palette-lines-default);
    overflow-y: auto;
    padding: 10px;    
    background-color: var(--mud-palette-surface) !important;
    border: 1px solid var(--mud-palette-lines-default);
}
.msg-explorer-main {
    display: flex; flex-direction: column;
    overflow: hidden; min-height: 0;
    background-color: var(--mud-palette-surface) !important;
    border: 1px solid var(--mud-palette-lines-default);
}
.msg-explorer-list {
    display: flex; flex-direction: column;
    /* Percentage of .msg-explorer-main's own (already-bounded) height, not the viewport — was
       `calc(50vh - 40px)`, which is only correct when this page fills the real browser viewport and
       breaks inside a window (see docs/page-window-contract.md §5k). Equivalent to ~2px difference from
       the old value in page mode, so this is a plain correctness fix, not conditional on hosting. */
    flex: 0 0 50%;
    height: 50%;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    overflow: hidden;
}
.msg-list-toolbar {
    display: flex; align-items: center; gap: 6px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    flex-shrink: 0;
}
.msg-label-filter {
    display: flex; align-items: center;
    padding-left: 4px;
    border-left: 1px solid var(--mud-palette-lines-default);
}
.msg-grid-loading-overlay {
    position: absolute; inset: 0; z-index: 2;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--mud-palette-surface) 65%, transparent);
    backdrop-filter: blur(1px);
}
.msg-panel-resizer {
    flex: 0 0 5px;
    height: 5px;
    cursor: row-resize;
    background: var(--mud-palette-lines-default);
    transition: background 0.15s;
    z-index: 1;
}
.msg-panel-resizer:hover,
.msg-panel-resizer:active {
    background: var(--mud-palette-primary);
}
/* Vertical splitter bars between the Report Designer (V2) panes */
.rpt-resizer {
    flex: 0 0 5px;
    width: 5px;
    align-self: stretch;
    cursor: col-resize;
    background: var(--mud-palette-lines-default);
    transition: background 0.15s;
    z-index: 1;
}
.rpt-resizer:hover,
.rpt-resizer:active {
    background: var(--mud-palette-primary);
}
/* Compact editable Data Source Parameters grid */
.rpt-dsparam-grid .mud-table-cell {
    padding: 3px 8px;
    vertical-align: middle;
}
.rpt-dsparam-grid .mud-input-control {
    margin-top: 0;
}
.msg-explorer-preview {
    display: flex; flex-direction: column;
    flex: 1; min-height: 0;
    overflow: hidden;
}
.msg-preview-header {
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    flex-shrink: 0;
    overflow-y: auto;
    max-height: 260px;
}
.msg-preview-body {
    flex: 1; overflow-y: auto;
    padding: 16px 18px;
    font-size: 0.85rem; line-height: 1.65;
}
.msg-preview-body p  { margin-bottom: 0.5rem; }
.msg-preview-body blockquote {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 12px; opacity: 0.7; margin: 8px 0;
}

/* ── Folder sidebar ─── */
.msg-sidebar-section-header {
    font-size: 0.6rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--mud-palette-text-secondary);
    padding: 6px 8px 2px;
}
.msg-sidebar-item {
    display: flex; align-items: center;
    padding: 7px 8px; border-radius: 6px;
    cursor: pointer; font-size: 0.82rem;
    transition: background 0.15s;
}
.msg-sidebar-item:hover { background: var(--mud-palette-action-hover); }
.msg-sidebar-item--active {
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    font-weight: 600;
}
.msg-sidebar-item--dropzone {
    outline: 2px dashed var(--mud-palette-primary);
    outline-offset: -2px;
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
}
.msg-sidebar-subfolder {
    padding-left: 20px;
    font-size: 0.85rem;
}
.msg-subfolder-actions {
    display: none; align-items: center; gap: 0;
}
.msg-sidebar-subfolder:hover .msg-subfolder-actions { display: flex; }
/* Context-menu (⋮) action trigger on folder rows — always visible. */
.msg-folder-actions {
    display: flex; align-items: center; gap: 0; margin-left: 4px;
}
.msg-sidebar-new-folder {
    opacity: 0.6; cursor: pointer;
    padding-left: 20px; font-size: 0.82rem;
}
.msg-sidebar-new-folder:hover { opacity: 1; background: var(--mud-palette-action-hover); }
.msg-drag-handle {
    display: flex; align-items: center; justify-content: center;
    width: 22px; height: 100%; cursor: grab; opacity: 0.35;
    transition: opacity 0.15s;
}
.msg-drag-handle:hover { opacity: 0.85; }
.msg-drag-handle:active { cursor: grabbing; }

/* ── Unread indicator dot ─── */
.msg-unread-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--mud-palette-primary);
}

/* ── Compose dialog ─── */
.compose-field-row {
    display: flex; align-items: flex-start;
    padding: 6px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    min-height: 44px;
}
.compose-field-label {
    min-width: 76px; font-size: 0.8rem; font-weight: 600;
    color: var(--mud-palette-text-secondary);
    padding: 10px 12px 0 0; flex-shrink: 0;
}
.compose-to-chips {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 4px; flex: 1; padding-top: 6px;
}
.compose-editor-wrapper .ql-container { min-height: 200px; }
.compose-quoted {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 10px;
}
.compose-quoted-body {
    max-height: 120px; overflow-y: auto;
    font-size: 0.78rem;
}

/* ── Quill editor dark mode adjustments ─── */
.mud-theme-dark .ql-toolbar,
.mud-theme-dark .ql-container {
    border-color: var(--mud-palette-lines-default) !important;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-surface);
}
.mud-theme-dark .ql-editor.ql-blank::before { color: var(--mud-palette-text-secondary); }

/* ── Message view dialog ─── */
.msgview-meta { display:flex; flex-direction:column; gap:2px; padding:2px 0 4px; }
.msgview-body {
    padding: 6px 0 10px;
    overflow-y: auto;
    max-height: 55vh;
    font-size: 0.9rem;
}
.msgview-body p { margin-bottom: 0.5rem; }
.msgview-body blockquote {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 10px;
    color: var(--mud-palette-text-secondary);
}

/* ── Compose: attachment strip ─── */
.compose-attach-strip {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 4px; padding: 6px 0 2px;
    min-height: 36px;
    border-top: 1px dashed var(--mud-palette-lines-default);
    margin-top: 6px;
}

/* ── Compose: attached element tile ─── */
.compose-attach-item {
    display: flex; flex-direction: column; align-items: center;
    width: 60px; cursor: default; padding: 4px;
    border-radius: 8px;
}
.compose-attach-item .msc-icon-name { max-width: 58px; }

/* ── Suitcase Picker ─── */
.suitcase-picker { padding: 4px 6px; }
.sp-group { margin-bottom: 8px; }
.sp-group-header {
    font-size: 0.65rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--mud-palette-text-secondary);
    padding: 2px 4px 4px;
}
.sp-icons-row { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 4px; }
.sp-icon {
    display: flex; flex-direction: column; align-items: center;
    width: 56px; cursor: pointer; padding: 4px;
    border-radius: 8px; transition: background 0.15s;
}
.sp-icon:hover { background: var(--mud-palette-action-hover); }
.sp-icon--attached { opacity: 0.45; cursor: default; }
.sp-icon--attached:hover { background: transparent; }
.sp-icon-wrap {
    position: relative; display: inline-flex;
    align-items: center; justify-content: center;
    width: 36px; height: 36px;
}
.sp-status-badge, .sp-attached-badge {
    position: absolute; bottom: -2px; right: -4px;
    font-size: 12px !important; width: 14px; height: 14px;
}
.sp-icon-name {
    font-size: 0.62rem; text-align: center; line-height: 1.2;
    color: var(--mud-palette-text-secondary);
    max-width: 54px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    margin-top: 2px;
}

/* ── Message viewer: attachment cards ─── */
.msg-attachments {
    padding: 10px 18px 14px;
    border-top: 1px solid var(--mud-palette-lines-default);
}
.msg-attachments-label { display: flex; align-items: center; margin-bottom: 8px; }
.msg-attachments-row { display: flex; flex-wrap: wrap; gap: 8px; }
.msg-attachment-card {
    display: flex; flex-direction: column; align-items: center;
    width: 72px; padding: 8px 4px 6px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px; cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.msg-attachment-card:hover {
    background: var(--mud-palette-action-hover);
    border-color: var(--mud-palette-primary);
}
.msg-attach-icon-wrap {
    position: relative; display: inline-flex;
    align-items: center; justify-content: center;
    width: 36px; height: 36px;
}
.msg-attach-name {
    font-size: 0.65rem; text-align: center; line-height: 1.2;
    color: var(--mud-palette-text-primary);
    max-width: 68px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    margin-top: 4px;
}
/* ── Payroll weekly timesheet grid ─────────────────────────────────────────── */
.pr-timesheet {
    width: 100%; border-collapse: collapse; font-size: 0.8rem;
}
.pr-timesheet th, .pr-timesheet td {
    padding: 4px 8px; border-bottom: 1px solid var(--mud-palette-lines-default);
    vertical-align: middle;
}
.pr-timesheet thead th {
    font-size: 0.6rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--mud-palette-text-secondary);
    text-align: left; white-space: nowrap;
}
.pr-timesheet th.pr-day { text-align: center; min-width: 56px; }
.pr-timesheet th.pr-day .pr-day-num { font-size: 0.85rem; font-weight: 600; }
.pr-timesheet th.pr-today { color: var(--mud-palette-primary); }
.pr-day-cell { text-align: center; padding: 2px 4px; }
.pr-hours-input {
    width: 52px; text-align: center; border: 1px solid transparent;
    background: var(--mud-palette-background-grey); border-radius: 4px;
    padding: 4px 2px; font-size: 0.8rem; color: var(--mud-palette-text-primary);
}
.pr-hours-input:hover  { border-color: var(--mud-palette-lines-default); }
.pr-hours-input:focus  { border-color: var(--mud-palette-primary); outline: none; background: var(--mud-palette-surface); }
.pr-timesheet tfoot .pr-foot td { border-top: 2px solid var(--mud-palette-lines-default); border-bottom: none; }

/* ── Payroll run → paycheck detail lines ───────────────────────────────────── */
.pr-paycheck-lines {
    width: 100%; border-collapse: collapse; font-size: 0.75rem; margin-top: 4px;
}
.pr-paycheck-lines th {
    font-size: 0.58rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--mud-palette-text-secondary);
    text-align: left; padding: 2px 8px; border-bottom: 1px solid var(--mud-palette-lines-default);
}
.pr-paycheck-lines td {
    padding: 3px 8px; border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* ── Payroll Run Panel (full-screen dialog: by-employee + table report) ─────── */
.pr-run-panel { 
    display: flex; 
    flex-direction: column; 
    gap: 10px; height: 100%; 
    padding: 12px;
}

.pr-run-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 8px;
}
.pr-sum-item { 
    display: flex; 
    flex-direction: column; 
    line-height: 1.25; 
    border: 1px solid var(--mud-palette-primary);
    padding: 6px;
    min-width:130px !important;
    border-radius: var(--mud-default-borderradius);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}
.pr-sum-label {
    font-size: 0.56rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--mud-palette-text-secondary);
    padding: 3px;
    color: var(--mud-palette-primary);
}
.pr-sum-value { 
    font-size: 0.95rem; 
    font-weight: 600; 
    padding: 3px;
}

.pr-print-head { margin-bottom: 10px; }
.pr-print-head .pr-print-title { font-weight: 700; font-size: 1rem; }
.pr-print-head .pr-print-sub { font-size: 0.78rem; color: var(--mud-palette-text-secondary); }

/* Master–detail */
.pr-md { display: flex; gap: 16px; align-items: flex-start; }
/* Employee list card: fixed-width column; its body is a fixed viewport height that
   scrolls (a self-contained scroll element is reliable inside MudTabs; a flex-stretch
   chain is not). */
.pr-emp-card { flex: 0 0 320px; }
.pr-emp-list-body { height: 65vh; overflow-y: auto; padding: 0 !important; }
.pr-md-detail { flex: 1 1 auto; min-width: 0; max-height: 69vh; overflow-y: auto; }

/* Table Report tab: scroll the report (a lot of rows) with a sticky column header.
   Scoped to the scroll wrapper so detail-tab tables and the print window are unaffected. */
.pr-report-scroll { max-height: 69vh; overflow: auto; }
.pr-report-scroll .pr-report-table thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--mud-palette-surface);
}
.pr-emp-row {
    display: flex; justify-content: space-between; align-items: center; gap: 8px;
    padding: 8px 12px; cursor: pointer;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-left: 3px solid transparent;
}
.pr-emp-row:hover { background: var(--mud-palette-action-default-hover); }
.pr-emp-row.pr-emp--selected { background: var(--mud-palette-primary-hover); border-left-color: var(--mud-palette-primary); }
.pr-emp-name { font-weight: 600; font-size: 0.82rem; }
.pr-emp-proj { font-size: 0.7rem; color: var(--mud-palette-text-secondary); }
.pr-emp-paid { font-weight: 700; font-size: 0.82rem; white-space: nowrap; }

.pr-detail-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.pr-detail-grid {
    display: grid;
    /* Auto-fit as many tiles as fit at >=130px each; columns reduce as the screen
       shrinks (iPad/phone) and the tiles never squish below the min. */
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 8px;
    margin: 6px 0 14px;
}
.pr-block-title {
    font-size: 0.6rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--mud-palette-primary); margin: 12px 0 4px;
}

/* Withholdings + employer-tax cards: two-up on wide screens, stacked when narrow.
   align-items:start so a collapsed card doesn't stretch to its neighbour's height. */
.pr-tax-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
    gap: 12px;
    align-items: start;
}

/* Generic report table (table report tab + earnings/tax sub-tables) */
.pr-report-table { width: 100%; border-collapse: collapse; font-size: 0.72rem; }
.pr-report-table th {
    font-size: 0.55rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--mud-palette-primary); text-align: left; padding: 4px 6px;
    border-bottom: 2px solid var(--mud-palette-primary); white-space: nowrap;
}
.pr-report-table td { padding: 3px 6px; border-bottom: 1px solid var(--mud-palette-lines-default); vertical-align: top; }
.pr-report-table .pr-num { text-align: right; white-space: nowrap; }
.pr-report-grouphdr td {
    background: var(--mud-palette-background-grey); font-weight: 600;
    border-top: 2px solid var(--mud-palette-lines-default);
}
.pr-report-taxrow td { color: var(--mud-palette-text-secondary); font-size: 0.68rem; }
.pr-tax-chip { display: inline-block; margin: 0 14px 2px 0; white-space: nowrap; }
.pr-tax-chip .pr-tax-amt { font-weight: 600; }

/* Expandable earnings line → per-day time-entry detail */
.pr-earn-row:hover { background: var(--mud-palette-action-default-hover); }
.pr-earn-detail > td { padding: 0 0 8px 26px; background: var(--mud-palette-background-grey); }

/* Fixed layout + colgroup widths so every project's day-detail table has identical,
   aligned columns (auto layout sized each one differently). */
.pr-subtable { table-layout: fixed; width: 100%; margin: 2px 0 4px; }
.pr-subtable th { font-size: 0.5rem; }
.pr-subtable td { font-size: 0.68rem; overflow: hidden; text-overflow: ellipsis; }
.pr-subtable tbody tr:nth-child(even) td {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, transparent);
}

/* Withholdings / employer-tax tables: fixed columns so both align with each other. */
.pr-taxtable { table-layout: fixed; width: 100%; max-width: 540px; }
.pr-taxtable td { overflow: hidden; text-overflow: ellipsis; }

/* Print: clean borders/colors, keep logical rows together */
@media print {
    .pr-run-summary { background: #f2f2f2 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .pr-report-table th { color: #000; border-bottom: 2px solid #000; }
    .pr-report-table td { border-bottom: 1px solid #999; }
    .pr-report-grouphdr td {
        background: #ededed !important; -webkit-print-color-adjust: exact; print-color-adjust: exact;
        border-top: 2px solid #000;
    }
    .pr-report-table tr, .pr-md-detail, .pr-block { page-break-inside: avoid; }
    .pr-earn-detail > td { background: #f7f7f7 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .pr-md-list, .pr-no-print { display: none !important; }
}

.msg-attach-type {
    font-size: 0.58rem !important; margin-top: 1px;
}

/* ── Check designer ──────────────────────────────────────────────────────────── */
/* App-shell with a fixed height so the panels scroll their own bodies (no page scroll).
   Height uses the SAME formula the dashboard page proved works: viewport minus the app bar
   minus 2.5rem for the MudContainer chrome (mt-1 + pa-4 top/bottom). No negative top/bottom
   margins — those only shifted the box visually without shrinking the document height, which
   left that chrome on top and overflowed the viewport. Side −6px keeps a 10px L/R gutter
   (cancels all but ~10px of the container's 16px side padding; horizontal-only, no overflow). */
/* position:relative so the off-screen #ck-print-sheet (an absolutely-positioned, ~11in-tall
   print page) is contained + clipped by overflow:hidden — otherwise it escapes the shell and
   adds ~1056px to the document height, which was the persistent vertical scrollbar. */
.ck-designer { position: relative; display: flex; flex-direction: column; gap: 8px; height: calc(100vh - var(--mud-appbar-height, 64px) - 2.5rem + 20px); overflow: hidden; margin: 0 -6px; }
.ck-body { display: flex; flex-direction: column; gap: 8px; flex: 1; min-height: 0; }
.ck-row { display: flex; gap: 8px; min-height: 0; }
/* 2:1 split, but shift 55px of height from the top row to the bottom row.
   (basis sums to body height − 8px gap, so −59/+51 = ∓55px transfer ∓ 4px gap each.) */
.ck-row-top    { flex: 0 1 calc(66.66% - 59px); }   /* designer/canvas — the taller row */
.ck-row-bottom { flex: 0 1 calc(33.34% + 51px); }   /* Add Field / Add Element / Data Field */
.ck-card       { min-height: 0; min-width: 0; }                /* let cards shrink so bodies can scroll */
.ck-card--tpl  { flex: 0 0 380px; }                            /* Template column width */
.ck-card--grow { flex: 1 1 0; }
.ck-card--30   { flex: 3 1 0; }   /* bottom row: ~30% */
.ck-card--40   { flex: 4 1 0; }   /* bottom row: ~40% (Data Field) */
.ck-card-body  { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* Editor card body: a flex ROW — vertical band tabs on the left, scrollable canvas on the
   right. The body itself doesn't scroll; only .ck-editor-main does. (!important padding to
   beat TritiumCardPanel's scoped .tcp-body 16px.) */
.ck-editor-body { padding: 8px !important; display: flex; gap: 8px; overflow: hidden !important; }
.ck-editor-main { flex: 1 1 auto; min-width: 0; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
.ck-palette { display: flex; flex-wrap: wrap; gap: 4px; }
.ck-chip {
    border: 1px solid var(--mud-palette-lines-default); background: var(--mud-palette-background-grey);
    border-radius: 12px; padding: 3px 10px; font-size: 0.72rem; cursor: pointer; color: var(--mud-palette-text-primary);
}
.ck-chip:hover { background: var(--mud-palette-primary); color: #fff; border-color: var(--mud-palette-primary); }

/* Vertical band tabs, stacked on the left of the canvas. */
.ck-region-tabs { display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; }
.ck-region-tab {
    border: 1px solid var(--mud-palette-lines-default);
    border-right: 3px solid transparent;   /* reserve the active accent so there's no shift */
    background: var(--mud-palette-background-grey); color: var(--mud-palette-text-secondary);
    border-radius: 6px 0 0 6px; padding: 8px 12px; font-size: 0.78rem; cursor: pointer;
    text-align: left; white-space: nowrap;
}
.ck-region-tab--active {
    background: var(--mud-palette-surface); color: var(--mud-palette-primary);
    font-weight: 600; border-right-color: var(--mud-palette-primary);
}
.ck-canvas {
    position: relative; background: var(--mud-palette-surface); box-shadow: 0 2px 10px rgba(0,0,0,0.18);
    border: 1px solid #d0d0d0; flex-shrink: 0; touch-action: none;
}
.ck-canvas.ck-grid {
    background-image:
        linear-gradient(to right, var(--mud-palette-tertiary) 1px, transparent 1px),
        linear-gradient(to bottom, var(--mud-palette-tertiary) 1px, transparent 1px);
    background-size: 24px 24px;  /* 0.25in at 96px/in */
}
.ck-reference { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: fill; opacity: 0.28; pointer-events: none; }

.ckf {
    position: absolute; cursor: move; line-height: 1.05; white-space: nowrap;
    border: 2px dashed transparent; box-sizing: border-box; user-select: none;
    display: flex; align-items: center;
    color:var(--mud-palette-text-primary);
}
.ckf:hover { border-color: rgba(25, 118, 210, 0.719); background: rgba(25,118,210,0.04); }
.ckf--selected { border: 1px solid var(--mud-palette-primary) !important; background: rgba(25,118,210,0.08); overflow: visible !important; }
.ckf--dragging { opacity: 0.85; }
/* Corner handles — sit just OUTSIDE the field edges (overflow:visible on selection). */
.ckf-handle { position: absolute; z-index: 5; pointer-events: auto; }
.ckf-handle-del {
    top: -9px; right: -9px; width: 16px; height: 16px; border-radius: 50%;
    background: var(--mud-palette-error); color: #fff; font-size: 12px; line-height: 14px;
    text-align: center; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.4); font-weight: 700;
}
.ckf-handle-resize {
    bottom: -7px; right: -7px; width: 12px; height: 12px;
    background: var(--mud-palette-primary); border: 1px solid #fff; border-radius: 2px;
    cursor: nwse-resize; box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.ckf-placeholder { font-size: 0.7em; color: #999; border: 1px dashed #bbb; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.ckf-sigline { border-top: 1px solid #000; width: 100%; align-self: flex-end; margin-bottom: 2px; }
.ckf-box { border: 1px solid #000; width: 100%; height: 100%; }

/* ── Web report section design canvas (clone of the check designer) ──────────── */
.rc-stage { 
    overflow: auto; 
    height: calc(100vh - 318px); 
    padding: 8px; 
    /* background: var(--mud-palette-background-grey); border-radius: 6px;  */
    background: color-mix(in srgb, var(--mud-palette-primary) 15%, transparent);
}
.rc-canvas { position: relative; background: var(--mud-palette-surface); box-shadow: 0 2px 10px rgba(0,0,0,0.18); border: 1px solid #d0d0d0; flex-shrink: 0; touch-action: none; }
/* Drag bar under a canvas band to set its height */
.rc-vresizer {
    height: 8px;
    margin-top: 2px;
    cursor: row-resize;
    background: var(--mud-palette-lines-default);
    border-radius: 0 0 3px 3px;
    transition: background 0.15s;
    touch-action: none;
    flex-shrink: 0;
    position: relative;
}
.rc-vresizer::after {
    content: "";
    position: absolute;
    left: 50%; top: 50%;
    width: 28px; height: 2px;
    transform: translate(-50%, -50%);
    background: var(--mud-palette-surface);
    border-radius: 2px;
}
.rc-vresizer:hover,
.rc-vresizer:active { background: var(--mud-palette-primary); }
/* width drag bar — vertical bar on the right edge (mirrors .rc-vresizer) */
.rc-hresizer {
    position: absolute;
    top: 0; right: -10px;
    width: 8px;
    cursor: col-resize;
    background: var(--mud-palette-lines-default);
    border-radius: 0 3px 3px 0;
    transition: background 0.15s;
    touch-action: none;
}
.rc-hresizer::after {
    content: "";
    position: absolute;
    left: 50%; top: 50%;
    width: 2px; height: 28px;
    transform: translate(-50%, -50%);
    background: var(--mud-palette-surface);
    border-radius: 2px;
}
.rc-hresizer:hover,
.rc-hresizer:active { background: var(--mud-palette-primary); }
.rc-canvas.rc-grid {
    background-image:
        linear-gradient(to right, var(--mud-palette-tertiary) 1px, transparent 1px),
        linear-gradient(to bottom, var(--mud-palette-tertiary) 1px, transparent 1px);
    background-size: var(--rc-grid, 24px) var(--rc-grid, 24px);
}
.rcf { position: absolute; cursor: move; line-height: 1.05; white-space: nowrap; box-sizing: border-box; user-select: none; display: flex; align-items: center; color: var(--mud-palette-text-primary); overflow: hidden; }
/* selection/hover use outline (not border) so the user-defined border is free to render */
.rcf:hover { outline: 2px dashed rgba(25,118,210,0.719); outline-offset: -2px; background: rgba(25,118,210,0.04); }
.rcf--selected { outline: 2px solid var(--mud-palette-primary); outline-offset: -2px; background: rgba(25,118,210,0.08); overflow: visible !important; }
.rcf--dragging { opacity: 0.85; }
.rcf-handle { position: absolute; z-index: 5; pointer-events: auto; }
.rcf-handle-del { top: -9px; right: -9px; width: 16px; height: 16px; border-radius: 50%; background: var(--mud-palette-error); color: #fff; font-size: 12px; line-height: 14px; text-align: center; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.4); font-weight: 700; }
/* Resize handles — positioned fully OUTSIDE the element so they never overlap a thin element body.
   Edges (w/e move x-extent, n/s move y-extent), plus the se corner (both). w/n move the origin. */
.rcf-rz { background: var(--mud-palette-primary); border: 1px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.4); border-radius: 3px; }
.rcf-rz-e  { top: 50%;  right: -12px;  transform: translateY(-50%); width: 9px;  height: 18px; cursor: ew-resize; }
.rcf-rz-w  { top: 50%;  left: -12px;   transform: translateY(-50%); width: 9px;  height: 18px; cursor: ew-resize; }
.rcf-rz-n  { left: 50%; top: -12px;    transform: translateX(-50%); width: 18px; height: 9px;  cursor: ns-resize; }
.rcf-rz-s  { left: 50%; bottom: -12px; transform: translateX(-50%); width: 18px; height: 9px;  cursor: ns-resize; }
.rcf-rz-se { right: -12px; bottom: -12px; width: 11px; height: 11px; border-radius: 2px; cursor: nwse-resize; }
/* grouped elements: a subtle inner ring (box-shadow stacks with the selection outline) */
.rcf--grouped { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mud-palette-secondary) 65%, transparent); }
/* locked elements (e.g. a signature the user can't edit): selectable but not draggable/resizable */
.rcf--locked { cursor: default; }
.rcf--locked:hover { outline: 2px dotted color-mix(in srgb, var(--mud-palette-warning) 70%, transparent); background: transparent; }
/* marquee rubber-band selection box */
.rc-marquee { position: absolute; z-index: 10; border: 1px dashed var(--mud-palette-primary); background: rgba(25,118,210,0.10); pointer-events: none; }
/* Smart alignment guides shown while dragging an element (snap to other elements' edges/centres). */
.rc-guide   { position: absolute; z-index: 40; pointer-events: none; background: #E5397E; display: none; }
.rc-guide-v { top: 0; bottom: 0; width: 1px; }
.rc-guide-h { left: 0; right: 0; height: 1px; }

/* Report element/property toolbar: let it wrap and grow taller instead of hiding controls off the
   right edge (behind the properties panel) when the designer is narrow. The MudSpacer keeps the
   property strip right-aligned on one line while there's room; only overflow wraps to new lines. */
.tt-toolbar-wrap.mud-toolbar,
.tt-toolbar-wrap .mud-toolbar-content {
    flex-wrap: wrap;
    height: auto;
}
.tt-toolbar-wrap.mud-toolbar {
    min-height: 48px;
    row-gap: 4px;
    padding-top: 4px;
    padding-bottom: 4px;
}

/* Keyboard-shortcuts cheat sheet (popover content). */
.rc-kbd-help { min-width: 250px; max-width: 300px; padding: 10px 12px 12px; }
.rc-kbd-title { font-weight: 700; font-size: 0.82rem; margin-bottom: 6px; }
.rc-kbd-grouptitle { font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--mud-palette-primary); margin: 8px 0 2px; }
.rc-kbd-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 2px 0; }
.rc-kbd-label { font-size: 0.75rem; color: var(--mud-palette-text-primary); }
.rc-kbd-keys { display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; }
.rc-kbd-or { color: var(--mud-palette-text-secondary); font-size: 0.7rem; margin: 0 1px; }
.rc-kbd {
    font-family: inherit;
    font-size: 0.64rem;
    line-height: 1.5;
    padding: 1px 5px;
    border: 1px solid var(--mud-palette-lines-default);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--mud-palette-surface) 70%, var(--mud-palette-action-default-hover));
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
}
/* child elements of an expanded TemplateRef (read-only preview, positioned within the ref box) */
.rcf-tchild { position: absolute; box-sizing: border-box; display: flex; align-items: center; white-space: nowrap; overflow: hidden; pointer-events: none; line-height: 1.05; }
.rcf-box { border: 1px solid var(--mud-palette-text-primary); width: 100%; height: 100%; }
.rcf-ph { opacity: 0.45; font-style: italic; }
.rc-ruler-h { position: relative; height: 16px; margin-left: 24px; }
.rc-ruler-v { position: relative; width: 24px; flex-shrink: 0; }
.rc-tick { position: absolute; font-size: 9px; color: var(--mud-palette-text-secondary); }
.rc-tick-h { bottom: 0; border-left: 1px solid var(--mud-palette-lines-default); padding-left: 2px; height: 7px; }
.rc-tick-v { right: 0; border-top: 1px solid var(--mud-palette-lines-default); padding-right: 2px; width: 12px; text-align: right; height: 1px; }
.rc-chip { border: 1px solid var(--mud-palette-lines-default); background: var(--mud-palette-surface); color: var(--mud-palette-text-primary); border-radius: 14px; padding: 2px 10px; font-size: 0.75rem; cursor: pointer; }
.rc-chip:hover { border-color: var(--mud-palette-primary); background: rgba(25,118,210,0.06); }

.tt-shaded-header {
    background: color-mix(in srgb, var(--mud-palette-primary) 15%, transparent);
}
.tt-shaded-body {
    background: color-mix(in srgb, var(--mud-palette-primary) 7%, transparent);
}

/* ── Uniform filter-bar field heights ───────────────────────────────────────
   A filter bar mixes MudTextField, MudDateRangePicker, TritiumDialogSelect and the
   Tritium pickers — all different intrinsic heights. Add `tt-filter-bar` on the
   filter container to: (1) give every field the same base height, and (2) collapse
   the contact/employee picker's rich multi-line card to a single line (it stays
   full-detail elsewhere, e.g. in dialogs). */
/* Every field (text, date-range, dialog-select, pickers) renders a
   `.mud-input.mud-input-outlined` box that, by default, sizes to its content + slot
   padding — so each ends up a different height. Give them a common MINIMUM height
   (so single-line fields line up), zero the slot's vertical padding and vertically
   centre the content. Must be `min-height`, not a fixed `height` — a multi-select
   Chips field has to GROW as its chips wrap to extra rows; a fixed height clips
   them and they overflow over the neighbouring controls. */
.tt-filter-bar .mud-input.mud-input-outlined {
    min-height: 44px !important;
    align-items: center !important;
}
.tt-filter-bar .mud-input.mud-input-outlined .mud-input-slot {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}

/* Contact / Employee picker → single compact line in the SELECTED display only
   (dropdown tiles keep their full detail). !important is required: these classes come
   from the component's *scoped* stylesheet (loaded after app.css) with equal specificity. */
.tt-filter-bar .tcpk-field-content .tcpk-meta,
.tt-filter-bar .tcpk-field-content .tcpk-address,
.tt-filter-bar .tep-field-content  .tep-meta,
.tt-filter-bar .tep-field-content  .tep-address { display: none !important; }

.tt-filter-bar .tcpk-field-content .tcpk-avatar,
.tt-filter-bar .tep-field-content  .tep-avatar {
    width: 24px !important; height: 24px !important; font-size: 0.58rem !important;
}

/* Master-search field sits in the always-dark top toolbar: force light text / icon / border
   and a 10px radius. Scoped to the toolbar wrapper so the decoupled TritiumGlobalSearch stays
   theme-agnostic. */
.tt-search-field .mud-input.mud-input-outlined,
.tt-search-field .mud-input.mud-input-outlined .mud-input-outlined-border {
    border-radius: 18px !important;
}
/* Shorter field: trim the dense outlined height and vertically centre the content. */
.tt-search-field .mud-input.mud-input-outlined {
    min-height: 32px !important;
    align-items: center !important;
}
.tt-search-field .mud-input.mud-input-outlined .mud-input-slot {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    font-size: 0.85rem;
}
.tt-search-field .mud-input.mud-input-outlined .mud-input-outlined-border {
    border-color: rgba(255, 255, 255, 0.5) !important;
}
.tt-search-field .mud-input.mud-input-outlined:hover .mud-input-outlined-border {
    border-color: rgba(255, 255, 255, 0.7) !important;
}
.tt-search-field .mud-input.mud-input-outlined:focus-within .mud-input-outlined-border {
    border-color: rgba(255, 255, 255, 0.9) !important;
}
.tt-search-field .mud-input-slot,
.tt-search-field .mud-input-root {
    color: #fff !important;
    caret-color: #fff !important;
}
.tt-search-field .mud-input-slot::placeholder {
    color: rgba(255, 255, 255, 0.6) !important;
    opacity: 1;
}
.tt-search-field .mud-icon-root {
    color: rgba(255, 255, 255, 0.85) !important;
}

/* Navigate launcher button — same always-dark toolbar treatment as the search field:
   light outline + light text/icon, pill radius. Scoped to the toolbar wrapper. */
.tt-navigate-btn .mud-button-root {
    border-radius: 18px !important;
    min-height: 32px !important;
    text-transform: none;
    color: #fff !important;
    border-color: rgba(255, 255, 255, 0.5) !important;
}
.tt-navigate-btn .mud-button-root:hover {
    border-color: rgba(255, 255, 255, 0.85) !important;
    background-color: rgba(255, 255, 255, 0.08) !important;
}
.tt-navigate-btn .mud-button-root .mud-icon-root {
    color: rgba(255, 255, 255, 0.9) !important;
}

.tt-rpt-output-wrapper {
    flex:1; 
    overflow:auto;
    background: color-mix(in srgb, var(--mud-palette-primary) 17%, silver);
    padding: 40px;
}
.tt-rpt-output{
    background:#fff;
    color:#000;
    margin:0 auto;
    width:max-content;
    box-shadow:0 2px 20px rgba(0,0,0,.5);

}

/* Page-view simulation: the output becomes a transparent column of paper "sheets" over a
   darker backdrop, with a generous gap between pages — like a desktop PDF viewer. */
.tt-rpt-output.tt-rpt-paged{
    background:transparent;
    box-shadow:none;
    width:auto;
}
.tt-rpt-output-wrapper.tt-rpt-paged-bg{
    background: color-mix(in srgb, var(--mud-palette-primary) 20%, gray);
}
.tt-rpt-sheet{
    background:#fff;
    color:#000;
    margin:0 auto 40px;
    box-shadow:0 2px 20px rgba(0,0,0,.5);
    overflow:hidden;
    position:relative;
}
.tt-rpt-sheet:last-child{ margin-bottom:0; }

/* Page-thumbnail rail (PDF-viewer style) on the right of the generator output. Each .tt-thumb is a
   CSS-scaled clone of a live sheet (see reports.js → window.reportThumbs). */
.tt-rpt-rail{
    width:182px; min-width:182px;
    overflow-y:auto; overflow-x:hidden;
    background: color-mix(in srgb, var(--mud-palette-primary) 22%, #555);
    border-left:1px solid rgba(0,0,0,.28);
    padding:14px 0;
    display:flex; flex-direction:column; align-items:center;
}
.tt-thumb{
    position:relative;
    margin:0 auto 14px;
    background:#fff;
    box-shadow:0 1px 6px rgba(0,0,0,.5);
    outline:2px solid transparent;
    outline-offset:-2px;
    overflow:hidden;
    cursor:pointer;
    flex:0 0 auto;
}
.tt-thumb:hover{ outline-color: color-mix(in srgb, var(--mud-palette-primary) 60%, white); }
.tt-thumb-active{ outline-color: var(--mud-palette-primary); }
.tt-thumb-inner{ transform-origin:top left; pointer-events:none; }
/* Lazy placeholder shown until the page is cloned in (a faint empty-page frame). */
.tt-thumb-ph::after{
    content:""; position:absolute; inset:8px;
    border:1px dashed rgba(0,0,0,.14); border-radius:2px;
}
.tt-thumb-num{
    position:absolute; bottom:2px; right:4px;
    font-size:10px; line-height:1; color:#fff;
    background:rgba(0,0,0,.55); border-radius:3px; padding:1px 4px;
    pointer-events:none;
}

/* The page-view simulation is on-screen only — strip the sheet chrome when printing so the
   real page breaks (page-break-before) drive pagination, not the simulated paper boxes. */
@media print {
    .tt-rpt-sheet { box-shadow:none; margin:0; min-height:0; }
    .tt-rpt-output.tt-rpt-paged { background:#fff; }
    .tt-rpt-rail { display:none; }
}

.tt-title {
    font-size: 0.84rem;
    font-weight: 600;
}

/* ── CAD designer (Drafting module) ──────────────────────────────────────────
   Global (not scoped) because entity SVG elements are emitted via RenderTreeBuilder
   and therefore don't carry the component's CSS-isolation attribute. */
.cad-root { display:flex; flex-direction:column; height:100%; min-height:0; outline:none; position:relative; }
.cad-modify-pop {
    position:absolute; top:46px; left:8px; z-index:30; width:280px;
    background:var(--mud-palette-surface); border:1px solid var(--mud-palette-lines-default);
    border-radius:8px; box-shadow:0 6px 22px rgba(0,0,0,0.18); padding:12px;
}
.cad-modify-title { font-size:0.8rem; font-weight:700; text-transform:uppercase; letter-spacing:0.4px;
    color:var(--mud-palette-text-secondary); margin-bottom:10px; }
.cad-toolbar {
    display:flex; align-items:center; gap:2px; padding:4px 8px;
    border-bottom:1px solid var(--mud-palette-lines-default);
    background:var(--mud-palette-surface); flex:0 0 auto;
    position:relative;   /* anchor for the host-triggered Drawing-settings popover (top-right) */
}
.cad-hint { margin-left:10px; color:var(--mud-palette-text-secondary); }
/* same height + style as the main toolbar (its tallest child sets the height) */
.cad-subbar {
    display:flex; align-items:center; gap:2px; padding:4px 8px; overflow-x:auto;
    border-bottom:1px solid var(--mud-palette-lines-default);
    background:var(--mud-palette-surface); flex:0 0 auto;
}
.cad-subbar-icon { color:var(--mud-palette-text-secondary); flex:0 0 auto; }
.cad-subbar-label {
    font-size:0.76rem; font-weight:600; color:var(--mud-palette-text-secondary);
    margin:0 8px 0 4px; white-space:nowrap; flex:0 0 auto;
}
.cad-subbar-sep { width:1px; height:22px; background:var(--mud-palette-lines-default); margin:0 6px; flex:0 0 auto; }

/* Native, toolbar-height controls (no MudBlazor field chrome → guaranteed compact row). */
.cad-native-select, .cad-native-input {
    height:28px; font-size:0.82rem; color:var(--mud-palette-text-primary);
    background:var(--mud-palette-surface); border:1px solid var(--mud-palette-lines-default);
    border-radius:4px; flex:0 0 auto; box-sizing:border-box;
}
.cad-native-select { max-width:170px; padding:2px 6px; cursor:pointer; }
.cad-native-input { width:92px; padding:2px 6px; }
.cad-native-select:hover, .cad-native-input:hover { border-color:var(--mud-palette-primary); }

/* Swatch / sample buttons that open a popover (color + line weight). */
.cad-pen-btn {
    display:inline-flex; align-items:center; gap:5px; height:28px; padding:2px 6px;
    background:var(--mud-palette-surface); border:1px solid var(--mud-palette-lines-default);
    border-radius:4px; cursor:pointer; flex:0 0 auto;
}
.cad-pen-btn:hover { border-color:var(--mud-palette-primary); }
.cad-pen-btn:disabled { opacity:.38; cursor:default; }
.cad-pen-btn:disabled:hover { border-color:var(--mud-palette-lines-default); }
.cad-pen-swatch { width:18px; height:14px; border-radius:2px; border:1px solid var(--mud-palette-lines-default); flex:0 0 auto; }
.cad-pen-caret { width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent; border-top:5px solid var(--mud-palette-text-secondary); flex:0 0 auto; }

/* Line-weight picker: sample line on the button face + the preset rows in the popover. */
.cad-lw-btn { min-width:74px; }
.cad-lw-sample { display:inline-block; width:26px; background:var(--mud-palette-text-primary); border-radius:1px; flex:0 0 auto; }
.cad-lw-sample.wide { width:auto; flex:1 1 auto; min-width:18px; }
.cad-lw-val { font-size:0.78rem; color:var(--mud-palette-text-primary); min-width:30px; text-align:left; }
.cad-lw-unit { font-size:0.62rem; color:var(--mud-palette-text-secondary); margin-left:2px; }
.cad-frame-row { padding:3px 2px; border-radius:4px; cursor:pointer; }
.cad-frame-row:hover { background:var(--mud-palette-action-default-hover); }
.cad-frame-row.sel { background:var(--mud-palette-primary-hover); }
.cad-frame-detail { padding:2px 2px 4px 6px; }
.cad-frame-layers { display:flex; flex-direction:column; max-height:150px; overflow-y:auto; }
.cad-lw-list { display:grid; grid-template-columns:repeat(3, 1fr); gap:2px; }
.cad-lw-row {
    display:flex; align-items:center; gap:6px; width:100%; padding:5px 6px; min-width:0;
    background:transparent; border:none; border-radius:4px; cursor:pointer; text-align:left;
}
.cad-lw-row:hover { background:var(--mud-palette-action-default-hover); }
.cad-lw-row.sel { background:var(--mud-palette-primary-hover); }
.cad-lw-rowval { font-size:0.74rem; color:var(--mud-palette-text-secondary); margin-left:auto; }
.cad-lw-manual-label { font-size:0.78rem; color:var(--mud-palette-text-secondary); white-space:nowrap; }
.cad-body { display:flex; flex:1 1 auto; min-height:0; }
.cad-cmdline {
    display:flex; align-items:center; gap:10px; padding:3px 10px; flex:0 0 auto;
    border-top:1px solid var(--mud-palette-lines-default); background:var(--mud-palette-surface);
    font-family:Consolas, "Courier New", monospace; font-size:0.82rem;
}
.cad-cmd-prompt { color:var(--mud-palette-text-secondary); white-space:nowrap; flex:0 0 auto; }
.cad-cmd-input {
    flex:1 1 auto; min-width:0; border:none; outline:none; background:transparent;
    color:var(--mud-palette-text-primary); font-family:inherit; font-size:inherit; padding:2px 0;
}
.cad-cmd-log { color:var(--mud-palette-text-secondary); white-space:nowrap; flex:0 0 auto; opacity:0.85; }

/* Thin status bar pinned to the bottom — holds the contextual tool hint (moved out of the toolbar) */
.cad-statusbar {
    display:flex; align-items:center; gap:6px; flex:0 0 auto;
    height:22px; padding:0 10px;
    border-top:1px solid var(--mud-palette-lines-default); background:var(--mud-palette-surface);
    font-size:0.72rem; line-height:1; user-select:none;
    color:var(--mud-palette-text-secondary); overflow:hidden; white-space:nowrap;
}
.cad-statusbar .cad-status-ico { font-size:0.95rem !important; color:var(--mud-palette-primary); flex:0 0 auto; }
.cad-status-hint { color:var(--mud-palette-text-primary); overflow:hidden; text-overflow:ellipsis; }
.cad-status-tool { opacity:0.6; text-transform:uppercase; letter-spacing:0.4px; font-size:0.66rem; }
/* 3-zone layout: left hint + center mode chips + right cluster. Equal-grow sides keep the center group centered. */
.cad-status-left   { flex:1 1 0; min-width:0; display:flex; align-items:center; gap:6px; overflow:hidden; }
.cad-status-center { flex:0 0 auto; display:flex; align-items:center; gap:6px; }
/* Right cluster: live cursor coordinates + Snap/Grid/Ortho toggle chips */
.cad-status-right { flex:1 1 0; min-width:0; display:flex; align-items:center; justify-content:flex-end; gap:6px; }
.cad-status-coord { display:flex; align-items:center; gap:8px; font-variant-numeric:tabular-nums; color:var(--mud-palette-text-secondary); }
.cad-status-xy { min-width:78px; }
.cad-status-sep { width:1px; height:13px; background:var(--mud-palette-lines-default); margin:0 2px; }
.cad-status-chip {
    border:none; background:transparent; cursor:pointer; padding:1px 6px; border-radius:4px;
    font:inherit; font-size:0.64rem; font-weight:700; letter-spacing:0.5px; text-transform:uppercase;
    color:var(--mud-palette-text-disabled); line-height:1.6;
}
.cad-status-chip:hover { background:var(--mud-palette-action-default-hover); }
.cad-status-chip.on { color:var(--mud-palette-primary-text); background:var(--mud-palette-primary); }
.cad-ctx-backdrop { position:fixed; inset:0; z-index:4100; }
.cad-ctxmenu {
    position:fixed; z-index:4101; min-width:194px; padding:4px;
    background:var(--mud-palette-surface); border:1px solid var(--mud-palette-lines-default);
    border-radius:8px; box-shadow:0 8px 26px rgba(0,0,0,0.22);
}
.cad-ctx-item {
    display:flex; align-items:center; gap:8px; padding:6px 10px; border-radius:6px; cursor:pointer;
    font-size:0.85rem; color:var(--mud-palette-text-primary); white-space:nowrap; user-select:none;
}
.cad-ctx-item:hover { background:var(--mud-palette-action-default-hover); }
.cad-ctx-item.cad-ctx-danger { color:var(--mud-palette-error); }
.cad-ctx-sep { height:1px; margin:4px 6px; background:var(--mud-palette-lines-default); }
.cad-schedule { width:100%; border-collapse:collapse; font-size:0.82rem; color:var(--mud-palette-text-primary); }
.cad-schedule th, .cad-schedule td { padding:3px 6px; border-bottom:1px solid var(--mud-palette-lines-default); text-align:left; }
.cad-schedule th { color:var(--mud-palette-text-secondary); font-weight:600; }
.cad-schedule .num { text-align:right; width:48px; }
.cad-schedule tfoot td { font-weight:700; border-top:2px solid var(--mud-palette-lines-default); border-bottom:none; }
/* Drag-drop re-filing of sheets between drawing sets (Project Drawings tab). */
.cad-dropzone { min-height:40px; border:1px dashed var(--mud-palette-lines-default); border-radius:6px; padding:4px; transition:background-color .15s ease, border-color .15s ease; }
.cad-dropzone.mud-drop-zone-drag-block { border-color:var(--mud-palette-primary); background-color:rgba(var(--mud-palette-primary-rgb), 0.08); }
/* The insertion placeholder MudBlazor renders while dragging (AllowReorder) — dashed line showing the drop spot. */
.cad-dropzone .mud-drop-item-placeholder { border:2px dashed var(--mud-palette-primary); border-radius:6px; background-color:rgba(var(--mud-palette-primary-rgb), 0.06); min-height:34px; opacity:.85; }
/* Sheet rows hosted in MudListItem inside the drop zone — trim the default list padding. */
.cad-sheet-item { padding:2px 4px !important; }
.cad-sheet-item .mud-list-item-text { margin:0; }
.cad-stage { flex:1 1 auto; min-width:0; min-height:0; display:grid; grid-template-columns:22px 1fr; grid-template-rows:22px 1fr; }
.cad-corner { background:var(--mud-palette-surface); border-right:1px solid var(--mud-palette-lines-default); border-bottom:1px solid var(--mud-palette-lines-default); display:flex; align-items:center; justify-content:center; font-size:0.58rem; font-weight:600; color:var(--mud-palette-text-secondary); text-transform:uppercase; }
.cad-ruler-top { background:var(--mud-palette-surface); border-bottom:1px solid var(--mud-palette-lines-default); overflow:hidden; }
.cad-ruler-left { background:var(--mud-palette-surface); border-right:1px solid var(--mud-palette-lines-default); overflow:hidden; }
.cad-ruler-top svg, .cad-ruler-left svg { display:block; width:100%; height:100%; }
.cad-canvas-wrap { position:relative; min-width:0; min-height:0; background:#525659; overflow:hidden; }
.cad-svg { width:100%; height:100%; display:block; touch-action:none; cursor:crosshair; user-select:none; -webkit-user-select:none; }
.cad-canvas-wrap.pan-armed .cad-svg { cursor:grab; }            /* hold-space: armed to pan */
.cad-canvas-wrap.pan-grabbing .cad-svg { cursor:grabbing; }     /* panning (incl. middle-drag / Pan tool) */
.cad-svg text, .cad-svg tspan { user-select:none; -webkit-user-select:none; }

/* Live measurement / inquiry readout (overlays the canvas top-left) */
.cad-measure-hud {
    position:absolute; top:10px; left:10px; z-index:5; pointer-events:none;
    min-width:170px; padding:8px 10px; border-radius:8px;
    background:rgba(28,32,38,0.88); color:#fff; box-shadow:0 4px 14px rgba(0,0,0,0.35);
    font-size:12px; line-height:1.5;
}
.cad-mh-title { display:flex; align-items:center; gap:6px; font-weight:600; margin-bottom:4px; color:#fdba74; }
.cad-mh-title .mud-icon-root { color:#fb8c00; }
.cad-mh-row { display:flex; justify-content:space-between; gap:14px; }
.cad-mh-row span { color:#cbd5e1; }
.cad-mh-row b { font-variant-numeric:tabular-nums; }
.cad-mh-hint { margin-top:5px; padding-top:4px; border-top:1px solid rgba(255,255,255,0.15); color:#94a3b8; font-size:11px; }

/* Selection info readout (top-right; blue accent to distinguish from the orange measure HUD) */
.cad-info-hud {
    position:absolute; top:10px; right:10px; z-index:5; pointer-events:none;
    min-width:150px; max-width:260px; padding:8px 10px; border-radius:8px;
    background:rgba(28,32,38,0.88); color:#fff; box-shadow:0 4px 14px rgba(0,0,0,0.35);
    font-size:12px; line-height:1.5;
}
.cad-info-hud .cad-mh-title { color:#93c5fd; }
.cad-info-hud .cad-mh-title .mud-icon-root { color:#60a5fa; }
.cad-info-hud .cad-mh-title span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Floating measuring rulers — dark draggable strips overlaid on the canvas, with a movable zero */
.cad-fr { position:absolute; z-index:6; background:rgba(17,24,39,0.92); cursor:grab; box-shadow:0 1px 4px rgba(0,0,0,0.3); }
.cad-fr:active { cursor:grabbing; }
.cad-fr svg { display:block; width:100%; height:100%; }
.cad-fr-h { top:4px; left:0; right:0; height:20px; }
.cad-fr-v { left:4px; top:0; bottom:0; width:20px; }
.cad-fr-catcher { position:fixed; inset:0; z-index:3001; cursor:grabbing; }

/* Native bordered numeric field (zoom %, grid size) — matches the sub-bar's native controls. */
.cad-native-field {
    display:inline-flex; align-items:center; height:28px; flex:0 0 auto; overflow:hidden;
    background:var(--mud-palette-surface); border:1px solid var(--mud-palette-lines-default); border-radius:4px;
}
.cad-native-field:hover, .cad-native-field:focus-within { border-color:var(--mud-palette-primary); }
.cad-native-num {
    border:none; background:transparent; outline:none; height:26px; width:48px;
    padding:2px 2px 2px 6px; font-size:0.82rem; text-align:right; color:var(--mud-palette-text-primary);
}
.cad-native-field .cad-native-suffix {
    font-size:0.74rem; color:var(--mud-palette-text-secondary); padding:0 6px 0 3px; white-space:nowrap; user-select:none;
}

/* Per-layer raster/PDF underlay controls (Layers panel) */
.cad-underlay-panel { padding:6px 8px 8px 30px; display:flex; flex-direction:column; gap:4px;
    border-left:2px solid var(--mud-palette-primary); margin:0 4px 6px 12px; background:rgba(127,127,127,0.06); border-radius:4px; }

/* Guide lines (CorelDraw-style, non-printing) */
.cad-guide { stroke:#06b6d4; stroke-dasharray:0.22 0.14; pointer-events:none; }
.cad-guide-hit { stroke:transparent; pointer-events:stroke; }
.cad-guide-hit.h { cursor:ns-resize; }
.cad-guide-hit.v { cursor:ew-resize; }
.cad-ruler-top.cad-ruler-drag { cursor:row-resize; }
.cad-ruler-left.cad-ruler-drag { cursor:col-resize; }
.cad-rail {
    background:var(--mud-palette-surface);
    color:var(--mud-palette-text-primary);   /* readable in dark mode (descendants inherit, e.g. switch labels) */
    padding: 5px;
    overflow:auto;
    max-height: calc(100vh - 180px);
}
/* width/flex come from an inline style (resizable). */
.cad-splitter { flex:0 0 6px; cursor:col-resize; background:var(--mud-palette-lines-default); }
.cad-splitter:hover { background:var(--mud-palette-primary); }
.cad-resize-overlay { position:fixed; inset:0; z-index:4000; cursor:col-resize; }
.cad-layer-drag { color:var(--mud-palette-text-secondary); cursor:grab; opacity:0.55; flex:0 0 auto; }
.cad-layer-name-edit { flex:1 1 auto; min-width:0; }
.cad-layer-color { flex:0 0 auto; margin:0 2px; }
.cad-layer-color .mud-input-control { margin-top:0; }
/* keep the inline layer color picker looking like a small swatch (drop the text-field underline) */
.cad-layer-color .mud-input.mud-input-underline::before,
.cad-layer-color .mud-input.mud-input-underline::after { border-bottom:none !important; }
/* compact toolbar canvas-background swatch (no underline) */
.cad-canvasbg-pick .mud-input-control { margin-top:0; }
.cad-canvasbg-pick .mud-input.mud-input-underline::before,
.cad-canvasbg-pick .mud-input.mud-input-underline::after { border-bottom:none !important; }
.cad-canvasbg-pick, .cad-canvasbg-pick * { cursor:pointer !important; }
.cad-layer-row.dragging { opacity:0.45; }
/* Expandable layer-elements list (2-column grid under the layer row) */
.cad-layer-ents { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:2px 6px; padding:4px 8px 6px 26px; max-height:240px; overflow:auto; border-bottom:1px solid var(--mud-palette-lines-default); }
.cad-layer-ent { display:flex; align-items:center; justify-content:space-between; gap:2px; min-width:0; padding:4px 4px 4px 6px; border-radius:4px; font-size:0.78rem; cursor:pointer; }
.cad-layer-ent:hover { background:var(--mud-palette-action-default-hover); }
.cad-layer-ent.sel { background:var(--mud-palette-primary-hover); }
.cad-layer-ent-name { display:flex; align-items:center; gap:3px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.cad-layer-ent-name.hid { opacity:0.45; }
.cad-layer-ent-ico { font-size:0.85rem !important; opacity:0.7; flex:0 0 auto; }
.cad-rail-section { border-bottom:1px solid var(--mud-palette-lines-default); padding:8px 10px; }
.cad-rail-section.cad-props { flex:1 1 auto; }
.cad-rail-head {
    display:flex; align-items:center; justify-content:space-between;
    font-size:0.78rem; font-weight:700; text-transform:uppercase; letter-spacing:0.4px;
    color:var(--mud-palette-text-secondary); margin-bottom:6px;
}
.cad-layers { display:flex; flex-direction:column; gap:2px; }
.cad-layer-row {
    display:flex; align-items:center; gap:2px; padding:1px 4px; border-radius:6px; cursor:pointer;
}
.cad-layer-row:hover { background:var(--mud-palette-action-default-hover); }
.cad-layer-row.active { background:color-mix(in srgb, var(--mud-palette-primary) 14%, transparent); }
.cad-layer-swatch { width:14px; height:14px; border-radius:3px; border:1px solid var(--mud-palette-lines-default); flex:0 0 auto; margin:0 4px; }
.cad-layer-name { flex:1 1 auto; font-size:0.85rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cad-layer-locked-ico { color:#f9a825; flex:0 0 auto; font-size:1rem !important; }   /* at-a-glance "layer is locked" (toggle moved to the ⋮ menu) */
.cad-prop-grid { display:flex; flex-direction:column; gap:10px; }
.cad-prop-fill { display:flex; align-items:flex-end; gap:6px; }
.cad-empty { color:var(--mud-palette-text-secondary); }
.cad-run-props { display:flex; flex-direction:column; gap:8px; padding:8px; margin-top:4px; border:1px solid var(--mud-palette-lines-default); border-radius:6px; }
.cad-run-readout { color:var(--mud-palette-text-secondary); font-variant-numeric:tabular-nums; }
.cad-run-lbl { font-weight:600; pointer-events:none; user-select:none; }
.cad-zone-lbl { font-weight:700; pointer-events:none; user-select:none; text-transform:uppercase; letter-spacing:0.03em; }
.cad-asm-row { padding:6px 8px; border-radius:6px; cursor:pointer; }
.cad-asm-row:hover { background:var(--mud-palette-action-default-hover); }
.cad-asm-sel { background:color-mix(in srgb, var(--mud-palette-primary) 14%, transparent); }
.cad-asm-comp { border:1px solid var(--mud-palette-lines-default); border-radius:6px; padding:8px; margin-bottom:8px; }

/* Entities: ignore the pointer except in Select mode (so draw/pan work over them). */
.cad-ent { pointer-events:none; }
.cad-ent.cad-selectable { pointer-events:all; cursor:move; }
.cad-selbox { stroke:var(--mud-palette-primary); stroke-dasharray:0.18 0.12; }
.cad-selbox.cad-locked { stroke:#f9a825; }   /* locked entity → amber selection outline (no handles) */
/* Snap markers: endpoint/grid = orange; "real geometry" osnaps (mid/center/quad/perp/tan) = success green */
.cad-snapmk  { stroke:#ff9800; }
.cad-snapmk.geo  { stroke:var(--mud-palette-success); }
.cad-snapdot { fill:#ff9800; }
.cad-snapdot.geo { fill:var(--mud-palette-success); }
/* snap type label under the glyph — secondary text color (falls back to silver) */
.cad-snaplbl { fill:var(--mud-palette-text-secondary, #b0b0b0); font-family:sans-serif; font-weight:600; }
.cad-handle { fill:#fff; stroke:var(--mud-palette-primary); pointer-events:all; cursor:pointer; }
.cad-handle:hover { fill:var(--mud-palette-primary); }
.cad-rot-stem { stroke:var(--mud-palette-primary); fill:none; pointer-events:none; }
.cad-rot-grip { fill:#fff; stroke:var(--mud-palette-primary); pointer-events:all; cursor:grab; }
.cad-rot-grip:hover { fill:var(--mud-palette-primary); }

/* Segment-midpoint vertex adders — the small "+" markers shown on a selected polyline */
.cad-mid-add { fill:#fff; fill-opacity:0.7; stroke:var(--mud-palette-primary); pointer-events:all; cursor:copy; }
.cad-mid-add:hover { fill:var(--mud-palette-primary); fill-opacity:1; }
.cad-mid-plus { stroke:var(--mud-palette-primary); pointer-events:none; }

/* Symbol palette */
.cad-sympicker { position:relative; display:inline-flex; }
.cad-sym-catcher { position:fixed; inset:0; z-index:2999; }
.cad-sympop { width:340px; max-width:92vw; padding:10px 12px; }
@media (min-width:1280px) { .cad-sympop { width:50vw; } }
.cad-sympop-head { display:flex; align-items:center; justify-content:space-between; font-size:0.8rem; font-weight:700;
    text-transform:uppercase; letter-spacing:0.4px; color:var(--mud-palette-text-secondary); margin-bottom:6px; }
.cad-sympop-body { max-height:min(70vh, 520px); overflow:auto; }
.cad-fieldpop { width:300px; max-width:92vw; padding:8px 6px; }
.cad-fieldlist { max-height:min(60vh, 440px); overflow:auto; }
.cad-field-row { display:flex; flex-direction:column; line-height:1.15; }
.cad-field-label { font-size:0.82rem; }
.cad-field-val { font-size:0.72rem; color:var(--mud-palette-text-secondary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:210px; }
.cad-drawpop { width:980px; max-width:96vw; padding:10px 12px; }
.cad-drawpop-grid { display:grid; grid-template-columns:repeat(4, 1fr); gap:10px; align-items:start; }
@media (max-width:1100px) { .cad-drawpop-grid { grid-template-columns:repeat(2, 1fr); } }
@media (max-width:860px) { .cad-drawpop-grid { grid-template-columns:1fr; } }
.cad-sym-cat { font-size:0.72rem; font-weight:700; text-transform:uppercase; letter-spacing:0.4px; color:var(--mud-palette-text-secondary); margin:8px 0 4px; }
.cad-sym-cat:first-child { margin-top:0; }
.cad-sym-grid { display:flex; flex-wrap:wrap; gap:6px; }
.cad-sym-tile { width:62px; display:flex; flex-direction:column; align-items:center; gap:2px; padding:4px; border:1px solid var(--mud-palette-lines-default); border-radius:6px; cursor:pointer; background:#fff; }
.cad-sym-tile:hover { border-color:var(--mud-palette-primary); box-shadow:0 2px 8px rgba(0,0,0,0.12); }
.cad-sym-thumb { width:46px; height:46px; display:flex; align-items:center; justify-content:center; }
.cad-sym-thumb svg { max-width:46px; max-height:46px; }
.cad-sym-name { font-size:0.64rem; line-height:1.05; text-align:center; color:#475569; }   /* fixed: the tile bg is always white */
.cad-comp-tile { position:relative; }
.cad-comp-del { position:absolute; top:-7px; right:-7px; display:none; cursor:pointer; color:var(--mud-palette-error); background:var(--mud-palette-surface); border-radius:50%; line-height:0; }
.cad-comp-tile:hover .cad-comp-del { display:inline-flex; }
.cad-comp-edit { position:absolute; top:-7px; left:-7px; display:none; cursor:pointer; color:var(--mud-palette-primary); background:var(--mud-palette-surface); border-radius:50%; line-height:0; }
.cad-comp-tile:hover .cad-comp-edit { display:inline-flex; }

/* ── Drawing Symbols Manager ─────────────────────────────────────────── */
.cad-symmgr { height:74vh; display:flex; gap:12px; }
.cad-symmgr-cats { width:320px; min-width:320px; display:flex; flex-direction:column; overflow-y:auto; }
.cad-symmgr-catpanel { width:100%; }
.cad-symmgr-syms { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; border:1px solid var(--mud-palette-lines-default); border-radius:8px; }
.cad-symmgr-head { display:flex; align-items:center; gap:8px; padding:8px 12px; border-bottom:1px solid var(--mud-palette-lines-default); font-weight:600; }
.cad-symmgr-catlist { display:flex; flex-direction:column; gap:2px; }
.cad-symmgr-cat { display:flex; align-items:center; gap:4px; padding:0 6px; min-height:40px; border-radius:6px; cursor:pointer; }
.cad-symmgr-cat:hover { background:var(--mud-palette-action-default-hover); }
.cad-symmgr-cat.active { background:color-mix(in srgb, var(--mud-palette-primary) 14%, transparent); }
.cad-symmgr-cat-name { flex:1 1 auto; font-size:0.85rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cad-symmgr-uncat { font-style:italic; color:var(--mud-palette-text-secondary); }
.cad-symmgr-cat-count { font-size:0.75rem; color:var(--mud-palette-text-secondary); }
.cad-symmgr-search { max-width:260px; }
.cad-symmgr-grid { flex:1 1 auto; overflow-y:auto; display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:10px; padding:12px; align-content:start; }
.cad-symmgr-tile { border:1px solid var(--mud-palette-lines-default); border-radius:8px; padding:8px; display:flex; flex-direction:column; gap:4px; background:#fff; }
.cad-symmgr-tile:hover { border-color:var(--mud-palette-primary); box-shadow:0 2px 8px rgba(0,0,0,0.10); }
.cad-symmgr-thumb { height:80px; display:flex; align-items:center; justify-content:center; cursor:pointer; }
.cad-symmgr-tile-name { font-size:0.82rem; font-weight:500; text-align:center; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#1f2937; }   /* fixed: the tile bg is always white */
.cad-symmgr-tile-meta { display:flex; flex-wrap:wrap; gap:4px; justify-content:center; min-height:18px; }
.cad-symmgr-chip { font-size:0.66rem; padding:1px 6px; border-radius:10px; background:#eef1f5; color:#555f6d; }
.cad-symmgr-chip.sys { background:#ede7f6; color:#5e35b1; }
.cad-symmgr-tile-acts { display:flex; align-items:center; justify-content:center; gap:2px; }
.cad-attr-row { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.cad-attr-name { min-width:140px; }
.cad-attr-type { max-width:140px; }
.cad-attr-flags { display:flex; align-items:center; gap:8px; }

/* Designer page shell (full viewport height under the top bar). */
.cad-page { height:calc(100vh - 70px); display:flex; flex-direction:column; overflow:hidden; }
.cad-page-bar {
    display:flex; align-items:center; gap:6px; padding:4px 10px;
    border-bottom:1px solid var(--mud-palette-lines-default); background:var(--mud-palette-surface); flex:0 0 auto;
}
.cad-title-field { max-width:380px; }
.cad-page-body { flex:1 1 auto; min-height:0; display:flex; }
.cad-page-body > * { flex:1 1 auto; min-height:0; }

/* CAD editor hosted in a fullscreen dialog (Project → Drawings) — fill the dialog minus the title bar. */
/* Fullscreen editor dialog: the shared CadDrawingEditor bar+body fill the whole viewport (the dialog
   renders no title bar of its own — the editor bar is the header, so no leftover scroll). */
.cad-dialog-body { height:100vh; min-height:0; display:flex; flex-direction:column; overflow:hidden; }
.cad-designer-dialog .mud-dialog-title { display:none; }
.cad-designer-dialog .mud-dialog-content { padding:0; }

/* Library cards */
.cad-lib-card { cursor:pointer; transition:box-shadow .15s ease, transform .15s ease; height:100%; }
/* Library-tile drawing thumbnail (live SVG render of the doc, left of the card text) */
.cad-lib-thumb { flex:0 0 112px; min-height:112px; display:flex; align-items:center; justify-content:center;
                 background:var(--mud-palette-background-gray, #f6f8fa); border-right:1px solid var(--mud-palette-lines-default);
                 padding:6px; overflow:hidden; }
.cad-lib-thumb svg { max-width:100%; max-height:100%; }

/* ── GeoMaps (TritiumMapCanvas) ─────────────────────────────────────────────── */
.tmapc-root { border-radius: 6px; z-index: 0; }
.tmapc-root .leaflet-container { border-radius: 6px; }
/* Text-label element rendered as a Leaflet divIcon (global — outside Blazor scoped css). */
.tmap-label { background: transparent !important; border: none !important; }
.tmap-label .tmap-label-text {
    display: inline-block; white-space: nowrap; transform: translate(-50%, -50%);
    padding: 2px 6px; border-radius: 4px; font-size: 12px; font-weight: 600;
    color: #fff; background: rgba(33,33,33,0.82); box-shadow: 0 1px 3px rgba(0,0,0,0.35);
}
/* GeoMap editor dialog: fill the dialog height. */
.geomap-dialog-body { height: calc(100vh - 160px); min-height: 420px; display: flex; }
.geomap-swatch { width: 22px; height: 22px; border-radius: 50%; cursor: pointer; border: 2px solid rgba(0,0,0,0.15); transition: transform .1s ease; }
.geomap-swatch:hover { transform: scale(1.15); }
/* Move handle for selected shapes (rect/frame/polygon/polyline) — drag to translate. */
.tmap-move-handle { background: transparent !important; border: none !important; }
.tmap-move-handle .tmap-move-handle-grip {
    width: 26px; height: 26px; border-radius: 50%; cursor: move;
    display: flex; align-items: center; justify-content: center;
    font-size: 15px; font-weight: 700; color: #fff;
    background: var(--mud-palette-primary, #1976d2);
    border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
}
/* View-frame name tag (Leaflet divIcon, global — outside Blazor scoped css). */
.tmap-frame-tag { background: transparent !important; border: none !important; }
.tmap-frame-tag .tmap-frame-tag-text {
    display: inline-block; white-space: nowrap; transform: translate(0, -100%);
    padding: 1px 6px; border-radius: 3px 3px 3px 0; font-size: 11px; font-weight: 700;
    color: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.cad-lib-card:hover { box-shadow:0 6px 20px rgba(0,0,0,0.14); transform:translateY(-2px); }
/* Global "working" indicator — a small pill tucked into the bottom-right corner, over the page
   content (a top bar blended into the primary-colored app bar). Non-interactive; shows while any
   server round-trip is in flight. */
.tritium-busybar {
    position: fixed;
    bottom: 8px;
    right: 10px;
    z-index: 2100;            /* above content, drawers, and the app bar */
    pointer-events: none;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
    padding: 5px 9px;
    border-radius: 8px;
    background: var(--mud-palette-surface);
    box-shadow: 0 2px 10px rgba(0, 0, 0, .22);
}
.tritium-busybar-text {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--mud-palette-text-secondary);
    text-align: center;
}
.tritium-busybar-line {
    width: 128px;
    height: 3px !important;   /* whisper-thin regardless of MudProgressLinear size */
    border-radius: 2px;
}

/* ── App-wide "you've got mail" bubble (floats bottom-center on any page) ──────── */
.mail-notify-bubble {
    position: fixed;
    left: 50%;
    /* Bottom-center on purpose: an alert worth interrupting for, kept where the eye already is.
       z-index 2000 keeps it above the taskbar (z 1350) if they overlap. */
    bottom: 24px;
    transform: translateX(-50%);
    z-index: 2000;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 20px 9px 12px;
    border-radius: 999px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    user-select: none;
    box-shadow: 0 8px 28px rgba(0,0,0,0.28);
    animation: mailNotifyIn .35s cubic-bezier(.2,.8,.2,1);
}
.mail-notify-bubble:hover  { filter: brightness(1.08); }
.mail-notify-bubble:active { transform: translateX(-50%) scale(0.97); }

.mail-notify-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: rgba(255,255,255,0.18);
    animation: mailNotifyPulse 1.6s ease-out infinite;
}

@keyframes mailNotifyPulse {
    0%   { box-shadow: 0 0 0 0 rgba(255,255,255,0.55); }
    70%  { box-shadow: 0 0 0 14px rgba(255,255,255,0); }
    100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}
@keyframes mailNotifyIn {
    from { opacity: 0; transform: translateX(-50%) translateY(14px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
