/**
 * HIS Loader — the single loading spinner component for the application.
 *
 * Markup contract (also produced by HISLoader.markup() in his-loader.js):
 *
 *   <div class="his-loader" role="status" aria-live="polite" aria-label="Loading">
 *       <span class="his-spinner" aria-hidden="true"></span>
 *       <span class="his-loader__text">Loading...</span>
 *   </div>
 *
 * States: full page, section, button, table. See his-loader.js for the JS API.
 */

:root {
    --his-loader-size: 40px;
    --his-loader-stroke: 3px;
    --his-loader-duration: 750ms;
    --his-loader-gap: 12px;

    /* Fixed blue. Theme accent is peach (#ff7043); the loader stays blue. */
    --his-loader-color: #1d6fd8;
    --his-loader-track: rgba(29, 111, 216, 0.16);

    --his-loader-text-color: #6b7c93;
    --his-loader-text-size: 13px;

    --his-loader-overlay-bg: rgba(255, 255, 255, 0.72);
    --his-loader-overlay-bg-strong: rgba(255, 255, 255, 0.86);
    --his-loader-z: 200000;
}

/* ============================================================
   1. Core spinner
   ============================================================ */

.his-spinner {
    box-sizing: border-box;
    display: block;
    flex: 0 0 auto;
    width: var(--his-loader-size);
    height: var(--his-loader-size);
    border: var(--his-loader-stroke) solid var(--his-loader-track);
    border-top-color: var(--his-loader-color);
    border-radius: 50%;
    /* Composited rotation: no layout work per frame, no sub-pixel flicker. */
    animation: his-spinner-rotate var(--his-loader-duration) linear infinite;
    will-change: transform;
    backface-visibility: hidden;
    transform: translateZ(0);
}

@keyframes his-spinner-rotate {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

.his-loader {
    box-sizing: border-box;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--his-loader-gap);
    margin: 0;
    padding: 0;
    text-align: center;
    line-height: 1;
}

.his-loader__text {
    display: block;
    max-width: 220px;
    color: var(--his-loader-text-color);
    font-size: var(--his-loader-text-size);
    font-weight: 500;
    letter-spacing: 0.01em;
    line-height: 1.35;
}

/* Visually hidden accessible label, used when no visible text is rendered. */
.his-loader__sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Size variants — set the token, everything else follows. */
.his-loader--xs {
    --his-loader-size: 14px;
    --his-loader-stroke: 2px;
    --his-loader-gap: 6px;
    --his-loader-text-size: 11px;
}

.his-loader--sm {
    --his-loader-size: 20px;
    --his-loader-stroke: 2px;
    --his-loader-gap: 8px;
    --his-loader-text-size: 11px;
}

.his-loader--md {
    --his-loader-size: 40px;
    --his-loader-stroke: 3px;
}

.his-loader--lg {
    --his-loader-size: 44px;
    --his-loader-stroke: 4px;
    --his-loader-gap: 12px;
    --his-loader-text-size: 13px;
}

.his-loader--xl {
    --his-loader-size: 56px;
    --his-loader-stroke: 4px;
    --his-loader-gap: 14px;
    --his-loader-text-size: 13px;
}

/* Horizontal layout: spinner and text side by side (inline/status strips). */
.his-loader--inline {
    flex-direction: row;
    --his-loader-gap: 8px;
}

/* ============================================================
   2. Overlay — shared by full page, section and table states
   ============================================================ */

.his-loading-overlay {
    box-sizing: border-box;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
    background: var(--his-loader-overlay-bg);
    border-radius: inherit;
    z-index: var(--his-loader-z);
    /* The overlay itself swallows pointer events: clicks never reach the
       controls underneath while the loading state is active. */
    pointer-events: auto;
    animation: his-loader-fade-in 140ms ease-out both;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .his-loading-overlay {
        -webkit-backdrop-filter: blur(1px) saturate(105%);
        backdrop-filter: blur(1px) saturate(105%);
    }
}

@keyframes his-loader-fade-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

.his-loading-overlay--out {
    animation: his-loader-fade-out 120ms ease-in both;
}

