/* Theme 2.0 (#520) component skin.
   Skins MudBlazor components to the mockup (docs/ui/tip-app-theme-2.0.html), driven by the
   MudBlazor palette variables so one IsDarkMode switch serves both modes. Self-hosted Inter
   is declared here. Loaded after app.css in App.razor so it wins the cascade. */

/* ---------- Inter (self-hosted, SIL OFL; wwwroot/fonts) ---------- */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/inter-latin-400-normal.woff2') format('woff2');
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/inter-latin-500-normal.woff2') format('woff2');
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/inter-latin-600-normal.woff2') format('woff2');
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/inter-latin-700-normal.woff2') format('woff2');
}

/* ---------- Body background: mockup radial (dark) / gradient (light) ----------
   The theme-dark / theme-light class is first set on <body> before paint by the inline
   anti-flash script in each portal's App.razor, then kept in sync by
   themeInterop.setBodyTheme (MainLayoutBase, on first render and on every toggle). */
/* The --tip-* shell tokens carry the mode-specific values MudBlazor's palette has no slot for.
   Values come from docs/ui/theme-2.1-mockup.html. */
body.theme-dark {
    background: radial-gradient(circle at 30% -10%, #1d1d20 0%, #141416 45%, #0b0b0c 100%) fixed;
    --tip-rail-edge: rgba(255, 255, 255, 0.06);
    --tip-rail-line: rgba(255, 255, 255, 0.07);
    --tip-rail-strong: #ffffff;
    --tip-rail-tagline: rgba(255, 255, 255, 0.55);
    --tip-rail-label: rgba(255, 255, 255, 0.60);
    --tip-rail-disabled: rgba(255, 255, 255, 0.40);
    --tip-rail-chip-bg: rgba(255, 255, 255, 0.05);
    --tip-rail-chip-edge: rgba(255, 255, 255, 0.10);
    --tip-rail-badge-bg: rgba(255, 255, 255, 0.08);
    --tip-rail-badge-text: rgba(255, 255, 255, 0.62);
    --tip-rail-scroll: rgba(255, 255, 255, 0.22);
    --tip-nav-hover: rgba(249, 115, 22, 0.12);
    --tip-nav-active: rgba(249, 115, 22, 0.16);
    --tip-nav-indicator: var(--mud-palette-primary);
    --tip-topbar-edge: rgba(255, 255, 255, 0.08);
    --tip-row-stripe: rgba(255, 255, 255, 0.02);
    --tip-row-hover: rgba(249, 115, 22, 0.10);
    --tip-btn-primary-end: var(--mud-palette-primary-darken);
    --tip-btn-disabled-bg: var(--mud-palette-action-disabled-background);
    /* Color roles: links, the neutral stat chip and the Waiting status. */
    --tip-link: #60a5fa;
    --tip-focus-ring: #60a5fa;
    --tip-neutral-tile: rgba(255, 255, 255, 0.08);
    --tip-status-wait-fg: #a78bfa;
    --tip-status-wait-bg: rgba(167, 139, 250, 0.16);
    --tip-status-wait-border: rgba(167, 139, 250, 0.45);
    /* Neutral progress fill (.tip-progress-neutral): bar 4.07:1 on its track, 6.91:1 on Surface. */
    --tip-progress-fill: #a1a1aa;
    --tip-progress-track: #3f3f46;
}

/* Light rail indicator is #c2410c: the accent #ea580c is 2.81:1 on #e4e4e7, under the 3:1 non-text minimum. */
body.theme-light {
    background: linear-gradient(180deg, #f4f4f5 0%, #ececee 100%) fixed;
    --tip-rail-edge: rgba(24, 24, 27, 0.10);
    --tip-rail-line: rgba(24, 24, 27, 0.08);
    --tip-rail-strong: #18181b;
    --tip-rail-tagline: #52525b;
    --tip-rail-label: #52525b;
    --tip-rail-disabled: #71717a; /* "soon" stubs; #a1a1aa read 2.02:1 on the light rail (#1657 review smoke) */
    --tip-rail-chip-bg: rgba(24, 24, 27, 0.04);
    --tip-rail-chip-edge: rgba(24, 24, 27, 0.10);
    --tip-rail-badge-bg: rgba(24, 24, 27, 0.06);
    --tip-rail-badge-text: #52525b;
    --tip-rail-scroll: rgba(24, 24, 27, 0.22);
    --tip-nav-hover: rgba(249, 115, 22, 0.10);
    --tip-nav-active: rgba(249, 115, 22, 0.14);
    --tip-nav-indicator: #c2410c;
    --tip-topbar-edge: rgba(24, 24, 27, 0.08);
    --tip-row-stripe: rgba(24, 24, 27, 0.025);
    --tip-row-hover: rgba(249, 115, 22, 0.08);
    /* Flat fill: the darkened gradient end is only 3.77:1 under the dark label. */
    --tip-btn-primary-end: var(--mud-palette-primary);
    /* Light ActionDisabledBackground is MudBlazor's 12% black, so the flat disabled gray is BackgroundGray. */
    --tip-btn-disabled-bg: var(--mud-palette-background-gray);
    /* Color roles. On white, colored text uses the darker shade: link #1d4ed8, Waiting #6d28d9. */
    --tip-link: #1d4ed8;
    --tip-focus-ring: #1d4ed8;
    --tip-neutral-tile: rgba(24, 24, 27, 0.06);
    --tip-status-wait-fg: #6d28d9;
    --tip-status-wait-bg: rgba(167, 139, 250, 0.18);
    --tip-status-wait-border: rgba(124, 58, 237, 0.40);
    /* Neutral progress fill (.tip-progress-neutral): bar 3.81:1 on its track, 4.83:1 on Surface. */
    --tip-progress-fill: #71717a;
    --tip-progress-track: #e4e4e7;
}

/* ---------- Neutral progress fill ---------- */
/* Completion, job and share bars (Color.Default plus class tip-progress-neutral). MudBlazor's default
   fill (ActionDefault on ActionDisabled) is 2.45:1 bar to track in light mode; these tokens hold 3:1
   bar to track and bar to surface in both modes (WCAG 2.2 SC 1.4.11) without touching the palette's
   action colors, which also paint icons and disabled controls. Scoped to the default color, so a
   conditional Color.Primary (a selected topic) keeps the accent. */
.mud-progress-linear.mud-progress-linear-color-default.tip-progress-neutral:not(.mud-progress-linear-buffer)::before {
    background-color: var(--tip-progress-track);
    opacity: 1;
}

.mud-progress-linear.mud-progress-linear-color-default.tip-progress-neutral:not(.mud-progress-linear-buffer) .mud-progress-linear-bar {
    background-color: var(--tip-progress-fill);
}

/* ---------- Cards / Paper ---------- */
.mud-paper {
    border: 1px solid var(--mud-palette-lines-default);
}

/* ---------- Buttons: filled primary reads as the accent gradient with dark text ---------- */
.mud-button-filled.mud-button-filled-primary {
    background: linear-gradient(135deg, var(--mud-palette-primary), var(--tip-btn-primary-end, var(--mud-palette-primary-darken)));
    color: var(--mud-palette-primary-text);
}

    .mud-button-filled.mud-button-filled-primary:hover {
        filter: brightness(1.07);
    }

/* No glow on any button: MudBlazor gives filled buttons and FABs an elevation shadow
   at rest, on hover, on focus and when pressed. Buttons sit flat; focus stays visible through the
   focus-visible outline, not a shadow. */
.mud-button-filled,
.mud-button-filled:hover,
.mud-button-filled:focus-visible,
.mud-button-filled:active,
.mud-fab,
.mud-fab:hover,
.mud-fab:focus-visible,
.mud-fab:active,
.mud-button-group-filled,
.mud-button-group-filled .mud-button-root:hover,
.mud-button-group-filled .mud-button-root:focus-visible,
.mud-button-group-filled .mud-button-root:active {
    box-shadow: none;
}

/* ---------- Keyboard focus: one ring ----------
   Every keyboard focus indicator is a 2px --tip-focus-ring outline (blue, the Links role). It
   clears 3:1 on every surface, the rails, the page gradient and the selected tints (PortalThemeContrastTests).
   The baseline has zero specificity (:where), so it only replaces the browser default and never beats a rule
   that sets its own offset or turns the outline off (rail rows, toggle items and segments draw it inset; dialogs,
   popovers and the h1 focus target clear it). MudBlazor buttons, chips, tabs and menu activators clear the
   outline themselves, so they get a class-level rule below it. Text inputs are left out: their underline or
   outlined border is their indicator (mud-blazor-overrides.css). Checkboxes, switches and radios hide their
   input, so the ring goes on the round button around it. */
:where(:focus-visible:not(input.mud-input-root, textarea.mud-input-root)) {
    outline: 2px solid var(--tip-focus-ring);
    outline-offset: 2px;
}

.mud-button-root:focus-visible,
.mud-chip:focus-visible,
.mud-tab:focus-visible,
.mud-menu-activator:focus-visible,
.mud-icon-button:has(input:focus-visible) {
    outline: 2px solid var(--tip-focus-ring);
    outline-offset: 2px;
}

/* The elevation shadow was MudBlazor's keyboard-focus cue, so filled buttons and FABs take the ring (SC 2.4.7). */
.mud-button-filled:focus-visible,
.mud-fab:focus-visible {
    outline: 2px solid var(--tip-focus-ring);
    outline-offset: 2px;
}

/* The top-bar light/dark toggle (ThemeToggle) gets the same keyboard ring. */
.tip-theme-toggle:focus-visible {
    outline: 2px solid var(--tip-focus-ring);
    outline-offset: 2px;
}

/* Disabled ICON buttons should dim, not paint a solid gray circle. The global
   .mud-button-root:disabled rule forces a solid background (right for filled buttons,
   wrong for icon buttons, where it hides the icon inside a gray dot). Filled icon buttons keep the fill. */
.mud-icon-button:not(.mud-button-filled):disabled,
.mud-icon-button.mud-disabled:not(.mud-button-filled) {
    background-color: transparent !important;
}

/* ---------- Tables: uppercase header on a tinted bar, zebra rows, accent-soft hover ---------- */
.mud-table-head .mud-table-cell {
    text-transform: uppercase;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-background-gray);
}

/* Zebra rows: very subtle tint, matching the mockup (heavier default looked off in dark).
   Covers MudTable (.mud-table-body rows) AND MudDataGrid (.mud-data-grid tbody rows), which
   uses a different DOM and otherwise gets no zebra. */
.mud-table-body .mud-table-row:nth-of-type(even),
.mud-data-grid tbody tr:nth-of-type(even) {
    background: var(--tip-row-stripe, transparent);
}

/* Row hover: orange accent-soft in both modes. !important to beat the MudTable default. */
.mud-table-body .mud-table-row:hover {
    background: var(--tip-row-hover) !important;
}

/* ---------- Tabs: orange active indicator (position), neutral bold active label ---------- */
.mud-tabs .mud-tab-slider {
    background: var(--mud-palette-primary);
}

.mud-tabs .mud-tab.mud-tab-active {
    color: var(--mud-palette-text-primary);
    font-weight: 700;
}

/* Tabs container reads as one card. The panel area can default to transparent, so fill the
   container with the surface; the now-crisper global card border (LinesDefault) carries the
   edge against the dark radial page bg. */
.mud-tabs.mud-paper {
    background-color: var(--mud-palette-surface);
}

/* ---------- App-bar Section / Page breadcrumb ---------- */
.tip-crumb {
    margin-left: 10px;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.tip-crumb-section {
    color: var(--mud-palette-text-secondary);
}

.tip-crumb-sep {
    color: var(--mud-palette-text-secondary);
}

.tip-crumb-page {
    color: var(--mud-palette-text-primary);
    font-weight: 700;
}

/* ---------- Quick Links tool cards (Home) ---------- */
.tip-ql-section {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--mud-palette-text-secondary);
    margin: 20px 0 10px;
}

/* Labeled divider between page sections (#1841, signed-out NS Home). Used with .tip-ql-section, which
   sets the label type; this adds the rule running to the right, the page-level twin of the rail's
   .tip-rail-label. */
.tip-ql-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 32px 0 12px;
}

