/* =============================================================================================
   TimeView theme layer — everything that must load AFTER the Syncfusion theme stylesheet.

   Served from TSO.TimeView.Shared.Components as _content/TSO.TimeView.Shared.Components/tv-theme.css.
   Hosts load: tv-tokens.css -> Syncfusion bootstrap5.3(-dark).css -> tv-theme.css -> host css.
   Contents: brand-primary override of the --color-sf-primary family, dark/high-contrast fallback
   keyed on body[data-theme], e-icons colour inheritance, scrollbars, html/body base, element
   defaults (links, focus ring), the .tv-btn hierarchy, and shell z-index plumbing for
   SfSidebar/SfDialog. Hosts MUST set body[data-theme="light|dark"] before first paint.
   ============================================================================================= */

/* Theme overrides for Syncfusion components - loaded last to ensure highest specificity */

/* Fix for Syncfusion e-icons to inherit theme colors instead of staying black */
/* This file is loaded AFTER all other CSS including Syncfusion themes */

/* Force all e-icons to inherit color from parent */
.e-icons,
.e-icons::before,
.e-icons::after {
    color: inherit !important;
}

/* More specific selectors to ensure they apply in TreeView context */
.e-treeview .e-icons,
.e-treeview .e-icons::before,
.e-treeview .e-icons::after {
    color: inherit !important;
}

/* Ensure all icon types inherit color */
span.e-icons,
span.e-icons::before,
div.e-icons,
div.e-icons::before,
i.e-icons,
i.e-icons::before {
    color: inherit !important;
}

/* For any SVG-based icons */
.e-icons svg,
.e-icons svg path {
    fill: currentColor !important;
}

/* Override any hardcoded colors in Syncfusion's CSS */
.e-treeview .e-text-content .e-icons,
.e-treeview .e-text-content .e-icons::before {
    color: inherit !important;
}

/* Fix for parent items with children (those with expand/collapse icons) */
.e-treeview .e-list-item .e-icons.e-icon-collapsible,
.e-treeview .e-list-item .e-icons.e-icon-expandable,
.e-treeview .e-list-item .e-icons.e-icon-collapsible::before,
.e-treeview .e-list-item .e-icons.e-icon-expandable::before {
    color: inherit !important;
}

/* TreeView specific overrides */
.e-treeview .e-list-item .e-text-content div.e-list-icon.e-icons,
.e-treeview .e-list-item .e-text-content div.e-list-icon.e-icons::before {
    color: inherit !important;
}

/* Hover and active states - let JavaScript handle colors dynamically */
.e-treeview .e-list-item.e-hover .e-text-content div.e-list-icon.e-icons,
.e-treeview .e-list-item.e-hover .e-text-content div.e-list-icon.e-icons::before,
.e-treeview .e-list-item.e-active .e-text-content div.e-list-icon.e-icons,
.e-treeview .e-list-item.e-active .e-text-content div.e-list-icon.e-icons::before {
    color: inherit !important;
}

/* =========================================================================
   Scrollbar Theme Support - Light and Dark Themes
   ========================================================================= */

/* Scrollbar colours are derived from the element's own foreground, so they track whichever
   Syncfusion theme is active without a per-theme branch. The previous light/dark pair hardcoded
   eight greys and had no high-contrast case at all. */
:root {
    /* Scrollbar track (background) */
    --scrollbar-track-color: var(--tv-surface-alt);
    /* Scrollbar thumb (the draggable part) */
    --scrollbar-thumb-color: color-mix(in srgb, currentColor 30%, transparent);
    /* Scrollbar thumb on hover */
    --scrollbar-thumb-hover-color: color-mix(in srgb, currentColor 45%, transparent);
    /* Scrollbar thumb when active/dragging */
    --scrollbar-thumb-active-color: color-mix(in srgb, currentColor 60%, transparent);
}

/* Base body styles. The surface and text colour come from the active Syncfusion theme rather
   than a hardcoded light pair plus a dark override. */
