/* ============================================================================
   AI Document Review — real-time review UI
   Implements the Claude Design project "AI Document Review Experience"
   (65694281-db21-454f-990c-3cc93888991e): the compact AI Result table cell and
   the single-document review modal.

   WHY THIS FILE EXISTS SEPARATELY FROM requiredDocsStateSystem.css
   ----------------------------------------------------------------------------
   That file predates the design-system token layer and redefines shipped token
   NAMES on :root with raw hex (--lw-border, --lw-primary, --lw-radius, ...).
   Nothing here redefines a token. Every value below resolves against
   public/assetsNew/css/lw-tokens.css, which BaseHTML loads unconditionally on
   every page, so light/dark both work with no extra declarations and the
   pre-commit no-hex guard has nothing to complain about.

   The verdict vocabulary is fixed and shared with the backend:
     pass | fail | human_review        -> passed / failed / needs-review
     matched | mismatched | not_validatable -> matched / differs / not on file
   "Needs Review" is a first-class verdict, NOT an error. "Not on file" means the
   loan file has no value to compare against — it is neutral, never a failure.
   ========================================================================== */

/* ----------------------------------------------------------------------------
   TOKEN NOTE — why this file uses warning-* for the "Needs Review" verdict
   ----------------------------------------------------------------------------
   The design mocked a --lw-status-review-* family. It does not exist: the token
   layer ships pass / fail / pending / disabled, and lw-tokens.css is GENERATED
   (.githooks/pre-commit runs build-lw-tokens.sh --check when it is staged), so a
   new family has to be added upstream in .claude/skills/lw-design/, not here.

   --lw-warning-* IS the deep orange the design asked for, and unlike a locally
   declared family it already carries correct light AND dark values (a dark ink
   on a pale tint in light mode; an amber ink on a deep brown tint in dark).
   Using it costs nothing and themes correctly today. If a real review family is
   ever added upstream, this is a find-and-replace.

   Document "paper" uses --lw-white deliberately, NOT --lw-surface: a scanned
   page stays white in dark mode, otherwise the preview stops looking like the
   document it is. --lw-white is a constant and does not theme-invert, which is
   exactly the property required here.
   -------------------------------------------------------------------------- */

/* ---------------------------------------------------------------- animation */

@keyframes lwAiScan { from { top: 4%; } to { top: 92%; } }
@keyframes lwAiSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* One reduced-motion block for the whole feature. The scan line is decorative
   and disappears entirely; spinners fall back to a static glyph rather than
   vanishing, because they are the only cue that work is still in progress. */
@media (prefers-reduced-motion: reduce) {
    .lw-air-scan { display: none; }
    .lw-air-spin { animation: none; }
}

/* ============================================================================
   SURFACE 1 — compact AI Result table cell
   Lives inside a ~180px x 40px <td>. Everything here must survive that box, so
   every text run either ellipsises or is allowed to be clipped deliberately.
   ========================================================================== */

.lw-air-cell {
    width: 100%;
    max-width: 180px;
    min-height: 40px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    font-family: var(--lw-font-sans);
    font-size: var(--lw-fs-sm);
    line-height: 1;
    color: var(--lw-text);
    overflow: hidden;
}

.lw-air-cell__line {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    white-space: nowrap;
}

.lw-air-cell__truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* idle ------------------------------------------------------------------- */

.lw-air-cell__idle { color: var(--lw-text-muted); }

.lw-air-cell__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--lw-status-disabled-fill);
    flex: none;
}

