html, body {
    font-family: 'Segoe UI', Helvetica, Arial, sans-serif;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    /* Reserves the vertical scrollbar's width whether or not it's actually
       showing - without this, .account-menu (position: fixed; right: 1rem)
       shifts sideways by the scrollbar's width every time a page's content
       crosses from shorter-than-viewport to taller-than-viewport (e.g. a
       DxLoadingPanel's placeholder resolving into its real, taller content),
       since a "right"-anchored fixed element sits flush against whichever
       edge the scrollbar currently occupies. */
    scrollbar-gutter: stable;
    /* Scroll bars in the theme's colour everywhere (user, 2026-10-12: "side nav bar scroll need come with theme based, same for the
       splitter") - scrollbar-color is inherited, so every scrolling area (lists, splitter panes, popups) follows; the side menu sets
       its own light thumb below because it sits on the dark brand colour. */
    scrollbar-color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 55%, transparent) transparent;
}

/* A slightly raised surface that follows the theme (user, 2026-10-12: "card foreground and background goes white"): the DevExpress dark
   themes do not redefine --bs-tertiary-bg, so a card on it stayed Bootstrap's light grey under the theme's white text. Mixed from the
   theme's own text and background colours, it is a light grey on a light theme and a lifted dark tone on a dark one. Use it for
   card-like boxes instead of --bs-tertiary-bg / bg-light / #fff. */
:root {
    --vk-surface: color-mix(in srgb, var(--bs-body-color) 5%, var(--bs-body-bg));
}

/* min-height, not left to the sidebar: the side navigation is hidden until
   asked for, so nothing else gives the page the height of the window - and
   without it the print preview (a flex-fill child) has no height to fill and
   is not shown. */
.page {
    display: flex;
    min-height: 100vh;
}

/* Hidden at every screen width until the hamburger is clicked - the toggler
   then reveals it as a fixed overlay over the page (see the checked rule
   below) and clicking it again (or picking a screen) hides it. Keeping it out
   of the flow means .content always has the full width, including for the
   print preview. */
.sidebar {
    display: none;
    background-color: var(--bs-primary);
    color: var(--bs-light);
    width: 280px;
    flex-shrink: 0;
    min-height: 100vh;
    flex-direction: column;
    /* Its own scroll bar: a light thumb on the brand-coloured column, thin. */
    scrollbar-color: rgba(255, 255, 255, 0.45) transparent;
    scrollbar-width: thin;
}

.page:has(.navbar-toggler:checked) .sidebar {
    display: flex;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1025;
    box-shadow: 4px 0 16px rgba(0, 0, 0, 0.3);
}

/* Hides/shows the sidebar's nav menu - a plain checkbox (unstyled, drawn as
   a circular hamburger button via its own background-image) rather than a
   Blazor event handler, so toggling it needs no server round-trip. It's a
   sibling of .sidebar (both children of .page in MainLayout), not a
   descendant of it - collapsing .sidebar sets overflow: hidden on it, which
   would otherwise clip this fixed-position button along with everything
   else, leaving no way to reach it again once collapsed. :has() on their
   shared ancestor .page reaches across to style the toggler's targets based
   on its checked state instead of a plain sibling combinator. */
.navbar-toggler {
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    width: 2.5rem;
    height: 2.5rem;
    position: fixed;
    top: 1rem;
    left: 1rem;
    z-index: 1030;
    background-color: var(--bs-primary);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.85)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 1.5rem;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}

/* While the side menu is open the same round button shows an X (close) in place of the three lines (open): only the
   icon changes, so the button's place and size stay put and it is clear which way it will act. */
.navbar-toggler:checked {
    filter: brightness(0.85);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.95)' stroke-width='2.4' stroke-linecap='round' stroke-miterlimit='10' d='M7 7l16 16M23 7L7 23'/%3e%3c/svg%3e");
}

.account-logo {
    display: block;
    max-width: 260px;
    width: 100%;
    height: auto;
    margin: 0 auto 1.5rem;
}

/* Whenever .sidebar itself is showing (mobile overlay or desktop in-flow -
   see .sidebar's own rules above), this just always renders - visibility is
   entirely .sidebar's own job now, not a second toggle duplicated here.
   padding-top clears the fixed .navbar-toggler button, which sits over the
   sidebar's top-left corner regardless of viewport size. */
.nav-scrollable {
    display: flex;
    flex: 1;
    flex-direction: column;
    justify-content: space-between;
    overflow-y: auto;
    padding-top: 4.5rem;
}

.nav-scrollable .nav-link {
    color: var(--bs-light);
    opacity: 0.85;
    padding: 0.5rem 0;
}

.nav-scrollable .nav-link:hover,
.nav-scrollable .nav-link.active {
    opacity: 1;
    font-weight: 600;
}

main {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

.content {
    flex: 1;
    min-height: 0;
    /* Column flex, not the default block, so a flex-fill-height child (e.g.
       Manage Modules' .module-editor-root) can actually stretch to fill
       whatever's left under .page-header - .content itself being flex:1
       only bounds *its own* height (via main, which is the flex column
       above it); without display: flex here too, that bound never reaches
       .content's own children, so a nested splitter/grid was sizing itself
       off an unconstrained, content-driven height instead of the real
       viewport space, silently breaking any drag/collapse math built on
       "fill the rest of the page". */
    display: flex;
    flex-direction: column;
    /* No padding-top: .page-header (below) is always the first thing here
       and supplies its own top spacing via its own padding - a padding-top
       here would leave a gap of .content's own background above the header
       instead of the header sitting flush against it. */
    padding-bottom: 1.5rem;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
}

/* Page title, sat at the top of every page's own content - no background fill (transparent, sits directly on
   .content's own white) and no divider line under it either; the margin below it is enough to separate it from the
   page content. Two stacked lines (brand lockup, then the current page name directly under it) sharing this same
   left/right padding, so the second line lines up under the first without its own separate indent. */
.page-header {
    background-color: transparent;
    color: var(--bs-emphasis-color);
    margin: 0 0 1.25rem;
    padding: 0.5rem 0 0.75rem;
    /* Both fixed-position circles (.navbar-toggler on the left,
       .account-menu on the right) are 2.5rem tall starting at top: 1rem,
       so their own bottom edge sits at 3.5rem - this keeps the header (and
       it) at least that tall so neither circle's own bottom edge pokes below the header. */
    min-height: 4rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.35rem;
    /* .sidebar is display: none until the toggler is clicked (see its own
       rule), so .page-header otherwise starts flush at the viewport's left
       edge, right under the still-fixed .navbar-toggler button. */
    padding-left: 3.5rem;
    /* Clears the fixed-position .account-menu avatar at the opposite
       corner (same reasoning as DatabaseAdmin.razor's own pe-5 in
       MyAccount) - both stacked lines share it, since either could
       otherwise run into the avatar's own space on a narrow viewport. */
    padding-right: 10.5rem;   /* bell, magnifier and profile button (each 2.5rem + gaps) */
    flex-shrink: 0;
}

/* One single color for the whole title line (mark, wordmark, badge outline
   + text, and the current page name) - var(--bs-primary), so it always
   matches whichever DevExpress theme is selected instead of the badge
   staying a fixed brand orange while everything else went a separate
   theme-neutral color. */
.page-header-brand {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.6rem;
    text-decoration: none;
    color: var(--vk-brand, var(--bs-primary)) !important;
}

.page-header-brand:hover,
.page-header-brand:focus {
    opacity: 0.8;
}

/* The current page's own name, on its own line directly under the brand -
   no "/" prefix (that only made sense inline next to the brand) and no
   separate "Home" crumb, since the brand itself already is the way back
   home. */
.page-header-current {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--vk-brand, var(--bs-primary));
    display: block;
}

/* Smaller brand lockup on mobile/tablet only - desktop (the >= 768px
   breakpoint already used everywhere else for the sidebar collapse)
   keeps the full size. The Razor components render at that full size via
   their own Height/Size parameters; this just overrides it below 768px,
   since SVG's own height attribute loses to a CSS height rule. */
@media (max-width: 767.98px) {
    .page-header-mark,
    .page-header-wordmark,
    .page-header-badge {
        height: 14px !important;
        width: auto !important;
    }

    .page-header-current {
        font-size: 0.65rem;
    }
}

/* NotFound / NotAuthorized (CoreRoutes.razor): a plain centered message and
   two ways out, instead of bare unstyled text sitting flush at the top of
   .content - which, with no .page-header above it supplying the top
   clearance every real page gets, used to render right under (and get
   visually clipped by) the fixed navbar-toggler/account-menu circles. */
.core-error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.25rem;
    text-align: center;
    padding: 3rem 1.5rem;
    margin: 0 auto;
    max-width: 26rem;
}

.core-error-message {
    font-size: 1.05rem;
    color: var(--bs-secondary-color, var(--bs-body-color));
    margin: 0;
}

.core-error-actions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    justify-content: center;
}

.module-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13.75rem, 1fr));   /* was 220px: in rem, so it follows the Font size setting */
    gap: 1rem;
}

/* The icon BESIDE the caption (at most two lines, then "..."), the description below both (user, 2026-10-14: "icon next to that, two lines if
   needed, otherwise ...; the card was too tall"). */