.tip-ql-rule {
    flex: 1;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

.tip-ql-grid {
    display: grid;
    /* auto-fill (not auto-fit) keeps the column width consistent across sections,
       so a 3-card section and a 7-card section have the same card size. The 300px min
       yields wider cards (about 3 per row in the md=8 area). */
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 12px;
}

.tip-toolcard {
    display: block;
    text-decoration: none;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    padding: 14px;
    height: 100%;
    min-height: 116px;
    box-sizing: border-box;
    transition: background .14s, border-color .14s, transform .14s;
}

    .tip-toolcard:hover {
        border-color: rgba(249, 115, 22, .55);
        background: var(--mud-palette-primary-hover);
        transform: translateY(-2px);
    }

/* Launcher icon chip is neutral; only the card hover carries the accent. */
.tip-toolcard-ic {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--tip-neutral-tile);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 10px;
}

.tip-toolcard-name {
    font-size: 14px;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
}

.tip-toolcard-desc {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
}

/* ---------- AI feature banner (Inbox rule suggestions, briefs) ----------
   The motif's AI call-to-action: a soft accent glow on the card surface with an orange
   icon chip, replacing the old MudBlazor purple. Theme-aware (surface var under an
   orange-tint gradient). Qualified with .mud-paper so it beats the base card border.
   Reusable on any AI surface; pair with a .tip-stat-ic.tip-stat-ic-accent icon chip. */