html, body {
    margin: 0;
    padding: 0;
    background-color: var(--tv-body-bg);
    color: var(--tv-body-fg);
}

/* The high-contrast theme ships **no** --color-sf-* custom properties at all (verified: zero
   definitions in highcontrast.css), and App.razor collapses it onto data-theme="dark". Without
   this branch every --color-sf-* above resolves to its light fallback, so a dark theme renders
   dark widgets on a light canvas.

   This is not a hand-rolled dark palette — the values still read the theme where it publishes
   one, so bootstrap5.3-dark continues to win with its own --color-sf-* values. Only the
   *fallback* differs, which is the one thing data-theme can still tell us.

   The selector must resolve on **html**, not body, for two reasons — App.razor sets data-theme
   on body, hence :has():
     1. A custom property is substituted at computed-value time on the element that declares it.
        The aliases above (--color-bg-surface: var(--tv-surface), :93) are declared at :root, so
        they are resolved once on html and descendants inherit the already-substituted result.
        Overriding --tv-surface on body therefore could not reach them, and AiChat's panels
        rendered white on a dark canvas.
     2. html's background is what propagates to the page canvas. A background set only on body
        paints the body box, leaving a light rim under high contrast. */
:root:has(body[data-theme="dark"]) {
    --tv-body-bg: color-mix(in srgb, var(--color-sf-content-bg-color, #1e1e1e) 96%, #000000);
    --tv-body-fg: var(--color-sf-content-text-color, #e0e0e0);
    --tv-surface: var(--color-sf-content-bg-color, #1e1e1e);
}

/* =========================================================================
   Brand primary — the Syncfusion "primary" is the TimeSolutions blue
   =========================================================================
   Every primary button, link, selected row, active nav item, focus ring and progress fill in
   the app takes its colour from the theme's --color-sf-primary family. Redefining that family
   here, in the one stylesheet that loads *after* the theme (see App.razor: the theme <link> is
   inserted immediately before this file), rebrands all of them at once. Components keep reading
   the theme's variable names; only what those names resolve to has changed. The app-level
   --palette-accent / --tv-accent alias --color-sf-primary, so they follow for free.

   Why the whole family and not just --color-sf-primary: bootstrap5.3.css does NOT derive its
   hover/pressed/light/lighter/dark/darker values from --color-sf-primary — each is a literal
   (#0b5ed7, #86b7fe, #cfe2ff, …). Override only the base and every hover flips back to Bootstrap
   blue. The derived values below are color-mix()ed from the chosen brand hue so the family stays
   internally consistent and the hue is still written down exactly once, in app.css. Four more
   variables outside the family (-content-bg-color-selected, -flyout-bg-color-pressed,
   -border-focus, -border-selected) are the same literal blue and are re-pointed at the end.

   Why BLUE, measured against white and the dark canvas #212529:

                              fill vs canvas    white text on fill   as link text
       light  --brand-blue          5.74               5.74               5.74   ✓ AA
       light  --brand-darkblue     11.98              11.98              11.98
       dark   --brand-blue          2.69               5.74               —  (links use -darker: 7.68)
       dark   --brand-darkblue      1.29                —                 1.29   ✗ invisible

   DARKBLUE is the flagship colour but disappears on the dark canvas, and running two hues meant
   the app looked like a different brand per theme. BLUE clears AA for text and links in light and
   carries white labels in dark, so it is the one primary for both. (Its dark fill-vs-canvas
   contrast of 2.69 is below the 3:1 component floor — accepted for the label contrast; Bootstrap's
   own dark primary sits at 3.43 / 4.50.) To change the brand primary later, change the one
   --tv-brand-primary line; nothing else references a hue.

   --color-sf-primary-shadow is an "r, g, b" triplet the theme feeds into rgba(); it cannot be
   derived with color-mix(), so it is the one place the hue is repeated, in a different notation.
   Keep it in step with --tv-brand-primary above it.

   The dark branch keys on data-theme like the block above, so highcontrast (which ships no
   --color-sf-* at all) also receives these values — meaning components' var(--color-sf-primary,
   #hex) fallbacks now resolve to brand blue there rather than to Bootstrap blue. Intended. */
:root {
    --tv-brand-primary: var(--brand-blue);
    --tv-brand-primary-shadow: 23, 104, 178;

    --color-sf-primary: var(--tv-brand-primary);
    --color-sf-primary-text-color: var(--brand-white);
    --color-sf-primary-shadow: var(--tv-brand-primary-shadow);

    /* Hover darkens, pressed darkens further — the same direction the theme takes. */
    --color-sf-primary-bg-color-hover:     color-mix(in srgb, var(--tv-brand-primary) 85%, black);
    --color-sf-primary-border-color-hover: color-mix(in srgb, var(--tv-brand-primary) 80%, black);
    --color-sf-primary-bg-color-pressed:     color-mix(in srgb, var(--tv-brand-primary) 75%, black);
    --color-sf-primary-border-color-pressed: color-mix(in srgb, var(--tv-brand-primary) 75%, black);
    --color-sf-primary-bg-color-disabled:    color-mix(in srgb, var(--tv-brand-primary) 65%, transparent);

    /* Tints, in the theme's own roles: -light is the soft border/outline (was #86b7fe),
       -lighter the selected/expanded wash (was #cfe2ff), -dark a mid fill, -darker the text that
       sits on the -lighter wash (was #052c65). Mixed toward the content surface rather than a
       fixed white so the wash sits on whatever the theme's panel colour is. */
    --color-sf-primary-light:   color-mix(in srgb, var(--tv-brand-primary) 45%, var(--color-sf-content-bg-color, white));
    --color-sf-primary-lighter: color-mix(in srgb, var(--tv-brand-primary) 15%, var(--color-sf-content-bg-color, white));
    --color-sf-primary-dark:    color-mix(in srgb, var(--tv-brand-primary) 90%, black);
    --color-sf-primary-darker:  color-mix(in srgb, var(--tv-brand-primary) 80%, black);

    /* Four siblings outside the -primary family are ALSO hardcoded Bootstrap blue in the theme
       (#0d6efd / #86b7fe) and drive the selected row in TreeView/ListView (the nav menu), the
       pressed flyout item, and the focus/selected input border. Left alone they stay Bootstrap
       blue next to a brand-blue primary — the mismatch the nav menu showed. */
    --color-sf-content-bg-color-selected: var(--tv-brand-primary);
    --color-sf-flyout-bg-color-pressed:   var(--tv-brand-primary);
    --color-sf-border-focus:    var(--color-sf-primary-light);
    --color-sf-border-selected: var(--color-sf-primary-light);
}

:root:has(body[data-theme="dark"]) {
    /* Same hue; only the tint roles invert. On a dark surface "darker" is the theme's *text* tint
       (was #6ea8fe): it must get lighter, not darker, to stay legible. 45 % toward white measures
       7.68 against #212529. */
    --color-sf-primary-lighter: color-mix(in srgb, var(--tv-brand-primary) 18%, var(--color-sf-content-bg-color, #212529));
    --color-sf-primary-darker:  color-mix(in srgb, var(--tv-brand-primary) 45%, white);
}

/* Modern browsers (Chrome, Edge, Safari, Opera) - Webkit scrollbars */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
}

*::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

*::-webkit-scrollbar-track {
    background: var(--scrollbar-track-color);
}

*::-webkit-scrollbar-thumb {
    background-color: var(--scrollbar-thumb-color);
    border-radius: 6px;
    border: 2px solid var(--scrollbar-track-color);
    /* The track token is a translucent color-mix, so without padding-box the thumb's own
       background paints through its border and the 2px inset pill gap disappears. */
    background-clip: padding-box;
}

*::-webkit-scrollbar-thumb:hover {
    background-color: var(--scrollbar-thumb-hover-color);
}

*::-webkit-scrollbar-thumb:active {
    background-color: var(--scrollbar-thumb-active-color);
}

/* Scrollbar corner (where horizontal and vertical scrollbars meet) */
*::-webkit-scrollbar-corner {
    background: var(--scrollbar-track-color);
}

/* Firefox - Standard scrollbar-color property */
* {
    scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
}

/* Specific styling for Syncfusion components with scrollable content */
.e-dialog .e-dlg-content::-webkit-scrollbar,
.e-popup::-webkit-scrollbar,
.time-registration-container::-webkit-scrollbar,
.e-content::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

.e-dialog .e-dlg-content::-webkit-scrollbar-track,
.e-popup::-webkit-scrollbar-track,
.time-registration-container::-webkit-scrollbar-track,
.e-content::-webkit-scrollbar-track {
    background: var(--scrollbar-track-color);
}

.e-dialog .e-dlg-content::-webkit-scrollbar-thumb,
.e-popup::-webkit-scrollbar-thumb,
.time-registration-container::-webkit-scrollbar-thumb,
.e-content::-webkit-scrollbar-thumb {
    background-color: var(--scrollbar-thumb-color);
    border-radius: 6px;
    border: 2px solid var(--scrollbar-track-color);
    background-clip: padding-box;
}

.e-dialog .e-dlg-content::-webkit-scrollbar-thumb:hover,
.e-popup::-webkit-scrollbar-thumb:hover,
.time-registration-container::-webkit-scrollbar-thumb:hover,
.e-content::-webkit-scrollbar-thumb:hover {
    background-color: var(--scrollbar-thumb-hover-color);
}

.e-dialog .e-dlg-content::-webkit-scrollbar-thumb:active,
.e-popup::-webkit-scrollbar-thumb:active,
.time-registration-container::-webkit-scrollbar-thumb:active,
.e-content::-webkit-scrollbar-thumb:active {
    background-color: var(--scrollbar-thumb-active-color);
}

/* High contrast mode support for scrollbars */
@media (prefers-contrast: high) {
    *::-webkit-scrollbar-thumb {
        border: 3px solid transparent;
        background-clip: padding-box;
    }
}

/* Forced colors mode (Windows High Contrast) */
@media (forced-colors: active) {
    *::-webkit-scrollbar {
        color-scheme: light dark;
    }
    *::-webkit-scrollbar-track {
        background: Canvas;
    }
    *::-webkit-scrollbar-thumb {
        background: ButtonText;
        border-color: Canvas;
    }
    *::-webkit-scrollbar-thumb:hover,
    *::-webkit-scrollbar-thumb:active {
        background: Highlight;
    }
}

/* =========================================================================
   Sidebar fix — preserve position:fixed inside pushed content
   =========================================================================
   Syncfusion SfSidebar adds .e-content-animation to the pushed content area
   and may apply a CSS transform for the push animation. Any CSS transform on
   an ancestor creates a new containing block for position:fixed descendants,
   making them behave like position:absolute and scroll with the page.
   Resetting to transform:none here restores correct fixed-positioning behavior
   while the margin-based push animation continues to work.
   ========================================================================= */
.e-content-animation {
    transform: none !important;
}

/* Element defaults and the two-tone focus ring. Bootstrap's own stylesheet is not loaded in the
   BFF, so links and .btn-primary must be stated here or fall back to browser blue; in hosts that
   do load Bootstrap these simply re-point it at the accent token. */
html, body {
    font-family: var(--tv-font-sans);
}

/* Bootstrap's own stylesheet is not loaded (see App.razor), so these few element
   defaults have to be stated here or links fall back to the browser's default blue.
   They previously carried the stock template's hardcoded light-theme hex values,
   which stayed light-blue on the dark and high-contrast themes; they now track the
   accent token instead. */
a, .btn-link {
    color: var(--tv-accent);
}

.btn-primary {
    color: var(--tv-on-accent);
    background-color: var(--tv-accent);
    border-color: var(--tv-accent);
}

/* The inner white ring was invisible against a dark panel, leaving a single-colour
   halo instead of the intended two-tone focus indicator. currentColor's inverse is
   not available in CSS, so the surface token supplies the separating ring. */
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem var(--tv-focus-ring-inner), 0 0 0 0.25rem var(--tv-focus-ring);
}

/* The layout markup carried Bootstrap's `px-2` for its horizontal gutter, but the Bootstrap
   stylesheet is not loaded (its <link> is commented out in App.razor), so that class resolved to
   nothing and every page — the full-bleed entity grids most visibly — ran edge-to-edge. The
   gutter is owned here instead, via the shared token. */
.content {
    padding-top: var(--tv-content-top-gap);
    padding-inline: var(--tv-page-gutter);
}

/* Reset margin added by Syncfusion e-icon-left on icon-only buttons using MDI */
.e-icon-btn.e-btn .e-btn-icon.mdi {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* TvButton visual hierarchy. The Secondary variant is an outline: transparent bg, theme-aware
   text/icon/border, primary colour on hover. Primary (.e-primary) and Danger (.e-danger) keep the
   Syncfusion solid fill, so they are excluded here — an unscoped rule with !important silently
   turned every IsPrimary button in the app into an outline. :where() keeps the exclusion at zero
   specificity so the scoped .tv-btn-colored overrides in TvButton.razor.css still win. */
.e-btn.tv-btn:where(:not(.e-primary, .e-danger)) {
    background-color: transparent !important;
    border: 1px solid var(--color-sf-content-text-color) !important;
    color: var(--color-sf-content-text-color) !important;
}

.e-btn.tv-btn .e-btn-icon {
    color: inherit !important;
}

.e-btn.tv-btn:where(:not(.e-primary, .e-danger)):hover,
.e-btn.tv-btn:where(:not(.e-primary, .e-danger)):focus {
    background-color: transparent !important;
    border-color: var(--color-sf-primary) !important;
    color: var(--color-sf-primary) !important;
}

.e-btn.tv-btn:where(:not(.e-primary, .e-danger)):active {
    background-color: color-mix(in srgb, var(--color-sf-primary) 10%, transparent) !important;
    border-color: var(--color-sf-primary) !important;
    color: var(--color-sf-primary) !important;
}

/* Tertiary variant: the outline without its border. */
.e-btn.tv-btn.e-btn-borderless {
    border: none !important;
}

.e-btn.tv-btn.e-btn-borderless:hover,
.e-btn.tv-btn.e-btn-borderless:focus {
    border: none !important;
}

.e-btn.tv-btn.e-btn-borderless:active {
    border: none !important;
}

/* =========================================================================
   Main-layout sidebar z-index — must render above the sticky TopBar
   (z-index: 1000) on mobile where sidebar type is Over.
   Scope this override to the layout container to avoid affecting other
   Syncfusion sidebars.
   ========================================================================= */
#contentContainer .e-sidebar {
    z-index: var(--tv-z-sidebar) !important;
}

/* =========================================================================
   Modal dialogs must clear the app chrome. Syncfusion computes a dialog
   z-index of 1000 and writes it inline, which loses to the sidebar override
   directly above — so a modal renders behind the navigation menu.

   Only the container is lifted, never the overlay or the dialog itself:
   Syncfusion sets the overlay to exactly one below the dialog, and since
   both are children of the container, raising the container carries them up
   as a stacking context with that relative order intact. Overriding the
   inner two as well collapses the gap and the overlay covers the dialog,
   which presents as an unresponsive, greyed-out modal.
   !important is unavoidable here: nothing else outranks an inline style.
   ========================================================================= */
.e-dlg-container {
    z-index: var(--tv-z-dialog, 1100) !important;
}

/* The error dialog clears everything, including the toasts and any dialog that raised it — an
   exception must never be reported behind the screen that caused it. The selector targets the
   *container*, because the rule above is a blanket !important that a ZIndex on the SfDialog
   itself cannot beat. Same invariant as above: lift the container only. */
.e-dlg-container:has(.error-dialog) {
    z-index: var(--tv-z-error-dialog, 1400) !important;
}
