/* SweetAlert2 popups follow the page's own theme, light or dark.
   Every app here ships the same sweetalert2 build, whose card is hard-coded
   white with near-black text. On a dark page that card stayed white — and the
   form fields drawn inside it kept the page's light-on-dark colours, so the
   labels came out invisible (KPI calculation popup, 2026-09-11). This file
   paints the popup from the surface colours of whichever theme is switched on.

   Dark is read from the three signals used across the site:
     html[data-theme="dark"]      WowDash apps (HRIS, e-doc, smart-booking …)
     html[data-bs-theme="dark"]   Bootstrap 5 apps
     body.dark                    legacy apps (assets/js/script_darkmode.js)
   A page carrying none of them keeps the stock light popup, so nothing moves
   for the apps that have no dark mode at all.

   Only sweetalert's own chrome is repainted — the title, the container, the
   fields, the hairlines. Everything a caller puts inside `html:` keeps its own
   colours and simply inherits the card's text colour, so a popup that draws a
   red warning span still draws it red.

   Served from every DocumentRoot as /popup-theme.css and linked in the <head>
   of every page, which is why it has since become the place for the rest of
   the site-wide dark-theme corrections too — see the sections at the end of
   the file for disabled and read-only form fields (2026-09-12).
   Written 2026-09-11. */

/* ---------- tokens: light is the default ---------- */

:root,
html[data-theme="light"],
html[data-bs-theme="light"],
body[data-theme="light"],
body[data-bs-theme="light"] {
  --swal-surface: #ffffff;
  --swal-field: #ffffff;
  --swal-field-border: rgba(15, 23, 42, 0.22);
  --swal-text: #111827;
  --swal-muted: #4b5563;
  --swal-link: #2563eb;
  --swal-border: rgba(15, 23, 42, 0.12);
  --swal-shadow: 0 20px 45px rgba(15, 23, 42, 0.16);
  --swal-hairline: rgba(15, 23, 42, 0.08);
  --swal-close-filter: none;
  --swal-cancel-bg: #6e7881;
  --swal-cancel-fg: #ffffff;
  --swal-cancel-border: #6e7881;
}

/* ---------- dark: WowDash theme (its own card and field surfaces) ---------- */

html[data-theme="dark"],
body[data-theme="dark"] {
  --swal-surface: #273142;
  --swal-field: #323d4e;
  --swal-field-border: #4b5563;
  --swal-field-off: #1b2431;
  --swal-field-off-text: #cbd5e1;
  --swal-field-off-border: rgba(243, 244, 246, 0.16);
  --swal-text: #f3f4f6;
  --swal-muted: #cbd5e1;
  --swal-link: #60a5fa;
  --swal-border: rgba(243, 244, 246, 0.14);
  --swal-shadow: 0 20px 45px rgba(0, 0, 0, 0.45);
  --swal-hairline: rgba(243, 244, 246, 0.1);
  --swal-close-filter: invert(1) grayscale(100%) brightness(200%);
  --swal-cancel-bg: var(--swal-field);
  --swal-cancel-fg: var(--swal-text);
  --swal-cancel-border: var(--swal-field-border);
}

/* ---------- dark: Bootstrap 5 (--bs-body-bg / --bs-tertiary-bg) ---------- */

html[data-bs-theme="dark"],
body[data-bs-theme="dark"] {
  --swal-surface: #212529;
  --swal-field: #2b3035;
  --swal-field-border: #495057;
  --swal-field-off: #1a1d20;
  --swal-field-off-text: #adb5bd;
  --swal-field-off-border: rgba(222, 226, 230, 0.16);
  --swal-text: #dee2e6;
  --swal-muted: #adb5bd;
  --swal-link: #6ea8fe;
  --swal-border: rgba(222, 226, 230, 0.14);
  --swal-shadow: 0 20px 45px rgba(0, 0, 0, 0.5);
  --swal-hairline: rgba(222, 226, 230, 0.1);
  --swal-close-filter: invert(1) grayscale(100%) brightness(200%);
  --swal-cancel-bg: var(--swal-field);
  --swal-cancel-fg: var(--swal-text);
  --swal-cancel-border: var(--swal-field-border);
}

