@import url('https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Inter:wght@400;500;600;700&family=Open+Sans:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700&family=Rubik:wght@400;500;600;700&family=Ubuntu:wght@400;500;700&family=Outfit:wght@400;500;600;700&family=Merriweather:wght@400;700&family=Lora:wght@400;500;600;700&display=swap');

/* Global: never show underline on links - overrides Tabler's a:hover underline */
a, a:hover, a:focus, a:active {
    text-decoration: none !important;
}

/* Prevent ApexCharts SVGs from overflowing card boundaries on wide viewports */
.card:has([data-controller="apexchart"]) {
    overflow: hidden;
}


.steps-no-border {
    margin-left: 0px;
    padding-left: 0px;
    border-left: 0px;
}

/* Remove border-left from counter-based horizontal steps
   (Tabler has a second .steps definition for doc-style vertical steps
   that adds border-left, margin-left, and padding-left - override those) */
.steps.steps-counter {
    border-left: none;
    margin-left: 0;
    padding-left: 0;
    margin-bottom: 0;
}

/* Vodafone font family - WOFF2 optimized for web rendering */
/* Light weight (300) */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone-Light.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone-Light.ttf') format('truetype');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* Normal/Regular weight (400) */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* Medium weight (500) - uses regular as no dedicated medium exists */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone.ttf') format('truetype');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* SemiBold weight (600) - uses bold */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone-Bold.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone-Bold.ttf') format('truetype');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* Bold weight (700) */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone-Bold.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* ExtraBold weight (800) */
@font-face {
    font-family: 'Vodafone';
    src: url('/tabler/custom/fonts/vodafone/Vodafone-ExtraBold.woff2') format('woff2'),
         url('/tabler/custom/fonts/vodafone/Vodafone-ExtraBold.ttf') format('truetype');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
    font-synthesis: none;
}

/* Averta font family (Speakup brand font, sourced from speakup.nl) - only regular/bold weights exist */
@font-face {
    font-family: 'Averta';
    src: url('/tabler/custom/fonts/averta/Averta-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Averta';
    src: url('/tabler/custom/fonts/averta/Averta-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Spline Sans + Spline Sans Mono - CallerConnect's own brand kit fonts (SIL OFL,
   self-hosted per the brand kit's own guidance, see ~/docs/brand/typography/typography.md).
   Rubik (the kit's third/display font) is already covered by the Google Fonts @import above. */
@font-face {
    font-family: 'Spline Sans';
    src: url('/tabler/custom/fonts/spline-sans/spline-sans-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Spline Sans';
    src: url('/tabler/custom/fonts/spline-sans/spline-sans-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Spline Sans';
    src: url('/tabler/custom/fonts/spline-sans/spline-sans-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Spline Sans Mono';
    src: url('/tabler/custom/fonts/spline-sans-mono/spline-sans-mono-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Spline Sans Mono';
    src: url('/tabler/custom/fonts/spline-sans-mono/spline-sans-mono-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

/* Titillium Web - x2com customer brand font (sourced from x2com.nl), only regular/bold exist */
@font-face {
    font-family: 'Titillium Web';
    src: url('/tabler/custom/fonts/titillium-web/TitilliumWeb-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Titillium Web';
    src: url('/tabler/custom/fonts/titillium-web/TitilliumWeb-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Open Sans - self-hosted weights from x2com.nl, layered on top of the Google Fonts
   @import above (which covers 400/500/600/700) so light (300) is also available and
   this specific customer's own asset is used for the weights they provided. */
@font-face {
    font-family: 'Open Sans';
    src: url('/tabler/custom/fonts/open-sans-local/OpenSans-Light.woff2') format('woff2');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Open Sans';
    src: url('/tabler/custom/fonts/open-sans-local/OpenSans-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Open Sans';
    src: url('/tabler/custom/fonts/open-sans-local/OpenSans-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Extra theme-primary colors beyond Tabler's built-in 12 hues + inverted
   (public/tabler/dist/css/tabler-themes.css) - same [data-bs-theme-primary]
   mechanism, just --tblr-primary/--tblr-primary-rgb for a color Tabler doesn't ship. */
[data-bs-theme-primary="amber"] {
    --tblr-primary: #f59e0b;
    --tblr-primary-rgb: 245, 158, 11;
}

[data-bs-theme-primary="emerald"] {
    --tblr-primary: #10b981;
    --tblr-primary-rgb: 16, 185, 129;
}

[data-bs-theme-primary="rose"] {
    --tblr-primary: #f43f5e;
    --tblr-primary-rgb: 244, 63, 94;
}

[data-bs-theme-primary="slate"] {
    --tblr-primary: #475569;
    --tblr-primary-rgb: 71, 85, 105;
}

[data-bs-theme-primary="violet"] {
    --tblr-primary: #8b5cf6;
    --tblr-primary-rgb: 139, 92, 246;
}

[data-bs-theme-primary="coral"] {
    --tblr-primary: #eb4a61;
    --tblr-primary-rgb: 235, 74, 97;
}

/* CallerConnect brand kit exact colors (~/docs/brand/colors/palette.md) - Cyan Signal
   and Signal Blue are the brand's primary/hover pair, Live Orange is the accent/CTA
   color. Distinct from Tabler's own "cyan"/"azure"/"orange", which are close but not
   pixel-accurate to the brand. */
[data-bs-theme-primary="cyan-signal"] {
    --tblr-primary: #11b5e4;
    --tblr-primary-rgb: 17, 181, 228;
}

[data-bs-theme-primary="signal-blue"] {
    --tblr-primary: #1481ba;
    --tblr-primary-rgb: 20, 129, 186;
}

[data-bs-theme-primary="live-orange"] {
    --tblr-primary: #ff5f00;
    --tblr-primary-rgb: 255, 95, 0;
}

:root {
    --bs-body-bg: var(--tblr-bg-surface);
}

/* Figtree font family support for Tabler theme system */
html[data-bs-theme-font="figtree"] {
    --tblr-font-sans-serif: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="figtree"] body {
    font-family: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Vodafone font family support for Tabler theme system */
html[data-bs-theme-font="vodafone"] {
    --tblr-font-sans-serif: Vodafone, Arial, sans-serif;
}

html[data-bs-theme-font="vodafone"] body {
    font-family: Vodafone, Arial, sans-serif;
    font-size: 16px;
    -webkit-font-smoothing: subpixel-antialiased;
    -moz-osx-font-smoothing: auto;
    text-rendering: geometricPrecision;
    font-smooth: always;
    transform: translateZ(0);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* Averta font family support for Tabler theme system */
html[data-bs-theme-font="averta"] {
    --tblr-font-sans-serif: 'Averta', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="averta"] body {
    font-family: 'Averta', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* DM Sans font family support for Tabler theme system */
html[data-bs-theme-font="dm-sans"] {
    --tblr-font-sans-serif: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="dm-sans"] body {
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Roboto font family support for Tabler theme system */
html[data-bs-theme-font="roboto"] {
    --tblr-font-sans-serif: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="roboto"] body {
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Inter font family support for Tabler theme system */
html[data-bs-theme-font="inter"] {
    --tblr-font-sans-serif: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="inter"] body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Open Sans font family support for Tabler theme system */
html[data-bs-theme-font="open-sans"] {
    --tblr-font-sans-serif: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="open-sans"] body {
    font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Poppins font family support for Tabler theme system */
html[data-bs-theme-font="poppins"] {
    --tblr-font-sans-serif: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="poppins"] body {
    font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Montserrat font family support for Tabler theme system */
html[data-bs-theme-font="montserrat"] {
    --tblr-font-sans-serif: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="montserrat"] body {
    font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Nunito font family support for Tabler theme system */
html[data-bs-theme-font="nunito"] {
    --tblr-font-sans-serif: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="nunito"] body {
    font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Rubik font family support for Tabler theme system */
html[data-bs-theme-font="rubik"] {
    --tblr-font-sans-serif: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="rubik"] body {
    font-family: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Ubuntu font family support for Tabler theme system */
html[data-bs-theme-font="ubuntu"] {
    --tblr-font-sans-serif: 'Ubuntu', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="ubuntu"] body {
    font-family: 'Ubuntu', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Spline Sans font family support for Tabler theme system (CallerConnect brand: body) */
html[data-bs-theme-font="spline-sans"] {
    --tblr-font-sans-serif: 'Spline Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

html[data-bs-theme-font="spline-sans"] body {
    font-family: 'Spline Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* Spline Sans Mono font family support for Tabler theme system (CallerConnect brand: meta/code) */
html[data-bs-theme-font="spline-sans-mono"] {
    --tblr-font-sans-serif: 'Spline Sans Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

html[data-bs-theme-font="spline-sans-mono"] body {
    font-family: 'Spline Sans Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

/* Titillium Web font family support for Tabler theme system */
html[data-bs-theme-font="titillium-web"] {
    --tblr-font-sans-serif: 'Titillium Web', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="titillium-web"] body {
    font-family: 'Titillium Web', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Outfit font family support for Tabler theme system */
html[data-bs-theme-font="outfit"] {
    --tblr-font-sans-serif: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

html[data-bs-theme-font="outfit"] body {
    font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Merriweather font family support for Tabler theme system (serif) */
html[data-bs-theme-font="merriweather"] {
    --tblr-font-sans-serif: 'Merriweather', Georgia, Cambria, 'Times New Roman', Times, serif;
}

html[data-bs-theme-font="merriweather"] body {
    font-family: 'Merriweather', Georgia, Cambria, 'Times New Roman', Times, serif;
}

/* Lora font family support for Tabler theme system (serif) */
html[data-bs-theme-font="lora"] {
    --tblr-font-sans-serif: 'Lora', Georgia, Cambria, 'Times New Roman', Times, serif;
}

html[data-bs-theme-font="lora"] body {
    font-family: 'Lora', Georgia, Cambria, 'Times New Roman', Times, serif;
}

/* Optional separate heading font (theme_font_heading), independent of the body font
   (data-bs-theme-font above). Each font sets --theme-heading-font-family (reusing the
   exact same stack as its body-font block); h1-h6 fall back to `inherit` (the body
   font) when no heading override is set - see WhitelabelConfiguration#theme_data_attributes. */
html[data-bs-theme-font-heading="sans-serif"] { --theme-heading-font-family: var(--tblr-font-sans-serif); }
html[data-bs-theme-font-heading="serif"] { --theme-heading-font-family: var(--tblr-font-serif); }
html[data-bs-theme-font-heading="monospace"] { --theme-heading-font-family: var(--tblr-font-monospace); }
html[data-bs-theme-font-heading="comic"] { --theme-heading-font-family: var(--tblr-font-comic); }
html[data-bs-theme-font-heading="figtree"] { --theme-heading-font-family: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="vodafone"] { --theme-heading-font-family: Vodafone, Arial, sans-serif; }
html[data-bs-theme-font-heading="averta"] { --theme-heading-font-family: 'Averta', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="dm-sans"] { --theme-heading-font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="roboto"] { --theme-heading-font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="inter"] { --theme-heading-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="open-sans"] { --theme-heading-font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="poppins"] { --theme-heading-font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="montserrat"] { --theme-heading-font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="nunito"] { --theme-heading-font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="rubik"] { --theme-heading-font-family: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="ubuntu"] { --theme-heading-font-family: 'Ubuntu', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="spline-sans"] { --theme-heading-font-family: 'Spline Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
html[data-bs-theme-font-heading="spline-sans-mono"] { --theme-heading-font-family: 'Spline Sans Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace; }
html[data-bs-theme-font-heading="titillium-web"] { --theme-heading-font-family: 'Titillium Web', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="outfit"] { --theme-heading-font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
html[data-bs-theme-font-heading="merriweather"] { --theme-heading-font-family: 'Merriweather', Georgia, Cambria, 'Times New Roman', Times, serif; }
html[data-bs-theme-font-heading="lora"] { --theme-heading-font-family: 'Lora', Georgia, Cambria, 'Times New Roman', Times, serif; }

h1, h2, h3, h4, h5, h6 {
    font-family: var(--theme-heading-font-family, inherit);
}

/* Set dropdown location */
.ts-dropdown {
    z-index: 10000;
}

/* Color swatch shown before the label in color-picker dropdowns
   (data-controller="color-select" - Primary Color, Sidebar Color). */
.color-select-swatch {
    display: inline-block;
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 0.25rem;
    margin-right: 0.5rem;
    vertical-align: middle;
    /* Outset, not inset - an inset shadow eats into the small square from the
       edges, which visibly darkens already-dark colors more than light ones. */
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.ts-dropdown .active {
    color: var(--tblr-dropdown-link-active-color);
    background-color: var(--tblr-dropdown-link-active-bg);
}

.ts-control, .ts-control input, .ts-dropdown {
    color: var(--bs-body-color);
}

.plugin-dropdown_input .dropdown-input {
    border: 0;
}

.plugin-dropdown_input .dropdown-input:focus  {
    outline-width: 0;
    outline: none;
    border: 0;
}

/* Page specific */
/* Services */
.card-header-avatar {
    margin-left: -5px;
    padding-right: 10px;
}

.card-img-start-service {
    /*border-top-left-radius: calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));*/
    border-bottom-left-radius: calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));
    height: 180px !important;
    width: 160px !important;
}

/* Datatables */
#dt-search-0 {
    padding: .4375rem .75rem;
    font-family: var(--tblr-font-sans-serif), serif;
    font-size: .875rem;
    font-weight: 400;
    line-height: 1.4285714286;
}

.card-no-padding {
    padding-left: 0px !important;
    padding-right: 0px !important;
    padding-bottom: 0px !important;
    padding-top: 0px !important;
}

.dataTable thead {
    background-color: var(--tblr-card-cap-bg);
}

.dataTable thead tr th.dt-left {
    padding: var(--tblr-card-cap-padding-y) var(--tblr-card-cap-padding-x) !important;
}

#dt-length-0 {
    padding: .4375rem .75rem;
    min-width: 80px;
    font-family: var(--tblr-font-sans-serif), serif;
    font-size: .875rem;
    font-weight: 400;
    line-height: 1.4285714286;
}

.note-popover, .note-popover:visited {
    color: var(--tblr-secondary-rgb);
    text-decoration: none;
}

.note-popover:hover, .note-popover:active {
    color: var(--tblr-body-color);
    text-decoration: none;
}

table.dataTable {
    clear: both;
    margin-top: 0px !important;
    margin-bottom: 0px !important;
    max-width: none !important;
    border-collapse: separate !important;
    border-spacing: 0;
}

#call-detail-records-datatable_length label select , #call-detail-records-datatable_filter label input {
    padding: .4375rem 2.25rem .4375rem .75rem !important;
    font-size: .875rem !important;
    border: var(--tblr-border-width) solid var(--tblr-border-color) !important;
    border-radius: var(--tblr-border-radius) !important;
}

/* DataTable controls area background matching header style */
.py-3:has(table.dataTable),
.py-3:has(.dataTables_wrapper),
.dataTables_wrapper .py-3,
.card:has(table.dataTable) .py-3 {
    background-color: var(--tblr-bg-surface-tertiary);
}

/* Account context indicator in top navbar — absolutely centered on page */
.navbar-account-context {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    pointer-events: none;
}

/* Layout */
.navbar-selector {
    width: 300px;
}

.ts-dropdown-content {
    max-height: 300px;
    overflow-y: auto;
}

/* Remove underline from list-group navigation items on hover */
.list-group-item-action:hover {
    text-decoration: none;
}

/* Cursor pointer utility class */
.cursor-pointer {
    cursor: pointer;
}

/* Cursor move utility class for drag handles */
.cursor-move {
    cursor: move;
}

/* BetterStack Status Item Link */
.status-item-link {
    cursor: pointer;
    transition: background-color 0.15s ease-in-out;
}

.status-item-link:hover {
    background-color: var(--tblr-bg-surface-secondary) !important;
}

/* BetterStack Uptime Bar Component */
.uptime-bar-container {
    margin-top: 0.35rem;
    margin-bottom: 0;
}

/* Grid layout for daily bars */
.uptime-bars-grid {
    display: flex;
    gap: 2px;
    width: 100%;
}

.uptime-bar-item {
    flex: 1;
    min-width: 0;
}

.uptime-bar-single {
    display: block;
    width: 100%;
    height: 16px;
    border-radius: 2px;
    overflow: hidden;
    background-color: #e9ecef;
    position: relative;
}

.uptime-segment {
    display: block;
    height: 100%;
    width: 100%;
    transition: all 0.2s ease;
    cursor: pointer;
    position: relative;
}

.uptime-segment:hover {
    opacity: 0.9;
    transform: scaleY(1.2);
}

/* Uptime status colors */
.uptime-excellent {
    background-color: #2fb344; /* Green - 99.9%+ */
}

.uptime-good {
    background-color: #f59f00; /* Yellow - 99.0-99.9% */
}

.uptime-degraded {
    background-color: #fd7e14; /* Orange - <99% but not down */
}

.uptime-down {
    background-color: #d63939; /* Red - Down */
}

.uptime-unknown {
    background-color: #868e96; /* Gray - No data */
}

/* Availability percentage display */
.availability-percentage {
    font-size: 0.875rem;
    font-weight: 600;
    margin-left: 0.5rem;
}

.availability-label {
    font-size: 0.75rem;
    color: #6c757d;
    margin-bottom: 0.25rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .uptime-bar-single {
        height: 12px;
    }

    .uptime-bars-grid {
        gap: 1px;
    }
}

/* Drag-and-drop styles for action reordering */

/* Drag handle column - left side of card */
.drag-handle-column {
    width: 40px !important;
    min-width: 40px !important;
    max-width: 40px !important;
    background-color: #f8f9fa !important;
    border-right: 1px solid #e6e7e9 !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 4px 0 0 4px !important;
    flex-shrink: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
}

/* Drag handle - grip icon */
.drag-handle {
    cursor: grab;
    opacity: 0.4;
    transition: opacity 0.2s ease;
    color: var(--tblr-secondary);
}

.drag-handle:hover {
    opacity: 0.8;
}

.drag-handle:active {
    cursor: grabbing;
}

/* Ghost element - shows where item will be dropped */
.sortable-ghost {
    opacity: 0.4;
    background: var(--tblr-bg-surface-secondary);
    border: 2px dashed var(--tblr-primary);
}

/* Chosen element - item being dragged */
.sortable-chosen {
    cursor: grabbing;
}

/* Drag element - the element being dragged */
.sortable-drag {
    opacity: 0.8;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    transform: rotate(3deg);
}

/* Fallback element for non-HTML5 browsers */
.sortable-fallback {
    opacity: 0.8;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

/* Action card during drag */
.action-card.sortable-chosen .drag-handle {
    opacity: 1;
}

/* Disable pointer events on delete/edit buttons during drag */
.sortable-chosen .btn-action,
.sortable-chosen .btn {
    pointer-events: none;
}
/* ========================================
   Turbo Frames + Pagy Tables Styling
   (for DataTables migration)
   ======================================== */

/* Ensure table cells are vertically centered (matches DataTables) */
.table-vcenter tbody td {
    vertical-align: middle !important;
}

/* Top controls area background (generic, works without DataTables) */
.card .card-body.py-3:has(+ .card-body.card-no-padding) {
    background-color: var(--tblr-bg-surface-tertiary);
}

/* ========================================
   Accounts Table Enhancements
   ======================================== */

/* Avatar badge for user counts - REMOVED */
/*
.avatar-status-badge {
    position: absolute;
    bottom: -2px;
    right: -2px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: 600;
    line-height: 18px;
    color: white;
    background-color: var(--tblr-primary);
    border-radius: 10px;
    border: 2px solid white;
    text-align: center;
    z-index: 2;
}
*/

/* Service health indicator dots - REMOVED (replaced with Tabler badges) */
/*
.avatar-status-indicator {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 2px solid white;
    z-index: 2;
}

.avatar-status-indicator.status-success {
    background-color: var(--tblr-success);
}

.avatar-status-indicator.status-warning {
    background-color: var(--tblr-warning);
}

.avatar-status-indicator.status-danger {
    background-color: var(--tblr-danger);
}

.avatar-status-indicator.status-secondary {
    background-color: var(--tblr-secondary);
}
*/

/* Clickable service avatars */
.avatar-list a {
    text-decoration: none;
}

.avatar-list .avatar:hover {
    opacity: 0.8;
    transition: opacity 0.2s ease;
}

/* Status-based row borders */
tr.row-status-active {
    border-left: 3px solid var(--tblr-success);
}

tr.row-status-setup {
    border-left: 3px solid var(--tblr-warning);
}

tr.row-status-suspended {
    border-left: 3px solid var(--tblr-orange);
}

tr.row-status-cancelled {
    border-left: 3px solid var(--tblr-danger);
}

/* Row hover: a row highlights and takes the pointer only when a click on it opens something - its View is marked
   data-row-link (row-link controller). Every row used to light up and show a pointer, which promised a click that
   mostly did nothing (PostHog review, Sep 2026). .table-hover keeps the tint for reading along a row, no pointer. */
.table-hover tbody tr:hover {
    background-color: var(--tblr-bg-surface-secondary);
    transition: background-color 0.15s ease;
}
tbody tr:has([data-row-link]) { cursor: pointer; }
tbody tr:has([data-row-link]):hover {
    background-color: var(--tblr-bg-surface-secondary);
    transition: background-color 0.15s ease;
}

/* Sortable column headers */
.sortable-header {
    cursor: pointer;
    user-select: none;
    position: relative;
    padding-right: 20px !important;
}

.sortable-header:hover {
    background-color: var(--tblr-bg-surface-secondary);
}

.sortable-header .sort-icon {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 12px;
    opacity: 0.5;
}

.sortable-header.sorted .sort-icon {
    opacity: 1;
}

/* Search result highlighting */
.search-highlight {
    background-color: var(--tblr-yellow);
    padding: 2px 0;
    font-weight: 600;
}

/* Quick actions (shown on row hover) - REMOVED */
/*
.quick-actions {
    opacity: 0;
    transition: opacity 0.2s ease;
    display: inline-flex;
    gap: 4px;
    margin-right: 8px;
}

tr:hover .quick-actions {
    opacity: 1;
}

.quick-actions .btn {
    padding: 2px 6px;
    font-size: 12px;
}
*/

/* Status filter buttons */
.status-filters {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.status-filter-btn {
    font-size: 0.875rem;
    padding: 0.375rem 0.75rem;
}

.status-filter-btn.active {
    background-color: var(--tblr-primary);
    color: white;
    border-color: var(--tblr-primary);
}

/* Expandable row indicator */
.expand-row-icon {
    cursor: pointer;
    transition: transform 0.2s ease;
}

.expand-row-icon.expanded {
    transform: rotate(90deg);
}

/* Expandable row content */
.expandable-row-content {
    background-color: var(--tblr-bg-surface-secondary);
    border-top: 1px solid var(--tblr-border-color);
    padding: 1rem;
}

/* Hierarchical account indicators */
.hierarchical-indent {
    margin-left: 1.5rem;
    position: relative;
}

.hierarchical-indent::before {
    content: '';
    position: absolute;
    left: -12px;
    top: 50%;
    width: 8px;
    height: 1px;
    background-color: var(--tblr-border-color);
}

/* ========================================
   Account Switcher Button Styling
   ======================================== */

/* Unstyled button for service avatar links with account switching */
.btn-link-unstyled {
    background: none !important;
    border: none !important;
    padding: 0 !important;
    margin: 0 !important;
    font: inherit !important;
    color: inherit !important;
    cursor: pointer !important;
    text-decoration: none !important;
    display: inline-block !important;
    line-height: inherit !important;
}

.btn-link-unstyled:hover,
.btn-link-unstyled:focus,
.btn-link-unstyled:active {
    background: none !important;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
    color: inherit !important;
}

/* Ensure button_to form is also unstyled */
.btn-link-unstyled form {
    display: inline-block !important;
    margin: 0 !important;
    padding: 0 !important;
}

/* ========================================
   Dashboard Component Styling
   ======================================== */

/* Health Indicator Cards */
.health-indicator {
    border-radius: var(--tblr-border-radius);
    transition: all 0.2s ease;
    background-color: var(--tblr-bg-surface);
}

.health-indicator:hover {
    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
}

/* Timeline Component Styling */
.list-timeline {
    position: relative;
    padding-left: 2rem;
}

.list-timeline-item {
    position: relative;
    padding-bottom: 1.5rem;
}

.list-timeline-item:not(:last-child)::before {
    content: '';
    position: absolute;
    left: -1.5rem;
    top: 2rem;
    bottom: -0.5rem;
    width: 2px;
    background-color: rgba(var(--tblr-border-color-rgb), 1);
}

.list-timeline-icon {
    position: absolute;
    left: -2rem;
    top: 0;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background-color: var(--tblr-bg-surface);
    border: 2px solid rgba(var(--tblr-border-color-rgb), 1);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    z-index: 1;
}

.list-timeline-time {
    font-size: 0.75rem;
    margin-bottom: 0.25rem;
}

.list-timeline-title {
    font-weight: 600;
    margin-bottom: 0.25rem;
}

.list-timeline-content {
    padding-left: 0.5rem;
}

/* Action Items & Investigation Items Styling */
.list-group-item .avatar {
    width: 2.5rem;
    height: 2.5rem;
    font-size: 1.25rem;
}

/* Quick Stats Card Progress Bars */
.card-progress {
    height: 0.25rem;
}

/* Partner Dashboard Styling */
.partner-dashboard .h1 {
    font-size: 2.5rem;
    font-weight: 600;
}

.partner-dashboard .card-table thead {
    background-color: var(--tblr-bg-surface-secondary);
}

/* Dashboard Tab Navigation */
.nav-tabs-lg .nav-link {
    padding: 0.75rem 1.5rem;
    font-weight: 500;
}

/* Empty State Styling */
.empty {
    padding: 3rem 1rem;
}

.empty-icon {
    margin-bottom: 1rem;
}

/* Badge Enhancements for Dashboard */
.badge {
    font-weight: 500;
}

/* Responsive Dashboard Adjustments */
@media (max-width: 767.98px) {
    .health-indicator {
        margin-bottom: 1rem;
    }

    .list-timeline {
        padding-left: 1.5rem;
    }

    .list-timeline-icon {
        left: -1.75rem;
        width: 1.5rem;
        height: 1.5rem;
        font-size: 0.875rem;
    }

    .partner-dashboard .h1 {
        font-size: 2rem;
    }
}

/* Dashboard Chart Container */
.dashboard-chart {
    min-height: 300px;
    height: 100%;
}

/* ECharts Canvas Visibility Fix */
[data-controller="dashboard-echarts"] {
    position: relative;
    width: 100% !important;
}

[data-controller="dashboard-echarts"] canvas {
    display: block !important;
    position: relative !important;
    z-index: 1 !important;
    opacity: 1 !important;
    visibility: visible !important;
}

/* Status Indicator Colors */
.status-indicator {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    margin-right: 0.5rem;
}

.status-indicator.operational {
    background-color: var(--tblr-green);
}

.status-indicator.degraded {
    background-color: var(--tblr-yellow);
}

.status-indicator.critical {
    background-color: var(--tblr-red);
}

/* ========================================
   Print Optimization for Support Cases
   ======================================== */

@media print {
    /* Hide navigation and non-essential elements */
    .navbar,
    .page-header,
    .d-print-none,
    .card-footer,
    .btn,
    button,
    .dropzone,
    .form-control,
    textarea,
    .dropdown {
        display: none !important;
    }

    /* Full width layout */
    .container-xl,
    .container {
        max-width: 100% !important;
        padding: 0 !important;
    }

    /* Remove margins and spacing */
    body {
        margin: 0;
        padding: 20px;
    }

    .page-body {
        padding: 0 !important;
    }

    /* Card styling for print */
    .card {
        border: 1px solid #ddd !important;
        page-break-inside: avoid;
        margin-bottom: 20px;
        box-shadow: none !important;
    }

    .card-header {
        background-color: #f8f9fa !important;
        border-bottom: 2px solid #ddd !important;
        padding: 10px 15px !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .card-body {
        padding: 15px !important;
    }

    /* Case header card */
    .card-header h3 {
        font-size: 18px !important;
        margin: 0 !important;
    }

    /* Metadata grid */
    .row {
        display: flex !important;
        flex-wrap: wrap !important;
    }

    .col,
    .col-md-2,
    .col-md-3 {
        flex: 0 0 33.333% !important;
        max-width: 33.333% !important;
        padding: 10px !important;
    }

    /* Badge styling */
    .badge {
        border: 1px solid currentColor !important;
        padding: 2px 6px !important;
        font-size: 11px !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* Timeline styling */
    .list-group-item {
        border: 1px solid #ddd !important;
        padding: 8px !important;
        page-break-inside: avoid;
    }

    /* Avatar icons */
    .avatar {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* File list */
    .list-group {
        border: 1px solid #ddd !important;
    }

    /* Chat bubbles */
    .chat-bubble {
        border: 1px solid #ddd !important;
        padding: 10px !important;
        margin-bottom: 10px !important;
        page-break-inside: avoid;
    }

    /* Links - show URL */
    a[href]:after {
        content: none !important; /* Don't show URLs after links for cleaner print */
    }

    /* Table styling */
    table {
        page-break-inside: auto;
    }

    tr {
        page-break-inside: avoid;
        page-break-after: auto;
    }

    /* Print header with case number */
    .card:first-child::before {
        content: "Support Case Report";
        display: block;
        font-size: 24px;
        font-weight: bold;
        margin-bottom: 10px;
        padding-bottom: 10px;
        border-bottom: 2px solid #000;
    }

    /* Preserve colors for status indicators */
    .bg-blue,
    .bg-blue-lt,
    .text-blue,
    .bg-yellow,
    .bg-yellow-lt,
    .text-yellow,
    .bg-green,
    .bg-green-lt,
    .text-green,
    .bg-red,
    .bg-red-lt,
    .text-red {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
    }

    /* SVG icons */
    svg {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* Ensure single column layout for main content */
    .col-8,
    .col-4 {
        flex: 0 0 100% !important;
        max-width: 100% !important;
    }

    /* Activity timeline compact for print */
    .list-timeline-item {
        padding-bottom: 0.5rem !important;
    }

    /* Hide upload areas */
    .dz-message,
    .dropzone {
        display: none !important;
    }
}

/* ========================================
   Support Case File List Hover Effects
   ======================================== */

/* File list item default state */
.file-list-item .file-download-btn {
    display: none;
}

.file-list-item .file-size {
    display: block;
}

/* File list item hover state */
.file-list-item:hover .file-download-btn {
    display: block;
}

.file-list-item:hover .file-size {
    display: none;
}

/* Smooth transition for hover effect */
.file-list-item {
    transition: background-color 0.2s ease;
}

/* Condensed file list rows */
.file-list-item {
    padding: 0.5rem 1rem !important;
}

.file-list-item .d-flex {
    min-height: 32px;
}

/* Smaller icon size for condensed layout */
.file-list-item i.ti {
    font-size: 1.5rem;
}

/* ========================================
   Table Dropdown Overflow Fix
   ======================================== */

/* Fix dropdown menus being clipped by table-responsive overflow */
/* When table has few entries, dropdowns should appear above the table */
.card .table-responsive {
    overflow: visible;
}


/* Ensure dropdown menus always appear on top */
.table .dropdown-menu {
    z-index: 1050;
    position: absolute;
}

/* For tables within cards, ensure card doesn't clip dropdown */
.card-body.card-no-padding {
    overflow: visible;
}

/* Ensure btn-list dropdowns in tables display correctly */
.table .btn-list .dropdown {
    position: static;
}

.table .btn-list .dropdown-menu {
    position: absolute;
    z-index: 1050;
}

/* ========================================
   Service Avatar Image Mode
   ======================================== */

/* When using mode: :image, the avatar contains an img tag instead of background-image */
.avatar .avatar-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: inherit;
}

/* ========================================
   TomSelect Dark Mode
   ======================================== */

/* ========================================
   Dark Mode: Form Controls
   ======================================== */

[data-bs-theme="dark"] .form-control:disabled,
[data-bs-theme="dark"] .form-control[readonly] {
    background-color: var(--tblr-bg-surface-secondary) !important;
    color: var(--tblr-body-color) !important;
    border-color: var(--tblr-border-color) !important;
    opacity: 0.7;
}

[data-bs-theme="dark"] .form-select:disabled {
    background-color: var(--tblr-bg-surface-secondary) !important;
    color: var(--tblr-body-color) !important;
    border-color: var(--tblr-border-color) !important;
    opacity: 0.7;
}

[data-bs-theme="dark"] .ts-control {
    background-color: var(--tblr-bg-forms) !important;
    border-color: var(--tblr-border-color) !important;
    color: var(--tblr-body-color) !important;
}

[data-bs-theme="dark"] .ts-control input {
    color: var(--tblr-body-color) !important;
}

[data-bs-theme="dark"] .ts-dropdown,
[data-bs-theme="dark"] .ts-dropdown.single {
    background-color: var(--tblr-bg-surface) !important;
    border-color: var(--tblr-border-color) !important;
    color: var(--tblr-body-color) !important;
}

[data-bs-theme="dark"] .ts-dropdown .ts-dropdown-content .option,
[data-bs-theme="dark"] .ts-dropdown .ts-dropdown-content .optgroup-header,
[data-bs-theme="dark"] .ts-dropdown .ts-dropdown-content .no-results {
    color: var(--tblr-body-color) !important;
}

[data-bs-theme="dark"] .ts-dropdown .dropdown-input,
[data-bs-theme="dark"] .ts-dropdown .dropdown-input input {
    background-color: var(--tblr-bg-surface-secondary) !important;
    color: var(--tblr-body-color) !important;
    border-color: var(--tblr-border-color) !important;
}

[data-bs-theme="dark"] .ts-dropdown .active {
    background-color: var(--tblr-dropdown-link-active-bg) !important;
    color: var(--tblr-dropdown-link-active-color) !important;
}

/* ========================================
   TomSelect Height Normalization
   ======================================== */

/* Match TomSelect control height to standard form-select (40px) */
.ts-wrapper.single .ts-control {
    padding: .625rem .75rem !important;
    min-height: 0 !important;
    height: 40px;
    line-height: 1.4285714286;
    display: flex;
    align-items: center;
}

/* Ensure input inside TomSelect doesn't add extra height */
.ts-wrapper.single .ts-control input {
    min-height: 0 !important;
    height: auto !important;
    padding: 0 !important;
    line-height: inherit;
}

/* Remove extra padding from selected item */
.ts-wrapper.single .ts-control > .item {
    padding: 0;
    margin: 0;
    line-height: inherit;
}


/* ========================================
   Edge-to-edge Table Container
   ======================================== */

/* Extends table to card edges - use on .table-responsive inside card-body */
.table-edge {
    margin: 0 -20px -17px -20px;
    border-top: 1px solid var(--tblr-border-color);
}

/* Compensate first/last cell padding to align with card-body content */
.table-edge .table th:first-child,
.table-edge .table td:first-child {
    padding-left: 20px;
}

.table-edge .table th:last-child,
.table-edge .table td:last-child {
    padding-right: 20px;
}

/* Remove border from last row */
.table-edge .table tbody tr:last-child td {
    border-bottom: none;
}

/* Modal variant — extends table to the modal-body edges.
   Tabler's .modal-body default padding is 1.5rem (24px); the negative
   margins cancel that so the table flush-mounts to the modal walls. The
   bottom margin also cancels the modal-body's bottom padding so the last
   row sits tight against the modal-footer divider. */
.table-edge-modal {
    margin: 0 -1.5rem -1.5rem -1.5rem;
    border-top: 1px solid var(--tblr-border-color);
}

/* First column holds the service-brand avatar — sit it closer to the
   modal's left wall (1rem vs 1.5rem) so the icon reads as leading art
   rather than being tucked behind the action name column. The
   neighbouring (second) column gets explicit left padding so the action
   name doesn't butt up against the avatar. */
.table-edge-modal .table th:first-child,
.table-edge-modal .table td:first-child {
    padding-left: 1rem;
    padding-right: 0;
}

.table-edge-modal .table th:nth-child(2),
.table-edge-modal .table td:nth-child(2) {
    padding-left: 0.75rem;
}

.table-edge-modal .table th:last-child,
.table-edge-modal .table td:last-child {
    padding-right: 1.5rem;
}

.table-edge-modal .table tbody tr:last-child td {
    border-bottom: none;
}

/* ========================================
   Invoice-Style Order Table
   Aligns cell content with card-lg body padding
   while table borders stretch edge-to-edge
   ======================================== */

table.table-invoice th:first-child,
table.table-invoice td:first-child {
    padding-left: 3.5rem !important;
}

table.table-invoice th:last-child,
table.table-invoice td:last-child {
    padding-right: 3.5rem !important;
}

/* ========================================
   Reapop-Style Notifications
   ======================================== */

/* Container - fixed bottom-right */
.reapop-container {
    position: fixed;
    z-index: 9999;
    bottom: 20px;
    right: 20px;
    max-width: 400px;
    display: flex;
    flex-direction: column-reverse;
    gap: 12px;
    pointer-events: none;
}

/* Notification card */
.reapop-notification {
    display: flex;
    width: 350px;
    position: relative;
    border-radius: 5px;
    border: 1px solid rgba(0, 0, 0, 0.1);
    box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 8px 2px;
    background-color: rgb(47, 47, 54);
    color: rgb(255, 255, 255);
    animation: reapop-slide-in 0.3s ease-out;
    pointer-events: all;
}

/* Status icons */
.reapop-notification-icon {
    width: 20px;
    height: 20px;
    margin: 12px 0 12px 15px;
    flex-shrink: 0;
    align-self: flex-start;
}

/* Icon colors by variant */
.reapop-notification--success .reapop-notification-icon {
    color: rgb(50, 211, 139);
}

.reapop-notification--info .reapop-notification-icon {
    color: rgb(65, 146, 255);
}

.reapop-notification--warning .reapop-notification-icon {
    color: rgb(255, 193, 7);
}

.reapop-notification--danger .reapop-notification-icon {
    color: rgb(239, 68, 68);
}

/* Image avatar (when present, replaces icon) */
.reapop-notification-image-container {
    padding: 10px 0 10px 15px;
    flex-shrink: 0;
}

.reapop-notification-image {
    display: inline-flex;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    background-size: cover;
    background-position: center;
}

/* Content area */
.reapop-notification-meta {
    flex: 1;
    padding: 10px 15px;
    min-width: 0;
}

.reapop-notification-title {
    margin: 0 0 4px 0;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.42857;
    color: rgb(255, 255, 255);
}

.reapop-notification-message {
    margin: 0;
    font-size: 14px;
    line-height: 1.42857;
    color: rgb(185, 194, 203);
}

/* Dismiss button */
.reapop-notification-dismiss {
    width: 12px;
    height: 12px;
    margin: 14px 10px;
    cursor: pointer;
    color: rgb(185, 194, 203);
    flex-shrink: 0;
    transition: color 0.2s ease;
}

.reapop-notification-dismiss:hover {
    color: rgb(255, 255, 255);
}

/* Action buttons container */
.reapop-notification-buttons {
    display: flex;
    flex-direction: column;
    border-left: 1px solid rgb(70, 76, 95);
    flex-shrink: 0;
}

.reapop-notification-button {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    min-height: 40px;
    min-width: 90px;
    max-width: 150px;
    padding: 0 15px;
    background: rgb(47, 47, 54);
    border: none;
    color: rgb(255, 255, 255);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.2s ease;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.reapop-notification-buttons .reapop-notification-button:not(:last-child) {
    border-bottom: 1px solid rgb(70, 76, 95);
}

.reapop-notification-button:hover {
    background-color: rgb(60, 60, 70);
    color: rgb(255, 255, 255);
    text-decoration: none;
}

/* Notification without buttons - ensure dismiss is visible */
.reapop-notification:not(:has(.reapop-notification-buttons)) .reapop-notification-dismiss {
    margin-right: 15px;
}

/* Animations */
@keyframes reapop-slide-in {
    from {
        opacity: 0;
        transform: translateX(100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes reapop-slide-out {
    from {
        opacity: 1;
        transform: translateX(0);
    }
    to {
        opacity: 0;
        transform: translateX(100%);
    }
}

.reapop-notification.dismissing {
    animation: reapop-slide-out 0.3s ease-in forwards;
}

/* Respect reduced motion preference - instant transitions instead of animations */
@media (prefers-reduced-motion: reduce) {
    .reapop-notification {
        animation: none;
    }

    .reapop-notification.dismissing {
        animation: none;
        opacity: 0;
        transition: opacity 0.1s ease-out;
    }
}


/* Table Export Dropdown - hide Bootstrap dropdown arrow for icon-only button */
/* A card action's icon tag at the size of the SVG icons it replaced (Tabler draws .icon at 1.25rem) */
.btn-actions .btn-action > .ti { font-size: 1.25rem; line-height: 1; }
.card-actions.btn-actions { gap: 0.5rem; } /* a little air between a card's actions (owner, 16 Oct 2026) */

.card-actions .btn-action.dropdown-toggle::after {
    display: none;
}

/* Card with sidebar layout - uniform minimum height with footer at bottom */
.card-sidebar-layout {
    min-height: 800px;
    display: flex;
    flex-direction: column;
}

/* Form wrapper grows to fill space */
.card-sidebar-layout > form {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* Row inside form grows */
.card-sidebar-layout > form > .row {
    flex: 1;
}

/* Direct row child (no form wrapper - e.g., security page) grows */
.card-sidebar-layout > .row {
    flex: 1;
}

/* Content column fills height */
.card-sidebar-layout .row > .col-12.col-md-9 {
    min-height: 100%;
}

/* Footer stays at bottom */
.card-sidebar-layout > .card-footer,
.card-sidebar-layout > form > .card-footer {
    margin-top: auto;
}

/* ========================================
   Setup Wizard - Multi-step Onboarding
   ======================================== */

/* Wizard Progress Bar Container */
.wizard-progress {
    background-color: var(--tblr-bg-surface);
    border-bottom: 1px solid var(--tblr-border-color);
    position: sticky;
    top: 0;
    z-index: 1000;
}

.wizard-progress .steps {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    align-items: flex-start;
}

/* Individual Step */
.wizard-progress .step {
    flex: 1;
    text-align: center;
    position: relative;
    opacity: 0.5;
    transition: opacity 0.2s ease;
}

.wizard-progress .step.active {
    opacity: 1;
    font-weight: 600;
}

.wizard-progress .step.completed {
    opacity: 0.8;
}

.wizard-progress .step.skipped {
    opacity: 0.4;
    text-decoration: line-through;
}

/* Step Number Circle */
.wizard-progress .step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background-color: var(--tblr-primary);
    color: white;
    margin-bottom: 0.5rem;
    font-weight: 600;
    transition: background-color 0.2s ease;
}

.wizard-progress .step.completed .step-number {
    background-color: var(--tblr-success);
}

.wizard-progress .step.skipped .step-number {
    background-color: var(--tblr-secondary);
}

/* Step Title */
.wizard-progress .step-title {
    display: block;
    font-size: 0.875rem;
    margin-top: 0.5rem;
}

/* Progress Percentage Bar */
.wizard-progress .progress {
    height: 4px;
    margin-bottom: 0;
    background-color: var(--tblr-bg-surface-tertiary);
}

.wizard-progress .progress-bar {
    background-color: var(--tblr-primary);
    transition: width 0.3s ease;
}

/* Wizard Step Content Area */
.wizard-step-content {
    min-height: 500px;
    padding: 2rem 0;
}

/* Wizard Navigation Footer */
.wizard-footer {
    background-color: var(--tblr-bg-surface);
    border-top: 1px solid var(--tblr-border-color);
    position: sticky;
    bottom: 0;
    z-index: 1000;
    padding: 1rem 0;
}

/* Skip Button Styling */
.wizard-footer .btn-link {
    text-decoration: none;
    padding: 0.5rem 1rem;
    color: var(--tblr-secondary);
    transition: color 0.2s ease;
}

.wizard-footer .btn-link:hover {
    text-decoration: underline;
    color: var(--tblr-body-color);
}

/* Wizard Feature Cards */
.wizard-feature-card {
    height: 100%;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.wizard-feature-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* Wizard Carrier Option Cards */
.wizard-carrier-option {
    cursor: pointer;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.wizard-carrier-option:hover {
    border-color: var(--tblr-primary);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.wizard-carrier-option.selected {
    border-color: var(--tblr-primary);
    border-width: 2px;
    background-color: var(--tblr-primary-lt);
}

/* Progressive Disclosure - Service Connection Cards */
.wizard-services-connection .card.border-dashed {
    border-style: dashed;
    border-width: 2px;
    background-color: var(--tblr-bg-surface-secondary);
}

/* Responsive Wizard Adjustments */
@media (max-width: 767.98px) {
    .wizard-progress .steps {
        gap: 0.5rem;
    }

    .wizard-progress .step-number {
        width: 2rem;
        height: 2rem;
        font-size: 0.875rem;
    }

    .wizard-progress .step-title {
        font-size: 0.75rem;
    }

    .wizard-step-content {
        padding: 1rem 0;
    }

    .wizard-footer {
        padding: 0.75rem 0;
    }
}

/* ========================================
   Step Indicator - Animated Progress Line
   ======================================== */

/* Container for animated step indicator - use inner wrapper for the line */
.steps-animated {
    position: relative;
}

/* Progress line wrapper - positioned behind step circles */
.steps-animated .step-progress-line {
    position: absolute;
    top: calc(var(--tblr-steps-dot-size, 1.5rem) / 2);
    left: var(--line-start, 8.33%);
    right: var(--line-start, 8.33%);
    height: 2px;
    margin-top: -1px;
    background-color: var(--tblr-border-color);
    z-index: 0;
    pointer-events: none;
}

/* Green progress overlay inside the line wrapper */
.steps-animated .step-progress-line::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: var(--progress-width, 0%);
    background-color: var(--tblr-green);
    transition: width 0.8s ease-out;
}

/* Step items need to be positioned above the line */
.steps-animated .step-item {
    position: relative;
    z-index: 1;
}

/* Override Tabler's step-item::after connector lines (hide them, we draw our own) */
.steps-animated.steps-counter .step-item::after {
    display: none;
}

/* Step counter circle styling */
.steps-animated.steps-counter .step-item::before {
    transition: transform 0.3s ease-out, box-shadow 0.3s ease-out;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

/* Increase gap between circle and label (default is 1.5rem = dot size) */
.steps-animated.steps-counter .step-item {
    padding-top: 1.75rem;
}


/* Future/inactive step circles: solid grey background */
.steps-animated.steps-green .step-item:not(.step-completed):not(.step-current):not(.step-skipped):not(.active)::before {
    background-color: var(--tblr-border-color);
    color: #fff;
}

/* Make step links cover the entire step item (circle + label) */
.steps-animated .step-item .step-link {
    display: block;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}
.steps-animated .step-item .step-link:hover {
    text-decoration: none;
    color: inherit;
}

/* Pop animation for step counter */
@keyframes step-pop {
    0% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.3);
    }
    100% {
        transform: scale(1);
    }
}

/* Apply pop animation when step becomes active */
.steps-animated .step-item.step-popping::before {
    animation: step-pop 0.4s ease-out;
}

/* Green glow effect on active step circle */
.steps-animated.steps-green .step-item.active::before {
    box-shadow: 0 0 0 4px rgba(47, 179, 68, 0.25);
}

/* Completed step: green fill with checkmark */
.steps-animated.steps-green .step-item.step-completed::before {
    background-color: var(--tblr-green);
    border-color: var(--tblr-green);
    color: #fff;
    content: '\ea5e'; /* ti-check */
    font-family: 'tabler-icons';
    font-size: 0.75rem;
}
.steps-animated.steps-green .step-item.step-completed {
    color: var(--tblr-green);
    font-weight: 500;
}
.steps-animated.steps-green .step-item.step-completed:hover::before {
    box-shadow: 0 0 0 3px rgba(47, 179, 68, 0.2);
}

/* Skipped step: reachable but not completed — white bg, green border, dash icon */
.steps-animated.steps-green .step-item.step-skipped::before {
    background-color: var(--tblr-bg-surface);
    border: 2px solid var(--tblr-green);
    box-sizing: border-box;
    color: var(--tblr-green);
    content: '\eb55'; /* ti-minus */
    font-family: 'tabler-icons';
    font-size: 0.75rem;
    z-index: 2;
}
.steps-animated.steps-green .step-item.step-skipped {
    color: var(--tblr-secondary);
}
.steps-animated.steps-green .step-item.step-skipped:hover::before {
    box-shadow: 0 0 0 3px rgba(47, 179, 68, 0.2);
}

/* Current step (wizard frontier) — white bg, green border */
.steps-animated.steps-green .step-item.step-current::before {
    background-color: var(--tblr-bg-surface);
    border: 2px solid var(--tblr-green);
    box-sizing: border-box;
    color: var(--tblr-green);
    z-index: 2;
}
.steps-animated.steps-green .step-item.step-current {
    color: var(--tblr-green);
    font-weight: 600;
}

/* ========================================
   Assignment Rule Cards (Global Styling)
   Used in Directory Service rules management
   and Setup Wizard suggested rules
   ======================================== */

.assignment-rule-card {
    transition: all 0.2s ease;
    background-color: var(--tblr-bg-surface-tertiary);
    border: 2px solid var(--tblr-border-color) !important;
}

.assignment-rule-card:hover {
    border-color: var(--tblr-primary) !important;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
}

/* Dark-mode: lean on a slightly lighter surface over the page bg so the card
   still reads as a distinct panel, and use an explicitly visible border. */
[data-bs-theme="dark"] .assignment-rule-card {
    background-color: #1F2937;
    border-color: rgba(255, 255, 255, 0.12) !important;
}
[data-bs-theme="dark"] .assignment-rule-card:hover {
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}

/* ========================================
   Segment Tree Sortable (Drag & Drop)
   ======================================== */

/* Sortable containers for segment and product items */
.segment-sortable,
.product-sortable {
    min-height: 10px;
}

/* When items are being dragged, highlight potential drop zones */
.segment-sortable.sortable-hover,
.product-sortable.sortable-hover {
    background-color: var(--tblr-primary-lt);
    border-radius: var(--tblr-border-radius);
}

/* Segment item specific drag handle */
.segment-item .drag-handle {
    padding: 0.25rem;
    font-size: 1rem;
}

.segment-item .drag-handle:hover,
.product-item .drag-handle:hover {
    opacity: 1;
    color: var(--tblr-primary);
}

/* Product item specific drag handle */
.product-item .drag-handle {
    padding: 0.25rem;
    font-size: 0.875rem;
}

/* EasyMDE Markdown Editor - Tabler integration */
.EasyMDEContainer {
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
}

.EasyMDEContainer .editor-toolbar {
    border-top: none;
    border-left: none;
    border-right: none;
    border-bottom: 1px solid var(--tblr-border-color);
    background-color: var(--tblr-bg-surface-tertiary);
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
}

.EasyMDEContainer .editor-toolbar button {
    color: var(--tblr-body-color);
}

.EasyMDEContainer .editor-toolbar button:hover,
.EasyMDEContainer .editor-toolbar button.active {
    background-color: var(--tblr-bg-surface-secondary);
    border-color: var(--tblr-border-color);
}

.EasyMDEContainer .CodeMirror {
    border: none;
    border-radius: 0 0 var(--tblr-border-radius) var(--tblr-border-radius);
    background-color: var(--tblr-bg-surface);
    color: var(--tblr-body-color);
    font-size: 0.875rem;
    padding: 0.5rem;
}

.EasyMDEContainer .CodeMirror-cursor {
    border-left-color: var(--tblr-body-color);
}

.EasyMDEContainer .editor-preview,
.EasyMDEContainer .editor-preview-side {
    background-color: var(--tblr-bg-surface);
    color: var(--tblr-body-color);
    font-size: 0.875rem;
    padding: 1rem;
}

.EasyMDEContainer .editor-preview-side {
    border-left: 1px solid var(--tblr-border-color);
}

.EasyMDEContainer .editor-toolbar.disabled-for-preview button:not(.no-disable) {
    opacity: 0.4;
}

.EasyMDEContainer .CodeMirror .CodeMirror-selected {
    background: var(--tblr-primary-lt);
}

.EasyMDEContainer .editor-toolbar i.separator {
    border-left-color: var(--tblr-border-color);
}

/* Markdown rendered content */
.markdown-content h1,
.markdown-content h2,
.markdown-content h3,
.markdown-content h4 {
    margin-top: 1rem;
    margin-bottom: 0.5rem;
}

.markdown-content h1:first-child,
.markdown-content h2:first-child,
.markdown-content h3:first-child,
.markdown-content h4:first-child {
    margin-top: 0;
}

.markdown-content p {
    margin-bottom: 0.5rem;
}

.markdown-content ul,
.markdown-content ol {
    padding-left: 1.5rem;
    margin-bottom: 0.5rem;
}

.markdown-content li {
    margin-bottom: 0.25rem;
}

.markdown-content hr {
    margin: 1rem 0;
}

.markdown-content code {
    padding: 0.125rem 0.25rem;
    background-color: var(--tblr-bg-surface-tertiary);
    border-radius: 3px;
    font-size: 0.875em;
}

.markdown-content pre {
    padding: 0.75rem;
    background-color: var(--tblr-bg-surface-tertiary);
    border-radius: var(--tblr-border-radius);
    overflow-x: auto;
}

.markdown-content pre code {
    padding: 0;
    background: none;
}

.markdown-content blockquote {
    border-left: 3px solid var(--tblr-primary);
    padding-left: 1rem;
    margin-left: 0;
    color: var(--tblr-secondary);
}

.markdown-content table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 0.5rem;
}

.markdown-content table th,
.markdown-content table td {
    padding: 0.375rem 0.75rem;
    border: 1px solid var(--tblr-border-color);
}

.markdown-content table th {
    background-color: var(--tblr-bg-surface-tertiary);
    font-weight: 600;
}

.markdown-content a {
    color: var(--tblr-primary);
}

/* ========================================
   QR Code Container — constrain SVG to parent
   ======================================== */

.qr-code-container svg {
    width: 100%;
    height: 100%;
}

/* ========================================
   OTP Input with Visual Digit Slots
   ======================================== */

.otp-container {
    position: relative;
    display: inline-flex;
    width: 282px;  /* 6 slots x 42px + 5 gaps x 6px */
    height: 56px;
    overflow: clip;
}

.otp-field {
    position: absolute;
    top: 0;
    left: 0;
    width: calc(100% + 48px);  /* extra slot-step to absorb trailing letter-spacing */
    height: 100%;
    background: transparent;
    border: none;
    outline: none;
    font-family: var(--tblr-font-monospace);
    font-size: 1.5rem;
    font-weight: 600;
    /* slot step (42 + 6 = 48px) minus one character width centers each digit */
    letter-spacing: calc(48px - 1ch);
    padding-left: calc((42px - 1ch) / 2);
    color: var(--tblr-body-color);
    z-index: 1;
    caret-color: var(--tblr-primary);
}

.otp-field.caret-hidden {
    caret-color: transparent;
}

.otp-field::selection {
    background: transparent;
}

.otp-slots {
    display: flex;
    gap: 6px;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.otp-slot {
    flex: 0 0 42px;
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    background-color: var(--tblr-bg-surface);
    transition: border-color 0.15s;
}

/* Highlight slots when input is focused */
.otp-field:focus ~ .otp-slots .otp-slot {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 1px rgba(var(--tblr-primary-rgb), 0.15);
}

/* ============================================================
   PARTNER SIDEBAR — Left-side, dark theme, persistent + collapsed
   ============================================================ */

/* Dark sidebar theme (matches Tabler navbar-dark pattern) */
/* Sidebar dimensions — defined at :root so siblings (.page-wrapper) can access them */
:root {
    --sidebar-width: 420px;
    --sidebar-collapsed-width: 5rem; /* avatar-md (2.5rem) + left/right padding (1.25rem each) */
    /* Overlay width below xl. Shared so the mobile flap can park itself on the
       open panel's edge without the two drifting apart. */
    --sidebar-offcanvas-width: 360px;
}

.partner-sidebar,
.sidebar-flap--mobile {
    --sidebar-bg: var(--tblr-bg-surface-dark);
    --sidebar-color: rgba(255, 255, 255, 0.7);
    --sidebar-color-hover: rgba(255, 255, 255, 0.85);
    --sidebar-border-color: rgba(255, 255, 255, 0.1);
    color: var(--sidebar-color);
}

/* Dark mode: slightly lighter surface for sidebar */
[data-bs-theme="dark"] .partner-sidebar,
[data-bs-theme="dark"] .sidebar-flap--mobile {
    --sidebar-bg: var(--tblr-bg-surface);
    --sidebar-border-color: var(--tblr-border-color);
}

/* Optional sidebar background color (theme_sidebar_color) - dedicated muted/
   desaturated palette (WhitelabelConfiguration::THEME_SIDEBAR_COLORS), NOT
   THEME_BASES or THEME_PRIMARIES. THEME_BASES's darkest shades all converge to
   near-identical near-black regardless of hue (slate/gray were indistinguishable);
   THEME_PRIMARIES is too saturated/bold for a sidebar surface. Spans near-black
   through medium-light so the existing white sidebar text (--sidebar-color) stays
   legible against every option. Unset falls through to the default --sidebar-bg above. */
[data-bs-theme-sidebar-color="ash"] .partner-sidebar, [data-bs-theme-sidebar-color="ash"] .sidebar-flap--mobile { --sidebar-bg: #52525b; }
[data-bs-theme-sidebar-color="charcoal"] .partner-sidebar, [data-bs-theme-sidebar-color="charcoal"] .sidebar-flap--mobile { --sidebar-bg: #27272a; }
[data-bs-theme-sidebar-color="denim"] .partner-sidebar, [data-bs-theme-sidebar-color="denim"] .sidebar-flap--mobile { --sidebar-bg: #2c4a6e; }
[data-bs-theme-sidebar-color="forest"] .partner-sidebar, [data-bs-theme-sidebar-color="forest"] .sidebar-flap--mobile { --sidebar-bg: #2d4a3a; }
[data-bs-theme-sidebar-color="graphite"] .partner-sidebar, [data-bs-theme-sidebar-color="graphite"] .sidebar-flap--mobile { --sidebar-bg: #343438; }
[data-bs-theme-sidebar-color="ink"] .partner-sidebar, [data-bs-theme-sidebar-color="ink"] .sidebar-flap--mobile { --sidebar-bg: #0a1628; }
[data-bs-theme-sidebar-color="mist"] .partner-sidebar, [data-bs-theme-sidebar-color="mist"] .sidebar-flap--mobile { --sidebar-bg: #64748b; }
[data-bs-theme-sidebar-color="navy"] .partner-sidebar, [data-bs-theme-sidebar-color="navy"] .sidebar-flap--mobile { --sidebar-bg: #1e3a5f; }
[data-bs-theme-sidebar-color="onyx"] .partner-sidebar, [data-bs-theme-sidebar-color="onyx"] .sidebar-flap--mobile { --sidebar-bg: #0a0a0b; }
[data-bs-theme-sidebar-color="petrol"] .partner-sidebar, [data-bs-theme-sidebar-color="petrol"] .sidebar-flap--mobile { --sidebar-bg: #0c6481; }
[data-bs-theme-sidebar-color="plum"] .partner-sidebar, [data-bs-theme-sidebar-color="plum"] .sidebar-flap--mobile { --sidebar-bg: #3d2c4a; }
[data-bs-theme-sidebar-color="pulse-blue"] .partner-sidebar, [data-bs-theme-sidebar-color="pulse-blue"] .sidebar-flap--mobile { --sidebar-bg: #001021; }
[data-bs-theme-sidebar-color="pulse-surface"] .partner-sidebar, [data-bs-theme-sidebar-color="pulse-surface"] .sidebar-flap--mobile { --sidebar-bg: #0f2c42; }
[data-bs-theme-sidebar-color="slate"] .partner-sidebar, [data-bs-theme-sidebar-color="slate"] .sidebar-flap--mobile { --sidebar-bg: #334155; }
[data-bs-theme-sidebar-color="steel"] .partner-sidebar, [data-bs-theme-sidebar-color="steel"] .sidebar-flap--mobile { --sidebar-bg: #46586b; }
[data-bs-theme-sidebar-color="stone"] .partner-sidebar, [data-bs-theme-sidebar-color="stone"] .sidebar-flap--mobile { --sidebar-bg: #44403c; }
[data-bs-theme-sidebar-color="taupe"] .partner-sidebar, [data-bs-theme-sidebar-color="taupe"] .sidebar-flap--mobile { --sidebar-bg: #57534e; }
[data-bs-theme-sidebar-color="teal"] .partner-sidebar, [data-bs-theme-sidebar-color="teal"] .sidebar-flap--mobile { --sidebar-bg: #1f4d4d; }
[data-bs-theme-sidebar-color="wine"] .partner-sidebar, [data-bs-theme-sidebar-color="wine"] .sidebar-flap--mobile { --sidebar-bg: #4a2a30; }

.partner-sidebar .subheader {
    color: rgba(255, 255, 255, 0.5);
}

[data-bs-theme="dark"] .partner-sidebar .subheader {
    color: var(--tblr-secondary);
}

/* Tabler ships `:host,:root { margin-left: calc(100vw - 100%) }` at this exact
   breakpoint — it shifts the whole document right by the live scrollbar width
   to keep centred pages from jumping when a scrollbar appears. That shift moves
   everything in flow (#site-header, .page-wrapper) but NOT the sidebar, which is
   position:fixed and so is laid out against the initial containing block. The
   difference showed up as a scrollbar-wide gap between the sidebar and the
   content. Cancel the shift here and let the sidebar offsets below be plain
   constants; scrollbar-gutter keeps Tabler's no-jump intent without displacing
   the document.

   This stays pinned to 992px because that is where TABLER's rule starts. The
   sidebar layout below cuts over at xl instead — the two breakpoints answer
   different questions and must not be merged. */
@media (min-width: 992px) {
    :root {
        margin-left: 0;
        scrollbar-gutter: stable;
    }
}

/* Desktop (xl+): Persistent fixed sidebar on LEFT.
   Cuts over at 1200px, not 992px. At 992-1199 a landscape tablet handed the
   permanent 420px sidebar 41% of the screen, and the horizontal main menu
   needs 1046px on top of that: measured 442px of horizontal page overflow at
   1024px, and 186px at 1280px with the sidebar open. Because the sidebar is
   position:fixed and the header/footer are in flow, that sideways scroll slid
   them out of line with it — the offset reported at the top AND bottom of the
   page. Below this width the sidebar is an overlay and the menu is a
   hamburger, exactly as on a phone. */
@media (min-width: 1200px) {
    .partner-sidebar {
        position: fixed !important;
        top: 0;
        left: 0;
        bottom: 0;
        width: var(--sidebar-width);
        border-right: 1px solid var(--sidebar-border-color);
        background-color: var(--sidebar-bg) !important;
        overflow: visible;
        z-index: 1020;
        visibility: visible !important;
        transform: none !important;
    }

    body.sidebar-transitioning .partner-sidebar {
        transition: width 0.3s ease;
    }

    .partner-sidebar .offcanvas-body {
        padding: 1.25rem !important;
        display: flex !important;
        flex-direction: column !important;
        overflow-y: auto !important;
        height: 100%;
    }

    /* Push main content and header to the right (only when sidebar is present). */
    #site-header,
    .partner-sidebar ~ .page-wrapper {
        margin-left: var(--sidebar-width);
    }

    body.sidebar-transitioning #site-header,
    body.sidebar-transitioning .partner-sidebar ~ .page-wrapper {
        transition: margin-left 0.3s ease;
    }

    /* ---- COLLAPSED STATE ---- */
    .partner-sidebar.collapsed {
        width: var(--sidebar-collapsed-width);
    }

    .partner-sidebar.collapsed .offcanvas-body {
        overflow: hidden !important;
    }

    body.sidebar-collapsed #site-header,
    body.sidebar-collapsed .partner-sidebar ~ .page-wrapper {
        margin-left: var(--sidebar-collapsed-width);
    }

    /* Toggle visibility classes: hide text/full elements, show icon replacements */
    .sidebar-collapse-show {
        display: none !important;
    }

    .partner-sidebar.collapsed .sidebar-collapse-hide {
        display: none !important;
    }

    .partner-sidebar.collapsed .sidebar-collapse-show {
        display: block !important;
    }

    /* Collapsed layout: center items in narrow strip */
    .partner-sidebar.collapsed .sidebar-content {
        align-items: center;
    }

    .partner-sidebar.collapsed .sidebar-header-section {
        margin-bottom: 0.5rem !important;
    }

    .partner-sidebar.collapsed .sidebar-header-section .d-flex {
        justify-content: center;
    }

    /* User section: center avatar when collapsed */
    .partner-sidebar.collapsed .sidebar-user-section .d-flex {
        justify-content: center;
    }

    /* Collapsed icon buttons — avatar-md sized (2.5rem) for uniform look */
    .sidebar-collapsed-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2.5rem;
        height: 2.5rem;
        border: none;
        background: rgba(255, 255, 255, 0.08);
        color: var(--sidebar-color);
        font-size: 1.15rem;
        line-height: 1;
        border-radius: var(--tblr-avatar-border-radius, 0.375rem);
        cursor: pointer;
        text-decoration: none;
        transition: background-color 0.15s, color 0.15s;
    }

    .sidebar-collapsed-icon:hover:not(.disabled) {
        background: rgba(255, 255, 255, 0.14);
        color: var(--sidebar-color-hover);
    }

    .sidebar-collapsed-icon.disabled {
        opacity: 0.35;
        cursor: default;
    }

    /* Collapsed show items — centered column with uniform spacing */
    .partner-sidebar.collapsed .sidebar-collapse-show {
        display: flex !important;
        justify-content: center;
        margin-bottom: 0.35rem !important;
    }

    /* Nav items when collapsed — shrink to icon box only */
    .partner-sidebar.collapsed .sidebar-nav {
        align-items: center;
    }

    .partner-sidebar.collapsed .sidebar-nav .nav-link {
        width: 2.5rem;
        justify-content: center;
        background: rgba(255, 255, 255, 0.08);
    }

    .sidebar-collapsed-badge {
        position: absolute;
        top: 2px;
        right: 2px;
        font-size: 0.6rem;
        min-width: 16px;
        height: 16px;
        line-height: 16px;
        padding: 0 4px;
        border-radius: 8px;
    }

    /* ---- Flap handle on the sidebar edge ---- */
    .sidebar-flap {
        position: absolute;
        top: 50%;
        right: -14px;
        transform: translateY(-50%);
        width: 14px;
        height: 48px;
        background: var(--sidebar-bg);
        border: 1px solid var(--sidebar-border-color);
        border-left: none;
        border-radius: 0 6px 6px 0;
        cursor: pointer;
        align-items: center;
        justify-content: center;
        z-index: 1021;
        transition: background 0.15s;
    }

    .sidebar-flap:hover {
        background: color-mix(in srgb, var(--sidebar-bg), white 10%);
    }

    .sidebar-flap-icon {
        font-size: 0.7rem;
        color: var(--sidebar-color);
        transition: transform 0.3s ease;
    }

    /* Flip chevron when collapsed */
    .partner-sidebar.collapsed .sidebar-flap-icon {
        transform: rotate(180deg);
    }
}

/* Phone AND tablet (<xl): Standard offcanvas from left */
@media (max-width: 1199.98px) {
    .partner-sidebar {
        --tblr-offcanvas-width: var(--sidebar-offcanvas-width);
        background-color: var(--sidebar-bg) !important;
    }

    .partner-sidebar .offcanvas-header {
        color: var(--sidebar-color-hover);
        border-bottom-color: var(--sidebar-border-color) !important;
    }

    /* NO invert. Tabler's .btn-close is a CSS MASK tinted with currentColor,
       not Bootstrap's dark SVG background - the offcanvas header already sets a
       light colour, so the X is correct as it comes. Inverting it turned that
       correct light X dark-on-dark and made it unreadable in light theme (the
       dark-theme branch below was the only one behaving). Opacity is Tabler's
       0.4 by default, which on a dark panel is close to invisible on its own. */
    .partner-sidebar .btn-close {
        filter: none;
        opacity: 0.85;
    }

    .partner-sidebar .btn-close:hover,
    .partner-sidebar .btn-close:focus {
        opacity: 1;
    }

    /* Hide the desktop flap and collapse-show elements on mobile; the mobile
       flap below is the one exception - it is how the offcanvas opens. */
    .sidebar-flap:not(.sidebar-flap--mobile),
    .sidebar-collapse-show {
        display: none !important;
    }

    /* The desktop flap, pinned to the screen edge: tapping it opens the
       offcanvas. The open offcanvas (z-index 1045) covers it.
       appearance: none matters - iOS Safari otherwise replaces all of this
       with its own button chrome. */
    .sidebar-flap--mobile {
        appearance: none;
        -webkit-appearance: none;
        -webkit-tap-highlight-color: transparent;
        position: fixed;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 20px;
        height: 56px;
        padding: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        background: var(--sidebar-bg);
        border: 1px solid var(--sidebar-border-color);
        border-left: none;
        border-radius: 0 6px 6px 0;
        color: var(--sidebar-color);
        z-index: 1021;
    }

    .sidebar-flap--mobile:hover,
    .sidebar-flap--mobile:active {
        background: color-mix(in srgb, var(--sidebar-bg), white 10%);
    }

    /* While the panel is OPEN the flap has to sit above it (an open offcanvas
       is z-index 1045) and ride on its edge, so the same control that opened
       the sidebar also closes it. Before this it was buried underneath, which
       left the X as the only way out - and the X was the unreadable one. */
    .partner-sidebar.show ~ .sidebar-flap--mobile {
        z-index: 1046;
        left: var(--sidebar-offcanvas-width);
    }

    .partner-sidebar.show ~ .sidebar-flap--mobile .sidebar-flap-icon {
        transform: rotate(180deg);
    }

    /* Same quiet chevron as the desktop flap (whose 0.7rem rule lives in the
       desktop media block and does not reach down here). */
    .sidebar-flap--mobile .sidebar-flap-icon {
        font-size: 0.7rem;
        color: var(--sidebar-color);
    }
}

/* ---- Sidebar Header ---- */
.sidebar-header-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    color: var(--sidebar-color);
    opacity: 0.6;
    font-size: 1rem;
    text-decoration: none !important;
    background: rgba(255, 255, 255, 0.08);
    border-radius: var(--tblr-avatar-border-radius, 0.375rem);
    transition: opacity 0.15s, background-color 0.15s;
}

.sidebar-header-btn:hover {
    opacity: 1;
    color: var(--sidebar-color-hover);
    background: rgba(255, 255, 255, 0.14);
}

/* Inline icon in sidebar user bar — no background box */
.sidebar-inline-icon {
    color: var(--sidebar-color);
    opacity: 0.5;
    font-size: 1.4rem;
    text-decoration: none !important;
    transition: opacity 0.15s;
    flex-shrink: 0;
    padding: 0 0.15rem;
    cursor: pointer;
}

.sidebar-inline-icon:hover {
    opacity: 1;
    color: var(--sidebar-color-hover);
}

.sidebar-brand-avatar {
    background: rgba(255, 255, 255, 0.85);
    color: #182433;
    font-weight: 600;
    border-radius: var(--tblr-avatar-border-radius, 0.375rem);
}

.sidebar-brand-avatar img {
    object-fit: contain;
    padding: 3px;
}

/* ---- Sidebar Navbar Nav — 2.5rem row height to match avatar-md ---- */
.partner-sidebar .sidebar-nav {
    gap: 0.35rem;
}

.partner-sidebar .sidebar-nav .nav-link {
    display: flex;
    align-items: center;
    height: 2.5rem;
    padding: 0;
    color: var(--sidebar-color);
    border-radius: var(--tblr-avatar-border-radius, 0.375rem);
    font-size: 0.85rem;
    background: rgba(255, 255, 255, 0.04);
    text-decoration: none;
    transition: background-color 0.15s;
}

/* Applications under Pulse: one sub-item per app, hung off a tree guide that
   drops from the Pulse icon (|- per row). 28px rows, icon beside a small name,
   external mark at the right edge. A hairline closes the block off from the
   rest of the group. Collapsed the guide goes and they stack as icon squares. */
.partner-sidebar .sidebar-nav .sidebar-apps {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-left: 1.25rem;           /* the spine sits under the Pulse icon's centre */
    padding: 0 0 0.6rem 0.75rem;
    margin-bottom: 0.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.partner-sidebar .sidebar-nav .sidebar-apps::before {
    content: "";
    position: absolute;
    left: 0;
    top: -0.35rem;                  /* runs up into the gap below Pulse */
    bottom: calc(0.6rem + 0.875rem); /* ends at the last row's tick */
    border-left: 1px solid rgba(255, 255, 255, 0.18);
}
.partner-sidebar .sidebar-nav .sidebar-app {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    height: 1.75rem;
    padding: 0 0.6rem;
    border-radius: var(--tblr-avatar-border-radius, 0.375rem);
    background: rgba(255, 255, 255, 0.04);
    color: var(--sidebar-color);
    font-size: 0.7rem;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    transition: background-color 0.15s;
}
.partner-sidebar .sidebar-nav .sidebar-app::before {
    content: "";
    position: absolute;
    left: -0.75rem;
    top: 50%;
    width: 0.55rem;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.partner-sidebar .sidebar-nav .sidebar-app.active {
    color: var(--sidebar-color-hover);
    background: rgba(255, 255, 255, 0.12);
}
.partner-sidebar .sidebar-nav .sidebar-app:hover {
    color: var(--sidebar-color-hover);
    background: rgba(255, 255, 255, 0.08);
}
.partner-sidebar .sidebar-nav .sidebar-app > .ti:first-child { font-size: 0.9rem; }
.partner-sidebar .sidebar-nav .sidebar-app__svg { width: 0.9rem; height: 0.9rem; flex: none; }
.partner-sidebar .sidebar-nav .sidebar-app > span { overflow: hidden; text-overflow: ellipsis; }
.partner-sidebar .sidebar-nav .sidebar-app__ext { margin-left: auto; font-size: 0.6rem; opacity: 0.4; }
.partner-sidebar.collapsed .sidebar-nav .sidebar-apps { margin-left: 0; padding-left: 0; align-items: center; }
.partner-sidebar.collapsed .sidebar-nav .sidebar-apps::before,
.partner-sidebar.collapsed .sidebar-nav .sidebar-app::before { display: none; }
.partner-sidebar.collapsed .sidebar-nav .sidebar-app { width: 2.5rem; height: 2.5rem; padding: 0; justify-content: center; }


.partner-sidebar .sidebar-nav .sidebar-section {
    padding: 0.5rem 0.25rem 0;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--sidebar-color);
    opacity: 0.6;
}
.partner-sidebar .sidebar-nav .sidebar-section:first-child {
    padding-top: 0;
}

.partner-sidebar .sidebar-nav .nav-link:hover:not(.disabled) {
    color: var(--sidebar-color-hover);
    background: rgba(255, 255, 255, 0.08);
}

.partner-sidebar .sidebar-nav .nav-link.disabled {
    color: var(--sidebar-color);
    opacity: 0.4;
}

/* Icon box inside nav link — 2.5rem square, centered icon */
.partner-sidebar .sidebar-nav .nav-link-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    flex-shrink: 0;
    color: var(--sidebar-color);
    opacity: 0.7;
    margin: 0;
}

.partner-sidebar .sidebar-nav .nav-link-title {
    padding-left: 0.5rem;
    padding-right: 0.75rem;
}

/* ---- Sidebar Search — 2.5rem height to match avatar-md ---- */
.sidebar-search-input {
    height: 2.5rem !important;
    background-color: rgba(255, 255, 255, 0.08) !important;
    border-color: rgba(255, 255, 255, 0.1) !important;
    color: var(--sidebar-color) !important;
    border-radius: var(--tblr-avatar-border-radius, 0.375rem) !important;
    font-size: 0.85rem !important;
}

.sidebar-search-input::placeholder {
    color: rgba(255, 255, 255, 0.4) !important;
}

.sidebar-search-input:focus {
    background-color: rgba(255, 255, 255, 0.12) !important;
    border-color: rgba(255, 255, 255, 0.2) !important;
}

.sidebar-search-results {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    background: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    border-radius: 0.375rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    max-height: 300px;
    overflow-y: auto;
    margin-top: 4px;
}

/* button_to wraps in a form — reset it */
.sidebar-search-results form {
    margin: 0;
    padding: 0;
}

.sidebar-search-result-item {
    color: var(--tblr-body-color);
    text-decoration: none;
    transition: background-color 0.15s;
    cursor: pointer;
}

/* Reset button styling for button_to results */
button.sidebar-search-result-item {
    background: none;
    border: none;
    text-align: left;
    font: inherit;
}

.sidebar-search-result-item:hover {
    background-color: var(--tblr-bg-surface-secondary);
    color: var(--tblr-body-color);
    text-decoration: none;
}

/* Avatar icons inside search results */
.sidebar-search-result-item .avatar {
    flex-shrink: 0;
}

.sidebar-search-result-item .avatar i {
    font-size: 1rem;
}

/* ---- Version Card ---- */
.sidebar-version-card {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--sidebar-color);
}

.sidebar-version-card .text-secondary {
    color: rgba(255, 255, 255, 0.5) !important;
}

/* ---- User Section ---- */
.sidebar-user-section {
    position: relative;
    padding-top: 0.5rem;
}

/* ---- User Avatar VIP Badge ---- */
/* Admin crown badge on avatar */
.sidebar-avatar-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    color: #f5c842;
    line-height: 1;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4));
}

/* ---- User Flyout Menu (right of sidebar) ---- */
.sidebar-user-flyout {
    position: fixed;
    z-index: 1060;
    background: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    min-width: 260px;
    max-width: 300px;
}

.sidebar-flyout-item {
    display: flex;
    align-items: center;
    padding: 0.5rem 0.75rem;
    color: var(--tblr-body-color);
    text-decoration: none !important;
    font-size: 0.85rem;
    border-radius: 0.375rem;
    transition: background-color 0.15s;
}

.sidebar-flyout-item:hover {
    background-color: var(--tblr-bg-surface-secondary);
    color: var(--tblr-body-color);
}

.sidebar-flyout-item.text-danger:hover {
    background-color: rgba(var(--tblr-danger-rgb), 0.08);
}

/* ---- Dark mode overrides ---- */
[data-bs-theme="dark"] .sidebar-search-input {
    background-color: rgba(255, 255, 255, 0.05) !important;
    border-color: rgba(255, 255, 255, 0.08) !important;
}

[data-bs-theme="dark"] .sidebar-version-card {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
}

/* ---- Notification card styling ---- */
.partner-sidebar .notification-card {
    border-radius: 0.5rem;
    background: rgba(255, 255, 255, 0.06);
    color: var(--sidebar-color-hover);
}

[data-bs-theme="dark"] .partner-sidebar .notification-card {
    background: rgba(255, 255, 255, 0.04);
}

.partner-sidebar .notification-card .text-secondary {
    color: rgba(255, 255, 255, 0.5) !important;
}

.partner-sidebar .notification-card .text-muted {
    color: rgba(255, 255, 255, 0.35) !important;
}

.partner-sidebar .notification-dismiss {
    position: absolute;
    top: 8px;
    right: 8px;
    color: rgba(255, 255, 255, 0.5);
    text-decoration: none;
    font-size: 0.75rem;
    line-height: 1;
    z-index: 1;
    transition: color 0.15s;
}

.partner-sidebar .notification-dismiss:hover {
    color: rgba(255, 255, 255, 0.85);
}

/* ---- Tenant switch loading overlay ---- */
.tenant-switch-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(var(--tblr-body-bg-rgb), 0.92);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    backdrop-filter: blur(4px);
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ============================================================
   Partner Layout — Dual Layout Architecture
   ============================================================ */

/* Active nav item in sidebar */
.partner-sidebar .sidebar-nav .nav-link.active {
    color: var(--sidebar-color-hover);
    background: rgba(255, 255, 255, 0.12);
    border-radius: 0.375rem;
}

/* Sidebar enter-account button — subtle border highlight */
.sidebar-enter-btn {
    border: 1px solid rgba(255, 255, 255, 0.25) !important;
    border-radius: 0.25rem;
    opacity: 0.8;
    transition: opacity 0.15s, border-color 0.15s;
}
.sidebar-enter-btn:hover {
    opacity: 1;
    border-color: rgba(255, 255, 255, 0.5) !important;
}

/* Sidebar header: inline button_to form wrapper */
.sidebar-header-section .button_to {
    display: inline;
}

/* Changelog iframe — fills card body */
.changelog-iframe {
    width: 100%;
    min-height: 80vh;
    border: none;
    border-radius: 0 0 var(--tblr-card-border-radius) var(--tblr-card-border-radius);
}

/* Setup wizard — clickable carrier/profile cards */
.config-card {
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.config-card:hover {
    border-color: var(--tblr-primary);
}

/* Fix form-switch alignment — ensure toggle and label sit on the same line */
.form-check.form-switch {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 1.5rem;
    padding-left: 0;
}
.form-check.form-switch .form-check-input {
    float: none;
    margin-left: 0;
    margin-top: 0;
}
.form-check.form-switch .form-check-label {
    margin-top: 0;
}
/* A switch's description goes under its label, not beside it: the flex row above would put it on the same line. */
.form-check.form-switch { flex-wrap: wrap; }
.form-check.form-switch .form-check-description {
    flex-basis: 100%;
    margin-top: 0;
    padding-left: 2.5rem; /* the 2rem switch and the 0.5rem gap */
}
/* SwitchSectionComponent: the options a switch turns on, under its label (the same 2.5rem), no box around them. */
.switch-section { margin-bottom: 1rem; }
.switch-section__options { padding: .5rem 0 0 2.5rem; }
/* ChoiceComponent: a segmented control with one line under it for the chosen mode only (artbook variant C). The line
   follows the checked radio by position: inputs count by :nth-of-type, lines by :nth-child, up to four. */
.choice__line { display: none; margin-top: .35rem; font-size: .8125rem; color: var(--tblr-secondary); }
.choice__line:empty { margin-top: 0; }
.choice:has(.btn-check:nth-of-type(1):checked) .choice__line:nth-child(1),
.choice:has(.btn-check:nth-of-type(2):checked) .choice__line:nth-child(2),
.choice:has(.btn-check:nth-of-type(3):checked) .choice__line:nth-child(3),
.choice:has(.btn-check:nth-of-type(4):checked) .choice__line:nth-child(4) { display: block; }
.choice__unavailable { margin-top: .2rem; font-size: .75rem; color: var(--tblr-secondary); }

/* Setup wizard sub-step slide animation (trunk config panels) */
@keyframes slide-in-from-right {
    from { opacity: 0; transform: translateX(30px); }
    to { opacity: 1; transform: translateX(0); }
}
@keyframes slide-in-from-left {
    from { opacity: 0; transform: translateX(-30px); }
    to { opacity: 1; transform: translateX(0); }
}
.panel-slide-forward {
    animation: slide-in-from-right 0.25s ease-out;
}
.panel-slide-back {
    animation: slide-in-from-left 0.25s ease-out;
}

/* Setup Wizard Filter Funnel */
.filter-step-number {
    min-width: 2rem;
    text-align: center;
}
.filter-step-number .badge {
    width: 2rem;
    height: 2rem;
    line-height: 2rem;
    font-size: 0.85rem;
}
.filter-type-card {
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.filter-type-card:hover {
    border-color: var(--tblr-primary);
}
.filter-type-card.active {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 1px var(--tblr-primary);
    background-color: rgba(var(--tblr-primary-rgb), 0.04);
}
.filter-panel {
    display: none;
    animation: fadeIn 0.2s ease-in-out;
}
.filter-panel.show {
    display: block;
}
.filter-results-body {
    overflow-y: auto;
    scrollbar-width: none;
}
.filter-results-body::-webkit-scrollbar {
    display: none;
}
.table-compact th,
.table-compact td {
    padding: 0.35rem 0.5rem;
    font-size: 0.8125rem;
}

/* Form section pattern for multi-section forms within cards */
.form-section {
    margin-bottom: 1.5rem;
}

.form-section:last-child {
    margin-bottom: 0;
}

.form-section-title {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 0.75rem;
}

/* Number range add/remove buttons — match form-control-sm height (30px) */
.number-range-action-btn {
    width: 32px;
    height: 32px;
    min-width: 0;
    min-height: 0;
    padding: 0;
}

/* Trix rich text editor — Tabler theme integration */
trix-editor {
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    min-height: 200px;
    padding: 0.75rem;
    font-family: inherit;
}
trix-editor:focus {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--tblr-primary-rgb), 0.25);
    outline: none;
}
trix-toolbar .trix-button-group--file-tools {
    display: none;
}

/* Tabler 1.5 made the default avatar a circle (--tblr-avatar-border-radius:
   pill); 1.4 was the rounded square, and every product, service and account
   avatar in Pulse was drawn for that. Hold the square as the default;
   .avatar-rounded still opts a person's avatar into the circle. */
.avatar {
    --tblr-avatar-border-radius: var(--tblr-border-radius);
}

/* Milkdown (Crepe) markdown editor — Tabler theme integration.
   .markdown-editor is the chrome every mount shares; the surface's look is a
   modifier the Stimulus controller sets from data-markdown-editor-style-value:
   --offer mimics the offer PDF, --product the marketplace product page. */
.markdown-editor {
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    min-height: 200px;
}
.markdown-editor:focus-within {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--tblr-primary-rgb), 0.25);
}
.markdown-editor .milkdown-top-bar {
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
}
.markdown-editor .milkdown {
    --crepe-font-title: inherit;
    --crepe-font-default: inherit;
    --crepe-font-code: var(--tblr-font-monospace);
    --crepe-color-background: var(--tblr-bg-forms);
    --crepe-color-on-background: var(--tblr-body-color);
    --crepe-color-primary: var(--tblr-primary);
}
.markdown-editor .milkdown .ProseMirror {
    padding: 1rem 1.25rem;
    font-size: 0.875rem;
}
/* Crepe gives every heading a top margin; the first one (after the virtual
   cursor element it prepends) would otherwise float below a band of empty space. */
.markdown-editor .milkdown .ProseMirror > :is(h1, h2, h3, h4):first-child,
.markdown-editor .milkdown .ProseMirror > .prosemirror-virtual-cursor + :is(h1, h2, h3, h4) {
    margin-top: 0;
}

/* --product: what .markdown-content renders on the marketplace product page */
.markdown-editor--product .milkdown .ProseMirror > :is(h1, h2, h3, h4) {
    font-size: 1.125rem;
    font-weight: 600;
    margin: 1rem 0 0.5rem;
    padding: 0;
}
.markdown-editor--product .milkdown .ProseMirror p {
    padding: 0;
    margin: 0 0 0.5rem;
}
.markdown-editor--product .milkdown .ProseMirror code {
    padding: 0.125rem 0.25rem;
    background-color: var(--tblr-bg-surface-tertiary);
    border-radius: 3px;
    font-size: 0.875em;
}

/* --offer: the offer PDF (lib/commerce_documents/assets/offer-style.css):
   Spline Sans body, Rubik article headings numbered in blue, clauses
   numbered "art.clause", the flat lines table. Sizes are the document's pt
   values scaled up so they read on screen. The numbering is CSS counters over
   the editor DOM, so the terms page restarts at 1 where the PDF continues
   from the scope page - close enough to write against. */
.markdown-editor--offer .milkdown {
    --crepe-font-title: 'Rubik', 'Spline Sans', sans-serif;
    --crepe-font-default: 'Spline Sans', system-ui, sans-serif;
    --crepe-font-code: 'Spline Sans Mono', ui-monospace, monospace;
    --crepe-color-on-background: #001021;
}
.markdown-editor--offer .milkdown .ProseMirror {
    max-width: 52rem;
    line-height: 1.5;
    color: #16242f;
    counter-reset: art;
}
.markdown-editor--offer .milkdown .ProseMirror p {
    padding: 0;
    margin: 0 0 0.5rem;
}
.markdown-editor--offer .milkdown .ProseMirror > :is(h1, h2, h3, h4) {
    counter-increment: art;
    font-family: 'Rubik', 'Spline Sans', sans-serif;
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.01em;
    color: #001021;
    margin: 1rem 0 0.25rem;
    padding: 0;
}
.markdown-editor--offer .milkdown .ProseMirror > :is(h1, h2, h3, h4)::before {
    content: counter(art) ". ";
    color: #1481BA;
}
/* Ordered lists are clauses: "1.1", "1.2" in blue mono, like the PDF */
.markdown-editor--offer .milkdown .ProseMirror > ol {
    counter-reset: cl;
    margin: 0 0 0.5rem;
}
.markdown-editor--offer .milkdown .ProseMirror > ol > .milkdown-list-item-block {
    counter-increment: cl;
}
/* Crepe's own "1." label is kept for its line box (so the number sits on the
   text baseline) but made invisible; the counter text is painted over it. */
.markdown-editor--offer .milkdown .ProseMirror > ol > .milkdown-list-item-block .label.ordered {
    position: relative;
    color: transparent;
    min-width: 2rem;
}
.markdown-editor--offer .milkdown .ProseMirror > ol > .milkdown-list-item-block .label.ordered::before {
    content: counter(art) "." counter(cl);
    position: absolute;
    left: 0;
    top: 0;
    color: #1481BA;
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-weight: 500;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}
.markdown-editor--offer .milkdown .ProseMirror .list-item .label.bullet {
    color: #1481BA;
}
/* Tables render as the house "lines flat" table: small mono uppercase column
   headers, hairline row rules, no vertical borders */
.markdown-editor--offer .milkdown .ProseMirror table.children {
    border: 0;
    font-size: 0.875rem;
}
.markdown-editor--offer .milkdown .ProseMirror table.children :is(th, td) {
    border: 0;
    border-bottom: 1px solid rgba(0, 16, 33, 0.10);
    padding: 0.35rem 0.75rem 0.35rem 0;
    background: transparent;
    vertical-align: top;
}
.markdown-editor--offer .milkdown .ProseMirror table.children th {
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-weight: 500;
    font-size: 0.7rem;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: #5e7488;
}
.markdown-editor--offer .milkdown .ProseMirror table.children :is(th, td) p {
    margin: 0;
}
.markdown-editor--offer .milkdown .ProseMirror strong {
    font-weight: 700;
}

/* ========================================
   Navbar Service Dropdown Overflow
   ======================================== */

/* Prevent long service names from expanding the dropdown beyond its container */
.navbar .dropend > .dropdown-menu {
    min-width: auto;
    width: max-content;
}

.navbar .dropend .dropdown-item {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Service name in the dropend trigger */
.navbar .dropend > .dropdown-item.dropdown-toggle {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 240px;
}

/* ========================================
   Top menu highlight (brand colour, hover-driven)
   - Highlight FONT colour follows the brand primary (blue/teal via whitelabel);
     background stays the Tabler default. The hover-menu Stimulus controller keeps
     exactly one chain open, so .show always equals the hovered path.
   ======================================== */

/* Top-level items: brand colour on hover and while their dropdown is open.
   !important beats the dark-mode `.navbar .nav-link { color: ... !important }`. */
.navbar-nav > .nav-item > .nav-link:hover,
.navbar-nav > .nav-item.show > .nav-link {
    color: var(--tblr-primary) !important;
}

/* The label lives in a `.nav-link-title` span that carries its own
   `color: ... !important` (dark-mode brighten), so it ignores the brand colour
   the parent link takes on hover/open/active - only the icon and caret (which
   inherit) recolour. Re-assert the brand colour on the title in those states. */
.navbar-nav > .nav-item > .nav-link:hover .nav-link-title,
.navbar-nav > .nav-item.show > .nav-link .nav-link-title,
.navbar-nav > .nav-item > .nav-link.active .nav-link-title {
    color: var(--tblr-primary) !important;
}

/* Dropdown items + nested submenu toggles: brand-colour the font on hover and
   when their own submenu is open. Background unchanged. */
.navbar .dropdown-item:hover,
.navbar .dropend.show > .dropdown-item.dropdown-toggle {
    color: var(--tblr-primary);
}

/* A clicked item must not keep its highlight after the pointer leaves: neutralise
   the lingering mouse :focus background (keyboard :focus-visible still highlights). */
.navbar .dropdown-item:focus:not(:hover):not(:focus-visible) {
    background-color: transparent;
}

/* Active section ("you are here"): persistent brand text + a flat border-bottom
   underline. A transparent 2px border is reserved on every top nav-link so the
   active one just colours it (no layout shift); border-radius:0 keeps the line
   flat (no eyebrow curve). Distinct from the transient hover/open highlight
   (which is text-colour only). */
.navbar-nav:not(.sidebar-nav) > .nav-item > .nav-link {
    border-bottom: 2px solid transparent;
    border-radius: 0;
}

.navbar-nav:not(.sidebar-nav) > .nav-item > .nav-link.active {
    color: var(--tblr-primary) !important;
    border-bottom-color: var(--tblr-primary);
}

/* No focus glow ring on the top nav toggles - clicking to open showed a stray
   box-shadow border. State is already conveyed by the brand colour + underline. */
.navbar-nav > .nav-item > .nav-link:focus,
.navbar-nav > .nav-item > .nav-link:focus-visible {
    box-shadow: none;
    outline: none;
}

/* The account sidebar list also carries .navbar-nav (the top-menu rules above
   exclude .sidebar-nav for that reason); its active state is branding-coloured
   text + icon only. */
.partner-sidebar .sidebar-nav .nav-link.active {
    color: var(--tblr-primary) !important;
}

.partner-sidebar .sidebar-nav .nav-link.active .nav-link-icon {
    color: var(--tblr-primary);
    opacity: 1;
}

/* Section nav items read as full-height tabs (only the menu bar, #site-navigation):
   the grey active/open fill runs all the way to the bar's TOP edge and the brand
   underline rests ON the bar's bottom border - instead of a rounded pill floating
   centred in the bar with a gap above and below.

   Tabler floors every nav-link at min-height:2.5rem (40px) and centres it in the
   3.5rem bar, leaving a gap top and bottom. We clamp the link up to the bar's full
   height (min-height:3.5rem) so its grey fill spans the bar and its 2px underline
   lands on the bar's bottom border; padding-y:0 removes the surrounding gap and
   border-radius:0 squares the fill to the edges. (align-items:stretch alone can't
   do this - Tabler's min-height keeps the link at 40px - so the explicit clamp is
   required.) */
#site-navigation .navbar {
    --tblr-navbar-padding-y: 0;
}
#site-navigation .navbar-nav > .nav-item > .nav-link {
    min-height: 3.5rem;     /* clamp Tabler's 2.5rem nav-link up to the full bar height */
    display: flex;
    align-items: center;    /* keep the label vertically centred in the tall tab */
    border-radius: 0;       /* square the grey fill flush to the edges */
}

/* Same for items inside the dropdowns (incl. the .dropend submenu toggles like
   "Numbers"): opening one left a blue focus box around it. Highlight is already
   the brand colour, so drop the ring. */
.navbar .dropdown-menu .dropdown-item:focus,
.navbar .dropdown-menu .dropdown-item:focus-visible {
    box-shadow: none;
    outline: none;
}

/* ========================================
   DateRangePicker - Tabler Integration
   ======================================== */

/* Match Tabler form-control styling */
.daterangepicker {
    font-family: var(--tblr-font-sans-serif);
    font-size: 0.875rem;
    border-color: var(--tblr-border-color);
    box-shadow: var(--tblr-box-shadow-dropdown);
    z-index: 10000;
}

/* Preset range buttons */
.daterangepicker .ranges li {
    font-size: 0.8125rem;
    padding: 0.375rem 0.75rem;
    border-radius: var(--tblr-border-radius);
    color: var(--tblr-body-color);
}

.daterangepicker .ranges li:hover {
    background-color: var(--tblr-bg-surface-secondary);
}

.daterangepicker .ranges li.active {
    background-color: var(--tblr-primary);
    color: #fff;
}

/* Calendar styling */
.daterangepicker td.active,
.daterangepicker td.active:hover {
    background-color: var(--tblr-primary);
}

.daterangepicker td.in-range {
    background-color: rgba(var(--tblr-primary-rgb), 0.1);
    color: var(--tblr-body-color);
}

/* Apply/Cancel buttons */
.daterangepicker .drp-buttons .btn {
    font-size: 0.8125rem;
    padding: 0.25rem 0.75rem;
}

.daterangepicker .drp-buttons .applyBtn {
    background-color: var(--tblr-primary);
    border-color: var(--tblr-primary);
}

/* Dark mode */
[data-bs-theme="dark"] .daterangepicker {
    background-color: var(--tblr-bg-surface);
    border-color: var(--tblr-border-color);
}

[data-bs-theme="dark"] .daterangepicker .calendar-table {
    background-color: var(--tblr-bg-surface);
    border-color: var(--tblr-border-color);
}

[data-bs-theme="dark"] .daterangepicker td.off,
[data-bs-theme="dark"] .daterangepicker td.off.in-range {
    background-color: var(--tblr-bg-surface);
    color: var(--tblr-secondary);
}

[data-bs-theme="dark"] .daterangepicker th,
[data-bs-theme="dark"] .daterangepicker td {
    color: var(--tblr-body-color);
}

[data-bs-theme="dark"] .daterangepicker .ranges li {
    color: var(--tblr-body-color);
}

[data-bs-theme="dark"] .daterangepicker .ranges li:hover {
    background-color: var(--tblr-bg-surface-secondary);
}

[data-bs-theme="dark"] .daterangepicker .drp-buttons {
    border-top-color: var(--tblr-border-color);
}

/* ------------------------------------------------------------------
   Sidebar-aware modal centering
   ------------------------------------------------------------------
   Bootstrap's `.modal` and `.modal-backdrop` are `position: fixed` and
   span the full viewport (`left: 0; right: 0`), which means modals get
   centered over the whole page including the persistent sidebar.
   Shift their left edge to match the page-wrapper's margin so they
   visually centre within the content area. Only applied where the sidebar
   is actually persistent; below that it is an offcanvas overlay and modals
   must use the full viewport.

   This breakpoint MUST track the sidebar's own (xl). It used to say 992px,
   and left at 992 it would shove every modal 420px right on a tablet where
   the sidebar no longer occupies that space at all.
   ------------------------------------------------------------------ */
@media (min-width: 1200px) {
    body:has(.partner-sidebar) .modal,
    body:has(.partner-sidebar) .modal-backdrop {
        left: var(--sidebar-width);
        width: calc(100% - var(--sidebar-width));
    }

    body.sidebar-collapsed:has(.partner-sidebar) .modal,
    body.sidebar-collapsed:has(.partner-sidebar) .modal-backdrop {
        left: var(--sidebar-collapsed-width);
        width: calc(100% - var(--sidebar-collapsed-width));
    }

    body.sidebar-transitioning:has(.partner-sidebar) .modal,
    body.sidebar-transitioning:has(.partner-sidebar) .modal-backdrop {
        transition: left 0.3s ease, width 0.3s ease;
    }
}

/* Reporting page live indicator — matches the countdown ring footprint
   (20x20 SVG) and pulses to signal ActionCable-driven updates. */
@keyframes sdrLivePulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.5; transform: scale(0.75); }
}
.sdr-live-pulse {
    transform-box: fill-box;
    transform-origin: center;
    animation: sdrLivePulse 1.4s ease-in-out infinite;
}

/* Match plain `.form-select` to TomSelect's visual style so forms that mix
   native selects and TomSelect-enhanced inputs line up pixel-for-pixel.
   The persona "Identity configuration" sections show/hide via display:none —
   TomSelect doesn't survive that, so those selects stay native. */
.form-select {
    padding: .625rem 2.25rem .625rem .75rem;
    height: 40px;
    line-height: 1.4285714286;
    font-size: .875rem;
    border-color: var(--tblr-border-color);
    background-color: var(--tblr-bg-forms);
    box-shadow: none;
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.form-select:focus {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .1);
}
.form-select:disabled {
    background-color: var(--tblr-bg-surface-secondary);
    color: var(--tblr-secondary);
}

/* Dashed placeholder card — used for "New persona" / "New blueprint" tiles.
   Muted at rest (so the real cards draw the eye); switches to primary
   border + foreground on hover to signal interactivity. */
.card-placeholder {
    border-style: dashed;
    border-color: var(--tblr-border-color);
    background-color: transparent;
    color: var(--tblr-secondary);
    transition: border-color 0.15s ease, color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.card-placeholder .card-title,
.card-placeholder p,
.card-placeholder i {
    color: var(--tblr-secondary);
    transition: color 0.15s ease;
}
.card-placeholder:hover {
    border-color: var(--tblr-primary);
    color: var(--tblr-primary);
    transform: translateY(-4px);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
.card-placeholder:hover .card-title,
.card-placeholder:hover p,
.card-placeholder:hover i {
    color: var(--tblr-primary);
}

/* ============================================================
   Dark-mode contrast lifts
   ------------------------------------------------------------
   Target the elements where Tabler's default dark palette sits
   below WCAG AA (or close enough to feel washed out). All rules
   are scoped to [data-bs-theme="dark"] so light mode is untouched.

   Audited via in-page Playwright script (WCAG luminance ratios);
   each rule here brings the flagged element to >= 4.5:1 (AA) or
   higher. See ticket / screenshot "identities-contrast-*.png".
   ============================================================ */
[data-bs-theme="dark"] {
    /* Sync button: white on mid-green (#2FB344) was 2.63:1.
       Darker green brings white to ~7.4:1 (AAA). */
    .btn-green,
    .btn.btn-green {
        background-color: #136329;
        border-color: #136329;
        color: #FFFFFF;
    }
    .btn-green:hover,
    .btn.btn-green:hover {
        background-color: #0F5321;
        border-color: #0F5321;
        color: #FFFFFF;
    }

    /* Outline-primary buttons ("View" etc.): blue-400 → blue-300
       (6.4:1). Darker dark-mode bg on hover for reversed legibility. */
    .btn-outline-primary {
        color: #63B3ED !important;
        border-color: #63B3ED !important;
    }
    .btn-outline-primary:hover,
    .btn-outline-primary:focus,
    .btn-outline-primary.active {
        background-color: #63B3ED !important;
        border-color: #63B3ED !important;
        color: #0F172A !important;
    }

    /* Top navbar + nav-link titles: lift gray-400 → gray-300 (≈10:1). */
    .navbar .nav-link,
    .navbar .nav-link-title,
    .nav-link-title {
        color: #D1D5DB !important;
    }

    /* Table column headers: same brighten for the text-muted slab. */
    .table > thead th,
    .table > thead tr > th,
    th {
        color: #D1D5DB !important;
    }

    /* Table-body muted text (emails, phone numbers, sub-labels):
       Tabler dark default ~#6C7A96 → #A3ADBC (6.5:1, AA+). Also
       nudge font-weight on the 11-12 px variants so small sizes read. */
    .table .text-muted,
    .table-vcenter .text-muted,
    td .text-muted,
    .card-body .text-muted.small,
    .text-muted.small {
        color: #A3ADBC !important;
    }
    .text-muted.small {
        font-weight: 500 !important;
    }

    /* Footer nav muted links: #6B7280 → #B8C0CC (~9.7:1). */
    footer .list-inline-item,
    footer .list-inline-item a,
    .footer .list-inline-item,
    .footer .list-inline-item a {
        color: #B8C0CC !important;
    }

    /* Subtle boost to card borders so cards read as distinct surfaces
       against the body (rgba(255,255,255,.04) → .12). */
    .card {
        border-color: rgba(255, 255, 255, 0.12) !important;
    }

    /* ------------------------------------------------------------
       Tint ("-lt") pills, avatars and chips: the worst offender.
       Tabler paints both background and foreground with the same
       base hue, producing "blue on blue" mush (~3.5:1) in dark.
       We keep the tint vibe but brighten the foreground to a light
       pastel token (Tailwind 300-ish) and lift the background tint
       to 22 % so the pill boundary is still legible. The selectors
       cover any element using a `.bg-<hue>-lt` utility (badges,
       .avatar chips, etc.) plus any icon/svg inside them.
       ------------------------------------------------------------ */
    .bg-blue-lt,   .bg-blue-lt i,   .bg-blue-lt svg   { color: #93C5FD !important; }
    .bg-azure-lt,  .bg-azure-lt i,  .bg-azure-lt svg  { color: #7DD3FC !important; }
    .bg-indigo-lt, .bg-indigo-lt i, .bg-indigo-lt svg { color: #A5B4FC !important; }
    .bg-purple-lt, .bg-purple-lt i, .bg-purple-lt svg { color: #D8B4FE !important; }
    .bg-pink-lt,   .bg-pink-lt i,   .bg-pink-lt svg   { color: #F9A8D4 !important; }
    .bg-red-lt,    .bg-red-lt i,    .bg-red-lt svg    { color: #FCA5A5 !important; }
    .bg-orange-lt, .bg-orange-lt i, .bg-orange-lt svg { color: #FDBA74 !important; }
    .bg-yellow-lt, .bg-yellow-lt i, .bg-yellow-lt svg { color: #FDE68A !important; }
    .bg-lime-lt,   .bg-lime-lt i,   .bg-lime-lt svg   { color: #BEF264 !important; }
    .bg-green-lt,  .bg-green-lt i,  .bg-green-lt svg  { color: #86EFAC !important; }
    .bg-teal-lt,   .bg-teal-lt i,   .bg-teal-lt svg   { color: #5EEAD4 !important; }
    .bg-cyan-lt,   .bg-cyan-lt i,   .bg-cyan-lt svg   { color: #67E8F9 !important; }

    /* Bootstrap-semantic ("success/danger/warning/info/primary/secondary")
       variants — Tabler aliases these to hue-based colours but the rules are
       distinct in CSS. Give them the same dark-mode lift. */
    .bg-success-lt,   .bg-success-lt i,   .bg-success-lt svg   { color: #86EFAC !important; }
    .bg-danger-lt,    .bg-danger-lt i,    .bg-danger-lt svg    { color: #FCA5A5 !important; }
    .bg-warning-lt,   .bg-warning-lt i,   .bg-warning-lt svg   { color: #FCD34D !important; }
    .bg-info-lt,      .bg-info-lt i,      .bg-info-lt svg      { color: #67E8F9 !important; }
    .bg-primary-lt,   .bg-primary-lt i,   .bg-primary-lt svg   { color: #93C5FD !important; }
    .bg-secondary-lt, .bg-secondary-lt i, .bg-secondary-lt svg { color: #D1D5DB !important; }

    /* Tint background derived from currentColor so any future -lt
       utility inherits the same legibility profile automatically. */
    .bg-blue-lt,  .bg-azure-lt, .bg-indigo-lt, .bg-purple-lt,
    .bg-pink-lt,  .bg-red-lt,   .bg-orange-lt, .bg-yellow-lt,
    .bg-lime-lt,  .bg-green-lt, .bg-teal-lt,   .bg-cyan-lt,
    .bg-success-lt, .bg-danger-lt, .bg-warning-lt, .bg-info-lt,
    .bg-primary-lt, .bg-secondary-lt {
        background-color: color-mix(in srgb, currentColor 22%, transparent) !important;
    }

    /* Standalone text-<hue> utilities (no tinted fill around them).
       Used for inline annotations like "Creates new blueprint". */
    .text-azure  { color: #7DD3FC !important; }
    .text-blue   { color: #93C5FD !important; }
    .text-indigo { color: #A5B4FC !important; }
    .text-purple { color: #D8B4FE !important; }
    .text-pink   { color: #F9A8D4 !important; }
    .text-red    { color: #FCA5A5 !important; }
    .text-orange { color: #FDBA74 !important; }
    .text-yellow { color: #FDE68A !important; }
    .text-lime   { color: #BEF264 !important; }
    .text-green  { color: #86EFAC !important; }
    .text-teal   { color: #5EEAD4 !important; }
    .text-cyan   { color: #67E8F9 !important; }
}

/* ---------------------------------------------------------------- */
/* Number range form (customer carrier number-ranges page)          */
/* Column proportions: Start Number compact, Range Size narrowest,  */
/* Route to widest. Header and row both follow the same ratios.     */
/* ---------------------------------------------------------------- */
.number-range-form .nr-col-start,
.number-range-form .nr-col-size,
.number-range-form .nr-col-route {
    min-width: 0;
}

/* Route to grows into the leftover space instead of a fixed 50% —
   22% + 28% + 50% left zero room for the action-button col-auto,
   wrapping the delete button onto its own line. */
.number-range-form .nr-col-start { flex: 0 0 22%; max-width: 22%; }
.number-range-form .nr-col-size  { flex: 0 0 28%; max-width: 28%; }
.number-range-form .nr-col-route { flex: 1 1 0; max-width: none; }

/* Range Size select stays compact — don't stretch to fill its column. */
.number-range-form [data-number-range-target="sizeSelect"] {
    width: auto !important;
    flex: 0 0 auto !important;
}

.number-range-form [data-number-range-target="customEndInput"] {
    flex: 1 1 auto;
    min-width: 0;
}

/* Match Range Size and Route to selects to the Start Number input.
   Mirror form-control-sm's font/padding/line-height and let the natural
   min-height match. Avoid hard-coded `height` — caused the selects to
   render shorter than the input. */
.number-range-form .form-select-sm {
    padding: 0.25rem 1.75rem 0.25rem 0.5rem !important;
    font-size: 0.75rem !important;
    line-height: 1.4285714286 !important;
    height: 2rem !important;        /* ~30px, matches Tabler form-control-sm */
    min-height: 2rem !important;
}
/* Datatable "Show N entries" length-select: Tabler's .form-select-sm renders a
   touch taller than the adjacent .form-control-sm search box, so the two controls
   in the table toolbar don't line up. Pin the length-select to the same ~30px box
   as form-control-sm (same approach as the number-range selects above). */
.dt-length-select.form-select-sm {
    height: 2rem !important;        /* ~30px, matches Tabler .form-control-sm */
    min-height: 2rem !important;
    padding-top: 0.25rem !important;
    padding-bottom: 0.25rem !important;
    line-height: 1.4285714286 !important;
}

/* Identity Call Quality — clickable device cards */
.card.card-link-style {
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  cursor: pointer;
}
.card.card-link-style:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(var(--tblr-primary-rgb), 0.15), 0 0 0 1px rgba(var(--tblr-primary-rgb), 0.4);
}

/* Async loader — app/views/shared/_async_loader.html.erb; artbook 3RSrG1UDxYj5MsqSQhHkUi, board 7.
   Placed where the result appears: inline on the content edge (a list, a section) or as a card
   centred in a reserved canvas. The only motion is the dots on what is running now. */
.async-loader {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 440px;
  padding: 1rem 0;
  /* Not shown for loads under 300 ms: a flash is worse than nothing. */
  animation: async-loader-show 0s linear 300ms both;
}
.async-loader--card {
  width: 420px;
  max-width: calc(100% - 2rem);
  padding: 1.25rem 1.375rem;
  gap: 0.875rem;
  background: var(--tblr-bg-surface);
  border: 1px solid var(--tblr-border-color);
  border-radius: 8px;
}
.async-loader--failed { animation: none; }
.async-loader__head { display: flex; align-items: center; gap: 0.625rem; }
.async-loader__title { font-size: 0.9375rem; font-weight: 600; color: var(--tblr-body-color); }
.async-loader__elapsed {
  margin-left: auto;
  font-size: 0.8125rem;
  color: var(--tblr-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.async-loader--inline .async-loader__elapsed { margin-left: 0; }
.async-loader__note, .async-loader__slow { font-size: 0.8125rem; color: var(--tblr-secondary); line-height: 1.5; }
.async-loader--inline .async-loader__note, .async-loader--inline .async-loader__slow { padding-left: 2.5rem; }
.async-loader--card .async-loader__note {
  border-top: 1px solid var(--tblr-border-color-translucent);
  padding-top: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.async-loader__slow { color: var(--tblr-body-color); }
.async-loader__steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.async-loader__step { display: flex; align-items: center; gap: 0.625rem; font-size: 0.875rem; min-height: 22px; }
.async-loader__step-mark { width: 18px; display: inline-flex; justify-content: center; flex-shrink: 0; }
.async-loader__step--pending { color: var(--tblr-gray-500); }
.async-loader__step--pending .async-loader__step-mark::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--tblr-gray-400); box-sizing: border-box;
}
.async-loader__step--active { font-weight: 500; }
.async-loader__step--done { color: var(--tblr-body-color); }
.async-loader__step--done .async-loader__step-mark { color: var(--tblr-green); }
.async-loader__step--failed { color: var(--tblr-red); font-weight: 500; }
.async-loader__step-time { margin-left: auto; font-size: 0.8125rem; color: var(--tblr-secondary); font-variant-numeric: tabular-nums; }
.async-loader__dots { display: inline-flex; gap: 4px; align-items: center; justify-content: center; width: 30px; flex-shrink: 0; }
.async-loader__dots i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--tblr-primary);
  animation: async-loader-blink 1.2s ease-in-out infinite;
}
.async-loader__step-mark .async-loader__dots { width: 18px; gap: 3px; }
.async-loader__step-mark .async-loader__dots i { width: 4px; height: 4px; }
.async-loader__dots i:nth-child(2) { animation-delay: 0.2s; }
.async-loader__dots i:nth-child(3) { animation-delay: 0.4s; }
/* The canvas an async card waits in: the footprint of what it will draw. */
.async-canvas {
  position: relative;
  height: 75vh;
  min-height: 600px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--tblr-bg-surface);
  background-image: radial-gradient(var(--tblr-border-color) 1px, transparent 1px);
  background-size: 18px 18px;
  border: 1px solid var(--tblr-border-color);
  border-radius: 6px;
}
.async-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 5; pointer-events: none; }
.async-overlay > * { pointer-events: auto; }
/* Placeholder rows under a list loader: the real columns, nothing invented. */
.async-skeleton td { height: 36px; }
.async-skeleton__bar { display: block; height: 10px; border-radius: 5px; background: var(--tblr-bg-surface-secondary, #eef1f5); }
@keyframes async-loader-show { from { visibility: hidden; } to { visibility: visible; } }
@keyframes async-loader-blink { 0%, 80%, 100% { opacity: 0.2; } 40% { opacity: 1; } }
@keyframes async-loader-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .async-loader__dots i { animation: none; opacity: 0.6; }
}

/* ---- Telephony Analytics dashboard grid -------------------------- */
/* 4-column CSS Grid wrapper for the analytics widgets. Each grid     */
/* item declares its own grid-column / grid-row span based on the     */
/* shape's SHAPE_SIZES entry. `grid-auto-flow: dense` packs items     */
/* tightly when later items are smaller than the gap they could fill. */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: 72px;
  grid-auto-flow: dense;
  gap: 1rem;
  /* Keep a small margin under the filter row above */
  margin-bottom: 1rem;
}

.dashboard-grid-item {
  /* Allow children to shrink inside the grid cell — without this, an  */
  /* ApexCharts SVG can blow out the column to its intrinsic width.    */
  min-width: 0;
  position: relative;
}

.dashboard-grid-item > .lazy-async-frame,
.dashboard-grid-item > turbo-frame {
  display: block;
  height: 100%;
}

.dashboard-grid-item .card,
.dashboard-grid-item .card-sm {
  /* Cards stretch to their grid cell so a 2-row gauge / 4-row chart   */
  /* fills its full vertical span. Without this they'd sit at their    */
  /* intrinsic content height and leave gaps below.                    */
  height: 100%;
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
}

/* Card body fills the remaining space below the optional card-header. */
.dashboard-grid-item .card > .card-body {
  flex: 1 1 auto;
  min-height: 0;
}

/* Chart bodies host the ApexCharts container as a flex child so the
   chart's percentage height resolves to the cell-derived pixel height.
   Padding tightened from Tabler's default ~1.25 rem so the chart has
   room for axis ticks + bottom legend without the card clipping it. */
.dashboard-grid-item .card > .card-body.chart-body {
  display: flex;
  flex-direction: column;
  padding: 0.5rem 0.75rem 0.875rem;
}
.dashboard-grid-item .card > .card-body.chart-body > [data-controller="apexchart"] {
  /* flex-basis 0 + grow:1 = the host fills the card-body purely from
     the flex parent's height, never from the chart's intrinsic SVG
     content height. Without this ApexCharts and the flex parent enter
     a feedback loop: SVG grows host, host grows parent, ResizeObserver
     fires (when watching the host), chart re-renders larger, repeat.
     We avoid `overflow: hidden` here so the bottom-positioned legend
     isn't clipped — the resize loop is already broken by:
       (a) basis 0 keeping the host's intrinsic content out of the
           flex calculation, and
       (b) the ResizeObserver in apexchart_controller.js targeting the
           parent cell (grid-driven, stable) with a 2 px tolerance. */
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  position: relative;
}

/* Tile-class cards (tile_stat / trend_tile / sparkline_tile / gauge):
   centre the single content row vertically inside the now-stretched
   card so the icon + headline don't sit at the top of a 1-row 72px
   cell. card-sm marks the simple stat tile. */
.dashboard-grid-item .card.card-sm > .card-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Sparkline / gauge chart inside a tile fills the remaining vertical
   space *after* the tile_chrome card-body, never the whole card.
   flex-basis: 0 keeps the SVG out of the flex sizing calculation
   (same anti-feedback rule as `.chart-body` charts above). */
.dashboard-grid-item .card > .dashboard-tile-chart {
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  position: relative;
}

/* Table widgets scroll vertically inside the cell when the row count
   exceeds the cell's height (e.g. 25 worst-mos rows in a 4-row cell). */
.dashboard-grid-item .card > .card-body.card-no-padding {
  overflow: hidden;
  padding: 0;
}
.dashboard-grid-item .card > .card-body.card-no-padding > .table-responsive {
  flex: 1 1 auto;
  min-height: 0;
  height: 100%;
  overflow-y: auto;
}

/* Drag handle in the corner of every dashboard widget. Visible only on
   hover so the card chrome isn't cluttered when you're not dragging. */
.dashboard-grid-item .dashboard-drag-handle {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  /* Above Apex's internal overlay z-indexes (~10..100) so chart cards
     stay grabbable. Without this the handle sits under Apex's
     tooltip / zoom-scroll layers and pointerdown never fires on it. */
  z-index: 200;
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--tblr-secondary);
  cursor: grab;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.dashboard-grid-item:hover .dashboard-drag-handle,
.dashboard-grid-item.sortable-chosen .dashboard-drag-handle {
  opacity: 0.7;
}

.dashboard-grid-item .dashboard-drag-handle:hover {
  opacity: 1;
}

.dashboard-grid-item .dashboard-drag-handle:active {
  cursor: grabbing;
}

/* Skeleton placeholder while a dashboard widget's lazy frame is
   fetching. Sits flush with the grid cell, hides the spinner +
   "Loading widget" text the legacy lazy_async_frame would have
   rendered, and shimmers softly so a dashboard with 18 cells
   doesn't look like a swarm of spinners on cold load. */
.dashboard-grid-item .dashboard-skeleton {
  position: relative;
  overflow: hidden;
}

.dashboard-grid-item .dashboard-skeleton .dashboard-skeleton-shimmer {
  position: absolute;
  inset: 0.75rem;
  border-radius: 4px;
  background: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.04) 0%,
    rgba(0, 0, 0, 0.08) 50%,
    rgba(0, 0, 0, 0.04) 100%
  );
  background-size: 200% 100%;
  animation: dashboard-skeleton-shimmer 1.6s ease-in-out infinite;
}

@keyframes dashboard-skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Inline card-header action icons (refresh + close). Borderless;
   colour-glow on hover instead of a button background. The two
   modifier classes give per-action accent: blue on refresh, red on
   close. */
.dashboard-card-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--tblr-secondary);
  border-radius: 4px;
  text-decoration: none;
  cursor: pointer;
  transition: color 0.15s ease;
}

.dashboard-card-action:focus,
.dashboard-card-action:focus-visible {
  outline: none;
  box-shadow: none;
  background: transparent;
}

.dashboard-card-action:hover {
  background: transparent;
}

.dashboard-card-action--refresh:hover {
  color: var(--tblr-primary);
}

.dashboard-card-action--close:hover {
  color: var(--tblr-danger);
}

/* Close (hide) button in the top-right of every grid item. Same
   hover-only visibility pattern as the drag handle. Click removes
   the slot from this user's saved layout via dashboard_close_controller. */
.dashboard-grid-item .dashboard-close-handle {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  z-index: 200;
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--tblr-secondary);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.dashboard-grid-item:hover .dashboard-close-handle {
  opacity: 0.7;
}

.dashboard-grid-item .dashboard-close-handle:hover {
  opacity: 1;
  color: var(--tblr-danger);
}

/* Resize grip in the bottom-right corner. Same hover-only visibility
   pattern as the drag handle. The diagonal resize cursor signals
   width+height drag; the dashboard_resize_controller takes over on
   pointerdown and snaps to integer cell deltas. */
.dashboard-grid-item .dashboard-resize-handle {
  position: absolute;
  bottom: 0.25rem;
  right:  0.25rem;
  /* Above Apex's internal overlay z-indexes (~10..100) so chart cards
     stay resizable. */
  z-index: 200;
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--tblr-secondary);
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity 0.15s ease;
  user-select: none;
  touch-action: none;
}

.dashboard-grid-item:hover .dashboard-resize-handle,
.dashboard-grid-item--resizing .dashboard-resize-handle {
  opacity: 0.7;
}

.dashboard-grid-item .dashboard-resize-handle:hover {
  opacity: 1;
}

/* While a resize is in progress, outline the cell so the user can see
   which item they're sizing — gives explicit feedback in addition to
   the snap-to-cell layout reflow. */
.dashboard-grid-item--resizing {
  outline: 2px dashed var(--tblr-primary);
  outline-offset: -2px;
}

/* Prevent text-selection mid-drag on the rest of the page. */
.dashboard-grid-item--resizing,
.dashboard-grid-item--resizing * {
  user-select: none;
}

@media (max-width: 768px) {
  .dashboard-grid-item .dashboard-resize-handle {
    display: none;
  }
}

/* Mobile: collapse the grid to a single column with auto-row height. */
@media (max-width: 768px) {
  .dashboard-grid {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
  }
  .dashboard-grid-item {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
  }
}

/* Edit mode gating. Read mode (default): hide all handles, the [+]
   placeholder card, and the per-tab X. Edit mode (the page wrapper
   carries .dashboard--edit-mode via dashboard_edit_mode_controller):
   reveal them. */
.container-xl:not(.dashboard--edit-mode) .dashboard-grid-item .dashboard-drag-handle,
.container-xl:not(.dashboard--edit-mode) .dashboard-grid-item .dashboard-close-handle,
.container-xl:not(.dashboard--edit-mode) .dashboard-grid-item .dashboard-resize-handle {
  display: none !important;
}

/* [+] add-widget placeholder card sits at the top of the grid in edit
   mode; in read mode it disappears (no slot for it). */
.dashboard-add-placeholder { display: none; }
.dashboard--edit-mode .dashboard-add-placeholder { display: block; }
.dashboard-add-placeholder-btn {
  border-style: dashed !important;
  border-width: 2px !important;
  border-color: var(--tblr-border-color);
  background: transparent;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.dashboard-add-placeholder-btn:hover {
  border-color: var(--tblr-primary) !important;
  color: var(--tblr-primary) !important;
}

/* Gallery card tile in the "+ Dashboard" modal. Each card is a
   button wrapping an avatar + title + description. Without these
   styles the buttons render bare (no border, no padding) so the
   modal reads as a list of run-on text. Tile gives a consistent
   clickable target with a soft hover. h-100 on the column lets
   adjacent cards equalize height regardless of description length. */
.dashboard-gallery-card {
  display: block;
  width: 100%;
  height: 100%;
  padding: 1rem;
  border: 1px solid var(--tblr-border-color);
  border-radius: 8px;
  background: var(--tblr-card-bg);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.dashboard-gallery-card:hover {
  border-color: var(--tblr-primary);
  box-shadow: 0 0 0 1px var(--tblr-primary);
  background: rgba(var(--tblr-primary-rgb), 0.02);
}
.dashboard-gallery-card:focus,
.dashboard-gallery-card:focus-visible {
  outline: none;
  border-color: var(--tblr-primary);
  box-shadow: 0 0 0 2px rgba(var(--tblr-primary-rgb), 0.25);
}

/* Icon picker tile in the dashboard settings modal. Clickable label
   wraps a hidden radio + a Tabler icon — without these styles the
   labels were invisible (no border, no padding) so the user couldn't
   tell what was clickable. Active state uses :has(:checked) so the
   selected tile lights up in primary blue without any JS. */
.dashboard-icon-pick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--tblr-border-color);
  border-radius: 6px;
  color: var(--tblr-secondary);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.dashboard-icon-pick:hover {
  border-color: var(--tblr-primary);
  color: var(--tblr-primary);
}
.dashboard-icon-pick.is-active,
.dashboard-icon-pick:has(input:checked) {
  border-color: var(--tblr-primary);
  color: var(--tblr-primary);
  background: rgba(var(--tblr-primary-rgb), 0.1);
}
.dashboard-icon-pick i {
  font-size: 1.1rem;
  line-height: 1;
}

/* Edit toggle in the toolbar. Inherits btn-ghost-secondary in read
   mode; flips to primary blue with a soft tinted background when the
   wrapper is in edit mode so users see the toggle is active. */
.dashboard--edit-mode .dashboard-edit-toggle {
  color: var(--tblr-primary);
  background-color: rgba(var(--tblr-primary-rgb), 0.12);
}
.dashboard--edit-mode .dashboard-edit-toggle:hover {
  color: var(--tblr-primary);
  background-color: rgba(var(--tblr-primary-rgb), 0.2);
}

/* Per-tab X delete button. Hidden by default, shown in edit mode.
   Sits to the right of the tab's title text. */
.dashboard-tab-remove {
  display: none;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 0.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--tblr-secondary);
  cursor: pointer;
  vertical-align: middle;
  transition: background 0.15s ease, color 0.15s ease;
}
.dashboard-tab-remove:hover {
  background: rgba(var(--tblr-danger-rgb), 0.12);
  color: var(--tblr-danger);
}
.dashboard--edit-mode .dashboard-tab .dashboard-tab-remove {
  display: inline-flex;
}

/* Blueprint Assignments 30-day heatmap cells.
   `<a>`-wrapped cells get a subtle hover lift + cursor, so they
   read as clickable drill-downs into the Blueprint Activity page. */
.heatmap-cell {
  display: block;
  transition: transform 0.1s ease, filter 0.1s ease;
  cursor: pointer;
}
.heatmap-cell:hover,
.heatmap-cell:focus {
  transform: translateY(-1px);
  filter: brightness(1.1);
  outline: none;
}

/* ---- Business hours heatmap ----
   Driven by app/javascript/controllers/business_hours_heatmap_controller.js.
   Days as rows (Mon-Sun), 48 half-hour cells across (00:00-23:30), 16×16
   squares. Per-row text-input ranges editor on the right. Paint by clicking
   or dragging; select a region with a single click; right-click a region
   to delete it; right-drag to erase a rectangle. */
.cf-heatmap-presets {
  display: flex;
  align-items: center;
  gap: .375rem;
  margin-bottom: .75rem;
  flex-wrap: wrap;
}
.cf-heatmap {
  width: max-content;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, .25rem);
  background: var(--tblr-bg-surface, #fff);
  overflow: visible;
}
.cf-heatmap,
.cf-heatmap *:not(input) {
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}
.cf-heatmap-headers,
.cf-heatmap-row {
  display: grid;
  grid-template-columns: 40px repeat(48, 14px) 130px;
  align-items: center;
  position: relative;
}
.cf-heatmap-headers {
  border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
  background: var(--tblr-bg-surface-secondary, #f4f5f7);
  padding: 6px 0;
}
.cf-heatmap-corner { width: 40px; }
.cf-heatmap-time-label {
  font-size: .75rem;
  font-weight: 500;
  color: var(--tblr-body-color, #232e3c);
  padding-left: 2px;
  line-height: 1;
}
.cf-heatmap-day-label {
  font-size: .8125rem;
  font-weight: 600;
  text-align: right;
  padding-right: 8px;
  color: var(--tblr-body-color, #232e3c);
}
.cf-heatmap-row { min-height: 20px; }
.cf-heatmap-row + .cf-heatmap-row {
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
}
.cf-heatmap-row-weekend { background: rgba(0, 0, 0, .02); }

/* Cells */
.cf-heatmap-cell {
  width: 14px;
  height: 18px;
  border-left: 1px solid rgba(0, 0, 0, .04);
  cursor: pointer;
  background: transparent;
  transition: background-color .08s ease, box-shadow .08s ease;
}
/* Stronger border at every full hour (cells tagged .cf-heatmap-cell-hour-start) */
.cf-heatmap-cell.cf-heatmap-cell-hour-start {
  border-left: 1px solid #adb5bd;
}
.cf-heatmap-cell:hover {
  background: var(--tblr-green-lt, rgba(47, 179, 68, .12));
}
.cf-heatmap-cell.cf-heatmap-cell-open {
  background: var(--tblr-green, #2fb344);
}

/* Pill grouping: contiguous open cells render as one continuous pill */
.cf-heatmap-cell-pill-first { border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
.cf-heatmap-cell-pill-last  { border-top-right-radius: 4px; border-bottom-right-radius: 4px; }
.cf-heatmap-cell-pill-only  { border-radius: 4px; }
.cf-heatmap-cell-pill-middle,
.cf-heatmap-cell-pill-last  { border-left-color: transparent !important; }

/* Selection: single rounded outline + primary-blue fill for cells inside */
.cf-heatmap-selection-overlay {
  border: 2px solid var(--tblr-primary, #066fd1);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .9),
    0 0 4px rgba(6, 111, 209, .35);
  border-radius: 5px;
  z-index: 4;
}
.cf-heatmap-cell.cf-heatmap-cell-selected-fill.cf-heatmap-cell-open {
  background: var(--tblr-primary, #066fd1) !important;
}
.cf-heatmap-cell.cf-heatmap-cell-selected-fill:not(.cf-heatmap-cell-open) {
  background: rgba(6, 111, 209, .08) !important;
}

/* Hover preselection: subtle dark outline */
.cf-heatmap-hover-overlay {
  border: 1.5px solid rgba(0, 0, 0, .45);
  border-radius: 5px;
  z-index: 3;
}

/* Drag previews */
.cf-heatmap-cell-preview {
  box-shadow: inset 0 0 0 2px var(--tblr-green, #2fb344);
  background: var(--tblr-green-lt, rgba(47, 179, 68, .22)) !important;
}
.cf-heatmap-cell-preview.cf-heatmap-cell-open {
  background: var(--tblr-green, #2fb344) !important;
  opacity: .8;
}
.cf-heatmap-cell-erase-preview {
  box-shadow: inset 0 0 0 1px var(--tblr-red, #dc3545);
  background: rgba(220, 53, 69, .22) !important;
}
.cf-heatmap-cell-erase-preview.cf-heatmap-cell-open {
  background: rgba(220, 53, 69, .55) !important;
  opacity: .85;
}

/* Per-row range editor */
.cf-heatmap-ranges-header {
  font-size: .625rem;
  color: var(--tblr-secondary, #6b7280);
  padding-left: 8px;
}
.cf-heatmap-ranges {
  width: calc(130px - 12px);
  margin: 0 6px;
  font-size: .6875rem;
  padding: .125rem .375rem;
  font-variant-numeric: tabular-nums;
}
.cf-heatmap-ranges::placeholder {
  color: var(--tblr-secondary, #adb5bd);
  font-style: italic;
}
.cf-heatmap-ranges:focus {
  box-shadow: 0 0 0 2px var(--tblr-green-lt, rgba(47, 179, 68, .25));
}

/* Legend below the grid */
.cf-heatmap-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .375rem 1rem;
  margin-top: .625rem;
  font-size: .75rem;
  color: var(--tblr-secondary, #6b7280);
}
.cf-heatmap-legend-item {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
}
.cf-heatmap-legend-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
}
.cf-heatmap-legend-swatch-open {
  background: var(--tblr-green, #2fb344);
  border-color: transparent;
}
.cf-heatmap-legend i { font-size: .875rem; }

/* ==========================================================================
   Voice Connections - vertical list rows
   Shared by the PBX server rows (PbxServerCardComponent) and the carrier rows
   (CarrierCardComponent), so the two can later merge into one list. White
   "job-listing" style cards; corners follow the branding radius (.card uses
   var(--tblr-border-radius)). Only the hover lift + the display:contents lazy
   frame live here.
   ========================================================================== */
.vc-row {
  cursor: pointer;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.vc-row:hover {
  border-color: var(--tblr-primary);
  box-shadow: 0 2px 10px rgba(24, 36, 51, 0.06);
}

/* A lazy Turbo Frame wrapping the identity + data band must not break the flex
   row grid, so it participates as if it were not there. */
.vc-frame {
  display: contents;
}

/* Small uppercase column label inside each row. */
.vc-col-label {
  font-size: 0.625rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 700;
}

/* Vertical "or" divider — a grey rule between two side-by-side choices with the
   word "or" floated in the middle. Mirrors Tabler's horizontal .hr-text but runs
   top-to-bottom. On small screens it collapses to a horizontal rule. */
.or-divider-vertical {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.or-divider-vertical::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--tblr-border-color);
}
.or-divider-vertical > span {
  position: relative;
  z-index: 1;
  padding: 0.5rem 0;
  background: var(--tblr-bg-surface);
  color: var(--tblr-secondary);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
@media (max-width: 767.98px) {
  .or-divider-vertical::before {
    top: 50%;
    bottom: auto;
    left: 0;
    right: 0;
    width: auto;
    height: 1px;
  }
  .or-divider-vertical > span {
    padding: 0 0.5rem;
  }
}

/* ==========================================================================
   Read-only "View as" impersonation overlay
   Floating pill centered at the bottom of the screen while a super-admin is
   viewing the app through another user's eyes. See
   app/views/layouts/shared/_impersonation_banner.html.erb
   ========================================================================== */
.impersonation-overlay {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%);
  z-index: 1080; /* above page content + sticky headers, below modals (1055+ backdrop) */
  pointer-events: none; /* let clicks pass except on the pill itself */
  max-width: calc(100vw - 2rem);
}

.impersonation-overlay-inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem 0.5rem 1rem;
  border-radius: 999px;
  background: var(--tblr-orange, #f76707);
  color: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  animation: impersonation-overlay-in 0.18s ease-out;
}

.impersonation-overlay-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  font-size: 1rem;
  flex: 0 0 auto;
}

.impersonation-overlay-text {
  min-width: 0;
  line-height: 1.2;
}

.impersonation-overlay-text > div {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.impersonation-overlay-sub {
  font-size: 0.75rem;
  opacity: 0.85;
}

/* Translucent "on-color" pill that sits on the orange instead of a solid white block */
.impersonation-overlay-exit {
  flex: 0 0 auto;
  border-radius: 999px;
  padding: 0.25rem 0.85rem;
  font-weight: 600;
  color: #fff;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.5);
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

.impersonation-overlay-exit:hover,
.impersonation-overlay-exit:focus {
  color: #fff;
  background: rgba(255, 255, 255, 0.32);
  border-color: rgba(255, 255, 255, 0.85);
}

@keyframes impersonation-overlay-in {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Teams voice config: dim + disable the phone-number fields when the user has no
   Phone System (MCOEV) license (assigning a number would fail in Teams). */
.voice-fields-disabled {
  opacity: 0.5;
  pointer-events: none;
}

/* Setup wizard go_live step: neutral pill chips with a status dot for the
   collapsed "Configuration" summary, and a dashed frame around the lazily-loaded
   directory-user picker. Tabler has no ready-made equivalent for either. */
.wizard-summary-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  font-size: 0.6875rem;
  background: var(--tblr-bg-surface-tertiary);
  border-radius: 999px;
  padding: 0.1875rem 0.5rem 0.1875rem 0.375rem;
  color: var(--tblr-secondary-color);
}

.wizard-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  display: inline-block;
  flex-shrink: 0;
}

.wizard-picker-frame {
  border: 1px dashed var(--tblr-border-color);
  border-radius: 8px;
  padding: 0.75rem;
  background: var(--tblr-bg-surface-tertiary);
}

/* Trunk device tab: the right-hand card (tabs + element table) sits beside a
   fixed-height sidebar card via Bootstrap's default row stretch. .card is
   already display:flex/flex-direction:column (Tabler default) - this just lets
   that flex chain continue through tab-content into whichever tab-pane is
   active, so its card-footer (Verify/Push All/Delete All) pins to the bottom
   of the card's full stretched height instead of trailing right after a short
   table. Scoped to this one component so it doesn't touch tabs elsewhere. */
.trunk-device-tabs {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.trunk-device-tabs > .tab-pane.active {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.trunk-device-tabs > .tab-pane.active > .card-body {
  flex: 0 0 auto;
  min-height: 0;
}

/* The filler div between the table and the footer absorbs whatever height is
   left over, so the footer table sits flush at the bottom of the card instead
   of trailing right after a short table. */
.trunk-device-tabs > .tab-pane.active > .flex-grow-1 {
  flex: 1 1 auto;
  min-height: 0;
}

.trunk-device-tabs > .tab-pane.active > .card-footer {
  flex: 0 0 auto;
}

/* Action columns (Push/Delete/Configure/Verify) on the trunk & service device
   element tables: narrow and right-aligned so the buttons bunch together at
   the row's end instead of spreading out across wide centered columns. */
.device-action-col {
  padding-left: 0.35rem !important;
  padding-right: 0.5rem !important;
  white-space: nowrap;
}

/* Compact variant of Tabler's .status pill (no built-in "sm" size) so status
   badges sit at the same visual weight as the .badge-sm / code text used
   alongside them in the trunk device tables, instead of the default 1.5rem
   tall pill dominating the row. */
.status-sm {
  --tblr-status-height: 1.125rem;
  padding: 0.125rem 0.5rem;
  gap: 0.35rem;
  font-size: 0.75rem;
}
.status-sm .status-dot {
  --tblr-status-size: 0.4rem;
}

/* Marketplace cart button: floating notification badge (Tabler badge-notification)
   cut-out style - system background with a darker shade of the button color as
   border/text, so it reads as a punched-out counter on the button corner. */
.cart-notification-badge {
  background-color: var(--tblr-body-bg);
  color: color-mix(in srgb, var(--tblr-primary) 85%, black);
  border: 1px solid color-mix(in srgb, var(--tblr-primary) 70%, black);
}

/* Partner Finance - collapsible tenant rows on the Licenses tab */
.finance-tenant > summary { cursor: pointer; list-style: none; }
.finance-tenant > summary::-webkit-details-marker { display: none; }
.finance-tenant > summary .ti-chevron-right { transition: transform .15s ease; }
.finance-tenant[open] > summary .ti-chevron-right { transform: rotate(90deg); }

/* ==========================================================================
   ADMIN FORM SHEET  (FormSheetComponent)
   --------------------------------------------------------------------------
   One sheet of labelled sections instead of a stack of cards. The rules this
   layer enforces, because they are what made the old admin forms read as
   assembled rather than designed:

     - one surface per form, sections divided by a hairline, never nested cards
     - one type scale and one family (Tabler's) - weight and letter-spacing do
       the work that extra fonts used to
     - a fixed 12-column field grid, so two forms never disagree about how
       wide a "half" field is
     - the full window width is used, but the reading column stays bounded so
       a wide screen gives more room to the aside, not longer lines
   ========================================================================== */

.sheet-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.sheet-layout--split { grid-template-columns: minmax(0, 1fr) 420px; }
@media (max-width: 1300px) { .sheet-layout--split { grid-template-columns: minmax(0, 1fr); } }
/* A sheet in a detail card's content column fills the column, so on a short page the action bar sits on the card's
   bottom edge instead of floating under the last band with the card's empty space below it. It still sticks to the
   viewport on a long page. */
.card-sidebar-layout .d-flex.flex-column > .sheet-layout { flex: 1 1 auto; align-items: stretch; }
.card-sidebar-layout .d-flex.flex-column > .sheet-layout > .sheet { display: flex; flex-direction: column; }
.card-sidebar-layout .d-flex.flex-column > .sheet-layout > .sheet > .sheet-actions { margin-top: auto; }
/* Provenance in a sheet: the same quiet line as on the identity pages, above the action bar. In a filling sheet it
   is what sits on the bottom, with the bar directly under it. */
.sheet-provenance { padding: .6rem 1.5rem; border-top: 1px solid var(--tblr-border-color); font-size: .8125rem;
                    color: var(--tblr-secondary); }
@container sheet (max-width: 820px) { .sheet-provenance { padding-inline: 1.15rem; } }
.card-sidebar-layout .d-flex.flex-column > .sheet-layout > .sheet > .sheet-provenance { margin-top: auto; }
.card-sidebar-layout .d-flex.flex-column > .sheet-layout > .sheet > .sheet-provenance + .sheet-actions { margin-top: 0; }

/* No `overflow: hidden` here: it clips `position: sticky` and the action bar
   stops sticking. Corners are rounded on the first/last child instead. The
   sheet is also the container fields measure themselves against. */
.sheet {
  background-color: var(--tblr-bg-surface);
  border: 1px solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  container: sheet / inline-size;
}

.sheet-head { padding: 1.15rem 1.5rem; border-bottom: 1px solid var(--tblr-border-color);
              border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0; }
.sheet-head__title { margin: 0; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.01em; }
.sheet-head__sub { margin: 0.2rem 0 0; font-size: 0.85rem; color: var(--tblr-secondary); max-width: 70ch; }
/* A sheet that is one platform service: its logo, its name, the platform as a tag on the right (Tenant › Voice). */
.sheet-head--row { display: flex; align-items: center; gap: .625rem; }
.sheet-head__logo { width: 1.75rem; height: 1.75rem; object-fit: contain; flex: none; }

/* The band: what the section is on the left, the fields on the right. The
   about column is fixed so every section on every form starts at the same
   x-position - that alignment is most of what "ordered" means here. */
.sheet-band {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: 2rem;
  padding: 1.4rem 1.5rem;
  border-bottom: 1px solid var(--tblr-border-color);
}
.sheet-band:last-of-type { border-bottom: 0; }
.sheet-band__about h2 { margin: 0 0 0.25rem; font-size: 0.9rem; font-weight: 600; }
/* h2, not h3: the page h1 is the title, so sections are the next level down.
   Heading order is an accessibility requirement, not a styling choice - the
   size here is set deliberately so semantics and appearance can disagree. */
.sheet-band__about p { margin: 0; font-size: 0.8rem; line-height: 1.5; color: var(--tblr-secondary); }
@container sheet (max-width: 820px) {
  .sheet-band { grid-template-columns: minmax(0, 1fr); gap: 0.85rem; padding: 1.15rem; }
}

/* Fixed field grid. Spans are the only widths a form may choose from, which is
   what stops columns drifting between pages. */
.sheet-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0.85rem 1rem; }
.sheet-grid > .sf-3  { grid-column: span 3; }
.sheet-grid > .sf-4  { grid-column: span 4; }
.sheet-grid > .sf-6  { grid-column: span 6; }
.sheet-grid > .sf-8  { grid-column: span 8; }
.sheet-grid > .sf-12 { grid-column: span 12; }
/* Fields re-flow by the width of their own CONTAINER, never the viewport: a
   viewport rule cannot see that an aside or a detail rail has taken the space,
   which is how a wider window ends up producing narrower fields. When a column
   narrows, fields drop to fewer per row - they are never squeezed. */
@container sheet (max-width: 1100px) { .sheet-grid > .sf-3 { grid-column: span 6; } }
@container sheet (max-width: 820px) {
  .sheet-grid > .sf-4, .sheet-grid > .sf-6, .sheet-grid > .sf-8 { grid-column: span 12; }
}
@container sheet (max-width: 560px) { .sheet-grid > .sf-3 { grid-column: span 12; } }
/* simple_form emits its own .mb-3 wrapper; the grid owns spacing here. */
.sheet-grid > [class^="sf-"] > .mb-3:last-child,
.sheet-grid > [class*=" sf-"] > .mb-3:last-child { margin-bottom: 0 !important; }

/* A value the form derives rather than accepts - shown so the consequence of a
   choice is visible, dashed so it reads as output, not input. */
.sheet-derived {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 0.65rem; border: 1px dashed var(--tblr-border-color);
  border-radius: var(--tblr-border-radius); background-color: var(--tblr-bg-surface-secondary);
  min-height: 2.25rem;
}
.sheet-derived__value { font-weight: 600; }
.sheet-derived__tag {
  font-size: 0.65rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--tblr-primary); margin-left: auto;
}

/* Action bar: stays on screen so the primary action never has to be scrolled for. */
.sheet-actions {
  position: sticky; bottom: 0; z-index: 2;
  border-radius: 0 0 var(--tblr-border-radius) var(--tblr-border-radius);
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  padding: 0.85rem 1.5rem;
  border-top: 1px solid var(--tblr-border-color);
  background-color: var(--tblr-bg-surface-secondary);
}
.sheet-actions .ms-auto { margin-left: auto; }
.sheet-actions__stat { font-size: 0.75rem; color: var(--tblr-secondary); line-height: 1.25; }
.sheet-actions__stat b { display: block; font-size: 0.95rem; color: var(--tblr-body-color); font-variant-numeric: tabular-nums; }

.sheet-aside { position: sticky; top: 1rem; display: flex; flex-direction: column; gap: 1rem; }
@media (max-width: 1300px) { .sheet-aside { position: static; } }

/* Editable line tables inside a sheet: ONE header row, figures right-aligned
   and tabular, inputs sized by the column rather than by their own labels. */
.sheet-lines { width: 100%; border-collapse: collapse; }
.sheet-lines thead th {
  font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--tblr-secondary); font-weight: 600; text-align: left;
  padding: 0 0.5rem 0.45rem; border-bottom: 1px solid var(--tblr-border-color);
}
.sheet-lines thead th.n { text-align: right; }
.sheet-lines tbody td { padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--tblr-border-color); vertical-align: middle; }
.sheet-lines tbody tr:last-child td { border-bottom: 0; }
.sheet-lines td.n { text-align: right; }
.sheet-lines td.n .form-control { text-align: right; }
.sheet-lines td.amount { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.sheet-lines .form-control, .sheet-lines .form-select { min-width: 0; }
.sheet-lines-scroll { overflow-x: auto; }
.sheet-lines-scroll > .sheet-lines { min-width: 640px; }
/* First and last cell sit ON the content edge rather than a half-cell inside
   it, so the table's left edge lines up with the fields and boxes above it.
   These tables used to be wrapped in .sheet-flush, which bleeds 1.5rem past the
   band and put them left of everything else on the page. */
.sheet-lines thead th:first-child, .sheet-lines tbody td:first-child { padding-left: 0; }
.sheet-lines thead th:last-child, .sheet-lines tbody td:last-child { padding-right: 0; }
/* The quiet confirmation a self-saving row shows. */
.sheet-lines .row-status { font-size: .75rem; color: var(--tblr-secondary); }

/* --- a nested table is flush ---------------------------------------------
   Inside a detail tab a table never draws its own border: the card around it
   already has one. `flush: true` drops the border and radius; the rest of this
   makes the component's cells read the same as a `.sheet-lines` table, so a
   read-only list and an editable one are the same object with different
   contents rather than two table designs on neighbouring tabs.
   See .claude/rules/admin-design.md. */
.detail-content__body .simple-table--flush { background: transparent !important; }
.detail-content__body .simple-table--flush > table { margin-bottom: 0; }
.detail-content__body .simple-table--flush thead th {
  background: var(--tblr-bg-surface-tertiary); border-top: 0;
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tblr-secondary); font-weight: 600;
  padding: .4rem .5rem; border-bottom: 1px solid var(--tblr-border-color);
}
/* A table the band above already names has no header bar, so its column labels
   ARE its top edge: quiet, on a hairline, and on the content edge so the columns
   line up with the fields and boxes above them. A titled one keeps the grey
   band, because it has a grey title bar to sit under. */
.detail-content__body .simple-table--flush:not(.simple-table--titled) thead th {
  background: transparent; padding: 0 .5rem .45rem;
}
.detail-content__body .simple-table--flush tbody td {
  padding: .5rem; border-bottom: 1px solid var(--tblr-border-color);
  border-top: 0; vertical-align: middle;
}
.detail-content__body .simple-table--flush tbody tr:last-child td { border-bottom: 0; }
/* First and last cell on the content edge, so the table lines up with the
   fields and boxes above it. Only where there is something above to line up
   with: a titled table keeps its cells inset to the same x as its title bar,
   because a grey band with its labels on the very edge hugs the card's border.
   The component already puts ps-3/pe-3 on those cells, so this is a matter of
   not taking it away. */
.detail-content__body .simple-table--flush:not(.simple-table--titled) thead th:first-child,
.detail-content__body .simple-table--flush:not(.simple-table--titled) tbody td:first-child { padding-left: 0; }
.detail-content__body .simple-table--flush:not(.simple-table--titled) thead th:last-child,
.detail-content__body .simple-table--flush:not(.simple-table--titled) tbody td:last-child { padding-right: 0; }
/* The title bar: the table's own name and count, on the same grey as the column
   heads under it, with no border around the whole thing - the card already has
   one, and a bordered panel inside a bordered card is a box in a box. */
.detail-content__body .simple-table--titled > .d-flex:first-child {
  border-bottom: 1px solid var(--tblr-border-color);
}

/* The commerce profile's segment tree: rows are divs, not a table (they nest and
   collapse), so they borrow the line table's head - one quiet row on a hairline,
   on the band's content edge like everything else in a band. */
.segment-grid__head {
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tblr-secondary); font-weight: 600;
  padding-bottom: .45rem; border-bottom: 1px solid var(--tblr-border-color);
}

.sheet-total {
  display: flex; justify-content: flex-end; align-items: baseline; gap: 0.9rem;
  margin-top: 0.9rem; padding-top: 0.75rem; border-top: 2px solid var(--tblr-body-color);
}
.sheet-total__label { font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--tblr-secondary); }
.sheet-total__value { font-size: 1.2rem; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Taxonomy chip: a TYPE or category (TLS, DDI, 088, a version), not a status.
   Neutral by design so semantic badge colour keeps meaning one thing and stays
   learnable - mixing the two is how a palette stops teaching anything. */
.tag {
  display: inline-block;
  font-size: 0.7rem; font-weight: 600;
  padding: 0.1rem 0.5rem; border-radius: 4px;
  border: 1px solid var(--tblr-border-color);
  color: var(--tblr-secondary);
  background-color: var(--tblr-bg-surface);
}

/* Sticky table header for long lists (past ~25 rows), so a column's meaning
   survives scrolling. Opt-in: the scroll container needs a bounded height. */
.table-sticky-head thead th {
  position: sticky; top: 0; z-index: 3;
  background-color: var(--tblr-bg-surface-tertiary);
}
/* NO inner scroll box. A table extends to its full height and the PAGE scrolls;
   if that is too much at once, the answer is fewer rows per page, which the
   controls strip already offers. A box-within-a-box gave two scrollbars, a
   second thing to find the bottom of, and - because `.card .table-responsive`
   sets `overflow: visible` for the row-action dropdowns - a capped height with
   no scrollbar at all, so any table taller than the cap painted straight over
   its own footer.
   `position: sticky` on the header still works: with no scrolling ancestor it
   sticks to the viewport, which is the behaviour that was wanted anyway. */
.adm-scroll { max-height: none; }

/* A dashboard PANEL is the opposite case and keeps its box. It is a summary
   widget, not an index: the failures list runs to 75 rows in the All lens, and
   a summary that pushes the rest of the dashboard off the screen has stopped
   summarising. `.card .table-responsive { overflow: visible }` (for the row
   dropdowns) has to be beaten on specificity, hence the doubled class. */
.adm-scroll-panel.adm-scroll-panel {
  max-height: min(60vh, 34rem);
  overflow-y: auto;
  overflow-x: auto;
}

/* ============================================================================
   ADMIN INDEX TABLE  (DataTableComponent)

   One row, one line, one rhythm. The row height is set here rather than by
   whichever cell happens to wrap: a list is read by scanning down a column, and
   a column you have to scan in twos is not a column. Anything with more to say
   than fits on a line gets its own column, or lives on the record.
   See .claude/rules/admin-design.md, Index page.
   ========================================================================== */
.adm-table { --adm-row-h: 36px; }
.adm-table thead th {
  background-color: var(--tblr-bg-surface-tertiary);
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  font-weight: 600; color: var(--tblr-secondary);
  padding: .35rem .75rem; white-space: nowrap; vertical-align: middle;
}
.adm-table tbody td {
  height: var(--adm-row-h); padding: 0 .75rem; vertical-align: middle;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 1px; /* makes ellipsis effective under table-layout: auto */
}
/* Figures compare down the column, so they are right-aligned and tabular. */
.adm-table td.text-end, .adm-table th.text-end { font-variant-numeric: tabular-nums; }
/* The action cell holds controls, not prose, so it is exempt from the ellipsis
   machinery above. A truncated sentence is still readable; a truncated button
   is unreachable - with `overflow: hidden` and `max-width: 1px` inherited here,
   a row's second and third actions were clipped to nothing and the buttons
   simply were not there (seen on /admin/branding, which carries up to three).
   Text columns give way first: abbreviating a name costs less than hiding an
   action. `overflow: visible` also lets the actions dropdown escape the cell. */
.adm-table tbody tr > td:last-child {
  white-space: nowrap; overflow: visible; max-width: none; width: 1%;
}
/* Declared column widths are only hints under `table-layout: auto`: the browser
   sizes each column from the content it holds, so the columns jump every time a
   filter changes the result set. Fixed layout makes a declared width the width.
   Applied only to tables that declare widths (DataTableComponent adds the
   class) - a table with no widths would otherwise render all columns equal. */
.adm-table--fixed { table-layout: fixed; }
.simple-table--fixed { table-layout: fixed; }
/* The ellipsis needs no max-width hack once the column width is authoritative. */
.adm-table--fixed tbody td { max-width: none; }
/* The action column is the one left unsized, so it takes what is left over.
   Under fixed layout "what is left over" can round to nothing, and a clipped
   button is unreachable - so it gets a floor.

   min-width, not width alone: width is only a starting size and any inline
   width beats it, so the column resizer - which pays for a drag by taking width
   from the last column first - could squeeze this one to the shared 48px floor
   and put the split button back outside its own cell. min-width is the floor
   the resizer reads (`floorFor`), so the cascade stops here and moves inward. */
.adm-table--fixed thead th:last-child { width: 6.5rem; min-width: 6.5rem; }

/* ---- Row height ---------------------------------------------------------
   .adm-table is the condensed row: 36px, one line, ellipsis. Comfortable is
   the same table with room to read rather than scan - a taller row, wrapping
   text and a full-size avatar. It is a working preference, remembered per
   table, so both shapes have to hold the same markup: only the metrics move,
   never the columns. */
/* Row-level state: a disabled identity is dimmed as a whole row, not in one
   cell. Set through DataTableComponent's row_class rather than an inline style
   so the table keeps one vocabulary. */
.adm-table tbody tr.adm-row--muted { opacity: .6; }
/* A row waiting on somebody. A marker on the leading edge rather than a wash
   across the row: the row already spends its colour on the status badge, and a
   tinted row outshouts it. Reading down the left edge, the flagged rows are the
   ones to work through. */
.adm-table tbody tr.adm-row--waiting > td:first-child {
  box-shadow: inset 3px 0 0 var(--tblr-warning);
}

/* The density toggle is icon-only, so the button has to carry its own size:
   .btn-icon collapses to the glyph (14px measured), which is neither a
   comfortable target nor readable. */
.dt-density-btn { min-width: 2rem; padding: .25rem .5rem; line-height: 1; }
.dt-density-btn i { font-size: 1.15rem; vertical-align: middle; }

/* The panel menu: one ⋮ holding view settings, column visibility, export and
   reset. Its segmented rows need to sit on one line with the label, and the
   menu must not close when a segment is clicked (data-bs-auto-close="outside"
   handles that side). */
.dt-panel-menu { min-width: 16rem; max-width: 20rem; }
.dt-menu-contents { display: contents; }

/* One grid for every row in the menu, whatever it is made of: an icon slot of a
   fixed width, then the label. The menu mixes three shapes - label-only rows
   (Rows, Width), Tabler `ti` items, and the export partial's `svg` icons with
   their own me-2 - and left to themselves each started at a different x. */
.dt-panel-menu .dropdown-item {
  display: flex; align-items: center; gap: .5rem;
  padding-left: 1rem; padding-right: 1rem;
}
.dt-panel-menu .dropdown-item > i,
.dt-panel-menu .dropdown-item > svg {
  flex: 0 0 1.15rem; width: 1.15rem; height: 1.15rem;
  margin: 0 !important; font-size: 1.05rem; line-height: 1; text-align: center;
}
.dt-panel-menu .dropdown-header { padding-left: 1rem; padding-right: 1rem; }

/* A settings row carries a control rather than an icon, so its label sits on
   the menu's own left edge with the section headers instead of being indented
   into the icon column - there is no icon there to line up with. */
.dt-panel-menu__row {
  display: flex; align-items: center; gap: .5rem;
  padding: .3rem 1rem;
}

/* Expandable rows: a narrow leading column holding the chevron, which turns
   when its detail row is open. */
.adm-table .dt-expand-col { width: 2.75rem; text-align: center; }
.adm-table .dt-expand { --tblr-btn-padding-y: .1rem; --tblr-btn-padding-x: .25rem; }
.adm-table .dt-expand i { transition: transform .15s ease; }
.adm-table .dt-expand.expanded i { transform: rotate(90deg); }
.adm-table tr.dt-detail-row > td { background: var(--tblr-bg-surface-secondary); }

/* A before/after cell in the audit trail's detail table. One line by default so
   a long JSON value cannot stretch the drawer, and the whole thing on hover -
   the point of opening a change is to read the value. Was inline <style> on the
   audit index, so the identity Activity tab, which renders the same partial,
   had no truncation at all. */
.dt-detail-row .audit-cell {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 0;
}
.dt-detail-row .audit-cell:hover {
  overflow: visible; white-space: normal; word-break: break-word;
}

/* Put a column away: revealed on hover of its header, so the header stays quiet
   until you are actually working on it. */
.adm-table thead th .dt-hide-column {
  position: absolute; top: 50%; right: 12px; transform: translateY(-50%);
  border: 0; background: transparent; padding: 0 .15rem; line-height: 1;
  color: var(--tblr-secondary); opacity: 0; transition: opacity .12s ease;
  cursor: pointer; z-index: 3;
}
.adm-table thead th:hover .dt-hide-column { opacity: .75; }
.adm-table thead th .dt-hide-column:hover { opacity: 1; color: var(--tblr-danger); }

/* The refresh control and its state light. Green means a stream is open; every
   other mode is a clock, which is a different claim and gets a neutral dot. The
   pulse is deliberately slow - a table that blinks at you is harder to read. */
/* Hover on the panel controls.
   Tabler's .btn-ghost-* fills the whole chip with grey on hover, which is a
   heavy answer to "is this a button?" - on a bar of five small controls it
   reads as five grey blocks appearing under the cursor. These say it with
   colour instead: the glyph takes the primary tint and the background gets a
   6% wash, enough to place the hit area without shouting. The ACTIVE state
   keeps its white chip, so selected still outranks hovered. */
.adm-controls .dt-density-btn.btn-ghost-secondary:hover,
.adm-controls .dt-density-btn.btn-ghost-secondary.show,
.card-header .dt-density-btn.btn-ghost-secondary:hover,
.card-header .dt-density-btn.btn-ghost-secondary.show,
.dt-panel-head .dt-density-btn.btn-ghost-secondary:hover,
.dt-panel-head .dt-density-btn.btn-ghost-secondary.show,
.dt-panel-menu .dt-density-btn.btn-ghost-secondary:hover,
.dt-refresh .dropdown-toggle:hover,
.dt-refresh .dropdown-toggle:focus-visible,
.dt-refresh .dropdown-toggle.show {
  background-color: color-mix(in srgb, var(--tblr-primary) 6%, transparent);
  color: var(--tblr-primary);
  border-color: transparent;
}
/* OPEN reads the same as hovered, deliberately. Bootstrap gives an open
   dropdown-toggle `.show` and its own active fill, which is the heavy grey
   these rules exist to avoid - so the ⋮ went grey the moment it was clicked
   while everything beside it stayed quiet. Same wash, and Tabler's
   `--tblr-btn-active-*` is overridden so nothing paints underneath it. */
.dt-panel-head .dt-density-btn.btn-ghost-secondary.show,
.adm-controls .dt-density-btn.btn-ghost-secondary.show,
.card-header .dt-density-btn.btn-ghost-secondary.show,
.dt-refresh .dropdown-toggle.show {
  --tblr-btn-active-bg: transparent;
  --tblr-btn-active-color: var(--tblr-primary);
  --tblr-btn-active-border-color: transparent;
}
/* The dots/ring keep their own meaning while the button is hovered. */
.dt-refresh .dropdown-toggle:hover .dt-live-dot.is-live { background: var(--tblr-green); }
.dt-refresh .dropdown-toggle:hover .dt-live-dot.is-off { background: var(--tblr-red); }

.dt-refresh .dropdown-toggle { display: inline-flex; align-items: center; gap: .4rem; }
/* The menu holds seven short labels and a dot; Bootstrap's default min-width is
   sized for sentences and left a wide empty gutter beside them. */
.dt-refresh .dropdown-menu { min-width: 7.5rem; }
.dt-refresh .dropdown-item { padding-left: .75rem; padding-right: .75rem; }
/* Bootstrap's caret carries a vertical-align meant for inline text, which sits
   it low inside a flex row. Centre it on the row and lift it a hair so it reads
   level with the label and the ring. */
.dt-refresh .dropdown-toggle::after {
  align-self: center; vertical-align: middle; margin-top: -.12em;
}
.dt-live-dot {
  width: .5rem; height: .5rem; border-radius: 50%; flex: 0 0 .5rem;
  background: var(--tblr-border-color-dark, #adb5bd);
}
.dt-live-dot.is-off { background: var(--tblr-red); }
.dt-live-dot.is-off { background: var(--tblr-red); }
.dt-live-dot.is-live {
  background: var(--tblr-green);
  box-shadow: 0 0 0 0 rgba(var(--tblr-green-rgb), .6);
  animation: dt-live-pulse 2.4s ease-out infinite;
}
@keyframes dt-live-pulse {
  70% { box-shadow: 0 0 0 .35rem rgba(var(--tblr-green-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--tblr-green-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .dt-live-dot.is-off { background: var(--tblr-red); }
.dt-live-dot.is-live { animation: none; }
}

/* A running timer shows its remaining time as a ring where the dot would be, so
   the control answers "when next?" without being opened. Ring only, no number:
   at 20px across, "60s" does not fit - the exact seconds are on the title. */
.dt-countdown { position: relative; display: inline-flex; width: 20px; height: 20px; }
/* The ring starts at twelve o'clock and empties clockwise as the seconds go. */
.dt-countdown svg { transform: rotate(-90deg); }
.dt-countdown circle[data-auto-refresh-target="ring"] { transition: stroke-dashoffset 1s linear; }

/* Column re-ordering: the header is the handle. Grab cursor only on the label
   area - the resize strip keeps its own col-resize cursor, so the two
   interactions never fight over the same pixels. */
.adm-table thead th[draggable="true"] .adm-th { cursor: grab; }
.adm-table thead th.dt-dragging { opacity: .4; }
.adm-table thead th.dt-drop-before { box-shadow: inset 3px 0 0 var(--tblr-primary); }
.adm-table thead th.dt-drop-after { box-shadow: inset -3px 0 0 var(--tblr-primary); }

/* Column resize: the indicator, and the column it acts on.
   The handle is ALWAYS visible - a hairline between the header cells, so the
   places you can drag are readable without hunting for them. Pointing at it
   thickens it; dragging paints the whole column so you can see what you are
   sizing rather than guessing from the header alone. */
.adm-table thead th { position: relative; }
.dt-resize-handle {
  position: absolute; top: 20%; right: -1px; width: 9px; height: 60%;
  cursor: col-resize; user-select: none; z-index: 2;
  display: flex; align-items: center; justify-content: center;
}
.dt-resize-handle::before {
  content: ""; width: 2px; height: 100%; border-radius: 1px;
  background: var(--tblr-border-color);
  transition: background-color .12s ease, height .12s ease;
}
.dt-resize-handle:hover::before,
.dt-resize-handle.is-active::before {
  background: var(--tblr-primary); height: 130%;
}

/* The column under the cursor, top to bottom. Deliberately stronger than a
   hover tint: it answers "which column am I about to change?", and a whole
   column of rows needs more than a whisper to read as one thing. */
.adm-table th.dt-col-active,
.adm-table td.dt-col-active {
  background-color: color-mix(in srgb, var(--tblr-primary) 14%, transparent);
  box-shadow: inset -2px 0 0 var(--tblr-primary);
}
.adm-table th.dt-col-active { background-color: color-mix(in srgb, var(--tblr-primary) 22%, transparent); }

/* While dragging, the pointer owns the page: no text selection, no I-beam. */
body.dt-resizing, body.dt-resizing * { cursor: col-resize !important; user-select: none; }

.adm-table--comfortable { --adm-row-h: 56px; }
/* Condensed is ONE line - but it does not THROW AWAY the second line, it folds
   it onto the first. Hiding it made the row shorter by losing information;
   inline, the cell keeps everything it had and the row still cannot grow,
   because the cell's own nowrap + ellipsis truncates whatever does not fit. */
.adm-table:not(.adm-table--comfortable) .adm-cell__sub {
  display: inline; margin-left: .5rem;
}
.adm-table:not(.adm-table--comfortable) .adm-cell__sub::before {
  content: "·"; margin-right: .5rem; opacity: .45;
}
.adm-table--comfortable tbody td {
  padding: .5rem .75rem;
  white-space: normal;      /* a long value wraps instead of being clipped */
  overflow: visible;
  max-width: none;
  /* Rows that wrap read top-aligned: a badge floating at the vertical middle
     of a two-line subject looks detached from it. */
  vertical-align: top;
}
/* A chip is one word-group; "Microsoft Teams" wrapping into a two-line box
   makes it as tall as the row. */
.adm-table .tag, .adm-table .badge { white-space: nowrap; }
/* A cell that spends the comfortable row's SECOND line on itself rather than on
   a supporting sub-line: two lines of text, then an ellipsis. For the one value
   in a row that is a sentence - a case subject, a description - where one line
   is not enough to tell two of them apart and unbounded wrapping is what used
   to set the row height from whichever record had the most to say.

   Condensed is deliberately left alone: the td there is already nowrap with an
   ellipsis, and the whole point of the 36px row is that it cannot grow. */
.adm-table--comfortable .adm-cell__clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

.adm-table--comfortable .avatar { --tblr-avatar-size: 2rem; }
/* Condensed shrinks the avatar to fit the 36px line without setting the row
   height from its content. */
.adm-table:not(.adm-table--comfortable) .avatar { --tblr-avatar-size: 1.25rem; }

.adm-table .btn-sm { --tblr-btn-padding-y: .1rem; --tblr-btn-padding-x: .5rem; font-size: .75rem; }

/* ---- KPI strip ----------------------------------------------------------
   The sparkline fills its cell edge to edge and sits BEHIND the figure, so the
   cell reads as one thing rather than a number with a chart bolted under it.
   The card clips it so the strip keeps its rounded corners; nothing in here is
   sticky, so `overflow: hidden` costs nothing (see rule 8). */
.kpi-strip { overflow: hidden; }
.kpi-cell { position: relative; }
/* The body reserves more bottom padding than the sparkline is tall, so the
   quiet secondary line always sits ABOVE the drawn line rather than being
   crossed by it - a graph behind a figure is texture, a graph through a
   sentence is damage. */
.kpi-cell__body { position: relative; z-index: 1; padding-bottom: 3.25rem !important; }
.kpi-spark {
  position: absolute; inset: auto 0 0 0; width: 100%; height: 2.75rem;
  display: block; z-index: 0; pointer-events: none;
}
.kpi-spark__line { fill: none; stroke: var(--tblr-primary); stroke-width: 1.75; opacity: .9; }
.kpi-spark__fill { fill: var(--tblr-primary); opacity: .14; stroke: none; }
/* Bars for an event count. Same surface as the line, so the two styles read as
   one family - what differs is what is being counted, not the decoration. */
.kpi-spark__bar { fill: var(--tblr-primary); opacity: .45; }
/* Direction is carried by the arrow as well as the colour, so the trend is
   still readable without colour vision. */
.kpi-trend {
  display: inline-flex; align-items: center; gap: .15rem;
  font-size: .75rem; font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.adm-controls { background-color: var(--tblr-bg-surface-tertiary); }

/* What is narrowing the list, above it, each removable in one click. A column
   search can be set from a cell (clicking a count drills into what it counts),
   so it has to be visible somewhere other than the head it came from. */
.adm-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .75rem; padding: .1rem .25rem .1rem .5rem;
  background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color);
  border-radius: 20px; color: var(--tblr-body-color); max-width: 22rem;
}
.adm-chip__label { color: var(--tblr-secondary); }
.adm-chip__clear {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.05rem; height: 1.05rem; border-radius: 50%;
  color: var(--tblr-secondary); line-height: 1;
}
.adm-chip__clear:hover { background: var(--tblr-bg-surface-secondary); color: var(--tblr-red); }

/* The head's own row: label, sort control, and the column's search. */
.adm-th { display: inline-flex; align-items: center; gap: .25rem; }
.adm-table thead th .sortable-header { padding-right: 18px !important; }

/* ---- a column's own search ---------------------------------------------
   The control belongs to the thing it narrows, so it opens from the head
   rather than living in a strip that names no column. Nothing is spent until
   it is used; an active one carries a dot. */
.col-filter { position: relative; display: inline-flex; }
.col-filter__toggle {
  background: none; border: 0; padding: 0 .1rem; line-height: 1; cursor: pointer;
  color: var(--tblr-secondary); position: relative; font-size: .8rem;
}
.col-filter__toggle:hover { color: var(--tblr-primary); }
.col-filter__toggle.is-active { color: var(--tblr-primary); }
.col-filter__toggle.is-active::after {
  content: ""; position: absolute; top: -1px; right: -2px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--tblr-primary);
}
.col-filter__pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  display: block; width: 15rem; padding: .6rem;
  background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color);
  border-radius: 6px; box-shadow: 0 8px 24px rgba(4, 32, 69, .14);
  text-transform: none; letter-spacing: 0; font-weight: 400;
  white-space: normal;
}
.col-filter__pop[hidden] { display: none; }
.col-filter__label {
  display: block; font-size: .7rem; color: var(--tblr-secondary); margin-bottom: .25rem;
}
.col-filter__range { display: flex; gap: .35rem; }
.col-filter__foot {
  display: flex; justify-content: space-between; align-items: center; gap: .5rem; margin-top: .5rem;
}
/* The last columns' popovers would open past the panel's right edge. */
.adm-table thead th:nth-last-child(-n+2) .col-filter__pop { left: auto; right: 0; }


/* A nested-record table inside a band bleeds to the band edge rather than
   sitting in a padded inner box. This is the one sanctioned exception to the
   padding rule: a padded box here would be the card-inside-a-card the system
   forbids, and re-padding would misalign the table's columns from the fields
   above it. */
.sheet-flush { margin: 0 -1.5rem; border-top: 1px solid var(--tblr-border-color);
               border-bottom: 1px solid var(--tblr-border-color); }
.sheet-flush > .table-responsive > table { margin-bottom: 0; }
.sheet-flush thead th { background-color: var(--tblr-bg-surface-secondary); }
.sheet-flush thead th:first-child, .sheet-flush tbody td:first-child { padding-left: 1.5rem; }
.sheet-flush thead th:last-child,  .sheet-flush tbody td:last-child  { padding-right: 1.5rem; }
@container sheet (max-width: 820px) {
  .sheet-flush { margin: 0 -1.15rem; }
  .sheet-flush thead th:first-child, .sheet-flush tbody td:first-child { padding-left: 1.15rem; }
  .sheet-flush thead th:last-child,  .sheet-flush tbody td:last-child  { padding-right: 1.15rem; }
}

/* --- a block of reported facts ------------------------------------------- */
/* Observed values - what a device said about itself - rather than fields.
   
   Four tracks: label, value, label, value. So a row carries TWO readings side
   by side, read left to right, and the next row starts the next pair - while
   every label lines up on one of two edges and every value on one of two more.
   That alignment is what makes it scannable; the two pairs per row are what
   stop seven readings becoming seven lines of mostly empty space.
   
   Two failure modes this deliberately avoids: the label above its value (which
   doubles the height and puts nothing in a predictable place), and one pair per
   row (which reads as seven unrelated sentences).
   
   Every fact is listed whether or not there is a value: a missing one renders
   as `-`, because a hidden row makes "not reported" look like "not
   applicable". */
.sheet-facts { display: grid; margin: 0;
               grid-template-columns: minmax(6.5rem, 9rem) minmax(0, 1fr)
                                      minmax(6.5rem, 9rem) minmax(0, 1fr);
               gap: .4rem 1rem; align-items: baseline; }
.sheet-facts dt { font-size: .8125rem; color: var(--tblr-secondary); font-weight: 400; margin: 0; }
.sheet-facts dd { margin: 0; color: var(--tblr-body-color); font-variant-numeric: tabular-nums;
                  min-width: 0; overflow-wrap: anywhere; }
.sheet-facts code { font-size: .8125rem; }
/* A value long by nature (an address, a sign-in name) takes the value columns of a row of its own, so it is read whole
   rather than cut off beside another pair. The label starts the row; everything still lines up on the same edges. */
/* Provenance under a detail page's content: when its values were read, and from where. One quiet line on a hairline;
   it answers "how current is this", never "what is this", so it sits last and at a fraction of the weight. */
.identity-provenance { display: flex; align-items: center; gap: .5rem; padding: .6rem 1.5rem; margin-top: auto;
                       border-top: 1px solid var(--tblr-border-color); font-size: .8125rem; color: var(--tblr-secondary); }
/* The content column is a "sheet" container too, so the line follows the bands' own padding when they narrow. */
.identity-content { container: sheet / inline-size; }
/* The persona in a Teams module's header, right of the platform name: an overlay on the person, seen from every page. */
.identity-rail-persona .badge { max-width: 7.5rem; display: inline-block; }
/* The same provenance line on an admin-style detail shell (Teams application pages): the body grows to the card's
   bottom so the line sits there, and is a "sheet" container so the line follows the bands' padding. */
.detail-content__body:has(> .identity-provenance) { container: sheet / inline-size; flex: 1; display: flex; flex-direction: column; }
/* The identity Policies table: one line per policy, like every other row (admin "The row is one line"). */
.policies-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.policies-table .tag { white-space: nowrap; }
.policies-table td { padding-top: .35rem; padding-bottom: .35rem; }
.policies-table .form-select { height: 2rem; min-height: 0; padding-top: .2rem; padding-bottom: .2rem; font-size: .8125rem; }
.policies-table tr.collapse td, .policies-table tr.collapsing td { white-space: normal; }
/* The Assign licence modal: one group per source, each headed by its brand mark, so a Pulse and an Entra ID
   licence never read as the same kind of thing. */
.assign-licence-group + .assign-licence-group { border-top: 1px solid var(--tblr-border-color); }
.assign-licence-group__head { display: flex; align-items: center; gap: .5rem; padding: .85rem 1.25rem .5rem; font-weight: 600; }
.assign-licence-group table { table-layout: fixed; }
.assign-licence-group td code { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.assign-licence-group th:first-child, .assign-licence-group td:first-child { padding-left: 1.25rem !important; }
.assign-licence-group th:last-child, .assign-licence-group td:last-child { padding-right: 1.25rem !important; }
@container sheet (max-width: 820px) { .identity-provenance { padding-inline: 1.15rem; } }
/* The identity content column sits beside the module rail, so its sheet is under 820px on most screens and the admin
   rule would put every field on its own row. Half and quarter fields are still 170px+ at that width: keep them until
   560px, where the admin rule's single column takes over. */
@container sheet (min-width: 561px) and (max-width: 820px) {
  .identity-content .sheet-grid > .sf-6 { grid-column: span 6; }
  .identity-content .sheet-grid > .sf-3 { grid-column: span 3; }
}
.sheet-facts dt.is-wide { grid-column: 1; }
.sheet-facts dd.is-wide { grid-column: 2 / -1; }

/* One pair per row only when two genuinely will not fit - by container width,
   since the rail and the band's about column have already taken their share. */
@container sheet (max-width: 560px) {
  .sheet-facts { grid-template-columns: minmax(6.5rem, 9rem) minmax(0, 1fr); }
}

/* --- data boxes ---------------------------------------------------------- */
/* A reading as an object rather than a table row: label above, value large
   enough to be read at a glance. Use for a handful of headline values someone
   scans - not for a long list of attributes, where the label/value pair grid
   above is faster to read down.
   
   Boxes fill the row and re-flow by count, so five readings on a wide band
   become three-and-two on a narrow one rather than shrinking. */
.sheet-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
               gap: .5rem; margin: 0; }
.sheet-stat { padding: .6rem .85rem; border-radius: 6px;
              background: var(--tblr-bg-surface-secondary);
              border: 1px solid var(--tblr-border-color-light, rgba(4, 32, 69, .06));
              min-width: 0; }
.sheet-stat__label { font-size: .75rem; color: var(--tblr-secondary); margin-bottom: .15rem;
                     white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sheet-stat__value { font-size: 1.0625rem; font-weight: 600; color: var(--tblr-body-color);
                     line-height: 1.25; font-variant-numeric: tabular-nums;
                     overflow-wrap: anywhere; }
.sheet-stat__value .unit { font-size: .8125rem; font-weight: 400; color: var(--tblr-secondary); }
/* A consequence of the value, under it: what being connected or missing means
   for the run. Set on its own quiet line rather than trailing the value, where
   a sentence next to a badge outweighs the fact it is explaining. */
.sheet-stat__note { font-size: .75rem; color: var(--tblr-secondary); line-height: 1.35;
                    margin-top: .2rem; }
/* A machine value - a serial, a MAC - is smaller because it is copied, not
   compared. */
.sheet-stat__value.is-machine { font-size: .875rem; font-family: var(--tblr-font-monospace); }

/* The age of the reading, above the boxes. Quiet when fresh; the one thing
   that turns colour is a reading old enough that the values below may no longer
   be true - that is state, which is the only thing colour means here. */
.sheet-reading { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
                 margin-bottom: .6rem; font-size: .8125rem; color: var(--tblr-secondary); }
.sheet-reading__age { font-weight: 600; color: var(--tblr-body-color); }
.sheet-reading__age.is-stale { color: var(--tblr-orange); }
.sheet-reading__note { flex-basis: 100%; margin-top: -.15rem; color: var(--tblr-orange); }

/* An empty state inside a band: states the fact, points at the action that
   fills it, and never grows an action of its own. */
.sheet-empty { padding: 1rem 1.15rem; border: 1px dashed var(--tblr-border-color);
               border-radius: 4px; color: var(--tblr-secondary); font-size: .875rem;
               background: var(--tblr-bg-surface-secondary); }

/* --- a panel of machine-readable text ------------------------------------ */
/* Same idea as the table panel: a header bar carrying the controls, then the
   content inside one surface. The pills used to float loose above a dark slab,
   which read as two unrelated objects.

   Deliberately NOT .sheet-flush. A table goes flush because re-padding it
   misaligns its columns; a code panel has no columns to misalign, and bleeding
   it 1.5rem past the band left its edge 24px left of every other band's
   content. It sits on the content edge like the data boxes above it. */
.code-panel { border: 1px solid var(--tblr-border-color); border-radius: 6px;
              overflow: hidden; }
.code-panel__bar { display: flex; align-items: center; gap: .75rem;
                   padding: .5rem 1rem;
                   background: var(--tblr-bg-surface-secondary);
                   border-bottom: 1px solid var(--tblr-border-color); }

/* A segmented control, not tabs: these are two shapes of the same content, so
   the switch belongs beside the content it changes rather than above it.

   Neutral, not primary blue. INI vs JSON is taxonomy - which shape you are
   looking at - and semantic colour in this system means state only. A solid
   blue chip here claims a significance the choice does not have. */
.code-switch { display: inline-flex; gap: 2px; padding: 2px; border-radius: 6px;
               background: var(--tblr-border-color-light, rgba(4, 32, 69, .06)); }
.code-switch button { border: 0; background: transparent; border-radius: 4px;
                      padding: .15rem .7rem; font-size: .8125rem; font-weight: 500;
                      color: var(--tblr-secondary); line-height: 1.6; }
.code-switch button:hover { color: var(--tblr-body-color); }
.code-switch button.active { background: var(--tblr-bg-surface);
                             color: var(--tblr-body-color); font-weight: 600;
                             box-shadow: 0 1px 2px rgba(0, 0, 0, .06); }

/* Bounded height: the file runs to thousands of lines and the band should not.
   It scrolls in its own box, so the page never grows to fit a machine's output.
   Tabler's dark `pre` is kept - a file as the machine stores it is the one place
   a terminal surface belongs. */
.sheet-code { margin: 0; border-radius: 0; max-height: 32rem; overflow: auto; }

/* The operation log inside a console's code panel: the same terminal surface as
   a machine-stored file, bounded so a long run does not grow the page. Its
   height is set here rather than inline because the fullscreen toggle overrides
   it, and an override needs something to override. */
.console-log {
  height: 25rem; overflow-y: auto; padding: 0.75rem 1rem;
  background: var(--tblr-dark); color: #fff;
  font-family: var(--tblr-font-monospace); font-size: 0.8125rem; line-height: 1.5;
}

/* ============================================================================
   ADMIN DETAIL SHELL  (DetailShellComponent)

   The detail page: one card, a rail, a content column. Replaces the
   hand-rolled `col-md-3 border-end` + list-group that thirteen sections each
   grew their own copy of.

   The rail is a COLUMN OF THE CARD, not a second surface, so "one surface per
   page" still holds. See .claude/rules/admin-design.md, Part 3.
   ========================================================================= */

/* The card is the query container: the rail collapses when the CARD is narrow,
   not when the window is. A viewport rule cannot see that something else has
   taken the space - the mistake that once produced narrower fields on a wider
   screen. */
/* The container is the FRAME, not the card: an element cannot respond to its
   own container query, so with container-type on the grid itself the rail's
   border collapsed at narrow widths while the columns never did. */
.detail-shell-frame { container: detail / inline-size; }
.detail-shell { display: grid; grid-template-columns: 17rem minmax(0, 1fr); }

.detail-rail { border-right: 1px solid var(--tblr-border-color); padding: 1rem 0; min-width: 0; }
.detail-content { display: flex; flex-direction: column; min-width: 0; }
.detail-content__body { flex: 1 1 auto; min-width: 0; }

/* --- identity block: what am I looking at, before a tab is chosen --------- */
.detail-ident { padding: .35rem 1.15rem 1rem; border-bottom: 1px solid var(--tblr-border-color);
                margin-bottom: .75rem; }
.detail-ident__head { display: flex; align-items: center; gap: .75rem; min-width: 0; }
.detail-ident__id { min-width: 0; }
.detail-ident__avatar { width: 2.75rem; height: 2.75rem; min-width: 2.75rem; border-radius: .5rem;
                        background: var(--tblr-primary-lt); color: var(--tblr-primary); font-weight: 700;
                        overflow: hidden; }
.detail-ident__avatar img { width: 100%; height: 100%; object-fit: contain; }
.detail-ident__name { font-weight: 600; color: var(--tblr-body-color); line-height: 1.3;
                      word-break: break-word; display: -webkit-box; -webkit-line-clamp: 2;
                      -webkit-box-orient: vertical; overflow: hidden; }
.detail-ident__parent { font-size: .8125rem; color: var(--tblr-secondary); margin-top: .1rem;
                        word-break: break-word; }
.detail-ident__meta { font-size: .8rem; color: var(--tblr-secondary); white-space: nowrap;
                      overflow: hidden; text-overflow: ellipsis; }
.detail-ident__chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .6rem; align-items: center; }
.detail-ident__facts { display: grid; grid-template-columns: auto 1fr; gap: .2rem .75rem; font-size: .8rem;
                       margin: .75rem 0 0; padding-top: .6rem; border-top: 1px dashed var(--tblr-border-color); }
.detail-ident__facts dt { color: var(--tblr-secondary); font-weight: 400; margin: 0; }
.detail-ident__facts dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

/* --- grouped navigation -------------------------------------------------- */
.detail-rail__group { font-size: .6875rem; letter-spacing: .06em; text-transform: uppercase;
                      color: var(--tblr-secondary); font-weight: 600;
                      margin: 1.1rem 0 .35rem; padding: 0 1.25rem; }
.detail-rail__group:first-child { margin-top: 0; }

/* The current item is a soft pill inset in the rail, not a bar on its edge (artbook, profile API & MCP,
   2026-09-26): it reads as "you are here" without competing with the page's own borders. */
.detail-rail__item { display: flex; align-items: center; gap: .5rem; margin: 1px .75rem;
                     padding: .45rem .5rem; border-radius: 6px; color: var(--tblr-body-color);
                     text-decoration: none; }
.detail-rail__item:hover { background: var(--tblr-bg-surface-secondary); color: var(--tblr-body-color); }
.detail-rail__item.is-current { background: rgba(var(--tblr-primary-rgb), .08);
                                color: var(--tblr-primary); font-weight: 600; }
.detail-rail__item.is-current .detail-rail__count { color: var(--tblr-primary); }
.detail-rail__item i { font-size: 1rem; line-height: 1; flex: none; }
.detail-rail__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.detail-rail__count { margin-left: auto; flex: none; }

/* --- the record line ----------------------------------------------------- */
/* Identifier and dates, under the card rather than inside it. It is neither
   content nor part of any tab - it is the page's own footnote about which row
   you are looking at, so it sits outside the surface and stays quiet. */

.detail-record { margin: .6rem .25rem 0; font-size: .75rem; color: var(--tblr-secondary); }

/* A collapse toggle that says what it will do next, not what it did.
   Pair <span class="when-collapsed"> / <span class="when-expanded"> inside any
   [data-bs-toggle="collapse"] button; Bootstrap keeps aria-expanded true. */
.collapse-toggle[aria-expanded="false"] .when-expanded { display: none; }
.collapse-toggle[aria-expanded="true"] .when-collapsed { display: none; }

/* ---- Support case page (Direction B) ------------------------------------
   A strip that identifies the case, a timeline that records it, a rail of
   context. The timeline is typed: replies get a card and a face, everything
   else - files arriving, status and priority changes - gets one quiet line on
   a small node, so a skim of the left edge tells the shape of the case. */
.case-grid {
  display: grid;
  /* Half and half, full window: what IS the case, and what happened to it. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 1199.98px) {
  .case-grid { grid-template-columns: 1fr; }
}

.case-tl { position: relative; padding-left: 2.4rem; }
.case-tl::before {
  content: ""; position: absolute; left: 14px; top: 10px; bottom: 10px;
  width: 1px; background: var(--tblr-border-color);
}
.case-tl__item { position: relative; padding-bottom: 1.1rem; }
.case-tl__item:last-child { padding-bottom: .25rem; }

.case-tl__node {
  position: absolute; left: -2.4rem; top: 0;
  width: 28px; height: 28px; border-radius: 50%;
  background-size: cover; background-position: center;
  background-color: var(--tblr-bg-surface-secondary);
  border: 1px solid var(--tblr-border-color);
  /* The halo is what lifts the node off the spine. The PAGE background, not
     the card surface: the timeline floats on the page. */
  box-shadow: 0 0 0 3px var(--tblr-body-bg);
}
.case-tl__item--event .case-tl__node {
  width: 11px; height: 11px; left: calc(-2.4rem + 9px); top: 5px;
  background-color: var(--tblr-secondary); border: 0;
}
/* Colour is state: only a change that raised urgency earns it. */
.case-tl__item--warn .case-tl__node { background-color: var(--tblr-warning); }

.case-tl__meta { font-size: .78rem; color: var(--tblr-secondary); display: flex; gap: .45rem; align-items: baseline; flex-wrap: wrap; }
.case-tl__who { font-weight: 600; color: var(--tblr-body-color); font-size: .85rem; }
.case-tl__side {
  font-size: .68rem; border: 1px solid var(--tblr-border-color); border-radius: 3px;
  padding: 0 .3rem; color: var(--tblr-secondary);
}
.case-tl__item--agent .case-tl__side {
  border-color: transparent; background: var(--tblr-primary-lt); color: var(--tblr-primary);
}

.case-tl__card {
  margin-top: .4rem; border: 1px solid var(--tblr-border-color); border-radius: 6px;
  background: var(--tblr-bg-surface); padding: .65rem .8rem;
}
/* Support's replies are told apart by surface, not by flipping sides: a
   record is one column, not a two-sided chat. The tint mixes from the
   whitelabel primary, so a partner's own colour carries through. */
.case-tl__item--agent .case-tl__card {
  background: color-mix(in srgb, var(--tblr-primary) 7%, var(--tblr-bg-surface));
  border-color: color-mix(in srgb, var(--tblr-primary) 22%, var(--tblr-border-color));
}
.case-tl__event { font-size: .82rem; color: var(--tblr-secondary); }
.case-tl__event strong { color: var(--tblr-body-color); }


/* The timeline filter wears the branding colour: the chosen view is filled
   with the primary, the others are outlined in a darker mix of it, and the
   shared edges double as dividers. */
.case-filter .btn {
  color: var(--tblr-primary);
  background: transparent;
  border-color: color-mix(in srgb, var(--tblr-primary) 60%, var(--tblr-border-color));
}
.case-filter .btn:hover {
  background: color-mix(in srgb, var(--tblr-primary) 8%, transparent);
  border-color: color-mix(in srgb, var(--tblr-primary) 60%, var(--tblr-border-color));
  color: var(--tblr-primary);
}
.case-filter .btn.active {
  background: var(--tblr-primary);
  border-color: var(--tblr-primary);
  color: #fff;
}
.detail-record code { font-size: .75rem; }

/* --- action bar: content column only ------------------------------------- */
/* It acts on what is shown, not on the whole record - so it does not span the
   rail. Sticky for the same reason the sheet's is: not hunting for Save. */
.detail-actions { position: sticky; bottom: 0; z-index: 2;
                  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
                  padding: .85rem 1.5rem;
                  border-top: 1px solid var(--tblr-border-color);
                  background: var(--tblr-bg-surface-secondary); }

/* A sheet inside the content column gives up its own edges: the detail card is
   already the surface, and a bordered sheet inside it is the card-in-a-card the
   system forbids. Descendant, not child - FormSheetComponent wraps the sheet in
   a layout div, so the child selector this started as never matched and the
   double border shipped invisibly. */
.detail-content__body .sheet { border: 0; border-radius: 0; }
.detail-content__body .sheet-layout { margin: 0; }

/* A table panel rendered as the tab's whole content is the content column's
   surface - it never becomes a card inside the card. */
.detail-content__body > .card { border: 0; border-radius: 0; box-shadow: none; margin-bottom: 0; }

/* --- consoles: cards that are already inside the card -------------------- */
/* Three tabs are operating panels rather than forms or lists - the service
   AudioCodes tab, its provisioning runner, and the trunk device tab. Each is a
   10-18-target Stimulus controller driving every row inside it, with ghost
   tables whose colgroups must stay byte-identical, so their markup is not
   rewritten (see .claude/rules/admin-design.md, Part 5).

   What that markup does have is `.card` chrome from before there was a card
   around it, which is the one thing the system bans hardest. Rather than edit
   1,400 lines of fragile console, the chrome is neutralised where it sits: the
   panels become plain blocks separated by a hairline, which is what a band
   looks like. */
.detail-content__body .card { border: 0; box-shadow: none; border-radius: 0;
                              background: transparent; }
.detail-content__body .card + .card { border-top: 1px solid var(--tblr-border-color);
                                      margin-top: .25rem; padding-top: .25rem; }
.detail-content__body .card > .card-header { background: transparent; border-bottom: 0;
                                             padding-left: 0; padding-right: 0;
                                             min-height: auto; }
.detail-content__body .card > .card-body { padding-left: 0; padding-right: 0; }
.detail-content__body .card > .card-footer { background: transparent; padding-left: 0;
                                             padding-right: 0; }
/* The log pane and any other deliberately dark surface keeps its own ground -
   it is output, not chrome. */
.detail-content__body .card > .card-body.bg-dark { padding: 1rem; border-radius: 4px; }
/* A flush table inside a console still needs its edges to reach the column. */
.detail-content__body .card > .card-body.card-no-padding { padding: 0; }

/* --- narrow card: rail above the content --------------------------------- */
@container detail (max-width: 900px) {
  .detail-shell { grid-template-columns: 1fr; }
  .detail-rail { border-right: 0; border-bottom: 1px solid var(--tblr-border-color);
                 padding-bottom: .5rem; }
  .detail-rail__item { margin: 0; }
}

/* Migration browser: "Hide accounts without licences".
   The class lands on the tree root, so rows added by a later lazy level load are
   hidden too — a one-off JS sweep would only catch the rows present when it ran.
   A blank attribute (source server that does not report the count) matches
   nothing, so nothing is hidden rather than everything. */
.migrate-hide-empty .migrate-node[data-subtree-licenses="0"] {
  display: none;
}

/* ---------------------------------------------------------------------------
   Admin > Services: identity change timeline and sync-run block graph.
   Both are read-only inspection surfaces on the detail shell.
   --------------------------------------------------------------------------- */

/* One entry per recorded change, with its field diff table beneath. */
.adm-timeline__entry {
  padding: .5rem 0;
  border-bottom: 1px solid var(--tblr-border-color);
}
.adm-timeline__entry:last-child { border-bottom: 0; }
.adm-timeline__head { display: flex; align-items: center; flex-wrap: wrap; }
.adm-timeline__diff { margin-top: .25rem; }
.adm-timeline__diff td { padding: .15rem .5rem; border-top: 0; font-size: .8125rem; }
.adm-timeline__diff tr td:first-child { padding-left: 0; }

/* GitHub-style run grid: one block per sync run, oldest first. Colour is state
   (rule 5) - it is the only thing these blocks encode. */
.run-blocks { display: flex; flex-wrap: wrap; gap: 3px; }
.run-block {
  width: 11px; height: 11px; border-radius: 2px;
  background-color: var(--tblr-border-color);
  display: block; text-decoration: none;
}
.run-block--completed { background-color: var(--tblr-green); }
.run-block--failed    { background-color: var(--tblr-red); }
/* The workflow finished, but something inside it did not - a Teams policy sync
   that timed out, say. Neither green nor red is true of that run. */
.run-block--partial   { background-color: var(--tblr-orange); }
.run-block--running   { background-color: var(--tblr-blue); }
.run-block--cancelled { background-color: var(--tblr-secondary); opacity: .45; }
a.run-block:hover { outline: 2px solid var(--tblr-border-color-active); outline-offset: 1px; }
.run-blocks__legend { display: flex; align-items: center; gap: 1rem; font-size: .75rem; }
.run-blocks__key { display: inline-flex; align-items: center; gap: .35rem; }


/* ── The mirrored spine ──────────────────────────────────────────────────────
   A block for fields that exist on BOTH legs of a call: ingress left, the
   field name down the middle, egress right. It lives inside a band alongside
   .sheet-stats, which keeps the sections exactly as they were - the pairing
   changes how a field is read, not which section it belongs to.

   Why a spine rather than two lists: a leg-to-leg difference is the question
   the call record exists to answer, and two values in two separate lists never
   get compared. Across one label they do - production had a call carrying
   packet loss 10 on ingress against 58 on egress, which was invisible until
   the two sat either side of the same word.

   Re-flow is by CONTAINER, per admin-design.md rule 10: the sheet already
   declares `container: sheet / inline-size`, so a narrow card collapses each
   row to label-over-pair instead of squeezing three columns. */
.sheet-spine {
  display: grid;
  grid-template-columns: 1fr minmax(7rem, 11rem) 1fr;
  align-items: baseline;
  column-gap: 0;
}
.sheet-spine__head { display: contents; }
.sheet-spine__head > * {
  padding-bottom: .35rem;
  margin-bottom: .35rem;
  border-bottom: 1px solid var(--tblr-border-color);
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.sheet-spine__head .is-ingress { text-align: right; padding-right: .75rem; }
.sheet-spine__head .is-egress  { text-align: left;  padding-left: .75rem; }
/* Ingress and egress take a hue in the HEADERS ONLY. Colour is state (rule 5);
   a side is not a state, so the values below stay neutral and red on a figure
   keeps meaning "threshold", not "this leg". */
.sheet-spine__head .is-ingress { color: var(--tblr-indigo); }
.sheet-spine__head .is-egress  { color: var(--tblr-teal); }

.sheet-spine__row { display: contents; }
.sheet-spine__row > * { padding: .3rem 0; min-width: 0; }
.sheet-spine__row:hover > * { background: var(--tblr-bg-surface-tertiary); }

.sheet-spine__in,
.sheet-spine__out {
  font-size: .875rem;
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
.sheet-spine__in > div,
.sheet-spine__out > div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* What the value WAS, under the value that was used. Quiet, because the number
   actually carried is the one being read. */
.sheet-spine__note {
  font-size: .6875rem;
  color: var(--tblr-secondary);
  font-family: var(--tblr-font-sans-serif);
}
.sheet-spine__in  { text-align: right; padding-right: .75rem; }
.sheet-spine__out { text-align: left;  padding-left: .75rem; }
.sheet-spine__key {
  text-align: center;
  font-size: .75rem;
  color: var(--tblr-secondary);
}
/* Computed, not decorative: it appears only where the two legs actually
   disagree, so it can be trusted. Never colour alone - the glyph carries it. */
.sheet-spine__mark { color: var(--tblr-orange); font-weight: 700; margin-left: .15rem; }
.sheet-spine__row.is-differs .sheet-spine__in,
.sheet-spine__row.is-differs .sheet-spine__out { font-weight: 600; }

@container sheet (max-width: 640px) {
  .sheet-spine { grid-template-columns: 1fr 1fr; }
  .sheet-spine__head > * { margin-bottom: .2rem; }
  .sheet-spine__head .is-ingress { text-align: left; padding-right: 0; }
  .sheet-spine__row > * { padding-top: 0; }
  /* The label leads its own pair rather than sitting between two squeezed
     columns - the same content re-flowing, not a second layout. */
  .sheet-spine__key {
    grid-column: 1 / -1;
    text-align: left;
    padding-top: .5rem !important;
    border-top: 1px solid var(--tblr-border-color);
  }
  .sheet-spine__in { text-align: left; padding-right: .5rem; }
}


/* ── Raw field map ───────────────────────────────────────────────────────────
   The SDR line is positional: 88 pipe-separated values, none of them labelled.
   Listing the parsed name beside each value is what turns "copyable" into
   "readable", and it is the only place the ~30 fields the page does not
   promote to a column can be seen at all.

   Bounded and scrolling like the code panel it sits in - 57 rows would
   otherwise push the envelope below the fold on every call. */
.raw-fields {
  display: grid;
  grid-template-columns: minmax(11rem, auto) 1fr;
  gap: 0 1rem;
  max-height: 20rem;
  overflow: auto;
  padding: .5rem .75rem .75rem;
  font-family: var(--tblr-font-monospace);
  font-size: .75rem;
  line-height: 1.7;
}
.raw-fields__key { color: var(--tblr-secondary); white-space: nowrap; }
.raw-fields__val { color: var(--tblr-body-color); word-break: break-all; }
.raw-fields__val.is-empty { color: var(--tblr-secondary); opacity: .5; }
.code-panel__meta { margin-left: auto; font-size: .6875rem; color: var(--tblr-secondary); }


/* ── Call timeline ───────────────────────────────────────────────────────────
   Start ──ring── Connect ──talk── End, drawn to scale. The RATIO is what the
   block adds: 2 seconds of ringing before a 4-minute conversation is a
   different call from the reverse, and the two duration figures beneath say
   nothing about that on their own.

   Every label is anchored to its own point. Laying the feet out separately with
   space-between put CONNECT in the middle of the track while its dot sat 170px
   to the left - the timestamps labelled the wrong instants, which is worse than
   not drawing them.

   Segments grow by their millisecond count with a floor, so a sub-second ring
   stays visible instead of collapsing. Neutral throughout: a duration is not a
   state, so it takes no semantic colour (rule 5), and the ingress/egress hues
   are deliberately not reused - they mean a leg, not a span. */
.call-timeline { max-width: 54rem; }
/* The whole span, bracketed over the two it is made of - |‾‾‾‾‾‾| with the
   figure centred beneath. Bracketed rather than printed in a corner because
   the shape says "all of this", which a floating number does not. */
.call-timeline__total {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.call-timeline__total-bar {
  width: 100%;
  height: .45rem;
  border: 2px solid var(--tblr-border-color-active);
  border-bottom: 0;             /* ticks point down, at the track it measures */
  border-top-left-radius: 2px;
  border-top-right-radius: 2px;
}
.call-timeline__total-value {
  margin-top: .3rem;
  font-size: .9375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.call-timeline__total-label {
  font-size: .6875rem;
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tblr-secondary);
  margin-right: .25rem;
}

.call-timeline__track {
  display: flex;
  align-items: center;
  padding: 1.6rem 0 3rem;   /* room for the labels above and the feet below */
}
.call-timeline__point { position: relative; flex: 0 0 auto; line-height: 0; }
.call-timeline__dot {
  display: block;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--tblr-body-bg);
  border: 3px solid var(--tblr-secondary);
}
.call-timeline__foot {
  position: absolute;
  top: 1rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  white-space: nowrap;
}
/* The end points align to the track's edges so they cannot overhang it. */
.call-timeline__point.is-first .call-timeline__foot { left: 0; transform: none; }
.call-timeline__point.is-last .call-timeline__foot { left: auto; right: 0; transform: none; text-align: right; }

.call-timeline__seg {
  flex: 1 1 auto;
  /* The floor is set by the LABELS, not by taste: each timestamp is ~52px and
     is centred on its dot, so two dots closer than ~6rem print their times on
     top of each other - a 2.3s ring inside a 4-minute call did exactly that
     ("10:37:3510:37:37"). A short segment is therefore drawn at the floor
     rather than to scale; the figures beneath remain exact. */
  min-width: 6.5rem;
  position: relative;
  /* 4px and a colour that actually reads: at 2px on --tblr-border-color the
     segments were invisible next to the dots, so the drawing showed three
     points and no spans - which is the opposite of its job. */
  height: 4px;
  border-radius: 2px;
  background: var(--tblr-secondary);
  display: flex;
  justify-content: center;
}
/* Ring is the lighter span, talk the solid one - weight, not hue, because a
   duration is not a state (rule 5). */
.call-timeline__seg:first-of-type { background: var(--tblr-border-color-active); }
.call-timeline__seg-label {
  position: absolute;
  bottom: .7rem;
  white-space: nowrap;
  font-size: .75rem;
  color: var(--tblr-secondary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.call-timeline__foot-label {
  font-size: .6875rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tblr-secondary);
}
.call-timeline__foot-time { font-size: .9375rem; font-variant-numeric: tabular-nums; }
.call-timeline__note { margin: .25rem 0 0; font-size: .75rem; color: var(--tblr-secondary); }

@container sheet (max-width: 520px) {
  .call-timeline__seg-label { font-size: .625rem; }
  .call-timeline__seg { min-width: 2.5rem; }
}


/* ── Call detail: compact boxes, linked boxes, continuous spine rule ─────────
   --compact uses auto-FILL rather than auto-fit: with auto-fit a lone box
   stretches across the whole band, which reads as a banner rather than as one
   fact among several. */
.sheet-stats--compact { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }

/* A box that names something with an admin page of its own IS the way to it.
   The arrow says so; without it a clickable box is a guess. */
a.sheet-stat { text-decoration: none; color: inherit; display: block; }
a.sheet-stat:hover { border-color: var(--tblr-primary); background: var(--tblr-bg-surface-tertiary); }
a.sheet-stat:focus-visible { outline: 2px solid var(--tblr-primary); outline-offset: 2px; }
.sheet-stat__link { font-size: .75rem; margin-left: .25rem; color: var(--tblr-secondary); vertical-align: baseline; }
a.sheet-stat:hover .sheet-stat__link { color: var(--tblr-primary); }
.sheet-spine__link { color: inherit; text-decoration: none; }
.sheet-spine__link:hover { color: var(--tblr-primary); text-decoration: underline; }

/* The head's rule was breaking in the middle: the centre cell is empty, so with
   baseline alignment it had no baseline to sit on and its border sat higher
   than its neighbours'. Aligning the row to its end and giving every cell the
   same minimum height makes one continuous hairline. */
.sheet-spine__head > * { align-self: end; min-height: 1.1rem; }

/* ---- Pulse table loader ---------------------------------------------------
   A 3px brand-gradient sweep (Live Orange -> Cyan Signal, the Pulse bar) shown
   while a DataTableComponent frame is fetching - filter change, sort, page or
   column search. Turbo sets [busy] on the frame for exactly that window, so
   this is CSS-only. The strip OVERLAYS the panel's top edge rather than
   sitting in flow - reserved height read as a band of card background
   splitting the title bar from the panel's border. The transition delay
   keeps an instant response from flashing the bar. */
turbo-frame:has(> .dt-loader) {
  display: block;
  position: relative;
}
.dt-loader {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 5;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease 0.15s;
}
turbo-frame[busy] .dt-loader { opacity: 1; }
.dt-loader::before {
  content: "";
  display: block;
  height: 100%;
  width: 40%;
  border-radius: 2px;
  background: linear-gradient(90deg, #ff5f00, #11b5e4);
  animation: dt-loader-sweep 1.1s ease-in-out infinite;
}
@keyframes dt-loader-sweep {
  from { transform: translateX(-110%); }
  to   { transform: translateX(360%); }
}

/* Full-page visits (a Narrowed-by bar chip clears via _top) show Turbo's own
   top progress bar - same brand gradient, so both loaders read as one system. */
.turbo-progress-bar {
  height: 4px;
  background: linear-gradient(90deg, #ff5f00, #11b5e4);
}

/* A frame that already shows content and is loading again (a sort, a filter, the next page) dims where the click
   was, since Turbo's top bar only runs for whole-page visits. A first lazy load keeps its own loader. The delay
   keeps fast reloads from flickering. */
turbo-frame[busy][complete] { opacity: .55; transition: opacity .15s ease .15s; pointer-events: none; }

/* Teams drift modal: the choice is a whole column, so the selection reads as a
   vertical band down it rather than a checked box somewhere off to the side.
   Cells are clickable, hence the cursor. */
.drift-table .drift-col {
  cursor: pointer;
  transition: background-color 0.12s ease-in-out;
}

/* Each side is tinted in its own colour: Microsoft Teams in the Teams brand
   violet-blue (#6264A7), local in neutral grey. Semantic colour means state
   everywhere else in the product, so a column tint that meant "selected" in
   the palette's primary would read as a status - this is identity, not
   health. */
.drift-table .drift-col-selected[data-side="teams"] {
  background-color: rgba(98, 100, 167, 0.14);
  box-shadow: inset 2px 0 0 #6264A7, inset -2px 0 0 #6264A7;
}

.drift-table .drift-col-selected[data-side="local"] {
  background-color: var(--tblr-bg-surface-secondary);
  box-shadow: inset 2px 0 0 var(--tblr-border-color-active), inset -2px 0 0 var(--tblr-border-color-active);
}

/* The band has to close at both ends or it reads as an unfinished column. */
.drift-table thead .drift-col-selected {
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
}

.drift-table tfoot .drift-col-selected {
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 4px;
}

/* The armed action wears its column's colour, so the button and the band it
   sits under read as one choice. Teams brand violet-blue. */
.btn-teams {
  background-color: #6264A7;
  border-color: #6264A7;
  color: #fff;
}

.btn-teams:hover,
.btn-teams:focus,
.btn-teams:active {
  background-color: #4f5199;
  border-color: #4f5199;
  color: #fff;
}

/* Call-direction chips (/admin/telephony/call-records, /app/reporting): the
   Pulse Blue brand ink #001021 instead of pure black. `badge-ink` is the filled
   "out" chip; `badge-ink-outline` is the outlined "in" chip. Self-contained so
   neither depends on Tabler's bg-black / badge-outline. "local" stays blue-outline. */
.badge.badge-ink {
  background-color: #001021;
  border-color: #001021;
  color: #fff;
}
.badge.badge-ink-outline {
  background-color: transparent;
  color: #001021;
  border: var(--tblr-border-width) var(--tblr-border-style) #001021;
}
/* Ink on a dark surface is invisible: the outline inverts to white. */
[data-bs-theme="dark"] .badge.badge-ink-outline {
  color: #fff;
  border-color: #fff;
}

/* /app/v2 dashboard (variant homepage under test).
   Stat strip: identical light boxes - hairline border, semi-transparent
   surface tint (lighter than a card), one tinted icon avatar each. */
.dash-stat-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.dash-stat {
  flex: 1 1 0;
  min-width: 160px;
  /* Text left, the radial gauge right. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.85rem;
  border: 1px solid var(--tblr-border-color-translucent);
  border-radius: var(--tblr-border-radius);
  background: color-mix(in srgb, var(--tblr-bg-surface-secondary) 45%, transparent);
  color: inherit;
  text-decoration: none;
}
a.dash-stat:hover {
  border-color: var(--tblr-primary);
  color: inherit;
}
.dash-stat-label {
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--tblr-secondary);
}
.dash-stat-value {
  font-size: 1.12rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--tblr-body-color);
  line-height: 1.25;
}
.dash-stat-value small {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--tblr-secondary);
}
.dash-stat-delta {
  font-size: 0.78rem;
  font-weight: 600;
  margin-left: 0.25rem;
  white-space: nowrap;
}
.dash-stat-text {
  min-width: 0; /* let the value line truncate instead of pushing the ring out */
}
.dash-radial {
  flex: 0 0 auto;
}
/* Brand marks inline in a stat value line ("56 / 41 on [Teams]") - sized to
   the small text beside them, never the avatar grid's 24px. */
/* Layered stat tile: the sparkline is the card's BACKGROUND (bottom-aligned,
   behind the text), the radial floats right-centre, the content rides above.
   A graph in its own strip under the body was a second row the tile never
   needed - texture belongs behind. */
.dash-tile {
  position: relative;
  overflow: hidden;
}
.dash-tile-content {
  position: relative;
  z-index: 1;
}
.dash-tile-spark {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: flex-end;
  opacity: 0.55;
  pointer-events: none;
}
.dash-tile-spark > div {
  width: 100%;
}
.dash-tile-radial {
  position: absolute;
  top: 50%;
  right: 0.85rem;
  transform: translateY(-50%);
  z-index: 1;
}

/* Sync-run outcome grid on the Services tile: contribution-graph squares,
   one per run, wrapping into rows. Colors are STATUS (rule: colour is state). */
.dash-run-grid {
  /* Two fixed rows; each new run adds one dot HORIZONTALLY (column flow),
     so the strip grows left-to-right like a timeline. */
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(2, 8px);
  gap: 2px;
  justify-content: start;
  overflow: hidden;
}
.dash-run-cell {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  display: inline-block;
  background: var(--tblr-border-color);
}
.dash-run-cell--completed { background: var(--tblr-green); }
.dash-run-cell--failed { background: var(--tblr-red); }
.dash-run-cell--running { background: var(--tblr-blue); }
.dash-run-cell--completed-with-errors { background: var(--tblr-yellow); }

/* The drift row's leading status light: a thumb-sized in-sync bar where a
   dot used to be - the dot said good/bad, the bar says how much. */
.dash-mini-bar {
  width: 2.6rem;
}

.dash-stat-mini-avatar {
  width: 1rem;
  height: 1rem;
  display: inline-block;
  vertical-align: text-bottom;
  border-radius: 3px;
  background-size: cover;
  font-size: 0.55rem;
  line-height: 1rem;
}
/* The Sync runs data box draws its blocks on ONE line filling the box: each
   block flexes to an equal share of the width, so the sequence always spans
   edge to edge and squeezes rather than wraps or hides. Scoped to the
   sequence container so the legend's swatches keep their fixed size. */
.dash-run-line .run-blocks {
  margin-bottom: 0 !important;
  flex-wrap: nowrap;
}
.dash-run-line .run-blocks .run-block {
  flex: 1 1 0;
  min-width: 4px;
}

/* Platform Services box: one brand avatar per service, its status as the
   avatar's badge dot. Height matches the sibling boxes' value line. */
.dash-stat-avatars {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 1.4rem;
  margin-top: 0.15rem;
}

/* Drill-down panels are unboxed: no card wrapper. The hero is a transparent
   row (avatar / name / description, status + configuration on the right);
   under it condensed data boxes (admin-design "data boxes": one fact each,
   quiet label, the value is the thing you came for), then content blocks on
   the same light tint as the stat strip. */
.dash-panel-hero {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  margin-bottom: 1rem;
}
.dash-panel-hero-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  flex: none;
  flex-wrap: wrap;
}
.dash-data-boxes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1rem;
}
.dash-data-box {
  min-width: 118px;
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--tblr-border-color-translucent);
  border-radius: var(--tblr-border-radius);
  background: color-mix(in srgb, var(--tblr-bg-surface-secondary) 45%, transparent);
}
.dash-data-box .dash-stat-label {
  font-size: 0.66rem;
}
.dash-data-box-value {
  font-size: 0.98rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dash-data-box-value small {
  font-size: 0.74rem;
  font-weight: 500;
  color: var(--tblr-secondary);
}
/* Content sections inside panels are unboxed: a quiet uppercase title over a
   flush table, separated by whitespace - no border, no tint. Every list row
   follows one grammar: [when] [badge] [text] [trailing], so the three glance
   lists and the drill-down panels read as one design. */
.dash-section-title {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--tblr-secondary);
  margin-bottom: 0.35rem;
}
.dash-list td:first-child {
  width: 1%;
  white-space: nowrap;
  color: var(--tblr-secondary);
}

/* Glance / panel list boxes: a subtle light-blue border frames each list so
   it reads as a designed element rather than a table splashed on the page.
   Header carries the title and a right-aligned "View all". Rows stay
   single-line column layouts; state and change verbs are quiet -lt label
   badges; the trailing chevron opens the item's detail. */
.dash-box {
  border: 1px solid color-mix(in srgb, var(--tblr-primary) 25%, transparent);
  border-radius: var(--tblr-border-radius);
  background: transparent;
  padding: 0.65rem 0.85rem;
}
.dash-box-header {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}
.dash-box-header .dash-section-title {
  margin-bottom: 0;
}
.dash-box-link {
  font-size: 0.78rem;
  white-space: nowrap;
}
.dash-box-header .dash-box-link {
  margin-left: auto;
}
.dash-list .badge {
  display: inline-flex;
  justify-content: center;
  min-width: 46px;
}
/* The last row's rule would double the box's own bottom edge. */
.dash-list tbody tr:last-child td {
  border-bottom-width: 0;
}
/* ONE fixed row height for every list. Padding-based sizing let each row take
   the height of whatever it held - a 16px type icon, a badge, a chevron
   button - so sibling tables drifted apart. A fixed cell height with middle
   alignment absorbs all of those: every content variant is shorter than the
   row and centres inside it. */
.dash-list td {
  height: 2.1rem;
  padding-top: 0;
  padding-bottom: 0;
  vertical-align: middle;
}
.dash-list .btn-icon {
  width: 1.4rem;
  height: 1.4rem;
  min-height: 0;
  padding: 0;
  border: 0;
}

/* The same idea one size up, for a call table that IS a card rather than a box
   inside a panel (Call activity, Faulty calls, Worst quality). Tabler's default
   cell padding let the chevron button set the height, so those three tables
   drifted apart exactly as the glance lists once did. 2.5rem is dense without
   the fixed 2.1rem's squeeze - it still holds a leg avatar. */
.dash-card-list td {
  height: 2.5rem;
  padding-top: 0;
  padding-bottom: 0;
  vertical-align: middle;
}
.dash-card-list .btn-icon {
  width: 1.6rem;
  height: 1.6rem;
  min-height: 0;
  padding: 0;
  border: 0;
}

/* An empty widget sharing a `row-deck` row is stretched to its neighbour's
   height, and one grey line pinned to the top of a 500px box reads as a card
   that failed to load rather than one with nothing to report. */
.dash-empty {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* A chart whose points are links. ApexCharts draws its own SVG and does not
   know a slice leads anywhere, so the affordance has to be said here. */
.chart-clickable .apexcharts-pie-area,
.chart-clickable .apexcharts-bar-area {
  cursor: pointer;
}

/* A row of device facts (field-lock bands on the trunk Device and service
   AudioCodes tabs) lays its columns out at the width the value needs, instead
   of the 12-column split: three thirds of a wide band turn a nine-character
   SBC name into a field that reads as an empty form. A deliberate exception to
   "widths come only from sf-*" (.claude/rules/admin-design.md), written down
   here because the values are short and fixed - the grid still owns every
   other band. Columns wrap when the container is narrow, so the inversion test
   still holds: a field never gets squeezed, the row gets shorter. */
.sheet-grid.is-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 1rem;
}
.sheet-grid.is-fields > * {
  width: 15rem;
  max-width: 100%;
}
.sheet-grid.is-fields > .is-wide {
  width: 22rem;
}

/* A band with a second row of blocks: the two grids are separate rows, not one
   flow, so they need the space a grid gap gives inside a row. Without it a
   locked field sits directly on top of the view field beneath it. */
.sheet-grid + .sheet-grid {
  margin-top: 1.1rem;
}

/* A datagrid in a narrow container (the CDR details page keeps two in col-6
   halves) cannot shrink below Tabler's 15rem item minimum and punches out of
   the page. Letting the minimum yield to the container is a no-op wherever
   the container is wider than 15rem - which is everywhere it worked before. */
.datagrid {
    --tblr-datagrid-item-width: min(15rem, 100%);
}

/* The main menu bar must never widen the page.
   It is a flex item, so its default min-width:auto refuses to shrink below its
   content - a full menu measures 1046px. Dropped into the column left by a
   persistent 420px sidebar that forced the whole PAGE to scroll sideways
   (measured: 442px of overflow at a 1024px viewport, 186px at 1280px). Because
   the sidebar is position:fixed while the header and footer are in normal flow,
   that sideways scroll slid them out of line with it - which is what showed up
   as an offset at the top AND bottom of the page.

   House rule (admin-design.md): wide content stays inside its own box; the page
   body never scrolls horizontally. The menu WRAPS rather than scrolling,
   because an overflow container would clip the nav's own dropdowns.

   Both menus are covered: the app layout nests a .navbar inside #navbar-menu,
   the admin layout puts the nav list straight in it. */
#navbar-menu,
#navbar-menu > .navbar,
#navbar-menu > .navbar > .container-xl,
.navbar > .container-fluid,
.navbar > .container-xl {
    min-width: 0;
}

#navbar-menu .navbar-nav {
    flex-wrap: wrap;
}

/* Page tab strips - Overview / Voice / Services / Actions, and the six section
   menus that copy that markup. They were a Bootstrap .collapse carrying the app
   header's OWN id="navbar-menu", with no toggler of their own: the header's
   hamburger therefore opened the header's menu, and these could not be opened
   at all. Below the navbar's expand breakpoint they were simply absent - on a
   phone the Voice, Services and Actions tabs did not exist. They are tabs, not
   a menu, so they are always shown, in a row, allowed to wrap. */
.page-tabs {
    display: flex !important;
    flex-basis: 100%;
    flex-grow: 1;
    align-items: center;
}

.page-tabs .navbar-nav {
    flex-direction: row;
    flex-wrap: wrap;
}

/* ==========================================================================
   Mobile pass (phones, below Bootstrap's md)
   Three measured failures on a 390px viewport drive every rule here:
   a fixed-layout table crushed 12 columns into 357px (12-24px cells), the
   footer's full page-number pagination held the whole document at 606px, and
   the chrome strips (panel head, controls, filters) refuse to wrap.
   ========================================================================== */

/* A column declared `mobile: false` on DataTableComponent. Its own class, not
   d-none: the column-visibility controller reads d-none as a user choice and
   would save the viewport into the session. */
@media (max-width: 767.98px) {
  .dt-mobile-hide {
    display: none;
  }

  /* The app header holds one row on a phone: hamburger, brand, sidebar
     toggle. Without nowrap the brand's width pushed the toggle onto a second
     row, where it sat on top of the opened collapse menu. */
  #site-header .navbar > .container-xl {
    flex-wrap: nowrap;
  }
  #site-header .navbar-brand {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
  }

  /* Phones get the horizontal scroll back that the desktop dropdown fix
     (.card .table-responsive { overflow: visible }) removed: on a phone an
     unreadable table costs more than a row-action dropdown clipped at the
     card edge. A table that names its phone columns (adm-table--mobile-tuned)
     fits the viewport; one that has not yet keeps a readable width and
     scrolls inside its card instead of crushing. */
  .card .table-responsive {
    overflow-x: auto;
  }
  .adm-table:not(.adm-table--mobile-tuned) {
    min-width: 640px;
  }

  /* The home glance boxes hold a bare table - not a .table-responsive inside a
     .card - so the scroll rule above never reached them. Measured at 390px:
     the calls list rendered 506px and the changes list 499px inside a 359px
     box, both spilling straight through the box's own border. Scroll them
     inside the box, the same trade the card tables take above. A phone number
     has no wrap point, so there is no width at which these honestly fit. */
  .dash-box {
    overflow-x: auto;
  }

  .dash-box .dash-list {
    min-width: 100%;
    width: max-content;
  }

  /* A tuned table drops fixed layout on phones: the declared shares assume
     every column is present, so with half of them display:none the leftover
     would all fall to the unsized action column. Auto layout sizes the few
     remaining columns by content; max-width:1px is the fixed-layout ellipsis
     trick and would crush auto columns, so it comes off with it. */
  .adm-table--mobile-tuned {
    table-layout: auto;
  }
  .adm-table--mobile-tuned tbody td {
    /* Bounded, not none: the ellipsis needs a ceiling or one long value
       (a UPN under a name) stretches its column past the viewport. */
    max-width: 60vw;
  }

  /* Right-hand control clusters in card header bars (the admin timeline's
     search + lens group, and their kin) wrap instead of widening the page. */
  .card .ms-auto.d-flex.gap-2 {
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* The controls strip's ONE LINE rule (see data_table_component.html.erb) is
     a laptop decision; on a phone the line wraps. Same for the panel head and
     the footer - the pagination is the widest element on the page, so it
     wraps rather than widening the document. */
  .dt-panel-head,
  .card-footer.d-flex {
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }
  .adm-controls .row {
    row-gap: 0.5rem;
  }
  .card-footer .pagination {
    flex-wrap: wrap;
  }

  /* Filter bars above panels (TableFiltersComponent and the hand-rolled ones
     carrying the same .table-filters hook): the flex children crush their
     selects to two letters at phone width. Stack them full width instead.
     !important because the widths being beaten are inline max-widths. */
  .table-filters form {
    flex-wrap: wrap;
  }
  .table-filters form > div {
    flex: 1 1 100%;
    max-width: 100% !important;
  }
}



/* Routing-rule manage chips (admin/telephony/routing-rules/:id/manage): the
   label sits OVER the value - long monospace values (number ranges, device
   tags) need the full chip width - and the external-link icon / derived tag
   pins to the top-right corner instead of centering vertically. */
.sheet-derived--stacked { flex-direction: column; align-items: stretch; position: relative; gap: 0.15rem; }
.sheet-derived--stacked > div { min-width: 0; }
.sheet-derived--stacked .sheet-derived__value { overflow-wrap: anywhere; }
.sheet-derived--stacked .ti-external-link,
.sheet-derived--stacked .sheet-derived__tag { position: absolute; top: 0.45rem; right: 0.65rem; margin-left: 0; }

/* --- /app/v2 drill-down: clicking the diagram has to look like it did something
   ------------------------------------------------------------------------
   The panel below the topology is a Turbo Frame whose src is re-pointed on
   select. Until the response landed, the OLD panel sat there unchanged, so a
   click read as "nothing happened" and people clicked again.

   The stale panel is veiled rather than blanked: the frame keeps its height, so
   the page does not jump under the cursor, and what is on screen is visibly no
   longer current. Reuses the async loader's spin keyframe rather than a second
   animation.

   Applied only to a user's selection - the live sdr-events refresh re-fetches
   this same frame every few seconds, and nobody is waiting on that one. */
.dashboard-drilldown { position: relative; display: block; }
.dashboard-drilldown.is-loading > * {
  opacity: 0.4;
  transition: opacity 0.12s ease-out;
  pointer-events: none;
}
.dashboard-drilldown.is-loading::after {
  content: "";
  position: absolute;
  top: 2.5rem;
  left: 50%;
  width: 36px;
  height: 36px;
  margin-left: -18px;
  border: 3px solid var(--tblr-border-color);
  border-top-color: var(--tblr-primary);
  border-radius: 50%;
  animation: async-loader-spin 0.9s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .dashboard-drilldown.is-loading::after { animation-duration: 3s; }
}

/* ============================================================
   Sign-in duo (application_sign_in_new layout)
   One centered card, two panes: brand voice left, form right.
   Brand colors derive from --login-brand (whitelabel primary).
   ============================================================ */
.login-duo-container {
  max-width: 60rem;
}
.login-duo {
  display: flex;
  min-height: 30rem;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid var(--tblr-border-color);
  background: var(--tblr-bg-surface);
  box-shadow: 0 30px 90px rgba(2, 20, 43, 0.16), 0 4px 14px rgba(2, 20, 43, 0.06);
}
.login-duo-voice {
  flex: 1 1 52%;
  position: relative;
  flex-direction: column;
  justify-content: space-between;
  padding: 2.6rem 2.8rem;
  color: #eaf2fa;
  background:
    radial-gradient(30rem 22rem at 20% 15%,
      color-mix(in srgb, var(--login-brand, #066fd1) 16%, transparent), transparent 60%),
    linear-gradient(160deg,
      color-mix(in srgb, var(--login-brand, #066fd1) 18%, #0a0e17),
      color-mix(in srgb, var(--login-brand, #066fd1) 36%, #070b12) 70%,
      color-mix(in srgb, var(--login-brand, #066fd1) 58%, #060a10));
}
.login-duo-logo img {
  filter: brightness(0) invert(1); /* size: .fit-logo, 28px */
}
.login-duo-headline {
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 0.8rem;
  color: #fff;
}
.login-duo-headline em {
  font-style: normal;
  color: color-mix(in srgb, var(--login-brand, #066fd1) 45%, #fff);
}
.login-duo-lede {
  color: rgba(214, 232, 248, 0.72);
  font-size: 0.95rem;
  margin: 0;
  max-width: 22rem;
}
.login-duo-lede p {
  margin: 0 0 0.5rem;
}
.login-duo-lede p:last-child {
  margin-bottom: 0;
}
.login-duo-lede a {
  color: color-mix(in srgb, var(--login-brand, #066fd1) 45%, #fff);
}
.login-duo-form {
  flex: 1 1 48%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 2.5rem 1rem;
}
@media (max-width: 991.98px) {
  .login-duo {
    min-height: 0;
  }
}

/* ============================================================================
   Partner settings - carrier allowlist
   ============================================================================
   A named mode ("All carriers" / "Only the ones I select") with the catalogue
   table appearing only in the second. The mode cards are labels wrapping a
   radio, so the whole card is the hit target.
*/
.carrier-mode-card {
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease;
}
.carrier-mode-card:hover {
  border-color: var(--tblr-border-color-active, #c8cdd4);
}
.carrier-mode-card.is-on {
  border-color: var(--tblr-primary);
  background-color: rgba(var(--tblr-primary-rgb), .04);
}
/* The radio itself is focusable, so the ring belongs on the card around it. */
.carrier-mode-card:focus-within {
  outline: 2px solid var(--tblr-primary);
  outline-offset: 1px;
}

/* A chosen row reads at a glance when the list is long. */
.carrier-allowlist-table tr.is-selected > td {
  background-color: rgba(var(--tblr-primary-rgb), .05);
}

/* Profile rows sit under their carrier, so they get no top border of their own -
   the pair should read as one block rather than two rows that happen to adjoin. */
.carrier-allowlist-table tr.carrier-allowlist-profile > td {
  border-top: 0;
  padding-top: .15rem;
  padding-bottom: .15rem;
}

.carrier-allowlist-table [data-carrier-allowlist-target="expander"] .ti-chevron-right {
  transition: transform .12s ease;
}
.carrier-allowlist-table [data-carrier-allowlist-target="expander"][aria-expanded="true"] .ti-chevron-right {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .carrier-mode-card,
  .carrier-allowlist-table [data-carrier-allowlist-target="expander"] .ti-chevron-right {
    transition: none;
  }
}

/* The chosen carriers, as badges above the catalogue.
   Every carrier's badge is rendered once and hidden unless chosen, so the logo fallback stays
   in the decorator that owns it and the Stimulus controller only flips `hidden`. */
/* ONE surface, not three stacked blocks: a header band carrying what you chose, a controls
   strip, then the table flush inside the same border. The house panel shape - see
   admin-design.md, "The panel is one shape for every table". Stacked separates; a shared
   border is what makes ticking a row and seeing a badge appear read as one action. */
.carrier-allowlist-panel {
  border: 1px solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  overflow: hidden;
  background: var(--tblr-bg-surface);
}
.carrier-allowlist-chosen {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  flex-wrap: wrap;
  min-height: 3rem;
  padding: .65rem .75rem;
  background: var(--tblr-bg-surface-secondary);
  border-bottom: 1px solid var(--tblr-border-color);
}
.carrier-allowlist-chosen-label {
  font-size: .625rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--tblr-secondary);
  white-space: nowrap;
}
.carrier-allowlist-chosen-count {
  display: inline-block;
  min-width: 1.25rem;
  padding: 0 .3rem;
  margin-left: .25rem;
  text-align: center;
  border-radius: 999px;
  background: var(--tblr-border-color);
  color: var(--tblr-body-color);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.carrier-allowlist-controls {
  padding: .65rem .75rem;
  border-bottom: 1px solid var(--tblr-border-color);
}
.carrier-allowlist-foot {
  padding: .5rem .75rem;
  border-top: 1px solid var(--tblr-border-color);
}
/* The table sits flush: the panel already has the border. */
.carrier-allowlist-panel .table-responsive { border: 0; }

/* Hovering a badge lights its row, so the two halves are visibly one selection. */
.carrier-allowlist-table tr.is-linked > td {
  background-color: rgba(var(--tblr-primary-rgb), .12);
}
.carrier-allowlist-badge {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .25rem .35rem .25rem .4rem;
  font-size: .8125rem;
  font-weight: 500;
  border: 1px solid var(--tblr-border-color);
  border-radius: 999px;
  background-color: var(--tblr-bg-surface);
  color: var(--tblr-body-color);
}
/* avatar_tag ships `me-3` for use beside a heading; inside a chip that is a chasm. */
.carrier-allowlist-badge .avatar {
  margin-right: 0 !important;
  /* The decorator's initials fallback hardcodes 1.25rem, which overflows a chip this size. */
  font-size: .5rem !important;
  line-height: 1;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  flex: none;
}
.carrier-allowlist-badge-name {
  white-space: nowrap;
}
.carrier-allowlist-badge-x {
  --tblr-btn-close-bg: none;
  font-size: .5rem;
  opacity: .5;
  padding: .25rem;
  margin: 0;
}
.carrier-allowlist-badge-x:hover { opacity: 1; }
.carrier-allowlist-badge-x:focus-visible {
  outline: 2px solid var(--tblr-primary);
  outline-offset: 1px;
  opacity: 1;
}


/* Tenant › AI › Data sources: a card per source; off dims everything but the switch and Check. */
.ai-source-off .avatar,
.ai-source-off .card-title,
.ai-source-off .card-body .icon,
.ai-source-off .card-body .text-secondary { opacity: .5; }

/* Page width on modern screens (2026-09-17). Tabler caps .container-xl at 1320px, which leaves a third of a
   1920 display empty beside the 320px sidebar. 1600px fills a 1920 display with the sidebar open, still leaves
   margin on ultrawide, and changes nothing below 1400px. Print keeps its own full-width rule above. */
@media screen and (min-width: 1400px) {
  .container-xl { max-width: 1600px; }
}

/* The Ask widget (ADR-0003): a pill at rest, the question bar on the first click, the chat window once a thread
   exists. One dark surface whatever the page theme; the blue button is Ask on the pill, Send once open. Anchored
   bottom right; when the page has a quick-help pill, Ask sits to its left. */
.ask {
  --ask-bg: #1b2432; --ask-bg2: #26313f; --ask-line: rgba(255, 255, 255, 0.09);
  --ask-text: #e8edf3; --ask-muted: rgba(232, 237, 243, 0.62);
  --ask-me: #0f6b4c; --ask-ai: #2a3646;
  --ask-primary: #206bc4; --ask-primary-hi: #2f7ddb; --ask-green: #2fb344; --ask-red: #d63939;
  --ask-w: 560px; --ask-wide: 820px; --ask-h: 440px; --ask-right: 1.25rem; --ask-bottom: calc(1.25rem - 4px);
  --ask-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  position: fixed; right: var(--ask-right); bottom: var(--ask-bottom); z-index: 1030; width: 96px;
  display: flex; flex-direction: column; border-radius: 28px; background: transparent;
  color: var(--ask-text); font-size: 13.5px; line-height: 1.45;
  transition: width 0.32s var(--ask-ease), background-color 0.25s, border-radius 0.3s var(--ask-ease), box-shadow 0.3s;
}
body:has(.quick-help-fab) .ask { --ask-right: 8rem; }
.ask.is-bar, .ask.is-chat {
  width: min(var(--ask-w), calc(100vw - var(--ask-right) - 1rem)); background: var(--ask-bg);
  box-shadow: 0 18px 48px rgba(15, 23, 42, 0.35), 0 0 0 1px var(--ask-line);
}
.ask.is-chat { border-radius: 20px; }
.ask.is-chat.is-wide { width: min(var(--ask-wide), calc(100vw - var(--ask-right) - 1rem)); }
.ask.is-chat.is-wide .ask__scroll { height: calc(100vh - 290px); }
.ask.no-motion, .ask.no-motion * { transition: none !important; }
.ask .ti { font-size: 1.25rem; line-height: 1; }

/* Window: header and thread, grows upward from the bar. */
.ask__panel { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows 0.34s var(--ask-ease), opacity 0.18s; }
.ask.is-chat .ask__panel { grid-template-rows: 1fr; opacity: 1; transition: grid-template-rows 0.34s var(--ask-ease), opacity 0.25s 0.08s; }
.ask__panel > div { min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.ask__head { display: flex; align-items: center; gap: 8px; height: 48px; padding: 0 8px 0 16px; border-bottom: 1px solid var(--ask-line); flex: none; }
.ask__title { font-weight: 600; }
.ask__spark { color: var(--ask-primary-hi); font-size: 1.125rem; }
.ask__chip {
  font-size: 11.5px; color: var(--ask-muted); border: 1px solid var(--ask-line); border-radius: 10px; padding: 2px 8px;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ask.is-wide .ask__chip { max-width: 320px; }
.ask__spacer { flex: 1; }
.ask__head .ask__ib { width: 34px; height: 34px; border-radius: 9px; }
.ask__scroll { height: var(--ask-h); max-height: calc(100vh - 200px); overflow-y: auto; padding: 12px 14px; scroll-behavior: smooth; }
.ask__msgs { display: flow-root; }

/* Bubbles: the person on the right in green, the answer on the left in slate. No avatars. */
.msg {
  position: relative; width: fit-content; max-width: 82%; margin: 0 0 6px; padding: 8px 12px 7px;
  border-radius: 14px; overflow-wrap: anywhere;
}
.msg--ai { margin-right: auto; background: var(--ask-ai); border-bottom-left-radius: 4px; }
.msg--me { margin-left: auto; background: var(--ask-me); border-bottom-right-radius: 4px; color: #fff; white-space: pre-wrap; }
.msg--error { color: #f2b8b5; }
.msg .markdown { color: inherit; font-size: inherit; }
.msg .markdown > :last-child { margin-bottom: 0; }
.msg .markdown code { background: rgba(255, 255, 255, 0.08); color: inherit; }
.msg .markdown a { color: var(--ask-primary-hi); }
/* A table in an answer: the widget is 560px wide, so it scrolls sideways rather than wraps; figures line up. */
.msg .markdown table { display: block; overflow-x: auto; max-width: 100%; border-collapse: collapse; margin: 6px 0 8px; font-size: 12.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.msg .markdown th, .msg .markdown td { padding: 4px 10px 4px 0; border-bottom: 1px solid var(--ask-line); text-align: left; vertical-align: top; }
.msg .markdown th { font-weight: 600; color: var(--ask-muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; }
.msg .markdown th:not(:first-child), .msg .markdown td:not(:first-child) { text-align: right; }
.msg .markdown tr:last-child td { border-bottom: 0; }
.msg .markdown ul, .msg .markdown ol { padding-left: 1.1rem; margin-bottom: 0.5rem; }
.msg__time { float: right; margin: 8px -2px -4px 12px; font-size: 10.5px; color: var(--ask-muted); font-variant-numeric: tabular-nums; }
.msg--me .msg__time { color: rgba(255, 255, 255, 0.7); }
/* The typed blocks of an answer (Ai::Blocks): stacked under the prose, one column even in the wide widget. */
.ask__block { display: block; margin-top: 8px; }
.ask__block-source { display: block; margin-top: 4px; font-size: 11px; color: var(--ask-muted); }
.ask__figures-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 6px; }
.ask__figure { background: rgba(255, 255, 255, 0.06); border-radius: 8px; padding: 8px 10px; min-width: 0; }
.ask__figure-label { display: block; font-size: 11px; color: var(--ask-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask__figure-value { display: block; font-size: 18px; font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.ask__figure-delta { display: inline-flex; align-items: center; gap: 2px; font-size: 11px; color: var(--ask-muted); font-variant-numeric: tabular-nums; }
.ask__chart-title { display: block; font-size: 12px; font-weight: 600; margin-bottom: 2px; }
.ask__chart [data-controller="apexchart"] { min-height: 180px; }
.ask__callout { display: flex; gap: 8px; align-items: flex-start; padding: 6px 10px; border-left: 3px solid var(--ask-muted); background: rgba(255, 255, 255, 0.05); border-radius: 0 6px 6px 0; font-size: 13px; }
.ask__callout .ti { flex: none; margin-top: 1px; }
.ask__callout--info { border-left-color: var(--ask-primary-hi); } .ask__callout--info .ti { color: var(--ask-primary-hi); }
.ask__callout--warning { border-left-color: #f59f00; } .ask__callout--warning .ti { color: #f59f00; }
.ask__callout--danger { border-left-color: var(--ask-red); } .ask__callout--danger .ti { color: #f2b8b5; }
.ask__goto { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border: 1px solid var(--ask-line); border-radius: 8px; color: inherit; text-decoration: none; font-size: 13px; }
.ask__goto:hover { background: rgba(255, 255, 255, 0.06); color: inherit; }
.ask__goto > .ti:first-child { color: var(--ask-primary-hi); }
.ask__goto span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask__goto-arrow { color: var(--ask-muted); }
.ask__suggestions { display: flex; flex-wrap: wrap; gap: 6px; }
.ask__suggest { border: 1px solid var(--ask-line); background: transparent; color: var(--ask-text); border-radius: 999px; padding: 4px 10px; font-size: 12px; cursor: pointer; text-align: left; }
.ask__suggest:hover { background: rgba(255, 255, 255, 0.06); }
.ask__unresolved { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ask-muted); border: 1px dashed var(--ask-line); border-radius: 999px; padding: 3px 10px; }
/* The same blocks on the run page, on a light card: the widget tokens do not exist there. */
.ask-blocks-page { --ask-line: var(--tblr-border-color); --ask-muted: var(--tblr-secondary); --ask-text: var(--tblr-body-color); --ask-primary-hi: var(--tblr-primary); --ask-red: #d63939; max-width: 640px; }
.ask-blocks-page .ask__figure, .ask-blocks-page .ask__callout { background: var(--tblr-bg-surface-secondary, #f6f8fa); }
.ask-blocks-page .ask__goto:hover, .ask-blocks-page .ask__suggest:hover { background: var(--tblr-bg-surface-secondary, #f6f8fa); }
.msg__ev { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--ask-line); font-size: 11.5px; color: var(--ask-muted); display: flex; flex-direction: column; gap: 3px; }
.msg__ev span { display: flex; gap: 6px; align-items: center; }
.msg__ev .ti { font-size: 0.875rem; flex: none; }
.msg__foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 6px; font-size: 11.5px; }
.msg__foot a { color: var(--ask-muted); text-decoration: underline dotted; text-underline-offset: 2px; }
.msg__foot .msg__time { float: none; margin: 0; }
.msg--typing { padding: 13px 14px; display: flex; gap: 4px; align-items: center; }
.msg--typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--ask-muted); animation: ask-dot 1.2s infinite; }
.msg--typing i:nth-child(2) { animation-delay: 0.2s; }
.msg--typing i:nth-child(3) { animation-delay: 0.4s; }
@keyframes ask-dot { 0%, 80%, 100% { opacity: 0.3; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
.ask__status { font-size: 11.5px; color: var(--ask-muted); padding-left: 6px; margin-bottom: 6px; display: flex; gap: 7px; align-items: center; }
.ask__status .spinner-border { width: 10px; height: 10px; border-width: 2px; }
/* The run's steps: a live list while it works, collapsed under the answer once done; a note is the model's own line. */
.ask__steps { font-size: 11.5px; color: var(--ask-muted); margin: 0 0 6px 6px; padding: 0; }
.ask__steps ol, ol.ask__steps { list-style: none; margin: 0; padding: 0; }
.ask__steps summary { cursor: pointer; list-style: none; }
.ask__steps summary::before { content: "\203A"; display: inline-block; width: 10px; transition: transform .15s; }
.ask__steps[open] summary::before { transform: rotate(90deg); }
.ask__step { padding: 1px 0 1px 12px; position: relative; }
.ask__step::before { content: ""; position: absolute; left: 2px; top: 8px; width: 4px; height: 4px; border-radius: 2px; background: var(--ask-muted); }
.ask__step--note { font-style: italic; color: var(--ask-text); }
.ask__step--thinking { color: var(--ask-muted); line-height: 1.45; }
.ask__step--thinking strong { font-weight: 600; }
.ask__step span { opacity: .7; margin-left: 4px; }
.ask-marker { font-size: 11.5px; color: var(--ask-muted); margin: 4px auto 10px; text-align: center; }

/* The bar: what to ask about, the question, mic (later), close; the send circle is the fab. */
.ask__bar {
  position: relative; display: flex; align-items: flex-end; gap: 2px; min-height: 56px; padding: 6px 60px 6px 8px;
  opacity: 0; pointer-events: none; transition: opacity 0.16s;
}
.ask.is-bar .ask__bar, .ask.is-chat .ask__bar { opacity: 1; pointer-events: auto; transition: opacity 0.22s 0.14s; }
.ask__input {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: 0; box-shadow: none; color: inherit; font: inherit;
  line-height: 20px; padding: 12px 6px; max-height: 104px; resize: none; overflow-y: auto;
}
/* In the bar state the question sits alone on the panel, so it starts where a line of text would, not against
   the edge; the chat composer has its own card padding and sets its own. */
.ask.is-bar .ask__input { padding-left: 14px; }
.ask__input:focus { outline: 0; box-shadow: none; }
.ask__input::placeholder { color: var(--ask-muted); }
.ask__ib {
  flex: none; width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: var(--ask-muted); border-radius: 12px; cursor: pointer; padding: 0;
}
.ask__ib:hover { color: var(--ask-text); background: rgba(255, 255, 255, 0.06); }
.ask__ib:disabled { opacity: 0.35; cursor: not-allowed; background: transparent; color: var(--ask-muted); }
.ask__ib:focus-visible { outline: 2px solid var(--ask-primary-hi); outline-offset: -2px; }
.ask__hint { display: none; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ask-muted); height: 40px; white-space: nowrap; }
.ask__hint kbd { font-size: 11px; line-height: 1; border: 1px solid var(--ask-line); border-radius: 4px; padding: 2px 5px; background: rgba(255, 255, 255, 0.04); color: var(--ask-text); }

/* Chat state: the bar becomes a composer card, the question above a tools row. */
.ask.is-chat .ask__bar {
  margin: 6px 12px 12px; background: var(--ask-bg2); border-radius: 16px; padding: 6px 10px 8px; flex-wrap: wrap;
  min-height: 0; box-shadow: 0 0 0 1px var(--ask-line); align-items: center;
}
.ask.is-chat .ask__input { flex-basis: 100%; order: 1; padding: 9px 6px 4px; }
.ask.is-chat .ask__plus-wrap { order: 2; }
.ask.is-chat .ask__mic { order: 3; }
.ask.is-chat .ask__hint { display: flex; order: 4; margin-left: auto; margin-right: 50px; }
.ask.is-chat .ask__close { display: none; }
.ask.is-chat .ask__ib { height: 40px; }

/* What to ask about: the page's record or the account. Opens upward. */
.ask__plus-wrap { position: relative; flex: none; }
.ask__plus .ti { transition: transform 0.2s var(--ask-ease); }
.ask.is-menu .ask__plus { color: var(--ask-text); background: rgba(255, 255, 255, 0.08); }
.ask.is-menu .ask__plus .ti { transform: rotate(45deg); }
.ask__menu {
  position: absolute; left: 0; bottom: 50px; width: 260px; background: var(--ask-bg2); border-radius: 12px; padding: 6px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.45), 0 0 0 1px var(--ask-line);
  opacity: 0; transform: translateY(6px); pointer-events: none; transition: opacity 0.18s, transform 0.18s var(--ask-ease);
}
.ask.is-menu .ask__menu { opacity: 1; transform: none; pointer-events: auto; }
.ask__menu-h { font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ask-muted); padding: 6px 10px 4px; }
.ask__mi {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border: 0; background: transparent;
  color: var(--ask-text); font: inherit; border-radius: 8px; cursor: pointer; text-align: left;
}
.ask__mi:hover { background: rgba(255, 255, 255, 0.06); }
.ask__mi > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask__mi .ti { color: var(--ask-muted); font-size: 1.125rem; flex: none; }
.ask__mi-check { opacity: 0; }
.ask__mi.is-on .ask__mi-check { opacity: 1; color: var(--ask-green); }

/* The fab: Ask pill at rest, Send circle once open. One element, it morphs in place. */
.ask__fab {
  position: absolute; right: 0; bottom: 4px; width: 96px; height: 48px; padding: 0; border: 0; border-radius: 24px;
  background: var(--ask-primary); color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 8px 24px rgba(32, 107, 196, 0.35); overflow: hidden; white-space: nowrap; font-weight: 600; font-size: 14px;
  transition: width 0.32s var(--ask-ease), height 0.3s var(--ask-ease), right 0.3s var(--ask-ease), bottom 0.3s var(--ask-ease),
    background-color 0.25s, box-shadow 0.3s, opacity 0.2s;
}
.ask__fab:hover { background: var(--ask-primary-hi); }
.ask__fab:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.ask__fab:disabled { cursor: wait; }
.ask.is-bar .ask__fab, .ask.is-chat .ask__fab { width: 44px; height: 44px; right: 6px; bottom: 6px; box-shadow: none; opacity: 0.6; }
.ask.is-chat .ask__fab { right: 18px; bottom: 18px; }
.ask.is-armed .ask__fab { opacity: 1; }
.ask__fab-pill { display: flex; align-items: center; gap: 7px; transition: opacity 0.12s; }
.ask__fab-send {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  opacity: 0; transform: scale(0.5); transition: opacity 0.2s, transform 0.28s var(--ask-ease);
}
.ask__fab-send .ti { font-size: 1.375rem; }
.ask.is-bar .ask__fab-pill, .ask.is-chat .ask__fab-pill { opacity: 0; }
.ask.is-bar .ask__fab-send, .ask.is-chat .ask__fab-send { opacity: 1; transform: none; transition-delay: 0.12s; }
/* The pill's edge while minimised (artbook "Ask Pill States", A + R2 without the dot): a rainbow ring turning around
   the pill while an answer is being written; when it lands, green (red for a failed run) fills the ring once around
   like a clock hand, glows once, and stays until Ask is opened. Both layers sit behind the fab, framing it. */
@property --ask-angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
@property --ask-fill { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
.ask__halo, .ask__edge {
  position: absolute; right: 0; bottom: 4px; width: 96px; height: 48px; border-radius: 24px; pointer-events: none;
  opacity: 0; transition: opacity 0.9s;
}
.ask__halo::before, .ask__halo::after, .ask__edge::before, .ask__edge::after {
  content: ""; position: absolute; inset: -3px; border-radius: 27px;
}
.ask__halo::after, .ask__edge::after { inset: -6px; border-radius: 30px; filter: blur(10px); }
.ask__halo::before, .ask__halo::after {
  background: conic-gradient(from var(--ask-angle), #4285f4, #9b72cb, #d96570, #f2a93b, #34a853, #4285f4);
  animation: ask-spin 2.4s linear infinite;
}
.ask__halo::after { opacity: 0.75; }
.ask__edge { --ask-edge: var(--ask-green); transition: opacity 0.3s; }
.ask__edge::before { background: conic-gradient(from 0deg, var(--ask-edge) var(--ask-fill), transparent 0); --ask-fill: 360deg; }
.ask__edge::after { background: var(--ask-edge); opacity: 0; }
.ask.is-pill.is-working .ask__halo { opacity: 1; }
.ask.is-pill.has-unread .ask__edge, .ask.is-pill.has-failed .ask__edge { opacity: 1; }
.ask.is-pill.has-failed .ask__edge { --ask-edge: var(--ask-red); }
.ask.is-pill.has-unread .ask__edge::before, .ask.is-pill.has-failed .ask__edge::before {
  animation: ask-gather 1.2s cubic-bezier(0.5, 0, 0.2, 1) both;
}
.ask.is-pill.has-unread .ask__edge::after, .ask.is-pill.has-failed .ask__edge::after { animation: ask-exhale 1.6s 1s ease-out; }
@keyframes ask-spin { to { --ask-angle: 360deg; } }
@keyframes ask-gather { from { --ask-fill: 0deg; } to { --ask-fill: 360deg; } }
@keyframes ask-exhale { 0% { opacity: 0; } 30% { opacity: 0.85; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ask__halo::before, .ask__halo::after, .ask__edge::before, .ask__edge::after { animation: none !important; }
}

@media (max-width: 640px) {
  .ask { --ask-right: 1rem; }
  body:has(.quick-help-fab) .ask { --ask-right: 8rem; }
  .ask__chip { max-width: 120px; }
}
@media (prefers-reduced-motion: reduce) {
  .ask, .ask * { transition-duration: 0.01ms !important; }
  .msg--typing i { animation: none; }
}
@media print { .ask { display: none; } }


/* The AI landing page (tenant/ai/coming_soon): the entry when the plan lacks the feature. Its own treatment, not the
   card layout: a navy hero with the inputs-to-outputs diagram, an auto-advancing examples block, sections on an open
   grid with hairlines. Colours from the sidebar's navy and Tabler's primary; type is the app's Inter. */
.ai-landing { --ai-navy: #0f2a47; --ai-navy-2: #143a63; --ai-ink: var(--tblr-body-color); --ai-muted: var(--tblr-secondary-color, var(--tblr-secondary)); --ai-line: var(--tblr-border-color); --ai-accent: var(--tblr-primary); --ai-card: #fff; --ai-card-ink: #0f2a47; --ai-card-muted: #5b6b7d; }
.ai-landing .container-xl { max-width: 1240px; }
.ai-hero { background: var(--ai-navy); color: #fff; border-radius: 1.5rem; padding: 3.5rem 2rem 2.5rem; text-align: center; margin-bottom: 1rem; }
.ai-hero__mark { display: inline-flex; align-items: center; gap: 0.4rem; font-weight: 600; letter-spacing: 0.02em; opacity: 0.95; margin-bottom: 1.25rem; }
.ai-hero__mark .ti { font-size: 1.25rem; }
.ai-hero__soon { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; background: rgba(255, 255, 255, 0.14); border-radius: 0.4rem; padding: 0.2rem 0.5rem; margin-left: 0.5rem; }
.ai-hero__title { font-size: clamp(2rem, 4.2vw, 3.5rem); line-height: 1.08; font-weight: 600; letter-spacing: -0.02em; margin: 0 auto 1.25rem; max-width: 22ch; text-wrap: balance; color: #fff; }
.ai-hero__lead { font-size: 1.05rem; line-height: 1.6; color: rgba(255, 255, 255, 0.78); max-width: 58ch; margin: 0 auto 1.5rem; }
.ai-hero__cta { display: inline-flex; align-items: center; gap: 0.5rem; background: #fff; color: var(--ai-navy); font-weight: 600; padding: 0.7rem 1.1rem; border: 0; border-radius: 0.6rem; text-decoration: none; cursor: pointer; }
.ai-hero__cta:hover { background: #eaf1fb; color: var(--ai-navy); }
.ai-hero__cta:focus-visible { outline: 3px solid #7db4ff; outline-offset: 4px; }
.ai-hero__note { font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); margin-top: 0.6rem; }
.ai-hero__note--light { margin-top: 0.5rem; }
.ai-hero__joined { display: inline-flex; align-items: center; gap: 0.5rem; color: #fff; font-weight: 600; padding: 0.7rem 0; }
.ai-hero__link { background: none; border: 0; padding: 0; color: inherit; text-decoration: underline; cursor: pointer; }
.ai-hero__link:hover { color: #fff; }

.ai-tabs { display: flex; gap: 0.25rem; background: rgba(255, 255, 255, 0.08); border-radius: 0.6rem; padding: 0.25rem; margin: 2.5rem auto 2rem; max-width: 640px; }
.ai-tab { flex: 1; border: 0; background: transparent; color: rgba(255, 255, 255, 0.6); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; padding: 0.65rem 0.5rem; border-radius: 0.45rem; cursor: pointer; }
.ai-tab.active { background: rgba(255, 255, 255, 0.14); color: #fff; }
.ai-tab:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* One example run in the shape Maarten drew: the question on top, the dark Pulse AI box under it holding the whole
   bottom (the skill with the data sources it reached under it, the result beside it). The question goes down into
   the box, the result comes back up. */
.ai-flow { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; max-width: 960px; margin: 0 auto; text-align: left; }
.ai-flow__example { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ai-navy); background: #cfe0f6; padding: 0.2rem 0.6rem; border-radius: 0.4rem; }
.ai-flow__in { width: 100%; max-width: 640px; }
.ai-flow__in--split { max-width: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.ai-flow__in--split .ai-mock__row { overflow-wrap: anywhere; }
.ai-flow .ai-mock__row { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.ai-flow .ai-mock { font-size: 0.9rem; background: var(--ai-navy-2); border: 1px solid rgba(255, 255, 255, 0.14); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); }
.ai-flow .ai-mock--done { background: #0f6b4c; border-color: rgba(255, 255, 255, 0.2); }
.ai-flow .ai-mock--done .ai-mock__head .ti { color: #fff; }
/* The Ask widget's input bar, as a picture: the question types itself in. */
.ai-mock__bar { display: flex; align-items: center; gap: 0.35rem; background: #1b2432; border: 1px solid rgba(255, 255, 255, 0.09); border-radius: 1rem; padding: 0.35rem 0.4rem 0.35rem 0.9rem; color: #e8edf3; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); }
.ai-mock__bar-text { flex: 1; min-width: 0; min-height: 1.45em; line-height: 1.45; overflow-wrap: anywhere; }
.ai-mock__bar > .ti { color: rgba(232, 237, 243, 0.4); font-size: 1.1rem; padding: 0.35rem; }
.ai-mock__bar-send { flex: none; width: 2.25rem; height: 2.25rem; border-radius: 50%; background: var(--ai-accent); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.ai-mock__bar-text.is-typing::after { content: ""; display: inline-block; width: 2px; height: 1em; background: #fff; margin-left: 2px; vertical-align: -0.15em; animation: ai-caret 0.9s steps(1) infinite; }
@keyframes ai-caret { 50% { opacity: 0; } }
.ai-flow__io, .ai-flow__updown { display: inline-flex; gap: 0.5rem; color: rgba(255, 255, 255, 0.55); font-size: 1.25rem; line-height: 1; }
.ai-flow__io { width: 100%; max-width: 640px; justify-content: space-between; padding: 0 3rem; }
.ai-flow__layer { width: 100%; background: #050f1d; color: #fff; border-radius: 0.9rem; padding: 1rem 1.25rem 1.25rem; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35); }
.ai-flow__engine { display: inline-flex; align-items: center; gap: 0.45rem; font-weight: 600; margin-bottom: 0.85rem; }
.ai-flow__engine .ti { color: #7db4ff; }
.ai-flow__grid { display: grid; grid-template-columns: minmax(0, 1fr) 2.5rem minmax(0, 1fr); grid-template-areas: "skill right out" "updown . out" "sources . out"; align-items: start; row-gap: 0.35rem; }
.ai-flow__skill { grid-area: skill; } .ai-flow__out { grid-area: out; } .ai-flow__sources { grid-area: sources; }
.ai-flow__right { grid-area: right; align-self: start; margin-top: 5.5rem; justify-self: center; color: rgba(255, 255, 255, 0.55); font-size: 1.25rem; line-height: 1; }
.ai-flow__updown { grid-area: updown; justify-self: center; }
.ai-flow__skill, .ai-flow__out, .ai-flow__sources { background: var(--ai-card); color: var(--ai-card-ink); border-radius: 0.75rem; padding: 1rem 1.25rem; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); min-width: 0; }
.ai-flow__out { background: #fffbe6; color: #0f2a47; }
.ai-flow__kind { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.65rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ai-accent); background: #eaf1fb; padding: 0.2rem 0.5rem; border-radius: 0.3rem; margin-bottom: 0.5rem; }
.ai-flow__skill .ai-flow__kind { color: #1a7f44; background: #e9f7ee; margin-right: 0.35rem; }
.ai-flow__kind--skill { color: var(--ai-card-ink) !important; background: transparent !important; border: 1px solid var(--ai-line); text-transform: none; letter-spacing: 0; font-size: 0.76rem; }
.ai-flow__out .ai-flow__kind { color: #5c4a00; background: #fff2a8; }
.ai-flow__out .ai-flow__meta { color: #5b6b7d; }
.ai-flow__sources .ai-flow__kind { color: #985107; background: #fdf0e1; display: flex; width: fit-content; }
.ai-source { display: inline-block; margin: 0 0.35rem 0.35rem 0; font-size: 0.78rem; font-weight: 500; padding: 0.25rem 0.55rem; border: 1px solid var(--ai-line); border-radius: 0.4rem; }
.ai-flow__trigger { font-size: 1.05rem; font-weight: 600; line-height: 1.35; margin: 0 0 0.4rem; overflow-wrap: anywhere; }
.ai-flow__answer { font-size: 0.92rem; line-height: 1.45; margin: 0 0 0.75rem; overflow-wrap: anywhere; }
.ai-flow__meta { display: block; font-size: 0.76rem; color: var(--ai-card-muted); overflow-wrap: anywhere; }
.ai-flow__meta .ti { margin-right: 0.3rem; }
/* The skill's steps, in order; the one the person answered is marked. */
.ai-checks { list-style: none; margin: 0; padding: 0; counter-reset: check; }
.ai-check { position: relative; padding: 0.5rem 0 0.5rem 1.75rem; border-top: 1px solid var(--ai-line); counter-increment: check; }
.ai-check::before { content: counter(check); position: absolute; left: 0; top: 0.6rem; width: 1.25rem; height: 1.25rem; border-radius: 50%; background: #e9f7ee; color: #1a7f44; font-size: 0.68rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
.ai-check--input::before { background: #eaf1fb; color: var(--ai-accent); }
.ai-check__q { display: block; font-size: 0.78rem; color: var(--ai-card-muted); }
.ai-check__fact { display: block; font-size: 0.86rem; font-weight: 500; line-height: 1.4; overflow-wrap: anywhere; }
.ai-check__source { display: inline-block; margin-top: 0.15rem; font-size: 0.64rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: #985107; }
.ai-check--input .ai-check__source { color: var(--ai-accent); }
.ai-check__a { min-width: 0; }
.ai-check__fact { display: block; font-size: 0.86rem; line-height: 1.4; overflow-wrap: anywhere; }
.ai-check__source { display: inline-block; margin-top: 0.15rem; font-size: 0.64rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: #985107; }

/* Partners on the early-access page (artbook "Partner Seats Landing"): the scope line in the hero and the tree. */
.ai-scope { display: inline-flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.5rem; margin: 0 auto 1.25rem;
  background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.16); border-radius: 999px; padding: 0.45rem 0.9rem; font-size: 0.875rem; }
.ai-scope b { color: #fff; }
.ai-scope__dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: #7cc4ff; }
.ai-hero .ai-scope { display: flex; width: fit-content; max-width: 100%; }
.ai-partner { display: grid; grid-template-columns: 1fr 1.25fr; gap: 2rem; align-items: start; padding: 2rem 0 3rem; border-top: 1px solid var(--ai-line); margin-top: 1rem; }
@media (max-width: 860px) { .ai-partner { grid-template-columns: 1fr; } }
.ai-partner__lead { color: var(--ai-muted); margin: 0.5rem 0 0; max-width: 46ch; }
.ai-partner__facts { list-style: none; padding: 0; margin: 1rem 0 0; display: grid; gap: 0.6rem; }
.ai-partner__facts li { display: grid; grid-template-columns: 1.4rem 1fr; gap: 0.4rem; }
.ai-tree__node { background: var(--ai-card); color: var(--ai-card-ink); border: 1px solid var(--ai-line); border-radius: 0.75rem; padding: 0.75rem 0.9rem; position: relative; }
.ai-tree__node h3 { margin: 0; font-size: 0.95rem; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; color: var(--ai-card-ink); }
.ai-tree__node--partner { border-color: var(--ai-accent); box-shadow: 0 0 0 3px #eaf1fb; }
.ai-tree__kind { font-size: 0.66rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ai-card-muted); }
.ai-tree__meta { margin-top: 0.35rem; font-size: 0.8rem; color: var(--ai-card-muted); }
.ai-tree__children { display: grid; gap: 0.6rem; margin: 1rem 0 0 1.6rem; padding-left: 1.4rem; border-left: 2px dashed var(--ai-line); }
.ai-tree__children .ai-tree__node::before { content: ""; position: absolute; left: -1.5rem; top: 1.35rem; width: 1.4rem; border-top: 2px dashed var(--ai-line); }
.ai-tree__caps { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }
.ai-cap { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.75rem; border-radius: 0.4rem; padding: 0.15rem 0.5rem; }
.ai-cap .ti { font-size: 0.85rem; }
.ai-cap--on { background: #e6f6e9; color: #2a8a3b; }
.ai-cap--own { background: #fff4e0; color: #9a5b00; }
.ai-cap--off { border: 1px dashed var(--ai-line); color: var(--ai-card-muted); }
.ai-tree__more { font-size: 0.82rem; color: var(--ai-muted); }
.ai-section { padding: 1rem 0 3.5rem; border-top: 1px solid var(--ai-line); margin-top: 1rem; }
.ai-section__head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 2rem; align-items: end; margin: 2.5rem 0 2.5rem; }
.ai-section__intro { color: var(--ai-muted); font-size: 1.02rem; line-height: 1.6; margin: 0; max-width: 46ch; justify-self: end; }
.ai-eyebrow { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ai-accent); margin-bottom: 0.75rem; }
.ai-eyebrow--light { color: rgba(255, 255, 255, 0.7); }
.ai-h2 { font-size: clamp(1.75rem, 3vw, 2.6rem); line-height: 1.12; font-weight: 600; letter-spacing: -0.02em; margin: 0; text-wrap: balance; }
.ai-h2 em { font-style: italic; color: var(--ai-accent); }
.ai-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 2.5rem; border-top: 1px solid var(--ai-line); }
.ai-grid__item { padding: 1.5rem 0 1.75rem; border-bottom: 1px solid var(--ai-line); }
.ai-grid__item .ti { font-size: 1.25rem; color: var(--ai-accent); }
.ai-grid__item h3 { font-size: 1rem; font-weight: 600; margin: 0.6rem 0 0.35rem; }
.ai-grid__item p { color: var(--ai-muted); font-size: 0.9rem; line-height: 1.55; margin: 0; }

/* Examples: vertical tabs with a filling bar on the left, the shot for the active tab on the right. The tallest shot
   sets the height (overlapping grid cells), so nothing jumps and nothing is clipped. */
.ai-showcase { padding: 3rem 0 3.5rem; border-top: 1px solid var(--ai-line); margin-top: 1rem; }
.ai-showcase__grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 3.5rem; align-items: start; }
.ai-showcase__body { color: var(--ai-muted); line-height: 1.6; margin: 0.75rem 0 1.75rem; max-width: 46ch; }
.ai-showcase__tabs { list-style: none; margin: 0; padding: 0; }
.ai-showcase__tab { position: relative; padding: 0.85rem 0 0.85rem 1.25rem; }
.ai-showcase__seg { position: absolute; left: 0; top: 0.85rem; bottom: 0.85rem; width: 3px; background: var(--ai-line); border-radius: 2px; overflow: hidden; }
.ai-showcase__fill { position: absolute; inset: 0; background: var(--ai-accent); transform: scaleY(0); transform-origin: top; }
.ai-showcase__fill.is-running { animation: ai-showcase-progress var(--ai-showcase-duration, 9000ms) linear forwards; }
.ai-showcase.is-paused .ai-showcase__fill.is-running { animation-play-state: paused; }
.ai-showcase.is-manual .ai-showcase__fill.is-running { animation: none; transform: scaleY(1); }
@keyframes ai-showcase-progress { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.ai-showcase__trigger { display: block; width: 100%; text-align: left; border: 0; background: none; padding: 0; font: inherit; font-weight: 600; font-size: 1.05rem; color: var(--ai-muted); cursor: pointer; }
.ai-showcase__tab.is-active .ai-showcase__trigger { color: var(--ai-ink); }
.ai-showcase__trigger:focus-visible { outline: 2px solid var(--ai-accent); outline-offset: 4px; border-radius: 2px; }
.ai-showcase__tab-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s ease; }
.ai-showcase__tab-body > p { overflow: hidden; margin: 0; color: var(--ai-muted); line-height: 1.55; font-size: 0.95rem; }
.ai-showcase__tab.is-active .ai-showcase__tab-body { grid-template-rows: 1fr; }
.ai-showcase__tab.is-active .ai-showcase__tab-body > p { margin-top: 0.4rem; }
.ai-showcase__media { display: grid; }
.ai-shot { grid-area: 1 / 1; margin: 0; align-self: start; visibility: hidden; opacity: 0; transform: translateY(8px); transition: opacity 0.4s ease, transform 0.4s ease, visibility 0s 0.4s; }
.ai-shot.is-active { visibility: visible; opacity: 1; transform: none; transition: opacity 0.4s ease, transform 0.4s ease, visibility 0s; }
.ai-shot figcaption { font-size: 0.75rem; color: var(--ai-muted); margin-top: 0.6rem; }
.ai-mock { background: var(--ai-navy); color: #e8edf3; border-radius: 1rem; padding: 1rem; font-size: 0.82rem; box-shadow: 0 16px 40px rgba(15, 42, 71, 0.25); }
.ai-mock__head { display: flex; align-items: center; gap: 0.4rem; font-weight: 600; margin-bottom: 0.9rem; }
.ai-mock__head .ti { color: #7db4ff; }
.ai-mock__head span { font-weight: 400; font-size: 0.72rem; color: rgba(232, 237, 243, 0.6); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 0.5rem; padding: 0.1rem 0.5rem; margin-left: 0.25rem; }
.ai-mock__me { background: #0f6b4c; color: #fff; border-radius: 0.8rem 0.8rem 0.2rem 0.8rem; padding: 0.5rem 0.75rem; width: fit-content; max-width: 85%; margin-left: auto; margin-bottom: 0.5rem; }
.ai-mock__ai { background: #2a3646; border-radius: 0.8rem 0.8rem 0.8rem 0.2rem; padding: 0.55rem 0.75rem; max-width: 92%; line-height: 1.45; margin-bottom: 0.5rem; }
.ai-mock__ai small, .ai-mock__finding small { display: block; margin-top: 0.5rem; font-size: 0.7rem; color: rgba(232, 237, 243, 0.62); overflow-wrap: anywhere; }
.ai-mock__input { margin-top: 0.75rem; background: #26313f; border-radius: 0.75rem; padding: 0.55rem 0.75rem; color: rgba(232, 237, 243, 0.55); display: flex; justify-content: space-between; align-items: center; }
.ai-mock__input .ti { background: var(--ai-accent); color: #fff; border-radius: 50%; padding: 0.3rem; }
.ai-mock__row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0.25rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1); margin-bottom: 0.75rem; overflow-wrap: anywhere; }
.ai-mock__row .ti { color: #7db4ff; }
.ai-mock__kind { font-size: 0.7rem; color: rgba(232, 237, 243, 0.6); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 0.4rem; padding: 0.05rem 0.4rem; }
.ai-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; display: inline-block; }
.ai-dot--red { background: #d63939; }
.ai-mock__finding { background: #2a3646; border-radius: 0.75rem; padding: 0.7rem 0.85rem; line-height: 1.45; }
.ai-mock__finding b { display: block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; color: #7db4ff; margin-bottom: 0.3rem; }
.ai-mock__steps { list-style: none; margin: 0 0 0.75rem; padding: 0; }
.ai-mock__steps li { display: flex; gap: 0.6rem; padding: 0.45rem 0; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
.ai-mock__steps li:last-child { border-bottom: 0; }
.ai-mock__steps li > span { flex: none; width: 1.3rem; height: 1.3rem; border-radius: 50%; background: #2a3646; color: #7db4ff; font-size: 0.7rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; margin-top: 0.1rem; }
.ai-mock__steps b { display: block; font-weight: 600; font-size: 0.8rem; margin-bottom: 0.1rem; }
.ai-mock__steps em { font-style: normal; color: #7db4ff; }
.ai-mock__steps small { display: block; font-size: 0.68rem; color: rgba(232, 237, 243, 0.55); margin-top: 0.15rem; }
.ai-mock__resolve { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.75rem; background: #0f6b4c; border-radius: 0.75rem; padding: 0.65rem 0.85rem; color: #fff; }
.ai-mock__resolve .ti { font-size: 1.1rem; flex: none; }
.ai-mock__resolve b { display: block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 0.15rem; }
.ai-mock__resolve span { font-size: 0.8rem; line-height: 1.4; }
.ai-mock__resolve em { margin-left: auto; font-style: normal; font-weight: 600; background: #fff; color: #0f6b4c; border-radius: 0.5rem; padding: 0.35rem 0.8rem; flex: none; }
.ai-mock__headline { font-size: 1.15rem; font-weight: 600; margin: 0.25rem 0 0.75rem; }
.ai-mock__figures { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; margin-bottom: 0.75rem; }
.ai-mock__figures div { background: #2a3646; border-radius: 0.6rem; padding: 0.5rem 0.6rem; }
.ai-mock__figures b { display: block; font-size: 1.1rem; font-weight: 600; }
.ai-mock__figures span { font-size: 0.7rem; color: rgba(232, 237, 243, 0.6); }
.ai-mock__consent { background: #2a3646; border-radius: 0.75rem; padding: 0.7rem 0.85rem; margin-bottom: 0.6rem; }
.ai-mock__consent b { display: block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; color: #7db4ff; margin-bottom: 0.45rem; }
.ai-chip { display: inline-block; font-size: 0.72rem; border: 1px solid rgba(255, 255, 255, 0.15); border-radius: 0.4rem; padding: 0.15rem 0.5rem; margin: 0 0.3rem 0.3rem 0; color: rgba(232, 237, 243, 0.6); }
.ai-chip--on { border-color: #2fb344; color: #b8f0c4; }

.ai-cta { background: var(--ai-navy); color: #fff; border-radius: 1.5rem; padding: 2.5rem 2rem; display: flex; align-items: center; justify-content: space-between; gap: 2rem; margin: 1rem 0 2rem; }
.ai-cta .ai-h2 { color: #fff; }
.ai-cta__action { text-align: right; }

/* Dark theme: the navy blocks keep their colour but get an edge; the cards inside the hero go dark too. */
[data-bs-theme="dark"] .ai-hero, [data-bs-theme="dark"] .ai-cta { background: #111e2e; border: 1px solid var(--tblr-border-color); }
[data-bs-theme="dark"] .ai-mock { background: #142132; border: 1px solid rgba(255, 255, 255, 0.12); box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45); }
[data-bs-theme="dark"] .ai-landing { --ai-card: #1b3857; --ai-card-ink: #e8edf3; --ai-card-muted: #bdcbdc; }


@media (max-width: 1200px) and (min-width: 992px) {
  .ai-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ai-grid__item:last-child:nth-child(odd) { grid-column: span 2; }
}
@media (max-width: 991px) {
  .ai-flow__grid { grid-template-columns: 1fr; grid-template-areas: "skill" "updown" "sources" "right" "out"; }
  .ai-flow__right { transform: rotate(90deg); margin-top: 0; }
  .ai-flow__io .ti-arrow-up { display: none; }
  .ai-flow__in--split { grid-template-columns: 1fr; }
  .ai-section__head, .ai-cta { grid-template-columns: 1fr; display: grid; }
  .ai-cta__action { text-align: left; }
  .ai-section__intro { justify-self: start; }
  .ai-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ai-showcase__grid { grid-template-columns: 1fr; gap: 2rem; }
  .ai-shot { display: none; }
  .ai-shot.is-active { display: block; }
}
@media (max-width: 767px) { .ai-grid { grid-template-columns: 1fr; } }
@media (max-width: 575px) {
  .ai-hero { padding: 2rem 1rem; }
  .ai-cta { padding: 1.5rem 1rem; }
  .ai-mock__figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  .ai-shot, .ai-showcase__tab-body, .ai-showcase__fill, .ai-mock__bar-text::after { transition: none !important; animation: none !important; }
  .ai-showcase__tab.is-active .ai-showcase__fill { transform: scaleY(1); }
}
@media print { .ai-hero, .ai-cta, .ai-mock { background: #fff; color: #000; box-shadow: none; } }

/* The Pulse AI result surface on a run page (AI pages redesign, 2026-09-21): a pale azure wash says where the
   output comes from, the text stays the body colour (bg-azure-lt would paint it azure with !important). */
.ai-result { background-color: var(--pulse-ai-wash); border-color: var(--pulse-ai-line); color: var(--tblr-body-color); }
.ai-result .card-header, .ai-result .card-footer { border-color: var(--pulse-ai-line); background: transparent; }

/* Pulse AI's own surfaces (chats read back, 2026-09-22): one ink for what the assistant says about itself, one
   accent for what it answers. Deep Operator Ink is the ground the Ask drawer already stands on, so a
   conversation read on a page looks like the conversation as it happened. */
:root {
  --pulse-ai-bg: #001021;
  --pulse-ai-accent: #1481ba;
  --pulse-ai-accent-hi: #8fc9f0;
  --pulse-ai-wash: #f2f7fd;
  --pulse-ai-line: #cfe0f3;
}
.ai-brand { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--pulse-ai-accent); }
.ai-brand .ti { font-size: 0.95rem; }
.ai-brand__what { font-weight: 400; color: var(--tblr-secondary); }
.ai-summary { background: var(--pulse-ai-bg); border-radius: 6px; padding: 13px 16px; color: #e8edf3; }
.ai-summary .ai-brand { color: var(--pulse-ai-accent-hi); }
.ai-summary .ai-brand__what { color: rgba(232, 237, 243, .62); }
.ai-summary__text { font-size: 13.5px; line-height: 1.5; margin-top: 4px; }

/* The conversation panel reuses the drawer's bubbles, on a page instead of in the dark drawer: the same markup,
   the palette turned around. */
.ai-convo {
  --ask-ai: var(--pulse-ai-wash); --ask-me: var(--pulse-ai-accent); --ask-line: var(--pulse-ai-line);
  --ask-muted: var(--tblr-secondary); --ask-text: var(--tblr-body-color); --ask-primary-hi: var(--tblr-primary);
  display: flow-root; color: var(--ask-text); font-size: 13.5px; line-height: 1.55;
}
.ai-convo .msg { max-width: 80%; margin-bottom: 10px; padding: 10px 14px; }
.ai-convo .msg--ai { border: 1px solid var(--pulse-ai-line); }
.ai-convo .msg--me { max-width: 62%; }
.ai-convo .msg--error { color: var(--tblr-red); }
.ai-convo .msg .markdown code { background: rgba(0, 16, 33, .06); }
.ai-convo .msg__foot { display: flex; gap: 10px; align-items: baseline; font-size: 11.5px; color: var(--tblr-secondary); margin-top: 6px; }
.ai-convo .msg__foot .msg__run { margin-left: auto; }
.ai-convo .msg__ev { font-size: 11.5px; color: var(--tblr-secondary); margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }

/* What was read to answer: one avatar per system or Pulse family, with what it gave and when. */
.ai-sources { display: flex; flex-wrap: wrap; gap: 14px 26px; }
.ai-source { display: flex; align-items: center; gap: 9px; min-width: 210px; }
.ai-source__name { font-size: 12.5px; font-weight: 600; }
.ai-source__note { font-size: 11.5px; color: var(--tblr-secondary); }

/* The library's "Write your own" card: a dashed edge says it is a start, not an item. */
.card.border-dashed { border-style: dashed; }

/* ========================================
   Pulse AI run states (artbook "Run Page States", design D; Ai::RunBadgeComponent, Ai::RunHaloComponent,
   Ai::RunTimelineComponent). The working ring is the Ask pill's (.ask__halo): the same turning rainbow and the same
   green or red filling once around like a clock hand when a run lands while someone watches (.is-fresh).
   ======================================== */
@property --ai-run-angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
@property --ai-run-fill { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
@keyframes ai-run-spin { to { --ai-run-angle: 360deg; } }
@keyframes ai-run-gather { from { --ai-run-fill: 0deg; } to { --ai-run-fill: 360deg; } }
@keyframes ai-run-exhale { 0% { opacity: 0; } 30% { opacity: 0.8; } 100% { opacity: 0; } }
@keyframes ai-run-breathe { 50% { opacity: 0.35; } }
.ai-run-rainbow { background: conic-gradient(from var(--ai-run-angle), #4285f4, #9b72cb, #d96570, #f2a93b, #34a853, #4285f4); }

/* The badge: queued breathes, working turns. */
.ai-run-badge { display: inline-flex; align-items: center; gap: 5px; }
.ai-run-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; animation: ai-run-breathe 1.6s ease-in-out infinite; }
.ai-run-ring { width: 11px; height: 11px; border-radius: 50%; background: conic-gradient(from var(--ai-run-angle), rgba(255, 255, 255, 0.2), #fff);
  -webkit-mask: radial-gradient(circle, transparent 3px, #000 3.5px); mask: radial-gradient(circle, transparent 3px, #000 3.5px);
  animation: ai-run-spin 1s linear infinite; }

/* The halo: a frame whose own background shows 2px around the card, and a blurred copy behind it for the glow. */
.ai-halo { position: relative; isolation: isolate; border-radius: calc(var(--tblr-border-radius, 4px) + 3px); padding: 1px; background: var(--pulse-ai-line); }
.ai-halo > .card { margin-bottom: 0; border: 0; }
.ai-halo::after { content: ""; position: absolute; inset: -4px; border-radius: inherit; z-index: -1; filter: blur(10px); opacity: 0; pointer-events: none; }
.ai-halo.is-queued { padding: 2px; background: #b9c9dd; }
.ai-halo.is-working, .ai-halo.is-working::after {
  background: conic-gradient(from var(--ai-run-angle), #4285f4, #9b72cb, #d96570, #f2a93b, #34a853, #4285f4);
  animation: ai-run-spin 2.4s linear infinite; }
.ai-halo.is-working { padding: 2px; }
.ai-halo.is-working::after { opacity: 0.5; }
.ai-halo.is-fresh { --ai-run-edge: var(--tblr-green, #2fb344); padding: 2px;
  background: conic-gradient(from 0deg, var(--ai-run-edge) var(--ai-run-fill), var(--pulse-ai-line) 0);
  animation: ai-run-gather 1.1s cubic-bezier(0.5, 0, 0.2, 1) both; }
.ai-halo.is-fresh.is-failed { --ai-run-edge: var(--tblr-red, #d63939); }
.ai-halo.is-fresh::after { background: var(--ai-run-edge); animation: ai-run-exhale 1.5s 0.9s ease-out both; }

/* The timeline: one line, a node per stage. */
.ai-tl { list-style: none; margin: 0; padding: 0 0 0 4px; position: relative; }
.ai-tl::before { content: ""; position: absolute; left: 10px; top: 9px; bottom: 9px; width: 2px; background: var(--pulse-ai-line); }
.ai-tl__node { position: relative; display: flex; align-items: flex-start; gap: 12px; padding: 4px 0; }
.ai-tl__dot { position: relative; z-index: 1; flex: none; width: 14px; height: 14px; margin-top: 3px; border-radius: 50%;
  background: var(--tblr-bg-surface, #fff); border: 2px solid var(--pulse-ai-line); display: grid; place-items: center; }
.ai-tl__node.is-done .ai-tl__dot { background: var(--tblr-green, #2fb344); border-color: var(--tblr-green, #2fb344); }
.ai-tl__node.is-done .ai-tl__dot::after { content: ""; width: 4px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0; transform: translateY(-1px) rotate(45deg); }
.ai-tl__node.is-now .ai-tl__dot { border: 0; width: 16px; height: 16px; margin-left: -1px; background: transparent; }
.ai-tl__node.is-now .ai-tl__dot::before { content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from var(--ai-run-angle), #4285f4, #9b72cb, #d96570, #f2a93b, #34a853, #4285f4);
  -webkit-mask: radial-gradient(circle, transparent 4.5px, #000 5px); mask: radial-gradient(circle, transparent 4.5px, #000 5px);
  animation: ai-run-spin 1.2s linear infinite; }
.ai-tl__node.is-wait .ai-tl__dot { border-style: dashed; }
.ai-tl__node.is-fail .ai-tl__dot { background: var(--tblr-red, #d63939); border-color: var(--tblr-red, #d63939); }
.ai-tl__label { color: var(--tblr-secondary); }
.ai-tl__node.is-done .ai-tl__label, .ai-tl__node.is-now .ai-tl__label { color: var(--tblr-body-color); }
.ai-tl__node.is-now .ai-tl__label { font-weight: 500; }
.ai-tl__node.is-fail .ai-tl__label { color: var(--tblr-red, #d63939); }
.ai-tl__label small { color: var(--tblr-secondary); margin-left: 6px; font-variant-numeric: tabular-nums; }
.ai-tl-summary > summary { cursor: pointer; color: var(--tblr-secondary); font-size: 0.8125rem; }
.ai-tl-summary[open] > summary { margin-bottom: 8px; }

@media (prefers-reduced-motion: reduce) {
  .ai-run-dot, .ai-run-ring, .ai-halo, .ai-halo::after, .ai-tl__node.is-now .ai-tl__dot::before { animation: none !important; }
}

/* AI model picker (tomselect renderer "model", artbook "Model Picker", design B): bands per provider under their
   source, one grid row per model - maker, name, tier, weight, residency - and a detail line under the list. */
.ts-dropdown.ai-model-dropdown { min-width: min(620px, 92vw); }
.ai-model-dropdown .optgroup-header { padding: 0; background: transparent; }
.ai-model-source { padding: .6rem .75rem .2rem; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--tblr-secondary); }
.ai-model-band { display: flex; align-items: center; gap: .5rem; margin: .35rem .35rem .15rem; padding: .3rem .6rem; border-radius: 6px; background: var(--tblr-bg-surface-secondary); font-size: 12px; }
.ai-model-band img, .ai-model-band .ti { width: 15px; height: 15px; font-size: 15px; }
.ai-model-band span { color: var(--tblr-secondary); }
.ai-model-row { display: grid; grid-template-columns: 22px minmax(0, 1fr) 76px 88px 72px; align-items: center; column-gap: .5rem; padding-left: .6rem; font-size: 12px; }
.ai-model-row code { background: none; padding: 0; color: var(--tblr-body-color); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-model-avatar { width: 20px; height: 20px; border-radius: 50%; background: var(--tblr-bg-surface-secondary); border: 1px solid var(--tblr-border-color); display: inline-flex; align-items: center; justify-content: center; flex: none; }
.ai-model-avatar img { width: 13px; height: 13px; }
.ai-model-avatar.sm { width: 18px; height: 18px; }
.ai-model-avatar.sm img { width: 11px; height: 11px; }
.ai-model-tier, .ai-model-where { display: inline-flex; align-items: center; gap: .35rem; color: var(--tblr-secondary); }
.ai-model-cost { justify-self: start; }
.ai-model-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 11px; }
.ai-model-bars i { width: 3px; border-radius: 1px; background: var(--tblr-border-color); }
.ai-model-bars i:nth-child(1) { height: 5px; } .ai-model-bars i:nth-child(2) { height: 8px; } .ai-model-bars i:nth-child(3) { height: 11px; }
.ai-model-bars i.on { background: var(--tblr-body-color); }
.ai-flag-eu { position: relative; width: 16px; height: 11px; border-radius: 2px; background: #039; flex: none; }
.ai-flag-eu::after { content: ''; position: absolute; inset: 1.5px 4.5px; border: 1.3px dotted #fc0; border-radius: 50%; }
.ai-model-detail { position: sticky; bottom: 0; padding: .5rem .75rem; border-top: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface); font-size: 12px; color: var(--tblr-secondary); }
.ai-model-row--plain { display: block; padding: .15rem .6rem; font-size: 13px; }
.ts-control .ai-model-avatar + code { background: none; padding: 0; }
.ai-model-head { padding: .1rem .6rem .1rem 1.35rem; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--tblr-secondary); }

/* ---------------------------------------------------------------------------------------------------------------
   Alerts (plan v14 increment 4), from the alerts artbook: the pipeline graph, state dots, priority chips, the run
   strip, the segmented section switch, radio cards and derived values. Prefixed `aa-` so nothing leaks elsewhere.
   --------------------------------------------------------------------------------------------------------------- */
.aa-steps { display: flex; align-items: center; gap: 8px; }
.aa-steps .aa-step-sep { color: var(--tblr-secondary); display: inline-flex; }
.aa-pipe { display: flex; flex-direction: column; gap: 10px; margin-bottom: 1rem; container-type: inline-size; }
/* V8 (alert pipeline strip artbook): one chevron bar; a lit bottom edge while a state holds alerts. */
.aa-gates { position: relative; height: 18px; }
.aa-gate { position: absolute; transform: translateX(-50%); display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.aa-gate-t { font-family: 'Spline Sans Mono', ui-monospace, monospace; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--tblr-secondary); }
.aa-gate-v { font-size: 12px; font-weight: 600; color: #1481ba; }
.aa-gate-v.aa-off { color: #b8480a; }
.aa-chevrons { display: flex; }
.aa-chev { --aa-clip: polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%, 18px 50%); flex: 1 1 0; min-width: 0; margin-left: -12px; padding: 1px; clip-path: var(--aa-clip); background: #e3e8ee; color: var(--tblr-body-color); }
.aa-chev:first-child { --aa-clip: polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%); margin-left: 0; }
.aa-chev:hover { background: var(--tblr-primary); text-decoration: none; color: var(--tblr-body-color); }
.aa-chev:focus-visible { outline: none; background: var(--tblr-primary); }
.aa-chev-in { display: flex; align-items: center; gap: 12px; height: 70px; padding: 0 30px 0 34px; background: var(--tblr-bg-surface); clip-path: var(--aa-clip); box-shadow: inset 0 -4px 0 #e3e8ee; }
.aa-chev:first-child .aa-chev-in { padding-left: 18px; }
.aa-chev.aa-ai .aa-chev-in { background: #eef7fc; }
.aa-chev.aa-lit .aa-chev-in { box-shadow: inset 0 -4px 0 #1481ba; }
.aa-chev.aa-ai.aa-lit .aa-chev-in { box-shadow: inset 0 -4px 0 #11b5e4, inset 0 -10px 12px -8px rgba(17,181,228,.55); }
.aa-chev.aa-busy .aa-chev-in { animation: aa-glow 1.8s ease-in-out infinite; }
@keyframes aa-glow { 50% { box-shadow: inset 0 -4px 0 #11b5e4, inset 0 -14px 16px -8px rgba(17,181,228,.75); } }
@media (prefers-reduced-motion: reduce) { .aa-chev.aa-busy .aa-chev-in { animation: none; } }
.aa-chev-n { font-family: 'Spline Sans Mono', ui-monospace, monospace; font-size: 28px; font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums; }
.aa-chev:not(.aa-lit) .aa-chev-n { color: #9aa7b4; }
.aa-chev-t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.aa-chev-l { font-size: 13px; font-weight: 600; white-space: nowrap; }
.aa-chev.aa-ai .aa-chev-l { color: #0f6a9a; }
.aa-chev-ai { margin-left: 4px; font-family: 'Spline Sans Mono', ui-monospace, monospace; font-size: 10px; letter-spacing: .08em; color: #11b5e4; }
.aa-chev-s { font-size: 11.5px; color: var(--tblr-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Narrow: the states stack, the chevron points down the page. */
@container (max-width: 760px) {
  .aa-gates { display: none; }
  .aa-chevrons { flex-direction: column; gap: 4px; }
  .aa-chev, .aa-chev:first-child { --aa-clip: none; margin-left: 0; border-radius: 6px; }
  .aa-chev-in { height: 52px; padding: 0 16px; border-radius: 5px; }
  .aa-chev:first-child .aa-chev-in { padding-left: 16px; }
}
.aa-ring { display: inline-block; width: 14px; height: 14px; border-radius: 50%; flex: none; background: conic-gradient(from 40deg,#4285f4,#9b72cb,#d96570,#f2a93b,#34a853,#4285f4); -webkit-mask: radial-gradient(circle,transparent 4px,#000 4.5px); mask: radial-gradient(circle,transparent 4px,#000 4.5px); }
.aa-pipe-line { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 12.25px; color: var(--tblr-secondary); }
.aa-st { display: inline-flex; align-items: center; gap: 6px; }
.aa-dot { width: 8px; height: 8px; border-radius: 50%; background: #9ca3af; flex: none; display: inline-block; }
.aa-dot.aa-blue { background: #066fd1; } .aa-dot.aa-green { background: #2fb344; } .aa-dot.aa-red { background: #d63939; }
.aa-dot.aa-hollow { background: transparent; border: 1.5px solid #9ca3af; }
.aa-chip { display: inline-block; padding: 2px 7px; border-radius: 4px; font-size: 11.5px; font-weight: 600; line-height: 16px; white-space: nowrap; }
.aa-chip.aa-red { background: rgba(214,57,57,.1); color: #b42318; }
.aa-chip.aa-orange { background: rgba(247,103,7,.1); color: #b8480a; }
.aa-chip.aa-blue { background: rgba(6,111,209,.1); color: #0a5aa8; }
.aa-chip.aa-grey { background: rgba(107,114,128,.12); color: #4b5563; }
.aa-chip.aa-green { background: rgba(47,179,68,.12); color: #1f7a2e; }
.aa-chip-n { margin-left: 5px; font-family: 'Spline Sans Mono', ui-monospace, monospace; font-weight: 500; }
.aa-segs { display: inline-flex; gap: 2px; padding: 2px; margin-bottom: 1rem; background: #eef0f3; border-radius: 7px; }
.aa-seg { padding: 5px 14px; border-radius: 5px; color: #4b5563; font-weight: 500; font-size: 13px; }
.aa-seg:hover { text-decoration: none; color: #1f2937; }
.aa-seg.aa-on { background: #fff; color: #1f2937; box-shadow: 0 1px 2px rgba(4,32,69,.12); }
.aa-strip { display: flex; gap: 12px; margin-bottom: 1rem; }
.aa-stat { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; padding: 8px 14px; border: 1px solid rgba(4,32,69,.1); border-radius: 6px; background: var(--tblr-bg-surface); color: var(--tblr-body-color); }
a.aa-stat:hover { text-decoration: none; border-color: var(--tblr-primary); color: var(--tblr-body-color); }
.aa-stat .aa-l { font-size: 10.9px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--tblr-secondary); }
.aa-stat .aa-v { font-size: 17.9px; font-weight: 600; line-height: 24px; font-variant-numeric: tabular-nums; }
.aa-stat .aa-v small { font-size: 12.5px; font-weight: 500; color: var(--tblr-secondary); }
.aa-up { font-size: 12.25px; font-weight: 600; text-transform: uppercase; color: var(--tblr-secondary); letter-spacing: .02em; }
.aa-why { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 12.25px; line-height: 17px; color: #4b5563; }
.aa-arrow { display: flex; align-items: center; gap: 12px; margin: 1rem 0 .5rem; }
.aa-runbadge { display: inline-flex; align-items: center; gap: 5px; padding: 2px 7px; border-radius: 4px; background: #066fd1; color: #fff; font-size: 11.5px; font-weight: 600; line-height: 16px; }
.aa-runstrip { list-style: none; margin: 0 0 .75rem; padding: 8px 12px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 0; background: var(--tblr-bg-surface); border: 1px solid rgba(4,32,69,.1); border-radius: 6px; font-size: 12.25px; }
.aa-runstrip li { display: inline-flex; align-items: center; gap: 6px; }
.aa-runstrip li + li::before { content: ""; width: 18px; height: 1.5px; background: #cbd0d6; margin: 0 10px; }
.aa-res p { margin: 8px 0 0; max-width: 820px; }
.aa-res ul { margin: 4px 0 0; padding-left: 20px; max-width: 820px; }
.aa-res .aa-up { margin-top: 14px; display: block; }
.aa-sgs { list-style: none !important; padding: 0 !important; margin: 6px 0 0; display: flex; flex-direction: column; gap: 6px; max-width: 900px; }
.aa-sg-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: #fff; border: 1px solid #cfe0f3; border-radius: 6px; }
details.aa-details { margin-top: 1rem; }
details.aa-details > summary { padding: 9px 16px; font-weight: 600; cursor: pointer; list-style: none; }
details.aa-details > summary::-webkit-details-marker { display: none; }
dl.aa-kv { display: grid; grid-template-columns: 22% 78%; row-gap: 8px; margin: 0; }
dl.aa-kv dt { font-weight: 600; } dl.aa-kv dd { margin: 0; }
.aa-opt { display: flex; align-items: flex-start; gap: 12px; height: 100%; padding: 14px 16px; border: 1px solid var(--tblr-border-color); border-radius: 6px; cursor: pointer; background: var(--tblr-bg-surface); margin: 0; }
.aa-opt:has(input:checked) { border-color: var(--tblr-primary); background: rgba(6,111,209,.04); }
.aa-opt .form-check-input { margin: 2px 0 0; flex: none; float: none; }
.aa-opt .aa-n { display: block; font-weight: 500; }
.aa-opt .aa-h { display: block; font-size: 12.25px; line-height: 17px; color: var(--tblr-secondary); }
.aa-derived { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 6px 10px; border: 1px dashed #d1d5db; border-radius: 6px; background: #f9fafb; }
.aa-derived b { font-weight: 600; white-space: nowrap; }
.aa-derived .aa-dt { margin-left: auto; font-size: 10.4px; letter-spacing: .08em; text-transform: uppercase; color: var(--tblr-primary); font-weight: 600; }
.aa-lines { width: 100%; border-collapse: collapse; table-layout: fixed; }
.aa-lines th { font-size: 11.2px; letter-spacing: .06em; text-transform: uppercase; color: var(--tblr-secondary); font-weight: 600; text-align: left; padding: 0 8px 7px; border-bottom: 1px solid var(--tblr-border-color); }
.aa-lines td { padding: 8px; border-bottom: 1px solid #f0f1f3; vertical-align: middle; }
.aa-lines tr:has(.aa-remove:checked) td { opacity: .45; text-decoration: line-through; }
.aa-icon-btn { display: inline-grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: var(--tblr-secondary); cursor: pointer; }
.aa-icon-btn:hover { background: rgba(6,111,209,.06); color: var(--tblr-primary); }
.aa-icon-btn[disabled] { opacity: .4; cursor: not-allowed; }
.aa-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-height: 36px; padding: 4px 8px; border: 1px solid var(--tblr-border-color); border-radius: 6px; background: var(--tblr-bg-surface); }
.aa-chips .aa-chip-input { flex: 1; min-width: 160px; border: 0; outline: 0; background: transparent; }
@media (max-width: 991px) { .aa-flow, .aa-strip { flex-wrap: wrap; } .aa-node { min-width: 120px; } }
.aa-nav-gear { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 5px; color: rgba(255,255,255,.7); }
.aa-nav-gear:hover { background: rgba(255,255,255,.1); color: rgba(255,255,255,.9); text-decoration: none; }
.aa-stars { display: inline-flex; align-items: center; gap: 2px; border: 0; margin: 0; padding: 0; }
.aa-stars label { position: relative; display: inline-grid; cursor: pointer; color: #8b929c; margin: 0; }
.aa-stars label.aa-on, .aa-stars label:hover { color: #d97706; }
.aa-stars input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.aa-stars input:focus-visible + i { outline: 2px solid var(--tblr-primary); outline-offset: 1px; border-radius: 3px; }
/* A small switch inside a card footer (Data sources › Alerts: the staff Shadow switch). */
.aa-switch-sm { padding-left: 0; min-height: 0; display: inline-flex; }
.aa-switch-sm .form-check-input { width: 1.6rem; height: .9rem; float: none; margin: 0; }
/* AI settings › Models (artbook "Model table", S2): three preset cards over the allowed list with switches. */
.ai-presets { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 1.25rem; container-type: inline-size; }
.ai-preset { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 12px 14px; border: 1px solid var(--tblr-border-color); border-radius: 8px; }
.ai-preset-label { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--tblr-secondary); }
.ai-preset-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; font-size: 12px; }
.ai-allowed-head { margin: 0 0 .25rem; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--tblr-secondary); }
.ai-models-table .ai-band-row td { padding-top: 1rem; border-bottom: 0; }
.ai-models-table code { background: none; padding: 0; color: var(--tblr-body-color); font-size: 12.5px; white-space: nowrap; }
.ai-models-table .form-switch { min-height: 0; }
/* Cost (artbook "Model table", C5): five € signs beside strength and residency, the euros in a callout on hover or focus. */
.ai-models-wrap { overflow: visible; }
.ai-cost { position: relative; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.ai-cost[tabindex] { cursor: help; border-radius: 3px; }
.ai-cost[tabindex]:focus-visible { outline: 2px solid var(--tblr-primary); outline-offset: 3px; }
.ai-cost-signs { display: inline-flex; gap: 1px; font-weight: 700; font-size: 13px; line-height: 1; }
.ai-cost-signs span { color: var(--tblr-border-color); }
.ai-cost-signs span.on { color: var(--tblr-body-color); }
.ai-cost-level { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--tblr-secondary); }
.ai-cost-level .ai-cost-signs { font-size: 12px; }
.ai-cost-pop { display: none; position: absolute; left: 0; top: calc(100% + 8px); z-index: 1070; width: 264px; box-sizing: border-box; padding: 14px 16px; flex-direction: column; gap: 10px; text-align: left; white-space: normal; font-size: 13px; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); border-radius: 8px; box-shadow: 0 10px 28px rgba(16, 32, 48, .14); color: var(--tblr-body-color); }
.ai-preset-facts .ai-cost-pop { left: auto; right: 0; }
.ai-cost:hover .ai-cost-pop, .ai-cost:focus .ai-cost-pop, .ai-cost:focus-within .ai-cost-pop { display: flex; }
.ai-cost-pop-head, .ai-cost-pop-label, .ai-cost-pop-note { display: block; }
.ai-cost-pop-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--tblr-border-color-light, var(--tblr-border-color)); }
.ai-cost-pop-head code { background: none; padding: 0; font-size: 13px; font-weight: 600; color: var(--tblr-body-color); }
.ai-cost-pop-group { display: flex; flex-direction: column; gap: 2px; }
.ai-cost-pop-row { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; line-height: 1.55; }
.ai-cost-pop-row > span:first-child { color: var(--tblr-secondary); }
.ai-cost-pop-row > span:last-child { font-family: 'Spline Sans Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }
.ai-cost-pop-label { font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--tblr-secondary); }
.ai-cost-pop-note { font-size: 11.5px; line-height: 1.4; color: var(--tblr-secondary); }
@media (prefers-reduced-motion: no-preference) { .ai-cost-pop { animation: ai-cost-in .12s ease-out; } }
@keyframes ai-cost-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
@media (max-width: 900px) { .ai-presets { grid-template-columns: 1fr; } }

/* --- Profile › API & MCP (artbook "Profile API & MCP", 2026-09-26) ------------------------------------------------
   One surface, three sections split by hairlines; each heads itself (title, count, one line) instead of the band's
   about column, which squeezed the snippets and tables. */
.access-section { padding: 1.75rem 2rem; display: flex; flex-direction: column; gap: 1rem;
                  border-bottom: 1px solid var(--tblr-border-color); }
.access-section:last-child { border-bottom: 0; }
.access-section__head { display: flex; flex-direction: column; gap: .25rem; }
.access-section__head--row { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: .6rem; }
.access-section__head h2 { margin: 0; font-size: 1.0625rem; font-weight: 600; }
.access-section__head p { margin: 0; color: var(--tblr-secondary); }
.access-section__head--row p { margin-left: .25rem; }
.access-endpoint { display: flex; align-items: center; gap: .6rem; }
.access-endpoint__label { width: 5.5rem; flex: none; font-size: .8125rem; font-weight: 500; color: var(--tblr-secondary); }
.access-endpoint code { flex: 1 1 auto; min-width: 0; padding: .55rem .75rem; background: var(--tblr-bg-surface-secondary);
                        border: 1px solid var(--tblr-border-color); border-radius: 6px; color: var(--tblr-body-color);
                        overflow-x: auto; white-space: nowrap; }
.access-clients { border: 1px solid var(--tblr-border-color); border-radius: 8px; }
/* The client switch is a neutral segmented control: which client is taxonomy, not state (admin-design rule 5). */
.access-seg { display: flex; flex-wrap: wrap; gap: 4px; padding: 6px; background: var(--tblr-bg-surface-tertiary);
              border-bottom: 1px solid var(--tblr-border-color); border-radius: 8px 8px 0 0; }
.access-seg .nav-link { padding: .35rem .75rem; border: 1px solid transparent; border-radius: 6px; font-size: .8125rem;
                        font-weight: 500; color: var(--tblr-secondary); background: transparent; }
.access-seg .nav-link:hover { color: var(--tblr-body-color); }
.access-seg .nav-link.active { background: var(--tblr-bg-surface); border-color: var(--tblr-border-color);
                               color: var(--tblr-body-color); font-weight: 600; box-shadow: 0 1px 2px rgba(16,24,40,.06); }
.access-snippet.active { display: grid; grid-template-columns: minmax(0, 1fr) 18.75rem; }
.access-snippet__code { padding: 1rem 1.1rem; display: flex; flex-direction: column; gap: .6rem;
                        border-right: 1px solid var(--tblr-border-color); min-width: 0; }
.access-snippet__bar { display: flex; justify-content: space-between; align-items: center; font-size: .75rem;
                       color: var(--tblr-secondary); }
.access-snippet__code pre { margin: 0; padding: .85rem 1rem; background: #1b2434; color: #e6edf6; border-radius: 6px;
                            font-size: .8125rem; line-height: 1.6; white-space: pre-wrap; word-break: break-all; min-height: 6rem; }
.access-snippet__steps { margin: 0; padding: 1rem 1.1rem 1rem 2.4rem; display: flex; flex-direction: column; gap: .6rem;
                         line-height: 1.45; }
.access-note { margin: 0; font-size: .8125rem; color: var(--tblr-secondary); }
.access-client { display: flex; align-items: center; gap: .6rem; }
.access-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
/* An action a client may take stands apart from what it may read: amber, not a status. */
.access-chip--act { background: var(--tblr-orange-lt); border-color: rgba(var(--tblr-orange-rgb), .35); color: var(--tblr-orange-darken, #8a5a17); }
.access-token-form { display: grid; grid-template-columns: minmax(0, 1fr) 11.25rem 9.5rem; gap: .6rem; align-items: end;
                     padding: .9rem; background: var(--tblr-bg-surface-secondary); border: 1px solid var(--tblr-border-color);
                     border-radius: 8px; }
.access-token-form .form-label { margin-bottom: .35rem; }
@container detail (max-width: 900px) {
  .access-section { padding: 1.25rem 1rem; }
  .access-snippet.active { grid-template-columns: minmax(0, 1fr); }
  .access-snippet__code { border-right: 0; border-bottom: 1px solid var(--tblr-border-color); }
  .access-token-form { grid-template-columns: minmax(0, 1fr); }
}
.access-reveal { max-width: 35rem; margin: 3rem auto; box-shadow: 0 24px 60px rgba(16,24,40,.12); }
.access-reveal__token { flex: 1 1 auto; min-width: 0; padding: .7rem .75rem; background: #1b2434; color: #e6edf6;
                        border-radius: 6px; word-break: break-all; user-select: all; }
.access-reveal__facts { display: grid; grid-template-columns: 7rem minmax(0, 1fr); row-gap: .5rem; }
.access-reveal__facts dt { font-weight: 400; color: var(--tblr-secondary); }
.access-reveal__facts dd { margin: 0; }

/* Hand-built side menus (Tabler's list-group-transparent, ~13 pages in /app and /partner) wear the same current-item
   pill as the shared detail rail (.detail-rail__item.is-current), so every side menu reads alike (artbook "Profile
   API & MCP", 2026-09-26). Inset instead of edge to edge; a tint of the primary instead of a grey block. */
.list-group-transparent { margin: 0 -.5rem; }
.list-group-transparent .list-group-item { margin: 1px 0; padding: .45rem .5rem; border-radius: 6px; }
.list-group-transparent .list-group-item-action:hover { background: var(--tblr-bg-surface-secondary); }
.list-group-transparent .list-group-item.active { background: rgba(var(--tblr-primary-rgb), .08);
                                                  color: var(--tblr-primary); font-weight: 600; }
.list-group-transparent .list-group-item.active .icon,
.list-group-transparent .list-group-item.active .ti { color: var(--tblr-primary); }

/* The AI balance as the Usage page's headline (artbook "AI balance in euros", E1). */
.ai-balance {
  font-size: 3rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.ai-legend-swatch {
  width: 9px;
  height: 9px;
  border-radius: 2px;
}
.ai-legend-line {
  width: 14px;
  height: 2px;
  background: #475569; /* the running-total line: a slate that reads on both themes */
}

/* Teams Synchronization (artbook S3NBhxuvwsdPTuX6NvhWAU, board 2): "Sync everything" over three vertical parts. */
.sync-switches { max-width: 40rem; }
.sync-switches .form-check { padding-top: .15rem; padding-bottom: .15rem; margin-bottom: 0; min-height: 0; }
.sync-switches .form-check-description { margin-top: 0; line-height: 1.35; font-size: .8rem; color: var(--tblr-secondary); }
/* The parts under the switch's label, no rule between them (artbook 5q4YbWLBxx9LASDgGWPRFL, variant B). */
.sync-switches__all { padding-bottom: .25rem !important; }
.sync-switches__parts { padding-left: 2.5rem; display: grid; gap: .15rem; }
.sync-switches__parts[hidden] { display: none; }
.sync-switches__status { font-size: .75rem; color: var(--tblr-secondary); border-top: 1px solid var(--tblr-border-color-translucent); padding-top: .4rem; margin-top: .4rem; }

/* Applications list: the Global caller ID policy presents this number tenant-wide, so it is marked (board 1). */
.application-global { display: inline-flex; align-items: center; gap: .25rem; font-weight: 600; color: var(--tblr-primary); }

/* Voice routing policy picker (artbook S3NBhxuvwsdPTuX6NvhWAU, board 9): every option one line. */
.vrp-row { display: flex; align-items: center; gap: .5rem; white-space: nowrap; min-width: 0; }
.vrp-row__check { width: 1rem; flex: none; display: inline-flex; color: var(--tblr-green); }
.vrp-row__name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.vrp-row__meta { margin-left: auto; font-size: .75rem; color: var(--tblr-secondary); padding-left: .5rem; }
.vrp-row--item .vrp-row__meta { display: none; }

/* A sheet in the content column of a card-sidebar page gives up its edges: the card is already the surface. */
.card-sidebar-layout .sheet { border: 0; border-radius: 0; }
.card-sidebar-layout .sheet-layout { margin: 0; }

/* Add application: the type as three cards (artbook S3NBhxuvwsdPTuX6NvhWAU, board 8). */
.application-kinds { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }
.application-kind { display: flex; gap: .6rem; align-items: flex-start; border: 1px solid var(--tblr-border-color); border-radius: var(--tblr-border-radius); padding: .6rem .75rem; cursor: pointer; }
.application-kind:has(:checked) { border-color: var(--tblr-primary); background: var(--tblr-primary-lt); }
.application-kind .form-check-input { margin-top: .2rem; flex: none; }
@container sheet (max-width: 820px) { .application-kinds { grid-template-columns: minmax(0, 1fr); } }

/* Teams Policies (artbook PPboaohENPpcWzSzNi5vMt, board C): a policy opens in a side drawer, rendered open by the
   server from ?policy= so a link to it is a link to the drawer. */
.policy-name { display: inline-flex; align-items: center; gap: .25rem; }
.policy-drawer { --tblr-offcanvas-width: 30rem; }
.policy-drawer .offcanvas-header { align-items: flex-start; border-bottom: 1px solid var(--tblr-border-color); }
.policy-drawer .offcanvas-title { font-size: 1.125rem; font-weight: 600; margin: .15rem 0 0; }
.policy-drawer__type { font-size: .7rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); }
.policy-drawer__section { font-size: .875rem; font-weight: 600; margin: 1.5rem 0 .5rem; }
.policy-drawer__actions { display: flex; align-items: center; gap: .5rem; padding: .85rem 1.5rem; border-top: 1px solid var(--tblr-border-color); }
.policy-drawer .sheet-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* ── Call detail: Journey | Quality | Records | Trace (artbook PPboaohENPpcWzSzNi5vMt, page "Call detail") ───── */
.cj-num { font-variant-numeric: tabular-nums; }
.cj-mono { font-family: var(--tblr-font-monospace); font-size: .8rem; word-break: break-all; }
.cj-cap { font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); margin-bottom: .35rem; }

/* Icons: 40px on the spine, 54px in the header, 28px in table heads */
.cj-icon { position: relative; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 40px; height: 40px; border-radius: 11px; background: var(--tblr-bg-surface); box-shadow: inset 0 0 0 1px var(--tblr-border-color); font-size: 1.15rem; color: var(--tblr-secondary); }
.cj-icon--lg { width: 54px; height: 54px; border-radius: 12px; font-size: 1.4rem; }
.cj-icon--sm { width: 28px; height: 28px; border-radius: 7px; font-size: .9rem; }
.cj-icon--sbc { background: #1d273b; box-shadow: none; color: #fff; }
.cj-icon--aa { background: #fff4d6; box-shadow: none; color: #b07d00; }
.cj-icon--cq { background: #eef0fb; box-shadow: none; color: #5b5fc7; }
.cj-icon--person { border-radius: 50%; background: #dbe7f8; box-shadow: none; color: var(--tblr-primary); }
.cj-icon--ended { background: var(--tblr-bg-surface-secondary); box-shadow: none; }
.cj-icon--dashed { background: transparent; box-shadow: none; border: 2px dashed var(--tblr-border-color-dark); }
.cj-icon--dashed .cj-icon__teams { opacity: .45; }
.cj-icon__teams { width: 60%; height: 60%; object-fit: contain; }
.cj-icon__logo { width: 80%; height: 80%; background-size: contain; background-repeat: no-repeat; background-position: center; background-color: transparent; }
.cj-icon__initials { font-size: .75em; font-weight: 700; }
.cj-icon__badge { position: absolute; right: -4px; bottom: -4px; width: 40%; height: 40%; border-radius: 4px; background: var(--tblr-bg-surface); box-shadow: 0 0 0 2px var(--tblr-bg-surface); }

/* Header B3: the two ends meet in the middle, details under the line */
.cj-header { display: flex; justify-content: center; align-items: center; gap: 1.75rem; padding: .5rem 0 1rem; }
.cj-header__end { width: 18.75rem; min-width: 0; }
.cj-header__end--from { text-align: right; }
.cj-header__end--from .cj-header__title { justify-content: flex-end; }
.cj-header__title { display: flex; align-items: center; gap: .5rem; font-size: 1.25rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.cj-header__line { display: flex; align-items: center; }
.cj-header__mid { width: 13.75rem; margin: 0 .875rem; display: flex; flex-direction: column; align-items: center; gap: .4rem; }
.cj-header__connector { display: block; width: 100%; height: 2px; background: var(--tblr-green); position: relative; }
.cj-header__connector::after { content: ''; position: absolute; right: -2px; top: -5px; border: 6px solid transparent; border-left: 9px solid var(--tblr-green); border-right: 0; }
@container (max-width: 900px) { .cj-header { flex-wrap: wrap; } }

/* Journey */
.cj-journey { display: flex; flex-direction: column; gap: 1.25rem; container: cj-journey / inline-size; }
.cj-journey__grid--flow { display: grid; grid-template-columns: 55rem minmax(28.75rem, 1fr); gap: 2rem; align-items: start; }
/* The events keep their fixed ~55rem and the flow takes the rest, at least 28.75rem; narrower, the flow moves under them. */
@container cj-journey (max-width: 1375px) { .cj-journey__grid--flow { grid-template-columns: minmax(0, 1fr); } }
/* Journey at a glance (board JourneyGlance): summary figures, then events on one spine */
.cj-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0; padding: .75rem 0; border-top: 1px solid var(--tblr-border-color-light); border-bottom: 1px solid var(--tblr-border-color-light); }
.cj-summary__cell { padding: 0 1rem; }
.cj-summary__cell + .cj-summary__cell { border-left: 1px solid var(--tblr-border-color-light); }
.cj-summary dt { font-size: .6875rem; font-weight: 400; color: var(--tblr-secondary); }
.cj-summary dd { margin: 0; font-size: 1.0625rem; font-weight: 600; }
.cj-summary__note { font-size: .6875rem; color: var(--tblr-secondary); }
@container cj-journey (max-width: 700px) { .cj-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: .75rem; } .cj-summary__cell:nth-child(3) { border-left: 0; } }
/* Findings: a warning box each, plain words first, the measurement last and quiet */
.cj-findings { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; font-size: .8125rem; align-items: start; }
@container cj-journey (max-width: 900px) { .cj-findings { grid-template-columns: minmax(0, 1fr); } }
.cj-finding { display: flex; gap: .75rem; align-items: flex-start; padding: .75rem 1rem; border-radius: 8px; background: #fff8e6; border: 1px solid #f5d98b; }
.cj-finding__title { font-weight: 600; margin-bottom: .15rem; }
.cj-finding__measured { margin-top: .35rem; font-size: .75rem; color: var(--tblr-secondary); }
.cj-findings__icon { font-size: 1.125rem; line-height: 1.2; }
.cj-findings__icon--fair { color: var(--tblr-orange); }
.cj-findings__icon--poor { color: var(--tblr-red); }
.cj-band { display: inline-flex; align-items: center; gap: .375rem; font-weight: 600; }
.cj-band .cj-dot { width: 9px; height: 9px; }
.cj-events { font-size: .8125rem; }
/* Fixed columns: Lasted and Quality stay beside what happened at any width, never pushed to the far edge. */
.cj-events__row { display: grid; grid-template-columns: 6rem 40px minmax(0, 24rem) 7.5rem 10.625rem; column-gap: .875rem; }
.cj-events--no-quality .cj-events__row { grid-template-columns: 6rem 40px minmax(0, 1fr) 6rem; }
.cj-events--no-quality .cj-events__moment, .cj-events--no-quality .cj-events__offer { grid-column: span 2; }
.cj-events__row--head { padding-bottom: .5rem; border-bottom: 1px solid var(--tblr-border-color-light); font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); }
.cj-events__row--party { padding-top: .875rem; }
.cj-events__spine { display: flex; flex-direction: column; align-items: center; }
.cj-events__spine::after { content: ''; flex-grow: 1; width: 2px; min-height: .5rem; background: var(--tblr-border-color); }
.cj-events li:last-child .cj-events__spine::after { display: none; }
.cj-events__time { padding-top: .125rem; }
.cj-events__row--moment .cj-events__time { padding-top: .25rem; font-size: .75rem; }
.cj-events__moment { grid-column: span 3; padding: .2rem 0 1rem; }
.cj-events__what { padding: .125rem 0 1.125rem; min-width: 0; }
.cj-events__title { font-size: .875rem; }
.cj-events__offer { grid-column: span 3; padding-bottom: 1.125rem; }
.cj-events__quality { display: block; color: inherit; }
.cj-flow__missing { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem; min-height: 12rem; padding: 1.5rem; border: 1px dashed var(--tblr-border-color-dark); border-radius: 10px; text-align: center; font-size: .8125rem; }
.cj-events__quality:hover { text-decoration: none; }
.cj-bullet { display: inline-block; width: 12px; height: 12px; margin: 6px 0; border-radius: 50%; box-shadow: 0 0 0 4px var(--tblr-bg-surface); }
.cj-bullet--start { background: var(--tblr-blue); }
.cj-bullet--ringing { background: var(--tblr-bg-surface); border: 2px solid #8a94a6; }
.cj-bullet--connected { background: var(--tblr-green); }
.cj-bullet--hold { background: var(--tblr-orange); }
.cj-bullet--ended { background: var(--tblr-red); }
@container cj-journey (max-width: 700px) {
  .cj-events__row { grid-template-columns: 4.5rem 40px minmax(0, 1fr); }
  .cj-events__row--party .cj-events__spine { grid-row: span 3; }
  .cj-events__row--party > :nth-child(n+4) { grid-column: 3; }
  .cj-events__row--head > :nth-child(n+4) { display: none; }
}
.cj-offer { display: flex; gap: 1rem; align-items: center; max-width: 47.5rem; margin-top: .6rem; padding: .875rem 1rem; border-radius: 8px; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); }
.cj-offer__text { flex-grow: 1; font-size: .8125rem; }
.cj-flow { display: flex; flex-direction: column; gap: .5rem; }
.cj-flow__head { display: flex; align-items: center; gap: .5rem; font-size: .8125rem; }
.cj-flow__canvas { position: relative; height: 41.25rem; border: 1px solid var(--tblr-border-color); border-radius: 10px; overflow: hidden; background: var(--tblr-bg-surface); }
.cj-flow__draw { width: 100%; height: 100%; }

/* Quality: the steps on a spine, the links between them */
.cj-quality { overflow: hidden; }
.cj-quality__verdict { display: flex; align-items: baseline; gap: .6rem; font-size: .8125rem; margin-bottom: .75rem; }
.cj-quality__row { display: grid; grid-template-columns: minmax(0, 1.3fr) 6.5rem 3.5rem minmax(0, 1fr) 6.5rem 5rem 4.5rem 5.5rem; gap: .6rem; align-items: baseline; padding: .3rem 0; font-size: .8125rem; }
.cj-quality__row + .cj-quality__row { border-top: 1px dashed var(--tblr-border-color-translucent); }
.cj-quality__row--head { grid-template-columns: 3.25rem minmax(0, 1.3fr) 6.5rem 3.5rem minmax(0, 1fr) 6.5rem 5rem 4.5rem 5.5rem; background: var(--tblr-bg-surface-secondary); border-bottom: 1px solid var(--tblr-border-color); padding: .6rem 1.875rem .6rem 1.125rem; font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); }
.cj-quality__node { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); gap: .6rem; align-items: center; padding: .35rem 1.125rem; font-size: .8125rem; }
.cj-quality__spine { display: flex; justify-content: center; }
.cj-quality__link { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); gap: .6rem; padding: 0 1.125rem; }
.cj-quality__bar { justify-self: center; width: 3px; border-radius: 2px; background: var(--tblr-border-color); }
.cj-quality__bar--good { background: var(--tblr-green); }
.cj-quality__bar--fair { background: var(--tblr-orange); }
.cj-quality__bar--poor { background: var(--tblr-red); }
.cj-quality__box { margin: .15rem 0; padding: .35rem .75rem; border-radius: 8px; background: var(--tblr-bg-surface-secondary); }
.cj-quality__note { padding: .2rem 0 .1rem; }
.cj-quality__foot { border-top: 1px solid var(--tblr-border-color); padding: .6rem 1.125rem; margin-top: .5rem; }
.cj-q--good { color: #1e7b34; font-weight: 600; }
.cj-q--fair { color: #b35c00; font-weight: 600; }
.cj-q--poor { color: var(--tblr-red); font-weight: 600; }
.cj-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--tblr-border-color-dark); }
.cj-dot--good { background: var(--tblr-green); }
.cj-dot--fair { background: var(--tblr-orange); }
.cj-dot--poor { background: var(--tblr-red); }
.cj-src { display: inline-block; font-size: .6875rem; font-weight: 600; padding: 0 .4rem; border-radius: 4px; border: 1px solid var(--tblr-border-color); color: var(--tblr-secondary); }
.cj-src--microsoft { color: #5b5fc7; border-color: #c9c9ef; }
.cj-endpoint { margin: .25rem 1.125rem .5rem 4.225rem; padding: .875rem 1rem; border-left: 3px solid #dbe7f8; background: var(--tblr-bg-surface-secondary); border-radius: 0 8px 8px 0; }
.cj-endpoint__head { display: flex; align-items: baseline; gap: .6rem; font-size: .8125rem; margin-bottom: .75rem; }
.cj-endpoint__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }
.cj-endpoint__list { display: grid; grid-template-columns: 6rem minmax(0, 1fr); gap: .3rem .6rem; margin: 0; font-size: .75rem; }
.cj-endpoint__list dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 900px) { .cj-endpoint__grid { grid-template-columns: 1fr; } }

/* Records: the sources side by side */
.cj-ids { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); padding: .875rem 0; margin-bottom: .75rem; border-top: 1px solid var(--tblr-border-color); border-bottom: 1px solid var(--tblr-border-color); }
.cj-ids__item { padding: 0 1rem; min-width: 0; }
.cj-ids__item + .cj-ids__item { border-left: 1px solid var(--tblr-border-color); }
/* The records in call order, one column each; the SBC record takes two half columns, IN and OUT, one per leg. A
   heavier line between records, a light one between the halves; a value both halves share spans them, centred. */
.cj-records__row { display: grid; grid-template-columns: var(--cj-records-columns); padding: 0 1.125rem; font-size: .8125rem; border-top: 1px solid var(--tblr-border-color-translucent); align-items: stretch; }
.cj-records__row > div, .cj-records__row > h3 { min-width: 0; }
.cj-records__label { padding: .45rem .75rem .45rem 0; }
.cj-records__cell { padding: .45rem .75rem; }
.cj-records__cell--record { border-left: 2px solid var(--tblr-border-color); }
.cj-records__cell--half { border-left: 1px solid var(--tblr-border-color-translucent); }
.cj-records__cell--both { grid-column: span 2; }
.cj-records__value.cj-records__cell--both { text-align: center; }
/* One value per cell, on one line: a long id truncates and shows in full on hover, never wraps into a stack. */
.cj-records__value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cj-records__match { display: inline-flex; align-items: center; gap: .2rem; margin-left: .35rem; padding: 0 .35rem; border-radius: 4px; background: var(--tblr-green-lt); color: var(--tblr-green); font-size: .6875rem; }
.cj-records__row--head { border-top: 0; background: var(--tblr-bg-surface-secondary); }
.cj-records__row--head .cj-records__cell { padding-top: .875rem; padding-bottom: .5rem; }
.cj-records__row--legs { background: var(--tblr-bg-surface-secondary); border-bottom: 1px solid var(--tblr-border-color); font-size: .75rem; color: var(--tblr-secondary); }
.cj-records__row--legs .cj-records__cell { padding-top: .3rem; padding-bottom: .4rem; }
.cj-records__source { display: flex; align-items: center; gap: .6rem; }
.cj-records__leg { font-size: .6875rem; font-weight: 600; letter-spacing: .04em; color: var(--tblr-body-color); }
.cj-records__row--note { background: #fffaf0; }
.cj-records__note { grid-column: 2 / -1; font-size: .6875rem; color: #b35c00; padding: 0 .75rem .45rem; }
.cj-records__row--title { border-top: 1px solid var(--tblr-border-color); border-bottom: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface-tertiary, #f6f8fb); }
.cj-records__row--title + .cj-records__row { border-top: 0; }
.cj-records__title { margin: 0; font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.cj-records__title .text-secondary { font-weight: 400; font-size: .75rem; }
.cj-records__session { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; text-decoration: underline dotted; text-underline-offset: 3px; cursor: pointer; }
.cj-session__segment + .cj-session__segment { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--tblr-border-color); }
.cj-session__sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
.cj-session__side { font-weight: 600; margin-bottom: .5rem; }
.cj-session__block { margin-bottom: .75rem; }
.cj-session__fields { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: .15rem .75rem; margin: .25rem 0 0; font-size: .8125rem; }
.cj-session__fields dt { font-weight: 400; color: var(--tblr-secondary); }
.cj-session__fields dd { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cj-session__streams { font-size: .8125rem; caption-side: top; }
.cj-map { position: relative; border: 1px solid var(--tblr-border-color); border-radius: 10px; overflow: hidden; }
.cj-map__canvas { height: 18.75rem; background: #e8eef3; }
.cj-map__legend { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; list-style: none; margin: 0; padding: .6rem .875rem; font-size: .75rem; border-top: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface); }
.cj-map__legend li { display: flex; align-items: center; gap: .4rem; }
.cj-map-pin__dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(29, 39, 59, .35); background: #1d273b; }
/* Timeline (board JourneyGlance): a lane per party on one axis, each session from its own start to its own end */
.cj-timeline { display: flex; flex-direction: column; gap: .35rem; font-size: .75rem; }
.cj-timeline__lane { display: grid; grid-template-columns: 9rem minmax(0, 1fr); column-gap: .875rem; align-items: center; }
.cj-timeline__name { color: var(--tblr-secondary); text-align: right; }
.cj-timeline__track { position: relative; height: 1.375rem; border-radius: 4px; background: var(--tblr-bg-surface-secondary); }
.cj-timeline__bar { position: absolute; top: 0; bottom: 0; border-radius: 4px; overflow: hidden; display: flex; align-items: center; }
.cj-timeline__label { padding: 0 .4rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #1d273b; }
.cj-timeline__bar--ringing { background: var(--tblr-bg-surface); box-shadow: inset 0 0 0 1.5px #8a94a6; }
.cj-timeline__bar--talk { background: #d3f0da; }
.cj-timeline__bar--auto_attendant { background: #fde9b8; }
.cj-timeline__bar--call_queue { background: #dfe0f6; }
.cj-timeline__bar--person { background: #d3f0da; }
.cj-timeline__bar--hold { top: auto; height: 4px; bottom: 0; border-radius: 0 0 4px 4px; background: repeating-linear-gradient(45deg, #f59f00 0 4px, #fcd48a 4px 8px); }
.cj-timeline__bar--hold .cj-timeline__label { display: none; }
.cj-timeline__lane--axis .cj-timeline__track { background: none; height: 2.5rem; border-top: 1px solid var(--tblr-border-color); border-radius: 0; }
.cj-timeline__tick { position: absolute; top: .2rem; transform: translateX(-50%); color: var(--tblr-secondary); font-size: .6875rem; }
.cj-timeline__moment { position: absolute; top: -.45rem; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; }
.cj-timeline__moment .cj-bullet { width: 10px; height: 10px; margin: 0; }
.cj-timeline__moment-label { margin-top: 1.05rem; font-size: .6875rem; color: var(--tblr-secondary); white-space: nowrap; }
.cj-map-pin__dot--number { background: #8a94a6; }
.cj-map-pin__dot--carrier { background: var(--tblr-primary); }
.cj-map-pin__dot--teams_dr { background: #5b5fc7; }
.cj-map-pin__dot--person { background: var(--tblr-green); }
.cj-map-tip { font-size: .6875rem; padding: .1rem .4rem; border-radius: 5px; box-shadow: 0 1px 2px rgba(29, 39, 59, .15); }

/* Voice routing band on Teams General (artbook F5bYXWJ8LanDogz7TsJAqf). */
.voice-routing__gateway code, .voice-routing__fqdn { font-size: .75rem; word-break: break-all; }
/* One row per carrier (boards 5 and 6): On, Carrier, Default; several gateways head their own rows. */
.voice-routing { max-width: 40rem; }
.voice-routing .voice-routing__on { width: 4rem; }
.voice-routing .voice-routing__default-col { width: 15rem; }
.voice-routing tbody td { padding-top: .625rem; padding-bottom: .625rem; }
.voice-routing tr.voice-routing__gw td { background: var(--tblr-bg-surface-secondary); padding: .5rem .75rem; border-top: 1px solid var(--tblr-border-color); }
.voice-routing__sub { font-size: .75rem; color: var(--tblr-secondary); }
/* One line per carrier (artbook AsMTSVx7S2abLsPu2W2Svy): the provider's logo, Provider › carrier. */
.voice-routing__carrier { display: flex; align-items: center; gap: .5rem; min-height: 1.5rem; }
.voice-routing__carrier .avatar { flex: none; }
.voice-routing__sep { color: var(--tblr-secondary); font-size: .8rem; }
/* Alerts on calls (Tenant › Voice): per rule Notify and Investigate; a muted rule is one tag with its X. */
.voice-alerts { max-width: 46rem; }
.voice-alerts td { vertical-align: middle; }
.voice-alerts__note { font-size: .6875rem; color: var(--tblr-secondary); margin-top: .125rem; }
.voice-alerts__muted { display: inline-flex; align-items: center; gap: .375rem; white-space: nowrap; }
.voice-alerts__unmute { border: 0; background: none; padding: 0; color: var(--tblr-secondary); display: inline-flex; cursor: pointer; }
.voice-alerts__unmute:hover { color: var(--tblr-danger); }
.voice-routing__sub.is-warning { color: #8a4200; } /* dark orange: AA on white, unlike Tabler's warning */
[data-bs-theme="dark"] .voice-routing__sub.is-warning { color: #FDBA74; }
.voice-routing__default { display: flex; align-items: center; gap: .625rem; min-height: 1.5rem; }
.voice-routing__default .form-check-input:disabled { cursor: not-allowed; }
.voice-routing__pending { display: inline-flex; align-items: center; gap: .5rem; font-size: .8125rem; color: var(--tblr-secondary); }

/* ========================================
   Live connection: reconnecting
   ======================================== */

/* Bottom-left, away from the flash toasts (bottom-right); quiet, it clears itself. */
.cable-status {
    position: fixed;
    z-index: 9998;
    left: 20px;
    bottom: 20px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid var(--tblr-border-color);
    background: var(--tblr-bg-surface);
    color: var(--tblr-secondary);
    font-size: 12px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.cable-status[hidden] {
    display: none;
}

/* ==========================================================================
   /my - end-user frame (artbook 7v5gHnJkb3xaUETfsoKvJP): dark rail, drawer, full-width main
   ========================================================================== */
.my-frame { display: flex; min-height: 100vh; background: var(--tblr-bg-surface-secondary, #f6f8fb); }
.my-main { flex-grow: 1; min-width: 0; padding: 24px 32px 32px; display: flex; flex-direction: column; gap: 24px; }
/* The rail is Pulse's sidebar shell (SidebarShellComponent, 16 Oct 2026): fixed at --sidebar-width from 1200px, the
   flap collapses it; the main column keeps clear of it as Pulse's .page-wrapper does. */
@media (min-width: 1200px) {
  .my-frame > .my-drawer, .my-frame > .my-main { margin-left: var(--sidebar-width); }
  body.sidebar-collapsed .my-frame > .my-drawer, body.sidebar-collapsed .my-frame > .my-main { margin-left: var(--sidebar-collapsed-width); }
  body.sidebar-transitioning .my-frame > .my-drawer, body.sidebar-transitioning .my-frame > .my-main { transition: margin-left 0.3s ease; }
  body .my-frame > .my-drawer ~ .my-main { margin-left: 0; } /* a page with a drawer: the drawer keeps clear, main follows it */
}
.my-rail .sidebar-nav .my-rail__section { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; text-align: left; gap: 6px; } /* a platform's label with its logo: Tabler stacks and centres a nav item's flex children */
.my-rail__logo { width: 14px; height: 14px; }
.my-rail__count { margin-left: auto; padding-right: 0.75rem; font-size: 12px; opacity: .6; font-variant-numeric: tabular-nums; }
.partner-sidebar.collapsed .my-rail__me > :not(.avatar) { display: none; } /* collapsed: the avatar alone, as Pulse */
.my-rail__me { gap: 10px; }
.my-rail__avatar { background: #dbe7f8; color: var(--tblr-primary); font-weight: 700; flex-shrink: 0; }

.my-drawer { width: 248px; flex-shrink: 0; background: var(--tblr-bg-surface); border-right: 1px solid var(--tblr-border-color); display: flex; flex-direction: column; padding: 18px 12px; gap: 12px; position: sticky; top: 0; height: 100vh; overflow-y: auto; }
.my-drawer__head { display: flex; align-items: center; padding: 0 6px; font-size: 15px; }
.my-drawer__head .text-secondary { margin-left: auto; font-size: 12px; }
.my-drawer__search { display: flex; align-items: center; gap: 8px; border: 1px solid var(--tblr-border-color); border-radius: 7px; padding: 7px 10px; color: var(--tblr-secondary); }
.my-drawer__search input { border: 0; outline: 0; font-size: 13px; width: 100%; background: transparent; }
.my-drawer__list { display: flex; flex-direction: column; gap: 2px; }
.my-q { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 7px; color: var(--tblr-body-color); font-size: 14px; }
.my-q:hover { background: var(--tblr-bg-surface-secondary); color: var(--tblr-body-color); }
.my-q.is-on { background: rgba(var(--tblr-primary-rgb), .1); font-weight: 600; }
.my-q__name { flex-grow: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.my-q__figures { font-size: 12px; font-weight: 400; color: var(--tblr-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }

.my-head { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.my-sub { font-size: 13px; color: var(--tblr-secondary); }
.my-h1 { margin: 4px 0 0; font-size: 22px; font-weight: 600; }
.my-seg { display: inline-flex; border: 1px solid var(--tblr-border-color); border-radius: 7px; overflow: hidden; background: var(--tblr-bg-surface); }
.my-seg a { padding: 6px 12px; font-size: 13px; color: var(--tblr-secondary); border-left: 1px solid var(--tblr-border-color); }
.my-seg a:first-child { border-left: 0; }
.my-seg a.is-on { background: #1d273b; color: #fff; }
.my-tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--tblr-border-color); }
.my-tabs a { padding: 10px 0; color: var(--tblr-secondary); font-size: 14px; }
.my-tabs a.is-on { color: var(--tblr-body-color); font-weight: 600; border-bottom: 2px solid var(--tblr-primary); }

.my-panel { background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); border-radius: 10px; }
.my-panel__head { display: flex; align-items: center; gap: 8px; padding: 14px 20px; border-bottom: 1px solid var(--tblr-border-color-translucent, #e9ecf1); font-size: 14px; font-weight: 600; }
.my-panel__body { padding: 18px 20px; }
.my-legend { font-weight: 400; font-size: 12px; color: var(--tblr-secondary); display: flex; gap: 12px; }
.my-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.my-timeline { display: flex; height: 14px; width: 100%; border-radius: 3px; overflow: hidden; background: var(--tblr-bg-surface-secondary, #f1f3f6); }
.my-dot--answered, .my-bars__answered { background: var(--tblr-green); }
.my-dot--missed, .my-bars__missed { background: var(--tblr-red); }
.my-figure { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.my-label { font-size: 12px; color: var(--tblr-secondary); margin-top: 2px; white-space: nowrap; }
.my-table-wrap { overflow-x: auto; overflow-y: hidden; } /* x alone computes y to auto: a pixel of row overflow drew a vertical scrollbar */
.my-foot { font-size: 12px; color: var(--tblr-secondary); }
.my-empty { padding: 24px 0; }


.my-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: hidden; }
.my-tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.my-meter { display: block; height: 8px; border-radius: 4px; background: var(--tblr-bg-surface-secondary, #e9ecf1); }
.my-meter > span { display: block; height: 8px; border-radius: 4px; }
.my-tile { padding: 18px 20px; border-right: 1px solid var(--tblr-border-color-translucent, #e9ecf1); border-bottom: 1px solid var(--tblr-border-color-translucent, #e9ecf1); }
.my-tile:nth-child(4n) { border-right: 0; }
.my-tiles--3 .my-tile:nth-child(4n) { border-right: 1px solid var(--tblr-border-color-translucent, #e9ecf1); }
.my-tiles--3 .my-tile:nth-child(3n) { border-right: 0; }
.my-tile:nth-child(n+5) { border-bottom: 0; }
.my-tile__value { font-size: 24px; font-weight: 600; font-variant-numeric: tabular-nums; }
.my-tiles--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.my-tiles--6 .my-tile:nth-child(4n) { border-right: 1px solid var(--tblr-border-color-translucent, #e9ecf1); }
.my-tiles--6 .my-tile:nth-child(6n) { border-right: 0; }
.my-tiles--6 .my-tile { border-bottom: 0; }
@media (max-width: 1100px) { .my-tiles--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.my-grid { display: grid; gap: 24px; }
.my-grid--2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.my-grid--1-1 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.my-bars { display: flex; align-items: flex-end; gap: 4px; height: 200px; padding: 18px 20px; }
.my-bars--week { gap: 18px; }
.my-bars__col { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.my-bars__stack { flex-grow: 1; width: 100%; max-width: 46px; display: flex; flex-direction: column; justify-content: flex-end; }
.my-bars__missed { border-radius: 3px 3px 0 0; }
.my-bars__label { font-size: 11px; color: var(--tblr-secondary); height: 14px; font-variant-numeric: tabular-nums; }
.my-donut { padding: 20px; display: flex; align-items: center; gap: 20px; }
.my-donut__legend { display: flex; flex-direction: column; gap: 8px; font-size: 13px; }
.my-table { width: 100%; border-collapse: collapse; }
.my-table th, .my-table td { padding: 10px 12px; font-size: 13px; border-top: 1px solid var(--tblr-border-color-translucent, #e9ecf1); white-space: nowrap; font-variant-numeric: tabular-nums; }
.my-table th { border-top: 0; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); }
.my-avatar { width: 24px; height: 24px; border-radius: 50%; background: #dbe7f8; color: var(--tblr-primary); font-size: 10px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; margin-right: 8px; }
.my-sources { padding: 20px; display: flex; flex-direction: column; gap: 14px; font-size: 13px; }
.my-source { display: flex; flex-direction: column; gap: 4px; }
.my-source__bar { height: 8px; border-radius: 4px; background: var(--tblr-border-color); display: block; }
.my-source__bar span { display: block; height: 8px; border-radius: 4px; background: var(--tblr-primary); }
.my-line { width: 100%; height: 160px; display: block; }
.my-line__value { fill: none; stroke: var(--tblr-primary); stroke-width: 2; vector-effect: non-scaling-stroke; }
.my-line__target { stroke: var(--tblr-secondary); stroke-dasharray: 4 4; vector-effect: non-scaling-stroke; }


@media (max-width: 1100px) {
  .my-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .my-grid--2-1, .my-grid--1-1 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  .my-frame { flex-direction: column; }
  .my-drawer { width: auto; height: auto; position: static !important; }
  .my-main { padding: 16px; }
  .my-cards { grid-template-columns: minmax(0, 1fr); }
  .my-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .my-tile:nth-child(n) { border-right: 1px solid var(--tblr-border-color-translucent, #e9ecf1); border-bottom: 1px solid var(--tblr-border-color-translucent, #e9ecf1); }
}
.my-filterbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.my-filterbar__form { display: flex; align-items: center; gap: 6px; }
.my-filterbar__form .form-select { width: auto; }
/* One call per row, on one line (artbook board 18): fixed columns, long names end in an ellipsis, the full text on hover. */
.my-table--one-line { table-layout: fixed; }
.my-table--one-line td { overflow: hidden; text-overflow: ellipsis; }
.my-filterbar__search { width: 160px; }
@media (max-width: 1100px) { .my-call-detail { grid-template-columns: 1fr; } }
.my-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); font-size: 13px; }
.my-chip a { color: var(--tblr-secondary); }
.my-result--answered { background: var(--tblr-green); }
.my-result--abandoned { background: var(--tblr-red); }
.my-result--late { background: var(--tblr-orange); }
.my-result--unknown { background: var(--tblr-secondary); }
.my-result--again { background: var(--tblr-blue); }
/* The queues a call went through (rule 12): a badge each, green answered, red not, grey unknown, › between. */
.my-queue-badges { display: inline-flex; align-items: center; flex-wrap: nowrap; max-width: 100%; overflow: hidden; }
.my-queue-badge { font-size: 12px; line-height: 1.5; padding: 0 7px; border-radius: 4px; border: 1px solid; background: var(--tblr-bg-surface); white-space: nowrap; }
.my-queue-badge--answered { border-color: var(--tblr-green); color: #2b8a3e; }
.my-queue-badge--not-answered { border-color: var(--tblr-red); color: #c92a2a; }
.my-queue-badge--unknown { border-color: var(--tblr-border-color); color: var(--tblr-secondary); }
.my-queue-badges__sep { color: var(--tblr-secondary); margin: 0 4px; }
/* Call as an icon beside View (rule 9): square, the height of View. */
.my-actions .btn-icon { padding: 0 7px; min-width: 30px; height: 26px; display: inline-flex; align-items: center; justify-content: center; }
/* Now: what happened after a call that was not answered (board 30); a call Teams reports later says when. */
.my-now__hint { font-size: 12px; color: var(--tblr-secondary); margin-left: 15px; line-height: 1.2; }
/* How far behind Teams is, at the foot of a table of calls (rule 3's one exception). */
.my-pager__note { display: inline-flex; align-items: center; gap: 6px; }
.my-pager__note::before { content: '·'; color: var(--tblr-border-color-dark, #c9d1db); margin-right: 2px; }
.my-pager { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--tblr-border-color-translucent, #e9ecf1); font-size: 13px; }
a.my-tile, a.my-tile:hover { color: inherit; display: block; }
a.my-tile:hover { background: var(--tblr-bg-surface-secondary); }
.my-legend-link, .my-legend-link:hover { color: inherit; }

/* /my v2 (artbook 1tMapW4NTchr2e8yQg8yFF): Pulse's tiles (shared/widgets/_tile) and cards, small boxes in grids. */
.my-grid4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.my-grid4 > .card { margin: 0; }
.my-grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.my-grid3 > .card { margin: 0; }
.my-card { margin: 0; min-width: 0; }
.my-card__head { display: flex; align-items: flex-start; gap: 12px; padding: 14px 20px 12px; }
.my-card__title { font-size: 16px; font-weight: 600; }
.my-card__sub { font-size: 13px; color: var(--tblr-secondary); margin-top: 2px; }
.my-card__meta { margin-left: auto; display: flex; gap: 14px; align-items: center; font-size: 13px; color: var(--tblr-secondary); white-space: nowrap; }
.my-card__meta .my-legend { gap: 14px; }
.my-card__empty { padding: 4px 20px 18px; font-size: 13px; }
.my-card--empty { align-items: center; justify-content: center; text-align: center; gap: 10px; padding: 72px 24px; }
.my-card--empty > .ti { font-size: 40px; color: var(--tblr-secondary); }
.my-card .my-bars { padding: 6px 20px 16px; }
.my-card .my-donut { padding: 4px 20px 18px; }
.my-bars__stack { position: relative; }
.my-bars__peak { position: absolute; left: 50%; transform: translate(-50%, -4px); font-size: 11px; font-weight: 600; white-space: nowrap; color: var(--tblr-body-color); }
.my-donut__ring { position: relative; flex: none; }
.my-donut__center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.my-donut__center strong { font-size: 20px; font-weight: 600; }
.my-donut__center span { font-size: 11px; color: var(--tblr-secondary); }
.my-donut__legend { flex-grow: 1; min-width: 0; gap: 9px; }
.my-donut__legend .my-legend-link { display: flex; align-items: center; gap: 8px; }
.my-donut__count { margin-left: auto; color: var(--tblr-secondary); font-variant-numeric: tabular-nums; }
.my-table--fixed { table-layout: fixed; }
.my-table--fixed th, .my-table--fixed td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.my-table--fixed td { height: 40px; font-size: 13px; }
.my-grid4 .dash-tile .card-body { padding-bottom: 46px; }
.my-table--fixed th, .my-table--fixed td { padding-left: 10px; padding-right: 10px; }
.my-table--fixed th:first-child, .my-table--fixed td:first-child { padding-left: 20px; }
.my-table--fixed th:last-child, .my-table--fixed td:last-child { padding-right: 20px; }
.my-table--fixed td.my-actions { overflow: visible; }
.my-strong-link, .my-strong-link:hover { color: var(--tblr-body-color); font-weight: 500; }
/* An agent's picture and name, the name on the picture's middle (the Agents panel, the Agents report). */
.my-agent-name { display: inline-flex; align-items: center; max-width: 100%; vertical-align: middle; }
/* A queue's agents behind each other on Home: the status bullet on each, dimmed when not taking this queue's calls. */
.my-agent-stack { display: inline-flex; align-items: center; vertical-align: middle; }
.my-agent-stack__item { display: inline-flex; }
.my-agent-stack__item .avatar { margin-right: 0 !important; box-shadow: 0 0 0 2px var(--tblr-bg-surface); }
.my-agent-stack__item + .my-agent-stack__item { margin-left: -.45rem; }
.my-agent-stack__item.is-out .avatar { opacity: .45; filter: grayscale(1); }
.my-agent-stack__more { margin-left: .5rem; font-size: .8125rem; color: var(--tblr-secondary); white-space: nowrap; }
.my-bullet { display: flex; align-items: center; gap: 10px; }
.my-bullet__bar { position: relative; flex-grow: 1; max-width: 120px; height: 8px; border-radius: 4px; background: var(--tblr-bg-surface-tertiary, #eef1f5); }
.my-bullet__fill { position: absolute; inset: 0 auto 0 0; border-radius: 4px; background: var(--tblr-green); }
.my-bullet__goal { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--tblr-body-color); }
.my-bullet.is-below .my-bullet__fill { background: var(--tblr-orange); }
.my-bullet__value { min-width: 38px; text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.my-bullet.is-below .my-bullet__value { color: #b35309; }
.my-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.my-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border: 1px solid var(--tblr-border-color); border-radius: 999px; background: var(--tblr-bg-surface); font-size: 13px; color: var(--tblr-body-color); }
.my-chip:hover { color: var(--tblr-body-color); border-color: var(--tblr-secondary); }
.my-card .my-pager { padding: 12px 20px; }
/* A call (board 6, Pulse's Journey unboxed): the call on one line, its figures, the story beside its call flow. */
.my-b3 { display: flex; justify-content: center; align-items: center; gap: 28px; padding: 8px 0 18px; }
.my-b3__party { width: 300px; min-width: 0; }
.my-b3__party--from { text-align: right; }
.my-b3__name { font-size: 20px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.my-b3__role { font-size: 13px; color: var(--tblr-secondary); margin-top: 2px; }
.my-b3__line { position: relative; width: 220px; display: flex; align-items: center; --line: var(--tblr-red); }
.my-b3__line--good { --line: var(--tblr-green); }
.my-b3__line--unknown { --line: var(--tblr-secondary); }
.my-b3__rule { flex-grow: 1; height: 2px; background: var(--line); }
.my-b3__line::after { content: ''; border: 6px solid transparent; border-left: 9px solid var(--line); border-right: 0; }
.my-b3__duration { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.my-b3__meta { position: absolute; left: 50%; top: 12px; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 5px; white-space: nowrap; font-size: 12px; }
.my-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--tblr-border-color); border-bottom: 1px solid var(--tblr-border-color); }
.my-kpis > div { padding: 10px 16px; min-width: 0; }
.my-kpis > div + div { border-left: 1px solid var(--tblr-border-color); }
.my-kpis__value { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }
.my-kpis__hint { font-size: 12px; color: var(--tblr-secondary); }
.my-call { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 2rem; align-items: start; }
.my-history { display: flex; flex-direction: column; gap: 6px; margin-top: 18px; font-size: 13px; }
.my-history__row, .my-history__row:hover { display: flex; align-items: center; gap: 8px; color: var(--tblr-body-color); }
.my-call__flow-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; font-size: 13px; }
.my-call__flow-head strong { font-size: 14px; }
.my-call__canvas { position: relative; height: 560px; border-radius: 8px; overflow: hidden; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); }
.my-call__canvas--empty { display: flex; align-items: center; justify-content: center; height: 160px; }
.my-call__draw { width: 100%; height: 100%; }
.my-qcard { margin: 0; padding: 16px 18px; gap: 12px; color: var(--tblr-body-color); overflow: hidden; }
.my-qcard:hover { color: var(--tblr-body-color); border-color: var(--tblr-primary); }
.my-qcard__head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.my-qcard__name { font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.my-qcard__agents { margin-left: auto; font-size: 12px; color: var(--tblr-secondary); white-space: nowrap; }
.my-qcard .my-bullet__bar { max-width: none; }
.my-qcard__note { font-size: 12px; color: var(--tblr-secondary); margin-top: 4px; }
.my-qcard__figures { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; font-size: 12px; color: var(--tblr-secondary); }
.my-qcard__figures strong { display: block; font-size: 18px; font-weight: 600; color: var(--tblr-body-color); font-variant-numeric: tabular-nums; }
.my-qcard__figures strong.text-red { color: var(--tblr-red); }
.my-qcard__spark { height: 36px; opacity: .55; }
.my-chip-state { display: inline-block; padding: 1px 8px; border-radius: 4px; font-size: 12px; font-weight: 600; background: #eef1f5; color: #3d4a5c; }
.my-chip-state--in, .my-chip-state--available { background: #e3f3e6; color: #1b6e2f; }
.my-chip-state--busy { background: #fbe6e6; color: #9b2222; }
.my-chip-state--away { background: #fdecd9; color: #8a4200; }
.my-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--tblr-secondary); margin-top: 8px; }
.my-card__body { padding: 4px 20px 18px; }
.my-rows { display: flex; flex-direction: column; }
.my-row { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--tblr-border-color-translucent, #f0f2f5); font-size: 14px; }
.my-row:last-child { border-bottom: 0; }
.my-row__label { color: var(--tblr-secondary); }
.my-row__control { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.my-select { display: inline-flex; align-items: center; gap: 8px; width: auto; min-width: 220px; max-width: 100%; background-color: var(--tblr-bg-surface-secondary); color: var(--tblr-body-color); cursor: default; }
.my-input-short { width: 70px; }
.my-route { display: inline-flex; width: auto; min-width: 160px; background: var(--tblr-bg-surface-secondary); }
.my-people { list-style: none; margin: 8px 0 0; padding: 0; }
.my-people li { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--tblr-border-color-translucent, #f0f2f5); font-size: 14px; }
.my-people li:last-child { border-bottom: 0; }
.my-people__logo { width: 16px; height: 16px; flex: none; }
.my-section__teams { display: inline-flex; align-items: center; gap: 6px; }
.my-chip-state--out { background: #eef1f5; color: #3d4a5c; }
.my-row--top { align-items: start; }
.my-row--top .my-row__label { padding-top: 2px; }
.my-row__stack { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.my-recipients { max-width: 520px; }
.my-card__foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 20px; border-top: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface-secondary); }
.my-card fieldset { min-width: 0; }
.my-settings-v2 { padding-top: 16px; }
.my-settings-v2 > .my-card__title { margin: 14px 0 4px; }
.my-settings-v2 > .my-card__title:first-of-type { margin-top: 0; }
.my-input-num { width: 80px; }
.my-synced { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; color: var(--tblr-green); }
/* The call-flow visualizer's toolbar (shared/_call_flow_toolbar), over the canvas's top left. */
.cf-toolbar { position: absolute; top: 12px; left: 12px; z-index: 5; display: inline-flex; align-items: center; gap: 10px; padding: 6px 10px; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); border-radius: 6px; box-shadow: 0 1px 2px rgba(0, 0, 0, .05); font-size: 13px; }
.cf-toolbar__label { color: var(--tblr-secondary); }
.cf-toolbar__dir { padding: 2px 8px; }
.cf-toolbar__dir[aria-pressed="true"] { background: var(--tblr-dark, #1d273b); border-color: var(--tblr-dark, #1d273b); color: #fff; }
.my-qcard__icon { width: 26px; height: 26px; border-radius: 7px; background: #EF4444; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.my-flow__canvas--roads { height: 400px; border-radius: 8px; border: 1px solid var(--tblr-border-color); }
.my-bars__ended { background: var(--tblr-secondary); border-radius: 3px 3px 0 0; }
.my-bullet--rate .my-bullet__fill { background: var(--tblr-primary); }
.my-head__tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.my-table__total td { font-weight: 600; }
.my-report-card { margin: 0; padding: 16px 18px; gap: 8px; }
.my-report-card__head { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 600; }
.my-report-card__icon { width: 30px; height: 30px; border-radius: 7px; background: var(--tblr-primary); color: #fff; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.my-report-card__text { font-size: 13px; color: var(--tblr-secondary); }
.my-report-card__actions { display: flex; gap: 8px; margin-top: 4px; }
.my-dests { display: flex; flex-direction: column; gap: 12px; }
.my-dests__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; align-items: center; font-size: 13px; color: var(--tblr-body-color); }
.my-dests__bar { grid-column: 1 / -1; height: 6px; background: var(--tblr-bg-surface-tertiary, #eef1f5); border-radius: 3px; overflow: hidden; }
.my-dests__bar > span { display: block; height: 100%; background: var(--tblr-primary); }
.my-select-field { width: auto; min-width: 220px; }
/* A call flow's route (shared/call_flow/controls/_route): the text box only for text to speech, the menu prompt and keys
   only when Then is Menu. Tom Select keeps the real select's option selected, so :has() follows the choice. */
.cf-prompt__text { display: none; }
.cf-prompt:has(.cf-prompt__kind option[value="tts"]:checked) .cf-prompt__text { display: block; }
.cf-prompt__library { display: none; }
.cf-prompt:has(.cf-prompt__kind option[value="library"]:checked) .cf-prompt__library { display: flex; }
.cf-route__menu { display: none; }
.cf-route:has(.cf-route__then option[value="menu"]:checked) .cf-route__menu { display: block; }
.cf-keys td:first-child { width: 48px; font-weight: 600; }
/* A queue's agents come from people and groups, or from a team's channel: the rows of the other choice fold away */
.cf-agents:has(.cf-agents__from option[value="channel"]:checked) .cf-agents__people { display: none; }
.cf-agents:not(:has(.cf-agents__from option[value="channel"]:checked)) .cf-agents__channel { display: none; }
.cf-agents:has(.cf-agents__from option[value="shifts"]:checked) .cf-agents__people { display: none; }
.cf-agents:not(:has(.cf-agents__from option[value="shifts"]:checked)) .cf-agents__shifts { display: none; }
/* The key chip on the node a menu key reaches (board 15) */
.cf-keychip { min-width: 18px; height: 18px; padding: 0 4px; border-radius: 5px; background: #eaf1fa; color: #206bc4; font-weight: 700; font-size: 11px;
  display: inline-flex; align-items: center; justify-content: center; border: 2px solid #fff; box-sizing: border-box; white-space: nowrap; cursor: pointer; }
/* The swap on a link (board 13): shown while the map is hovered, so a quiet map stays quiet */
/* A menu's ports: the key on a chip at the node's edge, the link leaving from it (owner, 15 Oct 2026) */
.cf-port { position: relative; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 6px; background: #eaf1fa; color: #206bc4; font-weight: 700; font-size: 11px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.cf-port--add { background: #fff; border: 1.5px dashed #8a97aa; color: #5c6b80; }
.cf-port:hover { background: #d7e5f7; }
.cf-port--missing { background: #fff4e0; border: 1.5px dashed #f59f00; color: #8a4200; } /* its target is gone from Teams: choose a new one */
/* A queue's agents card: a grid of people, three to a row (owner, 15 Oct 2026) */
.cf-agents-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 2px 8px 8px; }
.cf-agent { display: inline-flex; align-items: center; gap: 5px; min-width: 0; height: 26px; padding: 0 6px 0 3px; border-radius: 13px; border: 1.5px solid transparent; background: #f3f5f8; font-size: 11px; color: #1d273b; box-sizing: border-box; transition: border-color .2s, background .2s; }
.cf-agent__avatar { width: 20px; height: 20px; border-radius: 50%; background: #22C55E; color: #fff; font-size: 9px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.cf-agent__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cf-agent.is-ringing { border-color: #8fd9a3; background: #f0faf2; } /* ringing: a soft green border on the whole chip */
.cf-agent--more { justify-content: center; color: #5c6b80; }
.cf-agent--add { justify-content: center; background: #fff; border: 1.5px dashed #8a97aa; color: #5c6b80; font-weight: 600; cursor: pointer; }
.cf-agent--add:hover { border-color: #206bc4; color: #206bc4; }
/* A reference to an element drawn elsewhere: a pill in the lane; click pans there */
.cf-ref { position: relative; display: inline-flex; align-items: center; gap: 5px; max-width: 170px; height: 28px; padding: 0 10px; border-radius: 14px; border: 1px solid #c9d1db; background: #fff; color: #1d273b; font-size: 11px; font-weight: 500; cursor: pointer; box-sizing: border-box; }
.cf-ref:hover { border-color: #206bc4; color: #206bc4; }
.cf-swap { width: 22px; height: 22px; border-radius: 50%; border: 1px solid #c9d1db; background: #fff; color: #206bc4; font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; opacity: 0; transition: opacity .15s; }
.react-flow:hover .cf-swap, .cf-swap:focus-visible { opacity: 1; }
.cf-swap--node { position: absolute; top: -8px; left: -8px; z-index: 2; }
/* A group is a frame, not a target: clicks inside it reach the links and nodes it holds (links are drawn under nodes) */
.react-flow__node-group { pointer-events: none; }
.cf-note { flex-basis: 100%; margin-top: .25rem; }
/* The row the map opened (board 13): lit until the next click */
.my-row.is-lit, tr.is-lit > td { background: rgba(var(--tblr-primary-rgb), .08); }
.my-row.is-lit { margin: 0 -12px; padding-left: 12px; padding-right: 12px; border-radius: 4px; }
.cf-key__announcement { display: none; }
.cf-keys__add { width: auto; display: inline-block; margin-top: .5rem; }
.cf-key:has(select option[value="announcement"]:checked) .cf-key__announcement { display: block; }
.my-call-routes { display: flex; flex-direction: column; gap: 18px; }
/* Call routes' canvas (app/voice/_call_routes_canvas), /app and /my: a white rounded box, the diagram's grey dots on it. */
.call-routes-canvas { position: relative; height: calc(100vh - 210px); min-height: 560px; border-radius: 10px; border: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface, #fff); overflow: hidden; }
.my-call-routes .call-routes-canvas { height: calc(100vh - 150px); }
/* "Show all" to Call routes over a topology chart's top right, taking no height of its own. */
.call-routes-more { position: relative; z-index: 10; height: 0; display: flex; justify-content: flex-end; align-items: flex-start; }
.call-routes-more > a { margin-top: .75rem; }
.call-routes-highlight { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; margin: 0; }
.call-routes-highlight .form-select { min-width: 220px; }
/* Voice's tabs right under the page header, the first tab's icon in line with the title. */
.voice-tabs > header { margin-top: 0 !important; }
.voice-tabs .navbar-nav { margin-left: calc(-1 * var(--tblr-navbar-nav-link-padding-x, .75rem)); }
/* A scheduled report on the worksheet (board 24): a lone sheet keeps its width; the schedule table in the band, each
   cadence a row with its own time, days and data, the unchosen rows disabled and muted. */
.my-sheet { max-width: 1160px; }
.my-sheet fieldset { min-width: 0; }
.my-sheet legend { float: none; width: auto; font-size: .875rem; margin-bottom: .5rem; }
.my-choices { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; padding: 10px 12px; border: 1px solid var(--tblr-border-color); border-radius: var(--tblr-border-radius); background: var(--tblr-bg-surface-secondary); }
.my-schedule { width: 100%; border-collapse: collapse; font-size: 13px; }
.my-schedule th { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); padding: 0 10px 8px 0; text-align: left; border-bottom: 1px solid var(--tblr-border-color); }
.my-schedule td { padding: 8px 10px 8px 0; border-bottom: 1px solid var(--tblr-border-color-translucent, #f0f2f5); white-space: nowrap; }
.my-schedule tr:last-child td { border-bottom: 0; }
.my-schedule tr.is-off .form-check-label, .my-schedule tr.is-off td { color: var(--tblr-secondary); }
.my-schedule__at { display: inline-flex; align-items: center; gap: 6px; }
.my-schedule .form-select-sm { width: auto; }
.my-skeleton { background: var(--tblr-bg-surface-tertiary, #eef1f5); border-radius: 4px; }
.my-skeleton--value { height: 26px; width: 60%; margin-top: 8px; }
.my-skeleton--hint { height: 12px; width: 40%; margin-top: 8px; }
@media (max-width: 1100px) { .my-grid4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
a.my-source, a.my-source:hover { color: inherit; }
a.my-bars__col:hover .my-bars__stack { opacity: .8; }
.my-figures { display: flex; flex-direction: column; gap: 24px; }
.my-note { font-size: 13px; color: var(--tblr-secondary); display: flex; align-items: center; gap: 6px; }
.my-seg span.is-disabled { padding: 6px 12px; font-size: 13px; color: var(--tblr-border-color-dark, #c8d0da); border-left: 1px solid var(--tblr-border-color); cursor: not-allowed; }
.my-viewas__form { display: flex; gap: 8px; max-width: 520px; }
.my-rail__menu-button { color: var(--sidebar-color); }
.my-rail__menu-button:hover { color: var(--sidebar-color-hover); }
/* /my call flow: canvas, then the sections working down (artbook boards 6, 7) */
.my-flow { display: flex; flex-direction: column; gap: 16px; position: relative; }
/* The sheet (board 17; owner 15 Oct 2026: centred over the flow like a pop-up, not docked): one element's tabs */
.cf-sheet { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(1080px, calc(100% - 48px)); height: min(780px, calc(100% - 48px)); /* one height for every tab (owner, 15 Oct 2026) */
  overflow: auto; z-index: 6; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); border-radius: 8px;
  box-shadow: 0 16px 48px rgba(29, 39, 59, .18); }
.cf-sheet .my-section { border: 0; border-radius: 0; height: 100%; display: flex; flex-direction: column; }
.cf-sheet .my-section::details-content, /* Chrome wraps a details' content in this pseudo-element */
.cf-sheet .my-section > form, .cf-sheet .my-section > turbo-frame, .cf-sheet .my-section > turbo-frame > form { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.cf-sheet .my-section__body { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr); } /* the pane scrolls, the foot with Save stays put */
.cf-sheet .my-section__pane, .cf-sheet .my-section__rail { overflow: auto; }
.cf-sheet .my-section__caret { display: none; }
.cf-sheet .my-section__head { cursor: move; }
/* The routing tabs as a timeline in the rail: a heading, numbered steps joined by a line */
/* The routing tabs branch off Phone numbers (|- each item): a trunk down the left, a tick into each item */
.my-section__tab--branch { position: relative; margin-left: 28px; }
.my-section__tab--branch::before { content: ''; position: absolute; left: -16px; top: -4px; bottom: -4px; border-left: 2px solid var(--tblr-border-color); }
.my-section__tab--branch::after { content: ''; position: absolute; left: -16px; top: 50%; width: 12px; border-top: 2px solid var(--tblr-border-color); }
.my-section__tab--last::before { bottom: 50%; }
.my-subhead { font-size: 13px; font-weight: 600; color: var(--tblr-secondary); text-transform: uppercase; letter-spacing: .04em; margin: 1rem 0 .5rem; }
.cf-sheet .my-section__state { flex: 1; display: flex; justify-content: center; }
.cf-sheet .my-section__tools { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.cf-sheet .my-section__tools .btn-icon { width: 2rem; height: 2rem; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.cf-sheet .my-section__teams-logo { width: 16px; height: 16px; object-fit: contain; }
.my-flow__canvas.call-flow-fullscreen ~ .cf-sheet { position: fixed; z-index: 1051; }
/* The gear at a block's top right (board 17) */
.cf-gear { position: absolute; top: -8px; right: -8px; width: 22px; height: 22px; border-radius: 50%; background: #fff; border: 1px solid #c9d1db; color: #5c6b80;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; font-size: 12px; cursor: pointer; z-index: 2; }
.cf-gear:hover { color: #206bc4; border-color: #206bc4; }
/* The canvas fills the page (board 16): the viewport less the header and the room the sections need to show their heads */
.my-flow__canvas.my-flow__canvas--fill { height: calc(100vh - 220px); min-height: 520px; }
.my-flow__canvas.call-flow-fullscreen { position: fixed; inset: 0; z-index: 1050; height: 100vh; border-radius: 0; }
.cf-toolbar__fullscreen { position: absolute; top: 12px; right: 12px; z-index: 5; }
.my-flow__canvas { position: relative; height: 520px; overflow: hidden; background: var(--tblr-bg-surface) radial-gradient(var(--tblr-border-color) 1px, transparent 1px) 0 0 / 20px 20px; }
.my-flow__draw { width: 100%; height: 100%; }
.my-section { overflow: hidden; }
.my-section__head { display: flex; align-items: center; gap: 12px; padding: 12px 20px; cursor: pointer; list-style: none; }
.my-section__head::-webkit-details-marker { display: none; }
.my-section[open] > .my-section__head { border-bottom: 1px solid var(--tblr-border-color-translucent, #e9ecf1); background: var(--tblr-bg-surface-secondary); }
.my-section__caret { color: var(--tblr-secondary); transition: transform .15s; }
.my-section[open] .my-section__caret { transform: rotate(90deg); }
.my-section__icon { width: 28px; height: 28px; border-radius: 7px; display: inline-flex; align-items: center; justify-content: center; color: #fff; flex-shrink: 0; }
.my-section__icon--number { background: #3B82F6; }
.my-section__icon--auto_attendant { background: #A855F7; }
.my-section__icon--call_queue { background: #22C55E; }
.my-section__icon--ending { background: #8a94a6; }
.my-section__title { display: flex; flex-direction: column; font-size: 14px; }
.my-section__title .text-secondary { font-size: 12px; }
.my-section__ro { white-space: nowrap; }
.my-section[open] .my-section__ro { display: inline-block; }
.my-section__body { display: grid; grid-template-columns: 230px minmax(0, 1fr); min-height: 280px; }
.my-section__rail { border-right: 1px solid var(--tblr-border-color-translucent, #e9ecf1); padding: 10px; gap: 2px; background: var(--tblr-bg-surface-secondary); flex-wrap: nowrap; }
.my-section__tab { display: flex; flex-direction: column; align-items: flex-start; text-align: left; padding: 9px 12px; border-radius: 7px; border: 0; background: transparent; color: var(--tblr-body-color); }
.my-section__tab:hover { background: rgba(var(--tblr-primary-rgb), .06); }
.my-section__tab.active { background: rgba(var(--tblr-primary-rgb), .1); color: var(--tblr-body-color); }
.my-section__tab-title { font-size: 13px; font-weight: 600; }
.my-section__tab-sub { font-size: 11px; color: var(--tblr-secondary); }
.my-section__pane { padding: 18px 22px; }
.my-section__pane .tab-pane { display: none; }
.my-section__pane .tab-pane.active { display: flex; flex-direction: column; gap: 14px; }
.my-fields { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 14px 16px; }
.my-field__value { background: var(--tblr-bg-surface-secondary); min-height: 36px; }
.my-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.my-week { display: grid; grid-template-columns: 40px repeat(48, minmax(0, 1fr)); gap: 2px; align-items: center; }
.my-week__day, .my-week__hour { font-size: 11px; color: var(--tblr-secondary); }
.my-week__hour { grid-column: span 4; }
.my-week__slot { height: 18px; border-radius: 2px; background: var(--tblr-border-color); }
.my-week__slot.is-open { background: var(--tblr-primary); }
.my-holiday { display: flex; flex-direction: column; gap: 8px; }
.my-card__list { padding: 14px 20px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
@media (max-width: 760px) { .my-section__body { grid-template-columns: minmax(0, 1fr); } }
.my-settings fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.my-settings__row { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 16px; padding: 18px 20px; border-bottom: 1px solid var(--tblr-border-color-translucent, #e9ecf1); font-size: 14px; }
.my-settings__row .form-check { margin-bottom: 6px; }
.my-settings__minutes { width: 72px; display: inline-block; }
.my-settings__label { min-width: 180px; }
.my-settings__actions { display: flex; justify-content: flex-end; gap: 8px; padding: 16px 20px; }
.my-settings__sent { align-self: center; font-size: 14px; } /* Send now's outcome, beside the buttons */
@media (max-width: 760px) { .my-settings__row { grid-template-columns: minmax(0, 1fr); } }
.my-report-types { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
.my-report-type { display: flex; flex-direction: column; gap: 6px; padding: 18px 20px; color: inherit; font-size: 13px; }
.my-report-type strong { font-size: 15px; }
.my-report-type:hover { color: inherit; border-color: var(--tblr-primary); }
.my-drawer__group { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); padding: 12px 6px 0; }
.my-table__total td { font-weight: 600; border-top: 2px solid var(--tblr-border-color); }
.my-dates { display: flex; align-items: flex-end; gap: 8px; font-size: 13px; }
.my-dates label { display: flex; flex-direction: column; gap: 4px; }
.my-choose { min-width: 260px; max-height: 360px; overflow-y: auto; }
.my-settings__select { max-width: 320px; }
.my-settings__inline { width: auto; display: inline-block; }
.my-settings__choices { display: flex; flex-wrap: wrap; gap: 4px 16px; padding-left: 24px; }
div.my-settings__actions.my-panel { border-top: 0; }
@media (max-width: 1100px) { .my-report-types { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.my-call { padding: 8px 20px; }
.my-source { margin-top: auto; align-self: flex-end; font-size: 12px; color: var(--tblr-secondary); }
.my-report-types--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* A whitelabel logo fitted, never squeezed: at most --fit-logo-h high (60px by default) and never wider than what holds
   it, keeping its proportions. A fixed height squeezed a wide logo once the column or the phone capped its width
   (CallerConnect's 1200x100 sign-in logo drew at 510x63 on the setup wizard, and narrower still on a phone). */
.fit-logo, .navbar-brand-image.fit-logo { height: auto; width: auto; max-width: 100%; max-height: var(--fit-logo-h, 60px); }

/* Product page (artbook NQYFpkLiLz5iZm9e465GT5): one page per product, a dark hero with the product and its price or
   licence, then open sections separated by space, not boxes. The hero is dark in both themes. */
.mp-page { display: flex; flex-direction: column; gap: 2rem; }
/* The band of the commerce documents (lib/commerce_documents/assets/invoice-style.css .band): the same ink, the same
   light at the top right, and under CallerConnect's own whitelabel the CallerConnect mark washed in at 7%. */
.mp-hero { position: relative; overflow: hidden; display: flex; flex-wrap: wrap; gap: 2rem 3rem; align-items: stretch;
  padding: 2rem 2.5rem; border-radius: var(--tblr-border-radius-lg); color: #fff;
  /* The whitelabel primary, mixed into near-black the way the sign-in pane does (.login-duo-voice): CallerConnect
     reads blue, an orange whitelabel orange. The muted text is the same primary over white. */
  --mp-hero-muted: color-mix(in srgb, var(--tblr-primary) 18%, #e3e8ee);
  --mp-hero-faint: color-mix(in srgb, var(--tblr-primary) 22%, #a3adb9);
  --mp-hero-deep: color-mix(in srgb, var(--tblr-primary) 36%, #070b12);
  background: radial-gradient(120% 140% at 88% 0%, color-mix(in srgb, var(--tblr-primary) 30%, transparent), transparent 60%),
              linear-gradient(158deg, color-mix(in srgb, var(--tblr-primary) 18%, #0a0e17) 0%,
                                      color-mix(in srgb, var(--tblr-primary) 36%, #070b12) 62%,
                                      color-mix(in srgb, var(--tblr-primary) 18%, #0a0e17) 100%); }
.mp-hero > * { position: relative; z-index: 1; }
.mp-hero > .mp-hero__mark { position: absolute; z-index: 0; right: -60px; top: -90px; width: 460px; height: auto;
  filter: brightness(0) invert(1); opacity: .07; pointer-events: none; }
/* The product beside what to do with it, no box around either. The columns share the hero's height: the price stays
   top right and the actions sit on the bottom edge, level with the screenshots, so no empty corner under them. */
.mp-hero__product { flex: 999 1 460px; display: flex; gap: 1.25rem; align-items: flex-start; min-width: 0; }
.mp-hero__product > .avatar { width: 3.5rem; height: 3.5rem; flex: 0 0 3.5rem; font-size: 1.5rem; }
/* An app icon on the band: a rounded tile whatever the theme's radius (0 on some whitelabels), so a logo with its own
   white background reads as a tile, not a square cut out of the band. */
.mp-hero__product > .avatar { border-radius: 12px; overflow: hidden; }
.mp-hero__text { display: flex; flex-direction: column; gap: .625rem; min-width: 0; }
.mp-hero__pills { display: flex; flex-wrap: wrap; gap: .5rem; }
.mp-hero__type { display: inline-flex; align-items: center; gap: .25rem; padding: .125rem .5rem; font-size: 12px; font-weight: 600;
  color: #fff; border: 1px solid rgba(255, 255, 255, .45); border-radius: var(--tblr-border-radius); }
.mp-hero__name { margin: 0; font-size: 2.25rem; line-height: 1.1; font-weight: 700; letter-spacing: -.01em; color: #fff; }
.mp-hero__tagline { margin: 0; font-size: 1rem; color: var(--mp-hero-muted); max-width: 34rem; }
.mp-hero__buy { flex: 0 1 380px; min-width: 0; display: flex; }
.mp-hero__stack { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1rem; }
/* Cancel is an outline, not a second slab beside Update; Tabler's red is ~3:1 on the band, this one ~4.7:1. */
.mp-hero .btn-outline-danger { --tblr-btn-color: #ff8787; --tblr-btn-border-color: #ff8787; --tblr-btn-hover-color: #fff;
  --tblr-btn-hover-bg: #d63939; --tblr-btn-hover-border-color: #d63939; --tblr-btn-active-bg: #b52d2d; }
/* Quantity, then its actions on the same line: [- n +] [Update] [Cancel] or [- n +] [Add to cart]. */
.mp-hero__actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-top: auto; }
.mp-hero__action { flex: 1 1 auto; }
.mp-hero__change { font-size: 13px; color: var(--mp-hero-muted); }
.mp-hero__change:empty { display: none; }
.mp-hero__change--error { color: #ffa8a8; }
.mp-hero [hidden] { display: none !important; }
/* The price, top right of the hero; quantity and its actions under it. */
.mp-price { text-align: right; }
.mp-figure__label { font-size: 13px; color: var(--mp-hero-muted); }
.mp-figure__value { font-size: 2.5rem; line-height: 1.15; font-weight: 700; font-variant-numeric: tabular-nums; color: #fff; }
.mp-figure__value--small { font-size: 1.125rem; }
.mp-figure__unit { font-size: 14px; color: var(--mp-hero-muted); }
.mp-figure__was { font-size: 1rem; font-weight: 500; color: var(--mp-hero-muted); }
.mp-figure__note { font-size: 12px; color: var(--mp-hero-muted); }
.mp-stepper { width: auto; flex: 0 0 auto; }
.mp-stepper .btn, .mp-stepper .form-control { background: #fff; color: #001021; }
.mp-stepper .form-control { width: 4.5rem; flex: 0 0 4.5rem; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield; appearance: textfield; }
.mp-stepper .form-control::-webkit-inner-spin-button, .mp-stepper .form-control::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.mp-section { display: flex; flex-direction: column; gap: 1rem; padding: 0 .5rem; }
.mp-section h2 { margin: 0; font-size: 1.25rem; font-weight: 700; }
.mp-section__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .625rem; }
.mp-rule { margin: 0 .5rem; border-color: var(--tblr-border-color); opacity: 1; }
.mp-holders { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .875rem; }
.mp-holder { display: flex; align-items: center; gap: .875rem; }
.mp-holder__text { flex: 1 1 auto; min-width: 0; }
.mp-holder__name { font-weight: 600; font-size: 15px; }
.mp-timeline { list-style: none; margin: 0; padding: 0 0 0 18px; border-left: 2px solid var(--tblr-border-color);
  display: flex; flex-direction: column; gap: 18px; }
.mp-timeline li { position: relative; display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: baseline; }
.mp-timeline li::before { content: ""; position: absolute; left: -26px; top: 6px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--tblr-primary); border: 2px solid var(--tblr-body-bg); }
.mp-about { flex-direction: row; flex-wrap: wrap; gap: 2rem 3.5rem; }
.mp-about__text { flex: 999 1 480px; display: flex; flex-direction: column; gap: .75rem; min-width: 0; }
.mp-prose { font-size: 15px; max-width: 44rem; }
.mp-prose :is(h1, h2, h3, h4) { margin: 1rem 0 .375rem; font-size: 1rem; font-weight: 600; }
.mp-about__side { flex: 0 1 340px; display: flex; flex-direction: column; gap: 1.5rem; }
.mp-terms { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: .625rem 1.25rem; align-content: start; }
.mp-side { display: flex; flex-direction: column; gap: .5rem; }
.mp-side__title { margin: 0; font-size: 14px; font-weight: 600; }
.mp-side__link { display: inline-flex; align-items: center; gap: .5rem; font-weight: 600; text-decoration: none; }
.mp-terms dt { font-weight: 400; color: var(--tblr-secondary); }
.mp-terms dd { margin: 0; font-weight: 600; }
/* Screenshots in the hero, under the name: small, whole images on white, all on one line, sharing it. */
.mp-shots { display: flex; gap: .625rem; margin-top: .875rem; }
.mp-shot { flex: 1 1 0; min-width: 0; max-width: 8rem; padding: 0; aspect-ratio: 16 / 10; overflow: hidden; cursor: zoom-in;
  background: #fff; border: 1px solid rgba(255, 255, 255, .25); border-radius: var(--tblr-border-radius); }
.mp-shot:hover, .mp-shot:focus-visible { border-color: #fff; }
.mp-shot img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* Owned: who it is assigned to beside its history. */
.mp-owned { display: flex; flex-wrap: wrap; gap: 2rem 3.5rem; padding: 0 .5rem; }
.mp-owned > .mp-section { padding: 0; }
.mp-owned__assigned { flex: 7 1 420px; min-width: 0; }
.mp-owned__history { flex: 5 1 300px; min-width: 0; }

/* The Marketplace (artbook AUnFv9B7MEeHnnWPCdAVUK): the same band with the search and what is featured, then the
   segments as a tree beside the products as rows. A catalogue, not a gallery of cards. */
.mp-band__main { flex: 999 1 460px; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 1.125rem; }
.mp-band__search { max-width: 560px; }
.mp-band__search .form-control { height: 48px; font-size: 16px; border: 0; background: #fff; color: #182433; }
.mp-band__featured { flex: 0 1 400px; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: .75rem; }
.mp-featured { display: flex; align-items: center; gap: .75rem; color: #fff; text-decoration: none; }
.mp-featured:hover { color: #fff; }
.mp-featured:hover .mp-featured__name { text-decoration: underline; }
.mp-featured__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.mp-featured__name { font-weight: 600; }
.mp-featured__line { font-size: 13px; color: var(--mp-hero-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-featured__price { text-align: right; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.mp-featured__price span { display: block; font-size: 12px; font-weight: 400; color: var(--mp-hero-muted); }
.mp-catalogue { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 2rem 3.5rem; padding: 0 .5rem; }
.mp-rail { flex: 1 1 220px; max-width: 260px; display: flex; flex-direction: column; gap: 1.75rem; }
.mp-rail__toggle { display: flex; align-items: center; justify-content: flex-start; font-weight: 600; }
@media (max-width: 991.98px) { .mp-rail { flex-basis: 100%; max-width: none; } }
.mp-rail__group { display: flex; flex-direction: column; gap: 1px; }
.mp-rail__title { font-size: 14px; font-weight: 600; margin-bottom: .375rem; }
.mp-rail__item { display: flex; align-items: center; gap: .5rem; padding: .375rem .625rem; border-radius: var(--tblr-border-radius);
  color: var(--tblr-body-color); font-weight: 500; text-decoration: none; }
.mp-rail__item:hover { background: var(--tblr-bg-surface-secondary); color: var(--tblr-body-color); }
.mp-rail__item--depth-1 { padding-left: 1.625rem; font-weight: 400; }
.mp-rail__item--depth-2 { padding-left: 2.625rem; font-weight: 400; font-size: 13px; }
.mp-rail__item.is-current { background: rgba(var(--tblr-primary-rgb), .1); color: var(--tblr-primary); font-weight: 600; }
.mp-rail__count { margin-left: auto; color: var(--tblr-secondary); font-weight: 400; font-variant-numeric: tabular-nums; }
.mp-rail__item.is-current .mp-rail__count { color: inherit; }
.mp-catalogue__list { flex: 999 1 640px; min-width: 0; display: flex; flex-direction: column; gap: 2.25rem; }
.mp-catalogue__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .625rem; }
.mp-catalogue__title { margin: 0; font-size: 1.5rem; font-weight: 700; }
.mp-catalogue__sort { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.mp-catalogue__sort .form-select { width: auto; }
.mp-group { display: flex; flex-direction: column; }
.mp-group__head { display: flex; align-items: baseline; gap: .625rem; padding-bottom: .625rem; border-bottom: 1px solid var(--tblr-border-color); }
.mp-group__title { margin: 0; font-size: 1.125rem; font-weight: 700; }
.mp-row { display: flex; align-items: center; gap: 1rem; padding: .75rem 0; border-bottom: 1px solid var(--tblr-border-color-translucent); }
.mp-row__text { flex: 1; min-width: 0; }
.mp-row__name { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.mp-row__name a { color: var(--tblr-body-color); font-weight: 600; font-size: 15px; overflow-wrap: anywhere; }
.mp-row__name a:hover { color: var(--tblr-primary); }
.mp-row__line { font-size: 13px; color: var(--tblr-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-row__price { flex: 0 0 170px; text-align: right; }
.mp-row__amount { font-weight: 700; font-size: 15px; font-variant-numeric: tabular-nums; }
.mp-row__was { margin-right: .25rem; font-weight: 400; font-size: 13px; color: var(--tblr-secondary); }
.mp-row__unit { font-size: 12px; color: var(--tblr-secondary); }
.mp-row__action { flex: 0 0 124px; display: flex; justify-content: flex-end; }
.mp-row__owned { display: inline-flex; align-items: center; gap: .375rem; font-size: 14px; font-weight: 600; color: #1d7a33; text-decoration: none; }
.mp-row__owned:hover { color: #155a26; }
[data-bs-theme="dark"] .mp-row__owned { color: #6fd68a; }
.mp-empty { padding: 2rem 0; color: var(--tblr-secondary); }

/* The commerce document pages (artbook P8s112JQVAunVaXVpWS9f2): cart, order, invoice, plans. The band as on the
   marketplace, with the title, a status line and the order wizard; then one box the width of the band, the document
   on the left and From/To, the totals and the action in a side column. */
.mp-band__line { font-size: 15px; color: var(--mp-hero-muted); }
.mp-band__actions { position: relative; flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: .5rem; align-self: flex-start; }
.mp-wizard { list-style: none; margin: .5rem 0 0; padding: 0; width: 100%; max-width: 760px; display: flex; align-items: flex-start; }
.mp-wizard__step { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: .5rem; }
.mp-wizard__bar { flex: 1 1 0; height: 2px; margin: 13px .75rem 0; background: rgba(255, 255, 255, .25); }
.mp-wizard__bar.is-done { background: #2fb344; }
.mp-wizard__dot { width: 28px; height: 28px; box-sizing: border-box; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 13px; font-weight: 700; border: 2px solid rgba(255, 255, 255, .35); color: var(--mp-hero-faint); }
.mp-wizard__step.is-done .mp-wizard__dot { background: #2fb344; border-color: #2fb344; color: #fff; }
.mp-wizard__step.is-current .mp-wizard__dot { background: #fff; border-color: #fff; color: var(--mp-hero-deep); }
.mp-wizard__label { font-size: 14px; color: var(--mp-hero-faint); white-space: nowrap; }
.mp-wizard__step.is-done .mp-wizard__label { color: #fff; }
.mp-wizard__step.is-current .mp-wizard__label { color: #fff; font-weight: 700; }
.mp-doc { display: flex; flex-wrap: wrap; background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius-lg); overflow: hidden; }
.mp-doc__main { flex: 999 1 600px; min-width: 0; }
/* Nothing in the document yet (the empty cart): the fact and the way to fill it, centred in the box. */
.mp-doc__empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: .5rem; padding: 3.5rem 2.5rem; }
.mp-doc__empty-icon { display: flex; align-items: center; justify-content: center; width: 3.5rem; height: 3.5rem; margin-bottom: .5rem;
  border-radius: 50%; font-size: 1.75rem; color: var(--tblr-primary); background: var(--tblr-primary-lt); }
.mp-doc__empty-title { margin: 0; font-size: 1.25rem; font-weight: 700; }
.mp-doc__empty-text { margin: 0 0 1rem; color: var(--tblr-secondary); }
.mp-doc__side { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; border-left: 1px solid var(--tblr-border-color);
  background: var(--tblr-bg-surface-secondary); }
.mp-doc__head { display: flex; align-items: flex-start; gap: .75rem; padding: 1.75rem 2.5rem; }
.mp-doc__title { margin: 0; font-size: 1.625rem; font-weight: 700; }
.mp-doc__title--small { font-size: 1.125rem; }
.mp-doc__subtitle { margin: 0 0 1rem; font-size: 1rem; font-weight: 700; }
.mp-doc__section { padding: 1.5rem 2.5rem; border-top: 1px solid var(--tblr-border-color); }
.mp-doc__table { margin: 0; }
.mp-doc__table > :not(caption) > * > :first-child { padding-left: 2.5rem; }
.mp-doc__table > :not(caption) > * > :last-child { padding-right: 1.5rem; }
.mp-doc__group > * { background: var(--tblr-bg-surface-secondary); font-weight: 600; }
.mp-doc__product { display: flex; align-items: center; gap: .75rem; }
.mp-doc__product > .avatar, .mp-doc__product > .ti { flex: 0 0 auto; }
.mp-doc__product-name { color: var(--tblr-body-color); font-weight: 600; }
.mp-doc__product-line { font-size: 13px; color: var(--tblr-secondary); }
.mp-doc__required > td { background: var(--tblr-bg-surface-secondary); }
.mp-doc__stepper { width: auto; flex-wrap: nowrap; }
.mp-doc__stepper .form-control { width: 4rem; flex: 0 0 4rem; text-align: center; font-weight: 600; -moz-appearance: textfield; appearance: textfield; }
.mp-doc__stepper .form-control::-webkit-inner-spin-button, .mp-doc__stepper .form-control::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.mp-doc__block { padding: 1.5rem 2rem; border-bottom: 1px solid var(--tblr-border-color); }
.mp-doc__block:last-child { border-bottom: 0; }
.mp-doc__links { display: flex; justify-content: space-between; align-items: center; margin-top: .875rem; font-size: 14px; }
.mp-doc__label { font-size: 13px; font-weight: 600; color: var(--tblr-secondary); margin-bottom: .25rem; }
.mp-parties { display: flex; flex-direction: column; gap: 1rem; font-size: 14px; line-height: 1.6; }
.mp-totals { display: flex; flex-direction: column; gap: .125rem; }
.mp-total-row { display: flex; justify-content: space-between; gap: .75rem; padding: .25rem 0; font-size: 14px; color: var(--tblr-secondary); }
.mp-total-row > :last-child { color: var(--tblr-body-color); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mp-total-row--grand { margin-top: .375rem; padding-top: .625rem; border-top: 1px solid var(--tblr-border-color); font-size: 1rem;
  font-weight: 700; color: var(--tblr-body-color); }
.mp-total-row--part { font-size: 13px; padding: .125rem 0; }
/* The total leads when nothing stands above it: no divider then. */
.mp-totals > .mp-total-row--grand:first-child, .mp-totals > [hidden]:first-child + .mp-total-row--grand { margin-top: 0; padding-top: .25rem; border-top: 0; }
.mp-references { display: flex; flex-wrap: wrap; gap: .5rem 3rem; font-size: 14px; }
.mp-state { display: flex; align-items: center; gap: .5rem; font-weight: 600; }
.mp-facts { display: flex; flex-direction: column; gap: .375rem; font-size: 14px; }
.mp-facts > div { display: flex; justify-content: space-between; gap: .75rem; }
.mp-facts > div > :first-child { color: var(--tblr-secondary); }
@media (max-width: 991.98px) {
  .mp-doc__side { border-left: 0; border-top: 1px solid var(--tblr-border-color); }
  .mp-doc__head, .mp-doc__section { padding-left: 1.25rem; padding-right: 1.25rem; }
  .mp-doc__table > :not(caption) > * > :first-child { padding-left: 1.25rem; }
}
@media (max-width: 575.98px) {
  .mp-hero { padding: 1.5rem; }
  .mp-hero__name { font-size: 1.75rem; }
  .mp-row { flex-wrap: wrap; row-gap: .375rem; }
  .mp-row__text { flex: 1 1 calc(100% - 4rem); }
  .mp-row__price { flex: 1 1 auto; text-align: left; padding-left: 3.5rem; }
}

/* Access in /my (artbook 7v5gHnJkb3xaUETfsoKvJP boards 30-31): the call flows list's column and the modal's one list of
   people, a Teams icon before Teams' authorized users, adding as its last row. */
.call-flows__access { display: inline-flex; align-items: center; gap: .375rem; }
.access-list { border: 1px solid var(--tblr-border-color); border-radius: var(--tblr-border-radius); }
.access-list__row { display: flex; align-items: center; gap: .625rem; padding: .5rem .75rem; border-bottom: 1px solid var(--tblr-border-color-translucent); font-size: .875rem; min-width: 0; }
.access-list__icon { width: 1rem; height: 1rem; flex: none; }
.access-list__action { width: 5rem; flex: none; text-align: right; }
.access-list__row > .text-truncate { flex: 1 1 auto; min-width: 0; }
.access-list__row > .badge { flex: none; }
.access-list__add { display: flex; align-items: center; gap: .5rem; padding: .625rem .75rem; background: var(--tblr-bg-surface-secondary); }

/* ==========================================================================
   Admin home: task board and recent changes (artbook XC8fQgoBfkdK9YeMsvemun)
   Two admin table panels (SimpleTableComponent): tasks two thirds, changes one third, stacked when narrow.
   ========================================================================== */
.adm-home { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 1rem; }
.adm-home__panel--tasks { flex: 2 1 38rem; min-width: 0; }
.adm-home__panel--changes { flex: 1 1 22rem; min-width: 0; }
/* The header bar holds the lenses; in the narrow panel they wrap under the title instead of overflowing it. */
.adm-home [data-panel] > div:first-child { flex-wrap: wrap; row-gap: .375rem; }
.adm-home [data-panel] > div:first-child > .ms-auto { flex-wrap: wrap; }
/* One line per row (admin-design.md, "The row is one line"); the full value is on hover. */
.adm-home [data-panel] .simple-table--fixed td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-home [data-panel] td form { display: inline; margin: 0; }
.adm-num { font-variant-numeric: tabular-nums; }

.adm-lenses { display: flex; flex-wrap: wrap; gap: 2px; }
.adm-lens { display: inline-flex; align-items: center; gap: .375rem; font-size: .8125rem; color: var(--tblr-secondary); border-radius: 4px; padding: .2rem .55rem; text-decoration: none; }
.adm-lens:hover { color: var(--tblr-body-color); text-decoration: none; background: rgba(6, 111, 209, .06); }
.adm-lens.is-active { color: var(--tblr-body-color); font-weight: 600; background: var(--tblr-bg-surface); box-shadow: 0 0 0 1px var(--tblr-border-color); }
.adm-lens__count { font-size: .6875rem; font-weight: 600; color: var(--tblr-secondary); background: #eef1f5; border-radius: 3px; padding: 0 .375rem; font-variant-numeric: tabular-nums; }

.adm-task-circle { width: 20px; height: 20px; box-sizing: border-box; border-radius: 50%; border: 2px solid #9aa3af; background: var(--tblr-bg-surface); display: inline-flex; align-items: center; justify-content: center; padding: 0; color: #ffffff; font-size: .7rem; vertical-align: middle; }
button.adm-task-circle { cursor: pointer; }
button.adm-task-circle:hover, button.adm-task-circle:focus-visible { border-color: var(--tblr-green); }
.adm-task-circle.is-done { border-color: var(--tblr-green); background: var(--tblr-green); }
/* Ticked: struck through for a moment, then the row folds away. */
.adm-home tr:has(.adm-task--leaving) { background: #f6faf6; animation: adm-row-leave .3s ease 1.4s forwards; }
.adm-home tr:has(.adm-task--leaving) .adm-task-problem { text-decoration: line-through; color: #9aa3af; }
@keyframes adm-row-leave { to { opacity: 0; visibility: collapse; } }
@media (prefers-reduced-motion: reduce) { .adm-home tr:has(.adm-task--leaving) { animation-duration: 0s; } }

.adm-change__icon { color: var(--tblr-primary); margin-right: .375rem; }
.adm-change__icon.is-deleted { color: var(--tblr-red); }
details.adm-change summary { cursor: pointer; list-style: none; overflow: hidden; text-overflow: ellipsis; }
details.adm-change summary::-webkit-details-marker { display: none; }
details.adm-change summary::after { content: ""; display: inline-block; width: .4rem; height: .4rem; margin-left: .4rem; border-right: 2px solid var(--tblr-secondary); border-bottom: 2px solid var(--tblr-secondary); transform: translateY(-.15rem) rotate(45deg); }
details.adm-change[open] summary::after { transform: translateY(.05rem) rotate(-135deg); }
.adm-change__records { list-style: none; margin: .25rem 0 .125rem 1.375rem; padding: 0 0 0 .625rem; border-left: 2px solid var(--tblr-border-color); font-size: .8125rem; font-variant-numeric: tabular-nums; }

.adm-toasts { position: fixed; left: 50%; bottom: 1.75rem; transform: translateX(-50%); z-index: 1080; }
.adm-toast { display: flex; align-items: center; gap: 1rem; background: #182433; color: #ffffff; border-radius: 6px; padding: .75rem .875rem .75rem 1.125rem; box-shadow: 0 12px 32px rgba(24, 36, 51, .3); font-size: .875rem; animation: adm-toast-out .4s ease 8s forwards; }
.adm-toast form { margin: 0; }
.adm-toast__undo { font: inherit; font-weight: 600; color: #8fc1f2; background: transparent; border: 0; padding: .25rem .375rem; cursor: pointer; }
@keyframes adm-toast-out { to { opacity: 0; visibility: hidden; } }

/* Unassigned numbers on Tenant › Voice (artbook AsMTSVx7S2abLsPu2W2Svy): kind badges (auto attendant red, call queue
   orange, announcement green, as on the call-flow canvas), mono numbers, and the dialog's target field shown for the
   chosen kind only. */
.kind-badge { width: 22px; height: 22px; border-radius: 6px; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex: none; background: #64748b; font-size: 14px; }
.kind-badge--auto_attendant { background: #EF4444; }
.kind-badge--call_queue { background: #F97316; }
.kind-badge--announcement { background: #16A34A; }
.voice-unassigned__goes { display: flex; align-items: center; gap: 8px; }
.voice-unassigned__number, .voice-unassigned__pattern { font-family: var(--tblr-font-monospace); font-size: 12px; }
.voice-unassigned__handle { width: 28px; }
.voice-unassigned .drag-handle { cursor: grab; color: var(--tblr-secondary); }
.treatment-target { display: none; }
.treatment-form:has(#kind_user:checked) .treatment-target--user,
.treatment-form:has(#kind_auto_attendant:checked) .treatment-target--auto_attendant,
.treatment-form:has(#kind_call_queue:checked) .treatment-target--call_queue { display: block; }
.treatment-form:has(#kind_announcement:checked) .treatment-target--announcement { display: grid; gap: 1rem; }
.voice-settings-menu { min-width: 280px; }
.voice-settings-menu .dropdown-item { display: flex; align-items: center; gap: .625rem; }
.voice-settings-menu__logo { width: 18px; height: 18px; object-fit: contain; }
.voice-settings-menu__sub { margin-left: auto; color: var(--tblr-secondary); font-size: 12px; }
.treatment-kept { border: 1px solid var(--tblr-border-color); border-radius: 6px; padding: .625rem .75rem; background: var(--tblr-bg-surface-secondary); display: flex; flex-direction: column; gap: .375rem; }
.voice-unassigned__number b { font-weight: 600; color: var(--tblr-body-color); }
.range-list { border: 1px solid var(--tblr-border-color); border-radius: 6px; overflow: hidden; }
.range-list__row { display: flex; align-items: center; gap: .5rem; padding: .375rem .75rem; font-size: 13px; border-top: 1px solid var(--tblr-border-color-translucent, #eef1f4); }
.range-list__row:first-child { border-top: 0; }
.range-list__count { margin-left: auto; color: var(--tblr-secondary); font-size: 12px; }
.range-list__sum { background: var(--tblr-bg-surface-secondary); color: var(--tblr-secondary); font-size: 12px; }
.treatment-kept__pattern { font-family: var(--tblr-font-monospace); font-size: 12px; }
.treatment-kept__matches { font-size: 13px; }
.treatment-kept__replace { border: 0; background: none; padding: 0; font: inherit; font-size: 13px; color: var(--tblr-primary); align-self: flex-start; cursor: pointer; }
.treatment-kept__replace:hover { text-decoration: underline; }
/* The dialog's pickers and Goes to as the board draws them: the kind badge inside the field; the chosen mode an inset
   dark outline, not the platform's blue. */
.treatment-picker { position: relative; }
.treatment-picker .kind-badge { position: absolute; left: .5rem; top: 50%; transform: translateY(-50%); pointer-events: none; }
.treatment-picker .form-select { padding-left: 2.5rem; }
.treatment-form .choice .btn { color: var(--tblr-body-color); font-weight: 400; }
.treatment-form .choice .btn-check:checked + .btn { background: var(--tblr-bg-surface); color: var(--tblr-dark); border-color: var(--tblr-border-color); box-shadow: inset 0 0 0 2px var(--tblr-dark); font-weight: 500; }
.treatment-drop { display: block; border: 1px dashed var(--tblr-border-color-dark, #b9c2cf); border-radius: 6px; padding: 1.125rem; text-align: center; color: var(--tblr-secondary); font-size: 13px; background: var(--tblr-bg-surface-secondary); cursor: pointer; }
.treatment-drop:focus-within, .treatment-drop.drag-over { border-color: var(--tblr-primary); }
.treatment-drop .kind-badge { margin: 0 auto; }
.treatment-drop__hint { display: block; font-size: 12px; margin-top: 2px; }

/* Call problems on the admin call record (plan golden-foraging-bonbon): the evidence boxes that ARE the problem, and the
   SIP lines that carry an evidence value. Amber, the warning the ⚠ on the row already spent. */
.sheet-stat.is-problem { border-color: #f59f00; box-shadow: inset 3px 0 0 #f59f00; }
.sip-invite .sip-line { display: block; }
.sip-invite .sip-line.is-hit { background: rgba(245, 159, 0, .16); box-shadow: inset 3px 0 0 #f59f00; }

/* Watchers (artbook boards 6, 9, 11): the form's sections and condition rows, a fix check's progress bar. */
.watch-form .watch-sec { padding: .875rem 0; border-top: 1px solid var(--tblr-border-color-translucent); }
.watch-form .watch-sec:first-of-type { border-top: 0; padding-top: 0; }
.watch-cond { display: grid; grid-template-columns: minmax(0, 11rem) 4.5rem minmax(0, 1fr) 2.25rem; gap: .375rem; align-items: center; margin-bottom: .375rem; }
.watch-cond__op { text-align: center; font-size: .8125rem; }
.watch-fixed__calls { width: 5rem; }
.watch-fixed:has(#watcher_fixed_when:not(:checked)) .watch-fixed__rule { opacity: .5; }
.watch-fixed__on { display: none; }
.watch-fixed:has(#watcher_fixed_when:checked) .watch-fixed__on { display: inline; }
.watch-fixed:has(#watcher_fixed_when:checked) .watch-fixed__off { display: none; }
.watch-ends__date { display: none; }
.watch-ends:has(option[value="date"]:checked) .watch-ends__date { display: block; }
.watch-page .modal-body { padding: 1.25rem; }
.watch-progress { display: inline-flex; align-items: center; gap: .5rem; }
.watch-progress__bar { display: inline-block; width: 4rem; height: 6px; border-radius: 3px; background: var(--tblr-bg-surface-tertiary, #e6e9ef); overflow: hidden; flex: none; }
.watch-progress__bar i { display: block; height: 100%; background: var(--tblr-blue); }
.watch-progress__bar.is-recurred i { background: var(--tblr-orange); }
.watch-progress__bar.is-resolved i { background: var(--tblr-green); }
.watch-progress__bar.is-ended i { background: var(--tblr-secondary); }
.watch-digest__at, .watch-digest__on { display: none; }
.watch-digest:has(#watcher_digest_every option[value="day"]:checked) .watch-digest__at,
.watch-digest:has(#watcher_digest_every option[value="week"]:checked) .watch-digest__at { display: inline-block; }
.watch-digest:not(:has(#watcher_digest_every option[value="off"]:checked)) .watch-digest__on { display: inline-block; }
.watch-digest:not(:has(#watcher_digest_every option[value="off"]:checked)) .watch-digest__off { display: none; }
.watch-digest__people { min-width: 16rem; }

/* Add audio (board 19, A): the format tiles, then the drop zone, the recorder, the player */
.audio-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; padding: 6px 0 2px; }
.audio-tile { position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 22px 14px; border: 1px solid var(--tblr-border-color); border-radius: 8px; background: #fff; text-align: center; cursor: pointer; transition: border-color .15s, box-shadow .15s; }
.audio-tile:hover { border-color: #206bc4; }
.audio-tile:has(.audio-tile__input:checked) { border-color: #206bc4; box-shadow: 0 0 0 3px rgba(32, 107, 196, .15); }
.audio-tile__input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.audio-tile__icon { width: 44px; height: 44px; border-radius: 10px; background: #eaf1fa; color: #206bc4; display: inline-flex; align-items: center; justify-content: center; font-size: 22px; }
.audio-tile__title { font-weight: 600; color: #1d273b; }
.audio-tile__hint { font-size: 12px; color: #667382; }
.audio-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 28px 16px; border: 1.5px dashed #9aa5b4; border-radius: 8px; background: #fbfcfd; color: #667382; cursor: pointer; text-align: center; transition: border-color .15s, background .15s; }
.audio-drop.is-over, .audio-drop:hover { border-color: #206bc4; background: #f3f7fc; }
.audio-drop.has-file { border-style: solid; border-color: #2fb344; background: #f0faf2; }
.audio-drop__icon { font-size: 28px; color: #206bc4; }
.audio-drop__title { font-size: 14px; font-weight: 600; color: #1d273b; }
.audio-drop__hint { font-size: 12px; }
.audio-drop__file { font-size: 12px; color: #1a7f30; font-weight: 500; margin-top: 4px; }
.audio-drop__input { position: absolute; width: 1px; height: 1px; opacity: 0; }
/* Record (board 20, 16 Oct 2026): the panel is the state; the meter reads the microphone; the take plays in the library's player */
.audio-rec { border: 1px solid var(--tblr-border-color); border-radius: 10px; background: #fbfcfd; padding: 26px 16px; min-height: 150px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; text-align: center; }
.audio-rec.is-live { border-color: #d63939; background: var(--tblr-bg-surface, #fff); }
.audio-rec__button { width: 64px; height: 64px; border-radius: 50%; border: 0; background: #d63939; color: #fff; font-size: 24px; display: inline-flex; align-items: center; justify-content: center; flex: none; box-shadow: 0 0 0 8px rgba(214, 57, 57, .12); cursor: pointer; }
.audio-rec__button.is-recording { background: #1d273b; font-size: 18px; box-shadow: 0 0 0 8px rgba(29, 39, 59, .10); animation: audio-pulse 1.2s ease-in-out infinite; }
@keyframes audio-pulse { 0%, 100% { box-shadow: 0 0 0 8px rgba(29, 39, 59, .10); } 50% { box-shadow: 0 0 0 16px rgba(29, 39, 59, .04); } }
.audio-rec__meter { width: 100%; max-width: 480px; height: 36px; display: block; }
.audio-rec__time { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 8px; }
.audio-rec__time i { width: 10px; height: 10px; border-radius: 50%; background: #d63939; display: inline-block; }
.audio-rec__title { font-size: 15px; font-weight: 600; }
.audio-rec__hint { font-size: 13px; color: var(--tblr-secondary); }
.audio-take { gap: 12px; }
.audio-take .audio-play { width: 34px; height: 34px; font-size: 14px; }
.audio-take__clock { font-variant-numeric: tabular-nums; white-space: nowrap; }
.audio-take__bar { height: 4px; background: #dce1e7; border-radius: 2px; position: relative; margin-top: 6px; }
.audio-take__bar i { position: absolute; left: 0; top: 0; height: 100%; width: 0; background: #206bc4; border-radius: 2px; display: block; }
.audio-take__again { display: flex; gap: 12px; align-items: center; margin-top: 8px; }
/* Generate (board 21): the voice row and its picker, the tag chips */
.voice-row { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 6px; cursor: pointer; }
.voice-row:hover, .voice-row:focus-visible { background: var(--tblr-bg-surface-secondary, #f6f8fb); outline: none; }
.voice-row.is-chosen { background: #eaf1fa; }
.voice-row--chosen { border: 1px solid var(--tblr-border-color); background: var(--tblr-bg-surface, #fff); padding: 0 8px 0 0; cursor: default; }
.voice-row--chosen:hover { background: var(--tblr-bg-surface, #fff); }
.voice-row__open { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; border: 0; background: none; padding: 6px 10px; text-align: left; font: inherit; color: inherit; cursor: pointer; }
.voice-row__avatar { width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 600; font-size: 12px; color: #1d273b; flex: none; }
.voice-row__name { flex: 1; min-width: 0; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; } /* the picker sits in a right-aligned foot */
.voice-row__tags { display: flex; gap: 4px; flex: none; }
.voice-row__tags .tag { white-space: nowrap; }
.voice-play { width: 26px; height: 26px; border-radius: 50%; border: 1px solid #c9d1db; background: #fff; color: #206bc4; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; flex: none; cursor: pointer; padding: 0; }
.voice-play:hover { border-color: #206bc4; background: #eaf1fa; }
.voice-play.is-playing { background: #206bc4; color: #fff; border-color: #206bc4; }
.voice-picker { position: relative; margin-top: 6px; border: 1px solid #c9d1db; border-radius: 8px; background: var(--tblr-bg-surface, #fff); box-shadow: 0 12px 30px rgba(29, 39, 59, .16); font-size: 13px; overflow: hidden; }
.voice-picker__search { padding: 8px 10px; border-bottom: 1px solid var(--tblr-border-color); }
.voice-picker__filters { display: flex; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--tblr-border-color); }
.voice-picker__filters .form-select { width: auto; flex: 1; }
.voice-picker__list { max-height: 300px; overflow-y: auto; padding: 4px 6px 6px; }
.voice-picker__group { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--tblr-secondary); padding: 8px 10px 4px; }
.voice-picker__empty { padding: 14px 10px; text-align: center; }
.audio-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.audio-chip { border: 1px solid #c9d1db; border-radius: 4px; padding: 1px 7px; background: #fff; color: #1d273b; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 18px; cursor: pointer; }
.audio-chip:hover { border-color: #206bc4; background: #eaf1fa; }
.btn.is-playing { color: #206bc4; border-color: #206bc4; }
.audio-play { width: 30px; height: 30px; border-radius: 50%; border: 1px solid #c9d1db; background: #fff; color: #206bc4; display: inline-flex; align-items: center; justify-content: center; font-size: 13px; cursor: pointer; padding: 0; }
.audio-play:hover { border-color: #206bc4; background: #eaf1fa; }
.audio-play.is-playing { background: #206bc4; color: #fff; border-color: #206bc4; }
.audio-play--off { color: #9aa5b4; cursor: default; }
.audio-current { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--tblr-border-color); border-radius: 8px; background: #f9fafb; }