.tip-ai-banner.mud-paper {
    border: 1px solid rgba(249, 115, 22, .40);
    background: linear-gradient(135deg, rgba(249, 115, 22, .16) 0%, rgba(249, 115, 22, .02) 60%), var(--mud-palette-surface);
}

body.theme-light .tip-ai-banner.mud-paper {
    background: linear-gradient(135deg, rgba(249, 115, 22, .12) 0%, rgba(249, 115, 22, .02) 60%), var(--mud-palette-surface);
}

/* ---------- Stat-card icon chips (Inbox + SNOUT dashboards) ----------
   Square-rounded soft chip behind a MudIcon. A tile that carries no status uses the neutral chip
   with a Color.Secondary (TextSecondary) icon; a status tile tints the chip to its status hue.
   The accent chip is kept for a listed accent override only. */
.tip-stat-ic {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.tip-stat-ic-neutral {
    background: var(--tip-neutral-tile);
}

.tip-stat-ic-accent {
    background: rgba(249, 115, 22, .22);
}

.tip-stat-ic-success {
    background: rgba(16, 185, 129, .20);
}

.tip-stat-ic-info {
    background: rgba(96, 165, 250, .20);
}

.tip-stat-ic-error {
    background: rgba(239, 68, 68, .20);
}

.tip-stat-ic-warning {
    background: rgba(245, 158, 11, .20);
}

/* The stat value is the loud element: large, bold, theme primary text by default.
   Only the alert stat (errors) carries a status color, set per-card via MudText Color. */
.tip-stat-value {
    font-weight: 700;
    line-height: 1.1;
}

/* Clickable stat cards (SNOUT dashboard): hover lift + accent edge to signal they navigate. */
.tip-statcard-click {
    transition: transform .14s, border-color .14s;
}

    .tip-statcard-click:hover {
        transform: translateY(-2px);
        border-color: rgba(249, 115, 22, .55);
    }

/* ---------- File-upload dropzone (admin CSV imports) ----------
   Neutral dashed edge and text at rest; the accent border and tint appear only on hover,
   keyboard focus inside the zone, or drag-over (.tip-dropzone-over). */
.tip-dropzone {
    border: 1.5px dashed var(--mud-palette-lines-inputs);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    border-radius: 10px;
    text-align: center;
    cursor: pointer;
    transition: background .14s, border-color .14s;
}

    .tip-dropzone:hover,
    .tip-dropzone:focus-within,
    .tip-dropzone.tip-dropzone-over {
        background: rgba(249, 115, 22, .08);
        border-color: rgba(249, 115, 22, .70);
    }

/* Neutral icon inside the dropzone. */
.tip-dropzone .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* The public LOA Submission page is not on the color roles yet (public layout), so its dropzone keeps the
   accent look until that page moves onto them. */
.tip-dropzone.loa-dropzone {
    border-color: rgba(249, 115, 22, .45);
    background: rgba(249, 115, 22, .04);
    color: inherit;
}

    .tip-dropzone.loa-dropzone:hover {
        background: rgba(249, 115, 22, .08);
        border-color: rgba(249, 115, 22, .70);
    }

/* ---------- International Rates public: center the search block on the page ---------- */
.ir-search-wrap {
    max-width: 1040px;
    margin: 24px auto 0;
}

/* ---------- Meeting cards (Calendar Brief): subtle hover lift ---------- */
.tip-meeting-card {
    transition: transform .14s, border-color .14s;
}

    .tip-meeting-card:hover {
        transform: translateY(-2px);
    }

/* ---------- Alerts: readable message text in both modes ----------
   The default text and outlined alerts paint the severity color as the message text, which is under
   4.5:1 in both modes (light Warning 2.44 to 2.87, light Info 4.02, dark Info 3.55 to 3.74). The message
   reads in TextPrimary and the leading icon keeps the severity color. Dark mode also gets a soft
   severity tint on the text variant. Filled alerts take the dark contrast ink from PortalTheme. */
body.theme-dark .mud-alert-text-info {
    background-color: rgba(96, 165, 250, .12);
}

body.theme-dark .mud-alert-text-success {
    background-color: rgba(16, 185, 129, .12);
}

body.theme-dark .mud-alert-text-warning {
    background-color: rgba(245, 158, 11, .12);
}

body.theme-dark .mud-alert-text-error {
    background-color: rgba(239, 68, 68, .12);
}

body .mud-alert-text-info .mud-alert-message,
body .mud-alert-text-success .mud-alert-message,
body .mud-alert-text-warning .mud-alert-message,
body .mud-alert-text-error .mud-alert-message,
body .mud-alert-outlined-info .mud-alert-message,
body .mud-alert-outlined-success .mud-alert-message,
body .mud-alert-outlined-warning .mud-alert-message,
body .mud-alert-outlined-error .mud-alert-message {
    color: var(--mud-palette-text-primary);
}

/* ---------- Alerts: readable in light mode ----------
   The message reads in TextPrimary; the icon carries the severity at full opacity, in the light-mode
   status shades (Info keeps palette Info). PortalThemeContrastTests holds the ratios. */
body.theme-light .mud-alert-text-info .mud-alert-message,
body.theme-light .mud-alert-text-success .mud-alert-message,
body.theme-light .mud-alert-text-warning .mud-alert-message,
body.theme-light .mud-alert-text-error .mud-alert-message {
    color: var(--mud-palette-text-primary);
}

body.theme-light .mud-alert-text-info .mud-alert-icon,
body.theme-light .mud-alert-text-success .mud-alert-icon,
body.theme-light .mud-alert-text-warning .mud-alert-icon,
body.theme-light .mud-alert-text-error .mud-alert-icon {
    opacity: 1;
}

body.theme-light .mud-alert-text-success .mud-alert-icon {
    color: var(--tip-status-ok-fg);
}

body.theme-light .mud-alert-text-warning .mud-alert-icon {
    color: var(--tip-status-warn-fg);
}

body.theme-light .mud-alert-text-error .mud-alert-icon {
    color: var(--tip-status-fail-fg);
}

/* ---------- Filled status chips: dark ink ----------
   The label and icons take the filled-button ink (--tip-on-primary), as filled orange buttons do.
   Chips only: filled buttons and badges in these colors keep the palette ContrastText. */
.mud-chip-filled.mud-chip-color-success,
.mud-chip-filled.mud-chip-color-warning,
.mud-chip-filled.mud-chip-color-error,
.mud-chip-filled.mud-chip-color-info {
    color: var(--tip-on-primary);
    --mud-ripple-color: var(--tip-on-primary) !important;
}

/* A clickable filled status chip lightens on hover, focus and press; the ink fails AA on the darkened fills. */
@media (hover: hover) and (pointer: fine) {
    .mud-chip-filled.mud-chip-color-success.mud-clickable:hover:not(.mud-disabled) {
        background-color: var(--mud-palette-success-lighten);
    }

    .mud-chip-filled.mud-chip-color-warning.mud-clickable:hover:not(.mud-disabled) {
        background-color: var(--mud-palette-warning-lighten);
    }

    .mud-chip-filled.mud-chip-color-error.mud-clickable:hover:not(.mud-disabled) {
        background-color: var(--mud-palette-error-lighten);
    }

    .mud-chip-filled.mud-chip-color-info.mud-clickable:hover:not(.mud-disabled) {
        background-color: var(--mud-palette-info-lighten);
    }
}

.mud-chip-filled.mud-chip-color-success.mud-clickable:focus-visible:not(.mud-disabled),
.mud-chip-filled.mud-chip-color-success.mud-clickable:active:not(.mud-disabled) {
    background-color: var(--mud-palette-success-lighten);
}

.mud-chip-filled.mud-chip-color-warning.mud-clickable:focus-visible:not(.mud-disabled),
.mud-chip-filled.mud-chip-color-warning.mud-clickable:active:not(.mud-disabled) {
    background-color: var(--mud-palette-warning-lighten);
}

.mud-chip-filled.mud-chip-color-error.mud-clickable:focus-visible:not(.mud-disabled),
.mud-chip-filled.mud-chip-color-error.mud-clickable:active:not(.mud-disabled) {
    background-color: var(--mud-palette-error-lighten);
}

.mud-chip-filled.mud-chip-color-info.mud-clickable:focus-visible:not(.mud-disabled),
.mud-chip-filled.mud-chip-color-info.mud-clickable:active:not(.mud-disabled) {
    background-color: var(--mud-palette-info-lighten);
}

/* ---------- Scope-change snackbar (nav rail) ----------
   Mockup .toast: bottom right whatever the global snackbar position, a surface card with an indicator
   edge, the scope icon, the name in bold and "· N pages" in secondary text. */
.mud-snackbar.tip-scope-cue-snack {
    position: fixed;
    right: 24px;
    bottom: 24px;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 3px solid var(--tip-nav-indicator);
    border-radius: 0 10px 10px 0;
}

.tip-scope-cue-msg {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
}

.tip-scope-cue-msg .tip-scope-cue-icon {
    color: var(--tip-nav-indicator);
}

.tip-scope-cue-name {
    font-weight: 600;
}

.tip-scope-cue-count {
    color: var(--mud-palette-text-secondary);
}

/* ---------- Ticket cards (Home: My Open Tickets) ---------- */
.tip-ticket {
    display: block;
    text-decoration: none;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 8px;
    transition: background .14s, border-color .14s, transform .14s;
}

a.tip-ticket:hover {
    border-color: rgba(249, 115, 22, .55);
    background: var(--mud-palette-primary-hover);
    transform: translateY(-1px);
}

.tip-ticket-top {
    display: flex;
    align-items: center;
    gap: 8px;
}

.tip-ticket-num {
    color: var(--mud-palette-text-primary);
    font-weight: 700;
    font-size: 13px;
}

.tip-ticket-subj {
    color: var(--mud-palette-text-primary);
    font-size: 13px;
    margin-top: 5px;
    line-height: 1.4;
}

.tip-ticket-status {
    margin-left: auto;
    font-size: 11px;
    font-weight: 700;
    border-radius: 20px;
    padding: 1px 9px;
    border: 1px solid;
    white-space: nowrap;
}

.tip-st-open {
    color: #fcd34d;
    background: rgba(245, 158, 11, .16);
    border-color: rgba(245, 158, 11, .35);
}

.tip-st-other {
    color: #93c5fd;
    background: rgba(96, 165, 250, .16);
    border-color: rgba(96, 165, 250, .35);
}

/* Light mode: darker text + richer fill so the chips stay readable on white */
body.theme-light .tip-st-open {
    color: #92400e;
    background: rgba(245, 158, 11, .20);
    border-color: rgba(245, 158, 11, .45);
}

body.theme-light .tip-st-other {
    color: #1e40af;
    background: rgba(96, 165, 250, .18);
    border-color: rgba(96, 165, 250, .45);
}

/* ---------- Nav "soon" badge for disabled stub links ---------- */
.nav-soon {
    margin-left: auto;
    background: var(--tip-rail-badge-bg);
    color: var(--tip-rail-badge-text);
    font-size: 10px;
    font-weight: 700;
    border-radius: 10px;
    padding: 1px 7px;
    letter-spacing: 0.3px;
}

/* ---------- Route-change nav overlay (navOverlay.js) ----------
   Palette-driven skin for the JS-injected overlay (#548). Behavior (show/hide, the 5s
   safety timeout) lives in navOverlay.js; visibility is toggled there via style.display,
   which overrides the display:none default below. Colors come from the MudBlazor palette
   variables so the overlay follows the active light/dark mode. */
@keyframes tip-spin {
    to {
        transform: rotate(360deg);
    }
}

.tip-nav-overlay {
    position: fixed;
    inset: 0;
    background: var(--mud-palette-overlay-dark);
    z-index: 99999;
    display: none;
    align-items: center;
    justify-content: center;
}

.tip-nav-overlay-spinner {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 4px solid var(--mud-palette-lines-default);
    border-top-color: var(--mud-palette-primary);
    animation: tip-spin 0.6s linear infinite;
}

/* ---------- Live status tokens (epic #1629 Wave 3, True Context call chip) ----------
   Foreground, fill and border for a live "warn" (ringing) and "ok" (on call) status, from the True
   Context mockup (.ns-callchip). Dark values are the default; body.theme-light overrides the text, the
   same convention as .tip-st-open above. Components reference these instead of hardcoding hex. */
body {
    --tip-status-warn-fg: #fbbf24;
    --tip-status-warn-bg: rgba(245, 158, 11, .16);
    --tip-status-warn-border: rgba(245, 158, 11, .45);
    --tip-status-ok-fg: #34d399;
    --tip-status-ok-bg: rgba(16, 185, 129, .14);
    --tip-status-ok-border: rgba(16, 185, 129, .35);
}

body.theme-light {
    --tip-status-warn-fg: #92400e;
    --tip-status-ok-fg: #047857;
}

/* ---------- Color roles ----------
   Link fallback for a page whose body has no theme class yet (light is the default mode); the
   body.theme-* blocks above set the real value per mode. */
body {
    --tip-link: #1d4ed8;
    --tip-focus-ring: #1d4ed8;
}

/* Light-mode status text: the base status fills are under 4.5:1 on white, so colored status text and
   icons use the darker shades (Success #047857, Warning #92400e, Error #b91c1c). Dark mode keeps the
   base colors, which clear 4.5:1 on the dark surfaces. */
body.theme-light .mud-success-text {
    color: var(--tip-status-ok-fg) !important;
}

body.theme-light .mud-warning-text {
    color: var(--tip-status-warn-fg) !important;
}

body.theme-light .mud-error-text {
    color: var(--tip-status-fail-fg) !important;
}

/* Info text and the light accent label shade. Palette Info and the control accent (#ea580c) are under 4.5:1 on
   white and the end of the page gradient, so light info text and outlined accent labels take darker shades. */
body {
    --tip-status-info-fg: #60a5fa;
}

body.theme-light {
    --tip-status-info-fg: #1d4ed8;
    --tip-accent-text: #b83d0a;
}

body.theme-light .mud-info-text {
    color: var(--tip-status-info-fg) !important;
}

/* Light outlined and text status chips and buttons: the label (and an outlined edge) take the mode's status
   text shade, as .mud-*-text does above. Filled ones take the dark contrast ink from PortalTheme. */
body.theme-light .mud-chip-outlined.mud-chip-color-success,
body.theme-light .mud-chip-text.mud-chip-color-success,
body.theme-light .mud-button-outlined.mud-button-outlined-success:not(:disabled),
body.theme-light .mud-button-text.mud-button-text-success:not(:disabled) {
    color: var(--tip-status-ok-fg) !important;
    --mud-ripple-color: var(--tip-status-ok-fg);
}

body.theme-light .mud-chip-outlined.mud-chip-color-warning,
body.theme-light .mud-chip-text.mud-chip-color-warning,
body.theme-light .mud-button-outlined.mud-button-outlined-warning:not(:disabled),
body.theme-light .mud-button-text.mud-button-text-warning:not(:disabled) {
    color: var(--tip-status-warn-fg) !important;
    --mud-ripple-color: var(--tip-status-warn-fg);
}

body.theme-light .mud-chip-outlined.mud-chip-color-info,
body.theme-light .mud-chip-text.mud-chip-color-info,
body.theme-light .mud-button-outlined.mud-button-outlined-info:not(:disabled),
body.theme-light .mud-button-text.mud-button-text-info:not(:disabled) {
    color: var(--tip-status-info-fg) !important;
    --mud-ripple-color: var(--tip-status-info-fg);
}

body.theme-light .mud-chip-outlined.mud-chip-color-error,
body.theme-light .mud-chip-text.mud-chip-color-error {
    color: var(--tip-status-fail-fg) !important;
}

body.theme-light .mud-chip-outlined.mud-chip-color-success,
body.theme-light .mud-button-outlined.mud-button-outlined-success:not(:disabled) {
    border-color: var(--tip-status-ok-fg) !important;
}

body.theme-light .mud-chip-outlined.mud-chip-color-warning,
body.theme-light .mud-button-outlined.mud-button-outlined-warning:not(:disabled) {
    border-color: var(--tip-status-warn-fg) !important;
}

body.theme-light .mud-chip-outlined.mud-chip-color-info,
body.theme-light .mud-button-outlined.mud-button-outlined-info:not(:disabled) {
    border-color: var(--tip-status-info-fg) !important;
}

body.theme-light .mud-chip-outlined.mud-chip-color-error {
    border-color: var(--tip-status-fail-fg) !important;
}

/* Text error buttons (Delete, Deactivate), both modes, the same shape as the outlined error rule in
   mud-blazor-overrides.css: palette Error is 3.76:1 on white and 4.46:1 on the dark page. */
body .mud-button-text.mud-button-text-error:not(:disabled) {
    color: var(--tip-status-fail-fg);
    --mud-ripple-color: var(--tip-status-fail-fg);
}

/* Light outlined accent buttons and chips (Open Tool, Edit Schedule, New contact; PEEN's tertiary outlined
   button) take the darker accent label and edge. Dark mode keeps the palette accent, which clears 4.5:1. */
body.theme-light .mud-button-outlined.mud-button-outlined-primary:not(:disabled),
body.theme-light .mud-button-outlined.mud-button-outlined-tertiary:not(:disabled),
body.theme-light .mud-button-text.loa-invoice-download:not(:disabled),
body.theme-light .mud-chip-outlined.mud-chip-color-primary,
body.theme-light .mud-chip-text.mud-chip-color-primary,
body.theme-light .mud-chip-outlined.mud-chip-color-tertiary,
body.theme-light .mud-chip-text.mud-chip-color-tertiary {
    color: var(--tip-accent-text) !important;
    --mud-ripple-color: var(--tip-accent-text);
}

body.theme-light .mud-button-outlined.mud-button-outlined-primary:not(:disabled),
body.theme-light .mud-button-outlined.mud-button-outlined-tertiary:not(:disabled),
body.theme-light .mud-chip-outlined.mud-chip-color-primary,
body.theme-light .mud-chip-outlined.mud-chip-color-tertiary {
    border-color: var(--tip-accent-text) !important;
}

/* Light input error text: the helper and the label under an invalid field use the light error shade
   (palette Error is 3.76:1 on white). Dark keeps palette Error, 4.71:1 on Surface. */
body.theme-light .mud-input-helper-text.mud-input-error,
body.theme-light .mud-input-label.mud-input-error {
    color: var(--tip-status-fail-fg) !important;
}

/* Waiting status (violet): waiting on someone outside TIPS, such as a customer or carrier. Always
   paired with an icon or a word. .tip-chip-wait goes on a MudChip with Color.Default; .tip-status-wait-text
   colors a label or icon. */
.mud-chip.tip-chip-wait {
    background-color: var(--tip-status-wait-bg) !important;
    color: var(--tip-status-wait-fg) !important;
    border: 1px solid var(--tip-status-wait-border);
}

.mud-chip.tip-chip-wait .mud-icon-root {
    color: var(--tip-status-wait-fg);
}

.tip-status-wait-text {
    color: var(--tip-status-wait-fg) !important;
}

/* Accent override: the one greppable class for a listed, reviewed accent use on text or an icon
   (docs/ui/ui-branding-standard.md, Accent usage rule). Never use it without the PR listing. */
.tip-accent-override {
    color: var(--mud-palette-primary) !important;
}

/* Text that reads as a link inside a larger clickable element (a card that navigates). */
.tip-link-text {
    color: var(--tip-link) !important;
}

/* Text for screen readers only: part of an accessible name with no visible copy (the scope switcher's
   "Switch scope, current:" prefix). */
.tip-sr-only {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------- True Context Live Call (epic #1629 Wave 4, issue #1670) ----------
   Source chip fills by connection category, from the True Context mockup (:root --crm, --desk, --books,
   --ns). The chip text is the connection's display name; the color says the category. Fail tokens join the
   Wave 3 warn and ok status tokens. Components reference these classes and tokens, never hex. */
body {
    --tip-src-crm: #7c3aed;
    --tip-src-helpdesk: #059669;
    --tip-src-accounting: #d97706;
    --tip-src-telephony: #475569;
    --tip-src-fg: #ffffff;
    --tip-on-primary: #1b1206; /* same ink as PrimaryContrastText, so dark ink on orange is one value */
    --tip-accent-soft: rgba(249, 115, 22, .18);
    --tip-status-fail-fg: #f87171;
    --tip-status-fail-bg: rgba(239, 68, 68, .12);
    --tip-status-fail-border: rgba(239, 68, 68, .40);
}

body.theme-light {
    --tip-status-fail-fg: #b91c1c;
}

/* Pill text on status tints (issue #1737). Dark mode puts white text on every tinted tone and black on the solid
   accent fill, so each pill clears 7:1 (measured over #18181b and the .tip-ai-banner fill). Light mode keeps the
   tone colors: these tokens are unset there and the rules below fall back to the per-tone values. The
   --tip-status-*-fg tokens themselves do not change; borders keep the tone color, and icon plus word stays the cue. */
body {
    --tip-pill-on-tint: #ffffff;
    --tip-pill-on-fill: #000000;
}

body.theme-light {
    --tip-pill-on-tint: initial;
    --tip-pill-on-fill: initial;
}

.tc-src {
    display: inline-block;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    color: var(--tip-src-fg);
    letter-spacing: .02em;
    white-space: nowrap;
}

.tc-src-crm { background: var(--tip-src-crm); }
.tc-src-helpdesk { background: var(--tip-src-helpdesk); }
.tc-src-accounting { background: var(--tip-src-accounting); }
.tc-src-telephony { background: var(--tip-src-telephony); }

.tc-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 24px;
    padding: 0 10px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid var(--mud-palette-lines-default);
    color: var(--tip-pill-on-tint, var(--mud-palette-text-secondary));
    background: var(--mud-palette-background-gray);
}

.tc-pill .mud-icon-root { font-size: 14px; }
.tc-pill-ok { background: var(--tip-status-ok-bg); color: var(--tip-pill-on-tint, var(--tip-status-ok-fg)); border-color: var(--tip-status-ok-border); }
.tc-pill-warn { background: var(--tip-status-warn-bg); color: var(--tip-pill-on-tint, var(--tip-status-warn-fg)); border-color: var(--tip-status-warn-border); }
.tc-pill-fail { background: var(--tip-status-fail-bg); color: var(--tip-pill-on-tint, var(--tip-status-fail-fg)); border-color: var(--tip-status-fail-border); }
.tc-pill-acc { background: transparent; color: var(--tip-pill-on-tint, var(--mud-palette-primary)); border-color: var(--mud-palette-primary); }
.tc-pill-accf { background: var(--mud-palette-primary); color: var(--tip-pill-on-fill, var(--tip-on-primary)); border-color: var(--mud-palette-primary); }

.tc-grid { display: grid; gap: 16px; align-items: start; }
.tc-grid-3 { grid-template-columns: minmax(260px, 3fr) minmax(0, 5fr) minmax(280px, 3.4fr); }
.tc-grid-2 { grid-template-columns: minmax(260px, 3fr) minmax(0, 8.4fr); }
.tc-grid > div { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
@media (max-width: 1200px) { .tc-grid-3, .tc-grid-2 { grid-template-columns: 1fr; } }

.tc-card { padding: 16px; }
.tc-card-flush { padding: 0; }
.tc-ct { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
.tc-card-flush .tc-ct { padding: 14px 16px 0; }
.tc-ct .mud-icon-root { color: var(--mud-palette-text-secondary); }
.tc-ct-title { font-size: 15px; font-weight: 700; color: var(--mud-palette-text-primary); }
.tc-ct-right { margin-left: auto; display: flex; gap: 6px; align-items: center; }

.tc-who { display: flex; gap: 12px; align-items: center; }
.tc-avatar {
    width: 48px; height: 48px; border-radius: 50%;
    background: var(--tip-accent-soft); color: var(--mud-palette-primary);
    display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px;
}
.tc-who-name { font-size: 17px; font-weight: 700; }
.tc-who-sub { color: var(--mud-palette-text-secondary); font-size: 12.5px; }
.tc-kv { display: grid; grid-template-columns: 96px 1fr; gap: 6px 10px; margin-top: 12px; font-size: 13px; }
.tc-kv > div:nth-child(odd) { color: var(--mud-palette-text-secondary); }

.tc-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--mud-palette-lines-default); font-size: 13px; }
.tc-row:first-child { border-top: 0; }
.tc-row-text { flex: 1; min-width: 0; }
.tc-row-text small { display: block; color: var(--mud-palette-text-secondary); font-size: 12px; margin-top: 1px; }
.tc-open { display: inline-flex; align-items: center; gap: 3px; font-size: 12.5px; font-weight: 600; color: var(--tip-link); text-decoration: none; white-space: nowrap; }
.tc-open:hover { text-decoration: underline; }
.tc-open:focus-visible { outline: 2px solid var(--tip-focus-ring); outline-offset: 2px; }
.tc-open .mud-icon-root { font-size: 14px; }
.tc-muted { color: var(--mud-palette-text-secondary); font-size: 12px; }

/* True Context AI brief card (issue #1725, Step A spec items 3 to 6; mockup .ns-ai). */
.tc-brief p { margin: 0 0 8px; line-height: 1.55; font-size: 13.5px; }
.tc-brief ul { margin: 4px 0 0; padding-left: 18px; line-height: 1.6; font-size: 13.5px; }
.tc-brief-flags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.tc-brief-age { font-size: 11px; color: var(--mud-palette-text-secondary); white-space: nowrap; }
.tc-brief .tc-ct { min-height: 32px; }
.tc-brief-refresh-wrap { display: inline-flex; align-items: center; }

.tc-fchips { display: flex; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }
.tc-fchip {
    height: 26px; padding: 0 11px; border-radius: 13px; font-size: 12px; font-weight: 600;
    border: 1px solid var(--mud-palette-lines-default); display: inline-flex; align-items: center; cursor: pointer;
    color: var(--mud-palette-text-secondary); background: var(--mud-palette-surface);
}
.tc-fchip-on { background: var(--mud-palette-primary); color: var(--tip-on-primary); border-color: var(--mud-palette-primary); }

.tc-tl { position: relative; padding-left: 20px; }
.tc-tl::before { content: ""; position: absolute; left: 6px; top: 6px; bottom: 6px; width: 2px; background: var(--mud-palette-lines-default); }
.tc-ev { position: relative; padding: 6px 0 10px; font-size: 13px; }
.tc-ev::before {
    content: ""; position: absolute; left: -19px; top: 10px; width: 10px; height: 10px; border-radius: 50%;
    background: var(--mud-palette-surface); border: 2px solid var(--mud-palette-primary);
}
.tc-ev-date { color: var(--mud-palette-text-secondary); font-size: 11.5px; margin-top: 2px; }

.tc-banner .mud-alert-message { flex: 1; min-width: 0; }
.tc-banner-num { font-weight: 700; font-size: 15px; }
.tc-banner-right { margin-left: auto; display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }

/* True Context write actions (issue #1739, Wave 6 Step A spec; mockup .ns-dry, .ns-quick, .ns-slot, .ns-diff, .ns-rdrawer). */
.tc-dry {
    display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 4px;
    font-size: 10.5px; font-weight: 800; letter-spacing: .4px; white-space: nowrap;
    background: var(--tip-status-warn-bg); color: var(--tip-status-warn-fg); border: 1px solid var(--tip-status-warn-border);
}
.tc-sectl { margin: 14px 0 4px; font-size: 11.5px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; color: var(--mud-palette-text-secondary); }
.tc-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.tc-quick { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tc-quick .mud-button-root { justify-content: flex-start; }
.tc-write-results { margin-top: 10px; }
.tc-slot {
    display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin: 8px 0;
    border: 1px solid var(--mud-palette-lines-default); border-radius: 6px; font-size: 13px;
}
.tc-slot-sel { border-color: var(--mud-palette-primary); background: var(--tip-accent-soft); }
.tc-slot-select { max-width: 170px; }
.tc-diff {
    font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; line-height: 1.6; margin-top: 10px; padding: 10px;
    background: var(--mud-palette-background-gray); border: 1px solid var(--mud-palette-lines-default); border-radius: 6px;
}
.tc-diff-add { color: var(--tip-status-ok-fg); }
.tc-diff-old { color: var(--mud-palette-text-secondary); }
/* The drawer renders inside the page content, so as a plain temporary drawer it is absolute and as tall as the page.
   Fixed to the viewport, the header and the Save footer stay on screen and only the body scrolls (issue #1759 W2).
   It uses the surface color like the other cards, not the nav drawer gray (W1). */
.tc-wrapup.mud-drawer { display: flex; flex-direction: column; position: fixed; top: 0; bottom: 0; height: 100vh; height: 100dvh; max-height: 100dvh; background-color: var(--mud-palette-surface); z-index: calc(var(--mud-zindex-appbar) + 2); }
.tc-wrapup .mud-drawer-content { display: flex; flex-direction: column; height: 100%; }
.tc-wrapup-hd { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-bottom: 1px solid var(--mud-palette-lines-default); }
.tc-wrapup-title { flex: 1; font-size: 17px; font-weight: 700; }
.tc-wrapup-bd { flex: 1; overflow: auto; padding: 12px 20px; }
.tc-wrapup-ft { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--mud-palette-lines-default); }
.tc-log-tabs .mud-tab { min-width: 0; padding: 9px 11px; font-size: 11.5px; letter-spacing: .3px; }

/* True Context search, call card and codes (issue #1747, Wave 7 Step A spec; mockup .ns-result, .ns-hit, .ns-snack, .ns-steps, .ns-tbl). */
.tc-result { margin-top: 12px; }
.tc-result-hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-bottom: 6px; }
.tc-result-name { font-weight: 700; font-size: 15px; }
.tc-hit { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--mud-palette-lines-default); font-size: 13px; }
.tc-hit .tc-row-text { flex: 1; min-width: 0; }
.tc-call-card { margin-top: 12px; margin-left: auto; max-width: 420px; }
.tc-steps { list-style: none; margin: 12px 0 0; padding: 0; font-size: 13px; }
.tc-steps li { display: flex; align-items: center; gap: 8px; padding: 4px 0; color: var(--mud-palette-text-secondary); }
.tc-steps li.done { color: var(--tip-status-ok-fg); }
.tc-steps li.now { color: var(--mud-palette-text-primary); font-weight: 600; }
.tc-codes td, .tc-codes th { font-size: 13px; vertical-align: middle; }
.tc-codes .tc-code { font-weight: 700; white-space: nowrap; }