/* ---------- dark: legacy pages (assets/css/style_darkmode.css palette) ---------- */

body.dark,
body.dark-mode,
html.dark {
  --swal-surface: #242526;
  --swal-field: #3a3b3c;
  --swal-field-border: #4e4f50;
  --swal-field-off: #18191a;
  --swal-field-off-text: #b0b3b8;
  --swal-field-off-border: rgba(228, 230, 235, 0.16);
  --swal-text: #e4e6eb;
  --swal-muted: #b0b3b8;
  --swal-link: #6ea8fe;
  --swal-border: rgba(228, 230, 235, 0.14);
  --swal-shadow: 0 20px 45px rgba(0, 0, 0, 0.55);
  --swal-hairline: rgba(228, 230, 235, 0.1);
  --swal-close-filter: invert(1) grayscale(100%) brightness(200%);
  --swal-cancel-bg: var(--swal-field);
  --swal-cancel-fg: var(--swal-text);
  --swal-cancel-border: var(--swal-field-border);
}

/* ---------- the card ---------- */
/* !important throughout: sweetalert2 writes `background` straight onto the
   popup element whenever a call passes the `background` option. */

.swal2-popup,
.swal2-modal,
.swal2-toast {
  background: var(--swal-surface) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-border) !important;
  box-shadow: var(--swal-shadow) !important;
}

/* sweetalert's own text nodes. Children of the html container are left alone
   and inherit this colour. */
.swal2-title,
.swal2-html-container,
.swal2-content,
.swal2-input-label,
.swal2-popup label,
.swal2-popup .form-label,
.swal2-popup .form-check-label,
.swal2-popup .col-form-label,
.swal2-popup h1,
.swal2-popup h2,
.swal2-popup h3,
.swal2-popup h4,
.swal2-popup h5,
.swal2-popup h6 {
  color: var(--swal-text) !important;
}

.swal2-footer {
  color: var(--swal-muted) !important;
  border-top-color: var(--swal-hairline) !important;
}

.swal2-popup .text-muted,
.swal2-popup small.form-text {
  color: var(--swal-muted) !important;
}

/* No !important here: a popup that draws its own X over a coloured header
   (the logout sheet) must keep it. */
.swal2-close {
  color: var(--swal-muted);
}

.swal2-close:hover,
.swal2-close:focus {
  color: #f27474;
}

/* A few popups close with Bootstrap's .btn-close, which is a dark SVG. */
.swal2-popup .btn-close {
  filter: var(--swal-close-filter);
}

/* ---------- fields inside the card ---------- */

.swal2-input,
.swal2-file,
.swal2-select,
.swal2-textarea,
.swal2-popup input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="submit"]):not([type="button"]),
.swal2-popup select,
.swal2-popup textarea,
.swal2-popup .form-control,
.swal2-popup .form-select {
  background-color: var(--swal-field) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-field-border) !important;
}

.swal2-popup option,
.swal2-popup optgroup {
  background-color: var(--swal-field);
  color: var(--swal-text);
}

.swal2-popup input::placeholder,
.swal2-popup textarea::placeholder {
  color: var(--swal-muted) !important;
  opacity: 1;
}

/* The stock radio and checkbox rows carry a white background of their own. */
.swal2-checkbox,
.swal2-radio {
  background: transparent !important;
  color: var(--swal-text) !important;
}

.swal2-checkbox input,
.swal2-radio input,
.swal2-popup input[type="checkbox"],
.swal2-popup input[type="radio"] {
  accent-color: #2563eb;
}

.swal2-range output,
.swal2-range p {
  color: var(--swal-text) !important;
}

.swal2-validation-message {
  background: var(--swal-field) !important;
  color: var(--swal-text) !important;
}

.swal2-inputerror,
.swal2-popup .is-invalid {
  border-color: #f27474 !important;
}