.module-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "icon caption" "text text";
    align-items: center;
    align-content: start;
    column-gap: 0.65rem;
    row-gap: 0.45rem;
    padding: 1rem 1.1rem;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    text-align: left;
    cursor: pointer;
    /* The card is a <button>, which does not inherit the page's text colour or font: without these the title came out
       in the browser's dark button text, unreadable on a dark theme. */
    color: var(--bs-body-color);
    font: inherit;
    transition: box-shadow 0.2s ease, border-color 0.2s ease, background-color 0.2s ease, transform 0.2s ease;
}

/* Hover / keyboard focus: the card lights up in the theme skin's own colour - a tinted background, a coloured edge
   and a soft glow of the same colour - so every skin glows in its own tone. --vk-brand is the readable tone of the
   theme colour (see appearance.js); --bs-primary when that is not needed. */
.module-card:hover,
.module-card:focus-visible,
.module-card:focus {
    border-color: var(--vk-brand, var(--bs-primary));
    background-color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 7%, var(--bs-body-bg));
    box-shadow:
        0 0 0 1px var(--vk-brand, var(--bs-primary)),
        0 0 20px color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 45%, transparent),
        0 10px 26px rgba(0, 0, 0, 0.12);
    transform: translateY(-2px);
    outline: none;
}

.module-card:active {
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .module-card,
    .module-card:hover,
    .module-card:focus-visible,
    .module-card:focus {
        transition: none;
        transform: none;
    }
}

.module-card-caption {
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--bs-body-color);
}

/* At most two lines, then "..."; the full text is the card's hover tooltip (cards.js) once it does not fit. */
.module-card-description {
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.account-shell {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    padding: 1.5rem;
}

.account-page {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
}

.account-card {
    width: 100%;
    max-width: 400px;
}

.account-title {
    font-size: 1.75rem;
    font-weight: 700;
    margin-bottom: 0.375rem;
    /* Blazor's FocusOnNavigate (Routes.razor) moves focus to this heading on every page load - a genuine
       accessibility feature (a screen reader announces the page title), kept here. The script below moves the
       keyboard focus itself on to the Email box right after, but the moment on this heading still flashes a
       visible focus ring first; suppressing just the outline (not the focus move) removes that flash without
       touching the accessibility behaviour or any other page's heading. */
    outline: none;
}

.account-subtitle {
    color: var(--bs-secondary-color);
    margin-bottom: 2rem;
}

.account-demo-hint {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    margin-bottom: 1.5rem;
    white-space: pre-line;
    word-break: break-word;
}

.account-field {
    margin-bottom: 1.25rem;
}

.account-field input {
    width: 100%;
    background-color: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: 0.5rem 0.75rem;
    color: var(--bs-emphasis-color);
}

.account-field input:focus {
    outline: none;
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), 0.15);
}

.account-field-label-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
}

.account-forgot-link {
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
    text-decoration: none;
    white-space: nowrap;
}

.account-forgot-link:hover,
.account-forgot-link:focus {
    color: var(--bs-primary);
    text-decoration: underline;
}

.account-password-wrapper {
    position: relative;
}

/* The sign-in password box draws its dots itself (Login.razor script), so the browser sees no password field and offers no suggestions. */
.account-password-wrapper input[data-masked="true"] { -webkit-text-security: disc; text-security: disc; }
.account-password-wrapper input {
    padding-right: 2.75rem;
}

/* Sits on top of the input's own --bs-tertiary-bg (a light surface in every
   theme here, even the ones whose page background is dark), so like that
   input's text color, this needs --bs-emphasis-color rather than
   --bs-secondary-color/--bs-body-color - those are tuned for the page
   background and would render white-on-white on this field. */
.account-password-toggle {
    position: absolute;
    top: 50%;
    right: 0.9rem;
    transform: translateY(-50%);
    background: none;
    border: none;
    padding: 0;
    display: flex;
    color: var(--bs-emphasis-color);
    opacity: 0.6;
    cursor: pointer;
}

.account-password-toggle:hover,
.account-password-toggle:focus {
    opacity: 1;
}

.account-password-toggle svg {
    fill: currentColor;
}

/* Login: "Caps Lock is on" under the password box while it's being typed. An
   amber pill with dark text, readable on the light and the dark themes' cards
   alike - the theme's warning-emphasis text colour is a dark brown in every
   theme (made for light backgrounds) and vanished on Blazing Dark. */
.account-capslock {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    padding: 0.15rem 0.65rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    background-color: var(--bs-warning, #ffc107);
    color: #2b1d00;
}

.account-capslock[hidden] {
    display: none;
}

/* The hosting build's picture of characters (SignInCaptcha): the picture with its refresh button, the answer box below. */
.account-captcha-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.account-captcha-image { width: 180px; height: 56px; border-radius: 0.5rem; border: 1px solid var(--bs-border-color); background: #f2eefa; user-select: none; }
.account-captcha-refresh {
    width: 2.2rem; height: 2.2rem; border-radius: 50%; border: 1px solid var(--bs-border-color); background: transparent; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; color: var(--vk-brand, var(--bs-primary));
}
.account-captcha-refresh:hover { background-color: color-mix(in srgb, var(--bs-body-color) 8%, transparent); }
.account-captcha input#captchaText { text-transform: uppercase; letter-spacing: 0.2em; }

.account-remember-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.account-remember-row input[type="checkbox"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--bs-primary);
    cursor: pointer;
}

.account-remember-row label {
    font-size: 0.9rem;
    color: var(--bs-body-color);
    cursor: pointer;
}

.account-footer {
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--bs-border-color);
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
}

.account-footer-version {
    margin-left: 0.5rem;
    opacity: 0.7;
}

.account-footer-version::before {
    content: "\00b7";
    margin-right: 0.5rem;
}

.account-submit {
    width: 100%;
    background-color: var(--bs-primary);
    border: none;
    color: var(--bs-light);
    font-weight: 600;
    padding: 0.875rem;
    border-radius: 50rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem; /* breathing room between "Sign In" and the door icon */
    text-decoration: none;
    transition: filter 0.15s ease;
}

.account-submit:hover,
.account-submit:focus {
    filter: brightness(1.08);
    color: var(--bs-light);
}

/* Request a demo (the hosted demo site): the small link under Sign In, the honeypot box nobody sees, and the thank-you. */
.account-demo-request {
    margin-top: 1rem;
    text-align: center;
}

.demo-request-hp {
    position: absolute;
    left: -10000px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.demo-request-thanks {
    background-color: var(--vk-surface, var(--bs-body-bg));
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-left: 4px solid var(--vk-brand, var(--bs-primary));
    border-radius: var(--bs-border-radius);
    padding: 1rem 1.25rem;
    margin-bottom: 1.25rem;
}

/* Small round avatar/menu fixed to the top-right corner - a sibling of
   .sidebar in MainLayout (see AccountMenu.razor's own comment), so
   collapsing the sidebar never clips it. */
.account-menu {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1030;
}

.account-menu-toggle {
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background-color: var(--bs-primary);
    cursor: pointer;
    flex-shrink: 0;
}

.account-menu-avatar {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bs-light);
    font-weight: 600;
    font-size: 1rem;
}

.account-menu-avatar-placeholder {
    background-color: rgba(255, 255, 255, 0.15);
}

.account-menu-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 1040;
    width: calc(100vw - 2rem);
    max-width: 220px;
    background-color: var(--bs-primary);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: var(--bs-border-radius);
    padding: 1rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.account-menu-panel .nav-link {
    padding: 0.4rem 0;
}

/* On the brand-coloured panel the rows are white like the e-mail above them (user, 2026-10-24: "change password, support pin not
   visible" - they had the default dark link colour): Change Password, the Support PIN, its digits and its eye / copy buttons. */
.account-menu-panel .nav-link,
.account-menu-panel .nav-link:hover,
.account-menu-panel .nav-link:focus,
.account-menu-panel .account-support-pin,
.account-menu-panel .account-support-pin .secret-value-text,
.account-menu-panel .account-support-pin .dxbl-btn {
    color: #fff !important;
}

.account-menu-panel .account-support-pin svg {
    fill: currentColor;
}

.account-menu-panel .nav-link:hover {
    text-decoration: underline;
}

.account-menu-close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 24px;
    height: 24px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    border-radius: 50%;
    color: var(--bs-light);
    cursor: pointer;
}

.account-menu-close:hover,
.account-menu-close:focus {
    background-color: rgba(255, 255, 255, 0.15);
}

.account-menu-close svg {
    fill: currentColor;
}

.profile-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid rgba(255, 255, 255, 0.3);
    cursor: pointer;
    flex-shrink: 0;
}

.profile-avatar-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(255, 255, 255, 0.15);
    color: var(--bs-light);
    font-weight: 600;
    font-size: 1.35rem;
}