@keyframes his-loader-fade-out {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

/* Any element that hosts a scoped overlay needs a positioning context. */
.his-loading-host {
    position: relative !important;
}

/* 2a. Full page */
.his-loading-overlay--page {
    position: fixed;
    background: var(--his-loader-overlay-bg-strong);
}

body.his-loading-locked {
    overflow: hidden !important;
}

/* 2b. Section / content */
.his-loading-overlay--section {
    --his-loader-size: 28px;
}

/* Sections that would otherwise collapse need room for the spinner. */
.his-loading-host--min {
    min-height: 120px;
}

/* ============================================================
   3. Button loading
   ============================================================ */

/* Width is frozen inline by JS (min-width) before the label is hidden, so the
   button never reflows or jumps when the spinner swaps in. */
.his-btn-loading {
    position: relative !important;
    pointer-events: none;
    cursor: progress;
    /* Keep the button reading as enabled-but-busy rather than greyed out. */
    opacity: 0.9;
}

.his-btn-loading > .his-btn-loading__label {
    visibility: hidden;
}

.his-btn-loading > .his-btn-spinner {
    box-sizing: border-box;
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1em;
    height: 1em;
    margin: 0;
    /* currentColor keeps the spinner legible on any button variant. */
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: his-btn-spinner-rotate var(--his-loader-duration) linear infinite;
    will-change: transform;
    backface-visibility: hidden;
}

@keyframes his-btn-spinner-rotate {
    from {
        transform: translate(-50%, -50%) rotate(0deg);
    }
    to {
        transform: translate(-50%, -50%) rotate(360deg);
    }
}

/* ============================================================
   4. Table / data loading
   ============================================================ */

.his-table-loading {
    position: relative !important;
    min-height: 140px;
}

.his-loading-overlay--table {
    --his-loader-size: 28px;
    align-items: flex-start;
    padding-top: 48px;
    background: var(--his-loader-overlay-bg-strong);
}

/* Short tables keep the spinner vertically centred instead of pinned high. */
.his-loading-overlay--table.his-loading-overlay--centered {
    align-items: center;
    padding-top: 12px;
}

/* Skeleton rows, for first-load table states where there is no old data to
   keep on screen behind an overlay. */
.his-skeleton-row {
    display: block;
    height: 12px;
    margin: 10px 0;
    border-radius: 4px;
    background: linear-gradient(
        90deg,
        rgba(17, 24, 39, 0.06) 25%,
        rgba(17, 24, 39, 0.12) 37%,
        rgba(17, 24, 39, 0.06) 63%
    );
    background-size: 400% 100%;
    animation: his-skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes his-skeleton-shimmer {
    from {
        background-position: 100% 50%;
    }
    to {
        background-position: 0 50%;
    }
}

/* ============================================================
   5. jQuery LoadingOverlay bridge
   ------------------------------------------------------------
   his-loader.js injects .his-loader as the plugin's `custom` element. The
   plugin force-sizes .loadingoverlay_element on the first resize pass
   regardless of customAutoResize, so the sizing is reclaimed here.
   ============================================================ */

.loadingoverlay {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
}

/* Plugin default image/text sit beside the HIS spinner. Keep only the HIS one. */
.loadingoverlay > .loadingoverlay_element:not(:has(.his-loader)) {
    display: none !important;
}

.loadingoverlay > .loadingoverlay_element:has(.his-loader) ~ .loadingoverlay_element {
    display: none !important;
}

/* Extra full-page overlays stay hidden. A div overlay is not full-page. */
body > .loadingoverlay.his-overlay-page ~ .loadingoverlay.his-overlay-page,
body > .his-loading-overlay--page ~ .his-loading-overlay--page,
.his-loader-suppressed {
    display: none !important;
}

/* $.LoadingOverlay / $('body') only. Plugin appends every overlay to body;
   stretching all of them covers the page instead of the target div. */
body > .loadingoverlay.his-overlay-page {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
}

/* $(div).LoadingOverlay: plugin sets top/left/width/height to that div.
   Clip so the spinner and "Loading..." cannot paint onto the rest of the page. */
body > .loadingoverlay.his-overlay-scoped {
    overflow: hidden !important;
    margin: 0 !important;
    max-width: none;
}

/* Ophthal screen modals (z 10050): his-modals.css pins body overlays to 10030, which hides
   loaders for divs inside these dialogs (refraction columns, investigation, procedure). */
body.modal-open:has(#getEyeRefractionNewVersionModel.show) > .loadingoverlay.his-overlay-scoped,
body.modal-open:has(#getEyeRefractionNewVersionModel.in) > .loadingoverlay.his-overlay-scoped,
body.modal-open:has(#patient_investigation_min.show) > .loadingoverlay.his-overlay-scoped,
body.modal-open:has(#patient_investigation_min.in) > .loadingoverlay.his-overlay-scoped,
body.modal-open:has(#patient_procedure_min.show) > .loadingoverlay.his-overlay-scoped,
body.modal-open:has(#patient_procedure_min.in) > .loadingoverlay.his-overlay-scoped {
    z-index: 10060 !important;
}

.loadingoverlay .loadingoverlay_element {
    position: static !important;
    top: auto !important;
    left: auto !important;
    margin: 0 !important;
    transform: none !important;
    width: auto !important;
    height: auto !important;
    overflow: visible !important;
    font-size: inherit !important;
}

.loadingoverlay .his-loader {
    visibility: visible !important;
    opacity: 1 !important;
}

/* Legacy spinners that older call sites still pass in explicitly. */
.loadingoverlay .loadingoverlay_fa,
.loadingoverlay .his-loader-card,
.loadingoverlay .custom-dotted-loader,
.loadingoverlay .dotted-loader {
    display: none !important;
}

.emr-fetch-blur-host {
    position: relative !important;
}

.investigation_tree_area,
.procedure_tree_area,
.investigation_history_div,
.procedure_history_div,
.prescription_history_div,
.patient_history_container,
.todays_visit_details_div,
[id$="_history_section"] {
    position: relative;
}

.investigation_tree_area > .loadingoverlay,
.procedure_tree_area > .loadingoverlay,
.investigation_history_div > .loadingoverlay,
.procedure_history_div > .loadingoverlay,
.prescription_history_div > .loadingoverlay,
.patient_history_container > .loadingoverlay,
.todays_visit_details_div > .loadingoverlay,
[id$="_history_section"] > .loadingoverlay {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
}

.emr-fetch-blur-host > .loadingoverlay {
    background: var(--his-loader-overlay-bg) !important;
    z-index: var(--his-loader-z) !important;
    border-radius: inherit;
}

/* ============================================================
   6. Responsive
   ============================================================ */

@media (max-width: 767.98px) {
    /* The size classes set the token on the element, so the smaller phone
       sizes have to be applied to those classes rather than to :root. */
    .his-loader--md {
        --his-loader-size: 34px;
    }

    .his-loader--lg {
        --his-loader-size: 38px;
    }

    .his-loader--xl {
        --his-loader-size: 46px;
    }

    .his-loader__text {
        max-width: 180px;
    }

    .his-loading-overlay--table {
        padding-top: 32px;
    }
}

/* ============================================================
   7. Reduced motion
   ------------------------------------------------------------
   Rotation is dropped in favour of a slow opacity pulse: still a clear
   "work in progress" signal, without vestibular-triggering motion.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    .his-spinner {
        border-color: var(--his-loader-color);
        animation: his-spinner-pulse 1.4s ease-in-out infinite;
    }

    .his-btn-loading > .his-btn-spinner {
        border-color: currentColor;
        transform: translate(-50%, -50%);
        animation: his-spinner-pulse 1.4s ease-in-out infinite;
    }

    .his-loading-overlay,
    .his-loading-overlay--out {
        animation: none;
    }

    .his-skeleton-row {
        animation: none;
    }
}

@keyframes his-spinner-pulse {
    0%,
    100% {
        opacity: 0.25;
    }
    50% {
        opacity: 1;
    }
}