.lw-air-cell__sub {
    font-size: var(--lw-fs-xs);
    color: var(--lw-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.lw-air-cell__sub--indent { padding-left: calc(8px + 0.4rem); }

/* processing -------------------------------------------------------------- */

.lw-air-cell__stage {
    color: var(--lw-primary-ink);
    font-weight: 500;
}

.lw-air-cell__stage i {
    font-size: 11px;
    flex: none;
}

.lw-air-cell__counter {
    margin-left: auto;
    color: var(--lw-text-muted);
    font-weight: 400;
    font-size: var(--lw-fs-xs);
    flex: none;
    font-variant-numeric: tabular-nums;
}

/* The stage label as a call to action.
   The cell is ~180px wide, so the affordance has to be carried by the text
   itself: a dotted underline and an eye, in the same ink the stage row already
   uses. It is a <button> so it is reachable by keyboard and announced as a
   control; every browser default it brings is reset here. */
.lw-air-watch {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.lw-air-watch__text {
    overflow: hidden;
    text-overflow: ellipsis;
    border-bottom: 1px dotted currentColor;
}

.lw-air-watch__eye { opacity: 0.65; }

.lw-air-watch:hover .lw-air-watch__text,
.lw-air-watch:focus-visible .lw-air-watch__text { border-bottom-style: solid; }

.lw-air-watch:hover .lw-air-watch__eye,
.lw-air-watch:focus-visible .lw-air-watch__eye { opacity: 1; }

.lw-air-watch:focus { outline: none; }
.lw-air-watch:focus-visible { outline: 2px solid var(--lw-primary); outline-offset: 2px; }

/* Hairline between a settled verdict and a run still in flight underneath it.
   Margin rather than a spacer row so the cell keeps its 40px rhythm when nothing
   is running, which is the ordinary case. */
.lw-air-cell__also {
    margin-top: 0.3rem;
    padding-top: 0.3rem;
    border-top: 1px solid var(--lw-border);
}

/* "Run AI review" — files are in, the doc type is configured, and nothing was
   dispatched because this type does not review on upload. Warning ink, not the
   pending grey: grey says "wait" and waiting achieves nothing here. */
.lw-air-cell__manual {
    color: var(--lw-warning-ink);
    font-weight: 500;
}

.lw-air-cell__manual i {
    font-size: 11px;
    flex: none;
}

.lw-air-progress {
    height: 3px;
    border-radius: 2px;
    background: var(--lw-border-light);
    overflow: hidden;
}

.lw-air-progress__bar {
    height: 100%;
    border-radius: 2px;
    background: var(--lw-primary);
    transition: width 0.3s ease-in-out;
    width: 0;
}

/* verdict pills ----------------------------------------------------------- */

.lw-air-verdict {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 500;
    font-size: var(--lw-fs-xs);
    line-height: 1;
    padding: 0.3rem 0.5rem;
    border-radius: var(--lw-radius-pill);
    white-space: nowrap;
}

.lw-air-verdict i { font-size: 0.95em; }

.lw-air-verdict--pass   { color: var(--lw-status-pass-ink);     background: var(--lw-status-pass-tint); }
.lw-air-verdict--fail   { color: var(--lw-status-fail-ink);     background: var(--lw-status-fail-tint); }
.lw-air-verdict--review { color: var(--lw-warning-ink);   background: var(--lw-warning-tint); }

/* cross-validation note --------------------------------------------------- */

.lw-air-xval {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--lw-fs-xs);
    color: var(--lw-text-muted);
    white-space: nowrap;
    padding-left: 2px;
    min-width: 0;
}

.lw-air-xval i { font-size: 9px; flex: none; }

/* inline re-upload -------------------------------------------------------- */

.lw-air-reupload {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    border: none;
    background: transparent;
    padding: 2px 0;
    margin: 0;
    cursor: pointer;
    font-family: inherit;
    font-size: var(--lw-fs-xs);
    font-weight: 500;
    color: var(--lw-link);
    white-space: nowrap;
    text-decoration: underline;
    text-decoration-color: transparent;
    text-underline-offset: 2px;
    transition: text-decoration-color 0.15s ease, color 0.15s ease;
}

.lw-air-reupload:hover,
.lw-air-reupload:focus-visible {
    text-decoration-color: var(--lw-link);
    color: var(--lw-link-hover);
}

.lw-air-reupload i { font-size: 10px; }

/* ============================================================================
   SURFACE 2 — single-document review modal
   Rendered into the existing #exampleModal1 body, so it must not assume it owns
   the page. Container queries drive the responsive split rather than viewport
   media queries: the modal is also embedded at other widths.
   ========================================================================== */

.lw-air-modal {
    font-family: var(--lw-font-sans);
    font-size: var(--lw-fs-base);
    line-height: var(--lw-lh-base);
    color: var(--lw-text);
    background: var(--lw-surface);
    border-radius: var(--lw-radius-lg);
    overflow: hidden;
    width: 100%;
    box-sizing: border-box;
    container-type: inline-size;
}

.lw-air-modal__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 50px;
    padding: 12px 20px;
    border-bottom: 1px solid var(--lw-border-light);
}

.lw-air-modal__title {
    font-size: var(--lw-fs-xl);
    font-weight: 500;
    line-height: 1.2;
    color: var(--lw-text-primary);
}

.lw-air-modal__fileline {
    font-size: var(--lw-fs-sm);
    color: var(--lw-text-muted);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.lw-air-modal__body {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    padding: 20px;
}

/* left column — document preview ----------------------------------------- */

.lw-air-doc {
    flex: 1 1 170px;
    min-width: 150px;
    max-width: 220px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lw-air-doc__frame {
    background: var(--lw-surface-sunken);
    border: 1px solid var(--lw-border-strong);
    border-radius: var(--lw-radius);
    padding: 12px;
}

/* The paper is deliberately NOT theme-inverted: a scanned page is white in dark
   mode too, otherwise the preview stops looking like the document it is. */
.lw-air-doc__page {
    position: relative;
    background: var(--lw-white);
    aspect-ratio: 8.5 / 11;
    border-radius: 2px;
    box-shadow: var(--lw-shadow-sm);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* PDF.js renders page 1 into this canvas; see aiReviewRealtime.js. Until it
   resolves the placeholder below holds the exact same box, so nothing reflows. */
.lw-air-doc__canvas {
    max-width: 100%;
    max-height: 100%;
    display: block;
}

.lw-air-doc__placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--lw-neutral-ink);
    font-size: 28px;
}

.lw-air-scan {
    position: absolute;
    left: 0;
    right: 0;
    top: 4%;
    height: 2px;
    background: var(--lw-primary);
    box-shadow: 0 0 14px 4px var(--lw-primary-light);
    animation: lwAiScan 2.6s ease-in-out infinite alternate;
}

.lw-air-doc__meta {
    font-size: var(--lw-fs-xs);
    color: var(--lw-text-muted);
    display: flex;
    justify-content: space-between;
    gap: 8px;
}

.lw-air-doc__meta span:last-child {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* right column ------------------------------------------------------------ */

.lw-air-main {
    flex: 1 1 280px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.lw-air-main__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

.lw-air-main__title {
    font-size: var(--lw-fs-lg);
    font-weight: 500;
    color: var(--lw-text-primary);
}

.lw-air-main__remaining {
    font-size: var(--lw-fs-md);
    color: var(--lw-text-muted);
    font-variant-numeric: tabular-nums;
}

.lw-air-overall {
    height: 4px;
    border-radius: 2px;
    background: var(--lw-border-light);
    overflow: hidden;
    margin-top: -6px;
}

.lw-air-overall__bar {
    height: 100%;
    border-radius: 2px;
    background: var(--lw-primary);
    transition: width 0.4s ease-in-out;
    width: 0;
}

/* stage list -------------------------------------------------------------- */

.lw-air-stages {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.lw-air-stage {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 7px 0;
    border-top: 1px solid var(--lw-border-light);
}

.lw-air-stage__icon {
    width: 20px;
    height: 20px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
}

.lw-air-stage__icon--done    { color: var(--lw-status-pass-ink); font-size: 15px; }
.lw-air-stage__icon--current { color: var(--lw-primary-ink);     font-size: 14px; }
.lw-air-stage__icon--skipped { color: var(--lw-status-disabled-fill); font-size: 14px; }

.lw-air-stage__pending {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1.5px solid var(--lw-border-strong);
    box-sizing: border-box;
}

.lw-air-stage__body { flex: 1; min-width: 0; }

.lw-air-stage__row {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    align-items: baseline;
}

.lw-air-stage__label { font-size: var(--lw-fs-md); color: var(--lw-text-muted); }

.lw-air-stage--active .lw-air-stage__label {
    color: var(--lw-text-primary);
    font-weight: 500;
}

.lw-air-stage__meta {
    font-size: var(--lw-fs-xs);
    color: var(--lw-text-muted);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.lw-air-stage__sub {
    font-size: var(--lw-fs-sm);
    color: var(--lw-text-muted);
    margin-top: 2px;
    line-height: 1.4;
}

/* verdict ----------------------------------------------------------------- */

.lw-air-result {
    display: flex;
    align-items: center;
    gap: 12px;
}

.lw-air-result__icon {
    width: 40px;
    height: 40px;
    flex: none;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
}

.lw-air-result__icon--pass   { background: var(--lw-status-pass-tint);   color: var(--lw-status-pass-ink); }
.lw-air-result__icon--fail   { background: var(--lw-status-fail-tint);   color: var(--lw-status-fail-ink); }
.lw-air-result__icon--review { background: var(--lw-warning-tint); color: var(--lw-warning-ink); }

.lw-air-result__title {
    font-size: var(--lw-fs-xl);
    font-weight: 500;
    line-height: 1.2;
    color: var(--lw-text-primary);
}

.lw-air-result__meta {
    font-size: var(--lw-fs-sm);
    color: var(--lw-text-muted);
    margin-top: 2px;
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.lw-air-result__meta i { font-size: 9px; }

.lw-air-summary {
    display: flex;
    gap: 12px;
    background: var(--lw-surface-sunken);
    border-radius: var(--lw-radius-sm);
    padding: 12px 14px;
}

.lw-air-summary__accent {
    width: 3px;
    flex: none;
    border-radius: 2px;
    align-self: stretch;
}

.lw-air-summary__accent--pass   { background: var(--lw-status-pass-fill); }
.lw-air-summary__accent--fail   { background: var(--lw-status-fail-fill); }
.lw-air-summary__accent--review { background: var(--lw-warning-fill); }

.lw-air-summary p {
    margin: 0;
    font-size: var(--lw-fs-md);
    color: var(--lw-text);
    text-wrap: pretty;
}

.lw-air-sectionlabel {
    font-size: var(--lw-fs-xs);
    text-transform: uppercase;
    letter-spacing: var(--lw-ls-caps);
    font-weight: 600;
    color: var(--lw-text-muted);
    margin-bottom: 6px;
}

.lw-air-reasons {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.lw-air-reasons li {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    font-size: var(--lw-fs-md);
    color: var(--lw-text);
    line-height: 1.45;
}

.lw-air-reasons li::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--lw-text-muted);
    flex: none;
    margin-top: 7px;
}

/* cross-validation field table ------------------------------------------- */

.lw-air-fields {
    border: 1px solid var(--lw-border-light);
    border-radius: var(--lw-radius-sm);
    overflow: hidden;
}

.lw-air-fields__row {
    display: grid;
    grid-template-columns: minmax(64px, 0.8fr) minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(88px, auto);
    gap: 0 10px;
    padding: 8px 10px;
    border-top: 1px solid var(--lw-border-light);
    font-size: var(--lw-fs-md);
    align-items: start;
    line-height: 1.4;
}

.lw-air-fields__row--head {
    padding: 7px 10px;
    border-top: none;
    background: var(--lw-table-header-bg);
    font-size: var(--lw-fs-xs);
    text-transform: uppercase;
    letter-spacing: var(--lw-ls-caps);
    font-weight: 600;
    color: var(--lw-table-header-fg);
}

.lw-air-fields__label { color: var(--lw-text-muted); }

.lw-air-fields__doc {
    color: var(--lw-text-primary);
    font-weight: 500;
    overflow-wrap: break-word;
}

.lw-air-fields__loan {
    color: var(--lw-text);
    overflow-wrap: break-word;
}

.lw-air-fields__status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--lw-fs-sm);
    color: var(--lw-text-secondary);
    white-space: nowrap;
}

.lw-air-fields__status--nv { color: var(--lw-text-muted); }

.lw-air-fields__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
}

.lw-air-fields__dot--matched    { background: var(--lw-status-pass-ink); }
.lw-air-fields__dot--mismatched { background: var(--lw-warning-ink); }
.lw-air-fields__dot--nv         { background: var(--lw-status-disabled-fill); }

.lw-air-fields__note {
    font-size: var(--lw-fs-xs);
    color: var(--lw-text-muted);
    margin-top: 6px;
}

/* footer ------------------------------------------------------------------ */

.lw-air-modal__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px 16px;
    padding: 14px 20px;
    border-top: 1px solid var(--lw-border-light);
    background: var(--lw-surface);
}

.lw-air-modal__foothint {
    flex: 1 1 200px;
    font-size: var(--lw-fs-md);
    color: var(--lw-text-muted);
}

.lw-air-modal__footactions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

/* verdict feedback --------------------------------------------------------
 *
 * A tinted band rather than another hairline row: the dialog's other bands are
 * the evidence and the actions, and an ask that looks like either gets read as
 * neither. Primary tint, not a status tint — amber/teal/red in this dialog all
 * mean "the document is like this", and the question is not a verdict.
 *
 * Colour stays on the band and on the chosen vote. Nothing here floods. */
.lw-air-fb {
    padding: 10px 20px;
    border-top: 1px solid var(--lw-border-light);
    background: var(--lw-primary-tint);
}

.lw-air-fb[hidden] { display: none; }

.lw-air-fb__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px 14px;
    flex-wrap: wrap;
    min-height: 26px;
}

.lw-air-fb__ask {
    font-size: var(--lw-fs-md);
    font-weight: var(--lw-fw-medium);
    color: var(--lw-primary-ink);
}

.lw-air-fb__votes {
    display: flex;
    gap: 6px;
}

.lw-air-fb__votes[hidden] { display: none; }

/* Hollow at rest so neither answer is the suggested one. */
.lw-air-fb__vote {
    width: 26px;
    height: 26px;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    cursor: pointer;
    border: 1px solid var(--lw-border);
    border-radius: var(--lw-radius-full);
    background: var(--lw-surface);
    color: var(--lw-text-muted);
    transition: color var(--lw-transition-fast),
                border-color var(--lw-transition-fast),
                background var(--lw-transition-fast);
}

.lw-air-fb__vote:hover {
    color: var(--lw-text);
    border-color: var(--lw-border-strong);
}

.lw-air-fb__vote:focus-visible {
    outline: none;
    box-shadow: var(--lw-shadow-focus);
}

.lw-air-fb__vote--up.is-on {
    background: var(--lw-status-pass-tint);
    color: var(--lw-status-pass-ink);
    border-color: transparent;
}

.lw-air-fb__vote--down.is-on {
    background: var(--lw-status-fail-tint);
    color: var(--lw-status-fail-ink);
    border-color: transparent;
}

.lw-air-fb__panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
}