/* True Context Connector Map (issue #1754, Wave 8a Step A spec; mockup .ns-mapper, .palette, .canvas, .node, .edge, .inspector). */
.tc-map { display: grid; grid-template-columns: 220px minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
@media (max-width: 1199px) { .tc-map { grid-template-columns: 200px minmax(0, 1fr); } .tc-map-side { grid-column: 1 / -1; } }
.tc-map-conn { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--mud-palette-lines-default); font-size: 13px; }
.tc-map-conn .tc-row-text { flex: 1; min-width: 0; }
.tc-map-conn.off { color: var(--mud-palette-text-secondary); }
.tc-map-canvas { position: relative; min-height: 640px; overflow: auto; border-radius: 8px;
    background-color: var(--mud-palette-background-gray);
    background-image: radial-gradient(var(--mud-palette-lines-default) 1px, transparent 1px); background-size: 20px 20px; }
.tc-map-canvas svg[data-edges] { position: absolute; left: 0; top: 0; overflow: visible; }
.tc-map-edge { fill: none; stroke: var(--mud-palette-text-secondary); stroke-width: 2; cursor: pointer; pointer-events: stroke; }
.tc-map-edge.fuzzy { stroke-dasharray: 6 5; }
.tc-map-edge.phone { stroke-dasharray: 2 4; }
.tc-map-edge.inactive { stroke-dasharray: 1 6; stroke-linecap: round; }
.tc-map-edge:focus-visible { outline: none; stroke: var(--tip-focus-ring); stroke-width: 4; }
.tc-map-edge.sel { stroke: var(--mud-palette-primary); stroke-width: 3.5; }
.tc-map-label { font-size: 11px; fill: var(--mud-palette-text-secondary); cursor: pointer; paint-order: stroke; stroke: var(--mud-palette-background-gray); stroke-width: 3px; }
.tc-map-label.sel { fill: var(--mud-palette-primary); font-weight: 700; }
.tc-map-node { position: absolute; width: 190px; border-radius: 8px; background: var(--mud-palette-surface); box-shadow: var(--mud-elevation-2);
    border: 1px solid var(--mud-palette-lines-default); user-select: none; touch-action: none; cursor: grab; outline: none; }
