/* ========================================
   RESULT PREVIEW - the lightbox footer + overlay controls of
   static/shared/js/result-preview.js, shared by the Model Tester and the
   Pipeline Builder. Base lightbox styles are in lightbox.css.
   ======================================== */

.batch-lightbox-result {
    margin-bottom: var(--space-md);
}

.batch-lightbox-result .result-label {
    font-size: 0.75rem;
    color: var(--text-subtle);
    margin-bottom: 4px;
}

.batch-lightbox-result .result-value {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-high);
}

/* Classifier-only lightbox footer: one card per model — its single top
   prediction, always, whether or not a full per-class distribution exists
   underneath (adaptive/BYOM classifiers have one; production classifiers
   never do, see the comment at this list's call site) — model name and
   label sit on the SAME row, no per-model header. Left to right: the
   model's own name (same font as the detector/pipeline footer's
   .pipeline-model-name — no override here either, both just inherit the
   app's normal font), then the output label as a pill (the thing this row
   actually reports on) with
   its own confidence score bullet-separated inside the same pill — no
   separate bar/percentage group, no color coding beyond the one constant
   teal accent (identity here doesn't need color, there's no bounding box
   for it to key against). */
.score-row-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.score-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 14px;
    border: 1px solid var(--border-card);
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.012));
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

/* The prediction failed its own confidence/size gate (gateAll) — dimmed
   rather than iconed, since an unexplained checkmark communicates nothing
   on sight. Tooltip carries the "why" for anyone who hovers. */
.score-row-below-threshold {
    opacity: 0.5;
}

/* One step below the label's size (see the type scale used throughout
   this file: .6875/.75/.8125/.875rem) — the label is the thing this row
   reports on, the model name is context for it. */
.score-row-model {
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--text-high);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 220px;
    flex-shrink: 0;
}

.score-row-label-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    max-width: 280px;
    flex-shrink: 1;
    padding: 3px 11px;
    border: 1px solid rgba(79, 184, 184, 0.35);
    border-radius: 999px;
    background: rgba(79, 184, 184, 0.07);
    color: var(--text-high);
    font-size: 0.8125rem;
    font-weight: 600;
}

.score-row-pill-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.score-row-pill-sep {
    color: var(--text-subtle);
    font-weight: 400;
    flex-shrink: 0;
}

.score-row-pill-value {
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.label-toggle-btn {
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    border-radius: 3px;
    background: transparent;
    color: var(--text-subtle);
    cursor: pointer;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.label-toggle-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-high);
}

.label-toggle-btn svg {
    width: 13px;
    height: 13px;
}

.pipeline-class-row.label-hidden .pipeline-class-label,
.pipeline-class-row.label-hidden .pipeline-class-count {
    opacity: 0.35;
}

.master-toggle-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border-card);
}

.master-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border: 1px solid var(--border-card);
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-high);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
}

.master-toggle-btn:hover {
    background: rgba(255, 255, 255, 0.06);
}

.master-toggle-btn.filtered-only-btn.active {
    background: var(--teal-400, #4fb8b8);
    border-color: var(--teal-400, #4fb8b8);
    color: #10221f;
}

.master-toggle-btn svg {
    width: 13px;
    height: 13px;
}

/* Sized to match .pipeline-class-crops img (its only context — see
   _renderLabelRow, which now always renders into .pipeline-class-crops)
   so a classification with no crop_b64 of its own doesn't sit oversized
   next to real 28px thumbnails in the same row. */
.crop-placeholder {
    width: 28px;
    height: 28px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    flex-shrink: 0;
}

.no-detections {
    color: var(--text-subtle);
    font-size: 0.85rem;
}

/* Small legend explaining the per-crop filter checkmark, shown once above
   each footer's master toggle row. */
.footer-badge-legend {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.6875rem;
    color: var(--text-subtle);
    white-space: nowrap;
}

/* The legend's checkmark reuses .crop-filter-check itself (see below) so it's
   guaranteed to look identical to the real per-crop badge — this modifier
   only swaps the corner-badge positioning for inline flow. */
.crop-filter-check.legend-inline {
    position: static;
    border: none;
    flex-shrink: 0;
}

/* Wraps a crop thumbnail so the filter-inclusion checkmark can sit in its
   corner without disturbing the existing .pipeline-class-crops layout —
   the wrapper is just a sizing/positioning shell, not a visual box. */
.footer-crop-wrap {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}

.crop-filter-check {
    position: absolute;
    bottom: -3px;
    right: -3px;
    width: 13px;
    height: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--teal-400, #4fb8b8);
    color: #06201e;
    border-radius: 50%;
    border: 1.5px solid var(--bg-panel, #1c1c22);
}

.crop-filter-check svg {
    width: 8px;
    height: 8px;
}

/* Pipeline results — grouped by model. No max-height here: the lightbox
   footer is already a 200px scroll region, and a second one nested inside it
   produces two competing scrollbars. */
.pipeline-results-grouped {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.pipeline-model-section {
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 6px;
    overflow: hidden;
}

.pipeline-model-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    background: rgba(255, 255, 255, 0.05);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.pipeline-model-name {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-high);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pipeline-model-count {
    font-size: 0.7rem;
    color: var(--text-subtle);
    white-space: nowrap;
    margin-left: 8px;
}

/* Vision LLM answers, under the model sections of the lightbox footer: one row per LLM
   call, the answer in the same pill the classifier rows use, then the LLM's reason. */
.llm-calls {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 12px;
}

.llm-calls-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-high);
}

.llm-calls-usage {
    font-size: 0.7rem;
    font-weight: 400;
    color: var(--text-subtle);
    text-align: right;
}

.llm-call-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 6px 10px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.03);
}

