/* ═══════════════════════════════════════════════════════════
   GLASSS - Brand Design System & Glassmorphism
   Font: Plus Jakarta Sans
   Colors: Oxford Navy + Custom Blue + Gold
   Loading: libs.bundle.css → theme.bundle.css → app.css → brand.css
   ═══════════════════════════════════════════════════════════ */

/* ─── TOKENS ─── */
:root {
    /* Brand Colors - Oxford Navy (Primary) */
    --brand-primary: #0A1628;
    --brand-primary-light: #354B6A;
    --brand-primary-lighter: #8B99B1;
    --brand-primary-dark: #081322;
    --brand-primary-rgb: 10, 22, 40;

    /* Brand Colors - Custom Blue (Action) */
    --brand-secondary: #2F6CB0;
    --brand-secondary-light: #5A90D4;
    --brand-secondary-lighter: #8BB3E5;
    --brand-secondary-dark: #285A96;
    --brand-secondary-rgb: 47, 108, 176;

    /* Brand Colors - Gold (Accent) */
    --brand-accent: #D4A843;
    --brand-accent-light: #E7C96C;
    --brand-accent-dark: #B8923A;
    --brand-accent-rgb: 212, 168, 67;

    /* Semantic Colors */
    --brand-success: #007A52;
    --brand-warning: #FAD776;
    --brand-danger: #DF4759;

    /* Focus ring: Action blue, not --brand-primary (the same navy as --ink, so
       it would read as body text). 5.40:1 on white, past WCAG's 3:1 minimum. */
    --focus-ring: #2F6CB0;
    --focus-ring-rgb: 47, 108, 176;

    /* Warm Backgrounds */
    --brand-bg: #FFFEFA;
    --brand-card: #F8F7F4;
    --brand-surface: #FBF9F6;

    /* Glassmorphism */
    --glass-bg: rgba(255, 254, 250, 0.55);
    --glass-bg-2: rgba(255, 254, 250, 0.72);
    --glass-bg-3: rgba(255, 254, 250, 0.88);
    --glass-blur: blur(24px) saturate(180%);
    --glass-border: 1px solid rgba(255, 255, 255, 0.70);
    --glass-border-2: 1px solid rgba(255, 255, 255, 0.90);
    --glass-shadow: 0 8px 40px rgba(10, 22, 40, 0.14), inset 0 1px 0 rgba(255,255,255,0.80);

    /* Text */
    --ink: #0A1628;
    --ink-2: #354B6A;
    --ink-3: #8B99B1;

    /* Font */
    --font: 'Plus Jakarta Sans', system-ui, sans-serif;
    /* One corner radius everywhere (buttons, inputs, tables, cards, dialogs):
       0.5rem, the same as Blazor's built-in reconnect dialog. */
    --radius: 8px;
    --radius-lg: 8px;
    --radius-pill: 100px;

    /* Navbar height, read by .navbar and .rz-layout.pt-10 so the fixed bar and
       the space reserved for it cannot drift apart (57px below lg). */
    --navbar-h: 68px;

    /* Shadows */
    --shadow-sm: 0 2px 4px rgba(10,22,40,.075);
    --shadow-md: 0 8px 24px rgba(10,22,40,.1);
    --shadow-lg: 0 24px 64px rgba(10,22,40,.1);
}

/* ─── RADZEN TOKEN BRIDGE ─── */
/* Radzen's CSS is injected after brand.css and declares its palette on
   `:root, .rz-material` (Radzen roots carry .rz-material, which beats any value
   inherited from :root), so declare on both selectors and keep !important. */
:root, .rz-material {
    --rz-primary: #2F6CB0 !important;
    --rz-primary-light: #5A90D4 !important;
    --rz-primary-lighter: rgba(47, 108, 176, 0.12) !important;
    --rz-primary-dark: #255A9A !important;
    --rz-primary-darker: #1E4A80 !important;
    --rz-on-primary: #FFFFFF !important;
    --rz-secondary: #2F6CB0 !important; /* Radzen default is pink #e31c65 */
    --rz-secondary-light: #5A90D4 !important;
    --rz-secondary-lighter: rgba(47, 108, 176, 0.12) !important; /* Radzen default pink rgba(173,19,87,.12) - hover/selected tints */
    --rz-secondary-dark: #255A9A !important;
    --rz-secondary-darker: #1E4A80 !important;
    --rz-on-secondary-lighter: #2F6CB0 !important; /* Radzen default #ad1357 magenta */
    --rz-info: #2F6CB0 !important;
    --rz-success: #007A52 !important;
    --rz-warning: #FAD776 !important;
    --rz-on-warning: #0A1628 !important; /* white is illegible on pale amber */
    --rz-notification-warning-color: #7A5A00 !important; /* Toast text and icon: --rz-warning is the same pale amber as the toast background. */
    --rz-notification-warning-icon-color: #7A5A00 !important;
    --rz-danger: #DF4759 !important;
    --rz-header-background-color: #0A1628 !important;
    --rz-profile-menu-top-item-background-color: #0A1628 !important;
    --rz-button-border-radius: var(--radius) !important;
    --rz-border-radius: var(--radius) !important;
    --rz-button-shadow: var(--shadow-sm) !important;
    --rz-button-hover-shadow: var(--shadow-md) !important;
    --rz-footer-padding: 0.75rem;

    /* Navigation chrome marks selection in Oxford Navy; Action blue stays reserved for inline links and buttons. */
    --rz-on-primary-lighter: var(--brand-secondary) !important; /* Radzen default #4340D2 purple - selected-state text (pager, tree, dropdown, grid) */
    --rz-panel-menu-item-active-color: var(--brand-primary) !important;
    --rz-panel-menu-item-2nd-level-active-color: var(--brand-primary) !important;
    --rz-panel-menu-item-3rd-level-active-color: var(--brand-primary) !important;
    --rz-panel-menu-item-active-background-color: rgba(var(--brand-primary-rgb), 0.10) !important;
    --rz-panel-menu-item-2nd-level-active-background-color: rgba(var(--brand-primary-rgb), 0.10) !important;
    --rz-panel-menu-item-3rd-level-active-background-color: rgba(var(--brand-primary-rgb), 0.10) !important;
    --rz-panel-menu-item-active-indicator: var(--brand-primary) !important;
    --rz-tabs-tab-color: var(--ink-2) !important;
    --rz-tabs-tab-selected-color: var(--brand-primary) !important;
    --rz-tabs-tab-selected-top-border-color: var(--brand-primary) !important;
}

/* Sentence case and brand tracking; must beat Radzen's size-class rules
   (.rz-button-md etc.), which load later. */
.rz-button.rz-button-xs,
.rz-button.rz-button-sm,
.rz-button.rz-button-md,
.rz-button.rz-button-lg {
    font-family: var(--font) !important;
    text-transform: none !important;
    letter-spacing: 0.03em !important;
}

/* RadzenMarkdown renders headings, text and tables with Radzen's typography classes, which set their
   own font: use the brand font instead, keeping code monospace. */
.rz-markdown * {
    font-family: var(--font);
}

.rz-markdown :is(code, pre, pre *) {
    font-family: var(--bs-font-monospace, monospace);
}

/* Buttons in flex rows must not shrink below their content: a squeezed
   icon+text button let its label overflow to the right (off-centre). */
.rz-button {
    flex-shrink: 0;
}

/* Radzen paints the toast wrapper white (behind the translucent tint) but
   rounds only the inner item, leaving white corners. */
.rz-notification-item-wrapper {
    border-radius: var(--rz-notification-border-radius);
}

/* Combinations toolbar: taller buttons (44px instead of Radzen's 36px),
   id-scoped so every other button keeps its stock height. */