/* ---------- structure a popup may draw in its html ---------- */

.swal2-popup table,
.swal2-popup .table {
  color: var(--swal-text) !important;
  border-color: var(--swal-hairline) !important;
}

.swal2-popup .table > :not(caption) > * > * {
  background-color: transparent !important;
  color: var(--swal-text) !important;
  border-bottom-color: var(--swal-hairline) !important;
}

.swal2-popup hr {
  border-color: var(--swal-hairline) !important;
  opacity: 1;
}

.swal2-popup .card,
.swal2-popup .list-group-item {
  background-color: var(--swal-field) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-hairline) !important;
}

.swal2-popup a:not(.btn) {
  color: var(--swal-link) !important;
}

/* ---------- loader and timer, kept visible on a dark card ---------- */

.swal2-loader {
  border-color: #2563eb transparent #2563eb transparent !important;
}

.swal2-timer-progress-bar {
  background: var(--swal-hairline) !important;
}

/* The action buttons keep whatever colour the call asked for — sweetalert
   writes that inline. Only the grey default of the cancel button is repainted,
   from tokens, so it reads as stock grey in light and as a quiet card-coloured
   button on any dark page (including the legacy ones, which signal dark by
   loading a different stylesheet rather than by a class). */
.swal2-styled.swal2-cancel:not([style*="background"]) {
  background: var(--swal-cancel-bg) !important;
  color: var(--swal-cancel-fg) !important;
  border: 1px solid var(--swal-cancel-border) !important;
}

/* ---------- Bootstrap modals, the site's other kind of popup ---------- */
/* Only .modal-content is painted. A .modal-body is very often a .row as well,
   and a row's negative gutter margins make any background painted on it spill
   past the card on both sides and up over the title — which is exactly how the
   KPI calculation edit dialog came out clipped (2026-09-11). The header, body
   and footer stay transparent and show the card behind them. */

.modal-content:not([class*="bg-"]) {
  background-color: var(--swal-surface) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-border) !important;
  box-shadow: var(--swal-shadow) !important;
}

.modal-header:not([class*="bg-"]),
.modal-footer:not([class*="bg-"]) {
  border-color: var(--swal-hairline) !important;
}

.modal-content:not([class*="bg-"]) .modal-title {
  color: var(--swal-text) !important;
}

/* Inside a modal only the dark themes need help: in light the app's own
   colours are already right, and forcing them would flatten the muted labels
   the pages use on purpose. */

html[data-theme="dark"] .modal-content label,
html[data-theme="dark"] .modal-content .form-label,
html[data-theme="dark"] .modal-content .col-form-label,
html[data-bs-theme="dark"] .modal-content label,
html[data-bs-theme="dark"] .modal-content .form-label,
html[data-bs-theme="dark"] .modal-content .col-form-label,
body.dark .modal-content label,
body.dark .modal-content .form-label,
body.dark .modal-content .col-form-label {
  color: var(--swal-text) !important;
}

html[data-theme="dark"] .modal-content .form-control,
html[data-theme="dark"] .modal-content .form-select,
html[data-theme="dark"] .modal-content textarea,
html[data-bs-theme="dark"] .modal-content .form-control,
html[data-bs-theme="dark"] .modal-content .form-select,
html[data-bs-theme="dark"] .modal-content textarea,
body.dark .modal-content .form-control,
body.dark .modal-content .form-select,
body.dark .modal-content textarea {
  background-color: var(--swal-field) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-field-border) !important;
}

html[data-theme="dark"] .modal-content option,
html[data-theme="dark"] .modal-content optgroup,
html[data-bs-theme="dark"] .modal-content option,
html[data-bs-theme="dark"] .modal-content optgroup,
body.dark .modal-content option,
body.dark .modal-content optgroup {
  background-color: var(--swal-field);
  color: var(--swal-text);
}

/* Bootstrap draws the select chevron as a dark SVG in the background; on a
   dark field it disappears, so swap in the light one. */
