@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 effect */
.table-hover tbody tr:hover {
    background-color: var(--tblr-bg-surface-secondary);
    cursor: pointer;
    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 */
.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) */
}

.partner-sidebar {
    --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 {
    --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 { --sidebar-bg: #52525b; }
[data-bs-theme-sidebar-color="charcoal"] .partner-sidebar { --sidebar-bg: #27272a; }
[data-bs-theme-sidebar-color="denim"] .partner-sidebar { --sidebar-bg: #2c4a6e; }
[data-bs-theme-sidebar-color="forest"] .partner-sidebar { --sidebar-bg: #2d4a3a; }
[data-bs-theme-sidebar-color="graphite"] .partner-sidebar { --sidebar-bg: #343438; }
[data-bs-theme-sidebar-color="ink"] .partner-sidebar { --sidebar-bg: #0a1628; }
[data-bs-theme-sidebar-color="mist"] .partner-sidebar { --sidebar-bg: #64748b; }
[data-bs-theme-sidebar-color="navy"] .partner-sidebar { --sidebar-bg: #1e3a5f; }
[data-bs-theme-sidebar-color="onyx"] .partner-sidebar { --sidebar-bg: #0a0a0b; }
[data-bs-theme-sidebar-color="plum"] .partner-sidebar { --sidebar-bg: #3d2c4a; }
[data-bs-theme-sidebar-color="pulse-blue"] .partner-sidebar { --sidebar-bg: #001021; }
[data-bs-theme-sidebar-color="pulse-surface"] .partner-sidebar { --sidebar-bg: #0f2c42; }
[data-bs-theme-sidebar-color="slate"] .partner-sidebar { --sidebar-bg: #334155; }
[data-bs-theme-sidebar-color="steel"] .partner-sidebar { --sidebar-bg: #46586b; }
[data-bs-theme-sidebar-color="stone"] .partner-sidebar { --sidebar-bg: #44403c; }
[data-bs-theme-sidebar-color="taupe"] .partner-sidebar { --sidebar-bg: #57534e; }
[data-bs-theme-sidebar-color="teal"] .partner-sidebar { --sidebar-bg: #1f4d4d; }
[data-bs-theme-sidebar-color="wine"] .partner-sidebar { --sidebar-bg: #4a2a30; }

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

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

/* Desktop (lg+): Persistent fixed sidebar on LEFT */
@media (min-width: 992px) {
    /* 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. */
    :root {
        margin-left: 0;
        scrollbar-gutter: stable;
    }

    .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);
    }
}

/* Mobile (<lg): Standard offcanvas from left */
@media (max-width: 991.98px) {
    .partner-sidebar {
        --tblr-offcanvas-width: 360px;
        background-color: var(--sidebar-bg) !important;
    }

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

    .partner-sidebar .btn-close {
        filter: invert(1);
    }

    [data-bs-theme="dark"] .partner-sidebar .btn-close {
        filter: none;
    }

    /* Always hide flap and collapse-show elements on mobile */
    .sidebar-flap,
    .sidebar-collapse-show {
        display: none !important;
    }
}

/* ---- 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;
}

.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;
}

/* Partner layout: mobile toggle button (no header) */
.partner-mobile-toggle {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1019;
}

/* 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;
}

/* 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;
}

/* ========================================
   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 > .nav-item > .nav-link {
    border-bottom: 2px solid transparent;
    border-radius: 0;
}

.navbar-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 partner sidebar list also carries .navbar-nav, so the horizontal-nav
   border-bottom "eyebrow" underline leaks onto its vertical buttons. Drop the
   underline and express the active state as branding-coloured text + icon only. */
.partner-sidebar .sidebar-nav .nav-link,
.partner-sidebar .sidebar-nav .nav-link.active {
    border-bottom: 0;
}

.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 on >= lg where
   the sidebar is persistent; on mobile the sidebar is offcanvas and
   modals should continue to use the full viewport.
   ------------------------------------------------------------------ */
@media (min-width: 992px) {
    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 lazy-loading panel — see app/views/shared/_async_loader.html.erb */
.async-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6rem 1rem;
  gap: 1.25rem;
}
.async-loader__spinner {
  position: relative;
  width: 72px;
  height: 72px;
}
.async-loader__ring {
  position: absolute;
  inset: 0;
  border: 4px solid var(--tblr-border-color);
  border-top-color: var(--tblr-primary);
  border-radius: 50%;
  animation: async-loader-spin 0.9s linear infinite;
}
.async-loader__pulse {
  position: absolute;
  inset: 8px;
  background: var(--tblr-primary);
  opacity: 0.08;
  border-radius: 50%;
  animation: async-loader-pulse 1.6s ease-in-out infinite;
}
.async-loader__copy {
  text-align: center;
  max-width: 520px;
}
.async-loader__title {
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--tblr-body-color);
  margin-bottom: 0.25rem;
}
.async-loader__subtitle {
  font-size: 0.875rem;
  color: var(--tblr-secondary);
  line-height: 1.5;
}
@keyframes async-loader-spin {
  to { transform: rotate(360deg); }
}
@keyframes async-loader-pulse {
  0%, 100% { opacity: 0.05; transform: scale(0.9);  }
  50%      { opacity: 0.20; transform: scale(1.05); }
}

/* ---- 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;
}

/* ------------------------------------------------------------------
   Call Flow editor — left sidebar nav inside the node offcanvas
   (#callFlowNodePanel).

   Structure (full height of the offcanvas):
     +-------------+--------------+
     |  rail       | header       |
     |  (sticky    +--------------+
     |   buttons   | content      |
     |   fill      | (scrollable) |
     |   height)   |              |
     +-------------+--------------+
     | footer (sticky, full width) |
     +------------------------------+

   The rail is a vertical flipbook-style menu: each item is a full-rail-
   width button with a title + subtitle and an active state. Save lives
   in the sticky footer (uses `form="cf-aa-form"` to submit the form).
------------------------------------------------------------------ */
#callFlowNodePanel > turbo-frame {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
}
#callFlowNodePanel .offcanvas-body {
  padding: 1rem 1.25rem;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.cf-panel {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}
.cf-panel-content {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.cf-panel-footer {
  /* Inline the Tabler card-footer treatment — the `.card-footer` class only
     applies its full styling when nested inside a `.card`, which this isn't. */
  flex-shrink: 0;
  padding: 0.75rem 1.25rem;
  background-color: var(--tblr-card-cap-bg, var(--tblr-bg-surface));
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
}

/* ---- Tom Select inside the call-flow offcanvas: make it look like a
        regular Tabler .form-control (border, padding, focus ring). ---- */
#callFlowNodePanel .ts-control {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, 0.25rem);
  padding: 0.4375rem 0.75rem;
  background-color: var(--tblr-bg-surface, #fff);
  min-height: calc(1.5em + 0.875rem + 2px);
  box-shadow: none;
  transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
#callFlowNodePanel .ts-wrapper.focus .ts-control {
  border-color: var(--tblr-primary, #066fd1);
  box-shadow: 0 0 0 0.25rem rgba(var(--tblr-primary-rgb, 6, 111, 209), 0.15);
}
#callFlowNodePanel .ts-wrapper.multi .ts-control > .item {
  background: var(--tblr-bg-surface-secondary, #f4f5f7);
  color: var(--tblr-body-color, #232e3c);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 0.25rem;
  padding: 0.125rem 0.5rem;
  margin: 0.125rem;
}
#callFlowNodePanel .ts-wrapper.multi .ts-control > .item .remove {
  border-left: 1px solid var(--tblr-border-color, #e6e7e9);
  margin-left: 0.375rem;
  padding-left: 0.375rem;
}
#callFlowNodePanel .ts-dropdown {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, 0.25rem);
  box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.08);
}

/* ---- 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; }

/* ---- Sidebar nav (rail) ---- */
.cf-tab-rail {
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--tblr-bg-surface-secondary);
  border-right: 1px solid var(--tblr-border-color);
  overflow-y: auto;
}
.cf-tab-btn {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  min-height: 68px;
  padding: 0.75rem 0.875rem;
  border: 0;
  border-left: 3px solid transparent;
  background: transparent;
  color: var(--tblr-body-color);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.cf-tab-btn:not(:last-child) {
  border-bottom: 1px solid var(--tblr-border-color);
}
.cf-tab-btn:hover {
  background: var(--tblr-bg-surface);
}
.cf-tab-btn i {
  font-size: 1.125rem;
  color: var(--tblr-secondary);
  flex-shrink: 0;
}
.cf-tab-text {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}
.cf-tab-title {
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.2;
  color: inherit;
}
.cf-tab-sub {
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.2;
  color: var(--tblr-secondary);
}

.cf-tab-btn.active {
  background: var(--tblr-bg-surface);
  border-left-color: var(--tblr-primary);
  color: var(--tblr-primary);
}
.cf-tab-btn.active i,
.cf-tab-btn.active .cf-tab-sub {
  color: var(--tblr-primary);
}
.cf-tab-btn.active .cf-tab-sub {
  opacity: 0.75;
}

.cf-tab-content {
  flex: 1 1 auto;
  min-width: 0;
}

/* ==========================================================================
   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); } }

/* 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; }

/* 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);
}
/* The bounded height the rule above needs. Without it `position: sticky` has
   nothing to stick inside and the class quietly does nothing - which is exactly
   what it did for its first year. */
.adm-scroll { max-height: min(70vh, 46rem); overflow-y: 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%;
}
.adm-table .btn-sm { --tblr-btn-padding-y: .1rem; --tblr-btn-padding-x: .5rem; font-size: .75rem; }

.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; }

/* 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__name { font-weight: 600; color: var(--tblr-body-color); line-height: 1.3;
                      word-break: break-word; }
.detail-ident__parent { font-size: .8125rem; color: var(--tblr-secondary); margin-top: .1rem;
                        word-break: break-word; }
.detail-ident__chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .6rem; }

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

.detail-rail__item { display: flex; align-items: center; gap: .5rem;
                     padding: .45rem 1.15rem; color: var(--tblr-body-color);
                     text-decoration: none; border-left: 2px solid transparent; }
.detail-rail__item:hover { background: var(--tblr-bg-surface-secondary); color: var(--tblr-primary); }
.detail-rail__item.is-current { background: var(--tblr-bg-surface-secondary);
                                border-left-color: var(--tblr-primary);
                                color: var(--tblr-primary); font-weight: 600; }
.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); }
.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 { border-left: 0; border-bottom: 2px solid transparent; }
  .detail-rail__item.is-current { border-left: 0; border-bottom-color: var(--tblr-primary); }
}

/* 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;
}