#combinationsButtons .rz-button-md {
    padding-block: 0.75rem;
}

/* Brand hover: lift, mirroring .btn. */
.rz-button:not(.rz-state-disabled):hover {
    transform: translateY(-1px);
    transition: all 0.2s ease;
}

/* ─── BASE ─── */
*, *::before, *::after { box-sizing: border-box; }

/* Page-level scroll is for the public hero pages (carousel wheel containment,
   reveal animations, fragment scrolling). With the signed-in sidebar rendered
   they stay pinned, so the sidebar docks below the fixed navbar. */
html:has(#top.hero-video):not(:has(.rz-sidebar)) {
    scroll-behavior: smooth;
    overflow-x: hidden;
    overflow-y: auto;
}

body {
    font-family: var(--font) !important;
    font-size: 1rem;
    line-height: 1.65;
    color: var(--ink);
    background: var(--brand-bg);
    -webkit-font-smoothing: antialiased;
    margin: 0;
}

/* Public (no-sidebar) pages scroll the window, not .rz-body, so mobile browser
   chrome collapses and anchors land correctly. Docs pages keep their two-pane
   internal scroll on desktop and join the window scroll below 992px. */
body:not(:has(.rz-sidebar)):not(:has(.doc-container)) {
    overflow-x: hidden;
    overflow-y: auto;
}

.rz-layout:not(:has(.rz-sidebar)):not(:has(.doc-container)) {
    overflow: visible !important;
    height: auto !important;
    max-height: none !important;
    min-height: 100vh;
    min-height: 100dvh;
}

.rz-layout:not(:has(.rz-sidebar)):not(:has(.doc-container)) .rz-body {
    overflow: visible !important;
    height: auto !important;
}

@media (max-width: 991px) {
    body:has(.doc-container):not(:has(.rz-sidebar)) {
        overflow-x: hidden;
        overflow-y: auto;
    }

    .rz-layout:has(.doc-container):not(:has(.rz-sidebar)) {
        overflow: visible !important;
        height: auto !important;
        max-height: none !important;
        min-height: 100vh;
        min-height: 100dvh;
    }

    .rz-layout:has(.doc-container):not(:has(.rz-sidebar)) .rz-body {
        overflow: visible !important;
        height: auto !important;
    }
}

/* Anchor targets clear the fixed navbar when the window scrolls. */
html {
    scroll-padding-top: calc(var(--navbar-h) + 0.5rem);
}

/* The navbar is position:fixed beside <RadzenLayout class="pt-10">, so the
   layout reserves its height by hand; both read --navbar-h. Pinned, not
   measured: ResizeObserver does not report the navbar's padding-driven growth. */
.navbar {
    height: var(--navbar-h);
}

.rz-layout.pt-10 { padding-top: var(--navbar-h, 5rem) !important; }

/* ─── LIGHT AMBIENT MESH ─── */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    background:
        radial-gradient(ellipse 70% 60% at 10% 10%,  rgba(10,22,40,0.08) 0%, transparent 65%),
        radial-gradient(ellipse 55% 50% at 92% 8%,   rgba(212,168,67,0.06) 0%, transparent 60%),
        radial-gradient(ellipse 65% 55% at 80% 90%,  rgba(47,108,176,0.05) 0%, transparent 65%),
        radial-gradient(ellipse 50% 45% at 10% 88%,  rgba(212,168,67,0.04) 0%, transparent 60%),
        radial-gradient(ellipse 40% 35% at 55% 48%,  rgba(10,22,40,0.03) 0%, transparent 55%);
    pointer-events: none;
}

body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    background: linear-gradient(145deg, var(--brand-bg) 0%, var(--brand-card) 50%, var(--brand-surface) 100%);
    pointer-events: none;
}

/* ─── TYPOGRAPHY ─── */
h1, h2, h3, h4 {
    font-family: var(--font);
    color: var(--ink);
    line-height: 1.05;
    letter-spacing: -0.02em;
    font-weight: 700;
    margin: 0 0 0.75rem;
}

a {
    color: var(--brand-primary);
    text-decoration: none;
    transition: color 0.15s;
}

a:hover {
    color: var(--brand-primary-dark);
}

a:not(.btn):not(.nav-link):not(.product-tab):not(.dropdown-item):not(.doc-switcher-tab) {
    color: var(--brand-secondary);
}

a:not(.btn):not(.nav-link):not(.product-tab):not(.dropdown-item):not(.doc-switcher-tab):hover {
    color: var(--brand-secondary-dark);
}

/* ─── NAV CHROME = INK ───
   Sidebar menu, breadcrumb and tabs are navigation, not links: ink like
   .nav-link. !important for the same reason as the token bridge. */

.rz-panel-menu .rz-navigation-item-wrapper,
.rz-panel-menu .rz-navigation-item-link {
    color: var(--brand-primary) !important;
}

.rz-breadcrumb-item .rz-link {
    color: var(--brand-primary) !important;
}

/* Plain slash between crumbs instead of Radzen's double arrowhead. */
.rz-breadcrumb .rz-breadcrumb-item + .rz-breadcrumb-item::before {
    content: "/" !important;
    color: var(--ink-2);
}

.rz-tabview-nav li a {
    color: var(--ink-2) !important;
}

.rz-tabview-nav li.rz-tabview-selected a {
    color: var(--brand-primary) !important;
}

/* Selected-state marks are gold, not Action blue (blue means "you can press
   this"). Dark gold: plain --brand-accent is too faint for a 2px bar. */
.rz-tabview.rz-tabview-top > .rz-tabview-nav .rz-tabview-selected {
    border-bottom-color: var(--brand-accent-dark) !important;
    /* Underline only, like the grid's active cell and the workspace tree's
       open file, so every selected mark reads as one family. */
}

.display-4 {
    font-size: clamp(2rem, 4.5vw, 3.2rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.05;
    color: var(--ink);
}

/* ─── SECTION LABEL ─── */
.section-label {
    font-family: var(--font);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--brand-primary);
    margin-bottom: 1.25rem;
    display: inline-block;
    /* labels inside flex wrappers get blockified - keep the hairline
       hugging the text in every usage */
    width: fit-content;
    padding-bottom: 0.45rem;
    border-bottom: 1px solid var(--brand-accent);
}

/* ─── SECTIONS ─── */
section { padding: 110px 0; position: relative; }
#top.hero-video { padding: 0; }

/* Override RadzenLayout pt-10 for full-bleed hero - public hero pages only */
.rz-layout.pt-10:has(#top.hero-video):not(:has(.rz-sidebar)) > .rz-layout-content {
    padding-top: 0 !important;
}

/* Full-bleed hero: break out of RadzenBody, on public hero pages only. */
.rz-layout:has(#top.hero-video):not(:has(.rz-sidebar)) {
    padding-top: 0 !important;
    /* keep body track from stretching to content's intrinsic width
       (e.g. the GLASSShopper components strip) */
    grid-template-columns: auto minmax(0, 1fr) !important;
}

/* Hero content is flush in the body region: full-bleed anonymously, edge to
   edge against the docked sidebar when signed in. */
.rz-layout:has(#top.hero-video) .rz-body {
    padding: 0 !important;
}

/* ─── OVERLAY SCROLLBAR ───
   The page containers (html, .rz-body) hide their native scrollbars so content
   runs to the edge; brand.js paints a slim thumb instead. Component scrollers keep theirs. */
html,
.rz-body {
    scrollbar-width: none;
}

html::-webkit-scrollbar,
.rz-body::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}

.lk-osb {
    position: fixed;
    z-index: 8000;
    background: rgba(10, 22, 40, 0.40);
    border-radius: 999px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease, background 0.15s ease;
    touch-action: none;
}

