/**
 * Al-Bashayer — Document Management Styles
 *
 * Upload zones, progress bars, file list, status badges,
 * and staff review panel.
 *
 * @see PRD/06-Document-Management-System.md §6.6, §6.7
 */

/* ============================================
   REQUIRED-DOCUMENTS SECTION
   ============================================ */

.ab-documents-section {
    margin-block: var(--wp--preset--spacing--60, 2rem) 0;
}

.ab-documents-heading {
    font-size: var(--wp--preset--font-size--lg, 1.125rem);
    font-weight: 700;
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    margin-block-end: var(--wp--preset--spacing--40, 1rem);
    padding-block-end: 0.5rem;
    border-block-end: 2px solid var(--wp--preset--color--primary, #1B4D3E);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.ab-documents-heading svg {
    flex-shrink: 0;
}

/* ============================================
   DOCUMENT UPLOAD ITEM
   ============================================ */

.ab-doc-item {
    background: var(--wp--preset--color--surface, #fff);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: var(--ab-radius-lg, 0.75rem);
    padding: 1.25rem;
    margin-block-end: 1rem;
    box-shadow: var(--ab-shadow-sm);
    transition: box-shadow var(--ab-transition-normal, 250ms ease);
}

.ab-doc-item:last-child {
    margin-block-end: 0;
}

.ab-doc-item-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-block-end: 0.875rem;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.ab-doc-item-label {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.ab-doc-required-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.625rem;
    border-radius: var(--ab-radius-full, 9999px);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    background: rgba(220, 53, 69, 0.1);
    color: #b02a37;
    border: 1px solid rgba(220, 53, 69, 0.25);
}

.ab-doc-optional-badge {
    background: rgba(108, 117, 125, 0.1);
    color: #495057;
    border-color: rgba(108, 117, 125, 0.25);
}

/* ============================================
   DROP ZONE
   ============================================ */

.ab-drop-zone {
    position: relative;
    border: 2px dashed rgba(27, 77, 62, 0.3);
    border-radius: var(--ab-radius-md, 0.5rem);
    padding: 1.5rem 1rem;
    text-align: center;
    cursor: pointer;
    background: rgba(27, 77, 62, 0.025);
    transition:
        border-color var(--ab-transition-normal, 250ms ease),
        background var(--ab-transition-normal, 250ms ease),
        transform var(--ab-transition-fast, 150ms ease);
    outline: none;
}

.ab-drop-zone:hover,
.ab-drop-zone:focus-visible {
    border-color: var(--wp--preset--color--primary, #1B4D3E);
    background: rgba(27, 77, 62, 0.06);
}

.ab-drop-zone.is-dragging {
    border-color: var(--wp--preset--color--accent, #C5A54E);
    background: rgba(197, 165, 78, 0.08);
    transform: scale(1.01);
}

.ab-drop-zone.is-uploading {
    pointer-events: none;
    opacity: 0.7;
}

.ab-drop-zone-icon {
    display: block;
    margin: 0 auto 0.625rem;
    color: var(--wp--preset--color--primary, #1B4D3E);
    opacity: 0.6;
}

.ab-drop-zone-text {
    font-size: 0.875rem;
    color: var(--wp--preset--color--primary, #1B4D3E);
    font-weight: 500;
    margin: 0 0 0.25rem;
}

.ab-drop-zone-hint {
    font-size: 0.75rem;
    color: #6c757d;
    margin: 0;
}

.ab-drop-zone input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* ============================================
   UPLOAD PROGRESS BAR
   ============================================ */

.ab-upload-progress {
    display: none;
    margin-block-start: 0.75rem;
}

.ab-upload-progress.is-visible {
    display: block;
}

.ab-progress-bar-track {
    height: 6px;
    border-radius: var(--ab-radius-full, 9999px);
    background: rgba(27, 77, 62, 0.12);
    overflow: hidden;
    margin-block-end: 0.375rem;
}

.ab-progress-bar-fill {
    height: 100%;
    border-radius: var(--ab-radius-full, 9999px);
    background: linear-gradient(90deg,
        var(--wp--preset--color--primary, #1B4D3E),
        var(--wp--preset--color--primary-light, #2A7A5F));
    transition: width 0.2s ease;
    width: 0%;
}

.ab-progress-label {
    font-size: 0.75rem;
    color: #6c757d;
    text-align: center;
}

/* ============================================
   UPLOADED FILES LIST
   ============================================ */

.ab-file-list {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.ab-file-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.625rem 0.875rem;
    background: var(--wp--preset--color--surface-alt, #F8F9FA);
    border-radius: var(--ab-radius-md, 0.5rem);
    border: 1px solid rgba(0, 0, 0, 0.06);
    font-size: 0.8125rem;
    transition: background var(--ab-transition-fast, 150ms ease);
}

.ab-file-item:hover {
    background: rgba(27, 77, 62, 0.04);
}

.ab-file-icon {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: var(--ab-radius-sm, 0.375rem);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6875rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.01em;
}

.ab-file-icon--pdf  { background: rgba(220, 53, 69, 0.1);  color: #c82333; }
.ab-file-icon--jpg,
.ab-file-icon--jpeg { background: rgba(23, 162, 184, 0.1);  color: #117a8b; }
.ab-file-icon--png  { background: rgba(102, 16, 242, 0.1);  color: #5a0fd6; }

.ab-file-name {
    flex: 1;
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    font-weight: 500;
}

.ab-file-size {
    flex-shrink: 0;
    color: #6c757d;
    font-size: 0.75rem;
}

.ab-file-status {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: var(--ab-radius-full, 9999px);
    font-size: 0.6875rem;
    font-weight: 600;
}

.ab-file-status--uploaded      { background: rgba(23, 162, 184, 0.1);  color: #117a8b; }
.ab-file-status--pending_review { background: rgba(255, 193, 7, 0.15);   color: #856404; }
.ab-file-status--approved       { background: rgba(40, 167, 69, 0.12);   color: #155724; }
.ab-file-status--rejected       { background: rgba(220, 53, 69, 0.1);    color: #721c24; }
.ab-file-status--archived       { background: rgba(108, 117, 125, 0.1);  color: #495057; }

.ab-file-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}

.ab-file-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--ab-radius-sm, 0.375rem);
    border: 1px solid transparent;
    background: transparent;
    cursor: pointer;
    color: #6c757d;
    transition:
        background var(--ab-transition-fast),
        color var(--ab-transition-fast);
    padding: 0;
}

.ab-file-btn:hover {
    background: rgba(0, 0, 0, 0.06);
    color: var(--wp--preset--color--primary, #1B4D3E);
}

.ab-file-btn--remove:hover {
    background: rgba(220, 53, 69, 0.1);
    color: #c82333;
}

.ab-file-btn--submit:hover {
    background: rgba(40, 167, 69, 0.1);
    color: #155724;
}

/* Rejection reason callout */
.ab-rejection-callout {
    margin-block-start: 0.375rem;
    padding: 0.5rem 0.75rem;
    background: rgba(220, 53, 69, 0.06);
    border-inline-start: 3px solid #dc3545;
    border-radius: 0 var(--ab-radius-sm) var(--ab-radius-sm) 0;
    font-size: 0.75rem;
    color: #721c24;
}

/* ============================================
   VALIDATION ERROR INLINE
   ============================================ */

.ab-doc-error {
    display: none;
    margin-block-start: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: rgba(220, 53, 69, 0.08);
    border: 1px solid rgba(220, 53, 69, 0.2);
    border-radius: var(--ab-radius-sm, 0.375rem);
    font-size: 0.8125rem;
    color: #b02a37;
}

.ab-doc-error.is-visible {
    display: block;
}

/* ============================================
   STAFF REVIEW PANEL
   ============================================ */

.ab-review-panel {
    background: var(--wp--preset--color--surface, #fff);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: var(--ab-radius-xl, 1rem);
    overflow: hidden;
    box-shadow: var(--ab-shadow-md);
}

.ab-review-panel-header {
    padding: 1.25rem 1.5rem;
    background: linear-gradient(135deg,
        var(--wp--preset--color--primary-dark, #0F2E25) 0%,
        var(--wp--preset--color--primary, #1B4D3E) 100%);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.ab-review-panel-title {
    font-size: 1rem;
    font-weight: 700;
    margin: 0;
}

.ab-review-panel-meta {
    font-size: 0.8125rem;
    opacity: 0.8;
}

.ab-review-body {
    padding: 1.5rem;
}

/* Document preview */
.ab-preview-container {
    background: var(--wp--preset--color--surface-alt, #F8F9FA);
    border-radius: var(--ab-radius-lg, 0.75rem);
    overflow: hidden;
    aspect-ratio: 4 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(0, 0, 0, 0.08);
    margin-block-end: 1.25rem;
    position: relative;
}

.ab-preview-container iframe,
.ab-preview-container img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border: none;
}

.ab-preview-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.625rem;
    color: #6c757d;
    font-size: 0.875rem;
    text-align: center;
}

.ab-preview-placeholder svg {
    opacity: 0.4;
}

/* Review actions */
.ab-review-actions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-block-end: 1.25rem;
}

.ab-btn-approve {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1.25rem;
    background: linear-gradient(135deg, #28a745, #218838);
    color: #fff;
    font-size: 0.9375rem;
    font-weight: 600;
    border: none;
    border-radius: var(--ab-radius-md, 0.5rem);
    cursor: pointer;
    transition:
        opacity var(--ab-transition-fast),
        transform var(--ab-transition-fast),
        box-shadow var(--ab-transition-fast);
    box-shadow: 0 2px 8px rgba(40, 167, 69, 0.25);
}

.ab-btn-reject {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1.25rem;
    background: linear-gradient(135deg, #dc3545, #c82333);
    color: #fff;
    font-size: 0.9375rem;
    font-weight: 600;
    border: none;
    border-radius: var(--ab-radius-md, 0.5rem);
    cursor: pointer;
    transition:
        opacity var(--ab-transition-fast),
        transform var(--ab-transition-fast),
        box-shadow var(--ab-transition-fast);
    box-shadow: 0 2px 8px rgba(220, 53, 69, 0.25);
}

.ab-btn-approve:hover,
.ab-btn-reject:hover {
    opacity: 0.9;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.ab-btn-approve:active,
.ab-btn-reject:active {
    transform: translateY(0);
}

.ab-btn-approve:disabled,
.ab-btn-reject:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}

/* Rejection reason field */
.ab-rejection-form {
    display: none;
    margin-block-start: 0;
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.3s ease, margin 0.3s ease;
}

.ab-rejection-form.is-open {
    display: block;
    max-height: 200px;
    margin-block-start: 1rem;
}

.ab-rejection-form label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    margin-block-end: 0.5rem;
}

.ab-rejection-textarea {
    width: 100%;
    min-height: 80px;
    padding: 0.625rem 0.875rem;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: var(--ab-radius-md, 0.5rem);
    font-size: 0.875rem;
    font-family: inherit;
    resize: vertical;
    transition: border-color var(--ab-transition-fast);
    background: var(--wp--preset--color--surface, #fff);
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    box-sizing: border-box;
}

.ab-rejection-textarea:focus {
    outline: none;
    border-color: var(--wp--preset--color--primary, #1B4D3E);
    box-shadow: 0 0 0 3px rgba(27, 77, 62, 0.12);
}

.ab-rejection-confirm-btn {
    margin-block-start: 0.625rem;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 1rem;
    background: #dc3545;
    color: #fff;
    font-size: 0.875rem;
    font-weight: 600;
    border: none;
    border-radius: var(--ab-radius-md, 0.5rem);
    cursor: pointer;
    transition: opacity var(--ab-transition-fast);
}

.ab-rejection-confirm-btn:hover { opacity: 0.88; }

/* Version history */
.ab-version-history {
    border-block-start: 1px solid rgba(0, 0, 0, 0.08);
    padding-block-start: 1.25rem;
    margin-block-start: 1.25rem;
}

.ab-version-heading {
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--wp--preset--color--primary-dark, #0F2E25);
    margin: 0 0 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.ab-version-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.ab-version-item {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.625rem 0.875rem;
    border-radius: var(--ab-radius-md, 0.5rem);
    background: var(--wp--preset--color--surface-alt, #F8F9FA);
    font-size: 0.8125rem;
}

.ab-version-item--current {
    background: rgba(27, 77, 62, 0.06);
    border: 1px solid rgba(27, 77, 62, 0.15);
}

.ab-version-badge {
    flex-shrink: 0;
    font-weight: 700;
    color: var(--wp--preset--color--primary, #1B4D3E);
    font-size: 0.75rem;
    padding: 0.1rem 0.4rem;
    background: rgba(27, 77, 62, 0.1);
    border-radius: var(--ab-radius-sm, 0.375rem);
}

.ab-version-info {
    flex: 1;
    min-inline-size: 0;
}

.ab-version-date {
    color: #6c757d;
    font-size: 0.75rem;
}

.ab-version-reason {
    margin-block-start: 0.25rem;
    font-size: 0.75rem;
    color: #b02a37;
}

/* ============================================
   TOAST NOTIFICATIONS
   ============================================ */

.ab-doc-toast {
    position: fixed;
    inset-block-end: 1.5rem;
    inset-inline-end: 1.5rem;
    z-index: var(--ab-z-toast, 1090);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    pointer-events: none;
}

.ab-toast {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.75rem 1rem;
    background: var(--wp--preset--color--primary-dark, #0F2E25);
    color: #fff;
    border-radius: var(--ab-radius-lg, 0.75rem);
    font-size: 0.875rem;
    font-weight: 500;
    box-shadow: var(--ab-shadow-lg);
    pointer-events: auto;
    animation: ab-toast-in 0.3s ease forwards;
    max-inline-size: 340px;
}

.ab-toast--success { background: #155724; }
.ab-toast--error   { background: #721c24; }
.ab-toast--warning { background: #856404; color: #fff; }

@keyframes ab-toast-in {
    from { opacity: 0; transform: translateY(12px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes ab-toast-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(8px); }
}

.ab-toast.is-leaving {
    animation: ab-toast-out 0.25s ease forwards;
}

/* ============================================
   LOADING SPINNER (reusable)
   ============================================ */

.ab-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-inline-end-color: transparent;
    border-radius: 50%;
    animation: ab-spin 0.65s linear infinite;
    flex-shrink: 0;
}

@keyframes ab-spin {
    to { transform: rotate(360deg); }
}

/* ============================================
   RESPONSIVE
   ============================================ */

@media (max-width: 600px) {
    .ab-review-actions {
        flex-direction: column;
    }

    .ab-btn-approve,
    .ab-btn-reject {
        width: 100%;
        justify-content: center;
    }

    .ab-doc-toast {
        inset-inline-end: 0.75rem;
        inset-inline-start: 0.75rem;
    }
}

/* ============================================
   RTL OVERRIDES
   ============================================ */

[dir="rtl"] .ab-rejection-callout {
    border-inline-start: none;
    border-inline-end: 3px solid #dc3545;
}


/* ============================================
   DOCUMENT PREVIEW MODAL
   Read an attachment — image or PDF — without leaving the page.
   Shared by the staff review screen and the client documents list.
   ============================================ */

.ab-preview {
    position: fixed;
    inset: 0;
    /* Above the fixed site header (1000) and the dashboard drawer (1300), or
       the chrome paints over the document being read. */
    z-index: 1400;
    display: grid;
    place-items: center;
    padding: clamp(0.5rem, 3vw, 2.5rem);
}

.ab-preview[hidden] {
    display: none;
}

.ab-preview__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 10, 9, .78);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

/* Rows: title bar, then the document taking everything that is left.
   A grid rather than flex because `1fr` here means "the rest of the panel",
   which is what stops a tall image from pushing the bar off the top. */
.ab-preview__panel {
    position: relative;
    display: grid;
    grid-template-rows: auto 1fr;
    inline-size: min(1100px, 100%);
    block-size: min(92vh, 100%);
    max-block-size: 92vh;
    background: var(--dr-bg-2, #fff);
    color: var(--dr-text, inherit);
    border: 1px solid var(--dr-glass-border, rgba(0, 0, 0, .12));
    border-radius: clamp(8px, 2vw, 16px);
    box-shadow: 0 30px 80px rgba(0, 0, 0, .55);
    overflow: hidden;
}

.ab-preview__bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .7rem .9rem;
    border-block-end: 1px solid var(--dr-glass-border, rgba(0, 0, 0, .12));
    background: var(--dr-bg-3, rgba(0, 0, 0, .03));
}

.ab-preview__title {
    flex: 1;
    min-inline-size: 0;
    font-size: .88rem;
    font-weight: 600;
    /* Filenames are long and arrive in both scripts. Keep them to one line so
       the bar cannot grow and steal height from the document. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    direction: ltr;
    text-align: start;
}

.ab-preview__btn {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    flex-shrink: 0;
    padding: .35rem .7rem;
    font: inherit;
    font-size: .8rem;
    line-height: 1;
    color: inherit;
    text-decoration: none;
    background: transparent;
    border: 1px solid var(--dr-glass-border, rgba(0, 0, 0, .18));
    border-radius: 999px;
    cursor: pointer;
    transition: background .18s, border-color .18s, color .18s;
}

.ab-preview__btn:hover {
    background: rgba(200, 168, 75, .16);
    border-color: rgba(200, 168, 75, .55);
}

.ab-preview__close {
    flex-shrink: 0;
    inline-size: 32px;
    block-size: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    line-height: 1;
    color: inherit;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 50%;
    cursor: pointer;
    transition: background .18s, color .18s;
}

.ab-preview__close:hover {
    background: rgba(190, 60, 60, .16);
    color: #C0392B;
}

/* min-block-size:0 is what actually lets this scroll: a grid item defaults to
   min-content, so without it the row refuses to shrink and the image is cut
   off at the bottom of the panel instead of the panel scrolling. */
.ab-preview__body {
    min-block-size: 0;
    min-inline-size: 0;
    overflow: auto;
    background:
        repeating-conic-gradient(rgba(128, 128, 128, .10) 0% 25%, transparent 0% 50%)
        50% / 22px 22px;
    display: grid;
    place-items: center;
}

/* Fit mode (default): the whole page is visible, never cropped. */
.ab-preview__img {
    display: block;
    max-inline-size: 100%;
    max-block-size: 100%;
    inline-size: auto;
    block-size: auto;
    object-fit: contain;
    margin: auto;
    cursor: zoom-in;
}

/* Actual size: the body scrolls instead of the image shrinking — the only way
   to read the small print on a scanned ID. */
.ab-preview.is-zoomed .ab-preview__img {
    max-inline-size: none;
    max-block-size: none;
    inline-size: auto;
    block-size: auto;
    cursor: zoom-out;
}

.ab-preview__frame {
    inline-size: 100%;
    block-size: 100%;
    min-block-size: 0;
    border: 0;
    background: #fff;
}

/* PDFs get the whole panel — a viewer needs the height more than the padding. */
.ab-preview__body--pdf {
    display: block;
    overflow: hidden;
    background: #fff;
}

@media (max-width: 600px) {
    .ab-preview {
        padding: 0;
    }

    .ab-preview__panel {
        inline-size: 100%;
        block-size: 100%;
        max-block-size: none;
        border: 0;
        border-radius: 0;
    }

    /* Zoom is a pointer affordance; on a touch screen pinch does the job and a
       tap that silently changes scale reads as a bug. */
    .ab-preview__zoom {
        display: none;
    }
}

/* The WordPress admin bar is fixed at z-index 99999 — higher than anything a
   theme can reasonably claim — so it paints over the top of this overlay for
   signed-in staff. Reserve its height rather than fight it. The bar is 46px on
   small screens and 32px from 783px up, the same breakpoint core uses. */
body.admin-bar .ab-preview {
    padding-block-start: calc(46px + clamp(0.5rem, 3vw, 2.5rem));
}

@media (min-width: 783px) {
    body.admin-bar .ab-preview {
        padding-block-start: calc(32px + clamp(0.5rem, 3vw, 2.5rem));
    }
}

/* Loading state — the file is fetched over the network and, for a scan, that is
   long enough for an empty panel to read as a broken preview. */
.ab-preview__loader {
    position: absolute;
    inset-inline-start: 50%;
    inset-block-start: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .75rem;
    font-size: .85rem;
    opacity: .85;
    pointer-events: none;
}

.ab-preview__loader[hidden] {
    display: none;
}

/* The loader is absolutely positioned against the body, so the body has to be
   its containing block. */
.ab-preview__body {
    position: relative;
}

.ab-preview__spinner {
    inline-size: 34px;
    block-size: 34px;
    border: 3px solid rgba(128, 128, 128, .28);
    border-block-start-color: var(--dr-gold, #B8912A);
    border-radius: 50%;
    animation: ab-preview-spin .8s linear infinite;
}

@keyframes ab-preview-spin {
    to { transform: rotate(360deg); }
}

/* Respect a reduced-motion preference: pulse instead of spin. */
@media (prefers-reduced-motion: reduce) {
    .ab-preview__spinner {
        animation: ab-preview-pulse 1.4s ease-in-out infinite;
    }
    @keyframes ab-preview-pulse {
        50% { opacity: .35; }
    }
}

/* Hide the half-painted document while it arrives, so the spinner is not
   competing with a partially decoded image. */
.ab-preview__body.is-loading .ab-preview__img,
.ab-preview__body.is-loading .ab-preview__frame {
    visibility: hidden;
}

.ab-preview__error {
    margin: auto;
    padding: 2rem 1.5rem;
    text-align: center;
    font-size: .9rem;
    opacity: .8;
}