.lw-air-fb__chips {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.lw-air-fb__chip {
    font: inherit;
    font-size: var(--lw-fs-sm);
    cursor: pointer;
    border: 1px solid var(--lw-border);
    border-radius: var(--lw-radius-pill);
    padding: 4px 11px;
    background: var(--lw-surface);
    color: var(--lw-text-secondary);
    transition: color var(--lw-transition-fast),
                border-color var(--lw-transition-fast),
                background var(--lw-transition-fast);
}

.lw-air-fb__chip:hover {
    border-color: var(--lw-border-strong);
    color: var(--lw-text);
}

.lw-air-fb__chip.is-on {
    border-color: var(--lw-primary);
    background: var(--lw-surface);
    color: var(--lw-primary-ink);
}

.lw-air-fb__text {
    font: inherit;
    font-size: var(--lw-fs-md);
    border: 1px solid var(--lw-input-border);
    border-radius: var(--lw-radius-sm);
    background: var(--lw-input-bg);
    color: var(--lw-input-fg);
    padding: 7px 10px;
    resize: vertical;
    min-height: 40px;
    width: 100%;
    box-sizing: border-box;
}

.lw-air-fb__text::placeholder { color: var(--lw-input-placeholder); }

.lw-air-fb__text:focus {
    border-color: var(--lw-input-border-focus);
    outline: none;
}

.lw-air-fb__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.lw-air-fb__note {
    font-size: var(--lw-fs-sm);
    color: var(--lw-text-muted);
}

.lw-air-fb__note--error { color: var(--lw-status-fail-ink); }

.lw-air-fb__done {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: var(--lw-fs-md);
    color: var(--lw-text-secondary);
}

/* A class-level `display` outranks the UA [hidden] rule, so every element this
   component toggles has to restate it or the hidden state renders anyway. */
.lw-air-fb__done[hidden] { display: none; }

.lw-air-fb__done i { color: var(--lw-status-pass-ink); }

.lw-air-fb__link {
    font: inherit;
    font-size: var(--lw-fs-sm);
    background: none;
    border: 0;
    padding: 0;
    color: var(--lw-primary-ink);
    cursor: pointer;
    text-decoration: underline;
}

.lw-air-fb__link:hover { color: var(--lw-link-hover); }

/* At narrow widths the preview and the detail stack; the preview shrinks so it
   never eats the half of the dialog that carries the answer. */
@container (max-width: 520px) {
    .lw-air-doc {
        max-width: 150px;
        flex-basis: 130px;
    }
}

/* ============================================================================
   SURFACE 2b — file list <-> detail view, and the inline delete confirm
   (CU-868kmgegq)

   The popup now holds BOTH surfaces at once: the legacy file table is the list,
   and one detail view per file sits beside it, all but one hidden. The table is
   never removed — every existing AI mechanism keys off markup inside it (the SSE
   reader finds documents through `.ai-status-badge`, `deleteUploadFileDocWithAI()`
   counts `tr[id^=upload_chk_]`) — so the switch is purely a visibility toggle.

   Bootstrap 4's reboot already ships `[hidden] { display: none }`, but these
   elements sit inside `display: flex`/`inline-flex` parents whose own rules can
   out-specify it, so the toggle is made explicit here rather than left to luck.
   ========================================================================== */

[data-lw-air-detail][hidden],
[data-lw-air-mount][hidden],
[data-lw-air-rowconfirm][hidden],
.lw-air-delwrap > [hidden],
.lw-air-modal__headactions[hidden],
.lw-air-confirm[hidden] { display: none !important; }

/* ------------------------------------------------- row "expand" affordance */

/* An explicit, LABELLED control on every file row. The previous only way into
   the detail view was the "(1 file)" link on the host page behind this popup,
   which nobody found. Rendered the same before, during and after a review: the
   detail view is where the live progress is, so it has to be inviting while the
   document is still processing too. */
.lw-air-open {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 5px;
    padding: 3px 9px;
    border: 1px solid var(--lw-primary);
    border-radius: var(--lw-radius-pill);
    background: var(--lw-primary-tint);
    color: var(--lw-primary-ink);
    font-family: var(--lw-font-sans);
    font-size: var(--lw-fs-xs);
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.lw-air-open:hover,
.lw-air-open:focus-visible {
    background: var(--lw-primary);
    color: var(--lw-text-on-primary);
}

/* The colour change is the affordance and stays; only the easing goes, so the
   control still reads as interactive with motion turned down. */
@media (prefers-reduced-motion: reduce) {
    .lw-air-open { transition: none; }
}

.lw-air-open i { font-size: 0.95em; }

/* --------------------------------------------------- inline delete confirm */

/* Replaces the $.confirm dialog that used to open ON TOP of this popup. A
   confirmation stacked over the thing it is about hides the row being deleted;
   asking in place keeps it visible. */
.lw-air-delwrap {
    display: inline-flex;
    align-items: center;
}

.lw-air-rowconfirm,
.lw-air-confirm {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--lw-danger);
    border-radius: var(--lw-radius-pill);
    background: var(--lw-danger-tint);
    font-family: var(--lw-font-sans);
    font-size: var(--lw-fs-xs);
    white-space: nowrap;
}

.lw-air-confirm { margin: 0 20px 12px; }

.lw-air-confirm__text {
    color: var(--lw-danger-ink);
    font-weight: 500;
}

/* ------------------------------------------------------ detail view header */

.lw-air-modal__headactions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* The internal way back. The popup's own header X dismisses the whole dialog;
   this one only collapses the detail view, so the file list is always one
   click away without leaving the popup. */
.lw-air-modal__back {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    white-space: nowrap;
}

/* ---------------------------------------------------------- image previews */

/* JPG/PNG uploads (the common shape for a driver's licence) used to fall into
   the PDF.js path and render a broken-image glyph. They are drawn directly now,
   contained in the SAME frame and aspect ratio as the PDF canvas so switching
   between a PDF and an image never shifts the layout. */
.lw-air-doc__img {
    max-width: 100%;
    max-height: 100%;
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