.lk-osb.visible {
    opacity: 1;
    pointer-events: auto;
}

.lk-osb:hover,
.lk-osb.dragging {
    background: rgba(10, 22, 40, 0.65);
}

.lk-osb-v { top: 0; right: 4px; width: 6px; }
.lk-osb-h { left: 0; bottom: 4px; height: 6px; }

#top.hero-video {
    width: 100%;
    position: relative;
    z-index: 0;
    background: #e8e8e8;
}

section.bg-light {
    background: rgba(255,255,255,0.25) !important;
    border-top:  var(--glass-border);
    border-bottom: var(--glass-border);
}

/* ─── HERO ─── */
#top.hero-video {
    height: 100vh;
    min-height: 720px;
    display: flex;
    align-items: flex-end;
    position: relative;
    overflow: hidden;
    background: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
}

/* Signed in, the page scrolls inside .rz-body, between the fixed navbar and the
   footer, so 100vh would push the hero's band under the footer: size it to the
   scroll area instead (cqh), whatever the bars' heights. */
@media (min-width: 769px) {
    .rz-layout:has(.rz-sidebar):has(#top.hero-video) .rz-body {
        container-type: size;
    }

    .rz-layout:has(.rz-sidebar) #top.hero-video {
        height: 100cqh;
        min-height: 480px;
    }
}

#top.hero-video video {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    z-index: 1;
    opacity: 1;
}

.hero-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(to top, rgba(var(--brand-primary-rgb),0) 0%, transparent 40%);
}

.hero-content {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 3;
    width: 100%;
    max-width: 100%;
    padding: 2rem 5vw;
    background: rgba(var(--brand-primary-rgb),0.30);
    backdrop-filter: blur(4px) saturate(110%);
    -webkit-backdrop-filter: blur(4px) saturate(110%);
    border-top: 1px solid rgba(255,255,255,0.08);
    color: #fff;
}

.hero-content-inner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4vw;
}

.hero-left {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.hero-left img {
    height: 120px;
    width: auto;
    filter: brightness(0) invert(1);
}

.hero-right {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    border-left: 1px solid rgba(255,255,255,0.15);
    padding-left: 4vw;
}

.hero-right .hero-subtitle { margin: 0; }

.hero-subtitle {
    font-size: clamp(1rem, 2vw, 1.2rem);
    font-weight: 300;
    color: rgba(255,255,255,0.95);
    max-width: 500px;
    margin: 1.5rem 0 2.75rem;
    line-height: 1.65;
}

@media (max-width: 768px) {
    .hero-content-inner { flex-direction: column; gap: 1.5rem; }
    .hero-right { border-left: none; padding-left: 0; border-top: 1px solid rgba(255,255,255,0.15); padding-top: 1.5rem; }
    .hero-left img { height: 60px; }
    /* Stacked hero: the logo above is centered, so the subtitle and the CTA
       row center on the same axis. */
    .hero-right { text-align: center; }
    .hero-right .d-flex { justify-content: center; }

    /* g-8's negative row margin exceeds .container's padding at phone widths,
       so the rows would hang past the viewport. */
    .row.g-8 { --bs-gutter-x: 1rem; }

    /* Portrait: the hero sizes to content. Cover-filling a tall box would crop
       most of the 16:9 film, so the video is a full-width 16:9 strip (56.25vw,
       no crop) and the band stacks below it. */
    #top.hero-video {
        height: auto;
        min-height: 0;
        display: block;
        background: var(--brand-bg);
    }

    #top.hero-video video {
        position: relative;
        inset: auto;
        display: block;
        width: 100%;
        height: 56.25vw;
    }

    .hero-content {
        position: relative;
        inset: auto;
    }
}

/* ─── NAVBAR ─── */
.navbar {
    background: rgba(255, 255, 255, 0.65) !important;
    backdrop-filter: var(--glass-blur) !important;
    -webkit-backdrop-filter: var(--glass-blur) !important;
    border-bottom: var(--glass-border) !important;
    padding: 0.55rem 0 !important;
    box-shadow: 0 2px 20px rgba(var(--brand-primary-rgb),0.08) !important;
}

.navbar-brand-img { height: 34px !important; }

.nav-link {
    font-family: var(--font);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--ink-2) !important;
    padding: 0.5rem 1rem !important;
    transition: color 0.15s;
}

.nav-link:hover, .nav-link.active { color: var(--brand-primary) !important; }

/* Bootstrap's .p-0 cannot beat the !important padding above, so restore it
   for `nav-link p-0` (the footer social links). */
.nav-link.p-0 { padding: 0 !important; }

/* Yellow underline for active link - background technique to avoid
   conflicting with the Bootstrap dropdown caret (also uses ::after) */
.nav-link.active {
    background-image: linear-gradient(var(--brand-accent), var(--brand-accent));
    background-repeat: no-repeat;
    background-position: 1rem calc(100% - 4px);
    background-size: calc(100% - 2rem) 2px;
}

/* Solid menu */
.dropdown-menu {
    background: #fff !important;
    border: 1px solid rgba(10, 22, 40, 0.08) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--shadow-md) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    padding: 0.5rem !important;
    min-width: 180px;
    margin-top: 0.5rem !important;
}

/* Navbar dropdowns hang from the trigger's right edge, not landkit's centered
   position. Landkit's JS open animation never binds (the navbar renders after
   load), so the slide-in is a keyframe. Desktop only: below lg menus sit inline. */
@media (min-width: 992px) {
    /* Same specificity as landkit's rules, so later source order wins. No
       !important on transform, or the keyframes could not animate it. */
    .navbar-nav .dropdown > .dropdown-menu {
        left: auto !important;
        right: 0 !important;
        transform: translateY(10px);
    }

    .navbar-nav .dropdown > .dropdown-menu.show {
        transform: translateY(0);
        animation: lk-dropdown-in 0.2s ease-out;
    }
}

@keyframes lk-dropdown-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Mobile drawer. The navbar's backdrop-filter makes it the containing block for
   fixed descendants, so landkit's % max-height would resolve against the bar:
   use viewport units. 100vh first, as the fallback for engines without dvh. */
@media (max-width: 991.98px) {
    /* Shorter bar: the row collapses to the logo plus the toggler. */
    :root { --navbar-h: 57px; }

    /* Start the drawer just under the bar (landkit's top: 1rem overlaps the
       logo) and shrink max-height by the same offset. */
    .navbar .navbar-collapse {
        top: calc(var(--navbar-h) + 0.25rem) !important;
        max-height: calc(100vh - var(--navbar-h) - 1.25rem) !important;
        max-height: calc(100dvh - var(--navbar-h) - 1.25rem) !important;
    }
}

/* Trigger focus: no sticky outline or Bootstrap focus shadow after a click; the keyboard ring is kept. */
.dropdown-toggle:focus {
    outline: none !important;
    box-shadow: none !important;
}

.dropdown-toggle:focus-visible {
    outline: 2px solid var(--brand-secondary) !important;
    outline-offset: 2px;
}

.dropdown-item {
    font-family: var(--font);
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ink-2) !important;
    border-radius: 8px;
    padding: 0.65rem 1rem;
    margin: 2px 0;
    transition: background 0.15s, color 0.15s;
    white-space: nowrap;
}

.dropdown-item:hover, .dropdown-item.active {
    background: rgba(10,22,40,0.10) !important;
    color: var(--brand-primary) !important;
}

/* ─── BUTTONS ─── */
.btn {
    font-family: var(--font);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.03em;
    border-radius: var(--radius);
    padding: 0.85rem 1.75rem;
    /* No `border: none` here: brand.css loads after theme.bundle.css, so it
       would erase landkit's .btn-outline-* borders. */
    transition: all 0.2s ease;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    /* Flex ignores an inherited text-align, so center the label of buttons
       stretched to fill their container. */
    justify-content: center;
}