.tc-map-node:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--tip-focus-ring); }
.tc-map-node.tc-dragging { cursor: grabbing; box-shadow: var(--mud-elevation-8); }
.tc-map-node.picking { box-shadow: 0 0 0 3px var(--mud-palette-primary); }
.tc-map-node .tc-map-nh { padding: 6px 10px; border-radius: 8px 8px 0 0; color: var(--tip-src-fg); font-size: 12px; font-weight: 700; }
.tc-map-node.hub { cursor: default; }
.tc-map-node.hub .tc-map-nh { background: var(--mud-palette-primary); color: var(--tip-on-primary); }
.tc-map-node ul { list-style: none; margin: 0; padding: 6px 10px 8px; font-size: 12px; }
.tc-map-node li { display: flex; align-items: center; gap: 4px; padding: 1px 0; }
.tc-map-node li.key { font-weight: 700; }
.tc-map-legend { position: absolute; left: 12px; bottom: 10px; display: flex; gap: 14px; font-size: 11px; color: var(--mud-palette-text-secondary); }
.tc-map-legend svg line { stroke: var(--mud-palette-text-secondary); stroke-width: 2; }
.tc-map-result { margin-top: 8px; padding: 8px 10px; border-radius: 6px; background: var(--mud-palette-background-gray); font-size: 12px; }
.tc-map-result li { padding: 2px 0; }
.tc-map-error { color: var(--mud-palette-error); font-size: 13px; }
.tc-map-row { display: flex; justify-content: space-between; gap: 8px; padding: 6px 0; border-top: 1px solid var(--mud-palette-lines-default); font-size: 13px; }