html[data-theme="dark"] .modal-content .form-select,
html[data-theme="dark"] .swal2-popup .form-select,
html[data-theme="dark"] .swal2-select,
html[data-bs-theme="dark"] .modal-content .form-select,
html[data-bs-theme="dark"] .swal2-popup .form-select,
html[data-bs-theme="dark"] .swal2-select,
body.dark .modal-content .form-select,
body.dark .swal2-popup .form-select,
body.dark .swal2-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e") !important;
}

/* Bootstrap's close glyph is a dark SVG; invert it on a dark card. */
.modal-content .btn-close {
  filter: var(--swal-close-filter);
}

/* ---------- the older `sweetalert` build (swal-modal), still on ~75 legacy
   pages: it injects its own white card from JavaScript ---------- */

.swal-modal {
  background-color: var(--swal-surface) !important;
  color: var(--swal-text) !important;
  box-shadow: var(--swal-shadow) !important;
}

.swal-title,
.swal-text,
.swal-content,
.swal-content label {
  color: var(--swal-text) !important;
}

.swal-footer {
  border-top-color: var(--swal-hairline) !important;
}

.swal-content__input,
.swal-content__textarea,
.swal-content input,
.swal-content select,
.swal-content textarea {
  background-color: var(--swal-field) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-field-border) !important;
}

.swal-content__input::placeholder,
.swal-content__textarea::placeholder {
  color: var(--swal-muted) !important;
  opacity: 1;
}

.swal-button--cancel {
  background-color: var(--swal-cancel-bg) !important;
  color: var(--swal-cancel-fg) !important;
}

.swal-button--cancel:not([disabled]):hover {
  background-color: var(--swal-field-border) !important;
}

/* ---------- a modal taller than the window ---------- */
/* A dialog with many fields is taller than a laptop window, and Bootstrap
   scrolls the whole dialog inside the fixed .modal — so the title scrolls out
   of the top and the dialog reads as cut off (the KPI calculation edit dialog,
   reported 2026-09-11).

   The header and footer are made sticky instead of capping the card and
   scrolling its body. The body must keep its overflow visible: this theme
   replaces every <select> with a widget whose menu is an absolutely positioned
   child of the field, so a scrolling .modal-body would clip every open dropdown
   — worse than the problem being fixed. Sticky costs nothing on a dialog that
   already fits.

   They need an opaque background of their own, since the body now scrolls
   underneath them; a header or footer that carries its own bg-* class is left
   alone. */

.modal-content:not([class*="bg-"]) > .modal-header:not([class*="bg-"]),
.modal-content:not([class*="bg-"]) > form > .modal-header:not([class*="bg-"]) {
  position: sticky;
  top: 0;
  z-index: 3;
  background-color: var(--swal-surface);
}

.modal-content:not([class*="bg-"]) > .modal-footer:not([class*="bg-"]),
.modal-content:not([class*="bg-"]) > form > .modal-footer:not([class*="bg-"]) {
  position: sticky;
  bottom: 0;
  z-index: 3;
  background-color: var(--swal-surface);
}


/* ---------- disabled and read-only fields ---------- */
/* A field the page locks (`disabled` or `readonly`) was unreadable on a dark
   page: Bootstrap paints `.form-control:disabled` with --bs-secondary-bg, and
   that variable is only switched to its dark value by `data-bs-theme="dark"` —
   which the WowDash apps never set, they switch on `data-theme`. So the field
   kept the light #e9ecef box while the theme forced the text white: white on
   white, the employee-code box on the employee edit form (2026-09-12).

   Painted here from the same per-theme tokens the popup uses, so every app on
   this box is covered by the one file every page already links. Light pages
   are untouched — each rule is scoped to one of the dark signals.

   `[readonly]` is included even though the WowDash sheet already handles
   `.form-control[readonly]`: plenty of legacy pages use a bare <input> with no
   Bootstrap class at all. Checkboxes, radios and the button-like inputs are
   left out — a background on those repaints the control itself. */