.llm-call-row .score-row-label-pill {
    flex-shrink: 0;
    max-width: 200px;
    font-size: 0.75rem;
}

.llm-call-reason {
    min-width: 0;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--text-subtle);
    overflow-wrap: anywhere;
}

/* A read step's values: field -> value, model output wrapped to the footer. */
.llm-call-reading {
    margin: 4px 10px;
    width: calc(100% - 20px);
    font-size: 0.75rem;
    line-height: 1.45;
    border-collapse: collapse;
}

.llm-call-reading th,
.llm-call-reading td {
    padding: 3px 8px;
    vertical-align: top;
    overflow-wrap: anywhere;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.llm-call-reading th {
    width: 40%;
    font-weight: 600;
    color: var(--text-subtle);
}

.llm-call-reading td {
    color: var(--text-medium);
}

.llm-call-reading td.is-empty {
    color: var(--text-subtle);
    font-style: italic;
}

.llm-calls-request {
    font-size: 0.65rem;
    color: var(--text-subtle);
    user-select: all;
}

.pipeline-class-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px 4px 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.03);
}

.pipeline-class-row:last-child {
    border-bottom: none;
}

.pipeline-class-label {
    font-size: 0.75rem;
    color: var(--text-high);
    font-weight: 500;
    white-space: nowrap;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pipeline-class-count {
    font-size: 0.7rem;
    color: var(--text-subtle);
    min-width: 18px;
    text-align: center;
}

.pipeline-class-crops {
    display: flex;
    gap: 3px;
    align-items: center;
    margin-left: auto;
}

.pipeline-class-crops img {
    width: 28px;
    height: 28px;
    object-fit: cover;
    border-radius: 3px;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.pipeline-class-crops img[data-bbox] {
    cursor: pointer;
}

/* A crop the server sent no image for, before the browser cuts it from the displayed photo.
   Matches .crop-placeholder so the row does not flicker between two different empty looks. */
.pipeline-class-crops img.crop-pending {
    background: rgba(255, 255, 255, 0.05);
}

.pipeline-class-crops img[data-bbox]:hover {
    border-color: #ffffff;
    box-shadow: 0 0 6px rgba(255, 255, 255, 0.4);
}

.pipeline-class-crops img:hover {
    border-color: var(--primary);
}

/* Lightbox "How these controls interact" help modal — a real EsmModal
   (static/shared/js/esm-modal.js), not the inline popover .esm-modal-title/
   .esm-modal-message default to. Left-aligned, breathing room between
   paragraphs, same read as the old popover's prose. */
.lightbox-help-modal .esm-modal-title {
    text-align: left;
}

.lightbox-help-modal-body {
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--text-medium);
}

.lightbox-help-modal-body p {
    margin: 0 0 12px;
}

.lightbox-help-modal-body p:last-child {
    margin-bottom: 0;
}

.lightbox-help-modal-body strong {
    color: var(--text-high);
}

/* The footer's "?" button -- opens the help modal above. */
.lightbox-help-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 50%;
    color: var(--text-subtle);
    cursor: pointer;
    transition: color var(--transition-fast), background var(--transition-fast);
}

.lightbox-help-btn svg {
    width: 15px;
    height: 15px;
}

.lightbox-help-btn:hover {
    color: var(--text-high);
    background: rgba(255, 255, 255, 0.08);
}

@media (max-width: 767px) {
    /* Classifier-only score rows in lightbox: drop to two lines rather
       than clipping the label/model pill. */
    .score-row {
        flex-wrap: wrap;
    }

    /* Pipeline results: horizontal scroll on mobile */
    .pipeline-results-grouped {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}