/* True Context transfer context (issue #1792, Step A spec in docs/feat-issue-1629/transfer-context-component-spec.md). */
.tc-xfer-sub { color: var(--mud-palette-text-secondary); font-size: 12.5px; margin: -4px 0 6px; }
.tc-xfer-desc { color: var(--mud-palette-text-secondary); font-size: 12px; margin-top: 6px; }
.tc-xfer-opt { display: flex; align-items: center; gap: 10px; width: 100%; }
.tc-xfer-opt small { display: block; color: var(--mud-palette-text-secondary); font-size: 11.5px; }
.tc-xfer-ic { width: 28px; height: 28px; border-radius: 50%; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    background: var(--mud-palette-background-gray); color: var(--mud-palette-text-secondary); font-size: 11.5px; font-weight: 700; }
.tc-xfer-ic .mud-icon-root { font-size: 16px; }
.tc-xfer-steps { list-style: none; margin: 6px 0 0; padding: 0; }
.tc-xfer-steps li { display: flex; align-items: center; gap: 10px; padding: 6px 0; font-size: 13.5px; color: var(--mud-palette-text-secondary); }
.tc-xfer-step-ic { width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    font-size: 12px; background: var(--mud-palette-background-gray); color: var(--mud-palette-text-secondary); border: 1px solid var(--mud-palette-lines-default); }
.tc-xfer-step-ic .mud-icon-root { font-size: 15px; }
.tc-xfer-steps li.done, .tc-xfer-steps li.now, .tc-xfer-steps li.fail { color: var(--mud-palette-text-primary); }
.tc-xfer-steps li.now { font-weight: 600; }
.tc-xfer-steps li.done .tc-xfer-step-ic { color: var(--tip-status-ok-fg); border-color: var(--tip-status-ok-border); background: var(--tip-status-ok-bg); }
.tc-xfer-steps li.now .tc-xfer-step-ic { color: var(--mud-palette-primary); border-color: var(--mud-palette-primary); background: var(--tip-accent-soft); }
.tc-xfer-steps li.fail .tc-xfer-step-ic { color: var(--tip-status-fail-fg); border-color: var(--tip-status-fail-border); background: var(--tip-status-fail-bg); }
.tc-xfer-hold { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 10px 12px; border-radius: 8px; font-size: 13px;
    background: var(--mud-palette-background-gray); border: 1px solid var(--mud-palette-lines-default); }
.tc-xfer-hold .tc-row-text { flex: 1; }
.tc-xfer-spin { width: 14px; height: 14px; }
.tc-xfer-chip { margin: 0 0 8px 0; gap: 8px; }
.tc-xfer-chip .tc-xfer-ic { width: 22px; height: 22px; font-size: 11px; }
