/* ================================================================
   UI POLISH LAYER
   ================================================================
   Loaded after every global stylesheet and before the page-scoped
   and per-route sheets, so it corrects shared defaults without
   overriding a page that deliberately styles itself.

   Every value derives from the --company-* tokens defined in
   CompanyCSSCustomization.css, so per-tenant theming still applies.

   Sections:
     1.  Motion and accessibility foundation
     2.  Form controls
     3.  Buttons
     4.  Cards and surfaces
     5.  Tables
     6.  Badges and status pills
     7.  Overlays: modals, dropdowns, tooltips
     8.  Scrollbars
     9.  Responsive and overflow containment
     10. Empty and loading states
     11. Page header consistency
     12. Dark theme surfaces
     13. Print
   ================================================================ */


/* -- 1. MOTION AND ACCESSIBILITY FOUNDATION -------------------- */

:root {
    /* One motion scale, so hovers and transitions across modules
       settle at the same speed instead of each picking their own. */
    --ui-motion-fast: 120ms;
    --ui-motion-base: 180ms;
    --ui-motion-slow: 260ms;
    --ui-ease: cubic-bezier(.4, 0, .2, 1);

    /* Focus ring, expressed against the tenant brand colour. */
    --ui-focus-ring: 0 0 0 3px color-mix(in srgb, var(--company-primary-500, #3b82f6) 35%, transparent);
    --ui-focus-color: var(--company-primary-600, #2563eb);
}

/* Keyboard focus was invisible across the app: several sheets reset
   outline without providing a replacement. One consistent ring,
   applied only for keyboard users so it never fires on mouse click. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible,
.btn:focus-visible,
.hr-btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--ui-focus-color) !important;
    outline-offset: 2px !important;
    box-shadow: var(--ui-focus-ring) !important;
}

/* Mouse and touch users keep a clean surface. */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
.btn:focus:not(:focus-visible),
.hr-btn:focus:not(:focus-visible) {
    outline: none !important;
}

/* In-page anchors clear the fixed header. */
:target {
    scroll-margin-top: calc(var(--company-height-header, 70px) + 1rem);
}

/* Respect the OS reduce-motion setting everywhere, including the
   decorative page-entry and hover-lift animations added per module. */
@media (prefers-reduced-motion: reduce) {

    *,
    *::before,
    *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }

    *:hover {
        transform: none !important;
    }
}


/* -- 2. FORM CONTROLS ------------------------------------------ */

/* modern-global.css pins .form-control to a fixed height with
   !important. That rule also matches textareas and multi-selects, so
   every rows="3" textarea in the app collapsed to a single line.
   Restore intrinsic height for the controls that need to grow. */
textarea.form-control,
textarea.form-control-modern,
select[multiple].form-control,
select[size].form-control,
select[multiple].form-select,
select[size]:not([size="1"]).form-select {
    height: auto !important;
    min-height: calc(2.25rem + 2px);
}

textarea.form-control,
textarea.form-control-modern {
    /* Vertical only: horizontal resize breaks grid form layouts. */
    resize: vertical;
    padding-block: .5rem;
    line-height: var(--company-leading-normal, 1.5);
}

/* Single-line controls carry a fixed height (modern-global.css pins it,
   and a tenant's generated CSS can pin it again at 42px). Several
   module sheets then set .75rem vertical padding, which together with
   the 1.5 line-height needs ~46px inside a 40px content box - so the
   text was clipped along its bottom edge. Cap the vertical padding so
   the line always fits the height it is given. */
.form-control:not(textarea),
.form-select {
    padding-block: .5rem !important;
}

/* Placeholders were inheriting body colour in several sheets and read
   as filled-in values. Tie them to the tertiary text token. */
.form-control::placeholder,
.form-select::placeholder,
textarea::placeholder,
input::placeholder {
    color: var(--company-text-tertiary, #9ca3af);
    opacity: 1;
}

/* Disabled and readonly states were visually identical to editable
   ones on several forms. */
.form-control:disabled,
.form-select:disabled,
.form-control[readonly],
fieldset:disabled .form-control,
fieldset:disabled .form-select {
    background-color: var(--company-bg-tertiary, #f3f4f6) !important;
    color: var(--company-text-secondary, #6b7280) !important;
    cursor: not-allowed;
    opacity: 1;
}

/* Validation feedback needs the same treatment for Blazor's own
   .invalid class as for Bootstrap's .is-invalid. */
.form-control.invalid,
.form-select.invalid,
.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--company-danger, #ef4444) !important;
}

.form-control.invalid:focus,
.form-select.invalid:focus,
.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(var(--company-danger-rgb, 239, 68, 68), .25) !important;
}

.validation-message,
.invalid-feedback {
    display: block;
    margin-top: .3rem;
    font-size: var(--company-text-xs, .75rem);
    font-weight: var(--company-font-medium, 500);
    color: var(--company-danger, #ef4444);
}

/* Labels were rendering at several different weights across modules. */
.form-label {
    margin-bottom: .375rem;
    font-size: var(--company-text-sm, .875rem);
    font-weight: var(--company-font-medium, 500);
    color: var(--company-text-primary, #111827);
}

/* Required-field marker, opt-in via .required on the label. */
.form-label.required::after {
    content: " *";
    color: var(--company-danger, #ef4444);
    font-weight: var(--company-font-bold, 700);
}

/* Checkboxes and radios were at the 13px default and hard to hit. */
.form-check-input {
    width: 1.05rem;
    height: 1.05rem;
    margin-top: .18rem;
    cursor: pointer;
    transition: background-color var(--ui-motion-fast) var(--ui-ease),
                border-color var(--ui-motion-fast) var(--ui-ease);
}

.form-check-label {
    cursor: pointer;
    padding-inline-start: .15rem;
}

/* iOS zooms the page when a focused input is under 16px. */
@media (max-width: 767.98px) {

    .form-control,
    .form-select,
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input[type="number"],
    input[type="search"],
    input[type="date"],
    textarea {
        font-size: 16px !important;
    }
}


/* -- 3. BUTTONS ------------------------------------------------ */

/* Icon plus label buttons were relying on non-breaking spaces and
   ad-hoc margins, so the gap varied per page. Flex with a token gap
   normalises it and centres the icon against the label. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45em;
    line-height: 1.4;
    vertical-align: middle;
}

.btn > i,
.btn > .fa,
.btn > svg,
.hr-btn > i,
.hr-btn > svg {
    flex-shrink: 0;
    line-height: 1;
}

/* Margin-based icon spacing still ships on many pages; the flex gap
   already provides it, so collapse the duplicate. */
.btn > i.me-1,
.btn > i.me-2,
.btn > i.ms-1,
.btn > i.ms-2 {
    margin-inline: 0 !important;
}

/* Disabled buttons kept the hover lift and pointer, so they read as
   clickable. */
.btn:disabled,
.btn.disabled,
.btn[disabled] {
    cursor: not-allowed;
    opacity: .55;
    transform: none !important;
    box-shadow: none !important;
}

.btn:disabled:hover,
.btn.disabled:hover,
.btn[disabled]:hover {
    transform: none !important;
}

/* The global .btn overflow:hidden used for the ripple clips
   absolutely-positioned children such as count badges and carets. */
.btn:has(> .badge),
.btn:has(> .btn-badge),
.btn.dropdown-toggle {
    overflow: visible !important;
}

/* A tenant's generated stylesheet sets `a, .btn-link { color: <brand>
   !important }`. An <a> styled as a solid button matches that rule, so
   its label took the brand colour on top of a brand-coloured
   background - "Go To Dashboard" on the error page rendered at a 1.00
   contrast ratio, i.e. completely invisible.

   a.btn-primary (0,1,1) outranks a bare `a` (0,0,1), so this wins even
   though the tenant sheet is injected later. Deferring to Bootstrap's
   own --bs-btn-color keeps it variant-correct: white on the dark
   variants, near-black on .btn-warning and .btn-light. */
a.btn-primary,
a.btn-secondary,
a.btn-success,
a.btn-danger,
a.btn-warning,
a.btn-info,
a.btn-light,
a.btn-dark {
    color: var(--bs-btn-color) !important;
}

/* A padding utility written on a button should win over the blanket
   .btn padding. It did not: a tenant's generated sheet sets
   `.btn { padding: 12px 24px !important }` and is injected after
   Bootstrap, so `.p-1 !important` lost on source order at equal
   specificity. Around 60 buttons across the app carry one of these
   utilities to be compact - the Projects cards were the visible
   symptom, where two icon buttons marked p-1 rendered 62px wide and
   squeezed the card title into a 71px column four lines tall.

   .btn.p-1 is (0,2,0) and outranks a bare .btn, so these win from here
   regardless of injection order. */
.btn.p-0  { padding: 0 !important; }
.btn.p-1  { padding: .25rem !important; }
.btn.p-2  { padding: .5rem !important; }
.btn.p-3  { padding: 1rem !important; }

.btn.px-0 { padding-inline: 0 !important; }
.btn.px-1 { padding-inline: .25rem !important; }
.btn.px-2 { padding-inline: .5rem !important; }
.btn.px-3 { padding-inline: 1rem !important; }
.btn.px-4 { padding-inline: 1.5rem !important; }
.btn.px-5 { padding-inline: 3rem !important; }

.btn.py-0 { padding-block: 0 !important; }
.btn.py-1 { padding-block: .25rem !important; }
.btn.py-2 { padding-block: .5rem !important; }
.btn.py-3 { padding-block: 1rem !important; }

/* Icon-only buttons should be square and meet the touch target
   rather than inheriting the text button horizontal padding. */
.btn-icon,
.hr-btn-icon {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0 !important;
    border-radius: var(--company-radius-md, .5rem) !important;
}

@media (pointer: coarse) {

    .btn-icon,
    .hr-btn-icon {
        width: 2.5rem;
        height: 2.5rem;
    }
}

/* A button group's members were each rendering full rounding, so the
   seams doubled up. */
.btn-group > .btn:not(:first-child) {
    margin-inline-start: -1px;
}

/* Busy buttons: pairs with the existing .spinner-border markup. */
.btn .spinner-border-sm {
    width: .9rem;
    height: .9rem;
    border-width: .15em;
}


/* -- 4. CARDS AND SURFACES ------------------------------------- */

/* modern-global.css lifts every .card 2px on hover, including static
   form panels and read-only detail cards. The transform also opens a
   stacking context, which is why a dropdown opened inside a card can
   render behind a neighbouring card.

   Non-interactive cards now get a shadow-only hover (no transform, no
   stacking context); the lift is kept for cards that really click. */
.card:hover {
    transform: none !important;
}

a.card:hover,
.card[role="button"]:hover,
.card.is-clickable:hover,
.card.card-interactive:hover,
.card.clickable:hover {
    transform: translateY(-2px) !important;
}

a.card,
.card[role="button"],
.card.is-clickable,
.card.card-interactive,
.card.clickable {
    cursor: pointer;
    text-decoration: none;
}

/* Card padding was set independently per module; align the body and
   header so headers line up with the content beneath them. */
.card-header,
.card-body,
.card-footer {
    padding-inline: 1.25rem;
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    flex-wrap: wrap;
    padding-block: .875rem;
}

.card-header > h1,
.card-header > h2,
.card-header > h3,
.card-header > h4,
.card-header > h5,
.card-header > h6 {
    margin: 0;
    font-size: var(--company-text-base, 1rem);
    font-weight: var(--company-font-semibold, 600);
    line-height: 1.3;
}

.card-footer {
    background-color: var(--company-bg-secondary, #f9fafb);
    border-top: 1px solid var(--company-border-light, #e5e7eb);
}


/* -- 5. TABLES ------------------------------------------------- */

.table {
    width: 100%;
    margin-bottom: 0;
    vertical-align: middle;
}

.table > thead > tr > th,
.table > tbody > tr > td,
.table > tbody > tr > th {
    padding: .7rem .875rem;
    vertical-align: middle;
}

.table > thead > tr > th {
    font-size: var(--company-text-xs, .75rem);
    font-weight: var(--company-font-semibold, 600);
    letter-spacing: .03em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* Header stays visible when a wrapper constrains the height. Harmless
   where it does not: sticky without a scroll container is a no-op.
   The explicit background is required or rows show through it. */
.table-responsive > .table > thead > tr > th,
.hr-table-wrapper > .table > thead > tr > th,
.table-sticky > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--company-table-header-bg, var(--company-bg-secondary, #f9fafb));
}

/* Numeric columns read better right-aligned and tabular. */
.table td.text-end,
.table th.text-end,
.table .num,
.table .amount {
    font-variant-numeric: tabular-nums;
}

/* Row hover was defined only under .table-hover; many tables omit the
   class, so their rows gave no feedback at all. */
.table > tbody > tr {
    transition: background-color var(--ui-motion-fast) var(--ui-ease);
}

.table > tbody > tr:hover {
    background-color: var(--company-table-hover-bg, rgba(0, 0, 0, .025));
}

/* Action cells: keep controls on one line and hard against the edge. */
.table td.actions,
.table td .table-actions {
    display: flex;
    align-items: center;
    gap: .35rem;
    justify-content: flex-end;
    white-space: nowrap;
}

/* Every wrapper in use gets the same scroll affordance, so a wide
   table scrolls inside its card instead of widening the page. */
.table-responsive,
.hr-table-wrapper,
.employee-table-container,
.department-table-container,
.perf-table-container,
.wf-table-wrapper,
.zk-table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}

@media (max-width: 767.98px) {

    .table > thead > tr > th,
    .table > tbody > tr > td {
        padding: .55rem .625rem;
        font-size: var(--company-text-sm, .875rem);
    }
}

/* Safety net. Roughly twenty pages render a <table> with no scrollable
   wrapper around it. Those tables used to widen the page; with .page
   clipping horizontal overflow they would instead be silently cut off,
   which is worse. Making the table its own scroll container keeps the
   columns reachable without touching the markup.

   Scoped to narrow viewports, and undone for the wrappers that already
   scroll - display:block would otherwise stop those tables filling
   their wrapper. */
@media (max-width: 991.98px) {

    .main-content table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .table-responsive > table,
    .hr-table-wrapper > table,
    [class*="table-wrapper"] > table,
    [class*="table-container"] > table,
    [class*="table-scroll"] > table {
        display: table;
        width: 100%;
    }
}


/* -- 6. BADGES AND STATUS PILLS -------------------------------- */

/* Status text shipped as plain .badge, .status, and a dozen
   module-specific classes at differing heights. Normalise the shape
   so a status column lines up regardless of which class a page used. */
.badge,
.hr-badge,
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: .3em;
    padding: .3em .65em;
    font-size: var(--company-text-xs, .75rem);
    font-weight: var(--company-font-semibold, 600);
    line-height: 1.4;
    letter-spacing: .01em;
    border-radius: var(--company-radius-full, 9999px);
    white-space: nowrap;
    vertical-align: middle;
}

/* Solid contextual badges are heavy in a dense table. Soft tints keep
   the status readable without shouting. */
.badge.bg-success-soft { background: var(--company-success-light, #d1fae5); color: #065f46; }
.badge.bg-warning-soft { background: var(--company-warning-light, #fef3c7); color: #92400e; }
.badge.bg-danger-soft  { background: var(--company-danger-light,  #fee2e2); color: #991b1b; }
.badge.bg-info-soft    { background: var(--company-info-light,    #dbeafe); color: #1e40af; }


/* -- 7. OVERLAYS: MODALS, DROPDOWNS, TOOLTIPS ------------------ */

/* Long modals scrolled the page behind them instead of their own
   body, so the footer buttons drifted off-screen. */
.modal-body {
    max-height: min(70vh, 40rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.modal-header,
.modal-footer {
    flex-shrink: 0;
}

.modal-footer {
    gap: .5rem;
}

.modal-footer > * {
    margin: 0;
}

/* Dropdowns opened inside cards and table cells were being clipped or
   painted under the next card. */
.dropdown-menu {
    z-index: var(--company-z-dropdown, 1000);
    border: 1px solid var(--company-border-light, #e5e7eb);
    border-radius: var(--company-radius-lg, .75rem);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .11);
    padding: .35rem;
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .5rem .7rem;
    border-radius: var(--company-radius-md, .5rem);
    font-size: var(--company-text-sm, .875rem);
    transition: background-color var(--ui-motion-fast) var(--ui-ease);
}

.dropdown-item > i {
    width: 1rem;
    text-align: center;
    color: var(--company-text-tertiary, #9ca3af);
}

.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--company-bg-tertiary, #f3f4f6);
}

.dropdown-item.active,
.dropdown-item:active {
    background-color: var(--company-primary-600, #2563eb);
    color: #fff;
}

.dropdown-item.active > i,
.dropdown-item:active > i {
    color: inherit;
}


/* -- 8. SCROLLBARS --------------------------------------------- */

/* Default Windows scrollbars are 17px and sit heavily inside cards
   and table wrappers. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--company-border-medium, #d1d5db) transparent;
}

*::-webkit-scrollbar {
    width: 9px;
    height: 9px;
}

*::-webkit-scrollbar-track {
    background: transparent;
}

*::-webkit-scrollbar-thumb {
    background-color: var(--company-border-medium, #d1d5db);
    border-radius: var(--company-radius-full, 9999px);
    border: 2px solid transparent;
    background-clip: content-box;
}

*::-webkit-scrollbar-thumb:hover {
    background-color: var(--company-text-tertiary, #9ca3af);
    background-clip: content-box;
}


/* -- 9. RESPONSIVE AND OVERFLOW CONTAINMENT -------------------- */

/* Media and embeds were widening pages on mobile. */
img,
svg,
video,
canvas,
iframe {
    max-width: 100%;
}

img,
video {
    height: auto;
}

/* Long unbroken values - emails, tokens, URLs, file names - were the
   other source of horizontal overflow in tables and detail lists. */
.table td,
.hr-detail-value,
.text-break-anywhere {
    overflow-wrap: anywhere;
}

/* The main region scrolls; the page shell should not also scroll
   sideways. clip, unlike hidden, does not create a scroll container,
   so sticky headers and dropdowns keep working. */
.page {
    overflow-x: clip;
}

/* Page padding tightens with the viewport instead of holding 1.5rem
   all the way down to 360px. */
@media (max-width: 991.98px) {

    .hr-page,
    .page-container {
        padding-inline: 1rem;
    }
}

@media (max-width: 575.98px) {

    .hr-page,
    .page-container {
        padding-inline: .75rem;
        padding-block: 1rem;
    }

    /* Page-header actions stack and go full width rather than
       squeezing into a sliver of a column. */
    .hr-page-header,
    .hr-page-header-flat {
        padding: 1.125rem 1rem;
    }

    .hr-page-actions {
        width: 100%;
    }

    .hr-page-actions > .btn,
    .hr-page-actions > .hr-btn {
        flex: 1 1 auto;
        justify-content: center;
    }

    .hr-page-title {
        font-size: 1.25rem;
    }
}

/* Touch targets: anything interactive in a toolbar or table row
   should clear the recommended minimum on a touch device. */
@media (pointer: coarse) {

    .btn,
    .hr-btn,
    .dropdown-item,
    .nav-link {
        min-height: 2.5rem;
    }
}


/* -- 10. EMPTY AND LOADING STATES ------------------------------ */

/* Modules each rolled their own empty state; centre and calm them. */
.empty-state,
.hr-empty,
.no-data {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--company-text-secondary, #6b7280);
}

.empty-state > i,
.hr-empty > i,
.no-data > i {
    font-size: 2.5rem;
    color: var(--company-text-tertiary, #9ca3af);
    margin-bottom: .25rem;
}

.empty-state h3,
.empty-state h4,
.hr-empty h3,
.hr-empty h4 {
    margin: 0;
    font-size: var(--company-text-lg, 1.125rem);
    font-weight: var(--company-font-semibold, 600);
    color: var(--company-text-primary, #111827);
}

/* A region waiting on data should not accept clicks meanwhile. */
[aria-busy="true"] {
    cursor: progress;
}


/* -- 11. PAGE HEADER CONSISTENCY ------------------------------- */

/* .hr-page-header / .hr-page-title is the dominant page header - about
   seventy pages use it. Nine modules grew their own header block
   instead, and they drifted: titles landed anywhere between 24px and
   28px, header padding between 1.25rem and 2rem, and the gap to the
   content below between 1rem and 2rem. Side by side across a session
   the page headers visibly failed to line up.

   Only the metrics are normalised here. Each module keeps its own
   background and text colours - some of these headers are gradients
   with white text and others are flat white with dark text, so
   unifying colour would break contrast. */

/* The .main-content prefix is deliberate. These module headers are
   styled in per-route stylesheets, which the route manifest loads
   *after* this file, so a bare class selector would lose to them on
   source order. The descendant selector outranks it instead - no
   !important needed. */
.main-content .content-page-header,
.main-content .ann-page-header,
.main-content .wf-page-header,
.main-content .probation-page-header,
.main-content .notify-page-header,
.main-content .settings-page-header,
.main-content .emp-page-header,
.main-content .db-page-header,
.main-content .css-page-header {
    padding: 1.75rem 2rem;
    margin-bottom: 1.75rem;
    border-radius: var(--company-radius-xl, 1rem);
}

/* The flat (white) header variants keep their tighter padding - that
   distinction is deliberate - but the gap down to the page content
   should match the gradient headers rather than sitting 4px tighter. */
.main-content .hr-page-header-flat,
.main-content .ann-page-header-flat {
    margin-bottom: 1.75rem;
}

/* Title size is left to the tenant's own h1 rule so page titles stay
   under tenant control and move together. What is normalised is the
   block metrics above, and the subtitle beneath the title - which
   modules had set anywhere from 0.8rem to 0.95rem. */
.main-content .content-page-header > p,
.main-content .wf-page-header p,
.main-content .probation-page-header p,
.main-content .notify-page-header p,
.main-content .css-page-header p,
.main-content .ann-page-header p,
.main-content .settings-page-header p,
.main-content .emp-page-header p,
.main-content .db-page-header p {
    font-size: var(--company-text-sm, .875rem);
    margin: 0;
}

/* Matches the .hr-page-header treatment already applied at this width. */
@media (max-width: 575.98px) {

    .main-content .content-page-header,
    .main-content .ann-page-header,
    .main-content .wf-page-header,
    .main-content .probation-page-header,
    .main-content .notify-page-header,
    .main-content .settings-page-header,
    .main-content .emp-page-header,
    .main-content .db-page-header,
    .main-content .css-page-header {
        padding: 1.125rem 1rem;
    }
}


/* -- 12. DARK THEME SURFACES ----------------------------------- */

/* A tenant's generated stylesheet is injected into <head> after this
   file and pins the app's surfaces to literal light colours with
   !important - html body, .card, .card-header, table headers, the
   sidebar. Those declarations do not know about the theme, so in dark
   mode the surfaces stayed white while the text tokens went light, and
   the app became unreadable.

   Two !important declarations are resolved by specificity, not source
   order, so prefixing with :root[data-theme="dark"] wins from here even
   though this file is loaded first. Everything below re-points those
   surfaces at the theme tokens rather than at new hard-coded colours,
   so tenant branding still drives the palette. */

:root[data-theme="dark"] body,
:root[data-theme="dark"] html body {
    background-color: var(--company-bg-secondary) !important;
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] .card,
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .dropdown-menu {
    background-color: var(--company-bg-primary) !important;
    border-color: var(--company-border-light) !important;
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] .card-header,
:root[data-theme="dark"] .card-footer,
:root[data-theme="dark"] .modal-header,
:root[data-theme="dark"] .modal-footer {
    background-color: var(--company-bg-secondary) !important;
    border-color: var(--company-border-light) !important;
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] table,
:root[data-theme="dark"] .table {
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] table thead,
:root[data-theme="dark"] table thead th,
:root[data-theme="dark"] .table > thead > tr > th {
    background-color: var(--company-bg-tertiary) !important;
    color: var(--company-text-secondary) !important;
    border-color: var(--company-border-light) !important;
}

:root[data-theme="dark"] table tbody tr,
:root[data-theme="dark"] .table > tbody > tr {
    background-color: transparent !important;
    border-color: var(--company-border-light) !important;
}

:root[data-theme="dark"] table tbody tr:hover,
:root[data-theme="dark"] .table > tbody > tr:hover {
    background-color: var(--company-bg-tertiary) !important;
}

:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] .form-select,
:root[data-theme="dark"] textarea {
    background-color: var(--company-bg-secondary) !important;
    border-color: var(--company-border-medium) !important;
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] .form-control:disabled,
:root[data-theme="dark"] .form-select:disabled,
:root[data-theme="dark"] .form-control[readonly] {
    background-color: var(--company-bg-tertiary) !important;
    color: var(--company-text-secondary) !important;
}

/* Bootstrap's light utilities are opaque white and were punching holes
   through the dark surfaces. */
:root[data-theme="dark"] .bg-white,
:root[data-theme="dark"] .bg-light,
:root[data-theme="dark"] .table-light {
    background-color: var(--company-bg-secondary) !important;
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] .text-dark,
:root[data-theme="dark"] .text-body {
    color: var(--company-text-primary) !important;
}

:root[data-theme="dark"] .text-muted {
    color: var(--company-text-tertiary) !important;
}

:root[data-theme="dark"] .border,
:root[data-theme="dark"] .border-top,
:root[data-theme="dark"] .border-bottom,
:root[data-theme="dark"] .border-start,
:root[data-theme="dark"] .border-end {
    border-color: var(--company-border-light) !important;
}


/* -- 13. PRINT ------------------------------------------------- */

/* Reports and payslips are printed from these pages; the app chrome
   should not come with them. */
@media print {

    .top-nav-header,
    .mobile-nav,
    .header-actions,
    .hr-page-actions,
    .no-print,
    .btn,
    .dropdown-menu {
        display: none !important;
    }

    .page,
    .main-content {
        display: block !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    .card {
        border: 1px solid #ddd !important;
        box-shadow: none !important;
        break-inside: avoid;
    }

    .table > thead {
        display: table-header-group;
    }

    .table > tbody > tr {
        break-inside: avoid;
    }
}