html[data-theme="dark"] :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
body[data-theme="dark"] :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
html[data-bs-theme="dark"] :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
body[data-bs-theme="dark"] :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
body.dark :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
body.dark-mode :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]),
html.dark :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea):is(:disabled, [readonly]) {
  background-color: var(--swal-field-off) !important;
  color: var(--swal-field-off-text) !important;
  -webkit-text-fill-color: var(--swal-field-off-text) !important;
  border-color: var(--swal-field-off-border) !important;
  opacity: 1 !important;
}

html[data-theme="dark"] :is(input, textarea):is(:disabled, [readonly])::placeholder,
body[data-theme="dark"] :is(input, textarea):is(:disabled, [readonly])::placeholder,
html[data-bs-theme="dark"] :is(input, textarea):is(:disabled, [readonly])::placeholder,
body[data-bs-theme="dark"] :is(input, textarea):is(:disabled, [readonly])::placeholder,
body.dark :is(input, textarea):is(:disabled, [readonly])::placeholder,
body.dark-mode :is(input, textarea):is(:disabled, [readonly])::placeholder,
html.dark :is(input, textarea):is(:disabled, [readonly])::placeholder {
  color: var(--swal-muted) !important;
  -webkit-text-fill-color: var(--swal-muted) !important;
}

/* The Lao select widget (the theme clones every select.form-select into one)
   had a dark skin for the open field but not for the disabled one, so a locked
   dropdown stayed a light-grey box on a dark card. Its light rule lives in an
   inline <style> further down each app's <head>, hence !important. */
html[data-theme="dark"] .employee-records-custom-select.is-disabled .employee-records-custom-select-trigger,
body[data-theme="dark"] .employee-records-custom-select.is-disabled .employee-records-custom-select-trigger,
html[data-bs-theme="dark"] .employee-records-custom-select.is-disabled .employee-records-custom-select-trigger,
body[data-bs-theme="dark"] .employee-records-custom-select.is-disabled .employee-records-custom-select-trigger {
  background: var(--swal-field-off) !important;
  color: var(--swal-field-off-text) !important;
  border-color: var(--swal-field-off-border) !important;
}

/* Same story next door: .input-group-text takes its background from Bootstrap's
   light --bs-tertiary-bg while the theme colours its text for a dark page. One
   that carries its own bg-* class is left alone. */
html[data-theme="dark"] .input-group-text:not([class*="bg-"]),
body[data-theme="dark"] .input-group-text:not([class*="bg-"]),
body.dark .input-group-text:not([class*="bg-"]),
body.dark-mode .input-group-text:not([class*="bg-"]),
html.dark .input-group-text:not([class*="bg-"]) {
  background-color: var(--swal-field) !important;
  color: var(--swal-text) !important;
  border-color: var(--swal-field-border) !important;
}

/* ---------- printed tables: the total row once, on the last page ---------- */
/* A browser repeats a table's <tfoot> at the foot of every printed page, the
   way it repeats <thead> — so a report whose grand total sits in a tfoot
   printed that total under page 1, page 2, … (the security-attendance sheet,
   2026-09-22). Laying the footer out as an ordinary row group prints it once,
   after the last row. Every tfoot on this box follows its tbody in the source,
   so the order on paper is unchanged. Screen rendering is untouched. */
@media print {
  tfoot {
    display: table-row-group;
  }
}

/* ---------- printing: always a light sheet ---------- */
/* Every theme script on the site drops its dark signal for the print pass
   (the print-light block at the end of app.js / theme-boot / script_darkmode.js,
   2026-09-22); this is the stylesheet half. The page itself is forced white
   and the body's pseudo-elements — the glass-theme scene (a fixed dark
   gradient that printed on every page of the e-doc appointment list) and the
   sidebar overlay — are dropped, so a dark screen never becomes a dark sheet. */
@media print {
  html,
  body {
    background: #ffffff !important;
    color: #000000 !important;
    color-scheme: light;
  }
  body::before,
  body::after {
    display: none !important;
  }
}