.account-info {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.account-info-text {
    max-width: 100%;
    overflow: hidden;
}

.account-email {
    color: var(--bs-light);
    font-size: 0.85rem;
}

.account-role {
    font-size: 0.75rem;
}

/* Settings gear + expandable theme/font panel - used both in the sidebar
   (Dark, default) and as a small floating badge on the pre-login pages
   (Floating, via AccountLayout). */
.appearance-controls {
    padding: 0.25rem 0;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
}

/* Settings docked at the foot of the side menu, just above the version: pushed down by the free space, its panel drawn ABOVE the
   button (column-reverse) and sliding up after a short pause when opened (user, 2026-10-13). */
.nav-scrollable {
    justify-content: flex-start !important;
}

.nav-scrollable > .appearance-controls.settings-docked {
    margin-top: auto;
    display: flex;
    flex-direction: column-reverse;
    /* Only the OPEN panel inside may shrink (it scrolls); the block itself never does. With `flex: 0 1 auto; min-height: 0` on this
       block, a menu long enough to fill the column shrank the closed Settings bar to nothing and painted it over the last module
       item ("Financial Years" / "Settings" on top of each other - user, 2026-10-14). The bar now keeps its height; when the list is
       longer than the window the whole column scrolls (overflow-y on .nav-scrollable) and Settings stays at its foot. */
    flex: 0 0 auto;
}

.nav-scrollable > .appearance-controls.settings-docked > .settings-toggle {
    flex: 0 0 auto;
}

.nav-scrollable > nav,
.nav-scrollable > .sidebar-version {
    flex: 0 0 auto;
}

.appearance-controls.settings-docked .settings-panel {
    margin-top: 0 !important;
    margin-bottom: 0.5rem;
    /* Taller than the room left (a short window, a big font): the items scroll inside the panel, capped so the Settings bar and the
       version line below it stay in view. */
    max-height: calc(100vh - 14rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    animation: settings-slide-up 0.35s ease-out 0.15s both;
}

@keyframes settings-slide-up {
    from { opacity: 0; transform: translateY(1.5rem); }
    to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .appearance-controls.settings-docked .settings-panel { animation: none; }
}

.appearance-controls-floating {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.settings-toggle {
    color: var(--bs-light) !important;
    background: none;
    border: none;
}

.settings-toggle:hover,
.settings-toggle:focus {
    background-color: rgba(255, 255, 255, 0.1);
}

.settings-toggle.settings-toggle-light {
    color: var(--bs-emphasis-color) !important;
}

.settings-toggle.settings-toggle-light:hover,
.settings-toggle.settings-toggle-light:focus {
    background-color: rgba(0, 0, 0, 0.05);
}

.settings-toggle-floating {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 30;
    width: 2.75rem;
    height: 2.75rem;
    justify-content: center;
    padding: 0;
    border-radius: 50%;
    background-color: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color) !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.settings-toggle-floating .settings-gear {
    margin-right: 0;
    width: 1.15rem;
    height: 1.15rem;
}

.settings-gear {
    margin-right: 0.5rem;
    width: 1rem;
    height: 1rem;
    fill: currentColor;
    flex-shrink: 0;
}

.settings-caret {
    font-size: 0.65rem;
    opacity: 0.7;
}

.settings-panel {
    background-color: rgba(0, 0, 0, 0.15);
    border-radius: var(--bs-border-radius);
    padding: 0.75rem;
}

/* About block at the foot of the Settings panel: label / value pairs. */
.settings-about {
    border-top: 1px solid rgba(127, 127, 127, 0.35);
}

.settings-about-list {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 0.75rem;
    row-gap: 0.1rem;
}

.settings-about-list dt {
    font-weight: normal;
}

.settings-about-list dd {
    margin: 0;
    word-break: break-all;
}

.settings-panel-floating {
    position: fixed;
    top: 4.25rem;
    right: 1rem;
    z-index: 30;
    width: 220px;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: 1rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}

/* Change-password validation summary - lists every currently-invalid field. */
.validation-summary-box {
    border: 1px solid var(--bs-danger);
    border-radius: var(--bs-border-radius);
    background-color: rgba(var(--bs-danger-rgb), 0.08);
    padding: 0.5rem 0.75rem;
}

.validation-summary-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.validation-summary-list li {
    color: var(--bs-danger);
    padding: 0.15rem 0;
}

/* Document line editor (DocumentLinesEditor) - the itemised body of a
   proposal or invoice, DevExpress editors laid out in a plain table. */
.doc-lines .table {
    --bs-table-bg: transparent;
}

.doc-lines th {
    font-weight: 600;
    white-space: nowrap;
}

.doc-lines .doc-lines-no {
    width: 2.5rem;
    text-align: center;
}

.doc-lines .doc-lines-num {
    width: 11rem;
}

.doc-lines .doc-lines-unit {
    width: 8rem;
}

.doc-lines .doc-lines-actions {
    width: 7rem;
}

.doc-lines .doc-lines-amount {
    white-space: nowrap;
}

.doc-line-section td {
    background-color: rgba(var(--bs-primary-rgb), 0.08);
}

.doc-line-section .dxbl-text-edit input {
    font-weight: 600;
    text-transform: uppercase;
}

/* The form's own totals block under the lines. */
.doc-totals {
    max-width: 22rem;
    margin-left: auto;
}

.doc-totals div {
    display: flex;
    justify-content: space-between;
    padding: 0.15rem 0;
}

.doc-totals .doc-totals-grand {
    border-top: 1px solid var(--bs-border-color);
    font-weight: 700;
}

/* DocumentReportPage - the DevExpress report viewer fills the page below
   its Back bar. */
.report-viewer-page {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.report-viewer-frame {
    flex: 1;
    /* A floor as well as the flex fill: the viewer draws nothing at zero height. */
    min-height: 30rem;
}

/* Sidebar module groups (NavMenu): the module's caption is a link to its
   landing page; the chevron beside it expands the module's screens as
   indented child links, the current one highlighted. */
.nav-group-header {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.nav-group-header .nav-group-link {
    flex: 1;
    cursor: pointer;
    user-select: none;
}

/* The group holding the current screen reads as current even though its caption
   is no longer a link that can be "active". */
.nav-group-current > .nav-group-header .nav-group-link {
    opacity: 1;
    font-weight: 600;
}

.nav-group-toggle {
    background: none;
    border: none;
    color: var(--bs-light);
    opacity: 0.75;
    padding: 0.25rem;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    border-radius: 4px;
}

.nav-group-toggle:hover,
.nav-group-toggle:focus-visible {
    opacity: 1;
    background: rgba(255, 255, 255, 0.12);
}

.nav-group-toggle svg {
    transition: transform 0.15s ease;
}

.nav-group-toggle.expanded svg {
    transform: rotate(180deg);
}

.nav-group-pages {
    margin-left: 0.75rem;
    padding-left: 0.5rem;
    border-left: 1px solid rgba(255, 255, 255, 0.25);
    margin-bottom: 0.25rem;
}

.nav-scrollable .nav-page-link {
    padding: 0.3rem 0;
    font-size: 0.9rem;
}

.nav-scrollable .nav-page-link.active {
    color: #fff;
    opacity: 1;
    font-weight: 600;
}

/* A group liner between a module's screens (ModulePage.Divider()) - just a plain break in the list, so
   two loosely-related runs of screens (a job's money, then who supplies it) don't read as one
   undifferentiated group. Sits inside .nav-group-pages, so it keeps that container's own left border/
   indent rather than spanning the sidebar's full width. */
.nav-group-divider {
    margin: 0.4rem 0;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.2);
}

/* Page header's second line: "Module › Screen" inside a module. */
.page-header-module {
    color: var(--vk-brand, var(--bs-primary));
    opacity: 0.75;
    text-decoration: none;
}

.page-header-module:hover {
    opacity: 1;
    text-decoration: underline;
}

.page-header-separator {
    margin: 0 0.35rem;
    opacity: 0.6;
}

/* Money fields: text sits against the right edge, as on a ledger, with the
   validation-icon gutter staying on the left so nothing shifts when a value
   turns invalid. Grouping comes from the en-IN culture set in Program.cs
   (99,99,99,99,999.00). */
.amount-field .dxbl-text-edit-input {
    text-align: right;
    /* Equal-width digits, so a value re-formatted on blur (1000 -> 1,000.00)
       grows leftwards from the fixed right edge instead of shifting. */
    font-variant-numeric: tabular-nums;
}

/* Wide enough for a crore-sized amount with grouping and paise, whichever
   form it sits in; the spin buttons are gone (ShowSpinButtons="false"), so
   the whole width is digits. */
.amount-field {
    min-width: 10.5rem;
}

/* Sidebar groups: the whole header row is the toggle, and the chevron is a
   generous target rather than a 12px icon. */
.nav-group-header-toggle {
    cursor: pointer;
    border-radius: 4px;
}

.nav-group-header-toggle:hover {
    background: rgba(255, 255, 255, 0.06);
}

.nav-group-toggle {
    padding: 0.5rem 0.75rem;
}

/* Breadcrumb hover menu (PageHeader): "Contracting" is a DxMenu that opens a
   floating list of the module's screens on hover. It has to sit inline in
   the "Module › Screen" line, look like the plain link it replaced, and
   carry none of the menu bar's own background or padding. */
.page-header-current:has(.page-header-menu) {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
}

.page-header-menu.dxbl-menu {
    display: inline-flex;
    width: auto;
    min-height: 0;
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
}

.page-header-menu .dxbl-menu-bar {
    padding: 0;
    background: transparent;
    border: 0;
}

.page-header-menu .dxbl-menu-list-item.page-header-module {
    color: var(--vk-brand, var(--bs-primary));
    opacity: 0.75;
    background: transparent;
    padding: 0;
    font-weight: inherit;
}

.page-header-menu .dxbl-menu-list-item.page-header-module:hover {
    opacity: 1;
    background: transparent;
}

.page-header-menu-current {
    font-weight: 600;
}

/* Card and viewer pages (Home, Administration, Documents - MainLayout sets .page-home from the route): the side menu is CLOSED
   there by default (the cards are the way in; a document gets the whole width), but the three-line button ALWAYS stays, so
   Settings (font size, About, Documents, Help, sign-out ...) is never out of reach - hiding the button too left no way to it
   (the user, 2026-10-08: "three line floating menu is missing ... if setting is hidden how to navigate?"). */
.page-home:not(:has(.navbar-toggler:checked)) .sidebar {
    display: none !important;
}

/* The ">" between the module and the screen in the header ("Contracting > Suppliers")
   has to read as a sign, not a stray dot: full strength, a little larger, spaced
   clear of the menu's own down arrow. */
.page-header-current .page-header-separator {
    opacity: 1;
    font-size: 1rem;
    font-weight: 600;
    margin: 0 0.5rem;
}

/* With the module menu there is ONE sign, and it belongs to the menu: the
   menu's own down arrow is replaced by a ">" (the "Contracting > Suppliers"
   separator) that turns to point down while the floating menu is open. */
.page-header-menu .dxbl-menu-dropdown-toggle {
    display: none;
}

.page-header-menu .page-header-module {
    opacity: 1;
}

.page-header-menu .page-header-module .dxbl-menu-item-text {
    opacity: 0.85;
}

.page-header-menu .page-header-module:hover .dxbl-menu-item-text {
    opacity: 1;
}

.page-header-menu .page-header-module > dxbl-menu-item > a::after {
    content: ">";
    display: inline-block;
    margin: 0 0.5rem;
    font-size: 1rem;
    font-weight: 600;
    transition: transform 0.15s;
}

.page-header-menu .page-header-module > dxbl-menu-item > a[aria-expanded="true"]::after {
    transform: rotate(90deg);
}

/* Settings > Theme: a colour dot in front of each theme's name. */
.theme-swatch {
    display: inline-block;
    width: 0.85rem;
    height: 0.85rem;
    margin-right: 0.5rem;
    border-radius: 50%;
    vertical-align: -0.1rem;
    border: 1px solid rgba(128, 128, 128, 0.5);
}

/* The breadcrumb menu's link must not be underlined as a whole on hover: the
   underline ran on under the ">" / down arrow too. Only the word itself is
   underlined, so the arrow stays clean. */
.page-header-menu .page-header-module,
.page-header-menu .page-header-module:hover,
.page-header-menu .page-header-module:focus-within,
.page-header-menu .page-header-module a,
.page-header-menu .page-header-module a:hover,
.page-header-menu .page-header-module a:focus {
    text-decoration: none;
}

.page-header-menu .page-header-module:hover .dxbl-menu-item-text,
.page-header-menu .page-header-module:focus-within .dxbl-menu-item-text {
    text-decoration: underline;
}

/* "Contracting" (the DxMenu link) and the screen name beside it are one line
   of text and must be one font: DevExpress sizes its button text on its own
   (14px), so make the menu's link take the breadcrumb's font instead. */
.page-header-menu,
.page-header-menu .dxbl-btn,
.page-header-menu .dxbl-menu-item-text {
    --dxbl-btn-font-size: inherit;
    --dxbl-btn-line-height: inherit;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
}

/* Side menu: icon, then the caption. */
.nav-group-header .nav-icon {
    margin-right: 0.15rem;
}

.nav-page-link {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.nav-page-link .nav-icon {
    width: 1.35rem;
    height: 1.35rem;
}

.nav-page-link .nav-icon img {
    width: 0.95rem;
    height: 0.95rem;
}

/* Cards: icon above the caption. */
.module-card .nav-icon {
    grid-area: icon;
    margin-bottom: 0;
}

.module-card .module-card-caption {
    grid-area: caption;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.25;
}

.module-card .module-card-description {
    grid-area: text;
}

/* Administration links in the Settings panel. */
.nav-admin-link {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.nav-admin-link .nav-icon {
    width: 1.35rem;
    height: 1.35rem;
}

.nav-admin-link .nav-icon img {
    width: 0.95rem;
    height: 0.95rem;
}

/* The module link takes the band's readable tone, whatever colour DevExpress
   gives its menu button. */
.page-header-menu .page-header-module a,
.page-header-menu .page-header-module .dxbl-menu-item-text {
    color: var(--vk-brand, var(--bs-primary));
    opacity: 1;
}

/* DevExpress's menu item was still dimmed to 75% by an older, more specific rule,
   which pulled the module link below the 4.5:1 contrast the band aims for. */
.page-header-menu .dxbl-menu-list-item.page-header-module,
.page-header-menu .dxbl-menu-list-item.page-header-module:hover {
    opacity: 1;
}

/* Breadcrumb menu (DxMenuItem IconUrl): the DevExpress Image Library icons are
   32px artwork with no size of their own, so they filled the menu. Keep them the
   size of the menu's text. */
.dxbl-menu-dropdown-item img,
.page-header-menu img {
    width: 1.25rem;
    height: 1.25rem;
    max-width: 1.25rem;
    max-height: 1.25rem;
    object-fit: contain;
    flex: 0 0 auto;
}


/* ==== BRAND LOCKUP (BrandLockup.razor) ==============================
   The app's name as a wordmark, an optional mark before it and the tagline
   in an outlined pill after it - one line, in the current text colour, so
   it follows the theme wherever it sits (page header, sign-in card). */
.brand-lockup {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    height: var(--brand-height, 20px);
    color: inherit;
    white-space: nowrap;
}

.brand-mark {
    height: var(--brand-height, 20px);
    width: auto;
}

/* A mark that follows the theme (AppBranding.MarkGlyphUrl): the brand's glyph on a disc in the theme's own colour. */
.brand-mark-themed {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: var(--brand-height, 20px);
    height: var(--brand-height, 20px);
    border-radius: 50%;
    background-color: var(--bs-primary);
    overflow: hidden;
}

.brand-mark-themed img {
    width: 100%;
    height: 100%;
    display: block;
}

.brand-wordmark {
    font-weight: 800;
    font-size: calc(var(--brand-height, 20px) * 0.95);
    letter-spacing: 0.02em;
    line-height: 1;
}

.brand-badge {
    font-size: calc(var(--brand-height, 20px) * 0.5);
    font-weight: 700;
    line-height: 1;
    padding: 0.2em 0.7em;
    border: 1.5px solid currentColor;
    border-radius: 999px;
}

/* The sign-in card without a logo picture: the lockup, centred, in the brand colour. */
.account-brand {
    display: flex;
    justify-content: center;
    margin-bottom: 1.5rem;
    color: var(--vk-brand, var(--bs-primary));
}

/* The request form inside the app (/contact-sales): the card centred under the page header, no full-page frame. */
.demo-request-inapp {
    display: flex;
    justify-content: center;
    padding: 0.5rem 1rem 2rem;
}

/* Its hints (the company's details from Company Setup) show in every empty box, focused or not - an example, typed over by the person. */
.demo-request-inapp .floating-form input::placeholder {
    opacity: 0.55;
}

/* The Request a demo page's band is a link Home: no underline, a hand. */
a.account-brand-home,
a.account-brand-home:hover {
    text-decoration: none;
    cursor: pointer;
}


/* Sign-in boxes: an icon inside the left edge (envelope, lock), and on the
   password box a clear button just left of the show/hide eye - all in the
   field's own text colour at reduced opacity, so every theme reads the same. */
.account-input-wrapper {
    position: relative;
}

.account-input-wrapper input {
    padding-left: 2.4rem;
}

.account-input-icon {
    position: absolute;
    left: 0.85rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: var(--bs-emphasis-color);
    opacity: 0.55;
    pointer-events: none;
}

.account-password-wrapper.account-input-wrapper input {
    padding-right: 4.4rem;
}

.account-input-clear {
    position: absolute;
    top: 50%;
    right: 2.6rem;
    transform: translateY(-50%);
    background: none;
    border: none;
    padding: 0;
    display: flex;
    color: var(--bs-emphasis-color);
    opacity: 0.55;
    cursor: pointer;
}

.account-input-clear[hidden] {
    display: none;
}

/* The email box has no eye button: its x sits at the right edge, and the text stops short of it. */
#emailClear {
    right: 0.75rem;
}

#email {
    padding-right: 2.25rem;
}

.account-input-clear:hover,
.account-input-clear:focus {
    opacity: 1;
}

/* The site's account domain ("@bestpmcs.com") as fixed text at the right of the Email box (Login.razor): muted, in the theme's own secondary
   text colour, clicks pass through to the box, never a Tab stop. At the edge while the box is empty, just left of the x once there is text;
   hidden when a full address (with "@") is typed. The script sets the box's right padding to its width. */
.account-input-suffix {
    position: absolute;
    top: 50%;
    right: 0.75rem;
    transform: translateY(-50%);
    color: var(--bs-secondary-color);
    pointer-events: none;
    white-space: nowrap;
    user-select: none;
}

.account-input-suffix.account-input-suffix-beside-clear {
    right: 2.25rem;
}

.account-input-suffix[hidden] {
    display: none;
}

/* Toasts stay in the corner of the window, not of the page. DevExpress's toast portal is position:absolute
   (anchored to the document) unless it carries .dxbl-toast-fixed, so on a page scrolled down the toast
   appeared above the visible area and only showed after scrolling back up. */
.dxbl-toast-portal {
    position: fixed;
}

/* ---- Collaboration: chat, meetings, video room ---- */
.chat-page { display: flex; gap: 0; height: calc(100vh - 150px); min-height: 380px; margin: 12px 16px; border: 1px solid var(--bs-border-color); border-radius: 6px; overflow: hidden; }
.chat-channels { width: 250px; flex: none; border-right: 1px solid var(--bs-border-color); overflow-y: auto; background: var(--bs-tertiary-bg, #f8f9fa); }
.chat-channels-actions { display: flex; gap: 6px; padding: 10px; }
.chat-channel { display: flex; justify-content: space-between; align-items: center; padding: 9px 14px; cursor: pointer; }
.chat-channel:hover { background: rgba(0, 0, 0, 0.05); }
.chat-channel.active { background: var(--bs-primary-bg-subtle, #e2d9f3); font-weight: 600; }
.chat-unread { background: var(--bs-danger, #dc3545); color: #fff; border-radius: 10px; padding: 0 7px; font-size: 0.75rem; }
.chat-thread { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.chat-thread-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 14px; border-bottom: 1px solid var(--bs-border-color); }
.chat-messages { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.chat-message { max-width: 72%; align-self: flex-start; background: var(--vk-surface, #f1f3f5); border-radius: 10px; padding: 6px 10px; }
.chat-message.mine { align-self: flex-end; background: var(--bs-primary-bg-subtle, #e2d9f3); }
.chat-meta { font-size: 0.72rem; opacity: 0.7; }
.chat-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.chat-compose { display: flex; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--bs-border-color); }
.chat-input { flex: 1; }

.meetings-scheduler { height: 520px; }
.call-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 8px; }
.call-tile { position: relative; background: #111; border-radius: 8px; overflow: hidden; aspect-ratio: 16 / 9; }
.call-tile video { width: 100%; height: 100%; object-fit: cover; }
.call-tile-local video { transform: scaleX(-1); }
.call-name { position: absolute; left: 8px; bottom: 6px; color: #fff; background: rgba(0, 0, 0, 0.55); border-radius: 4px; padding: 1px 8px; font-size: 0.8rem; }

@media (max-width: 720px) {
    .chat-page { flex-direction: column; height: auto; }
    .chat-channels { width: 100%; max-height: 160px; border-right: 0; border-bottom: 1px solid var(--bs-border-color); }
    .chat-thread { min-height: 420px; }
}

/* ---- Remote support ---- */
.support-canvas { width: 100%; max-height: 78vh; background: #111; border-radius: 6px; object-fit: contain; outline: none; }
.support-engineer { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
.support-engineer-name { font-weight: 600; }
.presence-dot { width: 10px; height: 10px; border-radius: 50%; background: #adb5bd; display: inline-block; }
.presence-available { background: #28a745; }
.presence-busy { background: #dc3545; }
.presence-away { background: #ffc107; }
.presence-offline { background: #adb5bd; }
.ticket-priority { font-size: 0.75rem; padding: 1px 8px; border-radius: 10px; background: #e9ecef; }
.ticket-high { background: #ffe8cc; }
.ticket-urgent { background: #f8d7da; color: #842029; font-weight: 600; }
.ticket-thread { display: flex; flex-direction: column; gap: 8px; max-width: 820px; }
.ticket-comment { border: 1px solid var(--bs-border-color); border-radius: 8px; padding: 8px 12px; }
.ticket-comment.from-support { background: var(--bs-primary-bg-subtle, #e2d9f3); }
.ticket-comment.internal { background: #fff3cd; border-style: dashed; }
/* The Help link beside About: full-strength colour and underlined (it sits in muted small print, where it was hard to see). */
.settings-help-link { font-weight: 700; text-decoration: underline; opacity: 1; }
.settings-help-link:hover { text-decoration: underline; filter: brightness(1.15); }

/* The trial / AMC banner runs across the top of the page, under the round buttons fixed in the corners (menu at the left - not on
   Home - and search + account at the right): its text keeps clear of them. */
.license-banner { padding-right: 7.75rem !important; }
.page:not(.page-home) .license-banner { padding-left: 4.25rem !important; }
/* The offer under the trial line; in the last two days the whole banner and the offer stand out more. */
.license-trial-offer { margin-top: 0.15rem; }
.license-trial-last { border-width: 2px; }
.license-trial-last .license-trial-offer { font-size: 1rem; }
/* The campaign banner sits under the trial / AMC banner, same shape; it fades out by itself after 3 minutes (CampaignBanner). */
.campaign-banner { transition: opacity 0.4s ease; }
.campaign-banner-hiding { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .campaign-banner { transition: none; } }

/* ===== The demo site's LANDING page (Login.razor on the demo site; the plain sign-in card elsewhere) ===== */
.landing { display: grid; grid-template-columns: minmax(0, 1fr) 360px; grid-template-areas: "header header" "main signin"; gap: 1rem 1.5rem; max-width: 1280px; margin: 0 auto; }
.landing-header { grid-area: header; display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; padding-top: 0.5rem; }
.landing-signin { grid-area: signin; position: sticky; top: 4.5rem; align-self: start; }
.landing-signin-card { background: var(--vk-surface, var(--bs-body-bg)); border: 1px solid var(--bs-border-color); border-radius: 0.75rem; padding: 1.25rem; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.08); max-width: 360px; }
.landing-daily-quote { margin: 1rem 0 0; padding: 0.85rem 1.1rem; max-width: 360px; background: var(--vk-surface, var(--bs-body-bg)); border: 1px solid var(--bs-border-color); border-left: 4px solid var(--bs-primary); border-radius: 0.75rem; }
.landing-daily-quote-title { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bs-secondary-color); margin-bottom: 0.3rem; }
.landing-daily-quote-text { margin: 0; font-size: 1rem; font-style: italic; }
/* A tighter card on the landing page (user, 2026-10-14: "reduce some space to bring the quote window a bit up"). */
.landing-signin-card { padding: 1rem 1.25rem; }
.landing-signin-card .account-title { font-size: 1.2rem; margin-bottom: 0.1rem; }
.landing-signin-card .account-subtitle { font-size: 0.85rem; margin-bottom: 0.75rem; }
.landing-signin-card .alert { margin-bottom: 0.75rem; padding: 0.5rem 0.75rem; }
.landing-signin-card .account-field { margin-bottom: 0.7rem; }
.landing-signin-card .account-submit { padding: 0.65rem; }
.landing-signin-card .account-demo-request { margin-top: 0.5rem; }
.landing-daily-quote { margin-top: 0.6rem; }
.landing-main { grid-area: main; min-width: 0; }
.landing-hero { margin-bottom: 1.5rem; }
.landing-hero-carousel .landing-carousel-dx, .landing-carousel .dxbl-carousel { border-radius: 0.75rem; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12); background: var(--vk-surface, var(--bs-body-bg)); border: 1px solid var(--bs-border-color); }
.landing-carousel { max-width: 100%; }
.landing-carousel .dxbl-carousel { aspect-ratio: 1400 / 884; max-height: 560px; }
/* The slides fade out at all four edges instead of ending in a hard frame, and drift in very slowly (user, 2026-10-14: "corners faded on the edges,
   a little bit of animation"): a soft edge mask on each picture and a gentle zoom that turns back - none of it for someone who asks for less motion. */
.landing-carousel .landing-carousel-dx.dxbl-carousel,
.landing-hero-carousel .landing-carousel-dx { border: none; box-shadow: none; background: transparent; }
.landing-carousel .dxbl-carousel img {
    /* The picture stays fully clear; only a narrow band at each edge fades into the page (user, 2026-10-20: "too faded, only bordered fade is
       fine" - the earlier oval vignette washed out most of the slide). Two straight fades, left/right and top/bottom, intersected. */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%),
        linear-gradient(to bottom, transparent 0, #000 8%, #000 92%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image: linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%),
        linear-gradient(to bottom, transparent 0, #000 8%, #000 92%, transparent 100%);
    mask-composite: intersect;
    animation: landing-slide-drift 12s ease-in-out infinite alternate;
    transform-origin: center;
    will-change: transform;
}
/* The borders are BLURRED as well as faded (user, 2026-10-20: "carousel slideshow images should be blurred at borders"): a layer over the slide
   blurs what is under it, masked to the same narrow edge band as the fade (clear everywhere else) - the edge goes soft before it fades out.
   It lets every click through, and the arrows and dots sit above it, so they stay sharp. */
.landing-carousel .dxbl-carousel { position: relative; }
.landing-carousel .dxbl-carousel::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    -webkit-backdrop-filter: blur(9px);
    backdrop-filter: blur(9px);
    -webkit-mask-image: linear-gradient(to right, #000 0, transparent 9%, transparent 91%, #000 100%),
        linear-gradient(to bottom, #000 0, transparent 10%, transparent 90%, #000 100%);
    -webkit-mask-composite: source-over;
    mask-image: linear-gradient(to right, #000 0, transparent 9%, transparent 91%, #000 100%),
        linear-gradient(to bottom, #000 0, transparent 10%, transparent 90%, #000 100%);
    mask-composite: add;
}
.landing-carousel .dxbl-carousel .dxbl-carousel-nav-btn,
.landing-carousel .dxbl-carousel [class*="indicator"],
.landing-carousel .dxbl-carousel button { z-index: 2; }
/* The slide drifts as well as zooming - a slow pan across the screen and back (user, 2026-10-14: "add some moving animations"). */
@keyframes landing-slide-drift {
    0% { transform: scale(1) translate(0, 0); }
    50% { transform: scale(1.05) translate(-1.2%, -0.8%); }
    100% { transform: scale(1.03) translate(1%, 0.6%); }
}

/* ---- The landing page moves in: the header drops in, the sign-in card slides in from the right, the carousel rises, and every section and card
   below rises into place as it is scrolled into view (accountLogin.js adds .landing-in through an IntersectionObserver, and .landing-anim on <html>
   only when it runs - without the script nothing is hidden). Cards lift a little under the mouse. None of it with prefers-reduced-motion. */
@keyframes landing-drop { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
@keyframes landing-from-right { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
@keyframes landing-rise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
.landing-header { animation: landing-drop 0.6s ease-out both; }
.landing-signin { animation: landing-from-right 0.7s ease-out 0.15s both; }
.landing-hero { animation: landing-rise 0.8s ease-out 0.25s both; }
.landing-daily-quote { animation: landing-rise 0.8s ease-out 0.6s both; }
html.landing-anim .landing-main .landing-section:not(.landing-hero),
html.landing-anim .landing-main .landing-card { opacity: 0; transform: translateY(22px); transition: opacity 0.7s ease-out, transform 0.7s ease-out, box-shadow 0.25s ease, border-color 0.25s ease; transition-delay: var(--reveal-delay, 0ms); }
html.landing-anim .landing-main .landing-section.landing-in:not(.landing-hero),
html.landing-anim .landing-main .landing-card.landing-in { opacity: 1; transform: none; }
.landing-card { transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; }
.landing-card:hover { transform: translateY(-3px); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.12); }
html.landing-anim .landing-main .landing-card.landing-in:hover { transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) {
    .landing-carousel .dxbl-carousel img,
    .landing-header, .landing-signin, .landing-hero, .landing-daily-quote { animation: none; }
    html.landing-anim .landing-main .landing-section, html.landing-anim .landing-main .landing-card { opacity: 1; transform: none; transition: none; }
    .landing-card:hover { transform: none; }
}
.landing-carousel-caption { margin: 0.5rem 0 0; color: var(--bs-secondary-color); font-size: 0.95rem; min-height: 1.4em; }
.landing-hero-line { font-size: 1.1rem; font-weight: 600; margin: 0.75rem 0 0; }
.landing-section { margin-bottom: 1.75rem; }
.landing-h2 { font-size: 1.35rem; font-weight: 700; margin-bottom: 0.6rem; }
.landing-h3 { font-size: 1.05rem; font-weight: 600; }
.landing-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.75rem; }
.landing-card { background: var(--vk-surface, var(--bs-body-bg)); border: 1px solid var(--bs-border-color); border-radius: 0.6rem; padding: 0.8rem 0.9rem; color: var(--bs-body-color); text-decoration: none; display: flex; flex-direction: column; gap: 0.35rem; }
a.landing-card:hover { border-color: var(--bs-primary); color: var(--bs-body-color); }
.landing-bullets { padding-left: 1.2rem; }
.landing-bullets li { margin-bottom: 0.3rem; }
.landing-platform { font-size: 0.8rem; color: var(--bs-primary); font-weight: 600; }
.landing-quote { font-style: italic; }
.landing-who { font-size: 0.85rem; color: var(--bs-secondary-color); }
.landing-tag, .landing-hashtag { color: var(--bs-primary); font-weight: 600; font-size: 0.85rem; }
.landing-credentials { font-family: var(--bs-font-monospace); background: var(--vk-surface, var(--bs-body-bg)); border: 1px dashed var(--bs-border-color); border-radius: 0.5rem; padding: 0.6rem 0.8rem; display: inline-block; }
.landing-feedback-form .landing-honeypot { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.landing-stars { display: flex; gap: 0.1rem; }
.landing-star { font-size: 1.4rem; line-height: 1; padding: 0 0.1rem !important; color: var(--bs-secondary-color); }
.landing-star-on { color: #e0a800; }
.landing-feedback-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.4rem; }
.landing-feedback-item { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: 0.6rem; align-items: baseline; white-space: nowrap; }
.landing-feedback-text { overflow: hidden; text-overflow: ellipsis; }
.landing-feedback-stars { color: #e0a800; letter-spacing: 0.05em; }
.landing-feedback-name { font-weight: 600; }
.landing-footer { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; color: var(--bs-secondary-color); font-size: 0.9rem; border-top: 1px solid var(--bs-border-color); padding-top: 0.75rem; margin-top: 1rem; }
@media (max-width: 991px) {
    .landing { grid-template-columns: minmax(0, 1fr); grid-template-areas: "header" "signin" "main"; }
    .landing-signin { position: static; }
    .landing-signin-card { max-width: none; }
    .landing-daily-quote { max-width: none; }
}

/* Licensing: the activation page and the Super Admin License screen. */
.license-card { max-width: 560px; }

.license-machine-id {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 1.25rem;
    letter-spacing: 0.08em;
    font-weight: 600;
    user-select: all;
}

.license-facts { max-width: 640px; }
.license-facts th { width: 11rem; font-weight: normal; color: var(--bs-secondary-color); }
.license-key-box textarea { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 0.8rem; }

/* The Copy button beside the computer id (License page and the Super Admin License screen). */
.license-copy-btn, .license-copy-code-btn { padding: 0.15rem 0.6rem; font-size: 0.85rem; }

/* The hard lock (trial ended / licence moved): a danger-tinted edge and a lock mark above the title - theme-safe, the tint is mixed from the
   theme's own danger colour and surface. */
.license-locked { border-top: 4px solid var(--bs-danger); }
.license-lock-mark {
    width: 64px; height: 64px; margin: 0 auto 0.5rem; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: color-mix(in srgb, var(--bs-danger) 75%, var(--bs-body-color));
    background: color-mix(in srgb, var(--bs-danger) 14%, var(--vk-surface, var(--bs-body-bg)));
}
.license-locked .account-title { text-align: center; }
.license-surrender-code { font-size: 1rem; letter-spacing: 0.04em; word-break: break-all; }

/* Whom to contact (SupportContact): name, tap-to-call phone, e-mail - on the theme's surface, never a fixed light grey. */
.support-contact {
    display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; align-items: baseline;
    padding: 0.6rem 0.8rem; border-radius: 0.5rem; background: var(--vk-surface, var(--bs-body-bg));
    border: 1px solid color-mix(in srgb, var(--bs-body-color) 12%, transparent);
}
.support-contact-heading { flex-basis: 100%; font-size: 0.8rem; color: var(--bs-secondary-color); }
.support-contact-name { font-weight: 600; }
.support-contact a { color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 60%, var(--bs-body-color)); }

/* Administration > Updates. */
.updates-notes { white-space: pre-line; }
.updates-log-lines { word-break: break-word; }

/* ---- Menu search (MenuSearch.razor): the magnifier just left of the account icon, and its search box. ---- */
.menu-search {
    position: fixed;
    top: 1rem;
    right: 4.5rem;   /* the account icon is 2.5rem wide at right: 1rem, plus a 0.5rem gap */
    z-index: 1030;
}

.menu-search-toggle {
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background-color: var(--bs-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.menu-search-toggle:hover,
.menu-search-toggle:focus-visible {
    filter: brightness(1.12);
}

/* The same circle as the account avatar: a light magnifier centred on a softly lighter disc, no tile of its own. */
.menu-search-glyph {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bs-light);
    background-color: rgba(255, 255, 255, 0.15);
}

.menu-search-toggle:focus-visible {
    outline: 2px solid var(--bs-light);
    outline-offset: 2px;
}

/* The box sits near the top like a command palette (a fixed panel over a see-through backdrop that closes it on a click);
   on a phone it takes the full width. */
.menu-search-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1049;
    background: rgba(0, 0, 0, 0.25);
}

.menu-search-panel {
    position: fixed;
    top: 4.5rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1050;
    width: min(600px, calc(100vw - 1.5rem));
    padding: 0.6rem;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
}

.menu-search-results {
    margin-top: 0.5rem;
    max-height: min(26rem, calc(100vh - 11rem));
    overflow-y: auto;
}

.menu-search-result {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
    padding: 0.35rem 0.5rem;
    border-radius: var(--bs-border-radius);
    cursor: pointer;
}

.menu-search-result:hover,
.menu-search-result.active {
    background-color: rgba(var(--bs-primary-rgb), 0.14);
}

.menu-search-result.active {
    outline: 1px solid rgba(var(--bs-primary-rgb), 0.5);
}

.menu-search-item-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.menu-search-item-title {
    font-weight: 600;
}

.menu-search-item-module {
    font-weight: 400;
    opacity: 0.75;
}

.menu-search-item-desc {
    font-size: 0.75rem;
    opacity: 0.65;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.menu-search-empty {
    padding: 0.75rem;
    opacity: 0.7;
}

.menu-search-hint {
    padding: 0.4rem 0.5rem 0;
    font-size: 0.75rem;
    opacity: 0.6;
}

/* The pin at the right end of a result row: hollow until pinned, filled once it is. */
.menu-search-pin {
    flex: 0 0 auto;
    margin-left: auto;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--bs-body-color);
    opacity: 0.45;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.menu-search-pin:hover,
.menu-search-pin.pinned {
    opacity: 1;
    color: var(--bs-primary);
}

.menu-search-pin:hover {
    background-color: rgba(var(--bs-primary-rgb), 0.18);
}

.menu-search-pin:disabled {
    opacity: 0.2;
    cursor: default;
}

/* ---- Pinned screens (MenuSearch.razor): the bookmarks bar in the middle of the top bar - one circle per pinned screen, its icon
   and the number F2 + digit answers to. Kept clear of the hamburger on the left and the bell / magnifier / avatar on the right. ---- */
.menu-pins {
    position: fixed;
    top: 1rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1030;
    display: flex;
    gap: 0.5rem;
    max-width: calc(100vw - 24rem);
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 0.25rem;
}

.menu-pin {
    position: relative;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background-color: var(--bs-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.menu-pin:hover,
.menu-pin:focus-visible {
    filter: brightness(1.12);
}

.menu-pin:focus-visible {
    outline: 2px solid var(--bs-light);
    outline-offset: 2px;
}

.menu-pin .nav-icon {
    width: 1.5rem;
    height: 1.5rem;
}

.menu-pin-key {
    position: absolute;
    right: -0.2rem;
    bottom: -0.2rem;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.2rem;
    border-radius: 0.5rem;
    background-color: var(--bs-light);
    color: var(--bs-primary);
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1rem;
    text-align: center;
}

@media (max-width: 991.98px) {
    .menu-pins {
        display: none;   /* no room between the circles on a phone or a narrow tablet; F2 and the search still open the pins */
    }
}

@media (max-width: 767.98px) {
    .menu-search-panel {
        top: 4rem;
        width: calc(100vw - 1rem);
    }
}

/* Side menu filter (a module with more than 10 screens): a typeahead - the typed letters are marked in each caption, the chosen match
   (Up/Down; Enter opens it) is lit like the hovered link. */
.sidebar .nav-group-filter .nav-filter-box {
    width: 100%;
}

.sidebar .nav-filter-match {
    padding: 0;
    color: inherit;
    background: rgba(255, 255, 255, 0.28);
    border-radius: 2px;
    font-weight: 600;
}

.sidebar .nav-page-link.nav-filter-active {
    background-color: rgba(255, 255, 255, 0.18);
    color: #fff;
    outline: 1px solid rgba(255, 255, 255, 0.45);
}

.sidebar .nav-filter-empty {
    display: block;
    color: rgba(255, 255, 255, 0.6);
}

/* The header line never runs under the fixed buttons (hamburger left; menu search and profile right - .page-header's padding clears
   them): on a narrow window the brand line shrinks and the tagline pill is cut with "..." instead of sliding beneath the magnifier. */
.page-header-brand {
    max-width: 100%;
    min-width: 0;
}

.page-header .brand-lockup {
    min-width: 0;
    max-width: 100%;
}

.page-header .brand-badge {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The Settings page (user, 2026-10-11): its settings sit BELOW the line of floating buttons and scroll in their own area, so the
   hamburger, the magnifier and the profile button never cover a setting - the header line (brand, "Settings") stays put above. */
.page:has(#settingsPage) {
    height: 100vh;
    height: 100dvh;
}

.page:has(#settingsPage) main,
.page:has(#settingsPage) .content {
    min-height: 0;
    overflow: hidden;
}

#settingsPage {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* The notification bell (NotificationBell.razor): the same circle as the magnifier, left of it; a red badge counts the notices not yet
   seen. Its panel drops down under it at the top right. */
.notification-bell {
    position: fixed;
    top: 1rem;
    right: 8rem;   /* left of the magnifier (right: 4.5rem, 2.5rem wide) with the same 1rem gap */
    z-index: 1030;
}

.notification-bell-toggle {
    position: relative;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background-color: var(--bs-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.notification-bell-toggle:hover,
.notification-bell-toggle:focus-visible {
    filter: brightness(1.12);
}

.notification-bell-glyph {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bs-light);
    background-color: rgba(255, 255, 255, 0.15);
}

.notification-bell-badge {
    position: absolute;
    top: -0.3rem;
    right: -0.3rem;
    min-width: 1.15rem;
    height: 1.15rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: var(--bs-danger, #dc3545);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.15rem;
    text-align: center;
    box-shadow: 0 0 0 2px var(--bs-body-bg);
}

.notification-bell-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1049;
}

.notification-bell-panel {
    position: fixed;
    top: 4rem;
    right: 1rem;
    z-index: 1050;
    width: min(380px, calc(100vw - 2rem));
    max-height: 60vh;
    overflow-y: auto;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.3);
}

.notification-bell-head {
    padding: 0.55rem 0.8rem;
    font-weight: 600;
    border-bottom: 1px solid var(--bs-border-color);
}

.notification-bell-empty {
    padding: 0.8rem;
    color: var(--bs-secondary-color);
}

.notification-bell-item {
    padding: 0.6rem 0.8rem;
    border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
}

.notification-bell-title {
    font-weight: 600;
}

.notification-bell-time,
.notification-bell-by {
    font-size: 0.75rem;
    color: var(--bs-secondary-color);
    font-weight: 400;
}

.notification-bell-text {
    font-size: 0.85rem;
    margin: 0.15rem 0;
}

/* Administration > Menu Order: one row per screen; the row the cursor is in is lit (Tab / Up / Down move it; Ctrl+Up / Ctrl+Down move the screen). */
/* The chosen row (the one the cursor is in - clicked, Tab, Up/Down): lit like a grid's selected row, with a bar at its left edge. The cells
   are painted, not the row - Bootstrap's table cells have a background of their own that hid a row colour. */
.menu-order-table tr:focus {
    outline: none;
}

.menu-order-table tr.menu-order-current > td,
.menu-order-table tr:focus > td {
    background-color: rgba(var(--bs-primary-rgb), 0.18) !important;
}

.menu-order-table tr.menu-order-current > td:first-child,
.menu-order-table tr:focus > td:first-child {
    box-shadow: inset 3px 0 0 var(--bs-primary);
    font-weight: 600;
}

.menu-order-table tr {
    cursor: pointer;
}

.menu-order-table tr.menu-order-separator td:first-child {
    color: var(--bs-secondary-color);
    font-size: 0.8rem;
}

/* A narrow window (a phone): the path ("Administration > Menu Order") stays inside the header's padding instead of running under the
   bell, the magnifier and the profile button - it is cut at the edge. */
@media (max-width: 575.98px) {
    .page-header-current {
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
    }
}

.menu-order-caption {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
}

/* The same icon tile as the side menu's screens. */
.menu-order-caption .nav-icon {
    width: 1.35rem;
    height: 1.35rem;
    flex-shrink: 0;
}

.menu-order-caption .nav-icon img {
    width: 0.95rem;
    height: 0.95rem;
}

/* ==== FROZEN TOP ROW + SIDE MENU AS AN ICON COLUMN (user, 2026-10-11, like KAYAK) ====================================================
   The top row (three-line button, brand, path, bell, magnifier, profile) stays put while the page scrolls. The EXISTING side menu
   (NavMenu: module groups, their screens, the filter, Settings) is always there as a 4rem column of icons down the left: on Home the
   modules; inside a module its group is open, so its screens' icons show under it, the current one lit. Hovering the column - or the
   three-line button - opens the same menu to its full width OVER the page (names, chevrons, filter, Settings, version); the page never
   moves. Collapsed, everything past the icons is simply clipped by the column's width; the filter shows its magnifier. Not on the
   Documents viewer (no has-rail there) and not on phones, where the three-line button opens the menu as before. */
.page.has-rail main {
    margin-left: 4rem;
}

.page-header {
    position: sticky;
    top: 0;
    z-index: 1020;
    background-color: var(--bs-body-bg);
    margin-left: -1.5rem;
    margin-right: -1.5rem;
    padding-left: calc(3.5rem + 1.5rem);
    padding-right: calc(10.5rem + 1.5rem);
    border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
}

/* With the column, the three-line button sits at the column's top and the header starts right of it. */
.page.has-rail .page-header {
    padding-left: 1.5rem;
}

/* Card pages (Home, Administration): the older rule hid the menu there; with the column it shows. ONLY display here - this selector is
   so specific that a width in it beat the hover rule below, so on Home the names showed but the column never opened (2026-10-11). */
.page.has-rail.page-home:not(:has(.navbar-toggler:checked)) .sidebar {
    display: flex !important;
}

/* Collapsed: the column. */
.page.has-rail .sidebar {
    display: flex !important;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1025;
    width: 4rem;
    min-height: 0;
    overflow: hidden;
    white-space: nowrap;
    /* Closing is unhurried (user, 2026-10-12: "side navbar also close bit slowly"): a short pause, then a slower fold - so a cursor
       passing out for a moment does not snap it shut. Opening stays quick (the rule below). */
    transition: width 0.4s ease 0.1s, box-shadow 0.4s ease 0.1s;
}

.page.has-rail .sidebar .nav-scrollable {
    width: 280px;
    overflow-x: hidden;
}

/* Open: hovered, the cursor inside it, or the three-line button. */
.page.has-rail .sidebar:hover,
.page.has-rail .sidebar:focus-within,
.page.has-rail:has(.navbar-toggler:checked) .sidebar {
    width: 280px;
    box-shadow: 4px 0 16px rgba(0, 0, 0, 0.3);
    transition: width 0.15s ease, box-shadow 0.15s ease;
}

/* Collapsed, only the icons: the group's left line, the chevrons, Settings, the version and the filter's box are hidden. */
.page.has-rail:not(:has(.navbar-toggler:checked)) .sidebar:not(:hover):not(:focus-within) :is(.appearance-controls, .sidebar-version,
    .nav-group-toggle, .nav-filter-box, .nav-filter-empty) {
    visibility: hidden;
}

.page.has-rail:not(:has(.navbar-toggler:checked)) .sidebar:not(:hover):not(:focus-within) .nav-group-pages {
    border-left-color: transparent;
}

/* ... and no names: they start right after the icon, inside the 4rem, so they are made invisible rather than clipped. */
.page.has-rail:not(:has(.navbar-toggler:checked)) .sidebar:not(:hover):not(:focus-within) :is(.nav-link, .nav-group-link) {
    color: transparent !important;
    -webkit-text-fill-color: transparent;
    text-shadow: none;
}

/* ONE selected look for the whole menu (user, 2026-10-11: "use the selected menu highlight for all"): the current module's row and the
   current screen's row get a light box with a white bar at the left edge - in the collapsed column and the open menu, in every module. */
.sidebar .nav-group-current > .nav-group-header,
.sidebar .nav-page-link.active {
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 0.4rem;
    box-shadow: inset 3px 0 0 #fff;
}

.sidebar .nav-group-header,
.sidebar .nav-page-link {
    padding-left: 0.3rem !important;
    padding-right: 0.3rem !important;
    margin-left: -0.3rem;
    margin-right: 0.3rem;
}

/* The list scrolls BELOW the three-line button, never under it (user, 2026-10-11: "avoid overlaps" - a long module's list scrolled the
   top icons up beneath the button). */
.page.has-rail .sidebar .nav-scrollable {
    padding-top: 0;
    margin-top: 4.5rem;
}

/* In the column every icon - module, screen, the filter's magnifier - sits in the same place, under the one above it. */
.page.has-rail .sidebar .nav-group-pages {
    margin-left: 0;
    padding-left: 0;
    border-left: 0;   /* the screens sit right under the module's icon; the old left line ran along the menu's edge (user, 2026-10-11) */
}

.page.has-rail .sidebar .nav-group-filter {
    padding-left: 0 !important;
    padding-right: 0.5rem !important;
}

/* The filter of a long module (Contracting): a magnifier, then its box - collapsed, the magnifier alone. */
.nav-group-filter {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.nav-filter-icon {
    flex: 0 0 1.35rem;
}

@media (max-width: 575.98px) {
    .page.has-rail main {
        margin-left: 0;
    }

    .page.has-rail .page-header {
        padding-left: calc(3.5rem + 1.5rem);
    }

    .page.has-rail:not(:has(.navbar-toggler:checked)) .sidebar,
    .page.has-rail.page-home:not(:has(.navbar-toggler:checked)) .sidebar {
        display: none !important;
    }
}

/* ---- The help assistant (HelpAssistant.razor): a fourth round button left of the bell, the same size and look, and a chat panel on the
   right under the top bar. Only an app that called AddHelpAssistant has it (.page.has-help gives the header room for the fourth button). */
.help-assistant {
    position: fixed;
    top: 1rem;
    right: 11.5rem;   /* left of the bell (right: 8rem, 2.5rem wide) with the same 1rem gap */
    z-index: 1030;
}

.help-assistant-toggle {
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background-color: var(--bs-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.help-assistant-toggle:hover,
.help-assistant-toggle:focus-visible,
.help-assistant-toggle[aria-expanded="true"] {
    filter: brightness(1.12);
}

.help-assistant-glyph {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bs-light);
    background-color: rgba(255, 255, 255, 0.15);
}

/* The sparkle in the round button: DevExpress's dx-ai-chat symbol, white on the brand colour like the bell and magnifier. */
/* DevExpress's .dxbl-image sizes its icons to the text (12.8px here) - the glyph's own rule wins so it matches the bell (21px). */
.help-assistant-glyph svg.help-assistant-sparkle { width: 21px; height: 21px; fill: currentColor; color: var(--bs-light); }

.page.has-help .page-header {
    padding-right: 14rem;   /* help, bell, magnifier and profile button */
}

.help-assistant-panel {
    display: none;
    position: fixed;
    top: 4rem;
    right: 1rem;
    bottom: 1rem;
    width: min(440px, calc(100vw - 2rem));
    z-index: 1040;
    flex-direction: column;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.22);
    overflow: hidden;
}

.help-assistant-panel.is-open {
    display: flex;
}

.help-assistant-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "title close" "note close";
    align-items: center;
    column-gap: 0.5rem;
    padding: 0.6rem 0.75rem 0.55rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
    background-color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 10%, var(--bs-body-bg));
}

.help-assistant-title { grid-area: title; font-weight: 600; color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 70%, var(--bs-body-color)); }
.help-assistant-note { grid-area: note; font-size: 0.78rem; color: var(--bs-secondary-color); }

.help-assistant-close {
    grid-area: close;
    border: 0;
    background: transparent;
    color: var(--bs-body-color);
    font-size: 1.4rem;
    line-height: 1;
    padding: 0.1rem 0.4rem;
    border-radius: 0.4rem;
    cursor: pointer;
}

.help-assistant-close:hover { background-color: color-mix(in srgb, var(--bs-body-color) 10%, transparent); }

.help-assistant-chat {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
}

.help-assistant-message p { margin: 0 0 0.5rem; }
.help-assistant-message p:last-child, .help-assistant-message ul:last-child { margin-bottom: 0; }
.help-assistant-message ul { margin: 0.25rem 0 0.5rem; padding-left: 1.2rem; }
.help-assistant-link { color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 70%, var(--bs-body-color)); font-weight: 600; }

/* Voice: the DevExtreme SpeechToText button sits in the chat's input box, left of the send button. The app carries no DevExtreme theme,
   so the button is styled here (its icons are inline SVG passed from helpVoice.js). */
.help-assistant-voice {
    position: absolute;
    right: 3.6rem;
    bottom: 1.35rem;
    z-index: 2;
}

.help-assistant-voice.dx-button {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 75%, var(--bs-body-color));
    background-color: transparent;
}

.help-assistant-voice.dx-button .dx-button-content { display: flex; align-items: center; justify-content: center; }
.help-assistant-voice.dx-button .dx-icon { display: flex; width: auto; height: auto; }
.help-assistant-voice.dx-button:hover { background-color: color-mix(in srgb, var(--bs-body-color) 9%, transparent); }
.help-assistant-voice.dx-state-disabled { opacity: 0.45; cursor: default; }

.help-assistant-voice.dx-button.dx-speech-to-text-listening,
.help-assistant-voice.dx-button.dx-speech-to-text-listening:hover {
    color: #fff;
    background-color: #d63a3a;
    animation: help-assistant-listening 1.2s ease-in-out infinite;
}

@keyframes help-assistant-listening {
    0%, 100% { box-shadow: 0 0 0 0 rgba(214, 58, 58, 0.45); }
    50% { box-shadow: 0 0 0 0.45rem rgba(214, 58, 58, 0); }
}

.help-assistant-voice-status {
    position: absolute;
    left: 1rem;
    right: 1rem;
    bottom: 5.4rem;
    z-index: 2;
    padding: 0.35rem 0.65rem;
    font-size: 0.8rem;
    border-radius: 0.5rem;
    background-color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 12%, var(--bs-body-bg));
    border: 1px solid var(--bs-border-color);
}

.help-assistant-voice-status.is-error { background-color: color-mix(in srgb, #d63a3a 12%, var(--bs-body-bg)); }

.help-assistant-speak {
    margin-top: 0.35rem;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    color: var(--bs-secondary-color);
    cursor: pointer;
}

.help-assistant-speak:hover { background-color: color-mix(in srgb, var(--bs-body-color) 9%, transparent); color: var(--bs-body-color); }
.help-assistant-speak.is-speaking { color: #fff; background-color: color-mix(in srgb, var(--vk-brand, var(--bs-primary)) 80%, #000); }
.help-assistant-speak.is-unavailable { opacity: 0.4; cursor: not-allowed; }

@media (max-width: 767.98px) {
    .help-assistant-panel { top: 3.75rem; right: 0.5rem; left: 0.5rem; bottom: 0.5rem; width: auto; }
}