/* The fixed .btn padding above loads after theme.bundle.css and would flatten
   Bootstrap's size modifiers: restore the scale. */
.btn-sm {
    font-size: 0.78rem;
    padding: 0.5rem 1.1rem;
}

.btn-xs {
    font-size: 0.75rem;
    padding: 0.35rem 0.85rem;
}

.btn-primary {
    background: #2F6CB0;
    color: #fff;
    box-shadow: 0 4px 16px rgba(47,108,176,0.30);
}

.btn-primary:hover {
    background: #255A9A;
    box-shadow: 0 8px 24px rgba(47,108,176,0.40);
    transform: translateY(-2px);
    color: #fff;
}

/* Ghost for hero dark context */
.btn-accent {
    background: rgba(255,255,255,0.12);
    color: rgba(255,255,255,0.92);
    border: 1px solid rgba(255,255,255,0.28);
    backdrop-filter: blur(12px);
}

.btn-accent:hover {
    background: rgba(255,255,255,0.22);
    color: #fff;
    transform: translateY(-2px);
    border-color: rgba(255,255,255,0.45);
}

.btn-outline-primary {
    background: rgba(255, 254, 250, 0.72) !important;
    color: #2F6CB0 !important;
    /* These sit on light page sections, not the hero video: 0.8 alpha keeps
       the border at ~3.5:1 against the page. */
    border: 1px solid rgba(47,108,176,0.8) !important;
}

.btn-outline-primary:hover {
    background: rgba(47,108,176,0.10) !important;
    border-color: #2F6CB0 !important;
    transform: translateY(-1px);
}

/* Outline variants that would otherwise fall back to landkit's off-palette
   greys (external login buttons, notifications). */
.btn-outline-dark,
.btn-outline-secondary {
    background: #FFFFFF;
    color: var(--ink);
    border: 1px solid rgba(10, 22, 40, 0.55);
}

.btn-outline-dark:hover,
.btn-outline-secondary:hover {
    background: rgba(10, 22, 40, 0.05);
    border-color: rgba(10, 22, 40, 0.45);
    color: var(--ink);
}

.btn-outline-light {
    background: transparent;
    color: var(--ink);
    border: 1px solid rgba(10, 22, 40, 0.55);
}

.btn-link {
    background: none;
    border: none;
    color: var(--brand-primary);
    text-decoration: none;
    padding: 0;
}

.btn-link:hover { color: var(--brand-primary-dark); text-decoration: underline; }

/* ─── GLASS CARDS ─── */
.card-glass {
    background: var(--glass-bg) !important;
    backdrop-filter: var(--glass-blur) !important;
    -webkit-backdrop-filter: var(--glass-blur) !important;
    border: var(--glass-border) !important;
    border-radius: var(--radius-lg) !important;
    padding: 2.5rem !important;
    height: 100%;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    transition: background 0.28s, border-color 0.28s, transform 0.28s, box-shadow 0.28s !important;
    box-shadow: var(--glass-shadow) !important;
}

/* Top accent on hover - disabled */
.card-glass::before { display: none; }

.card-glass:hover {
    background: var(--glass-bg-2) !important;
    border-color: rgba(255,255,255,0.90) !important;
    transform: translateY(-5px) !important;
    box-shadow:
        0 20px 60px rgba(var(--brand-primary-rgb),0.14),
        0 0 0 1px rgba(255,255,255,0.80),
        inset 0 1px 0 rgba(255,255,255,0.95) !important;
}

.card-glass:hover::before { opacity: 1; }

.card-glass img {
    border-radius: 10px;
    margin-bottom: 2rem;
    border: 1px solid rgba(255,255,255,0.50);
    box-shadow: 0 4px 16px rgba(var(--brand-primary-rgb),0.08);
    width: 100%;
    display: block;
}

.card-glass h2, .card-glass h3 {
    font-family: var(--font);
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0 0 0.65rem;
    line-height: 1.2;
}

.card-glass p {
    color: var(--ink-2);
    font-size: 0.95rem;
    line-height: 1.65;
    flex-grow: 1;
    margin: 0;
}

/* ─── PRICING ─── */
/* Plan cards on /pricing: the glass card stretches every paragraph, which would push the
   price around; only the button row takes the free space. */
.pricing-card { text-align: center; }
.pricing-card p { flex-grow: 0; }
.pricing-card h3 { font-size: 1.5rem; }

/* ─── COMING FEATURES ─── */
.coming-card {
    position: relative;
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    padding: 1.5rem;
    overflow: hidden;
    box-shadow: var(--glass-shadow);
    height: 100%;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.coming-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}

/* Card used as a link: repeats the global link rule's :not() chain to beat its
   specificity, or the whole card turns Action blue. */
a.coming-card:not(.btn):not(.nav-link):not(.product-tab):not(.dropdown-item):not(.doc-switcher-tab) {
    display: block;
    text-decoration: none;
    color: inherit;
}

.coming-card-img-wrap {
    position: relative;
    margin: 0 0 1rem;
}

.coming-card-badge {
    position: static;
    transform: none;
    vertical-align: middle;
    font-family: var(--font);
    font-size: 0.65rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 6px;
    padding: 0.3em 0.7em;
    background: var(--brand-secondary);
    color: #fff;
    border: none;
    z-index: 1;
}

.coming-card-img {
    width: 100%;
    display: block;
    border-radius: 10px;
    margin: 0;
    border: 1px solid rgba(255,255,255,0.55);
    box-shadow: 0 6px 24px rgba(var(--brand-primary-rgb),0.10);
}

.coming-title {
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0 0 0.4rem;
    line-height: 1.4;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0;
}

.coming-desc {
    color: var(--ink-2);
    font-size: 0.88rem;
    line-height: 1.65;
    margin: 0;
    padding: 0;
}

/* Home "What's new": one glass box split into tiles by hairlines */
.whats-new-box {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
    overflow: hidden;
}

.whats-new-tile {
    padding: 1.5rem;
    transition: background 0.3s ease;
}

.whats-new-tile--wide {
    border-bottom: 1px solid rgba(var(--brand-primary-rgb), 0.12);
}

.whats-new-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.whats-new-row > .whats-new-tile + .whats-new-tile {
    border-left: 1px solid rgba(var(--brand-primary-rgb), 0.12);
}

@media (max-width: 575.98px) {
    .whats-new-row { grid-template-columns: 1fr; }
    .whats-new-row > .whats-new-tile + .whats-new-tile {
        border-left: none;
        border-top: 1px solid rgba(var(--brand-primary-rgb), 0.12);
    }
}

/* Same :not() chain as a.coming-card, to beat the global link rule */
a.whats-new-tile:not(.btn):not(.nav-link):not(.product-tab):not(.dropdown-item):not(.doc-switcher-tab) {
    display: block;
    text-decoration: none;
    color: inherit;
}

a.whats-new-tile:hover {
    background: var(--glass-bg-3);
}

@media (min-width: 992px) {
    .home-intro-col {
        border-right: 1px solid rgba(var(--brand-primary-rgb), 0.12);
    }
}

/* ─── BADGES ─── */
.badge {
    font-family: var(--font);
    font-size: 0.65rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 6px;
    padding: 0.3em 0.7em;
}

.bg-primary-soft {
    background: var(--brand-primary-light) !important;
    color: #fff !important;
    border: 1px solid rgba(10,22,40,0.25);
}

/* ─── FORMS ───
   Opaque, not glass: no form surface has a dark backdrop, so glass fields would
   have no visible edge (WCAG wants 3:1). Radius is --radius, not --radius-pill,
   which would make a text field read as a search box. */
