﻿:root {
    --shell-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-font-size: 15px;
    --shell-page-background: radial-gradient(circle at top right, rgba(13, 110, 253, 0.14), transparent 28%), linear-gradient(180deg, #f7faff 0%, #eef4ff 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(255, 255, 255, 0.14), transparent 22%), linear-gradient(180deg, #0d6efd 0%, #0b5ed7 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0d6efd 0%, #0b5ed7 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0d6efd 0%, #0b5ed7 100%);
    --shell-surface-background: rgba(255, 255, 255, 0.88);
    --shell-panel-background: linear-gradient(145deg, #ffffff 0%, #f7faff 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #ffffff 0%, #f5f8ff 100%);
    --shell-item-background: rgba(255, 255, 255, 0.08);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.04);
    --shell-item-hover-background: rgba(255, 255, 255, 0.14);
    --shell-footer-background: rgba(20, 39, 79, 0.96);
    --shell-text-primary: #1b2a41;
    --shell-text-secondary: #5f718d;
    --shell-text-inverse: #ffffff;
    --shell-text-muted-inverse: rgba(234, 242, 255, 0.8);
    --shell-border: rgba(13, 110, 253, 0.14);
    --shell-border-strong: rgba(13, 110, 253, 0.22);
    --shell-shadow: 0 18px 48px rgba(13, 41, 98, 0.12);
    --shell-shadow-strong: 0 24px 60px rgba(13, 41, 98, 0.18);
    --shell-sidebar-shadow: 18px 0 40px rgba(13, 41, 98, 0.18);
    --shell-header-shadow: 0 10px 28px rgba(13, 41, 98, 0.16);
    --shell-button-primary: #0d6efd;
    --shell-button-primary-hover: #0b5ed7;
    --shell-button-secondary-bg: #ffffff;
    --shell-button-secondary-text: #0d6efd;
    --shell-button-secondary-border: rgba(13, 110, 253, 0.24);
    --shell-pill-bg: #e7f0ff;
    --shell-pill-text: #0d6efd;
    --shell-field-border: #cfdbf3;
    --shell-loader-bg: linear-gradient(180deg, #f4f8ff 0%, #edf3ff 100%);
    --shell-loader-border: rgba(13, 110, 253, 0.16);
    --shell-loader-spinner: #0d6efd;
    --shell-error-bg: #fff7ef;
    --shell-error-border: #f4d1b5;
    --shell-error-text: #8d4d11;
    --shell-focus-ring: rgba(13, 110, 253, 0.18);
    --shell-contrast-surface-bg: rgba(255, 255, 255, 0.92);
    --shell-contrast-surface-bg-strong: rgba(255, 255, 255, 0.88);
    --shell-contrast-surface-text: #1b2a41;
    --shell-contrast-surface-text-muted: #5f718d;
    --shell-login-field-background: rgba(255, 255, 255, 0.96);
    --shell-login-field-border: #cfdbf3;
    --shell-login-field-text: #1b2a41;
    --shell-login-field-text-muted: #5f718d;
    --shell-input-background: var(--shell-login-field-background);
    --shell-input-border: var(--shell-login-field-border);
    --shell-input-text: var(--shell-login-field-text);
    --shell-input-text-muted: var(--shell-login-field-text-muted);

    /* Semantic status tokens — unified across every dialog's warn/ok/info/error
       pill and banner styling. Previously each dialog (BillByBill, CostCentre,
       CostSheet) copy-pasted the same hex values, which broke on dark and
       high-contrast themes. Centralising lets one edit propagate everywhere. */
    --shell-status-warn-bg:     #fff4e5;
    --shell-status-warn-border: #ffb74d;
    --shell-status-warn-text:   #bf360c;
    --shell-status-warn-accent: #ff9800;
    --shell-status-ok-bg:       #e8f5e9;
    --shell-status-ok-border:   #81c784;
    --shell-status-ok-text:     #1b5e20;
    --shell-status-ok-accent:   #4caf50;
    --shell-status-error-bg:    #fde7e7;
    --shell-status-error-border:#d32f2f;
    --shell-status-error-text:  #b71c1c;
    --shell-status-info-bg:     #e3f2fd;
    --shell-status-info-border: #1976d2;
    --shell-status-info-text:   #0d47a1;
}

/* ── Alias tokens ────────────────────────────────────────────────────────
   The payroll-family pages (salary payment, notifications, batch pay bill,
   leave, claims, time management ...) reference these SHORTER names - which
   were never defined, so every var() fell back to its hardcoded light-mode
   literal and the pages rendered white panels under light text on the dark
   themes. Defined ONCE here, chained to the real tokens: each theme block
   redefines the real token on the same html element, and the chain picks the
   themed value up at the use site, so every alias follows every theme with
   no per-file edits. New styles should use the REAL tokens directly. */
:root {
    --shell-surface: var(--shell-panel-background);
    --shell-surface-alt: var(--shell-panel-background-soft);
    --shell-text: var(--shell-text-primary);
    --shell-accent: var(--shell-button-primary);
    --shell-accent-soft: var(--shell-pill-bg);
    --shell-status-success-bg: var(--shell-status-ok-bg);
    --shell-status-success-text: var(--shell-status-ok-text);
    --shell-status-success-border: var(--shell-status-ok-border);

    /* The full sweep (sessions' worth of pages, 17 more names found by
       checking every var(--shell-...) in the component CSS against what is
       actually defined here): */
    --shell-app-background: var(--shell-page-background);
    --shell-border-color: var(--shell-border);
    --shell-border-subtle: var(--shell-border);
    --shell-danger: var(--shell-status-error-text);
    --shell-muted-text: var(--shell-text-secondary);
    --shell-primary: var(--shell-button-primary);
    --shell-shadow-subtle: var(--shell-shadow);
    --shell-status-ok: var(--shell-status-ok-text);
    --shell-success: var(--shell-status-ok-text);
    --shell-surface-elevated: var(--shell-panel-background);
    --shell-surface-muted: var(--shell-panel-background-soft);
    --shell-text-muted: var(--shell-text-secondary);
    --shell-warning: var(--shell-status-warn-text);
    --shell-warning-background: var(--shell-status-warn-bg);
    --shell-warning-border: var(--shell-status-warn-border);
    --shell-warning-subtle: var(--shell-status-warn-bg);
    --shell-warning-surface: var(--shell-status-warn-bg);
}

html[data-theme-family="bootstrap"][data-theme-appearance="dark"] {
    --shell-page-background: radial-gradient(circle at top right, rgba(110, 168, 254, 0.12), transparent 26%), linear-gradient(180deg, #0f1728 0%, #111b30 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(110, 168, 254, 0.12), transparent 24%), linear-gradient(180deg, #1f2a44 0%, #172033 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(110, 168, 254, 0.12), transparent 24%), linear-gradient(135deg, #24304d 0%, #172033 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(110, 168, 254, 0.12), transparent 24%), linear-gradient(135deg, #24304d 0%, #172033 100%);
    --shell-surface-background: rgba(18, 25, 40, 0.88);
    --shell-panel-background: linear-gradient(145deg, #172033 0%, #1c2740 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #172033 0%, #1a2440 100%);
    --shell-item-background: rgba(255, 255, 255, 0.05);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.03);
    --shell-item-hover-background: rgba(255, 255, 255, 0.1);
    --shell-footer-background: rgba(11, 16, 28, 0.96);
    --shell-text-primary: #eef4ff;
    --shell-text-secondary: #b8c7df;
    --shell-text-inverse: #ffffff;
    --shell-text-muted-inverse: rgba(232, 239, 252, 0.78);
    --shell-border: rgba(147, 197, 253, 0.14);
    --shell-border-strong: rgba(147, 197, 253, 0.28);
    --shell-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
    --shell-shadow-strong: 0 24px 60px rgba(0, 0, 0, 0.32);
    --shell-sidebar-shadow: 18px 0 40px rgba(0, 0, 0, 0.32);
    --shell-header-shadow: 0 10px 28px rgba(0, 0, 0, 0.24);
    --shell-button-primary: #6ea8fe;
    --shell-button-primary-hover: #8bb9ff;
    --shell-button-secondary-bg: rgba(255, 255, 255, 0.08);
    --shell-button-secondary-text: #eef4ff;
    --shell-button-secondary-border: rgba(255, 255, 255, 0.16);
    --shell-pill-bg: rgba(110, 168, 254, 0.18);
    --shell-pill-text: #cfe2ff;
    --shell-field-border: rgba(184, 199, 223, 0.22);
    --shell-loader-bg: linear-gradient(180deg, #172033 0%, #1e2a46 100%);
    --shell-loader-border: rgba(147, 197, 253, 0.22);
    --shell-loader-spinner: #8bb9ff;
    --shell-error-bg: rgba(141, 77, 17, 0.18);
    --shell-error-border: rgba(244, 209, 181, 0.22);
    --shell-error-text: #ffd7b2;
    --shell-focus-ring: rgba(110, 168, 254, 0.25);
    --shell-login-field-background: rgba(255, 255, 255, 0.08);
    --shell-login-field-border: rgba(184, 199, 223, 0.24);
    --shell-login-field-text: #eef4ff;
    --shell-login-field-text-muted: #d6e2f5;

    /* Status tokens — translucent fills on dark so the panel gradient shows
       through instead of dropping a jarring bright card onto the surface. */
    --shell-status-warn-bg:     rgba(255, 152, 0, 0.18);
    --shell-status-warn-border: rgba(255, 183, 77, 0.42);
    --shell-status-warn-text:   #ffcc80;
    --shell-status-warn-accent: #ffb74d;
    --shell-status-ok-bg:       rgba(76, 175, 80, 0.18);
    --shell-status-ok-border:   rgba(129, 199, 132, 0.42);
    --shell-status-ok-text:     #a5d6a7;
    --shell-status-ok-accent:   #81c784;
    --shell-status-error-bg:    rgba(211, 47, 47, 0.22);
    --shell-status-error-border:rgba(239, 154, 154, 0.45);
    --shell-status-error-text:  #ef9a9a;
    --shell-status-info-bg:     rgba(25, 118, 210, 0.20);
    --shell-status-info-border: rgba(144, 202, 249, 0.45);
    --shell-status-info-text:   #90caf9;
}

html[data-theme-family="fluent2"][data-theme-appearance="light"] {
    --shell-font-family: "Segoe UI Variable Text", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-font-size: 14.75px;
    --shell-page-background: radial-gradient(circle at top right, rgba(15, 108, 189, 0.12), transparent 28%), linear-gradient(180deg, #f7fbff 0%, #eef6ff 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(255, 255, 255, 0.18), transparent 22%), linear-gradient(180deg, #0f6cbd 0%, #115ea3 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0f6cbd 0%, #115ea3 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0f6cbd 0%, #115ea3 100%);
    --shell-footer-background: rgba(16, 56, 93, 0.96);
    --shell-button-primary: #0f6cbd;
    --shell-button-primary-hover: #115ea3;
    --shell-button-secondary-text: #0f6cbd;
    --shell-button-secondary-border: rgba(15, 108, 189, 0.24);
    --shell-pill-bg: #dff0ff;
    --shell-pill-text: #0f6cbd;
    --shell-field-border: #c5dcf2;
    --shell-loader-border: rgba(15, 108, 189, 0.16);
    --shell-loader-spinner: #0f6cbd;
    --shell-focus-ring: rgba(15, 108, 189, 0.18);
}

html[data-theme-family="fluent2"][data-theme-appearance="dark"] {
    --shell-font-family: "Segoe UI Variable Text", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-font-size: 14.75px;
    --shell-page-background: radial-gradient(circle at top right, rgba(96, 165, 250, 0.12), transparent 26%), linear-gradient(180deg, #111827 0%, #172033 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(96, 165, 250, 0.14), transparent 22%), linear-gradient(180deg, #1d3557 0%, #16263d 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(96, 165, 250, 0.12), transparent 24%), linear-gradient(135deg, #1d3557 0%, #16263d 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(96, 165, 250, 0.12), transparent 24%), linear-gradient(135deg, #1d3557 0%, #16263d 100%);
    --shell-surface-background: rgba(17, 24, 39, 0.88);
    --shell-panel-background: linear-gradient(145deg, #16263d 0%, #1b314d 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #16263d 0%, #1d3557 100%);
    --shell-item-background: rgba(255, 255, 255, 0.05);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.03);
    --shell-item-hover-background: rgba(255, 255, 255, 0.1);
    --shell-footer-background: rgba(10, 16, 26, 0.96);
    --shell-text-primary: #eff6ff;
    --shell-text-secondary: #b8c7dd;
    --shell-border: rgba(125, 211, 252, 0.14);
    --shell-border-strong: rgba(125, 211, 252, 0.28);
    --shell-button-primary: #60a5fa;
    --shell-button-primary-hover: #93c5fd;
    --shell-button-secondary-bg: rgba(255, 255, 255, 0.08);
    --shell-button-secondary-text: #eff6ff;
    --shell-button-secondary-border: rgba(255, 255, 255, 0.16);
    --shell-pill-bg: rgba(96, 165, 250, 0.18);
    --shell-pill-text: #dbeafe;
    --shell-field-border: rgba(184, 199, 221, 0.22);
    --shell-loader-bg: linear-gradient(180deg, #16263d 0%, #1d3557 100%);
    --shell-loader-border: rgba(96, 165, 250, 0.22);
    --shell-loader-spinner: #93c5fd;
    --shell-error-bg: rgba(141, 77, 17, 0.18);
    --shell-error-border: rgba(244, 209, 181, 0.22);
    --shell-error-text: #ffd7b2;
    --shell-focus-ring: rgba(96, 165, 250, 0.25);
    --shell-login-field-background: rgba(255, 255, 255, 0.08);
    --shell-login-field-border: rgba(184, 199, 221, 0.24);
    --shell-login-field-text: #eff6ff;
    --shell-login-field-text-muted: #d8e4f4;
}

html[data-theme-family="fluent2-highcontrast"][data-theme-appearance="highcontrast"] {
    --shell-font-family: "Segoe UI Variable Text", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-page-background: linear-gradient(180deg, #000000 0%, #111111 100%);
    --shell-sidebar-background: linear-gradient(180deg, #000000 0%, #111111 100%);
    --shell-header-background: linear-gradient(135deg, #000000 0%, #111111 100%);
    --shell-hero-background: linear-gradient(135deg, #000000 0%, #111111 100%);
    --shell-surface-background: rgba(0, 0, 0, 0.94);
    --shell-panel-background: linear-gradient(145deg, #000000 0%, #121212 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #000000 0%, #151515 100%);
    --shell-item-background: rgba(255, 255, 255, 0.03);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.02);
    --shell-item-hover-background: rgba(255, 255, 255, 0.1);
    --shell-footer-background: rgba(0, 0, 0, 0.98);
    --shell-text-primary: #ffffff;
    --shell-text-secondary: #f7f7f7;
    --shell-text-inverse: #ffffff;
    --shell-text-muted-inverse: rgba(255, 255, 255, 0.88);
    --shell-border: rgba(255, 255, 255, 0.4);
    --shell-border-strong: #ffd939;
    --shell-button-primary: #ffd939;
    --shell-button-primary-hover: #ffe36f;
    --shell-button-secondary-bg: #000000;
    --shell-button-secondary-text: #ffffff;
    --shell-button-secondary-border: #ffd939;
    --shell-pill-bg: #ffd939;
    --shell-pill-text: #000000;
    --shell-field-border: #ffd939;
    --shell-loader-bg: linear-gradient(180deg, #000000 0%, #121212 100%);
    --shell-loader-border: rgba(255, 217, 57, 0.4);
    --shell-loader-spinner: #ffd939;
    --shell-error-bg: #200000;
    --shell-error-border: #ff9a9a;
    --shell-error-text: #ffffff;
    --shell-focus-ring: rgba(255, 217, 57, 0.32);
    --shell-login-field-background: #000000;
    --shell-login-field-border: #ffd939;
    --shell-login-field-text: #ffffff;
    --shell-login-field-text-muted: #ffffff;
}

html[data-theme-family="material3"][data-theme-appearance="light"] {
    --shell-font-family: "Roboto", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-page-background: radial-gradient(circle at top right, rgba(103, 80, 164, 0.14), transparent 28%), linear-gradient(180deg, #faf7ff 0%, #f4efff 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(255, 255, 255, 0.16), transparent 22%), linear-gradient(180deg, #6750a4 0%, #5b4692 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #6750a4 0%, #5b4692 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #6750a4 0%, #5b4692 100%);
    --shell-footer-background: rgba(61, 49, 96, 0.96);
    --shell-button-primary: #6750a4;
    --shell-button-primary-hover: #5b4692;
    --shell-button-secondary-text: #6750a4;
    --shell-button-secondary-border: rgba(103, 80, 164, 0.24);
    --shell-pill-bg: #ede6ff;
    --shell-pill-text: #6750a4;
    --shell-field-border: #d8cfed;
    --shell-loader-border: rgba(103, 80, 164, 0.16);
    --shell-loader-spinner: #6750a4;
    --shell-focus-ring: rgba(103, 80, 164, 0.18);
}

html[data-theme-family="material3"][data-theme-appearance="dark"] {
    --shell-font-family: "Roboto", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-page-background: radial-gradient(circle at top right, rgba(208, 188, 255, 0.12), transparent 26%), linear-gradient(180deg, #1d1b20 0%, #241f2c 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(208, 188, 255, 0.12), transparent 22%), linear-gradient(180deg, #332d41 0%, #241f2c 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(208, 188, 255, 0.12), transparent 24%), linear-gradient(135deg, #332d41 0%, #241f2c 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(208, 188, 255, 0.12), transparent 24%), linear-gradient(135deg, #332d41 0%, #241f2c 100%);
    --shell-surface-background: rgba(29, 27, 32, 0.88);
    --shell-panel-background: linear-gradient(145deg, #241f2c 0%, #2f2738 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #241f2c 0%, #2a2333 100%);
    --shell-item-background: rgba(255, 255, 255, 0.05);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.03);
    --shell-item-hover-background: rgba(255, 255, 255, 0.1);
    --shell-footer-background: rgba(20, 18, 24, 0.96);
    --shell-text-primary: #f4eff4;
    --shell-text-secondary: #d1c5d8;
    --shell-border: rgba(208, 188, 255, 0.14);
    --shell-border-strong: rgba(208, 188, 255, 0.28);
    --shell-button-primary: #d0bcff;
    --shell-button-primary-hover: #e7ddff;
    --shell-button-secondary-bg: rgba(255, 255, 255, 0.08);
    --shell-button-secondary-text: #f4eff4;
    --shell-button-secondary-border: rgba(255, 255, 255, 0.16);
    --shell-pill-bg: rgba(208, 188, 255, 0.18);
    --shell-pill-text: #f4eff4;
    --shell-field-border: rgba(209, 197, 216, 0.22);
    --shell-loader-bg: linear-gradient(180deg, #241f2c 0%, #332d41 100%);
    --shell-loader-border: rgba(208, 188, 255, 0.22);
    --shell-loader-spinner: #e7ddff;
    --shell-error-bg: rgba(141, 77, 17, 0.18);
    --shell-error-border: rgba(244, 209, 181, 0.22);
    --shell-error-text: #ffd7b2;
    --shell-focus-ring: rgba(208, 188, 255, 0.24);
    --shell-login-field-background: rgba(255, 255, 255, 0.08);
    --shell-login-field-border: rgba(209, 197, 216, 0.24);
    --shell-login-field-text: #f4eff4;
    --shell-login-field-text-muted: #e1d6e6;
}

html[data-theme-family="tailwind3"][data-theme-appearance="light"] {
    --shell-font-family: "Inter", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-font-size: 15.25px;
    --shell-page-background: radial-gradient(circle at top right, rgba(14, 165, 233, 0.14), transparent 28%), linear-gradient(180deg, #f0fdfa 0%, #ecfeff 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(255, 255, 255, 0.16), transparent 22%), linear-gradient(180deg, #0f766e 0%, #0f766e 45%, #0891b2 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0f766e 0%, #0891b2 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.16), transparent 24%), linear-gradient(135deg, #0f766e 0%, #0891b2 100%);
    --shell-footer-background: rgba(15, 118, 110, 0.96);
    --shell-button-primary: #0f766e;
    --shell-button-primary-hover: #115e59;
    --shell-button-secondary-text: #0f766e;
    --shell-button-secondary-border: rgba(15, 118, 110, 0.24);
    --shell-pill-bg: #d1fae5;
    --shell-pill-text: #0f766e;
    --shell-field-border: #b8e5df;
    --shell-loader-border: rgba(15, 118, 110, 0.16);
    --shell-loader-spinner: #0f766e;
    --shell-focus-ring: rgba(15, 118, 110, 0.18);
}

html[data-theme-family="tailwind3"][data-theme-appearance="dark"] {
    --shell-font-family: "Inter", "Segoe UI", Helvetica, Arial, sans-serif;
    --shell-font-size: 15.25px;
    --shell-page-background: radial-gradient(circle at top right, rgba(45, 212, 191, 0.12), transparent 26%), linear-gradient(180deg, #0f172a 0%, #111827 100%);
    --shell-sidebar-background: radial-gradient(circle at top left, rgba(45, 212, 191, 0.12), transparent 22%), linear-gradient(180deg, #134e4a 0%, #0f172a 100%);
    --shell-header-background: radial-gradient(circle at top right, rgba(45, 212, 191, 0.12), transparent 24%), linear-gradient(135deg, #134e4a 0%, #0f172a 100%);
    --shell-hero-background: radial-gradient(circle at top right, rgba(45, 212, 191, 0.12), transparent 24%), linear-gradient(135deg, #134e4a 0%, #0f172a 100%);
    --shell-surface-background: rgba(15, 23, 42, 0.88);
    --shell-panel-background: linear-gradient(145deg, #111827 0%, #162033 100%);
    --shell-panel-background-soft: linear-gradient(180deg, #111827 0%, #162033 100%);
    --shell-item-background: rgba(255, 255, 255, 0.05);
    --shell-item-background-subtle: rgba(255, 255, 255, 0.03);
    --shell-item-hover-background: rgba(255, 255, 255, 0.1);
    --shell-footer-background: rgba(2, 6, 23, 0.96);
    --shell-text-primary: #ecfeff;
    --shell-text-secondary: #bfe9e5;
    --shell-border: rgba(45, 212, 191, 0.14);
    --shell-border-strong: rgba(45, 212, 191, 0.28);
    --shell-button-primary: #2dd4bf;
    --shell-button-primary-hover: #5eead4;
    --shell-button-secondary-bg: rgba(255, 255, 255, 0.08);
    --shell-button-secondary-text: #ecfeff;
    --shell-button-secondary-border: rgba(255, 255, 255, 0.16);
    --shell-pill-bg: rgba(45, 212, 191, 0.18);
    --shell-pill-text: #ccfbf1;
    --shell-field-border: rgba(191, 233, 229, 0.22);
    --shell-loader-bg: linear-gradient(180deg, #111827 0%, #134e4a 100%);
    --shell-loader-border: rgba(45, 212, 191, 0.22);
    --shell-loader-spinner: #5eead4;
    --shell-error-bg: rgba(141, 77, 17, 0.18);
    --shell-error-border: rgba(244, 209, 181, 0.22);
    --shell-error-text: #ffd7b2;
    --shell-focus-ring: rgba(45, 212, 191, 0.24);
    --shell-login-field-background: rgba(255, 255, 255, 0.08);
    --shell-login-field-border: rgba(191, 233, 229, 0.24);
    --shell-login-field-text: #ecfeff;
    --shell-login-field-text-muted: #cfeee9;
}

html:not([data-theme-appearance]),
html[data-theme-appearance="light"] {
    color-scheme: light;
}

html[data-theme-appearance="dark"],
html[data-theme-appearance="highcontrast"] {
    color-scheme: dark;
}

html,
body {
    font-family: var(--shell-font-family);
    font-size: var(--shell-font-size);
}

body {
    background: var(--shell-page-background);
    color: var(--shell-text-primary);
}

body .e-control,
body .e-control input,
body .e-control textarea,
body .e-control button,
body .e-popup,
body .e-popup .e-list-item {
    font-family: var(--shell-font-family);
    font-size: var(--shell-font-size);
}

.app-branding {
    display: grid;
    gap: 0.12rem;
    line-height: 1;
}

.app-branding--center {
    justify-items: center;
    text-align: center;
}

.app-branding__title {
    font-size: 1.7rem;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.02em;
}

/* The small "v12.0" beside the large product name (user layout call
   2026-09-03: name large, version small). Sits INSIDE the title line so
   it rides the name's baseline, but resets the display sizing. */
.app-branding__version {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: normal;
    opacity: 0.92;
}

.app-branding__subtitle {
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.2;
    opacity: 0.92;
}

@media (max-width: 575.98px) {
    .app-branding__title {
        font-size: 1.45rem;
    }
}

h1:focus {
    outline: none;
}

a,
.btn-link {
    color: var(--shell-button-primary);
}

.btn-primary {
    color: #fff;
    background-color: var(--shell-button-primary);
    border-color: var(--shell-button-primary);
}

.btn:focus,
.btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--shell-focus-ring);
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    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;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3dy53My5vcmcvMTk5OS94bGluayIgb3ZlcmZsb3c9ImhpZGRlbiI+PGRlZnM+PGNsaXBQYXRoIGlkPSJjbGlwMCI+PHJlY3QgeD0iMjM1IiB5PSI1MSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjQ5Ii8+PC9jbGlwUGF0aD48L2RlZnM+PGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwKSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTIzNSAtNTEpIj48cGF0aCBkPSJNMjYzLjUwNiA1MUMyNjQuNzE3IDUxIDI2NS44MTMgNTEuNDgzNyAyNjYuNjA2IDUyLjI2NThMMjY3LjA1MiA1Mi43OTg3IDI2Ny41MzkgNTMuNjI4MyAyOTAuMTg1IDkyLjE4MzEgMjkwLjU0NSA5Mi43OTUgMjkwLjY1NiA5Mi45OTZDMjkwLjg3NyA5My41MTMgMjkxIDk0LjA4MTUgMjkxIDk0LjY3ODIgMjkxIDk3LjA2NTEgMjg5LjAzOCA5OSAyODYuNjE3IDk5TDI0MC4zODMgOTlDMjM3Ljk2MyA5OSAyMzYgOTcuMDY1MSAyMzYgOTQuNjc4MiAyMzYgOTQuMzc5OSAyMzYuMDMxIDk0LjA4ODYgMjM2LjA4OSA5My44MDcyTDIzNi4zMzggOTMuMDE2MiAyMzYuODU4IDkyLjEzMTQgMjU5LjQ3MyA1My42Mjk0IDI1OS45NjEgNTIuNzk4NSAyNjAuNDA3IDUyLjI2NThDMjYxLjIgNTEuNDgzNyAyNjIuMjk2IDUxIDI2My41MDYgNTFaTTI2My41ODYgNjYuMDE4M0MyNjAuNzM3IDY2LjAxODMgMjU5LjMxMyA2Ny4xMjQ1IDI1OS4zMTMgNjkuMzM3IDI1OS4zMTMgNjkuNjEwMiAyNTkuMzMyIDY5Ljg2MDggMjU5LjM3MSA3MC4wODg3TDI2MS43OTUgODQuMDE2MSAyNjUuMzggODQuMDE2MSAyNjcuODIxIDY5Ljc0NzVDMjY3Ljg2IDY5LjczMDkgMjY3Ljg3OSA2OS41ODc3IDI2Ny44NzkgNjkuMzE3OSAyNjcuODc5IDY3LjExODIgMjY2LjQ0OCA2Ni4wMTgzIDI2My41ODYgNjYuMDE4M1pNMjYzLjU3NiA4Ni4wNTQ3QzI2MS4wNDkgODYuMDU0NyAyNTkuNzg2IDg3LjMwMDUgMjU5Ljc4NiA4OS43OTIxIDI1OS43ODYgOTIuMjgzNyAyNjEuMDQ5IDkzLjUyOTUgMjYzLjU3NiA5My41Mjk1IDI2Ni4xMTYgOTMuNTI5NSAyNjcuMzg3IDkyLjI4MzcgMjY3LjM4NyA4OS43OTIxIDI2Ny4zODcgODcuMzAwNSAyNjYuMTE2IDg2LjA1NDcgMjYzLjU3NiA4Ni4wNTQ3WiIgZmlsbD0iI0ZGRTUwMCIgZmlsbC1ydWxlPSJldmVub2RkIi8+PC9nPjwvc3ZnPg==) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

.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: var(--shell-button-primary);
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
}

.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");
}

code {
    color: #c02d76;
}

.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder,
.form-floating > .form-control:focus::placeholder {
    text-align: start;
}

body .e-sidebar,
body .e-sidebar.e-left,
body .e-sidebar.e-right,
body .e-sidebar.e-open,
body .e-sidebar.e-close,
body .e-sidebar.e-push,
body .e-sidebar.e-slide,
body .e-sidebar.e-over,
body .e-sidebar.e-dock,
body .e-sidebar.app-sidebar,
body .app-sidebar.e-sidebar,
body .app-sidebar,
body .e-sidebar .e-sidebar-content,
body .app-sidebar .e-sidebar-content,
body .app-sidebar__surface {
    background: var(--shell-sidebar-background) !important;
    border: none !important;
}

.e-sidebar-context,
.e-sidebarcontainer,
.e-sidebar-overflow {
    background: transparent !important;
}

.app-sidebar .e-sidebar-content,
.app-sidebar__surface,
.app-sidebar .nav-shell {
    background: transparent !important;
}

body .login-page .field__input.e-control-wrapper,
body .login-page .field__input.e-control-wrapper.e-float-input,
body .login-page .field__input.e-input-group,
body .login-page .field__input.e-input-group.e-control-wrapper,
body .login-page .field__input.e-float-input {
    background: var(--shell-login-field-background) !important;
    border-color: var(--shell-login-field-border) !important;
    box-shadow: none !important;
}

body .login-page .field__input input,
body .login-page .field__input input.e-input,
body .login-page .field__input .e-input {
    color: var(--shell-login-field-text) !important;
    -webkit-text-fill-color: var(--shell-login-field-text) !important;
    caret-color: var(--shell-login-field-text) !important;
    background: transparent !important;
}

body .login-page .field__input input::placeholder,
body .login-page .field__input input.e-input::placeholder {
    color: var(--shell-login-field-text-muted) !important;
    opacity: 1 !important;
}

body .login-page .field__input label.e-float-text,
body .login-page .field__input label.e-float-text.e-label-top {
    color: var(--shell-text-inverse) !important;
}

body .app-textbox.e-control-wrapper,
body .app-textbox.e-control-wrapper.e-float-input,
body .app-textbox.e-input-group,
body .app-textbox.e-input-group.e-control-wrapper,
body .app-textbox.e-float-input {
    background: var(--shell-input-background) !important;
    border-color: var(--shell-input-border) !important;
    box-shadow: none !important;
}

body .app-textbox input,
body .app-textbox input.e-input,
body .app-textbox .e-input {
    color: var(--shell-input-text) !important;
    -webkit-text-fill-color: var(--shell-input-text) !important;
    caret-color: var(--shell-input-text) !important;
    background: transparent !important;
}

body .app-textbox input::placeholder,
body .app-textbox input.e-input::placeholder {
    color: var(--shell-input-text-muted) !important;
    opacity: 1 !important;
}

body .app-textbox input:-webkit-autofill,
body .app-textbox input:-webkit-autofill:hover,
body .app-textbox input:-webkit-autofill:focus,
body .app-textbox input.e-input:-webkit-autofill,
body .app-textbox input.e-input:-webkit-autofill:hover,
body .app-textbox input.e-input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--shell-input-text) !important;
    caret-color: var(--shell-input-text) !important;
    box-shadow: 0 0 0 1000px var(--shell-input-background) inset !important;
}

body .app-textbox label.e-float-text,
body .app-textbox label.e-float-text.e-label-top {
    color: var(--shell-input-text-muted) !important;
}

body .app-textbox--inverse-label label.e-float-text,
body .app-textbox--inverse-label label.e-float-text.e-label-top {
    color: var(--shell-input-text-muted) !important;
}

html[data-theme-appearance="dark"] body .app-textbox--inverse-label label.e-float-text,
html[data-theme-appearance="dark"] body .app-textbox--inverse-label label.e-float-text.e-label-top,
html[data-theme-appearance="highcontrast"] body .app-textbox--inverse-label label.e-float-text,
html[data-theme-appearance="highcontrast"] body .app-textbox--inverse-label label.e-float-text.e-label-top {
    color: var(--shell-text-inverse) !important;
}



body .e-filter-popup.e-popup-open,
body .e-gridpopup.e-popup-open,
body .e-xlflmenu.e-popup-open,
body .e-filtermenudiv.e-popup-open {
    z-index: 10001 !important;
}

/* Pivot Field List dialog – ensure it renders above dashboard cards */
body .e-pivotfieldlist-wrapper,
body .e-pivotfieldlist-container,
body .e-member-editor-dialog.e-dialog,
body .e-pivot-field-list-dialog.e-dialog {
    z-index: 10001 !important;
}

body .e-pivotfieldlist-wrapper.e-dialog .e-dlg-header-content {
    z-index: 10002 !important;
}

/* ── Global Compact Grid ── */
.e-grid .e-row,
.e-grid .e-altrow {
    height: 24px !important;
}
.e-grid .e-rowcell {
    padding: 2px 6px !important;
    font-size: 0.78rem;
    line-height: 1.2;
}
/* CONVENTION (all grids): header captions WRAP onto multiple lines instead of
   truncating with an ellipsis, at a slightly smaller font, so long headers like
   "Is Allow Finished Goods Receipt" stay readable. Syncfusion defaults the header
   text to nowrap + ellipsis, so the wrapping props need !important to win. */
.e-grid .e-headercell {
    padding: 4px 6px !important;
    font-size: 0.72rem;
    height: auto !important;
    white-space: normal !important;
    vertical-align: middle;
}
.e-grid .e-headercell .e-headercelldiv,
.e-grid .e-headercell .e-headertext {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    line-height: 1.2 !important;
    height: auto !important;
}
.e-grid .e-summarycell {
    padding: 2px 6px !important;
}

/* CONVENTION (all masters): status / validation messages are COMPACT — a small,
   left-aligned line, never large centred text. Use `master-status` (+ the error/ok
   modifier) on the status <div>. Global so every master picks it up. */
/* CONVENTION: the explanatory line at the top of a dialog / panel renders as
   an INFO NOTE (ⓘ badge + tinted card), never as a bare grey paragraph —
   `<p class="dialog-hint">…</p>`. One global rule so every dialog matches. */
/* NOTE: block + absolutely-positioned badge, NEVER display:flex — flex turns
   inline children (<em>, <code>) into separate flex items, which shatters the
   sentence into columns. */
.dialog-hint {
    position: relative;
    display: block;
    /* breathing room above so the note never sits flush against the dialog
       header / the element before it */
    margin: 0.5rem 0 0.3rem;
    padding: 0.5rem 0.7rem 0.5rem 2.05rem;
    font-size: 0.8rem;
    line-height: 1.45;
    color: #35506d;
    background: rgba(11, 87, 208, 0.055);
    border: 1px solid rgba(11, 87, 208, 0.18);
    border-left: 3px solid rgba(11, 87, 208, 0.5);
    border-radius: 0.35rem;
}
.dialog-hint::before {
    content: "i";
    position: absolute;
    left: 0.68rem;
    top: 0.58rem;
    width: 15px;
    height: 15px;
    font-family: Georgia, "Times New Roman", serif;
    font-style: italic;
    font-weight: 700;
    font-size: 0.72rem;
    line-height: 15px;
    text-align: center;
    color: #fff;
    background: #3b7ddd;
    border-radius: 50%;
}
/* UI labels referenced inside a hint read better semibold than italic. */
.dialog-hint em {
    font-style: normal;
    font-weight: 600;
    color: #23405c;
}
.dialog-hint code {
    font-size: 0.76rem;
    padding: 0 0.2rem;
    background: rgba(11, 87, 208, 0.1);
    border-radius: 0.2rem;
}

/* CONVENTION: status messages render as COLORED PANELS by severity with a
   dismiss (✕) button — via the shared MasterStatusBanner component. */
.master-status {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    font-size: 0.8rem;
    line-height: 1.3;
    text-align: left;
    margin: 0.15rem 0 0.35rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid transparent;
    border-radius: 0.45rem;
}
.master-status--error { color: var(--shell-status-error-text, #b3261e); background: rgba(179, 38, 30, 0.08); border-color: rgba(179, 38, 30, 0.35); }
.master-status--ok { color: var(--shell-status-ok, #137333); background: rgba(19, 115, 51, 0.08); border-color: rgba(19, 115, 51, 0.35); }
.master-status--warning { color: #8a6d00; background: rgba(202, 164, 7, 0.12); border-color: rgba(202, 164, 7, 0.4); }
.master-status--info { color: #0b57d0; background: rgba(11, 87, 208, 0.08); border-color: rgba(11, 87, 208, 0.35); }
.master-status__text { flex: 1 1 auto; min-width: 0; word-break: break-word; }

/* CONVENTION: a save reports EVERY problem at once — the banner gets a
   "\n"-joined message and renders the lines as a NUMBERED list under a short
   lead-in, so the operator fixes everything in one pass instead of meeting one
   error per save. Colour is inherited from the severity modifier. */
.master-status__lead { font-weight: 600; margin: 0 0 0.2rem; }
.master-status__list {
    list-style: decimal outside;
    margin: 0;
    padding: 0 0 0 1.35rem;
    color: inherit;
}
.master-status__list > li {
    margin: 0 0 0.12rem;
    padding-left: 0.1rem;
    /* numbers must stay visible — they are the operator's checklist */
    list-style: decimal outside;
}
.master-status__list > li::marker { color: inherit; font-weight: 600; }
.master-status__list > li:last-child { margin-bottom: 0; }

.master-status__close {
    flex: 0 0 auto;
    background: transparent;
    border: none;
    color: inherit;
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1;
    padding: 0 0.1rem;
    opacity: 0.7;
}
.master-status__close:hover { opacity: 1; }

/* CONVENTION: the SAME dismiss (✕) inside a status host that is NOT the banner
   — an SfMessage panel or a plain `<div class="…__error">` — rendered by the
   shared StatusMessageText component when a host wires OnClose. The host keeps
   supplying its own padding, background and colour; this row only lays the
   text/numbered list and the ✕ side by side, so the button sits at the panel's
   top-right and never overlaps the list numbers (which hang in the list's own
   left gutter). Colour is inherited from the host panel. */
.status-msg {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    text-align: left;
    color: inherit;
    /* Hosts that are themselves flex rows (the dialog error lines) must let this
       row take the free width, or the ✕ would sit against the text instead of
       the panel's right edge. Ignored by block hosts. */
    flex: 1 1 auto;
    min-width: 0;
}
.status-msg__body { flex: 1 1 auto; min-width: 0; word-break: break-word; }
.status-msg__close { margin-left: auto; align-self: flex-start; }

/* A newly shown banner pulses briefly so the message is noticed (the shared
   component also scrolls it into view when it is off screen). */
@keyframes master-status-flash {
    0%, 100% { box-shadow: 0 0 0 0 rgba(90, 100, 114, 0); }
    18% { box-shadow: 0 0 0 4px rgba(90, 100, 114, 0.3); }
    55% { box-shadow: 0 0 0 4px rgba(90, 100, 114, 0.12); }
}
.master-status--flash { animation: master-status-flash 0.9s ease-out 2; }
@media (prefers-reduced-motion: reduce) {
    .master-status--flash { animation: none; }
}

/* ── Master pages — STANDARD HEADER BANNER (convention) ──────────────────
   Every master/transaction page opens with this banner inside master-sticky-top:
     <header class="prod-master__header">
       <div>
         <p class="prod-master__eyebrow">Master Setup</p>
         <h1>{Page Title}</h1>
         <p>{one-line purpose}</p>
       </div>
       <div class="prod-master__header-meta">
         <div class="prod-master__meta-card"><span>{Total X}</span><strong>{n}</strong></div>
         <div class="prod-master__meta-card"><span>Mode</span><strong>{View/Add/Modify}</strong></div>
       </div>
     </header>
   followed by the pinned toolbar row (Find/Add/Modify/Delete/Save/Cancel).
   Global so any page gets it without scoped CSS. ProductMaster is the visual
   reference (its scoped .razor.css mirrors these rules; keep both in sync). */
.prod-master__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--shell-border);
    border-radius: 1.35rem;
    background: var(--shell-hero-background);
    box-shadow: var(--shell-shadow);
    color: var(--shell-text-inverse);
}
.prod-master__eyebrow,
.prod-master__panel-eyebrow {
    margin: 0 0 0.35rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    opacity: 0.8;
}
.prod-master__header h1 {
    margin: 0;
    font-size: 1.75rem;
    line-height: 1.1;
}
.prod-master__header p {
    margin: 0.55rem 0 0;
    max-width: 48rem;
    color: var(--shell-text-muted-inverse);
}
/* One ROW of cards, however many there are. This was a fixed 2-column grid
   capped at 260px, so a header with three cards (Attendance entry, Pay Bill,
   Product Browser, Notification Log, Variant Attributes, Customer Points)
   wrapped its third onto a second line. Auto columns follow the card count, so
   two-card headers keep the width they had and three-card ones sit on one
   line.
   A column is never narrower than what it holds: with a fixed 110px floor
   under a 420px cap, a large amount ("71,252,059.26" on Linked Transactions)
   spilled out of its card. Cards stay equal width (1fr = the widest one's
   content) and the row may take the header's full width before it squeezes. */
.prod-master__header-meta {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(max-content, 1fr);
    gap: 0.75rem;
    width: auto;
    max-width: 100%;
    flex-shrink: 0;
}

/* Narrow viewports have no room for three across - wrap rather than squeeze
   the cards below a readable width. */
@media (max-width: 640px) {
    .prod-master__header-meta {
        grid-auto-flow: row;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        max-width: 100%;
    }
}
.prod-master__meta-card,
.prod-master__record-badge {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.8rem 0.9rem;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 1rem;
    background: rgba(255, 255, 255, 0.08);
    color: var(--shell-text-inverse);
}
.prod-master__meta-card span,
.prod-master__record-badge {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}
.prod-master__meta-card { min-width: 110px; }
/* Figures line up and stay on one line; only when the card is genuinely
   narrower than the figure (the two-column phone layout) does it wrap -
   inside its card, never over the border. */
.prod-master__meta-card strong {
    font-size: 1.1rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
@media (max-width: 640px) {
    .prod-master__meta-card { min-width: 0; }
    .prod-master__meta-card strong { white-space: normal; overflow-wrap: anywhere; }
}
/* Record badge sits on a light panel outside the banner — needs dark text. */
.prod-master__panel-head .prod-master__record-badge {
    border-color: var(--shell-border);
    background: var(--shell-panel-background-soft, rgba(0, 0, 0, 0.04));
    color: var(--shell-text-primary);
}
@media (max-width: 760px) {
    .prod-master__header { flex-direction: column; }
    .prod-master__header-meta { width: 100%; }
}

/* Busy chip on master toolbars ("Saving…" / "Loading…" / "Deleting…") —
   visible progress feedback while a server round-trip runs (buttons alone
   just grey out). Shared by all masters (BOM is the reference). */
.master-busy {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    align-self: center;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--shell-text-secondary, #555);
    white-space: nowrap;
}
.master-busy__spinner {
    width: 0.95rem;
    height: 0.95rem;
    flex: 0 0 auto;
    border: 2px solid rgba(128, 128, 128, 0.35);
    border-top-color: var(--shell-button-primary, #0d6efd);
    border-radius: 50%;
    animation: master-busy-spin 0.7s linear infinite;
}
@keyframes master-busy-spin { to { transform: rotate(360deg); } }

/* ──────────────────────────────────────────────────────────────────
   Numeric inputs — right-aligned (accounting convention)
   ------------------------------------------------------------------
   Every SfNumericTextBox value is right-aligned, app-wide: amounts,
   quantities, rates, balances read column-like the way ledgers do.
   Single global rule (grid-header-wrap precedent) so current AND
   future pages inherit it with no per-page CSS. !important because
   Syncfusion styles the input element directly. */
input.e-numerictextbox,
.e-input-group input.e-numerictextbox {
    text-align: right !important;
}

/* ──────────────────────────────────────────────────────────────────
   Master pages — pinned action toolbar
   ------------------------------------------------------------------
   Every master page's action toolbar (Find / Add / Modify / Delete /
   Save / Cancel) carries the `master-sticky-toolbar` class so it stays
   visible while the long record form scrolls. Defined here (global, not
   component-scoped) so current AND future masters get it just by adding
   the class — no per-page CSS.

   How it works: the scrolling ancestor is `.app-tabhost__panel--active`
   (overflow:auto, ~1.15rem gutter). `position:sticky; top:0` pins the bar
   to the top of that scrollport. The negative inline margin + matching
   padding bleed the opaque backdrop out to the panel's gutter edges so
   scrolled content can't peek beside the buttons.
   ────────────────────────────────────────────────────────────────── */
.master-sticky-toolbar {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--shell-page-background);
    margin-inline: -1.15rem;
    padding-inline: 1.15rem;
    padding-block: 0.5rem;
    box-shadow: 0 8px 14px -12px rgba(0, 0, 0, 0.45);
}

/* ──────────────────────────────────────────────────────────────────
   Master page layout: a FIXED top region (header card + status message +
   action toolbar) that never scrolls, over a scrolling body. The form
   pane and the user-guide pane each get their OWN scrollbar. Applies to
   all masters (current and future) via these global classes:
     master-page   → on the outer <section> (flex column, fills panel)
     master-shell  → on the inner shell div (flex column)
     master-sticky-top → wraps header + message + toolbar (fixed, no scroll)
     master-body   → on the content area (form + guide); panes scroll
     master-body--scroll → when the body itself is the scroll surface
                           (e.g. a tabbed master with no guide pane)
   ────────────────────────────────────────────────────────────────── */
/* `!important` on the structural properties only — the per-master scoped
   CSS (e.g. `.xyz-master { display:block }`) is more specific, so the
   flex-height chain must force-win to establish the fixed-top / scrolling-
   body layout. Visual styling stays in the scoped CSS. */
.master-page {
    height: 100% !important;
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
}
.master-shell {
    flex: 1 1 auto !important;
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
}

/* Fixed top region — does NOT scroll with the body. */
.master-sticky-top {
    flex: 0 0 auto !important;
    position: static !important;
    z-index: 21;
    background: var(--shell-page-background);
    margin-inline: -1.15rem;
    padding-inline: 1.15rem;
    padding-top: 0.25rem;
    box-shadow: 0 10px 16px -14px rgba(0, 0, 0, 0.5);
}
.master-sticky-top .master-sticky-toolbar {
    position: static;
    margin-inline: 0;
    padding-inline: 0;
    box-shadow: none;
    background: transparent;
}

/* Scrolling body. The body clips; its direct children (the form pane and
   the user-guide pane) scroll independently. */
.master-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow: hidden !important;
}
.master-body > section,
.master-body > aside {
    min-height: 0 !important;
    max-height: 100% !important;
    overflow-y: auto !important;
    /* Vertical scrolling ONLY: overflow-y:auto silently computes overflow-x
       to auto as well, which put a page-wide horizontal scrollbar under
       forms. Anything genuinely wide (SfGrid, tables) scrolls inside its
       own container instead. */
    overflow-x: hidden !important;
}
/* Multiline Address/Description boxes: vertical resize only — a sideways
   drag would overflow the pane (whose horizontal scrolling is off). */
.app-textbox textarea,
.e-input-group textarea.e-input {
    resize: vertical;
}

/* When the body is itself the single scroll surface (no separate panes). */
.master-body.master-body--scroll {
    overflow-y: auto !important;
}

/* ──────────────────────────────────────────────────────────────────
   Help panel docks RIGHT — global safety net (2026-08-16).

   .ct-page__help is flex-SIZED globally (flex-basis var(--invnet-help-w)),
   but that only works inside a flex row, and .master-body is not one by
   itself. Historically every master carried its own scoped
   `display:flex` on the body; the five payroll masters shipped without
   it and their guides rendered full-width BELOW the form. This rule
   removes the per-page obligation: any master-body that directly
   contains a help aside becomes a flex row automatically.

   Scoped one level with :has(> …) so it cannot fire on the older
   grid-layout masters (their asides use per-page __panel classes, not
   ct-page__help) or on --scroll bodies (excluded, and none carries a
   guide today). Existing scoped flex rules keep winning on specificity;
   this is the floor, not an override. */
.master-body:not(.master-body--scroll):has(> .ct-page__help) {
    display: flex;
    gap: 1rem;
    align-items: stretch;
    min-height: 0;
}

/* ...and the guide sits at the RIGHT EDGE of that row, always.

   The row only pushes the aside right when the content beside it grows into
   the leftover width. Content that sizes to itself - a grid whose columns are
   content-sized, a wizard capped at its reading measure - stops short, and on
   a wide screen the guide ends up marooned in the middle of the canvas with
   dead space beyond it. An auto inline-start margin absorbs whatever is left
   over, so the aside is flush right whether the content filled the row or
   not; where the content already fills it, there is no free space and this
   does nothing. */
.master-body:not(.master-body--scroll):has(> .ct-page__help) > .ct-page__help {
    margin-inline-start: auto;
}

/* PANELS RUN TO THE RIGHT EDGE - every page (user rule, 2026-09-21).

   The form pane of a master / transaction page takes ALL the width the guide leaves it, and the panels inside
   it stretch across that pane - a panel that sizes to its content stops short and leaves a dead strip on its
   right. Written with :where() so it carries NO specificity: it is the floor every page stands on, and a page
   that deliberately sizes a pane (a list column beside a form, the wizard's reading measure) keeps its own
   rule. Fieldsets get min-inline-size:0 because a fieldset otherwise refuses to be narrower - or, in a flex
   column, wider - than its content. */
:where(.master-body:not(.master-body--scroll)) > :where(section:not(.wizard)) {
    flex: 1 1 auto;
    min-width: 0;
}
:where(.master-body) > :where(section:not(.wizard)) > :where(fieldset, div, form, section) {
    align-self: stretch;
    justify-self: stretch;
    max-width: none;
    box-sizing: border-box;
}
:where(.master-body) :where(fieldset) { min-inline-size: 0; }

/* The wizard keeps its 860px reading measure - a form this narrow is the
   point - and grows INTO it rather than sizing to whatever its current step
   happens to contain. Past that cap it stays CENTRED, because a form pinned
   to the left of a wide monitor leaves the eye crossing a few hundred pixels
   of nothing to reach the guide.

   Centring and a right-edge guide are the same mechanism here, not two: flex
   distributes leftover space equally among the auto margins in the row, so
   the wizard's own pair takes half to each side, and the aside that follows
   the right one has nowhere to sit but the edge. That only holds while those
   two are the ONLY autos in the row - the aside's own margin rule below has
   to stand down for it, which is what the next rule does. */
.master-body:not(.master-body--scroll):has(> .ct-page__help) > .wizard {
    flex: 1 1 auto;
    margin-inline: auto;
    /* Scrolls itself, for the same reason the sibling rule gives every
       `section` and `aside` in this row a scrollbar: the body CLIPS. A pane
       that does not scroll inside a clipping body simply loses its bottom,
       and a wizard is tall enough to reach it. */
    min-height: 0;
    max-height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
}
.master-body:not(.master-body--scroll):has(> .wizard) > .ct-page__help {
    margin-inline-start: 0;
}

/* Compact the master hero header to roughly the action-bar height (plus a
   little): tighter padding, smaller title, the verbose description hidden,
   and slimmer meta cards. Targets the header inside the fixed top region so
   it applies to every master (the `__eyebrow` / `__meta-card` suffixes are
   shared across all prefixes). */
.master-sticky-top > header {
    padding-block: 0.4rem !important;
    align-items: center !important;
    border-radius: 0.85rem !important;
}
.master-sticky-top > header h1 {
    font-size: 1.1rem !important;
    line-height: 1.15 !important;
}
.master-sticky-top > header [class*="__eyebrow"] {
    margin-bottom: 0.05rem !important;
    font-size: 0.6rem !important;
}
/* The description paragraph (the class-less <p> after the title) is dropped
   to keep the header compact. */
.master-sticky-top > header > div > p:not([class]) {
    display: none !important;
}
.master-sticky-top > header [class*="__meta-card"] {
    padding: 0.3rem 0.7rem !important;
}
.master-sticky-top > header [class*="__meta-card"] span {
    font-size: 0.58rem !important;
}
.master-sticky-top > header [class*="__meta-card"] strong {
    font-size: 0.95rem !important;
}

/* Product master multicolumn combo popups: no fixed width — the popup
   defaults to the combobox textbox width and expands beyond it, but never
   narrower than this minimum (so the two-column Name|Description layout
   stays readable). Syncfusion copies the combobox CssClass onto its popup,
   so `prod-mc-popup` lands on the popup element. */
.e-popup.prod-mc-popup {
    min-width: 22rem;
}

/* Auto-fitted multi-column popup columns. Pages declare fixed proportional
   tracks inline ("1fr 1.2fr" and friends), which truncate the value column
   while an empty description column still claims its share of the width.
   initComboPopupFitWidth (layout.js) measures the widest first-column value
   across every row, pins it as --mc-col1 and stamps `mc-fitted`; the value
   column then takes exactly what it needs and the remainder goes to the
   description. !important because the tracks are declared inline.
   Applies to BOTH popup families — the shared .app-mc-* rows and the
   inline-styled ones (Product master and friends). */
.e-popup.mc-fitted .e-list-item > div,
.e-popup.mc-fitted .e-ddl-header > div,
.e-popup.mc-fitted .app-mc-row,
.e-popup.mc-fitted .app-mc-head {
    grid-template-columns: var(--mc-col1) minmax(0, 1fr) !important;
}

/* House style for entity-bound multi-column combo popups (memory:
   feedback_combobox_multicolumn). The popup width is set to 1.5x the control
   via PopupWidth="150%"; this class keeps a readable floor and tidies the
   aligned "value | description/alias" rows. Syncfusion copies the combobox
   CssClass onto its portalled .e-popup, so the rules must live globally.
   Each combo sets its own grid-template-columns inline on the header + rows
   so the two stay column-aligned. */
/* Convention: popup is DOUBLE the control width (PopupWidth="200%" on the
   combo) with a readable ~0.85rem font and roomy rows — matches the reference
   Item Name | Description picker. */
.e-popup.app-mc-popup { min-width: 25rem; font-size: 0.85rem; }
/* Syncfusion sets an explicit font-size on the list items, so a font-size on
   the popup alone only reaches the header (which inherits) — the item rows keep
   Syncfusion's size. Set it on the list item + our row/head cells directly. */
.e-popup.app-mc-popup .e-list-item,
.e-popup.app-mc-popup .app-mc-head,
.e-popup.app-mc-popup .app-mc-row,
.e-popup.app-mc-popup .app-mc-head > span,
.e-popup.app-mc-popup .app-mc-row > span { font-size: 0.85rem; }
/* Comfortable row height (reference-style spacing). */
.e-popup.app-mc-popup .e-list-item { line-height: 1.45; min-height: 0; padding-top: .35rem; padding-bottom: .35rem; }
/* Convention: columns stay inside the popup width and never scroll sideways. */
.e-popup.app-mc-popup .e-content,
.e-popup.app-mc-popup .e-dropdownbase { overflow-x: hidden; }
.e-popup.app-mc-popup .app-mc-head,
.e-popup.app-mc-popup .app-mc-row {
    display: grid;
    gap: .25rem .75rem;
    width: 100%;
    align-items: center;
}
.e-popup.app-mc-popup .app-mc-head {
    font-weight: 600;
    padding: .3rem .75rem;
    border-bottom: 1px solid rgba(128, 128, 128, 0.35);
}
/* One line per cell: overflow truncates with an ellipsis. The key is
   min-width:0 — it lets each grid track shrink below its content so the
   ellipsis appears WITHIN the column instead of the text overlapping the
   next column (grid cells default to min-width:auto, which caused overlap). */
.e-popup.app-mc-popup .app-mc-head > span,
.e-popup.app-mc-popup .app-mc-row > span {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}
.e-popup.app-mc-popup .app-mc-sub { color: var(--shell-text-secondary); }
/* "＋ Create new …" footer action inside an entity-bound combo popup. */
.app-mc-create {
    display: block;
    width: 100%;
    text-align: left;
    padding: .45rem .75rem;
    font-size: 0.8rem;
    font-weight: 600;
    background: transparent;
    border: none;
    border-top: 1px solid rgba(128, 128, 128, 0.35);
    color: var(--shell-button-primary, #0d6efd);
    cursor: pointer;
}
.app-mc-create:hover { background: rgba(13, 110, 253, 0.08); }

/* CONVENTION: master-page switches right-align — label on the left, the
   toggle flush against its column's right edge, so every switch in a section
   lines up vertically. Compact inline switches (e.g. beside an input) opt out
   in the page's scoped CSS with width:auto + justify-content:flex-start. */
.prod-master__switch {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    width: 100%;
}
.prod-master__switch label { font-weight: 600; font-size: 0.85rem; }

/* CONVENTION: every control that is not self-explanatory carries a ONE-LINE
   plain-English hint DIRECTLY UNDER it — small, muted, wrapping, tight to the
   control it explains. Put the <p class="app-field-hint"> immediately after
   the input / switch / grid inside the same field wrapper; the wrapper is the
   page's own (a flex column), only the type styling is global so hints read
   identically on every master. Tokens only — no literal colours — so the hint
   stays legible in dark mode. */
.app-field-hint {
    margin: 0.15rem 0 0;
    font-size: 0.72rem;
    line-height: 1.35;
    font-weight: 400;
    white-space: normal;
    overflow-wrap: anywhere;
    color: var(--shell-text-secondary);
}

/* CONVENTION: a rate / price / amount input the signed-in user may not edit
   (Services/PriceEditGate - "Allow Rate Edit", or an administrator's Tools
   deny tick). Read-only alone is not enough: a read-only box looks almost
   like an editable one, so operators click in and type and nothing happens.
   The locked cell is tinted, shows a not-allowed cursor and no caret, and
   carries a title saying why. Put app-price-locked on the control itself
   (CssClass, which Syncfusion applies to its e-input-group wrapper), or
   app-price-locked-field on a field wrapper that also holds a label - that
   form tints only the box, never the label. Tokens only - the tint is mixed
   from the theme's secondary text colour, so it reads in light and dark. */
.e-input-group.app-price-locked,
.app-price-locked input.e-input,
.app-price-locked-field .e-input-group,
.app-price-locked-field input.e-input {
    background: color-mix(in srgb, var(--shell-text-secondary) 12%, transparent) !important;
    color: var(--shell-text-secondary) !important;
    cursor: not-allowed !important;
    caret-color: transparent !important;
}
.app-price-locked input.e-input:focus,
.app-price-locked-field input.e-input:focus {
    box-shadow: none !important;
}

/* CONVENTION: data-entry grids (master sub-grids, allocation grids) keep a
   ~5-row body (185px) with its own vertical scrollbar, visible even with no
   rows — mirrors the legacy grids' fixed panel height. Set Height="185" on
   the SfGrid (that makes the body fixed + scrollable) AND apply the class
   (CssClass="... app-entry-grid") as the CSS backstop. */
.app-entry-grid .e-gridcontent .e-content {
    min-height: 185px;
    overflow-y: auto !important;
}

/* Focus highlight for Syncfusion switches — applies to every master (current
   and future). The real focus target is the hidden <input class="e-switch">
   inside .e-switch-wrapper, so :focus-within is what fires on keyboard focus;
   .e-focus covers the class Syncfusion toggles on the wrapper itself. */
.e-switch-wrapper:focus-within,
.e-switch-wrapper.e-focus {
    outline: 2px solid var(--shell-button-primary, #0d6efd);
    outline-offset: 3px;
    border-radius: 16px;
    box-shadow: 0 0 0 4px var(--shell-focus-ring, rgba(13, 110, 253, 0.18));
}

/* Right-align numeric text inputs everywhere (the `prod-master__input--num`
   class is only put on numeric cells, so this is safe globally). Covers the
   in-page grids too, not just dialog content — Syncfusion portals dialog
   content to <body>, so the rule lives here globally rather than in scoped CSS. */
.prod-master__input--num input,
.prod-master__input--num .e-input { text-align: right; }

/* Grid aggregate-footer total cells (BOM + other template-editor grids). */
.division-op__grid .e-summaryrow .e-summarycell { font-weight: 600; }
.division-op__agg {
    display: block;
    text-align: right;
    padding-right: .5rem;
    font-weight: 600;
}
.division-op__agg-label {
    font-weight: 600;
    color: var(--shell-text-secondary);
}

/* Division-wise opening — summary pills (mirrors BillByBill's .bbb-summary).
   Colours route through the shared --shell-status-* tokens so dark and
   high-contrast themes flip them automatically. */
.division-op__summary {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 4px 0 10px;
}
.division-op__pill {
    /* --shell-contrast-surface-bg is the LIGHT contrast surface, meant to carry
       DARK text. Paired here with --shell-text-primary it put near-white
       (#eef4ff) on near-white (rgba(255,255,255,.92)) in the dark theme, so the
       Total / Allocated figures on every opening dialog were unreadable while
       only the coloured Remaining pill could be read. The panel surface is the
       one that pairs with primary text in BOTH themes. */
    background: var(--shell-panel-background);
    border: 1px solid var(--shell-border);
    border-radius: 999px;
    padding: 6px 14px;
    display: inline-flex;
    flex-direction: column;
    min-width: 120px;
    color: var(--shell-text-primary);
    box-shadow: var(--shell-shadow-subtle, none);
}
.division-op__pill > span {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--shell-text-secondary);
}
.division-op__pill > strong {
    font-size: 1.02rem;
    font-weight: 700;
}
.division-op__pill--ok {
    background: var(--shell-status-ok-bg);
    border-color: var(--shell-status-ok-border);
    color: var(--shell-status-ok-text);
}
.division-op__pill--ok > span { color: var(--shell-status-ok-text); }
.division-op__pill--warn {
    background: var(--shell-status-warn-bg);
    border-color: var(--shell-status-warn-border);
    color: var(--shell-status-warn-text);
}
.division-op__pill--warn > span { color: var(--shell-status-warn-text); }
.division-op__pill--over {
    background: var(--shell-status-error-bg);
    border-color: var(--shell-status-error-border);
    color: var(--shell-status-error-text);
}
.division-op__pill--over > span { color: var(--shell-status-error-text); }

/* Division dialog — grid footer totals (mirrors BillByBill's .bbb-agg*). */
.division-op__grid .e-gridfooter {
    background: color-mix(in srgb, var(--shell-button-primary) 14%, var(--shell-panel-background));
    border-top: 2px solid var(--shell-button-primary);
}
.division-op__grid .e-summarycell {
    font-weight: 700;
    color: var(--shell-text-primary);
    padding: 4px 6px !important;
}
.division-op__agg-label {
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
    font-size: .78rem;
    color: var(--shell-text-primary);
}
.division-op__agg-sum {
    font-weight: 800;
    font-size: .95rem;
    color: var(--shell-button-primary);
}

/* Opening Batch Inventory — the batch's own expiry, shown read-only beside the
   picker. A date already gone is the thing the operator must not miss, so it
   is the one coloured cell; a compulsory expiry left unset is the master-data
   fault Verify Batch reports, flagged here where it can still be fixed.
   Dialog content is portaled to <body>, so these live globally. */
.batch-op__expiry--past {
    color: var(--shell-status-error-text);
    font-weight: 700;
}
.batch-op__expiry--missing {
    color: var(--shell-status-warn-text);
    font-weight: 700;
}

/* Custom Group dialog — group name row + per-group actions. */
.custom-group__head {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    margin-bottom: .25rem;
}
.custom-group__name { flex: 1 1 auto; min-width: 0; }
.custom-group__head-actions { display: flex; gap: .5rem; flex: 0 0 auto; }

/* Compact inline error line for the division dialog. */
.division-op__error {
    color: var(--shell-status-error-text);
    background: var(--shell-status-error-bg, transparent);
    border-left: 3px solid var(--shell-status-error-border, currentColor);
    padding: .2rem .6rem;
    margin: .25rem 0;
    font-size: .85rem;
    line-height: 1.25;
    border-radius: 4px;
}
/* Compact inline success line (same footprint as the error line). */
.division-op__success {
    color: var(--shell-status-ok-text);
    background: var(--shell-status-ok-bg, transparent);
    border-left: 3px solid var(--shell-status-ok-border, currentColor);
    padding: .2rem .6rem;
    margin: .25rem 0;
    font-size: .85rem;
    line-height: 1.25;
    border-radius: 4px;
}

/* ── Help panel: ONE shared width + drag grip (all pages & dialogs) ─────────
   Every master page's Help aside uses .ct-page__help, but the width used to
   be duplicated per page's scoped CSS (and missing on newer pages, letting
   the panel swallow the screen). This single rule owns it now:
   - default is MINIMAL (300px); the form keeps the space.
   - width comes from --invnet-help-w on :root, so the left-edge drag grip
     (wired in layout.js, no per-page code) resizes EVERY page at once and
     the choice persists via localStorage.
   !important intentionally beats the older per-page scoped flex rules. */
.ct-page__help {
    position: relative;
    flex: 0 0 var(--invnet-help-w, 300px) !important;
    width: auto !important;
    min-width: 240px;
    max-width: 60vw;
    /* Base look, so pages without their own scoped copy render the same. */
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.1rem 1.15rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.6rem;
    background: var(--shell-panel-background-soft, rgba(255, 255, 255, 0.6));
    overflow-y: auto;
    max-height: 100%;
    color: var(--shell-text-primary);
}
.ct-page__help--docked {
    flex: 0 0 56px !important;
    min-width: 0;
    max-width: none;
    padding: 0.9rem 0.55rem;
    overflow: hidden;
}
.ct-page__help-dock {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}
.ct-page__help-dock-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-weight: 600;
    letter-spacing: 0.04em;
}
.ct-page__panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.ct-page__panel-eyebrow {
    margin: 0;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.7;
}
.ct-page__help-intro { margin: 0; font-size: 0.9rem; }
.ct-page__help-content { font-size: 0.86rem; line-height: 1.35; }
.ct-page__help-list { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.4rem; }
.ct-page__help-list li { padding-left: 0.15rem; }

/* Guides name real database objects - FnGetEmpATSummeryForPayBillEx,
   EmpPayBillBatch_Trigger_StatusCascade - and each is ONE unbreakable word.
   The panel is ~300px wide and its pane is overflow-x:hidden, so a name that
   cannot wrap is silently cut off with no scrollbar to reach the rest. Let
   them break; a sideways scrollbar inside a help panel would be worse.
   min-width:0 stops a long word widening the flex column instead of wrapping. */
.ct-page__help,
.ct-page__help-intro,
.ct-page__help-content,
.ct-page__help-list li,
.ct-page__help .e-acrdn-header-content {
    min-width: 0;
    overflow-wrap: anywhere;
}
.ct-page__help-accordion .e-acrdn-header .e-acrdn-header-content {
    font-weight: 600;
}
/* The grip: a strip straddling the panel's left border. Pseudo-element only —
   pointer handling is delegated in layout.js (initHelpPanelResize). */
.ct-page__help:not(.ct-page__help--docked)::before {
    content: "";
    position: absolute;
    left: -6px;
    top: 0;
    bottom: 0;
    width: 12px;
    cursor: col-resize;
    z-index: 5;
    border-radius: 4px;
    background: linear-gradient(to right, transparent 4px, var(--shell-border, #cfd6de) 4px, var(--shell-border, #cfd6de) 6px, transparent 6px);
    opacity: .55;
    transition: opacity .12s ease, background-color .12s ease;
}
.ct-page__help:not(.ct-page__help--docked):hover::before {
    opacity: 1;
}
/* ── List pages: the list and the guide scroll SEPARATELY (2026-09-15) ────
   VoucherTypeListPage, MenuGroupPage, ReportListPage and ReportLauncherPage.
   The page fills the tab's height; the row below its header takes the rest;
   the list scrolls on its own, the guide sits at the right edge and scrolls
   inside itself.
     .list-split-page   column filling the tab (height 100%)
     .list-split        the row: list + guide
     .list-split__main  the list pane, own vertical scrollbar

   INNER SCROLL (.ct-page__help--inner-scroll + .ct-page__help-scroll): the
   aside itself does not scroll, its content does. A scrolling aside clips its
   own ::before grip (it straddles the left border) and scrolls it away with
   the text; this way the same thin grip every help panel has (ProductMaster
   included) runs the full height. */
.list-split-page {
    height: 100%;
    min-height: 0;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
}
.list-split {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    display: flex;
    gap: 1rem;
    align-items: stretch;
}
.list-split__main {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}
/* A pane whose top part (title, search, status) stays put while the
   .list-split__main inside it scrolls - the scrollbar starts BELOW the
   header, not beside it. */
.list-split__pane {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.list-split > .ct-page__help {
    margin-inline-start: auto;
    align-self: stretch;
    max-height: 100%;
}
.ct-page__help.ct-page__help--inner-scroll,
.master-body > aside.ct-page__help--inner-scroll {
    overflow: visible !important;
}
.ct-page__help-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding-right: 0.2rem;
}
@media (max-width: 900px) {
    .list-split-page { height: auto; }
    .list-split { flex-direction: column; }
    .list-split__main { overflow: visible; }
    .list-split__pane { min-height: auto; }
    .list-split > .ct-page__help { margin-inline-start: 0; }
}

/* Small screens stack the columns — full width, no grip. The body must
   actually FLIP to a column here: without it the 100%-wide help sits in a
   flex ROW whose other children shrink to zero (help has flex-shrink 0),
   and the page content vanishes behind an empty full-width help panel —
   exactly what tablet mode showed on the report viewer. */
@media (max-width: 900px) {
    /* Stacked, the BODY becomes the one scroll surface (its base rule is
       overflow:hidden !important - clip-and-pane is a side-by-side idea)
       and the panes take their natural heights inside it. */
    .master-body:not(.master-body--scroll):has(> .ct-page__help) {
        flex-direction: column;
        overflow-y: auto !important;
    }
    /* `.wizard` is listed beside `section` because the create wizard's content
       pane is a div: without it the grow it takes in the side-by-side layout
       would follow it into the stack and pull it vertically. */
    .master-body:not(.master-body--scroll):has(> .ct-page__help) > section,
    .master-body:not(.master-body--scroll):has(> .ct-page__help) > .wizard {
        flex: 0 0 auto !important;
        max-height: none !important;
        overflow-y: visible !important;
    }
    .ct-page__help,
    .ct-page__help--docked {
        flex: 0 0 auto !important;
        width: 100% !important;
        max-width: none;
        min-width: 0;
    }
    /* Stacked, the guide must not crowd out the content above it. */
    .ct-page__help:not(.ct-page__help--docked) {
        max-height: 45vh !important;
    }
    .ct-page__help::before {
        display: none;
    }
    /* Docked in a column = a slim horizontal bar, not a sideways rail. */
    .ct-page__help--docked {
        padding: 0.5rem 0.9rem;
    }
    .ct-page__help-dock {
        flex-direction: row;
        justify-content: space-between;
    }
    .ct-page__help-dock-label {
        writing-mode: horizontal-tb;
        transform: none;
    }
}

/* ── Status row tints in the shared lookup picker (GenericDataLookupDialog) ──
   Hosts opt in via ShowAsync's rowClass callback returning one of these.
   Selected cells keep the selection highlight (:not(.e-active)). */
.inv-find-grid .e-row.lookup-row--inactive .e-rowcell:not(.e-active) {
    background: #ffe3c2;
}
.inv-find-grid .e-row.lookup-row--cancelled .e-rowcell:not(.e-active) {
    background: #ffd2d2;
}

/* ════════════════════════════════════════════════════════════════════════════
   MODERN UI LAYER — every master page (root carries .master-page).
   Rollout of the ProductMaster pilot. COSMETICS ONLY: no positioning, sizing
   mechanics, grid, or keyboard behaviour is touched. Everything keys off the
   shell variables so the theme families keep working. SfDialogs portal to
   <body>, outside .master-page, so dialogs are deliberately unaffected.
   Scoped page CSS loads after this file and still wins where a page differs.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Design tokens ── */
.master-page {
    --pm-radius-lg: 1.25rem;   /* hero, panels   */
    --pm-radius:    0.85rem;   /* cards, buttons */
    --pm-radius-sm: 0.6rem;    /* inputs, chips  */
    --pm-accent: var(--shell-button-primary, #0d6efd);
    --pm-ring: color-mix(in srgb, var(--pm-accent) 22%, transparent);
    --pm-surface: var(--shell-surface-background, rgba(255, 255, 255, 0.9));
    --pm-ease: cubic-bezier(0.2, 0, 0, 1);
    --pm-speed: 150ms;
}

/* One motion language for everything interactive. */
.master-page .e-btn,
.master-page .prod-master__meta-card,
.master-page .prod-master__switch,
.master-page .app-textbox {
    transition: background-color var(--pm-speed) var(--pm-ease),
                border-color     var(--pm-speed) var(--pm-ease),
                box-shadow       var(--pm-speed) var(--pm-ease),
                transform        var(--pm-speed) var(--pm-ease);
}

@media (prefers-reduced-motion: reduce) {
    .master-page * { transition: none !important; }
}

/* ── Hero header: layered, corner highlight, light top edge ── */
.master-page .prod-master__header {
    position: relative;
    overflow: hidden;
    padding: 1.15rem 1.35rem;
    border: none;
    border-radius: var(--pm-radius-lg);
    box-shadow: 0 12px 32px rgba(13, 41, 98, 0.22),
                inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.master-page .prod-master__header::after {
    content: "";
    position: absolute;
    inset: -40% -10% auto auto;
    width: 55%;
    height: 160%;
    background: radial-gradient(closest-side, rgba(255, 255, 255, 0.16), transparent);
    pointer-events: none;
}

.master-page .prod-master__header h1 {
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.master-page .prod-master__header p { font-size: 0.9rem; }

/* Meta cards as frosted stat chips. */
.master-page .prod-master__meta-card {
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: var(--pm-radius);
    background: rgba(255, 255, 255, 0.12);
    backdrop-filter: blur(6px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.master-page .prod-master__meta-card:hover { transform: translateY(-1px); }
.master-page .prod-master__meta-card strong { font-size: 1.25rem; font-weight: 700; }
.master-page .prod-master__meta-card span { opacity: 0.85; }

/* ── Toolbar: glass strip. The sticky mechanics (position, negative margins,
      z-index) live in the base rules above and are NOT repeated here. ── */
.master-page .master-sticky-toolbar {
    background: color-mix(in srgb, var(--pm-surface) 82%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--shell-border);
    box-shadow: 0 8px 18px -14px rgba(13, 41, 98, 0.35);
}

/* Pill buttons inside master toolbars. */
.master-page .master-sticky-toolbar .e-btn {
    min-width: 0;
    padding: 0.5rem 1rem;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.85rem;
    line-height: 1.2;
    box-shadow: none;
}

.master-page .master-sticky-toolbar .e-btn .e-btn-icon {
    font-size: 0.9rem;
    margin-right: 0.45rem;
}

/* Secondary = quiet ghost; colour arrives on hover. */
.master-page .secondary-action.e-btn {
    background: transparent;
    border: 1px solid var(--shell-border-strong);
    color: var(--shell-text-primary);
}

.master-page .secondary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    background: color-mix(in srgb, var(--pm-accent) 8%, transparent);
    border-color: var(--pm-accent);
    color: var(--pm-accent);
}

.master-page .master-sticky-toolbar .secondary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    transform: translateY(-1px);
}

/* Primary = gradient pill with lift. */
.master-page .primary-action.e-btn {
    background: linear-gradient(135deg, var(--pm-accent) 0%, var(--shell-button-primary-hover, #0b5ed7) 100%);
    border: none;
    color: #fff;
    box-shadow: 0 4px 12px var(--pm-ring);
}

.master-page .primary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    box-shadow: 0 8px 18px var(--pm-ring);
}

.master-page .master-sticky-toolbar .primary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    transform: translateY(-1px);
}

/* Danger keeps its red; toolbar geometry gives it the pill. */
.master-page .master-sticky-toolbar .danger-action.e-btn { border-radius: 999px; }

/* Keyboard focus is part of the design. */
.master-page .e-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--pm-ring);
}

.master-page .master-sticky-toolbar .e-btn:disabled,
.master-page .master-sticky-toolbar .e-btn.e-disabled {
    opacity: 0.45;
    transform: none;
    box-shadow: none;
}

/* ── Panels: one card language ── */
.master-page .prod-master__panel {
    border-radius: var(--pm-radius-lg);
    border: 1px solid var(--shell-border);
    background: var(--pm-surface);
    box-shadow: 0 2px 10px rgba(13, 41, 98, 0.05);
}

.master-page .prod-master__panel-head {
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--shell-border);
}

.master-page .prod-master__panel-head h2 {
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.master-page .prod-master__panel-eyebrow { color: var(--pm-accent); opacity: 1; }

/* Record badge as an accent chip. */
.master-page .prod-master__record-badge {
    flex-direction: row;
    align-items: center;
    padding: 0.35rem 0.8rem;
    border: none;
    border-radius: 999px;
    background: var(--shell-pill-bg, #e7f0ff);
    color: var(--shell-pill-text, var(--pm-accent));
    letter-spacing: 0.06em;
}

/* ── Tabs: underline style instead of boxed headers ── */
.master-page .e-tab .e-tab-header {
    background: transparent;
    border-bottom: 1px solid var(--shell-border);
}

.master-page .e-tab .e-tab-header .e-toolbar-item .e-tab-wrap {
    padding: 0.55rem 1rem;
    border-radius: var(--pm-radius-sm) var(--pm-radius-sm) 0 0;
}

.master-page .e-tab .e-tab-header .e-toolbar-item .e-tab-text {
    font-weight: 600;
    font-size: 0.86rem;
    text-transform: none;
    color: var(--shell-text-secondary);
}

.master-page .e-tab .e-tab-header .e-toolbar-item:hover .e-tab-text {
    color: var(--shell-text-primary);
}

.master-page .e-tab .e-tab-header .e-toolbar-item.e-active .e-tab-text {
    color: var(--pm-accent);
    font-weight: 700;
}

.master-page .e-tab .e-tab-header .e-indicator {
    background: var(--pm-accent);
    height: 3px;
    border-radius: 3px 3px 0 0;
}

/* ── Inputs: unified radius + accent focus ring ── */
body .master-page .app-textbox.e-input-group,
body .master-page .app-textbox.e-input-group.e-control-wrapper {
    border-radius: var(--pm-radius-sm) !important;
}

body .master-page .app-textbox.e-input-group.e-input-focus,
body .master-page .app-textbox.e-input-group.e-control-wrapper.e-input-focus {
    border-color: var(--pm-accent) !important;
    box-shadow: 0 0 0 3px var(--pm-ring) !important;
}

/* ── Switch rows: quiet until hovered (base rule further up keeps layout) ── */
.master-page .prod-master__switch {
    border: 1px solid transparent;
    border-radius: var(--pm-radius-sm);
    background: var(--shell-item-background-subtle, rgba(13, 110, 253, 0.03));
    padding: 0.4rem 0.6rem;
}

.master-page .prod-master__switch:hover {
    border-color: var(--shell-border);
    background: color-mix(in srgb, var(--pm-accent) 5%, transparent);
}

/* ── Slim accent scrollbars inside master scroll surfaces ── */
.master-page *::-webkit-scrollbar { width: 8px; height: 8px; }
.master-page *::-webkit-scrollbar-track { background: transparent; }
.master-page *::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--pm-accent) 25%, transparent);
    border-radius: 999px;
}
.master-page *::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--pm-accent) 45%, transparent);
}

/* ════════════════════════════════════════════════════════════════════════════
   MODERN UI LAYER — dialogs (all of them).
   SfDialogs portal to <body>, outside .master-page, so the master layer never
   reaches them. This block targets Syncfusion's STRUCTURAL classes
   (.e-dlg-container / .e-dialog / .e-dlg-overlay), which every dialog carries
   regardless of its CssClass — 364 dialogs, one block. COSMETICS ONLY: no
   sizing, positioning, focus or keyboard behaviour is touched. Scoped page
   CSS still wins where a dialog deliberately differs.
   ════════════════════════════════════════════════════════════════════════ */

/* Tokens again here — dialogs live outside .master-page, where the master
   layer's tokens are declared. */
.e-dlg-container,
.e-dialog {
    --pm-radius:    0.85rem;
    --pm-radius-sm: 0.6rem;
    --pm-accent: var(--shell-button-primary, #0d6efd);
    --pm-ring: color-mix(in srgb, var(--pm-accent) 22%, transparent);
    --pm-ease: cubic-bezier(0.2, 0, 0, 1);
    --pm-speed: 150ms;
}

/* Dimmed, softly blurred backdrop — the dialog reads as the only live layer. */
.e-dlg-overlay {
    background: rgba(10, 18, 34, 0.45);
    backdrop-filter: blur(3px);
}

/* The dialog itself: rounded card with a strong-but-soft elevation. */
.e-dialog {
    border: 1px solid var(--shell-border);
    border-radius: var(--pm-radius);
    overflow: hidden;
    box-shadow: 0 24px 64px rgba(13, 41, 98, 0.28),
                0 4px 16px rgba(13, 41, 98, 0.12);
}

/* Header: keep the theme's identity colour, tighten the typography, and give
   the close icon a hover surface. */
.e-dialog .e-dlg-header-content {
    padding: 0.85rem 1.15rem;
}

.e-dialog .e-dlg-header {
    font-weight: 700;
    letter-spacing: -0.01em;
}

.e-dialog .e-dlg-header-content .e-btn.e-dlg-closeicon-btn {
    border-radius: 999px;
    transition: background-color var(--pm-speed) var(--pm-ease);
}

.e-dialog .e-dlg-header-content .e-btn.e-dlg-closeicon-btn:hover {
    background: rgba(255, 255, 255, 0.18);
}

.e-dialog .e-dlg-content {
    padding: 1rem 1.15rem;
}

/* Buttons inside any dialog: the same pill language as the master toolbars.
   Geometry on .e-btn variants only — layout containers are untouched. */
.e-dlg-container .e-btn,
.e-dialog .e-btn {
    transition: background-color var(--pm-speed) var(--pm-ease),
                border-color     var(--pm-speed) var(--pm-ease),
                box-shadow       var(--pm-speed) var(--pm-ease),
                transform        var(--pm-speed) var(--pm-ease);
}

.e-dialog .primary-action.e-btn,
.e-dialog .secondary-action.e-btn,
.e-dialog .danger-action.e-btn {
    border-radius: 999px;
    font-weight: 600;
    padding: 0.45rem 1rem;
    line-height: 1.2;
}

.e-dialog .primary-action.e-btn .e-btn-icon,
.e-dialog .secondary-action.e-btn .e-btn-icon,
.e-dialog .danger-action.e-btn .e-btn-icon {
    font-size: 0.9rem;
    margin-right: 0.45rem;
}

.e-dialog .secondary-action.e-btn {
    background: transparent;
    border: 1px solid var(--shell-border-strong);
    color: var(--shell-text-primary);
}

.e-dialog .secondary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    background: color-mix(in srgb, var(--pm-accent) 8%, transparent);
    border-color: var(--pm-accent);
    color: var(--pm-accent);
}

.e-dialog .primary-action.e-btn {
    background: linear-gradient(135deg, var(--pm-accent) 0%, var(--shell-button-primary-hover, #0b5ed7) 100%);
    border: none;
    color: #fff;
    box-shadow: 0 4px 12px var(--pm-ring);
}

.e-dialog .primary-action.e-btn:hover:not(:disabled):not(.e-disabled) {
    box-shadow: 0 8px 18px var(--pm-ring);
    transform: translateY(-1px);
}

.e-dialog .primary-action.e-btn:disabled,
.e-dialog .primary-action.e-btn.e-disabled,
.e-dialog .secondary-action.e-btn:disabled,
.e-dialog .secondary-action.e-btn.e-disabled {
    opacity: 0.45;
    transform: none;
    box-shadow: none;
}

.e-dialog .e-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--pm-ring);
}

/* Inputs inside dialogs: same radius + focus ring as the masters. */
body .e-dialog .app-textbox.e-input-group,
body .e-dialog .app-textbox.e-input-group.e-control-wrapper {
    border-radius: var(--pm-radius-sm) !important;
}

body .e-dialog .app-textbox.e-input-group.e-input-focus,
body .e-dialog .app-textbox.e-input-group.e-control-wrapper.e-input-focus {
    border-color: var(--pm-accent) !important;
    box-shadow: 0 0 0 3px var(--pm-ring) !important;
}

/* Hint paragraphs used across the dialogs. */
.e-dialog .dialog-hint {
    color: var(--shell-text-secondary);
    line-height: 1.55;
}

/* Slim accent scrollbars inside dialog content. */
.e-dialog .e-dlg-content::-webkit-scrollbar,
.e-dialog .e-dlg-content *::-webkit-scrollbar { width: 8px; height: 8px; }
.e-dialog .e-dlg-content::-webkit-scrollbar-track,
.e-dialog .e-dlg-content *::-webkit-scrollbar-track { background: transparent; }
.e-dialog .e-dlg-content::-webkit-scrollbar-thumb,
.e-dialog .e-dlg-content *::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--pm-accent) 25%, transparent);
    border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
    .e-dlg-container *, .e-dialog * { transition: none !important; }
}

/* ── Help panel head: never let a long title collide with the toggle ──
   The voucher page titles the guide with the voucher-type name, which can be
   arbitrarily long ("Outward Delivery Challan Guide") — it WRAPS onto the
   next line inside its flex cell instead of running under the button
   (wrap, never ellipsis — same policy as grid headers). Applies on every
   page that mounts the panel (the class names are shared even though each
   page scopes its own layout rules). */
.ct-page__panel-head > div,
.prod-master__panel-head > div,
.custom-entry__panel-head > div {
    min-width: 0;
    flex: 1 1 auto;
}

.ct-page__panel-head h2,
.prod-master__panel-head h2,
.custom-entry__panel-head h2 {
    white-space: normal;
    overflow-wrap: break-word;
}

/* Icon-only show/hide toggle: an exact CIRCLE, same on every page and inside
   embedded dialogs — width equals height, icon centred, never shrinks. */
.ct-page__help-toggle.e-btn,
.prod-master__help-toggle.e-btn,
.custom-entry__help-toggle.e-btn {
    flex: 0 0 auto;
    min-width: 0;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    border-radius: 50%;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.ct-page__help-toggle.e-btn .e-btn-icon,
.prod-master__help-toggle.e-btn .e-btn-icon,
.custom-entry__help-toggle.e-btn .e-btn-icon {
    margin: 0;
    font-size: 0.9rem;
}

/* The docked strip's scoped CSS stretches the button full-width — a circle
   stays a circle there too. The descendant selectors out-specify the scoped
   `.x--docked[b-...] .x-toggle` rules by the extra .e-btn class. */
.ct-page__help--docked .ct-page__help-toggle.e-btn,
.prod-master__panel--docked .prod-master__help-toggle.e-btn,
.prod-master__help--docked .prod-master__help-toggle.e-btn,
.custom-entry__help--docked .custom-entry__help-toggle.e-btn {
    width: 2.1rem;
    height: 2.1rem;
}

/* ── Shared help width for the OTHER panel families ─────────────────────────
   The ct-page__help family already takes its width from --invnet-help-w
   (single rule + drag grip further up in this file). ProductMaster's
   prod-master__help and CustomTableDataEntry's custom-entry__help are the
   same panel by another class name — they join the same variable and grip
   here so EVERY page's help panel has one width and one splitter. Width
   only: their look stays in the scoped page CSS. */
.prod-master__help,
.custom-entry__help {
    position: relative;
    flex: 0 0 var(--invnet-help-w, 300px) !important;
    width: auto !important;
    min-width: 240px;
    max-width: 60vw;
}

.prod-master__help--docked,
.custom-entry__help--docked {
    flex: 0 0 64px !important;
    min-width: 0;
    max-width: none;
}

.prod-master__help:not(.prod-master__help--docked)::before,
.custom-entry__help:not(.custom-entry__help--docked)::before {
    content: "";
    position: absolute;
    left: -6px;
    top: 0;
    bottom: 0;
    width: 12px;
    cursor: col-resize;
    z-index: 5;
    border-radius: 4px;
    background: linear-gradient(to right, transparent 4px, var(--shell-border, #cfd6de) 4px, var(--shell-border, #cfd6de) 6px, transparent 6px);
    opacity: .55;
    transition: opacity .12s ease, background-color .12s ease;
}

.prod-master__help:not(.prod-master__help--docked):hover::before,
.custom-entry__help:not(.custom-entry__help--docked):hover::before {
    opacity: 1;
}

/* Small screens stack the columns — full width, no grip (mirrors the
   ct-page__help rule further up). */
@media (max-width: 900px) {
    .prod-master__help,
    .prod-master__help--docked,
    .custom-entry__help,
    .custom-entry__help--docked {
        flex: 0 0 auto !important;
        width: 100% !important;
        max-width: none;
        min-width: 0;
    }
    .prod-master__help::before,
    .custom-entry__help::before {
        display: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   CUSTOMER PORTAL ADMIN PAGES
   ══════════════════════════════════════════════════════════════════════════
   One block for all eight screens in Pages\Customer Portal rather than the
   same overrides copied into eight scoped stylesheets. Two problems it fixes,
   both specific to these pages:

   1. THE HEADER WAS EATING THE SCREEN. The shared master hero is sized for a
      master-data page you sit on all day. A portal admin screen is a QUEUE —
      the rows are the point, and the banner was pushing them below the fold.
      Everything here is the same design, smaller.

   2. THE FILTERS STACKED ONE PER ROW. Syncfusion inputs render as full-width
      blocks, so a flex-wrap row gave every filter its own line and pushed the
      grid off-screen entirely. They are laid out on a real 3-column grid now.

   Opt in with `portal-admin-page` on the page's root <section> (beside
   master-page) and `portal-filters` on the filter row. Selectors carry both
   classes so they beat the .master-page defaults on specificity rather than
   on source order — this block must keep working if it is ever moved.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Compact hero ─────────────────────────────────────────────────────── */

.master-page.portal-admin-page .prod-master__header {
    padding: 0.65rem 1rem;
    border-radius: 0.9rem;
    align-items: center;
    box-shadow: 0 8px 22px rgba(13, 41, 98, 0.18),
                inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.master-page.portal-admin-page .prod-master__eyebrow {
    margin-bottom: 0.1rem;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
}

.master-page.portal-admin-page .prod-master__header h1 {
    font-size: 1.15rem;
    font-weight: 600;
}

.master-page.portal-admin-page .prod-master__header p {
    margin-top: 0.2rem;
    max-width: 78rem;
    font-size: 0.76rem;
    line-height: 1.35;
}

/* Stat chips: flex rather than the default 2-column grid, so three of them
   sit on ONE row (the third was wrapping and doubling the header's height)
   and two do not stretch to fill a track they do not need. */
.master-page.portal-admin-page .prod-master__header-meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.4rem;
    width: auto;
    max-width: none;
}

.master-page.portal-admin-page .prod-master__meta-card {
    gap: 0.05rem;
    padding: 0.3rem 0.6rem;
    border-radius: 0.55rem;
    min-width: 5.2rem;
}

.master-page.portal-admin-page .prod-master__meta-card span {
    font-size: 0.58rem;
    letter-spacing: 0.07em;
    line-height: 1.25;
}

.master-page.portal-admin-page .prod-master__meta-card strong {
    font-size: 0.95rem;
    line-height: 1.2;
}

@media (max-width: 760px) {
    .master-page.portal-admin-page .prod-master__header-meta { justify-content: flex-start; }
}

/* ── Filter row: a real 3-column grid ─────────────────────────────────── */

.portal-admin-page .portal-filters {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.4rem 0.85rem;
    /* Bottom-aligned: float labels make the inputs taller than the plain
       switch labels, and aligning on the baseline of the CONTROL is what
       keeps the row looking level. */
    align-items: end;
}

/* minmax(0, …) alone is not enough — a grid item's default min-width is auto,
   so a wide Syncfusion popup or a long placeholder would blow the track out
   and reintroduce the horizontal scrollbar this layout removes. */
.portal-admin-page .portal-filters > * {
    min-width: 0;
    max-width: 100%;
}

.portal-admin-page .portal-filters .e-input-group,
.portal-admin-page .portal-filters .e-control-wrapper {
    min-width: 0;
    width: 100%;
}

/* Switches have no floating label, so they need the label height back to sit
   level with the inputs beside them. */
.portal-admin-page .portal-filters > label {
    align-self: end;
    padding-bottom: 0.45rem;
}

/* Apply — the only thing on these pages that goes to the database for a filter
   change. Every control above it records the choice and waits, so on a cloud
   database a five-part filter costs ONE round trip instead of five. Spans the
   row and sits right, where the eye finishes reading the filters. */
.portal-admin-page .portal-filters__apply,
.sd-filters .portal-filters__apply {
    grid-column: 1 / -1;
    display: flex;
    justify-content: flex-end;
    align-items: end;
}

@media (max-width: 1200px) {
    .portal-admin-page .portal-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
    .portal-admin-page .portal-filters { grid-template-columns: 1fr; }
    .portal-admin-page .portal-filters > label { padding-bottom: 0; }

    /* Full width when the filters stack — a right-floated button under a
       single column reads as detached from them. */
    .portal-admin-page .portal-filters__apply { justify-content: stretch; }
    .portal-admin-page .portal-filters__apply .e-btn { width: 100%; }
}

/* ── Grid footer totals on the Customer Portal admin pages ───────────────
   Each grid ends in a Count and, where the rows carry money, a Sum. Styled
   here rather than in six scoped stylesheets for the same reason as the
   filter grid above: six copies drift.

   Numeric footers are right-aligned to sit under the figures they total —
   the app-wide numeric alignment rule applies to the footer row as much as
   to the cells. The money total is heavier because it is the one a person
   reads across the room. */

.portal-admin-page .e-gridfooter .e-summarycell {
    font-weight: 600;
    font-size: 0.78rem;
    color: #34445e;
    background: #f7f9fc;
}

.portal-admin-page .pom-total,
.portal-admin-page .pdl-total,
.portal-admin-page .pdr-total,
.portal-admin-page .ppy-total,
.portal-admin-page .pac-total,
.portal-admin-page .sd-total {
    white-space: nowrap;
}

.portal-admin-page .pom-total--money,
.portal-admin-page .pdl-total--money,
.portal-admin-page .pdr-total--money,
.portal-admin-page .ppy-total--money {
    font-weight: 700;
    color: #1d3f74;
}

/* ── Help Search (inline header box + results popup) ──────────────────────
   One box over every page's User Guide (help-index.json). Lives in the
   app header; the popup anchors below the input. */
/* "Getting started" - a pill beside the help search, same height and look. On
   a narrow header only the icon stays. */
.help-guide-link {
    display: inline-flex; align-items: center; gap: 0.4rem;
    height: 2rem; padding: 0 0.75rem; flex: 0 0 auto;
    border: 1px solid rgba(255, 255, 255, 0.45); border-radius: 999px;
    background: rgba(255, 255, 255, 0.12); color: inherit;
    font-size: 0.82rem; font-weight: 600; white-space: nowrap; text-decoration: none;
}
.help-guide-link:hover,
.help-guide-link:focus-visible {
    background: rgba(255, 255, 255, 0.22); border-color: rgba(255, 255, 255, 0.8);
    color: inherit; text-decoration: none; outline: none;
}
.help-guide-link .e-icons { font-size: 0.85rem; }
@media (max-width: 900px) {
    .help-guide-link { padding: 0 0.55rem; }
    .help-guide-link__text { display: none; }
}
.help-search { position: relative; display: flex; align-items: center; }
.help-search__icon {
    position: absolute; left: 0.55rem; font-size: 0.8rem; opacity: 0.65;
    pointer-events: none; color: inherit;
}
.help-search__input {
    height: 2rem; width: 13rem; max-width: 30vw;
    padding: 0 0.6rem 0 1.8rem;
    border: 1px solid rgba(255, 255, 255, 0.45); border-radius: 999px;
    background: rgba(255, 255, 255, 0.12); color: inherit;
    font-size: 0.82rem; outline: none;
}
.help-search__input::placeholder { color: inherit; opacity: 0.7; }
.help-search__input:focus { background: rgba(255, 255, 255, 0.22); border-color: rgba(255, 255, 255, 0.8); }
.help-search__backdrop { position: fixed; inset: 0; z-index: 1190; }
.help-search__popup {
    position: absolute; top: calc(100% + 0.4rem); right: 0; z-index: 1200;
    width: 480px; max-width: 92vw; max-height: 60vh; overflow: auto;
    background: var(--shell-surface, #fff); color: var(--shell-text, #1f2937);
    border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
    padding: 0.4rem 0.6rem 0.6rem;
}
.help-search__scope {
    display: flex; align-items: center; gap: 0.4rem;
    font-size: 0.78rem; opacity: 0.85; padding: 0.25rem 0.15rem 0.4rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.help-search__none { font-size: 0.82rem; opacity: 0.7; padding: 0.6rem 0.2rem; margin: 0; }
.help-search__row {
    display: flex; align-items: flex-start; gap: 0.5rem;
    padding: 0.45rem 0.15rem; border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.help-search__row:last-child { border-bottom: none; }
.help-search__row-body { min-width: 0; flex: 1 1 auto; }
.help-search__row-title { font-size: 0.83rem; font-weight: 600; }
.help-search__row-title span { font-weight: 400; opacity: 0.65; }
.help-search__row-snippet { font-size: 0.79rem; opacity: 0.85; line-height: 1.35; }
.help-search__row-snippet mark { background: #ffe9a8; color: inherit; padding: 0 0.1rem; border-radius: 2px; }
.help-search__row-hint { font-size: 0.72rem; opacity: 0.55; }
.help-search__open {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 0.15rem;
    border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 999px;
    background: transparent; color: inherit; cursor: pointer;
    font-size: 0.74rem; padding: 0.2rem 0.55rem; margin-top: 0.1rem;
}
.help-search__open:hover { background: rgba(0, 0, 0, 0.06); }
.help-search__open .e-icons { font-size: 0.65rem; }

/* Icon-only power/logout in the header: PLAIN glyph (no background,
   no border) sitting right beside the user name; subtle hover halo. */
.header-power-btn.e-btn,
.header-power-btn.e-btn:focus,
.header-power-btn.e-btn:active {
    background: transparent; border: none; box-shadow: none;
    color: inherit;
    width: 1.9rem; height: 1.9rem; min-width: 1.9rem; padding: 0;
    border-radius: 50%; line-height: 1;
    display: inline-flex; align-items: center; justify-content: center;
}
.header-power-btn.e-btn:hover {
    background: rgba(255, 255, 255, 0.16);
    color: #ffc2c2;
}
.header-power-btn__svg {
    width: 1.05rem; height: 1.05rem; display: block;
}

/* ── Pending leave-approvals badge (MainLayout header) — a small bell chip
   that renders ONLY while requests await the signed-in user. Follows the
   header-control language: inherited (inverse) text on the header gradient,
   the same subtle white hover halo as .header-power-btn; the count pill
   reuses the danger token so it reads as "action needed" in every theme. */
/* ════════════════════════════════════════════════════════════════════════
   GLOBAL APPROVAL ALERTS - the bell and its flyout.
   Spec: CLand.WebApiV4/SqlScripts/SPEC_Global_Approval_Alerts.md, layer 3.

   Global rather than component-scoped because the bell lives in the header
   alongside the other header controls, which are styled here.

   ONE TRAP, learned on 2026-09-10 and stated so this does not repeat it:
   neutral surfaces take --shell-panel-background, NOT
   --shell-contrast-surface-bg. The latter is the LIGHT contrast surface meant
   to carry DARK text; paired with --shell-text-primary it renders near-white
   on near-white in the dark theme, which is exactly how the figures on three
   opening dialogs became unreadable.
   ════════════════════════════════════════════════════════════════════════ */
.notif { position: relative; display: inline-flex; }

.notif__bell {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 999px;
    color: var(--shell-text-inverse, inherit);
    cursor: pointer;
    padding: 0;
}
.notif__bell:hover,
.notif__bell--open { background: rgba(255, 255, 255, 0.26); }
.notif__bell:focus-visible { outline: 2px solid var(--shell-button-primary); outline-offset: 2px; }
.notif__bell-icon { width: 1.05rem; height: 1.05rem; display: block; }

/* The badge counts UNREAD, not pending: the bell answers "is there something
   new for me", the flyout answers "how much is outstanding". */
.notif__badge {
    position: absolute; top: -0.28rem; right: -0.28rem;
    background: var(--shell-status-error-text, #c0392b);
    color: #fff;
    border-radius: 999px;
    min-width: 1.05rem; height: 1.05rem;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 0.24rem;
    font-size: 0.66rem; font-weight: 800; line-height: 1;
    font-variant-numeric: tabular-nums;   /* so the count does not jitter */
}
/* One short pulse per arrival. An ERP that beeps is an ERP people mute. */
@keyframes notif-pulse {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.35); }
    100% { transform: scale(1); }
}
.notif__badge--pulse { animation: notif-pulse 400ms ease-out 1; }
@media (prefers-reduced-motion: reduce) {
    .notif__badge--pulse { animation: none; }
}

.notif__sr {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.notif__flyout {
    position: absolute; top: calc(100% + 0.5rem); right: 0; z-index: 1200;
    width: 26rem; max-width: 92vw;
    max-height: 70vh;
    display: flex; flex-direction: column;
    background: var(--shell-panel-background);
    border: 1px solid var(--shell-border);
    border-radius: 0.6rem;
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.32);
    color: var(--shell-text-primary);
    overflow: hidden;
}

.notif__tabs { display: flex; border-bottom: 1px solid var(--shell-border); flex: 0 0 auto; }
.notif__tab {
    flex: 1 1 0; min-width: 0;
    background: transparent; border: 0; border-bottom: 2px solid transparent;
    color: var(--shell-text-secondary);
    padding: 0.6rem 0.5rem;
    font: inherit; font-size: 0.82rem; font-weight: 600;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem;
}
.notif__tab:hover { color: var(--shell-text-primary); }
.notif__tab--active {
    color: var(--shell-text-primary);
    border-bottom-color: var(--shell-button-primary);
}
.notif__tab-count {
    background: var(--shell-button-primary); color: #fff;
    border-radius: 999px; padding: 0 0.35rem;
    font-size: 0.68rem; font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.notif__list { flex: 1 1 auto; overflow-y: auto; }
.notif__empty {
    margin: 0; padding: 1.6rem 1rem;
    text-align: center; color: var(--shell-text-secondary); font-size: 0.85rem;
}

.notif__row {
    display: flex; align-items: stretch;
    border-bottom: 1px solid var(--shell-border);
}
.notif__row:last-child { border-bottom: 0; }
.notif__row:hover { background: rgba(127, 127, 127, 0.09); }
/* Unread carries a faint ground and a dot. Read rows lose both but are never
   hidden - reading a notification is not doing the work. */
.notif__row--unread { background: rgba(127, 127, 127, 0.06); }

.notif__row-main {
    flex: 1 1 auto; min-width: 0;
    display: flex; align-items: flex-start; gap: 0.5rem;
    background: transparent; border: 0; text-align: left;
    color: inherit; font: inherit;
    padding: 0.6rem 0.35rem 0.6rem 0.6rem;
    cursor: pointer;
}
.notif__dot {
    flex: 0 0 auto; width: 0.42rem; height: 0.42rem; margin-top: 0.42rem;
    border-radius: 999px; background: transparent;
}
.notif__row--unread .notif__dot { background: var(--shell-button-primary); }

.notif__icon { flex: 0 0 auto; width: 1.1rem; text-align: center; font-size: 0.9rem; line-height: 1.35; }
.notif__icon--ok    { color: var(--shell-status-ok-text); }
.notif__icon--bad   { color: var(--shell-status-error-text); }
.notif__icon--warn  { color: var(--shell-status-warn-text); }
.notif__icon--muted { color: var(--shell-text-secondary); }

.notif__text { display: flex; flex-direction: column; gap: 0.12rem; min-width: 0; }
.notif__title {
    font-size: 0.85rem; line-height: 1.3;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.notif__row--unread .notif__title { font-weight: 700; }
.notif__detail {
    font-size: 0.76rem; color: var(--shell-text-secondary); line-height: 1.3;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.notif__detail--remark { font-style: italic; }
.notif__foot { font-size: 0.72rem; color: var(--shell-text-secondary); }

/* An escape hatch, not an invitation: visible on hover and on keyboard focus. */
.notif__dismiss {
    flex: 0 0 auto; width: 2rem;
    background: transparent; border: 0;
    color: var(--shell-text-secondary);
    font-size: 0.8rem; cursor: pointer;
    opacity: 0;
}
.notif__row:hover .notif__dismiss,
.notif__dismiss:focus-visible { opacity: 1; }
.notif__dismiss:hover { color: var(--shell-status-error-text); }

.notif__foot-bar {
    flex: 0 0 auto;
    display: flex; justify-content: space-between; gap: 0.5rem;
    padding: 0.5rem 0.6rem;
    border-top: 1px solid var(--shell-border);
}
.notif__link {
    background: transparent; border: 0;
    color: var(--shell-button-primary);
    font: inherit; font-size: 0.78rem; font-weight: 600;
    cursor: pointer; padding: 0.15rem 0.2rem;
}
.notif__link:disabled { color: var(--shell-text-secondary); cursor: default; }
.notif__link:hover:not(:disabled) { text-decoration: underline; }

.header-approvals-chip {
    display: inline-flex; align-items: center; gap: 0.32rem;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 999px;
    color: var(--shell-text-inverse, inherit);
    padding: 0.22rem 0.6rem 0.22rem 0.5rem;
    font: inherit; font-size: 0.8rem; line-height: 1;
    cursor: pointer;
}
.header-approvals-chip:hover { background: rgba(255, 255, 255, 0.24); }
.header-approvals-chip__bell {
    width: 0.95rem; height: 0.95rem; display: block;
}
.header-approvals-chip__count {
    background: var(--shell-danger, #c0392b);
    color: var(--shell-text-inverse, #fff);
    border-radius: 999px;
    min-width: 1.15rem; height: 1.15rem;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 0.28rem;
    font-size: 0.72rem; font-weight: 700;
}

/* ── Cash/Card Collection dialog (CashCollectionDialog) — touch-first:
   44px+ tap targets, big due/change readouts, segmented pay-mode buttons,
   quick-cash denomination chips. Plain HTML inputs by design (Sf numeric
   inside dialogs caused re-fire hangs — StockGroup Phase 7.6). */
.cashcol-dialog .e-dlg-content { padding: 1rem 1.15rem; }
.cashcol__title { font-weight: 700; }
.cashcol__subtitle { margin-left: 0.6rem; font-size: 0.78rem; opacity: 0.7; font-weight: 400; }
.cashcol { display: flex; flex-direction: column; gap: 0.9rem; }
.cashcol__strip { display: flex; gap: 0.75rem; align-items: stretch; flex-wrap: wrap; }
.cashcol__due, .cashcol__change {
    flex: 1 1 160px; border-radius: 0.7rem; padding: 0.55rem 0.9rem;
    background: var(--shell-panel-background-soft, #f4f6f9);
    border: 1px solid var(--shell-border, #d5dbe3);
    display: flex; flex-direction: column;
}
.cashcol__due { border-color: var(--shell-button-primary, #0d6efd); }
.cashcol__due-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; opacity: 0.7; }
.cashcol__due-value { font-size: 1.6rem; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; }
.cashcol__change--give { background: #fff7e0; border-color: #f6c344; color: #633806; }
.cashcol__change--give .cashcol__due-label { color: #854f0b; opacity: 1; }
.cashcol__counter { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.75rem; min-width: 200px; }
.cashcol__counter select, .cashcol__f select, .cashcol__f input {
    min-height: 44px; font-size: 1rem; padding: 0.35rem 0.6rem;
    border: 1px solid var(--shell-border, #c9d1dc); border-radius: 0.55rem;
    background: var(--shell-panel-background, #fff);
    color: var(--shell-text-primary, inherit);
    width: 100%; box-sizing: border-box;
}
.cashcol input[type="number"] { text-align: right; }   /* numeric right-align convention */
.cashcol__f input[readonly] { background: var(--shell-panel-background-soft, #f2f4f7); }
.cashcol__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0.6rem; }
.cashcol__f { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.78rem; }
.cashcol__f em { font-style: normal; opacity: 0.65; }
.cashcol__f--wide { grid-column: 1 / -1; }
.cashcol__f--big input { font-size: 1.35rem; font-weight: 700; min-height: 52px; }
.cashcol__modes { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.cashcol__mode {
    min-height: 52px; padding: 0 1.1rem; border-radius: 0.6rem;
    border: 1px solid var(--shell-border, #c9d1dc);
    background: var(--shell-panel-background, #fff);
    color: var(--shell-text-primary, inherit);
    font-size: 0.95rem; font-weight: 600; cursor: pointer; touch-action: manipulation;
}
.cashcol__mode--on {
    background: var(--shell-button-primary, #0d6efd); color: #fff;
    border-color: var(--shell-button-primary, #0d6efd);
}
.cashcol__cashwrap { display: flex; gap: 0.9rem; align-items: stretch; flex-wrap: wrap; }
.cashcol__cash { display: flex; flex-direction: column; gap: 0.5rem; flex: 1 1 300px; min-width: 260px; }
.cashcol__chips { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.cashcol__chip {
    min-height: 46px; min-width: 68px; border-radius: 999px;
    border: 1px solid var(--shell-border, #c9d1dc);
    background: var(--shell-panel-background, #fff);
    color: var(--shell-text-primary, inherit);
    font-weight: 600; cursor: pointer; touch-action: manipulation;
}

/* POS keypad — big square keys, hardware keyboard still works on the input. */
.cashcol__pad {
    display: grid; grid-template-columns: repeat(3, 64px);
    gap: 0.4rem; align-content: start; flex: 0 0 auto;
}
.cashcol__key {
    min-height: 56px; border-radius: 0.6rem;
    border: 1px solid var(--shell-border, #c9d1dc);
    background: var(--shell-panel-background, #fff);
    color: var(--shell-text-primary, inherit);
    font-size: 1.25rem; font-weight: 700; cursor: pointer; touch-action: manipulation;
    font-variant-numeric: tabular-nums;
}
.cashcol__key:active { background: var(--shell-panel-background-soft, #e8ecf1); }
.cashcol__key--back { background: #fcebeb; border-color: #e24b4a; color: #7a1f1f; font-size: 1.05rem; }
.cashcol__key--wide { grid-column: span 3; min-height: 48px; }

/* Big CHANGE banner — the number the cashier reads out to the customer. */
.cashcol__refund {
    display: flex; align-items: baseline; justify-content: space-between;
    padding: 0.55rem 0.9rem; border-radius: 0.7rem;
    background: #e1f5ee; border: 1px solid #1d9e75; color: #085041;
}
.cashcol__refund span { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; }
.cashcol__refund strong { font-size: 1.9rem; font-variant-numeric: tabular-nums; }

/* Footer: Collect is the one big obvious button. */
.cashcol-dialog .e-footer-content .e-btn { min-height: 50px; font-size: 1rem; }
.cashcol-dialog .e-footer-content .e-primary { min-width: 200px; font-weight: 700; }
.cashcol__chip--exact { background: #e1f5ee; border-color: #1d9e75; color: #085041; }
.cashcol__chip--clear { background: #fcebeb; border-color: #e24b4a; color: #7a1f1f; }
.cashcol__error {
    background: #fcebeb; border: 1px solid #e24b4a; color: #7a1f1f;
    padding: 0.5rem 0.7rem; border-radius: 0.5rem; font-size: 0.85rem;
}
/* The bill's special discount: amber note (waiting / lapsed), green when
   approved and taken off, red when it stops the bill. */
.cashcol__spl {
    display: grid; gap: 0.2rem;
    padding: 0.5rem 0.7rem; border-radius: 0.5rem; font-size: 0.88rem;
    border: 1px solid #d97706; background: rgba(245, 158, 11, 0.12);
}
.cashcol__spl strong { font-size: 1rem; font-variant-numeric: tabular-nums; }
.cashcol__spl--on { border-color: #2f9e55; background: rgba(40, 167, 69, 0.12); }
.cashcol__spl--blocked { border-color: #e24b4a; background: rgba(220, 38, 38, 0.12); }
@media (max-width: 700px) {
    .cashcol-dialog .e-dialog { width: 96vw !important; max-width: 96vw !important; }
}

/* ── Help-panel inline search (injected by layout.js into every open help
   panel; DOM-last child, order:-1 floats it to the top of the flex column). */
.help-panel-search {
    order: -1;
    flex: 0 0 auto;
}
.help-panel-search__input {
    width: 100%;
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--shell-border, #d5dbe3);
    border-radius: 999px;
    font: inherit;
    font-size: 0.8rem;
    background: var(--shell-panel-background, #fff);
    color: inherit;
}
.help-panel-search__input:focus {
    outline: none;
    border-color: var(--shell-button-primary, #0d6efd);
    box-shadow: 0 0 0 0.15rem var(--shell-focus-ring, rgba(13, 110, 253, 0.2));
}
.help-panel-search__results {
    margin-top: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 40vh;
    overflow-y: auto;
}
.help-panel-search__row {
    text-align: left;
    border: none;
    background: transparent;
    padding: 0.35rem 0.5rem;
    border-radius: 0.45rem;
    cursor: pointer;
    font: inherit;
    font-size: 0.78rem;
    color: inherit;
}
.help-panel-search__row:hover {
    background: rgba(0, 0, 0, 0.06);
}
.help-panel-search__row-title {
    display: block;
    font-weight: 600;
}
.help-panel-search__row-snip {
    display: block;
    opacity: 0.75;
}
.help-panel-search__row-snip mark {
    background: var(--shell-button-primary, #0d6efd);
    color: #fff;
    border-radius: 2px;
    padding: 0 2px;
}
.help-panel-search__none {
    font-size: 0.75rem;
    opacity: 0.7;
    padding: 0.25rem 0.5rem;
}
/* Docked strip shows only the rotated label — no search box there. */
.ct-page__help--docked .help-panel-search,
.prod-master__help--docked .help-panel-search,
.custom-entry__help--docked .help-panel-search {
    display: none;
}

/* Searched text inside a help panel after a deep-open from Help Search:
   selection-style highlight in the active theme's primary colour. */
.invnet-help-hit {
    background: var(--shell-button-primary, #0d6efd);
    color: #fff;
    border-radius: 3px;
    padding: 0 2px;
}

/* Icon-only variant of the result "open" action. */
.help-search__open--icon {
    width: 1.7rem; height: 1.7rem; padding: 0;
    justify-content: center; border-radius: 50%;
}
.help-search__open--icon .e-icons { font-size: 0.75rem; }
.help-search__row-title a { color: var(--shell-primary, #0d6efd); text-decoration: none; }
.help-search__row-title a:hover { text-decoration: underline; }

/* ── POS splitter drag state (P3-01) ──────────────────────────────────
   Applied to <body> for the duration of a splitter drag by
   registerPosSplitter in layout.js. It lives here rather than in
   TouchPosPanel.razor.css because scoped CSS appends the component's scope
   attribute to the last selector element — `body[b-xxxx]` matches nothing.

   Without it, a fast drag selects the tile captions it passes over and the
   cursor flickers as it crosses each pane. */
body.pos-splitter-dragging {
    cursor: col-resize;
    user-select: none;
    -webkit-user-select: none;
}

/* ── Control Finder (NF-03) ──────────────────────────────────────────────
   The marks land on Syncfusion-owned wrappers, which a page's SCOPED css
   can never reach — the scope attribute is only stamped on elements the
   component itself renders. So these live here, globally, deliberately.

   Two levels: every match gets a quiet tint so the operator can see how
   many there are and where, and the CURRENT one gets a ring and a one-shot
   flash so it is unmistakable among them. */
.cf-hit {
    border-radius: 6px;
    box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.45);
    transition: box-shadow 0.18s ease;
}

.cf-hit--current {
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.85);
    animation: cf-flash 0.9s ease-out 1;
}

@keyframes cf-flash {
    0%   { background-color: rgba(220, 38, 38, 0.22); }
    100% { background-color: transparent; }
}

/* Respect a reduced-motion preference: the ring alone still identifies the
   current match, so the flash is the only thing dropped. */
@media (prefers-reduced-motion: reduce) {
    .cf-hit--current { animation: none; }
}

/* ── Voucher status chips (app-wide) ─────────────────────────────────────────
   ONE colour vocabulary for every voucher status, so the same word never has
   two colours on two screens. Pages used to map statuses themselves and
   disagreed: "Approved" was green on Pay Bill and blue on Attendance because
   the attendance mapper had no Approved case.

   Pair with InvoiceNETWebV1.Services.StatusChip, which decides WHICH modifier a
   status gets. Add a colour here only with a matching rule there. */
.app-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.12rem 0.5rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.71rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

/* Approved, Released, Completed, Active, Billed, Posted … */
.app-chip--success {
    background: var(--shell-status-success-bg, #e4f5e9);
    color: var(--shell-status-success-text, #1d6b37);
    border-color: var(--shell-status-success-border, #b4dfc2);
}

/* Open, Draft, New, In Progress … */
.app-chip--info {
    background: var(--shell-status-info-bg, #e8f0fe);
    color: var(--shell-status-info-text, #1a4b8c);
    border-color: var(--shell-status-info-border, #b9d1f5);
}

/* On Hold, Altered, Under Review, anything "… Approval …" */
.app-chip--warn {
    background: var(--shell-status-warn-bg, #fff4e0);
    color: var(--shell-status-warn-text, #7a4b00);
    border-color: var(--shell-status-warn-border, #f0cf9a);
}

/* Cancelled, Rejected — the app-wide cancelled vocabulary. */
.app-chip--danger {
    background: var(--shell-status-error-bg, #ffd2d2);
    color: var(--shell-status-error-text, #7a1b16);
    border-color: var(--shell-status-error-border, #f2b4b0);
}

/* Closed, Inactive, Unposted, and anything unrecognised — never mis-coloured
   as something it is not. */
.app-chip--neutral {
    background: var(--shell-item-background-subtle, #eceff4);
    color: var(--shell-text-secondary, #4a5566);
    border-color: var(--shell-border, #d8dee7);
}

/* ── Licence refusal (ModuleGuard) ───────────────────────────────────────────
   Shown INSTEAD of a page whose module the licence does not include. Styled as
   a calm explanation rather than an error: the customer has done nothing wrong,
   and the message has to tell them what to ask their supplier for. */
.module-guard {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 3rem 1.5rem;
    min-height: 60vh;
}
.module-guard__panel {
    max-width: 560px;
    background: var(--shell-surface, #fff);
    color: var(--shell-text, #1b2430);
    border: 1px solid var(--shell-border, #dfe4ea);
    border-radius: 8px;
    padding: 2rem 2.2rem;
    text-align: center;
    box-shadow: 0 1px 2px rgba(20, 30, 45, .06), 0 8px 24px rgba(20, 30, 45, .06);
}
.module-guard__icon { font-size: 2.2rem; line-height: 1; margin-bottom: .8rem; }
.module-guard__panel h2 { margin: 0 0 .8rem; font-size: 1.15rem; font-weight: 600; }
.module-guard__panel p { margin: 0 0 .8rem; line-height: 1.6; }
.module-guard__hint {
    font-size: .88rem;
    color: var(--shell-text-muted, #5a6472);
    margin-bottom: 0 !important;
}


/* -- Company wizard and company details (.wizard__*) ------------------------
   GLOBAL, not scoped, and that is the whole point.

   These rules began in CompanyCreatePage.razor.css. Blazor's CSS isolation
   stamps a scope attribute onto the markup a component DECLARES, so a rule
   written there never reaches markup rendered by a CHILD component - and the
   address and registration fields come from CompanyFormFields. The result was
   a page whose headings and buttons were styled while every field was not.

   Two pages use this block - the creation wizard and Admin > Company Details -
   and the stylesheet had already been copied between them. One global copy,
   next to the other shared conventions in this file, cannot drift.

   EVERY COLOUR IS A --shell-* TOKEN. The first version hardcoded hex values
   and invented --shell-accent-strong, which does not exist: in dark mode the
   primary button's hover fell back to a light-theme navy. The tokens below all
   exist in all three theme blocks, so this block follows the theme instead of
   guessing at it.
   -------------------------------------------------------------------------- */
.wizard { max-width: 860px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }

/* ── The company Settings block (CompanyFormFields Section="settings") ──────
   Shared by the creation wizard and Company Details, so it lives here rather
   than in either page's scoped file.

   The five optional features are CHECKBOXES with their explanation beside
   them, not the desktop form's Yes/No dropdowns: they are independent
   opt-ins, and a dropdown per row made five rows of "No" that all looked like
   a required choice. Each row is a <label>, so the whole card toggles. */
.cfx-optional-head {
    margin: 1.1rem 0 0.25rem;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--shell-text-secondary);
}

.cfx-optional-note { margin: 0 0 0.6rem; }

.cfx-switches {
    display: grid;
    gap: 0.5rem;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.cfx-switch {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--shell-border);
    border-radius: 14px;
    background: var(--shell-panel-background-soft);
    cursor: pointer;
}

.cfx-switch:hover {
    border-color: var(--shell-border-strong, var(--shell-border));
}

.cfx-switch input[type="checkbox"] {
    width: 1.05rem;
    height: 1.05rem;
    margin-top: 0.15rem;
    flex: 0 0 auto;
    accent-color: var(--shell-button-primary);
}

.cfx-switch__text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.cfx-switch__text strong { font-size: 0.9rem; color: var(--shell-text-primary); }
.cfx-switch__text small { font-size: 0.78rem; line-height: 1.35; color: var(--shell-text-secondary); }
.wizard__head { margin-bottom: 1.2rem; }
.wizard__eyebrow { margin: 0; font-size: .72rem; letter-spacing: .09em;
                   text-transform: uppercase; color: var(--shell-text-muted); }
.wizard__head h1 { margin: .2rem 0 .3rem; font-size: 1.5rem; font-weight: 600;
                   color: var(--shell-text); }
.wizard__sub { margin: 0; color: var(--shell-text-muted); }

.wizard__steps { display: flex; gap: .5rem; list-style: none; margin: 0 0 1rem; padding: 0; }
.wizard__step { flex: 1; display: flex; align-items: center; gap: .5rem;
                padding: .55rem .8rem; border-radius: 6px; font-size: .9rem;
                background: var(--shell-surface-muted);
                border: 1px solid var(--shell-border);
                color: var(--shell-text-muted); }
.wizard__step span { display: inline-flex; align-items: center; justify-content: center;
                     width: 1.5rem; height: 1.5rem; border-radius: 50%; font-size: .8rem;
                     background: var(--shell-border); color: var(--shell-text); }
.wizard__step--now { border-color: var(--shell-button-primary);
                     color: var(--shell-text); font-weight: 600; }
.wizard__step--now span { background: var(--shell-button-primary); color: #fff; }
.wizard__step--done span { background: var(--shell-status-ok); color: #fff; }

.wizard__card { background: var(--shell-surface);
                border: 1px solid var(--shell-border);
                color: var(--shell-text);
                border-radius: 8px; padding: 1.4rem 1.5rem;
                box-shadow: 0 1px 2px rgba(20,30,45,.05), 0 6px 20px rgba(20,30,45,.05); }
.wizard__card h2 { margin: 0 0 .3rem; font-size: 1.1rem; font-weight: 600; }
.wizard__muted { color: var(--shell-text-muted); margin: 0 0 1rem; }
.wizard__mono { font-family: Consolas, "Cascadia Mono", monospace; font-size: .85rem; word-break: break-all; }
.wizard__subhead { margin: 1.4rem 0 .5rem; font-size: .82rem; font-weight: 700;
                   text-transform: uppercase; letter-spacing: .06em;
                   color: var(--shell-text-muted); }

.wizard__grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: .9rem 1.1rem; }
.wizard__field--wide { grid-column: 1 / -1; }
@media (max-width: 700px) { .wizard__grid { grid-template-columns: 1fr; } }

.wizard__field label { display: block; font-size: .78rem; font-weight: 600;
                       color: var(--shell-text-muted); margin-bottom: .2rem; }
.wizard__field input,
.wizard__field select { width: 100%; padding: .45rem .6rem; font: inherit;
                        border: 1px solid var(--shell-input-border);
                        border-radius: 6px;
                        background: var(--shell-input-background);
                        color: var(--shell-input-text); }
.wizard__field input:focus,
.wizard__field select:focus { outline: none; border-color: var(--shell-button-primary);
                              box-shadow: 0 0 0 3px var(--shell-accent-soft); }
.wizard__field input:disabled,
.wizard__field select:disabled { opacity: .6; cursor: not-allowed; }
.wizard__input--bad { border-color: var(--shell-danger) !important; }
.wizard__hint { display: block; font-size: .74rem; color: var(--shell-text-muted); margin-top: .2rem; }
.wizard__warn { color: var(--shell-status-warn-text); font-weight: 600; }
.wizard__ok { color: var(--shell-status-ok-text); font-weight: 600; }

.wizard__facts { display: grid; grid-template-columns: auto 1fr; gap: .45rem 1.1rem; margin: 0 0 1rem; }
.wizard__facts dt { font-size: .78rem; font-weight: 600; color: var(--shell-text-muted); }
.wizard__facts dd { margin: 0; }

.wizard__list { margin: 0 0 1rem; padding-left: 1.1rem; color: var(--shell-text-muted); font-size: .9rem; }

/* Company creation progress (2026-09-29): the steps of a running create, polled from the API. */
.cprog { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .55rem; }
.cprog__step { display: grid; grid-template-columns: 1.6rem 1fr; gap: .6rem; align-items: start; }
.cprog__mark {
    width: 1.35rem; height: 1.35rem; border-radius: 50%; display: grid; place-items: center;
    font-size: .8rem; font-weight: 700; line-height: 1; margin-top: .1rem;
    border: 2px solid var(--shell-border-strong, var(--shell-border)); color: var(--shell-text-inverse, #fff);
}
.cprog__step--done .cprog__mark { background: var(--shell-status-ok-accent, #4caf50); border-color: var(--shell-status-ok-accent, #4caf50); }
.cprog__step--failed .cprog__mark { background: var(--shell-status-error-border, #d32f2f); border-color: var(--shell-status-error-border, #d32f2f); }
.cprog__step--running .cprog__mark {
    border-color: var(--shell-button-primary, #0d6efd); border-right-color: transparent;
    animation: cprog-spin .8s linear infinite;
}
@keyframes cprog-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cprog__step--running .cprog__mark { animation: none; border-right-color: var(--shell-button-primary, #0d6efd); } }
.cprog__title { font-weight: 600; }
.cprog__step--waiting .cprog__title { color: var(--shell-text-muted); font-weight: 500; }
.cprog__state { font-weight: 400; color: var(--shell-text-muted); font-size: .85rem; }
.cprog__detail { color: var(--shell-text-muted); font-size: .85rem; word-break: break-word; }
.cprog__error {
    margin-top: .3rem; padding: .45rem .6rem; border-radius: 6px; font-size: .85rem; word-break: break-word;
    background: var(--shell-status-error-bg); border: 1px solid var(--shell-status-error-border); color: var(--shell-status-error-text, var(--shell-text-primary));
}
.cprog__bar { height: .5rem; border-radius: 999px; background: var(--shell-border); overflow: hidden; margin: .35rem 0 .2rem; max-width: 28rem; }
.cprog__bar > span { display: block; height: 100%; background: var(--shell-button-primary, #0d6efd); transition: width .4s ease; }
@media (prefers-reduced-motion: reduce) { .cprog__bar > span { transition: none; } }

.wizard__banner { padding: .6rem .8rem; border-radius: 6px; border: 1px solid;
                  margin: .9rem 0; font-size: .92rem; }
.wizard__banner--bad  { background: var(--shell-status-error-bg);
                        border-color: var(--shell-status-error-border);
                        color: var(--shell-status-error-text); }
.wizard__banner--good { background: var(--shell-status-ok-bg);
                        border-color: var(--shell-status-ok-border);
                        color: var(--shell-status-ok-text); }
.wizard__banner--warn { background: var(--shell-status-warn-bg);
                        border-color: var(--shell-status-warn-border);
                        color: var(--shell-status-warn-text); }

.wizard__actions { display: flex; gap: .6rem; justify-content: flex-end; margin-top: 1.2rem; }
.wizard__btn { padding: .5rem 1.1rem; font: inherit; cursor: pointer; border-radius: 6px;
               border: 1px solid var(--shell-button-secondary-border);
               background: var(--shell-button-secondary-bg);
               color: var(--shell-button-secondary-text); }
.wizard__btn:hover:not(:disabled) { border-color: var(--shell-button-primary); }
.wizard__btn:disabled { opacity: .55; cursor: not-allowed; }

/* White on primary is the house pattern - see .btn-primary above, which pairs
   colour #fff with this same token. Matched deliberately rather than improved
   on: a button that reads differently here than everywhere else is worse than
   one that matches. */
.wizard__btn--primary { background: var(--shell-button-primary);
                        border-color: var(--shell-button-primary);
                        color: #fff; font-weight: 600; }
.wizard__btn--primary:hover:not(:disabled) { background: var(--shell-button-primary-hover);
                                             border-color: var(--shell-button-primary-hover); }

/* ── Permission tabs (UserPermissionTabs) ──────────────────────────────────
   A plain table on purpose: the voucher tab is 89 rows by 21 columns, and a
   grid component with a template per cell would build nearly two thousand
   components for one tab. Global rather than scoped because the component is
   shared. */
.perm { display: flex; flex-direction: column; gap: 0.5rem; }

.perm__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.perm__co { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; }
.perm__co span { color: var(--shell-text-secondary); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.7rem; }

.perm__co select {
    min-height: 34px;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--shell-field-border);
    border-radius: 10px;
    background: var(--shell-contrast-surface-bg);
    color: var(--shell-contrast-surface-text);
    font: inherit;
}

.perm__tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; }

.perm__tab {
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--shell-border);
    border-radius: 999px;
    background: var(--shell-panel-background-soft);
    color: var(--shell-text-primary);
    font: inherit;
    font-size: 0.82rem;
    cursor: pointer;
}

.perm__tab--on {
    background: var(--shell-button-primary);
    border-color: var(--shell-button-primary);
    color: #fff;
    font-weight: 600;
}

.perm__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

.perm__note { margin: 0; font-size: 0.8rem; line-height: 1.4; color: var(--shell-text-secondary); }
.perm__note--warn { color: var(--shell-warning-text, var(--shell-text-primary)); }
.perm__note--ok { color: var(--shell-success-text, var(--shell-text-secondary)); }

.perm__empty, .perm-empty {
    padding: 1rem;
    border: 1px dashed var(--shell-border);
    border-radius: 14px;
    color: var(--shell-text-secondary);
    background: var(--shell-panel-background-soft);
}

/* ── Permission tabs: the SfGrid ──────────────────────────────────────────
   The grid brings its own scrolling, sticky header and row striping, so what
   is left here is only what is ours: the whole-column "all" button, the tree
   indent in the Description cell, and the tint that separates a row which
   already has a stored permission row from one that never had any. */
.perm__gridwrap { width: 100%; }

/* Headers WRAP rather than truncate - the app-wide rule - and a header that
   carries the "all" button needs room for both lines. */
.perm__head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1rem;
    line-height: 1.2;
}

.perm__colbtn {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-size: 0.68rem;
    color: var(--shell-button-primary);
    cursor: pointer;
    text-decoration: underline;
}

.perm__name { display: inline-block; color: var(--shell-text-primary); }
.perm__name--head { font-weight: 700; }

/* Editors are visibly bordered AT REST, never transparent-until-focus - the
   reader has to see where a value can be typed without hunting for it. */
.perm__text {
    width: 100%;
    min-width: 90px;
    padding: 0.2rem 0.4rem;
    border: 1px solid var(--shell-field-border);
    border-radius: 8px;
    background: var(--shell-contrast-surface-bg);
    color: var(--shell-contrast-surface-text);
    font: inherit;
    font-size: 0.8rem;
}

/* The alert day counts are numbers, so they line up right like every other
   number in the product. */
.perm__text--num { width: 5.5rem; text-align: right; }

.perm__gridwrap input[type="checkbox"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--shell-button-primary);
}

/* A row that already carries a stored permission row is marked, so "granted
   nothing" and "never configured" are told apart at a glance - they look
   identical from the ticks alone. */
.perm__gridwrap .e-row.perm__row--set .e-rowcell:first-child { font-weight: 600; }

/* A menu heading: structure, not something to tick. */
.perm__gridwrap .e-row.perm__row--head .e-rowcell {
    background: var(--shell-contrast-surface-bg);
    font-weight: 700;
}

/* The Required Status Items cell: several statuses, not free text. It needs
   to breathe more than a checkbox does, and its chips must not push the row
   taller than the rest of the grid. */
.perm__multi { min-width: 220px; font-size: 0.78rem; }
.perm__multi .e-multi-select-wrapper { padding: 1px 4px; }
.perm__multi .e-chips { max-height: 3.2rem; overflow-y: auto; }

.perm__dash { color: var(--shell-text-secondary); }
.perm__foot { font-weight: 600; }

/* A field checked when it is left says so under the control, in the same place
   the hint sits, and outlines the control itself - an annotation nobody looks
   at is not a validation. Tokens only, so both themes stay legible. */
.app-field-error {
    margin: 0.15rem 0 0;
    font-size: 0.72rem;
    line-height: 1.35;
    font-weight: 500;
    white-space: normal;
    overflow-wrap: anywhere;
    color: var(--shell-danger);
}

.app-textbox--invalid .e-input-group,
.app-textbox--invalid.e-input-group,
.app-textbox--invalid .e-control-wrapper {
    border-color: var(--shell-danger) !important;
}

/* E-mail compose window (Components/Others/EmailComposeDialog) - wide and
   tall; its content scrolls on a short screen so Send stays in reach. */
.e-dialog.emc-dialog .e-dlg-content {
    max-height: calc(92vh - 110px);
    overflow-y: auto;
}

/* ── Toasts (Services/ToastService, Components/Others/AppToastHost) ──
   Outcome notices, coloured by the same status tokens as MasterStatusBanner,
   so both themes follow. A severity stripe on the left carries the kind. */
.app-toast .e-toast,
.e-toast-container .e-toast.app-toast--success,
.e-toast-container .e-toast.app-toast--info,
.e-toast-container .e-toast.app-toast--warning,
.e-toast-container .e-toast.app-toast--error {
    border-radius: 0.5rem;
    border: 1px solid var(--shell-border);
    border-left-width: 5px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}
.e-toast-container .e-toast.app-toast--success { background: var(--shell-status-ok-bg); border-left-color: var(--shell-status-ok-border); }
.e-toast-container .e-toast.app-toast--info { background: var(--shell-status-info-bg); border-left-color: var(--shell-status-info-border); }
.e-toast-container .e-toast.app-toast--warning { background: var(--shell-status-warn-bg); border-left-color: var(--shell-status-warn-border); }
.e-toast-container .e-toast.app-toast--error { background: var(--shell-status-error-bg); border-left-color: var(--shell-status-error-border); }
.e-toast-container .e-toast.app-toast--success .e-toast-title { color: var(--shell-status-ok-text); }
.e-toast-container .e-toast.app-toast--info .e-toast-title { color: var(--shell-status-info-text); }
.e-toast-container .e-toast.app-toast--warning .e-toast-title { color: var(--shell-status-warn-text); }
.e-toast-container .e-toast.app-toast--error .e-toast-title { color: var(--shell-status-error-text); }
.e-toast-container .e-toast[class*="app-toast--"] .e-toast-close-icon {
    display: flex !important;
    color: var(--shell-text-primary);
    opacity: 0.75;
    cursor: pointer;
}
.e-toast-container .e-toast[class*="app-toast--"] .e-toast-close-icon:hover { opacity: 1; }
.e-toast-container .e-toast[class*="app-toast--"] .e-toast-content {
    color: var(--shell-text-primary);
    white-space: pre-line;
}
@media (max-width: 600px) {
    .e-toast-container .e-toast[class*="app-toast--"] { width: calc(100vw - 32px) !important; }
}

/* ═══ GST Returns (Tools & Utilities): workspace, filing register, filing settings.
   Shared by three pages, so global; every class is gst-*. Shell tokens only. ═══ */

.gst-body { min-height: 0; }

.gst-main {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    max-height: 100%;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    padding-bottom: 1rem;
}

.gst-filters {
    display: grid;
    grid-template-columns: minmax(200px, 1fr) minmax(280px, 2fr) minmax(160px, 1fr);
    gap: 0.75rem 1rem;
    align-items: start;
}

.gst-field { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.gst-field > span:first-child { font-size: 0.78rem; font-weight: 600; opacity: 0.85; }
.gst-field--full { width: 100%; }

.gst-input {
    width: 100%;
    min-width: 0;
    padding: 0.4rem 0.55rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.4rem;
    background: var(--shell-input-background, var(--shell-panel-background));
    color: var(--shell-text-primary);
    font: inherit;
    font-size: 0.9rem;
}
.gst-input:focus-visible { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: 1px; }
textarea.gst-input { resize: vertical; }

.gst-empty { margin: 0.5rem 0; opacity: 0.75; font-size: 0.9rem; }
.gst-muted { opacity: 0.7; font-size: 0.85rem; }
.gst-bad { color: var(--shell-status-error-text, #c62828); }

.gst-filing {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.5rem;
    background: var(--shell-panel-background);
    font-size: 0.88rem;
}
.gst-filing__text { flex: 1 1 320px; min-width: 0; }

.gst-link {
    border: 0;
    background: none;
    padding: 0;
    color: var(--shell-accent, #2563eb);
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    text-decoration: underline;
}

.gst-trail { margin: 0; padding-left: 1.3rem; font-size: 0.85rem; display: flex; flex-direction: column; gap: 0.2rem; }

.gst-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.08rem 0.5rem;
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid var(--shell-border);
}
.gst-chip--ok { background: var(--shell-status-success-bg, #e8f5e9); color: var(--shell-status-success-text, #1b5e20); border-color: transparent; }
.gst-chip--warn { background: var(--shell-status-warning-bg, #fff3e0); color: var(--shell-status-warning-text, #8a4b00); border-color: transparent; }
.gst-chip--error { background: var(--shell-status-error-bg, #ffebee); color: var(--shell-status-error-text, #b71c1c); border-color: transparent; }
.gst-chip--plain { background: transparent; }

.gst-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 0.6rem;
}

.gst-card {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.6rem 0.7rem;
    text-align: left;
    border: 1px solid var(--shell-border);
    border-radius: 0.5rem;
    background: var(--shell-panel-background);
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.gst-card:hover { border-color: var(--shell-accent, #2563eb); }
.gst-card:focus-visible { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: 1px; }
.gst-card--on { border-color: var(--shell-accent, #2563eb); box-shadow: inset 0 0 0 1px var(--shell-accent, #2563eb); }
.gst-card--failed { border-color: var(--shell-status-error-text, #c62828); }
.gst-card__title { font-size: 0.82rem; font-weight: 700; line-height: 1.25; }
.gst-card__figs { display: flex; flex-wrap: wrap; gap: 0.15rem 0.6rem; font-size: 0.78rem; opacity: 0.85; font-variant-numeric: tabular-nums; }
.gst-card__flags { display: flex; flex-wrap: wrap; gap: 0.3rem; min-height: 1rem; }

.gst-section-head h2 { margin: 0.25rem 0 0.15rem; font-size: 1.05rem; }
.gst-section-head p { margin: 0; font-size: 0.85rem; opacity: 0.8; }

.gst-grid {
    flex: 0 0 auto;
    height: 460px;
    min-height: 360px;
    display: flex;
    flex-direction: column;
}
.gst-grid .e-grid { flex: 1 1 auto; }
.gst-grid .e-gridcontent .e-content { overflow-x: auto !important; }
.gst-grid .gst-row--issue td { background: var(--shell-status-warning-bg, #fff8e1); }

.gst-rowbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: 0.85rem; }

.gst-foot { font-variant-numeric: tabular-nums; }

.gst-stmtwrap, .gst-drillwrap { overflow-x: auto; max-width: 100%; }

.gst-stmt {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
}
.gst-stmt th, .gst-stmt td {
    padding: 0.35rem 0.55rem;
    border-bottom: 1px solid var(--shell-border);
    text-align: left;
    vertical-align: top;
}
.gst-stmt thead th { font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.03em; opacity: 0.8; white-space: normal; }
.gst-stmt .gst-num, .gst-num { text-align: right; white-space: nowrap; }
.gst-stmt__row--head td { font-weight: 700; background: var(--shell-surface-background, rgba(127, 127, 127, 0.06)); }
.gst-stmt__row--total td { font-weight: 700; border-top: 2px solid var(--shell-border); }
.gst-stmt__row--drill { cursor: pointer; }
.gst-stmt__row--drill:hover td, .gst-stmt__row--drill:focus-visible td { background: var(--shell-hover-background, rgba(37, 99, 235, 0.07)); }
.gst-stmt tfoot td { border-top: 2px solid var(--shell-border); }

.gst-issues { display: flex; flex-direction: column; gap: 0.4rem; }
.gst-issues__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem; }
.gst-issues__head h2 { margin: 0; font-size: 1rem; }
.gst-check { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; }

.gst-issuelist {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 280px;
    overflow-y: auto;
    border: 1px solid var(--shell-border);
    border-radius: 0.5rem;
}
.gst-issue {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 0.6rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.85rem;
    border-bottom: 1px solid var(--shell-border);
}
.gst-issue:last-child { border-bottom: 0; }
/* An issue with something behind it READS as clickable: link-coloured text,
   underlined on hover, and a button at its end naming what opens. */
.gst-issue--link { cursor: pointer; }
.gst-issue--link .gst-issue__text { color: var(--shell-link, var(--shell-accent, #1d4ed8)); text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
.gst-issue--link:hover .gst-issue__text, .gst-issue--link:focus-visible .gst-issue__text { text-decoration-style: solid; }
.gst-issue--link:focus-visible { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: -2px; }
.gst-issue__open {
    display: inline-flex; align-items: center; gap: 0.25rem; margin-left: 0.6rem; padding: 0.1rem 0.6rem;
    border: 1px solid var(--shell-accent, #2563eb); border-radius: 999px; white-space: nowrap;
    font-size: 0.78rem; font-weight: 700; color: var(--shell-accent, #2563eb); background: transparent;
}
.gst-issue--link:hover .gst-issue__open { background: var(--shell-accent, #2563eb); color: var(--shell-button-primary-text, #fff); }
.gst-issue--link:hover { background: var(--shell-hover-background, rgba(37, 99, 235, 0.07)); }
.gst-issue__sec { font-weight: 600; opacity: 0.8; }

.gst-print { display: none; }
.gst-grid--tall { height: calc(100vh - 360px); min-height: 380px; }
.gst-filters--two { grid-template-columns: repeat(2, minmax(180px, 260px)); }

.gst-dlg__body { display: flex; flex-direction: column; gap: 0.7rem; }
.gst-dlg__body p { margin: 0; }

@media (max-width: 900px) {
    .gst-filters { grid-template-columns: minmax(0, 1fr); }
}

.gst-setgrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 0.9rem 1.25rem;
    align-items: start;
}
.gst-chain {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 0.8rem 1rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.5rem;
    background: var(--shell-panel-background);
    max-width: 760px;
}
.gst-chain h2 { margin: 0; font-size: 1rem; }
.gst-chain__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.gst-decision { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; }
.gst-decision > span { font-weight: 600; }
.gst-decision .gst-input { width: auto; min-width: 220px; }

.gst-cell--manual { padding: 0.15rem 0.3rem !important; }
.gst-input--cell { width: 8.5rem; text-align: right; padding: 0.2rem 0.4rem; border-style: dashed; font-variant-numeric: tabular-nums; }
.gst-input--cell:disabled { border-style: solid; opacity: 0.7; }

.gst-scope { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.9rem; padding: 0.4rem 0.6rem; border: 1px solid var(--shell-border); border-radius: 0.4rem; background: var(--shell-surface-background, rgba(127,127,127,0.06)); font-size: 0.9rem; }
.gst-scope > span { opacity: 0.85; }

/* GST Returns: fixed "what to prepare" header, the three views, bill-wise dialogs */
.master-sticky-top > .gst-filters { padding: 0.6rem 0 0.2rem; }
.gst-viewswitch { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.gst-viewtoggle.e-btn { min-width: 7.5rem; }
/* The DOCUMENT of a list - the report viewer's document (Day Book): a clean
   listing under its own heading, one line per row, ruled totals. No error or
   warning marks here; those are the "Errors & warnings" view.
   flex 0 0 auto: .gst-main is a flex column and a box with overflow:auto may
   otherwise shrink to NOTHING - which is how the document went missing. */
.gst-dochead { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 0.1rem; font-size: 0.82rem; }
.gst-dochead strong { font-size: 1rem; }
.gst-dochead span { opacity: 0.8; }
.gst-docwrap { flex: 0 0 auto; overflow: auto; max-height: 560px; border: 1px solid var(--shell-border); border-radius: 0.5rem; background: var(--shell-panel-background); }
.gst-stmtwrap, .gst-drillwrap { flex: 0 0 auto; }
.gst-doc { width: max-content; min-width: 100%; font-size: 0.85rem; }
.gst-doc th, .gst-doc td { white-space: nowrap; max-width: 420px; overflow: hidden; text-overflow: ellipsis; padding: 0.3rem 0.6rem; }
.gst-doc thead th {
    position: sticky; top: 0; z-index: 1; opacity: 1;
    background: var(--shell-panel-background-soft, var(--shell-panel-background));
    border-bottom: 2px solid var(--shell-border);
    text-transform: none; letter-spacing: 0; font-size: 0.8rem; font-weight: 700;
}
.gst-doc tbody tr:nth-child(even) td { background: rgba(127, 127, 127, 0.045); }
.gst-doc__sl { width: 3rem; text-align: right; opacity: 0.6; font-variant-numeric: tabular-nums; }
.gst-doc tfoot td { position: sticky; bottom: 0; background: var(--shell-panel-background-soft, var(--shell-panel-background)); font-weight: 700; border-top: 2px solid var(--shell-border); }
.gst-doc tfoot td.gst-num { border-bottom: 3px double var(--shell-text-primary, currentColor); }

/* Errors & warnings - a view of its own, the two kinds apart. */
.gst-viewtoggle--error.e-btn { border-color: #dc2626 !important; }
.gst-viewtoggle--error.e-btn:not(.primary-action) { color: #b91c1c !important; }
.gst-viewtoggle--warn.e-btn { border-color: #d97706 !important; }
.gst-viewtoggle--warn.e-btn:not(.primary-action) { color: #b45309 !important; }
/* The drill button - shown wherever a row can be opened (the report viewer's icon). */
.gst-drillcol { width: 2.2rem; padding-left: 0.3rem !important; padding-right: 0.2rem !important; text-align: center; }
.gst-drill {
    border: 1px solid var(--shell-border); background: var(--shell-panel-background);
    color: var(--shell-button-primary, #0d6efd); border-radius: 6px; cursor: pointer;
    padding: 0 0.35rem; line-height: 1.4; font-size: 0.85rem;
}
.gst-drill:hover { background: var(--shell-hover-background, rgba(37, 99, 235, 0.1)); }
.gst-drill__why { white-space: normal; min-width: 280px; max-width: 460px; font-size: 0.8rem; }
.gst-field--figures { min-width: 320px; flex: 1 1 320px; max-width: 640px; }
.gst-figpick.e-multiselect { width: 100%; }
.gst-issues { flex: 0 0 auto; }
.gst-issues__group { margin: 0.5rem 0 0; font-size: 0.9rem; font-weight: 700; padding-left: 0.55rem; border-left: 4px solid; }
.gst-issues__group--error { color: #b91c1c; border-color: #dc2626; }
.gst-issues__group--warn { color: #b45309; border-color: #d97706; }
html[data-theme-appearance="dark"] .gst-issues__group--error { color: #fca5a5; }
html[data-theme-appearance="dark"] .gst-issues__group--warn { color: #fcd34d; }
.gst-row--sel td, .gst-stmt tr.gst-row--sel td { background: var(--shell-selection-background, rgba(37, 99, 235, 0.14)) !important; }
.gst-stmt tr:focus-visible { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: -2px; }
.gst-doc .gst-row--issue td { background: var(--shell-status-warning-bg, #fff8e1); }
.gst-chartbar { display: grid; grid-template-columns: repeat(3, minmax(160px, 260px)); gap: 0.6rem 1rem; }
/* flex 0 0 auto: .gst-main is a flex column, and a box with a fixed height still
   SHRINKS there when the page is short - the chart came out under 300px tall,
   and the slanted buyer names took nearly all of it (2026-09-20). */
.gst-chart text, .gst-chart tspan { font-family: inherit !important; }
.gst-chart { flex: 0 0 auto; height: 480px; min-height: 480px; border: 1px solid var(--shell-border); border-radius: 0.5rem; background: var(--shell-panel-background); padding: 0.25rem; }
.gst-errdlg { display: flex; flex-direction: column; gap: 0.6rem; height: 100%; min-height: 0; }
.gst-errchips { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.5rem; }
.gst-chipbtn { padding: 0.15rem 0.6rem; border: 1px solid var(--shell-border); border-radius: 999px; background: transparent; color: inherit; font: inherit; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.gst-chipbtn--on { background: var(--shell-accent, #2563eb); border-color: transparent; color: var(--shell-button-primary-text, #fff); }
.gst-chipbtn:focus-visible { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: 2px; }
.gst-errgrid { flex: 1 1 auto; min-height: 320px; }
.gst-errgrid .e-grid { height: 100%; }
/* The Sum footer is part of the grid's fixed frame: only the ROWS scroll, so the
   totals stay in sight however long the list is. (A grid told to be 100% high
   otherwise sizes its rows area to 100% too, and pushes its footer out of the
   box, where it is clipped.) The same for the section grid of the workspace. */
.gst-errgrid .e-grid, .gst-grid .e-grid { display: flex; flex-direction: column; }
.gst-errgrid .e-grid .e-gridcontent, .gst-grid .e-grid .e-gridcontent { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.gst-errgrid .e-grid .e-gridcontent .e-content, .gst-grid .e-grid .e-gridcontent .e-content { height: 100% !important; }
.gst-errgrid .e-grid .e-gridheader, .gst-errgrid .e-grid .e-gridfooter, .gst-errgrid .e-grid .e-gridpager, .gst-errgrid .e-grid .e-groupdroparea, .gst-errgrid .e-grid .e-toolbar,
.gst-grid .e-grid .e-gridheader, .gst-grid .e-grid .e-gridfooter, .gst-grid .e-grid .e-gridpager, .gst-grid .e-grid .e-groupdroparea, .gst-grid .e-grid .e-toolbar { flex: 0 0 auto; }
.gst-errgrid .e-grid .e-summarycell, .gst-grid .e-grid .e-summarycell { text-align: right; font-variant-numeric: tabular-nums; }
/* The row COUNT (a span) reads left; the sums (strong) stay right under their figures. */
.gst-errgrid .e-grid .e-summarycell:has(span.gst-foot), .gst-grid .e-grid .e-summarycell:has(span.gst-foot) { text-align: left; }
/* Row tints by level - the house status colours (red = error, orange =
   warning). The selected row keeps the selection highlight (:not(.e-active)). */
.gst-errgrid .e-grid .e-row.gst-row--error .e-rowcell:not(.e-active) { background: #ffd2d2; color: #7f1d1d; }
.gst-errgrid .e-grid .e-row.gst-row--warning .e-rowcell:not(.e-active) { background: #ffe3c2; color: #7a3e00; }
.gst-errgrid .e-grid .e-row.gst-row--error .e-rowcell:first-child { font-weight: 700; }
html[data-theme-appearance="dark"] .gst-errgrid .e-grid .e-row.gst-row--error .e-rowcell:not(.e-active) { background: rgba(239, 68, 68, 0.24); color: #fecaca; }
html[data-theme-appearance="dark"] .gst-errgrid .e-grid .e-row.gst-row--warning .e-rowcell:not(.e-active) { background: rgba(245, 158, 11, 0.22); color: #fde68a; }
.gst-entry-dlg .e-dlg-content { padding: 0 !important; overflow: auto; }
@media (max-width: 900px) { .gst-chartbar { grid-template-columns: minmax(0, 1fr); } }

/* GST Filing Settings - the module-settings look (groups, one card per setting, editor docked right) */
.gst-setform { display: flex; flex-direction: column; gap: 0.55rem; max-width: 1100px; }
.gst-setgroup { display: flex; flex-direction: column; gap: 0.55rem; }
.gst-setgroup + .gst-setgroup { margin-top: 0.7rem; }
.gst-setgroup__head { margin: 0; padding-bottom: 0.25rem; border-bottom: 1px solid var(--shell-border, #d8dee7); font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--shell-text-secondary, #5b6a7d); }
.gst-setgroup__count { margin-left: 0.4rem; font-weight: 400; font-size: 0.72rem; }
.gst-setcard { display: flex; align-items: center; gap: 1rem; padding: 0.55rem 0.8rem; border: 1px solid var(--shell-border, #d8dee7); border-radius: 6px; background: var(--shell-panel-background, #fff); }
.gst-setcard--dirty { border-color: var(--shell-accent, #4b6bfb); background: color-mix(in srgb, var(--shell-accent, #4b6bfb) 5%, var(--shell-panel-background, #fff)); }
.gst-setcard__text { flex: 1 1 auto; min-width: 0; }
.gst-setcard__name { margin: 0; font-size: 0.88rem; font-weight: 600; color: var(--shell-text-primary, inherit); overflow-wrap: break-word; }
.gst-setcard__id { margin-left: 0.35rem; font-size: 0.72rem; font-weight: 400; color: var(--shell-text-secondary, #5b6a7d); }
.gst-setcard__dirty-tag { margin-left: 0.45rem; font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--shell-accent, #4b6bfb); }
.gst-setcard__desc { margin: 0.15rem 0 0; font-size: 0.8rem; color: var(--shell-text-secondary, #5b6a7d); }
.gst-setcard__editor { flex: 0 0 auto; width: min(20rem, 45%); display: flex; justify-content: flex-end; }
.gst-setcard__editor--wide { width: min(28rem, 50%); }
.gst-setcard__editor > * { width: 100%; }
.gst-setswitch { display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; width: 100%; }
.gst-setswitch__state { font-size: 0.8rem; color: var(--shell-text-secondary, #5b6a7d); min-width: 1.8rem; text-align: right; }
.gst-setcell { width: 100%; min-width: 0; padding: 0.32rem 0.4rem; border: 1px solid var(--shell-border, #d8dee7); border-radius: 3px; background: var(--shell-panel-background, #fff); color: var(--shell-text-primary, inherit); font: inherit; font-size: 0.86rem; }
.gst-setcell:focus { border-color: var(--shell-accent, #4b6bfb); outline: none; }
.gst-setcell:disabled { opacity: 0.55; }
@media (max-width: 760px) { .gst-setcard { flex-direction: column; align-items: stretch; } .gst-setcard__editor, .gst-setcard__editor--wide { width: 100%; } }

/* GST settings form: keep headings clear of the scroll container's edge */
.gst-setform { padding: 0.1rem 0.5rem 0.5rem; box-sizing: border-box; }

/* ════════════════════════════════════════════════════════════════════════
   CRM (phase 1, 2026-09-21) - the pieces every CRM page and dialog shares:
   field groups, the form grid, status chips, the follow-up timeline, the
   sharing list. Global on purpose - isolated CSS does not cross pages, and
   the CRM's dialogs render outside their page. Wrap a page or a dialog body
   in .crm-scope. Shell tokens only, so both themes hold.
   ════════════════════════════════════════════════════════════════════════ */
.crm-group {
    /* every CRM panel runs to the right edge of whatever holds it - page, column or dialog */
    width: 100%;
    box-sizing: border-box;
    align-self: stretch;
    margin: 0;
    padding: 0.85rem 1rem 1rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.6rem;
    min-width: 0;
}
.crm-group > legend {
    padding: 0 0.4rem;
    font-size: 0.74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--shell-text-secondary, var(--shell-text-primary));
}

.crm-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 0.9rem 1rem;
}

.crm-scope .app-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}
.crm-scope .app-field--wide { grid-column: span 2; }
.crm-scope .app-field--full { grid-column: 1 / -1; }

.crm-toolbar__sep {
    align-self: stretch;
    width: 1px;
    margin: 0 0.25rem;
    background: var(--shell-border);
}

.crm-consent {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    padding-top: 0.9rem;
}

.crm-muted {
    margin: 0;
    font-size: 0.84rem;
    color: var(--shell-text-secondary, var(--shell-text-primary));
    opacity: 0.85;
}

/* Status and kind chips - the WORD is always shown; colour is never the only signal. */
.crm-chip {
    display: inline-block;
    margin-inline: 0.35rem;
    padding: 0.08rem 0.55rem;
    border-radius: 999px;
    border: 1px solid var(--shell-border);
    font-size: 0.72rem;
    font-weight: 600;
    vertical-align: middle;
}
.crm-chip--qualified,
.crm-chip--converted { border-color: var(--shell-success, #2e7d32); color: var(--shell-success, #2e7d32); }
.crm-chip--nurturing { border-color: var(--shell-warning, #b26a00); color: var(--shell-warning, #b26a00); }
.crm-chip--disqualified { border-color: var(--shell-danger, #c62828); color: var(--shell-danger, #c62828); }
/* ── CRM record pages (Lead, Opportunity, Contact): FULL-WIDTH CARDS, TWO-COLUMN FIELDS ─────
   Every field group is a card that runs the FULL WIDTH of the form, one under the other;
   inside a card the fields sit in two columns. (The cards were first laid side by side with
   align-items:start - and the pages' own scoped `display:flex` won over the grid, so each
   card shrank to its content and stopped short of the right edge. `stretch` is the point.)
   One column of fields below 640px. Shell tokens only, so both themes hold. */
.crm-scope .crm-form2.crm-form2 {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
    width: 100%;
}
.crm-scope .crm-form2 > .crm-group, .crm-scope .crm-form2 > * { width: 100%; max-width: none; box-sizing: border-box; }
.crm-scope .crm-form2 > .crm-group {
    border: 1px solid var(--shell-border);
    border-radius: 0.9rem;
    padding: 1rem 1.1rem 1.15rem;
    background: var(--shell-surface, transparent);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 6px 18px rgba(0, 0, 0, 0.05);
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.crm-scope .crm-form2 > .crm-group:focus-within {
    border-color: var(--shell-accent, var(--shell-border));
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 10px 26px rgba(0, 0, 0, 0.09);
}
.crm-scope .crm-form2 > .crm-group > legend {
    float: left;                     /* the legend becomes the card's heading, inside the card */
    width: 100%;
    margin: 0 0 0.85rem;
    padding: 0 0 0.55rem;
    border-bottom: 1px solid var(--shell-border);
    font-size: 0.82rem;
    letter-spacing: 0.05em;
    color: var(--shell-text-primary);
}
.crm-scope .crm-form2 > .crm-group > legend + * { clear: both; }
.crm-scope .crm-form2 > .crm-group--full { grid-column: 1 / -1; }
.crm-scope .crm-form2 .crm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.crm-scope .crm-form2 .crm-group--link > .crm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.crm-scope .crm-form2 .app-field--wide { grid-column: span 2; }
.crm-scope .crm-form2 .app-field--full { grid-column: 1 / -1; }

/* Contact > Lead > Opportunity: where this record sits. */
.crm-scope .crm-chain {
    clear: both;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    list-style: none;
    margin: 0 0 0.9rem;
    padding: 0;
    font-size: 0.78rem;
    color: var(--shell-text-secondary, var(--shell-text-primary));
}
.crm-scope .crm-chain > li + li::before {
    content: "\2192";
    margin-right: 0.55rem;
    font-weight: 400;
    opacity: 0.55;
}
.crm-scope .crm-chain > li { margin-right: 0.2rem; }
.crm-scope .crm-chain > .crm-chain__here {
    color: var(--shell-accent, var(--shell-text-primary));
    font-weight: 700;
}
@media (max-width: 640px) {
    .crm-scope .crm-form2 .crm-grid { grid-template-columns: minmax(0, 1fr); }
    .crm-scope .crm-form2 .app-field--wide { grid-column: 1 / -1; }
}

/* ── CRM Board: the Syncfusion Kanban, dressed in the shell's tokens ───────────────────
   Column heads carry count, total, weighted and the stage's share of the pipeline; a card
   is a soft tile with the owner's initials, the money, a probability bar and what is next.
   Won / lost / neglected are said by a left edge AND by words - never by colour alone. */
.crm-scope .crm-kanban { flex: 1 1 auto; min-height: 420px; height: calc(100vh - 330px); }
.crm-scope .crm-kanban .e-kanban { background: transparent; height: 100%; }
.crm-scope .crm-kanban .e-kanban .e-kanban-table { border-spacing: 0.7rem 0; }
.crm-scope .crm-kanban .e-kanban .e-kanban-header .e-header-cells {
    padding: 0; border: 0; background: transparent; height: auto;
}
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-content-row .e-content-cells {
    background: color-mix(in srgb, var(--shell-text-primary) 4%, transparent);
    border: 1px dashed transparent; border-radius: 0 0 0.9rem 0.9rem; padding: 0.35rem;
}
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-content-row .e-content-cells.e-dropping,
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-content-row .e-content-cells .e-target-dropped-clone {
    border-color: var(--shell-accent, var(--shell-border));
}
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-card {
    border: 0; background: transparent; box-shadow: none; margin: 0 0 0.55rem; padding: 0; min-height: 0;
}
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-card.e-selection,
.crm-scope .crm-kanban .e-kanban .e-kanban-content .e-card:focus { outline: 2px solid var(--shell-accent, currentColor); outline-offset: 2px; border-radius: 0.8rem; }

.crm-scope .crm-kb__head {
    display: flex; flex-direction: column; gap: 0.3rem; text-align: left; width: 100%;
    padding: 0.7rem 0.8rem 0.6rem; border: 1px solid var(--shell-border); border-bottom: 0;
    border-radius: 0.9rem 0.9rem 0 0; background: var(--shell-surface, transparent);
    border-top: 3px solid var(--shell-accent, var(--shell-border));
}
.crm-scope .crm-kb__head--won { border-top-color: var(--shell-success, #2e7d32); }
.crm-scope .crm-kb__head--lost { border-top-color: var(--shell-danger, #c62828); }
.crm-scope .crm-kb__headtop { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-size: 0.86rem; }
.crm-scope .crm-kb__count {
    min-width: 1.6rem; padding: 0.05rem 0.45rem; border-radius: 999px; text-align: center; font-size: 0.72rem; font-weight: 600;
    background: color-mix(in srgb, var(--shell-text-primary) 10%, transparent);
}
.crm-scope .crm-kb__headfig { display: flex; justify-content: space-between; gap: 0.5rem; font-size: 0.78rem; font-variant-numeric: tabular-nums; }
.crm-scope .crm-kb__weighted { opacity: 0.7; }
.crm-scope .crm-kb__bar, .crm-scope .crm-kb__probbar {
    height: 4px; border-radius: 999px; overflow: hidden; background: color-mix(in srgb, var(--shell-text-primary) 10%, transparent);
}
.crm-scope .crm-kb__bar > span, .crm-scope .crm-kb__probbar > span { display: block; height: 100%; border-radius: 999px; background: var(--shell-accent, currentColor); }
.crm-scope .crm-kb__more {
    align-self: flex-start; margin-top: 0.15rem; padding: 0.15rem 0.55rem; border-radius: 999px; font-size: 0.72rem; cursor: pointer;
    border: 1px solid var(--shell-border); background: transparent; color: inherit;
}
.crm-scope .crm-kb__more:hover:not(:disabled) { border-color: var(--shell-accent, currentColor); }

.crm-scope .crm-kb__card {
    display: flex; flex-direction: column; gap: 0.4rem; padding: 0.7rem 0.75rem 0.65rem;
    border: 1px solid var(--shell-border); border-left: 3px solid transparent; border-radius: 0.8rem;
    background: var(--shell-surface, transparent); color: var(--shell-text-primary);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 4px 12px rgba(0, 0, 0, 0.05);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.crm-scope .crm-kb__card:hover { transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06), 0 10px 22px rgba(0, 0, 0, 0.1); }
.crm-scope .crm-kb__card--late { border-left-color: var(--shell-danger, #c62828); }
.crm-scope .crm-kb__card--won { border-left-color: var(--shell-success, #2e7d32); }
.crm-scope .crm-kb__card--lost { border-left-color: var(--shell-danger, #c62828); opacity: 0.85; }
.crm-scope .crm-kb__card--pending { opacity: 0.6; }
.crm-scope .crm-kb__cardtop { display: flex; align-items: flex-start; gap: 0.5rem; }
.crm-scope .crm-kb__avatar {
    flex: 0 0 auto; width: 1.75rem; height: 1.75rem; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
    font-size: 0.66rem; font-weight: 700; letter-spacing: 0.02em;
    background: color-mix(in srgb, var(--shell-accent, var(--shell-text-primary)) 18%, transparent);
}
.crm-scope .crm-kb__name { flex: 1 1 auto; min-width: 0; font-size: 0.86rem; line-height: 1.25; overflow-wrap: anywhere; }
.crm-scope .crm-kb__open { flex: 0 0 auto; border: 0; background: transparent; color: inherit; cursor: pointer; opacity: 0.6; font-size: 0.95rem; line-height: 1; padding: 0.1rem 0.2rem; border-radius: 0.3rem; }
.crm-scope .crm-kb__open:hover, .crm-scope .crm-kb__open:focus-visible { opacity: 1; outline: 1px solid var(--shell-border); }
.crm-scope .crm-kb__party { font-size: 0.78rem; opacity: 0.8; overflow-wrap: anywhere; }
.crm-scope .crm-kb__money { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; font-variant-numeric: tabular-nums; }
.crm-scope .crm-kb__amount { font-size: 1rem; font-weight: 700; }
.crm-scope .crm-kb__prob { font-size: 0.74rem; opacity: 0.75; }
.crm-scope .crm-kb__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-size: 0.74rem; }
.crm-scope .crm-kb__due { opacity: 0.85; }
.crm-scope .crm-kb__due--late { color: var(--shell-danger, #c62828); font-weight: 600; opacity: 1; }
.crm-scope .crm-kb__age { opacity: 0.65; }
.crm-scope .crm-kb__tags { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.crm-scope .crm-kb__wait { display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; }
.crm-scope .crm-kb__move { display: flex; align-items: center; gap: 0.4rem; font-size: 0.72rem; opacity: 0.85; }
.crm-scope .crm-kb__move > select {
    flex: 1 1 auto; min-width: 0; padding: 0.15rem 0.3rem; border-radius: 0.4rem; font: inherit;
    border: 1px solid var(--shell-border); background: transparent; color: inherit;
}
@media (prefers-reduced-motion: reduce) { .crm-scope .crm-kb__card { transition: none; } .crm-scope .crm-kb__card:hover { transform: none; } }

/* ── CRM Calendar: the Syncfusion Scheduler in the shell's tokens ──────────────────────
   Appointments are drawn SOLID, other follow-ups as an outline, overdue in the danger
   colour, done ones faded - and the legend says each in words, never by colour alone. */
.crm-scope .crm-cal__body { display: flex; gap: 1rem; align-items: stretch; min-height: 0; }
.crm-scope .crm-cal__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; min-height: 0; }
.crm-scope .crm-cal__board { flex: 1 1 auto; min-height: 520px; height: calc(100vh - 360px); border: 1px solid var(--shell-border); border-radius: 0.9rem; overflow: hidden; }
/* The calendar's filters sit IN the calendar column, not in the sticky toolbar: a toolbar that wraps onto extra
   rows pushes the whole body - and the guide beside it - down the page. */
.crm-scope .crm-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem 0.9rem; margin-bottom: 0.6rem; }
.crm-scope .crm-cal__filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem 0.9rem; }
.crm-scope .crm-cal__switch { align-self: flex-end; min-width: 190px; }
.crm-scope .crm-cal__legend { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; list-style: none; margin: 0; padding: 0; font-size: 0.76rem; }
.crm-scope .crm-cal__legend > li { display: inline-flex; align-items: center; gap: 0.4rem; }
.crm-scope .crm-cal__dot { width: 0.75rem; height: 0.75rem; border-radius: 0.2rem; border: 2px solid var(--shell-accent, currentColor); }
.crm-scope .crm-cal__dot--appt { background: var(--shell-accent, currentColor); }
.crm-scope .crm-cal__dot--manual { border-color: var(--shell-warning, #b26a00); background: var(--shell-warning, #b26a00); }
.crm-scope .crm-cal__dot--off { border-color: var(--shell-text-secondary, currentColor); opacity: 0.55; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--off {
    background: color-mix(in srgb, var(--shell-text-primary) 12%, var(--shell-surface, #fff)); color: var(--shell-text-primary); opacity: 0.7;
}
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--off .e-subject { text-decoration: line-through; color: var(--shell-text-primary); }
.crm-scope .crm-cal__dhead { margin: 0.9rem 0 0.35rem; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.7; }
.crm-scope .crm-cal__dhistory { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.84rem; }
/* the details box of a calendar entry */
.crm-scope .crm-cal__dtitle { margin: 0 0 0.5rem; font-size: 1.05rem; line-height: 1.3; overflow-wrap: anywhere; }
.crm-scope .crm-cal__dchips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.8rem; }
.crm-scope .crm-cal__dlist { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.4rem 1rem; margin: 0; font-size: 0.88rem; }
.crm-scope .crm-cal__dlist > dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.7; padding-top: 0.15rem; }
.crm-scope .crm-cal__dlist > dd { margin: 0; overflow-wrap: anywhere; }
.crm-scope .crm-cal__dnotes { white-space: pre-wrap; }
.crm-scope .crm-cal__repeat { font-weight: 700; font-size: 0.95rem; line-height: 1; }
/* A repeating entry: the Scheduler's own repeat icon, plus a dashed edge - said twice, not by colour. */
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--repeat { outline: 2px dashed color-mix(in srgb, #fff 70%, transparent); outline-offset: -3px; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--repeat .e-recurrence-icon { opacity: 1; }
.crm-scope .crm-cal__dot--late { border-color: var(--shell-danger, #c62828); background: var(--shell-danger, #c62828); }
.crm-scope .crm-cal__dot--done { border-color: var(--shell-success, #2e7d32); opacity: 0.55; }
.crm-scope .crm-cal__board .e-schedule .e-appointment { border-radius: 0.45rem; border: 0; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--appt { background: var(--shell-accent, #1565c0); color: #fff; font-weight: 600; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--task {
    background: color-mix(in srgb, var(--shell-accent, #1565c0) 14%, var(--shell-surface, #fff)); color: var(--shell-text-primary);
    border-left: 3px solid var(--shell-accent, #1565c0);
}
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--task .e-subject,
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--task .e-time,
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--task .e-location { color: var(--shell-text-primary); }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--manual { background: var(--shell-warning, #b26a00); color: #fff; font-weight: 600; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--late { background: var(--shell-danger, #c62828); color: #fff; font-weight: 600; }
.crm-scope .crm-cal__board .e-schedule .e-appointment.crm-cal-ev--done { background: var(--shell-success, #2e7d32); color: #fff; opacity: 0.6; }

/* CRM filter bars (Board, Follow-ups): boxes sit IN the toolbar row. Global as well as in the pages' own
   stylesheets - a filter box without its width takes a whole row each, which is what a stale bundle shows. */
.crm-scope .crm-board__bar, .crm-scope .crm-act__bar { align-items: flex-end; }
.crm-scope .crm-board__filter, .crm-scope .crm-act__filter { flex: 0 1 190px; min-width: 150px; }
.crm-scope .crm-board__filter--search, .crm-scope .crm-act__filter--search { flex: 1 1 240px; }
/* Board (2026-09-21): the card a follow-up will be logged on, the toolbar's word about it, and the narrow probability boxes. */
.crm-scope .crm-board__filter--prob { flex: 0 1 130px; min-width: 110px; }
.crm-scope .crm-board__filter--btn { flex: 0 0 auto; min-width: 0; display: flex; gap: 0.4rem; align-items: flex-end; }
.crm-scope .crm-board__picked { margin-left: 0.35rem; font-size: 0.85rem; opacity: 0.8; max-width: 38ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crm-scope .crm-kb__card--selected { outline: 2px solid var(--shell-accent, #2563eb); outline-offset: 1px; }

/* A share's state (CrmSharePanel): working, waiting, refused, over. */
.crm-chip--ok { border-color: var(--shell-success, #2e7d32); color: var(--shell-success, #2e7d32); }
.crm-chip--wait { border-color: var(--shell-warning, #b26a00); color: var(--shell-warning, #b26a00); }
.crm-chip--bad { border-color: var(--shell-danger, #c62828); color: var(--shell-danger, #c62828); }
.crm-chip--off { opacity: 0.65; }
.crm-share { flex-wrap: wrap; }
.crm-share__dates { display: inline-flex; gap: 0.35rem; align-items: center; }
.crm-share__error { color: var(--shell-danger, #c62828); margin: 0 0 0.4rem; }

.crm-lead__became {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 0.75rem;
    padding: 0.6rem 0.8rem;
    border: 1px solid var(--shell-border);
    border-radius: 0.6rem;
    background: var(--shell-panel-background-soft, transparent);
    font-size: 0.88rem;
}

.crm-lines__foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    margin: 0.5rem 0 0.35rem;
    font-variant-numeric: tabular-nums;
}

.crm-rowbtn.e-btn {
    min-width: 0;
    padding: 0.15rem 0.45rem;
}

.crm-shares,
.crm-history,
.crm-timeline {
    list-style: none;
    margin: 0 0 0.6rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.crm-shares li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.crm-history li { font-size: 0.86rem; }

.crm-timeline__item {
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--shell-border);
    border-inline-start-width: 3px;
    border-radius: 0.45rem;
    font-size: 0.88rem;
}
.crm-timeline__item--open { border-inline-start-color: var(--shell-accent, #2f7d6b); }
.crm-timeline__item--overdue { border-inline-start-color: var(--shell-danger, #c62828); }
.crm-timeline__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.4rem;
    margin-bottom: 0.2rem;
}

.crm-dialog {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}


@media (max-width: 900px) {
    .crm-scope .app-field--wide { grid-column: 1 / -1; }
}