.form-control, .rz-textbox, .rz-textarea {
    font-family: var(--font);
    background: #FFFFFF;
    /* !important: Radzen's material-base.css loads after brand.css and its
       .rz-textbox border would win. */
    border: 1px solid rgba(10, 22, 40, 0.55) !important;
    border-radius: var(--radius);
    color: var(--ink);
    font-size: 0.92rem;
    transition: border-color 0.18s, box-shadow 0.18s;
}

/* iOS Safari zooms into focused fields under 16px. Only the auth forms'
   .form-control is raised; Radzen textboxes in grids keep their compact size. */
@media (max-width: 991.98px) {
    .form-control { font-size: 1rem; }
}

/* Input tokens for Radzen's other inputs (.rz-dropdown, .rz-numeric,
   .rz-datepicker, .rz-multiselect), which the class rules above do not match. */
:root, .rz-material {
    --rz-input-background-color: #FFFFFF;
    --rz-input-border-color: rgba(10, 22, 40, 0.55);
    --rz-input-color: var(--ink);
    /* --rz-input-border-radius is left to Radzen: material-base redeclares it
       later on :root, and winning it would also restyle many Radzen surfaces
       brand.css never styles. The !important rule below applies the radius. */
}

/* material-base.css (loaded later) sets border-radius from
   --rz-input-border-radius, Radzen's 4px, on these controls: the !important
   here is what gives them --radius. */
.rz-textbox,
.rz-dropdown, .rz-numeric, .rz-multiselect, .rz-datepicker, .rz-textarea,
.rz-form-field-content {
    border-radius: var(--radius) !important;
    border-color: rgba(10, 22, 40, 0.55) !important;
    font-family: var(--font);
    background: #FFFFFF !important;
}

/* RadzenFormField draws its own outlined box: match the 40px row height and
   keep the nested input borderless, so only one border shows. */
.rz-form-field-content { min-height: 40px; }
.rz-form-field-content .rz-textbox {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
}

.rz-dropdown.rz-state-empty, .rz-textbox.rz-state-empty { color: var(--ink); }

/* Dropdown popups: show short option lists in full, no scrollbar */
.rz-dropdown-panel .rz-dropdown-items-wrapper { max-height: 400px !important; }
/* Radzen sizes the panel to the input; let popups that ask for max-content grow to fit their options */
.rz-dropdown-panel:has(> .rz-dropdown-items-wrapper[style*="max-content"]) { width: max-content !important; }
/* Clip a scrolling list's scrollbar inside the panel's rounded corners */
.rz-dropdown-panel { overflow: hidden; }

/* Grid pager's page-size dropdown: Radzen's 80px, less the input padding above and the arrow's room, leaves
   24px for the value and cuts "100" to "1…". The doubled :root wins over material-base, which loads later. */
:root:root { --rz-pager-dropdown-width: 96px; }

.form-control::placeholder, .rz-textbox::placeholder { color: var(--ink-3); }

/* Focus: a 1px dark-gold border, no halo. !important because material-base.css
   loads later and sets border-color on the same selectors. */
.form-control:focus, .rz-textbox:focus,
.rz-dropdown:focus-within, .rz-numeric:focus-within,
.rz-form-field.rz-state-focused .rz-form-field-content {
    outline: none;
    border-color: var(--brand-accent-dark) !important;
    box-shadow: none !important;
    background: #FFFFFF !important;
}

/* Hover looks like focus. :where() keeps the form-field selector at one class,
   so the chromeless grid-cell editors below (two classes + td) still win. */
.form-control:hover, .rz-textbox:hover,
.rz-dropdown:hover, .rz-numeric:hover,
:where(.rz-form-field:hover) .rz-form-field-content {
    border-color: var(--brand-accent-dark) !important;
}

/* Radzen's own focus/hover tokens (material-base, loaded later, so the
   doubled :root out-specifies its definitions). Same gold as above for
   the outlined FormField's ring and its floating label. */
:root:root {
    --rz-input-focus-border: 1px solid var(--brand-accent-dark);
    --rz-input-focus-shadow: none;
    --rz-input-hover-border: 1px solid var(--brand-accent-dark);
    --rz-input-hover-shadow: none;
    --rz-form-field-focus-shadow: none;
    --rz-form-field-hover-shadow: none;
    --rz-form-field-label-focus-color: var(--brand-accent-dark);
}

/* ─── GRID CELL EDITORS ───
   Spreadsheet semantics: the edited cell is the affordance, so editors in body
   cells lose their own chrome. `td` matters: the column-filter popover renders
   inside the grid's th and must keep its outlined fields. */
.rz-data-grid-data td .rz-numeric,
.rz-data-grid-data td .rz-textbox,
.rz-data-grid-data td .rz-textarea,
.rz-data-grid-data td .rz-dropdown,
.rz-data-grid-data td .rz-multiselect,
.rz-data-grid-data td .rz-datepicker,
.rz-data-grid-data td .rz-form-field-content {
    /* !important like the rules above, winning on specificity. Only the
       colour is cleared: the layout depends on the 1px border width. */
    border-radius: 0 !important;
    border-color: transparent !important;
    background: transparent !important;
    box-shadow: none !important;
}

/* The editor must not grow the row: negative block margins make the 40px control
   take one text line and spill evenly into the td padding. Outermost control
   only (not one nested in a FormField); textarea is multi-line by design. */
.rz-data-grid-data td .rz-numeric:not(.rz-form-field .rz-numeric),
.rz-data-grid-data td .rz-textbox:not(.rz-form-field .rz-textbox),
.rz-data-grid-data td .rz-dropdown:not(.rz-form-field .rz-dropdown),
.rz-data-grid-data td .rz-multiselect:not(.rz-form-field .rz-multiselect),
.rz-data-grid-data td .rz-datepicker:not(.rz-form-field .rz-datepicker),
.rz-data-grid-data td .rz-form-field {
    /* Whole pixels: a half-pixel offset would draw the value ~1px below its
       display-mode position. */
    margin-block-start: round(down, calc((var(--rz-grid-cell-line-height) * var(--rz-grid-cell-font-size) - var(--rz-input-height)) / 2), 1px) !important;
    margin-block-end: round(up, calc((var(--rz-grid-cell-line-height) * var(--rz-grid-cell-font-size) - var(--rz-input-height)) / 2), 1px) !important;
    /* inline-block on the baseline leaves a descender gap under the box,
       which grew the row by a further 0.5-2.5px. */
    vertical-align: top;
}

/* Compact grids define --rz-grid-cell-line-height as a length (1rem), not a
   factor, so the product above is invalid; the line height is the text line. */
.rz-density-compact .rz-data-grid-data td .rz-numeric:not(.rz-form-field .rz-numeric),
.rz-density-compact .rz-data-grid-data td .rz-textbox:not(.rz-form-field .rz-textbox),
.rz-density-compact .rz-data-grid-data td .rz-dropdown:not(.rz-form-field .rz-dropdown),
.rz-density-compact .rz-data-grid-data td .rz-multiselect:not(.rz-form-field .rz-multiselect),
.rz-density-compact .rz-data-grid-data td .rz-datepicker:not(.rz-form-field .rz-datepicker),
.rz-density-compact .rz-data-grid-data td .rz-form-field {
    margin-block-start: round(down, calc((var(--rz-grid-cell-line-height) - var(--rz-input-height)) / 2), 1px) !important;
    margin-block-end: round(up, calc((var(--rz-grid-cell-line-height) - var(--rz-input-height)) / 2), 1px) !important;
}

/* Chromeless on focus too: the mark goes on the cell (below). !important
   because material-base.css loads later and sets a focus border-color. */
.rz-data-grid-data td .rz-numeric:focus-within,
.rz-data-grid-data td .rz-textbox:focus,
.rz-data-grid-data td .rz-textarea:focus,
.rz-data-grid-data td .rz-dropdown:focus-within,
.rz-data-grid-data td .rz-multiselect:focus-within,
.rz-data-grid-data td .rz-form-field-content:focus-within {
    border-color: transparent !important;
    box-shadow: none !important;
    background: transparent !important;
}

/* The edited cell is marked like a spreadsheet's active cell: a 2px gold bar
   on the bottom gridline. An inset shadow survives the td's overflow:hidden. */
.rz-data-grid-data td:has(.rz-numeric:focus-within),
.rz-data-grid-data td:has(.rz-textbox:focus),
.rz-data-grid-data td:has(.rz-textarea:focus),
.rz-data-grid-data td:has(.rz-dropdown:focus-within),
.rz-data-grid-data td:has(.rz-multiselect:focus-within),
.rz-data-grid-data td:has(.rz-form-field-content:focus-within) {
    box-shadow: inset 0 -2px 0 var(--brand-accent-dark);
}

/* The value must not move when the cell turns into an editor: the td padding
   already insets it, so inputs get no leading padding and use the grid cell
   font size. padding-right stays for the numeric spinner. */
.rz-data-grid-data td .rz-numeric,
.rz-data-grid-data td .rz-textbox,
.rz-data-grid-data td .rz-dropdown,
.rz-data-grid-data td .rz-multiselect,
.rz-data-grid-data td .rz-datepicker,
.rz-data-grid-data td .rz-form-field-content {
    font-size: var(--rz-grid-cell-font-size) !important;
}

.rz-data-grid-data td .rz-numeric-input,
.rz-data-grid-data td input.rz-textbox,
.rz-data-grid-data td .rz-datepicker input,
.rz-data-grid-data td .rz-dropdown-label {
    padding-inline-start: 0 !important;
    font-size: inherit !important;
    /* The column's TextAlign, not Radzen's rz-text-align-left, so centred
       values do not jump left on click. */
    text-align: inherit !important;
}

/* Display templates wrap values in <RadzenText> (Body1) while editors use the
   grid cell font: body cells use one font, so the value does not change on click. */
.rz-data-grid-data td .rz-cell-data [class*="rz-text-"]:is(p, span, div, h1, h2, h3, h4, h5, h6) {
    font-family: inherit !important;
    font-size: var(--rz-grid-cell-font-size) !important;
    line-height: var(--rz-grid-cell-line-height) !important;
    letter-spacing: normal !important;
    /* Body1's bottom margin would pin the text to the top, while the editor
       sits centred in the td. */
    margin: 0 !important;
}

/* ...and that only lines up if the editor spans the same box as the
   display text, i.e. the whole cell. */
.rz-data-grid-data td .rz-numeric:not(.rz-form-field .rz-numeric),
.rz-data-grid-data td .rz-textbox:not(.rz-form-field .rz-textbox),
.rz-data-grid-data td .rz-form-field {
    width: 100% !important;
    /* the transparent 1px border would still nudge the text 1px right */
    border-inline-width: 0 !important;
}

/* Without up/down buttons there is nothing to reserve room for on the
   right; the 20px would pull centred and right-aligned values off-axis. */
.rz-data-grid-data td .rz-numeric:not(:has(.rz-numeric-up)) .rz-numeric-input {
    padding-inline-end: 0 !important;
}

/* ─── CAROUSEL ─── */
/* GLASSS features strip, after the reference flickity carousel: uniform 460px
   cards ~340px wide, no snap, arrows, dots or autoplay. */
#features .feat-strip {
    display: flex;
    gap: 24px;
    overflow-x: auto;
    /* No scroll-snap: the strip stops where the drag is released. */
    /* X only, so a horizontal swipe stops at the edge while vertical wheel
       scrolling still reaches the page. */
    overscroll-behavior-x: contain;
    /* A scroll container clips at its padding box: leave room for the card
       shadow, including on hover. */
    padding: 3rem max(2.5rem, 4vw) 5rem;
    scrollbar-width: none;
    -webkit-user-select: none;
    user-select: none;
    cursor: grab;
}

#features .feat-strip::-webkit-scrollbar { display: none; }

/* Native image drag fires pointercancel and kills the drag gesture (also
   prevented in brand.js). */
#features .feat-strip img,
#glasshopper-components .gh-comp-strip img { -webkit-user-drag: none; }

#features .feat-strip.dragging { cursor: grabbing; }

#features .feat-card {
    flex: 0 0 min(340px, 84vw);
}

/* No padding override: the global .card-glass padding is !important. The
   line clamp below keeps long copy inside the fixed height. */
#features .card-glass {
    height: 460px;
}

#features .card-glass img {
    height: 200px;
    flex-shrink: 0;
    object-fit: cover;
    object-position: top;
    margin-bottom: 1.25rem;
}

/* Long copy gets ellipsized instead of overflowing the fixed 460px card */
#features .card-glass p {
    font-size: 0.9rem;
    line-height: 1.55;
    display: -webkit-box;
    -webkit-line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Below lg the reference uses full-width cells (col-12) */
@media (max-width: 991.98px) {
    #features .feat-card { flex-basis: 100%; }
}

/* GLASSShopper components strip - uniform card sizes
   (ported from reference #glasshopper-components flickity rules) */
#glasshopper-components .gh-comp-strip {
    display: flex;
    gap: 24px;
    overflow-x: auto;
    /* No scroll-snap and X-only overscroll, as on .feat-strip. */
    overscroll-behavior-x: contain;
    /* Shadow room, as on .feat-strip. */
    padding: 3rem max(2.5rem, 4vw) 5rem;
    scrollbar-width: none;
    -webkit-user-select: none;
    user-select: none;
    cursor: grab;
}

#glasshopper-components .gh-comp-strip::-webkit-scrollbar { display: none; }

#glasshopper-components .gh-comp-strip.dragging { cursor: grabbing; }

#glasshopper-components .gh-comp-card {
    flex: 0 0 320px;
}

#glasshopper-components .card-glass {
    height: 310px;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

#glasshopper-components .card-glass img {
    height: 180px;
    width: 100%;
    object-fit: contain;
    object-position: center;
    background: var(--brand-card);
    padding: 0.5rem;
    margin-bottom: 1.5rem;
    border-radius: 10px;
}

#glasshopper-components .card-glass p {
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0 1rem;
}

/* ─── REVEAL ANIMATION ─── */
.reveal {
    opacity: 0;
    transform: translateY(20px);
    transition:
        opacity 0.60s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.60s cubic-bezier(0.16, 1, 0.3, 1);
}

.reveal.visible { opacity: 1 !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
    .reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ─── NEWSLETTER BUTTON + DIALOG (public pages) ─── */
/* Above the footer (2), below Radzen's dialog mask (1000) and the navbar (1030). */
.newsletter-fab {
    position: fixed;
    right: 1.5rem;
    bottom: 4rem;
    z-index: 990;
    display: inline-flex;
    align-items: center;
    height: 56px;
    padding: 0 1.1rem;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--brand-secondary);
    color: #fff;
    font-family: var(--font);
    font-size: 0.9rem;
    font-weight: 600;
    box-shadow: 0 4px 16px rgba(var(--brand-secondary-rgb),0.30);
    cursor: pointer;
    transition: background 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.newsletter-fab .fe {
    font-size: 1.3rem;
    line-height: 1;
}

.newsletter-fab-label {
    max-width: 0;
    margin-left: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    transition: max-width 0.3s ease, margin-left 0.3s ease, opacity 0.2s ease;
}

.newsletter-fab:hover,
.newsletter-fab:focus-visible {
    background: var(--brand-secondary-dark);
    box-shadow: 0 8px 24px rgba(var(--brand-secondary-rgb),0.40);
    transform: translateY(-2px);
}

.newsletter-fab:hover .newsletter-fab-label,
.newsletter-fab:focus-visible .newsletter-fab-label {
    max-width: 12rem;
    margin-left: 0.6rem;
    opacity: 1;
}

@media (max-width: 575.98px) {
    .newsletter-fab {
        right: 1rem;
        bottom: 7.5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .newsletter-fab,
    .newsletter-fab-label {
        transition: none;
    }
}

.newsletter-dialog-img {
    max-height: 220px;
}

/* Radzen docks dialogs at the top on phones, under the fixed navbar (which stacks above
   dialogs): start below it. Four classes to beat Radzen's rule, which loads later. */
@media (max-width: 768px) {
    .rz-dialog-wrapper .rz-dialog.newsletter-dialog:not(.rz-dialog-alert) {
        inset-block-start: var(--navbar-h) !important;
    }

    .newsletter-dialog-img {
        max-height: 140px;
    }
}

/* Subscribe button - brand styling, never clipped */
.newsletter-dialog .newsletter-subscribe {
    flex: 0 0 auto;
    font-family: var(--font);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-transform: none;
    white-space: nowrap;
    background: #2F6CB0;
    color: #fff !important;
    border: none;
    border-radius: var(--radius);
    padding: 0.85rem 1.75rem;
    box-shadow: 0 4px 16px rgba(47,108,176,0.30);
    transition: all 0.2s ease;
}

.newsletter-dialog .newsletter-subscribe:hover:not(.rz-state-disabled) {
    background: #255A9A;
    box-shadow: 0 8px 24px rgba(47,108,176,0.40);
    transform: translateY(-2px);
}

/* ─── FOOTER ─── */
/* The navbar's soft shadow, mirrored upward, so the two bars that frame
   the page read as a pair. */
footer,
.rz-footer {
    box-shadow: 0 -2px 20px rgba(var(--brand-primary-rgb),0.08) !important;
    /* The sidebar (z-index 1) and the positioned content cards paint over
       a static footer, so the shadow only showed on the bare page
       background. Stack the footer above them, below the navbar (1030). */
    position: relative;
    z-index: 2;
}

/* Satin treatment for the public hero pages only; every other page keeps the
   plain Radzen footer. */
body:has(#top.hero-video) footer,
body:has(#top.hero-video) .rz-footer {
    background: rgba(255,255,255,0.50) !important;
    backdrop-filter: var(--glass-blur) !important;
    -webkit-backdrop-filter: var(--glass-blur) !important;
    border-top: var(--glass-border) !important;
}

body:has(#top.hero-video) footer p,
body:has(#top.hero-video) footer a,
body:has(#top.hero-video) .rz-footer p,
body:has(#top.hero-video) .rz-footer a { color: var(--ink-2) !important; }

/* Footer legal links: an invisible ::after enlarges the tap target without
   changing the footer height; the overline text grows on narrow screens. */
.rz-footer .rz-link {
    position: relative;
}

.rz-footer .rz-link::after {
    content: "";
    position: absolute;
    inset: -0.5rem -0.25rem;
}

@media (max-width: 991.98px) {
    .rz-footer .rz-text-overline { font-size: 0.75rem; }
}

/* Mobile menu: transparent tap-outside layer + page scroll lock while open.
   Viewport units, not inset/100%, so it covers the screen whatever its
   containing block. */
.nav-backdrop { display: none; }

@media (max-width: 991.98px) {
    .nav-backdrop {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        height: 100dvh;
        z-index: 1029;
        background: transparent;
    }

    html:has(#navbarCollapse.show),
    body:has(#navbarCollapse.show) {
        overflow: hidden !important;
    }
}

/* ─── RESPONSIVE ─── */
@media (max-width: 768px) {
    section { padding: 80px 0; }
    /* Narrower horizontal inset; the vertical 2rem keeps the wrapped buttons'
       shadow clear of the hero's overflow:hidden edge. */
    .hero-content { padding: 2rem 1.5rem; }
    .display-4 { font-size: 1.9rem; }
    .card-glass { padding: 2rem !important; }
}

/* ===== SIDEBAR WORKSPACE TREE ===== */
.workspace-tree-host { list-style: none; }
.workspace-tree-placeholder { display: none !important; }
/* Glass editors opened as a context-menu popover (package, spacer, supports)
   have no surface of their own; give them the panel background there. In a
   dialog the dialog already provides it. */
.rz-context-menu .glass-editor {
    background-color: var(--rz-panel-background-color);
    border: var(--rz-panel-border);
    border-radius: var(--rz-border-radius, 8px);
    box-shadow: var(--rz-shadow-2);
    /* Top is reduced by the 0.5rem every outlined form field already
       reserves above itself for its floating label. */
    padding: 0.25rem 0.75rem 0.75rem !important;
}
/* Editors without an outlined field (e.g. surface coating) have nothing
   reserved above, so they get even padding. */
.rz-context-menu .glass-editor:not(:has(.rz-form-field)) { padding: 0.75rem !important; }
/* Bounded both ways: a long or deeply nested tree scrolls inside the sidebar
   instead of pushing the menu below it off screen or clipping on the right. */
.workspace-tree { max-height: min(45vh, 24rem); max-width: 100%; overflow: auto; padding: 0.25rem 0.5rem 0.5rem 1rem; }
.workspace-tree .rz-tree { width: max-content; min-width: 100%; }
.workspace-tree .rz-tree { background: transparent !important; border: 0 !important; padding: 0 !important; }
.workspace-tree .rz-treenode-content { padding-block: 0.125rem !important; font-size: 0.8125rem; }
.workspace-tree-item { display: inline-flex; align-items: center; gap: 0.375rem; min-width: 0; }
.workspace-tree-item .rzi { font-size: 1.125rem !important; color: var(--rz-text-secondary-color); }
.workspace-tree-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 11rem; }
/* The open file is marked like the data grid's active cell: a 2px gold
   bar on the bottom edge (no background tint), sized to the label (icon +
   name) like Radzen's own selected-node fill rather than the full row. */
.workspace-tree .rz-treenode-content-selected .rz-treenode-label { background-color: transparent !important; color: inherit !important; }
.workspace-tree .rz-treenode-label:has(.workspace-tree-item.is-current) {
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: inset 0 -2px 0 var(--brand-accent-dark);
}
.workspace-tree-item.is-current { font-weight: 600; color: var(--brand-primary); }
.workspace-tree-item.is-current .rzi { color: inherit; }
.workspace-tree-empty { display: block; padding: 0.25rem 0; color: var(--rz-text-tertiary-color); }
/* ===== WORKSPACE GRID DRAG & DROP ===== */
/* Row being dragged fades; the folder it would drop into is highlighted. */
.rz-data-row[data-drag-state="source"] > td { opacity: 0.45; }
.rz-data-row[data-drag-state="target"] > td {
    background-color: var(--rz-primary-lighter) !important;
    box-shadow: inset 0 1px 0 var(--brand-secondary), inset 0 -1px 0 var(--brand-secondary);
}

/* ===== CLICKABLE GRID ROWS ===== */
/* Grids that open a row on click (admin lists); RowLink keeps the main value a real link for Ctrl/middle-click. */
.clickable-rows .rz-data-row { cursor: pointer; }
.clickable-rows a.row-link:hover { text-decoration: underline; }

/* Account and Organization settings: wider than container-xl on large screens, full width
   (inside the gutters) once the nav stacks above the content. */
@media (min-width: 992px) {
    .manage-container { max-width: 80%; }
}

/* Account > Manage nav: below lg the side card becomes a horizontally scrolling
   pill bar above the content. */
@media (max-width: 991.98px) {
    .manage-nav .card-body { padding: .75rem; }
    .manage-nav h6 { display: none; }
    .manage-nav .card-list {
        display: flex;
        gap: .5rem;
        margin: 0 !important;
        padding: 0;
        overflow-x: auto;
        scrollbar-width: none;
        scroll-snap-type: x proximity;
    }
    .manage-nav .card-list::-webkit-scrollbar { display: none; }
    .manage-nav .card-list .list-item { flex: 0 0 auto; margin: 0; scroll-snap-align: start; }
    .manage-nav .card-list .list-link {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 1rem;
        border: 1px solid var(--bs-gray-300);
        border-radius: 999px;
        white-space: nowrap;
        text-decoration: none;
    }
    .manage-nav .card-list .list-link:before { display: none !important; }
    .manage-nav .card-list .active .list-link {
        background: var(--bs-primary);
        border-color: var(--bs-primary);
        color: #fff !important;
    }
}

/* Mobile drawer layout: left-aligned rows sized to their label (so the active
   underline spans only the name), no dividers, full-width Sign in button. */
@media (max-width: 991.98px) {
    .navbar .navbar-collapse {
        border-radius: var(--radius) !important;
        padding: 0.75rem !important;
    }

    .navbar .navbar-collapse .navbar-nav {
        align-items: stretch !important;
        text-align: left !important;
        gap: 0.125rem !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    .navbar .navbar-collapse .navbar-nav > .nav-item {
        border: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    .navbar .navbar-collapse .navbar-nav > .nav-item > .nav-link:not(.dropdown-toggle) {
        display: inline-flex;
        align-items: center;
        width: fit-content;
        min-height: 44px;
        font-size: 1rem;
        font-weight: 600;
        padding: 0.5rem 0.75rem !important;
        border-radius: 8px;
    }

    .navbar .navbar-collapse .navbar-nav > .nav-item > .nav-link.active {
        background-position: 0.75rem calc(100% - 6px);
        background-size: calc(100% - 1.5rem) 2px;
    }

    /* Sign in: one divider above, then a full-width button */
    .navbar .navbar-collapse .navbar-nav > .nav-item:has(> .btn) {
        border-top: 1px solid var(--bs-border-color, #e9ecef) !important;
        margin-top: 0.5rem !important;
        padding-top: 0.75rem !important;
    }

    .navbar .navbar-collapse .navbar-nav > .nav-item > .btn {
        display: flex;
        justify-content: center;
        width: 100%;
    }
}

/* Dropdowns in centred grid columns: Radzen pins .rz-dropdown to
   text-align:start, so the control inherits the cell's alignment too. No leading
   label pad: in-cell triggers are hidden (see READ-ONLY GRID CELLS below). */
.rz-data-grid-data td[style*="text-align:center"] .rz-dropdown {
    text-align: inherit !important;
}

.rz-data-grid-data td[style*="text-align:center"] .rz-dropdown-label {
    padding-inline-start: 0 !important;
}

/* ===== CHECK OPTIONS GRIDS ===== */
/* Option tables keep readable columns and scroll sideways on narrow screens
   instead of squeezing every dropdown to an ellipsis. */
/* 5 option columns x ~150px + package/pane/f_gk: below that the dropdown
   values truncate. The grid's own data area (overflow:auto) scrolls. */
.options-grid .rz-grid-table { min-width: 64rem; }
/* The flex column and the @ref wrapper default to min-width:auto, which let
   the table's min-width push the whole card wider than the screen instead of
   handing the overflow to the grid. */
.rz-col:has(.options-grid),
div:has(> .options-grid) { min-width: 0; max-width: 100%; }
div:has(> .options-grid) { width: 100%; }

/* ===== READ-ONLY GRID CELLS / IN-CELL DROPDOWNS ===== */
/* Columns the user cannot edit in an editable grid carry CssClass="cell-readonly":
   grey fill and secondary text. Frozen cells set their own background, hence
   the td.cell-readonly specificity + !important. */
.rz-data-grid-data td.cell-readonly {
    background-color: var(--rz-base-100) !important;
    color: var(--rz-text-secondary-color);
}
.rz-data-grid-data td.cell-readonly .rz-text { color: inherit; }
/* Every other row a shade darker, so a run of grey cells still reads row by row. */
.rz-data-grid-data tr.rz-data-row:nth-child(even) > td.cell-readonly {
    background-color: var(--rz-base-200) !important;
}

/* In-cell dropdowns drop their arrow: the cell is the affordance, and the arrow
   takes ~2rem of every narrow column. Filter-row dropdowns (in the th) keep theirs. */
.rz-data-grid-data td .rz-dropdown .rz-dropdown-trigger { display: none !important; }
.rz-data-grid-data td .rz-dropdown { cursor: pointer; }
.rz-data-grid-data td .rz-dropdown .rz-dropdown-label { padding-inline-end: 0 !important; }

/* Tooltips that show a reference table image (Loads sheet): Radzen caps tooltip content at 480px. */
.image-tooltip .rz-tooltip-content,
.rz-tooltip-content.image-tooltip {
    max-width: calc(100vw - 32px);
}

/* Tables, cards, panels and dialogs share the brand radius (see --radius). */
.rz-data-grid,
.rz-card,
.rz-panel,
.rz-dialog,
.rz-fieldset,
.rz-tabview-panels,
/* Sheet sections (RadzenRow/RadzenStack with rz-shadow-1) and Bootstrap cards. */
.rz-shadow-1,
.card {
    border-radius: var(--radius) !important;
}

/* Thermal control data: outlined fields in an even grid instead of side labels. */
.thermal-fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 1rem;
}

/* Switches inside grid cells (e.g. the Ortho column of the load grids): Material's checked track is
   a 12% tint of the primary color, which almost vanishes on the highlighted (selected) row. Use a
   solid primary track with a white knob instead. */
.rz-data-grid-data td .rz-switch.rz-switch-checked .rz-switch-circle {
    background: var(--rz-primary);
}

.rz-data-grid-data td .rz-switch.rz-switch-checked .rz-switch-circle::before {
    background: var(--rz-white, #fff);
}

/* The cell wrapper truncates text with overflow:hidden, which clips the switch knob (taller than the
   track) and its shadow. Let cells that hold a switch overflow. */
.rz-data-grid-data td .rz-cell-data:has(> .rz-switch) {
    overflow: visible;
}

/* Loads list (LoadSelector.razor): the selected load card renders as Radzen's outlined variant, which
   looks greyed out. Mark it like other brand selections instead: same white card and shadow as the
   others, plus a uniform gold border. */
#loadsList .rz-card.rz-variant-outlined {
    background-color: var(--rz-base-background-color, #fff);
    border: 1px solid var(--brand-accent);
    box-shadow: 0 1px 3px rgba(var(--brand-accent-rgb), 0.35);
}

/* Barrier/Point loads grids (Loads.razor, #loadOptions): row selection only tells "Delete load" which
   row to remove. Keep the selected row looking like the others (white/striped background, normal text),
   like the other sheet grids, instead of Radzen's blue highlight. */
#loadOptions .rz-selectable tbody tr.rz-data-row.rz-state-highlight > td {
    background-color: var(--rz-grid-background-color);
}

#loadOptions .rz-selectable .rz-grid-table-striped tbody tr.rz-data-row.rz-state-highlight:nth-child(even) > td {
    background-color: var(--rz-grid-stripe-background-color);
}

#loadOptions .rz-selectable tbody tr.rz-data-row.rz-state-highlight .rz-cell-data {
    color: var(--rz-grid-cell-color);
}
