/* research.css — property permit research flow (.research-shell, .research-confirm, .research-status, .research-report). */

/* ==========================================================================
   Research Report · Editorial layout
   Migrated from app/templates/research/report.html <style> block.
   All selectors scoped under .research-report to prevent collisions with
   dashboard .report-card and other shared class names.
   ========================================================================== */

.research-report {
    max-width: 1120px;
    margin: 0 auto;
    padding: 2.5rem 1.5rem 5rem;
    color: var(--text-body);
    display: grid;
    gap: 1.5rem;
}

.research-report .report-hero {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(ellipse at 85% 15%, rgba(212, 168, 75, 0.09) 0%, transparent 55%),
        radial-gradient(ellipse at 10% 90%, rgba(193, 127, 89, 0.06) 0%, transparent 55%),
        var(--bg-paper);
    color: var(--text-primary);
    border-radius: 16px;
    padding: 2.75rem 2.5rem 2.25rem;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border-subtle);
}
.research-report .report-kicker {
    font-family: "IBM Plex Mono", "Source Code Pro", monospace;
    font-size: .72rem;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--accent-gold, #d4a84b);
    margin-bottom: .85rem;
    display: flex;
    align-items: center;
    gap: .85rem;
}
.research-report .report-kicker::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, rgba(212, 168, 75, 0.35), transparent);
}
.research-report .report-hero h1 {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-weight: 400;
    font-size: clamp(2rem, 5vw, 3.6rem);
    line-height: 1.04;
    letter-spacing: -0.02em;
    margin: 0 0 1rem;
    color: var(--text-primary);
    word-break: break-word;
    text-wrap: balance;
}
.research-report .report-subhead {
    max-width: 54rem;
    line-height: 1.6;
    color: var(--text-body);
    font-size: 1.05rem;
    font-weight: 300;
    margin: 0 0 1.25rem;
}
.research-report .report-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0 1.1rem;
    padding: .9rem 0 .2rem;
    border-top: 1px solid var(--border-subtle);
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-report .report-meta span {
    white-space: nowrap;
    padding: .3rem 0;
}
.research-report .report-meta span + span {
    position: relative;
    padding-left: 1.1rem;
}
.research-report .report-meta span + span::before {
    content: "·";
    position: absolute;
    left: 0;
    color: var(--text-faint, #5a5754);
}
.research-report .report-actions {
    display: flex;
    gap: .75rem;
    flex-wrap: wrap;
    margin-top: 1.5rem;
}

/* Hero stats — hierarchical, editorial. Two headline numbers anchor the
   eye, a single date-range line carries the timespan, and a slim mono
   meta strip handles status + generated-on. Replaces the flat six-cell
   grid that read as a generic SaaS dashboard. */
.research-report .report-stats {
    padding: 1.75rem 0 .25rem;
    margin-top: 1.75rem;
    border-top: 1px solid var(--border-subtle);
}
.research-report .report-stats-headline {
    display: grid;
    grid-template-columns: minmax(0, .85fr) minmax(0, .85fr) minmax(0, 1.6fr);
    gap: 2.75rem;
    align-items: end;
}
.research-report .report-stat {
    display: flex;
    flex-direction: column;
    gap: .45rem;
    min-width: 0;
}
.research-report .report-stat-large .report-stat-value {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-size: clamp(2.5rem, 5vw, 3.75rem);
    font-weight: 400;
    line-height: 0.95;
    color: var(--text-primary);
    letter-spacing: -.03em;
}
.research-report .report-stat-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .16em;
    color: var(--text-muted);
}

/* Date-range stat — values span a single horizontal line with a gold
   arrow as the visual hinge. Borderless and column-anchored so it
   doesn't compete with the two headline numerals next to it. */
.research-report .report-stat-range {
    padding-left: 2rem;
    border-left: 1px solid var(--border-subtle);
}
.research-report .report-stat-range-value {
    display: inline-flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .75rem;
    font-family: "IBM Plex Mono", monospace;
    font-size: clamp(1.05rem, 1.8vw, 1.4rem);
    font-weight: 500;
    color: var(--text-primary);
    letter-spacing: -.005em;
}
.research-report .report-stat-range-arrow {
    color: var(--accent-gold, #d4a84b);
    font-size: .9em;
    line-height: 1;
    padding: 0 .15rem;
}

/* Meta strip — tiny mono row with a status pill and a generated-on
   timestamp, separated by a thin rule. Always sits BELOW the headline
   stats with a comfortable gap, never inline with them. */
.research-report .report-stats-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 1.75rem;
    padding-top: 1.1rem;
    border-top: 1px dashed var(--border-subtle);
}
.research-report .report-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    padding: .35rem .7rem;
    border-radius: 999px;
    background: rgba(125, 154, 125, 0.12);
    border: 1px solid rgba(125, 154, 125, 0.32);
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: var(--color-success, #7d9a7d);
}
.research-report .report-meta-pill-dot {
    width: 6px;
    height: 6px;
    background: var(--color-success, #7d9a7d);
    border-radius: 50%;
}
/* Partial / failed / refunded variants — same shape, different chroma. */
.research-report .report-meta-pill-completed_partial,
.research-report .report-meta-pill-completed-partial {
    background: rgba(212, 168, 75, 0.10);
    border-color: rgba(212, 168, 75, 0.32);
    color: var(--accent-gold, #d4a84b);
}
.research-report .report-meta-pill-completed_partial .report-meta-pill-dot,
.research-report .report-meta-pill-completed-partial .report-meta-pill-dot {
    background: var(--accent-gold, #d4a84b);
}
.research-report .report-meta-pill-failed,
.research-report .report-meta-pill-refunded {
    background: rgba(193, 127, 89, 0.10);
    border-color: rgba(193, 127, 89, 0.32);
    color: var(--accent-terracotta-light, #c17f59);
}
.research-report .report-meta-pill-failed .report-meta-pill-dot,
.research-report .report-meta-pill-refunded .report-meta-pill-dot {
    background: var(--accent-terracotta-light, #c17f59);
}

.research-report .report-meta-divider {
    width: 1px;
    height: 12px;
    background: var(--border-subtle);
}
.research-report .report-meta-detail {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: var(--text-muted);
}

@media (max-width: 960px) {
    .research-report .report-stats-headline {
        grid-template-columns: 1fr 1fr;
        gap: 1.75rem 2.25rem;
    }
    .research-report .report-stat-range {
        grid-column: 1 / -1;
        padding-left: 0;
        padding-top: 1.5rem;
        border-left: none;
        border-top: 1px solid var(--border-subtle);
    }
}
@media (max-width: 560px) {
    .research-report .report-stats-headline {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }
    .research-report .report-stat-large .report-stat-value {
        font-size: 2.4rem;
    }
    .research-report .report-stat-range-value {
        font-size: 1rem;
    }
}

/* Section cards — explicit override of the sibling .report-card rule at line ~3053
   (dashboard 3-column grid). Same specificity, so scope the layout + hover here. */
.research-report .report-card {
    display: block;
    background: var(--bg-paper);
    border: 1px solid var(--border-subtle);
    border-radius: 14px;
    padding: 1.75rem 2rem;
    box-shadow: var(--shadow-md);
    overflow: hidden;
    transition: none;
}
.research-report .report-card:hover {
    border-color: var(--border-subtle);
    background: var(--bg-paper);
}

.research-report .section-head {
    display: grid;
    grid-template-columns: 140px 1fr;
    gap: 1.5rem;
    align-items: baseline;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-subtle);
}
.research-report .section-num {
    font-family: "IBM Plex Mono", monospace;
    font-size: .7rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--accent-gold, #d4a84b);
}
.research-report .section-head h2 {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-weight: 400;
    font-size: clamp(1.5rem, 2.4vw, 2rem);
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--text-primary);
    line-height: 1.1;
}

/* § 01 · What stands out */
.research-report .standouts-list {
    display: grid;
    gap: 0;
}
.research-report .standout {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 1.5rem;
    align-items: start;
    padding: 1rem 0;
    border-top: 1px solid var(--border-subtle);
}
.research-report .standout:first-child { border-top: 0; padding-top: 0; }
.research-report .standout:last-child { padding-bottom: 0; }
.research-report .standout-text {
    font-family: "Source Serif 4", "Playfair Display", Georgia, serif;
    font-size: 1.08rem;
    line-height: 1.55;
    color: var(--text-primary);
    font-weight: 300;
}
.research-report .standout-text strong {
    font-weight: 500;
    color: var(--text-primary);
}
.research-report .standout-tags {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .35rem;
    white-space: nowrap;
}

.research-report .src-tag {
    font-family: "IBM Plex Mono", monospace;
    font-size: .66rem;
    color: var(--text-muted);
    letter-spacing: .04em;
}

/* § 01 · Flags strip — horizontal, typographic, no nested card chrome. */
.research-report .flags-strip {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
    margin: 0 0 1.75rem;
    padding: 1.1rem 0;
    border-top: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
}
.research-report .flags-strip-clear {
    grid-template-columns: 1fr;
}
.research-report .flag-item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .3rem;
    padding: 0 1.25rem;
    border-left: 1px solid var(--border-subtle);
    color: var(--text-muted);
}
.research-report .flag-item:first-child { border-left: 0; padding-left: 0; }
.research-report .flag-count {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-size: clamp(2rem, 4vw, 2.8rem);
    font-weight: 400;
    line-height: 1;
    color: var(--text-primary);
    letter-spacing: -0.02em;
}
.research-report .flag-item.flag-open .flag-count { color: var(--accent-gold, #d4a84b); }
.research-report .flag-item.flag-expired .flag-count { color: var(--accent-terracotta, #c17f59); }
.research-report .flag-item.flag-stale .flag-count { color: var(--accent-terracotta, #c17f59); }
.research-report .flag-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .7rem;
    letter-spacing: .16em;
    text-transform: uppercase;
}
.research-report .flag-clear {
    font-family: "Source Serif 4", "Playfair Display", Georgia, serif;
    font-size: 1.05rem;
    color: var(--text-body);
    font-weight: 300;
    font-style: italic;
    text-align: center;
    line-height: 1.5;
}
.research-report .flag-clear-detail {
    display: block;
    margin-top: .4rem;
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    font-style: normal;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
}
/* Explains that Stale is a subset of Open, not a fourth population. */
.research-report .flags-note {
    margin: -1.25rem 0 1.25rem;
    font-family: "Source Serif 4", Georgia, serif;
    font-size: .9rem;
    font-style: italic;
    font-weight: 300;
    color: var(--text-body);
    line-height: 1.5;
}
.research-report .flags-caveat {
    margin: -.5rem 0 1.75rem;
    padding: .5rem 0 0;
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-align: right;
}

/* § 01 · Systems matrix — dense table, one row per tracked system. */
.research-report .systems-matrix {
    display: grid;
    gap: 0;
    margin: 0 0 1.75rem;
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    overflow: hidden;
}
.research-report .systems-matrix-head,
.research-report .system-row {
    display: grid;
    grid-template-columns:
        minmax(180px, 1.4fr)
        minmax(110px, .7fr)
        90px
        minmax(0, 1fr)
        minmax(140px, 1fr);
    gap: 1rem;
    align-items: center;
    padding: .68rem 1.1rem;
}
.research-report .systems-matrix-head {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.025);
    border-bottom: 1px solid var(--border-subtle);
}
.research-report .system-row + .system-row {
    border-top: 1px solid var(--border-subtle);
}
.research-report .system-row:nth-child(even) {
    background: rgba(255, 255, 255, 0.015);
}
.research-report .system-label {
    font-family: "Source Serif 4", "Playfair Display", Georgia, serif;
    font-size: 1.02rem;
    color: var(--text-primary);
    font-weight: 400;
}
.research-report .system-year {
    font-family: "IBM Plex Mono", monospace;
    font-size: .92rem;
    color: var(--accent-gold, #d4a84b);
    letter-spacing: .02em;
}
.research-report .system-status {
    font-family: "IBM Plex Mono", monospace;
    font-size: .78rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-body);
}
.research-report .system-permit .permit-ref {
    font-family: "IBM Plex Mono", monospace;
    font-size: .8rem;
    color: var(--text-body);
    text-decoration: none;
    border-bottom: 1px dashed var(--border-subtle);
    padding-bottom: 1px;
    transition: color .15s ease, border-color .15s ease;
}
.research-report .system-permit .permit-ref:hover {
    color: var(--accent-gold, #d4a84b);
    border-bottom-color: var(--accent-gold, #d4a84b);
}
.research-report .system-row.empty .system-label { color: var(--text-muted); }
.research-report .system-row.empty .system-empty {
    grid-column: 3 / -1;
    font-family: "IBM Plex Mono", monospace;
    font-size: .78rem;
    letter-spacing: .04em;
    color: var(--text-muted);
    font-style: italic;
}

/* Records column — count pill for matched rows, soft "checked" badge for empty. */
.research-report .system-count {
    display: flex;
    align-items: center;
}
.research-report .system-count-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.8rem;
    height: 1.5rem;
    padding: 0 .55rem;
    border-radius: 999px;
    background: rgba(212, 168, 75, 0.12);
    border: 1px solid rgba(212, 168, 75, 0.32);
    color: var(--accent-gold, #d4a84b);
    font-family: "IBM Plex Mono", monospace;
    font-size: .8rem;
    font-weight: 500;
    letter-spacing: .02em;
}
.research-report .system-count-zero {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-faint, #5a5754);
}
.research-report .system-row.empty .system-count {
    opacity: .85;
}

.research-report .systems-matrix-footer {
    margin: 0 0 1.5rem;
    padding: .25rem 0 0;
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.research-report .chip {
    font-family: "IBM Plex Mono", monospace;
    font-size: .66rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: .22rem .55rem;
    border-radius: 999px;
    background: rgba(212, 168, 75, 0.1);
    color: var(--accent-gold, #d4a84b);
    border: 1px solid rgba(212, 168, 75, 0.25);
}
/* ─── § 03 · Analysis & Observations ────────────────────────────────────
   Confident, neutral observations only. Standouts get full emphasis. */
.research-report .observations .standouts-list {
    margin-bottom: 2rem;
}

/* ─── Coverage & Sources ────────────────────────────────────────────────
   The per-report scope statement: exactly which portals were searched,
   when, with what result, and what sits outside the search's scope. */
.research-report .coverage-intro {
    margin: 0 0 1.25rem;
    font-size: 1.02rem;
    color: var(--text-body);
}
.research-report .coverage-table {
    display: grid;
    margin: 0 0 1.25rem;
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    overflow: hidden;
}
.research-report .coverage-table-head,
.research-report .coverage-row {
    display: grid;
    grid-template-columns: minmax(180px, 1.6fr) minmax(140px, 1fr) minmax(110px, .8fr);
    gap: 1rem;
    align-items: center;
    padding: .68rem 1.1rem;
}
.research-report .coverage-table-head {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.025);
    border-bottom: 1px solid var(--border-subtle);
}
.research-report .coverage-row + .coverage-row {
    border-top: 1px solid var(--border-subtle);
}
.research-report .coverage-name {
    font-family: "Source Serif 4", "Playfair Display", Georgia, serif;
    font-size: 1.02rem;
    color: var(--text-primary);
}
.research-report .coverage-result,
.research-report .coverage-asof {
    font-family: "IBM Plex Mono", monospace;
    font-size: .78rem;
    letter-spacing: .04em;
    color: var(--text-body);
}
.research-report .coverage-asof {
    color: var(--text-muted);
}
.research-report .coverage-row-failed .coverage-result {
    color: var(--accent-terracotta, #c17f59);
}
.research-report .coverage-failed-note {
    margin: 0 0 1.25rem;
    padding: .7rem 1.1rem;
    border-left: 3px solid var(--accent-terracotta, #c17f59);
    background: rgba(193, 127, 89, 0.08);
    border-radius: 0 8px 8px 0;
    font-size: .92rem;
    line-height: 1.55;
    color: var(--text-body);
}
.research-report .coverage-authoritative {
    margin: 0 0 1.5rem;
    font-family: "Source Serif 4", Georgia, serif;
    font-style: italic;
    font-size: .9rem;
    line-height: 1.55;
    color: var(--text-muted);
}
.research-report .coverage-scope {
    border-top: 1px solid var(--border-subtle);
    padding-top: 1.1rem;
}
.research-report .coverage-scope-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--accent-terracotta-light, var(--accent-terracotta));
    margin-bottom: .6rem;
}
.research-report .coverage-scope ul {
    margin: 0;
    padding-left: 1.1rem;
}
.research-report .coverage-scope li {
    color: var(--text-muted);
    font-size: .92rem;
    line-height: 1.55;
    margin-bottom: .45rem;
}
.research-report .coverage-scope li:last-child {
    margin-bottom: 0;
}

/* § 03 · Filings, grouped (legacy — retained for older payloads) */
.research-report .project {
    padding: 1.5rem 0;
    border-top: 1px solid var(--border-subtle);
}
.research-report .project:first-of-type { border-top: 0; padding-top: 0; }
.research-report .project:last-of-type { padding-bottom: 0; }
.research-report .project-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: .75rem;
    flex-wrap: wrap;
}
.research-report .project-title {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-weight: 400;
    font-size: 1.4rem;
    color: var(--text-primary);
    margin: 0;
    line-height: 1.25;
    display: flex;
    align-items: baseline;
    gap: .75rem;
    flex-wrap: wrap;
}
.research-report .project-year {
    display: inline-block;
    font-family: "IBM Plex Mono", monospace;
    font-size: .75rem;
    letter-spacing: .06em;
    background: rgba(193, 127, 89, 0.14);
    color: var(--accent-terracotta, #c17f59);
    border: 1px solid rgba(193, 127, 89, 0.3);
    padding: .2rem .55rem;
    border-radius: 4px;
    position: relative;
    top: -2px;
}
.research-report .project-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem .55rem;
    margin-top: .4rem;
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-report .project-meta .sep { color: var(--text-faint, #5a5754); }
.research-report .project-summary {
    font-family: "Source Serif 4", Georgia, serif;
    font-size: 1.02rem;
    line-height: 1.6;
    color: var(--text-body);
    margin: .5rem 0 .75rem;
    font-weight: 300;
}
.research-report .project-summary strong {
    font-weight: 500;
    color: var(--text-primary);
}
.research-report .project-permits {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}
.research-report .project-permit-link {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    padding: .3rem .6rem;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--border-subtle);
    color: var(--text-body);
    text-decoration: none;
    transition: all 0.15s ease;
}
.research-report .project-permit-link:hover {
    background: rgba(212, 168, 75, 0.08);
    border-color: rgba(212, 168, 75, 0.3);
    color: var(--accent-gold, #d4a84b);
}

/* Status pills (shared by projects + timeline).

   Each pill drives its entire look from two custom properties: --pill (the
   accent ink) and --pill-rgb (its RGB triplet, for tinted fills/borders/halo).
   The semantic rules below only reset those two, so the structure stays in one
   place. Colors are the *light* accent variants — on the near-black report
   paper the base accents (#c17f59 / #d4a84b) read soft, so the brighter tints
   carry the contrast that the prior 0.04–0.14 fills lacked. */
.research-report .status-pill {
    /* Neutral fallback for any status without a semantic class (e.g. the
       jurisdiction-specific "CC Issued" / "CB Issued"). Lifted off --text-muted
       so unmatched statuses are still clearly legible, not bare grey text. */
    --pill: var(--text-body, #c9c4bc);
    --pill-rgb: 201, 196, 188;
    display: inline-flex;
    align-items: center;
    gap: .42rem;
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    padding: .34rem .72rem .34rem .6rem;
    border-radius: 999px;
    background: rgba(var(--pill-rgb), 0.18);
    color: var(--pill);
    border: 1px solid rgba(var(--pill-rgb), 0.5);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    white-space: nowrap;
    flex-shrink: 0;
}
/* Filled status dot with a soft halo — the at-a-glance signal that makes the
   row scannable without reading the label. */
.research-report .status-pill::before {
    content: "";
    width: .44rem;
    height: .44rem;
    border-radius: 999px;
    background: var(--pill);
    box-shadow: 0 0 0 3px rgba(var(--pill-rgb), 0.2);
    flex-shrink: 0;
}
/* Favorable / closed-out (sage) */
.research-report .status-pill.closed,
.research-report .status-pill.completed,
.research-report .status-pill.complete,
.research-report .status-pill.finaled,
.research-report .status-pill.finalized,
.research-report .status-pill.co-issued,
.research-report .status-pill.cc-issued,
.research-report .status-pill.cb-issued,
.research-report .status-pill.c-of-o-issued,
.research-report .status-pill.certificate-of-occupancy {
    --pill: #b3cdab;
    --pill-rgb: 179, 205, 171;
}
/* Live / active (gold) */
.research-report .status-pill.open,
.research-report .status-pill.issued,
.research-report .status-pill.active,
.research-report .status-pill.approved {
    --pill: var(--accent-gold-light, #e4be6a);
    --pill-rgb: 228, 190, 106;
}
/* Administrative / recorded (terracotta) */
.research-report .status-pill.recorded,
.research-report .status-pill.granted,
.research-report .status-pill.amended,
.research-report .status-pill.reissued {
    --pill: var(--accent-terracotta-light, #d4956f);
    --pill-rgb: 212, 149, 111;
}
/* In process / awaiting action (slate-blue) */
.research-report .status-pill.pending,
.research-report .status-pill.submitted,
.research-report .status-pill.applied,
.research-report .status-pill.application-accepted,
.research-report .status-pill.in-review,
.research-report .status-pill.under-review,
.research-report .status-pill.plan-review,
.research-report .status-pill.review,
.research-report .status-pill.routing,
.research-report .status-pill.on-hold,
.research-report .status-pill.hold {
    --pill: #9fc0d8;
    --pill-rgb: 159, 192, 216;
}
/* Terminated unfavorably (muted red) */
.research-report .status-pill.expired,
.research-report .status-pill.void,
.research-report .status-pill.voided,
.research-report .status-pill.withdrawn,
.research-report .status-pill.denied,
.research-report .status-pill.revoked,
.research-report .status-pill.canceled,
.research-report .status-pill.cancelled,
.research-report .status-pill.rejected,
.research-report .status-pill.abandoned,
.research-report .status-pill.stop-work {
    --pill: #e29494;
    --pill-rgb: 226, 148, 148;
}

/* § 04 · Evidence — Full timeline */
.research-report .timeline-list {
    display: grid;
    gap: 0;
    position: relative;
}
.research-report .timeline-item {
    position: relative;
    padding: 1.1rem 0 1.1rem 2rem;
    scroll-margin-top: 2rem;
}
.research-report .timeline-item:first-child { padding-top: .25rem; }
.research-report .timeline-item + .timeline-item {
    border-top: 1px solid var(--border-subtle);
}
.research-report .timeline-item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 1.4rem;
    width: .6rem;
    height: .6rem;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--accent-gold, #d4a84b), var(--accent-terracotta));
    box-shadow: 0 0 0 3px var(--bg-paper);
    z-index: 1;
}
.research-report .timeline-item:first-child::before { top: .5rem; }
.research-report .timeline-item::after {
    content: "";
    position: absolute;
    left: .26rem;
    top: 0;
    bottom: 0;
    width: 1px;
    background: rgba(193, 127, 89, 0.18);
}
.research-report .timeline-item:first-child::after { top: .8rem; }
.research-report .timeline-item:last-child::after { bottom: 50%; }

.research-report .timeline-category {
    display: inline-block;
    font-family: "IBM Plex Mono", monospace;
    font-size: .64rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    padding: .22rem .5rem;
    border-radius: 3px;
    margin-bottom: .5rem;
}
.research-report .timeline-classifications {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    margin-bottom: .5rem;
}
.research-report .timeline-classifications .timeline-category {
    margin-bottom: 0;
}
.research-report .timeline-category.cat-construction {
    background: rgba(212, 168, 75, 0.1);
    color: var(--accent-gold, #d4a84b);
    border: 1px solid rgba(212, 168, 75, 0.25);
}
.research-report .timeline-category.cat-planning {
    background: rgba(193, 127, 89, 0.1);
    color: var(--accent-terracotta, #c17f59);
    border: 1px solid rgba(193, 127, 89, 0.25);
}
.research-report .timeline-category.cat-use_occupancy,
.research-report .timeline-category.cat-use-occupancy {
    background: rgba(125, 154, 125, 0.1);
    color: var(--accent-sage, #a8c4a0);
    border: 1px solid rgba(125, 154, 125, 0.25);
}
.research-report .timeline-category.cat-electrical,
.research-report .timeline-category.cat-hvac,
.research-report .timeline-category.cat-plumbing,
.research-report .timeline-category.cat-addition,
.research-report .timeline-category.cat-new-construction,
.research-report .timeline-category.cat-demolition,
.research-report .timeline-category.cat-roof,
.research-report .timeline-category.cat-interior-buildout,
.research-report .timeline-category.cat-sprinkler,
.research-report .timeline-category.cat-planning-zoning,
.research-report .timeline-category.cat-site-exterior,
.research-report .timeline-category.cat-septic-utility,
.research-report .timeline-category.cat-signage,
.research-report .timeline-category.cat-occupancy,
.research-report .timeline-category.cat-elevator {
    background: rgba(212, 168, 75, 0.1);
    color: var(--accent-gold, #d4a84b);
    border: 1px solid rgba(212, 168, 75, 0.25);
}
.research-report .timeline-category.cat-alarm {
    background: rgba(193, 127, 89, 0.12);
    color: var(--accent-terracotta, #c17f59);
    border: 1px solid rgba(193, 127, 89, 0.3);
}
.research-report .timeline-category.cat-solar {
    background: rgba(123, 158, 184, 0.12);
    color: var(--accent-info, #7b9eb8);
    border: 1px solid rgba(123, 158, 184, 0.3);
}
.research-report .timeline-category.cat-porch-deck-patio {
    background: rgba(125, 154, 125, 0.12);
    color: var(--accent-sage, #a8c4a0);
    border: 1px solid rgba(125, 154, 125, 0.3);
}

.research-report .timeline-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: .75rem;
}
.research-report .timeline-header > div {
    min-width: 0;
    flex: 1 1 0%;
}
.research-report .timeline-header strong {
    color: var(--text-primary);
    font-size: 1.05rem;
    display: block;
    font-family: "IBM Plex Mono", monospace;
    letter-spacing: .04em;
}
.research-report .timeline-copy {
    margin: .25rem 0 0;
    line-height: 1.6;
    color: var(--text-muted);
    font-size: .95rem;
}
.research-report p.timeline-copy {
    color: var(--text-body);
    margin-top: .5rem;
}
.research-report .timeline-systems {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin-top: .45rem;
}
.research-report .timeline-system-tag {
    display: inline-flex;
    align-items: center;
    padding: .12rem .5rem;
    border-radius: 4px;
    background: rgba(212, 168, 75, 0.10);
    border: 1px solid rgba(212, 168, 75, 0.28);
    color: var(--accent-gold, #d4a84b);
    font-family: "IBM Plex Mono", monospace;
    font-size: .7rem;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.research-report .timeline-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem .7rem;
    margin-top: .5rem;
    color: var(--text-muted);
    font-size: .88rem;
}
.research-report .timeline-meta a {
    color: var(--accent-terracotta);
    text-decoration: none;
}
.research-report .timeline-meta a:hover { text-decoration: underline; }
.research-report .timeline-source {
    padding-top: .4rem;
    border-top: 1px dashed rgba(193, 127, 89, 0.12);
    margin-top: .7rem;
}
.research-report .timeline-op-missing span {
    color: var(--text-muted);
    font-style: italic;
}
.research-report .confidence {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    color: var(--text-muted);
    letter-spacing: .04em;
}
.research-report .timeline-badge {
    flex-shrink: 0;
    max-width: 14rem;
    white-space: normal;
    text-align: right;
}

/* Methodology (collapsed) */
.research-report details.methodology {
    padding: 0;
}
.research-report details.methodology > summary {
    display: grid;
    grid-template-columns: 140px 1fr auto;
    gap: 1.5rem;
    align-items: center;
    padding: 1.25rem 2rem;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.research-report details.methodology > summary::-webkit-details-marker { display: none; }
.research-report details.methodology .methodology-title {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-size: 1.2rem;
    color: var(--text-primary);
    font-weight: 400;
}
.research-report details.methodology .methodology-chevron {
    font-family: "IBM Plex Mono", monospace;
    font-size: 1rem;
    color: var(--text-muted);
    transition: transform 0.2s ease;
}
.research-report details.methodology[open] .methodology-chevron { transform: rotate(180deg); }
.research-report .methodology-body {
    padding: .5rem 2rem 1.75rem;
    display: grid;
    gap: 1.5rem;
    border-top: 1px solid var(--border-subtle);
    padding-top: 1.5rem;
    margin-top: 0;
}
.research-report .methodology-section h4 {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--accent-gold, #d4a84b);
    margin: 0 0 .6rem;
    font-weight: 500;
}
.research-report .methodology-section p {
    color: var(--text-body);
    line-height: 1.65;
    font-family: "Source Serif 4", Georgia, serif;
    font-weight: 300;
    margin: 0 0 .5rem;
}
.research-report .method-source-list {
    display: grid;
    gap: 0;
}
.research-report .method-source-row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 0;
    border-top: 1px solid var(--border-subtle);
}
.research-report .method-source-row:first-child { border-top: 0; padding-top: .2rem; }
.research-report .method-source-row > div { min-width: 0; }
.research-report .method-source-row b {
    display: block;
    color: var(--text-primary);
    font-weight: 500;
    font-size: .95rem;
    margin-bottom: .15rem;
}
.research-report .method-source-row span {
    color: var(--text-muted);
    font-size: .88rem;
    display: block;
}
.research-report .method-source-error {
    color: var(--accent-terracotta, #c17f59);
    font-size: .85rem;
    margin-top: .2rem;
}
.research-report .method-source-row span.method-source-error {
    color: var(--accent-terracotta, #c17f59);
    font-size: .85rem;
}
.research-report .method-source-status {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    white-space: nowrap;
    padding: .3rem .6rem;
    border-radius: 999px;
    align-self: flex-start;
    border: 1px solid transparent;
}
.research-report .method-source-status.ok {
    background: rgba(125, 154, 125, 0.14);
    color: var(--accent-sage, #a8c4a0);
    border-color: rgba(125, 154, 125, 0.3);
}
.research-report .method-source-status.live {
    background: rgba(193, 127, 89, 0.12);
    color: var(--accent-terracotta, #c17f59);
    border-color: rgba(193, 127, 89, 0.25);
}
.research-report .method-source-status.fail {
    background: rgba(200, 80, 70, 0.12);
    color: #d4736a;
    border-color: rgba(200, 80, 70, 0.2);
}

/* Responsive */
@media (max-width: 960px) {
    .research-report .section-head { grid-template-columns: 1fr; gap: .4rem; }
}
@media (max-width: 640px) {
    .research-report { padding: 1.5rem 1rem 3rem; }
    .research-report .report-hero { padding: 1.75rem 1.5rem; border-radius: 12px; }
    .research-report .report-card { padding: 1.5rem 1.25rem; border-radius: 12px; }
    .research-report details.methodology > summary { padding: 1rem 1.25rem; grid-template-columns: 1fr auto; }
    .research-report details.methodology > summary .section-num { display: none; }
    .research-report .methodology-body { padding: 1rem 1.25rem 1.5rem; }
    .research-report .standout { grid-template-columns: 1fr; gap: .6rem; }
    .research-report .standout-tags { flex-direction: row; align-items: flex-start; }
    .research-report .timeline-header { flex-direction: column; gap: .4rem; }
    .research-report .timeline-badge { align-self: flex-start; }
    .research-report .report-actions { flex-direction: column; }
    .research-report .report-actions .btn { width: 100%; }
    .research-report .project-head { flex-direction: column; align-items: flex-start; }
    .research-report .flags-strip { grid-template-columns: 1fr; padding: .5rem 0; }
    .research-report .flag-item { border-left: 0; border-top: 1px solid var(--border-subtle); padding: .9rem 0 .6rem; }
    .research-report .flag-item:first-child { border-top: 0; padding-top: .4rem; }
    .research-report .systems-matrix-head { display: none; }
    .research-report .system-row {
        grid-template-columns: 1fr auto;
        row-gap: .3rem;
        padding: .9rem 1rem;
    }
    .research-report .system-row .system-count { justify-self: end; }
    .research-report .system-row .system-year { justify-self: end; }
    .research-report .system-row .system-status,
    .research-report .system-row .system-permit {
        grid-column: 1 / -1;
    }
    .research-report .system-row.empty .system-empty { grid-column: 1 / -1; }
    .research-report .systems-matrix-footer {
        font-size: .68rem;
    }
    .research-report .coverage-table-head { display: none; }
    .research-report .coverage-row {
        grid-template-columns: 1fr auto;
        row-gap: .3rem;
        padding: .9rem 1rem;
    }
    .research-report .coverage-row .coverage-asof {
        grid-column: 1 / -1;
    }
    /* Desktop has a column header; stacked mobile rows need the label inline. */
    .research-report .coverage-row .coverage-asof::before {
        content: "Records as of ";
        color: var(--text-muted);
    }
}

/* ==========================================================================
   Research Search (research/search.html) — address entry + coverage preview
   Scoped under .research-shell.
   ========================================================================== */

.research-shell {
    max-width: 880px;
    margin: 0 auto;
    padding: 6rem 1.5rem 6rem;
    color: var(--text-body);
}

.research-shell .research-spotlight {
    position: relative;
    text-align: center;
}
.research-shell .research-spotlight::before {
    content: "";
    position: absolute;
    top: 28%;
    left: 50%;
    width: 760px;
    height: 760px;
    max-width: 120vw;
    max-height: 120vw;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(193, 127, 89, 0.09) 0%, rgba(193, 127, 89, 0.03) 35%, transparent 65%);
    pointer-events: none;
    z-index: 0;
}
.research-shell .research-spotlight > * {
    position: relative;
    z-index: 1;
}

.research-shell .research-eyebrow {
    font-family: "IBM Plex Mono", monospace;
    letter-spacing: .22em;
    font-size: .78rem;
    text-transform: uppercase;
    color: var(--accent-terracotta);
    margin: 0 0 1.25rem;
}

.research-shell .research-headline {
    font-family: "Playfair Display", serif;
    font-size: clamp(2.4rem, 5.5vw, 4.25rem);
    line-height: 1.04;
    letter-spacing: -0.01em;
    margin: 0 auto 2.75rem;
    max-width: 18ch;
    color: var(--text-primary);
}

.research-shell .research-search-form {
    position: relative;
    max-width: 680px;
    margin: 0 auto;
}
.research-shell .research-search-form input[type="text"] {
    width: 100%;
    border-radius: 999px;
    border: 1px solid var(--border-medium);
    background: var(--bg-paper);
    color: var(--text-primary);
    padding: 1.25rem 4.5rem 1.25rem 1.85rem;
    margin: 0;
    font-size: 1.15rem;
    font-family: "Crimson Pro", serif;
    transition: border-color 0.25s, background 0.25s, box-shadow 0.25s;
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.22);
}
.research-shell .research-search-form input::placeholder { color: var(--text-faint); }
.research-shell .research-search-form input:focus {
    outline: none;
    border-color: var(--accent-terracotta);
    background: var(--bg-elevated);
    box-shadow:
        0 0 0 4px rgba(193, 127, 89, 0.18),
        0 8px 32px rgba(0, 0, 0, 0.28);
}

.research-shell .research-search-submit {
    position: absolute;
    top: 50%;
    right: .55rem;
    transform: translateY(-50%);
    width: 3rem;
    height: 3rem;
    border-radius: 999px;
    border: 0;
    background: var(--accent-terracotta);
    color: #0d0c0b;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.research-shell .research-search-submit:hover {
    background: var(--accent-gold, #d4a84b);
    transform: translateY(-50%) translateX(2px);
    box-shadow: 0 4px 14px rgba(212, 168, 75, 0.35);
}
.research-shell .research-search-submit:focus-visible {
    outline: 2px solid var(--accent-gold, #d4a84b);
    outline-offset: 3px;
}
.research-shell .research-search-submit svg {
    width: 1.15rem;
    height: 1.15rem;
}

.research-shell .research-pills {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin: 2rem 0 0;
    font-family: "IBM Plex Mono", monospace;
    font-size: .76rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-shell .research-pills span { position: relative; }
.research-shell .research-pills span + span::before {
    content: "·";
    position: absolute;
    left: -.95rem;
    color: var(--accent-terracotta);
    font-weight: 700;
}

.research-shell .research-coverage-note {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: .45rem .9rem;
    margin-top: .85rem;
    font-size: .78rem;
    color: var(--text-muted);
}

.research-shell .research-coverage-note strong {
    color: var(--text-body);
    font-weight: 500;
}

.research-shell .research-jurisdiction-muted {
    opacity: .75;
}

.research-shell .research-preview {
    max-width: 680px;
    margin: 2.75rem auto 0;
    text-align: left;
}
.research-shell .research-preview:empty {
    display: none;
}
.research-shell .research-preview-card,
.research-shell .research-preview-empty {
    background: var(--bg-paper);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    animation: researchPreviewIn 0.35s cubic-bezier(.2, .65, .3, 1) both;
}
.research-shell .research-preview-card {
    padding: 1.5rem 1.75rem;
}
.research-shell .research-preview-empty {
    color: var(--text-muted);
    font-size: .92rem;
    line-height: 1.55;
    padding: 1.15rem 1.5rem;
    text-align: center;
    border-style: dashed;
}
.research-shell .research-preview-header {
    font-family: "IBM Plex Mono", monospace;
    text-transform: uppercase;
    letter-spacing: .18em;
    font-size: .72rem;
    color: var(--accent-terracotta);
    margin-bottom: .9rem;
}
.research-shell .research-jurisdictions {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}
.research-shell .research-jurisdiction {
    border-radius: 999px;
    padding: .45rem .85rem;
    background: rgba(193, 127, 89, 0.1);
    border: 1px solid rgba(193, 127, 89, 0.22);
    font-size: .85rem;
    color: var(--text-body);
}
.research-shell .research-preview-note {
    margin-top: 1rem;
    padding-top: .85rem;
    border-top: 1px solid var(--border-subtle);
    font-size: .85rem;
    color: var(--text-muted);
    line-height: 1.55;
}

@keyframes researchPreviewIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 640px) {
    .research-shell { padding: 3.5rem 1rem 4rem; }
    .research-shell .research-headline { margin-bottom: 2rem; }
    .research-shell .research-search-form input[type="text"] {
        padding: 1rem 3.75rem 1rem 1.35rem;
        font-size: 1rem;
    }
    .research-shell .research-search-submit {
        width: 2.5rem;
        height: 2.5rem;
        right: .4rem;
    }
    .research-shell .research-pills {
        gap: 1.1rem;
        font-size: .7rem;
    }
    .research-shell .research-pills span + span::before { left: -.7rem; }
}

@media (prefers-reduced-motion: reduce) {
    .research-shell .research-preview-card,
    .research-shell .research-preview-empty { animation: none; }
}

/* ==========================================================================
   Research Confirm (research/confirm.html) — coverage confirm before checkout
   Scoped under .research-confirm.
   ========================================================================== */

.research-confirm {
    max-width: 1040px;
    margin: 0 auto;
    padding: 4.5rem 1.25rem 5rem;
    color: var(--text-body);
}
.research-confirm .confirm-spotlight {
    position: relative;
    display: grid;
    gap: 1.35rem;
}
.research-confirm .confirm-spotlight::before {
    content: "";
    position: absolute;
    top: 2rem;
    left: 50%;
    width: 760px;
    height: 760px;
    max-width: 120vw;
    max-height: 120vw;
    transform: translateX(-50%);
    background: radial-gradient(circle, rgba(193, 127, 89, 0.08) 0%, rgba(193, 127, 89, 0.025) 38%, transparent 66%);
    pointer-events: none;
    z-index: 0;
}
.research-confirm .confirm-spotlight > * {
    position: relative;
    z-index: 1;
}
.research-confirm .confirm-eyebrow,
.research-confirm .confirm-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
}
.research-confirm .confirm-eyebrow {
    color: var(--accent-terracotta);
    text-align: center;
}
.research-confirm h1 {
    max-width: 14ch;
    margin: 0 auto .6rem;
    text-align: center;
    font-family: "Playfair Display", serif;
    font-weight: 500;
    font-size: clamp(2.4rem, 5.4vw, 4rem);
    line-height: 1.03;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}
.research-confirm .confirm-address-bar {
    max-width: 760px;
    width: 100%;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    padding: 1.05rem 1.15rem 1.05rem 1.5rem;
    border: 1px solid var(--border-medium);
    border-radius: 999px;
    background: var(--bg-paper);
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.22);
}
.research-confirm .confirm-address-bar div {
    min-width: 0;
    display: grid;
    gap: .18rem;
}
.research-confirm .confirm-address-bar strong {
    overflow-wrap: anywhere;
    color: var(--text-primary);
    font-size: 1.08rem;
    line-height: 1.25;
}
.research-confirm .confirm-address-bar span:not(.confirm-label) {
    color: var(--text-muted);
    font-size: .92rem;
    line-height: 1.25;
}
.research-confirm .confirm-label {
    color: var(--text-muted);
}
.research-confirm .confirm-edit-link {
    flex: 0 0 auto;
    min-width: 3rem;
    height: 3rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 .9rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.research-confirm .confirm-edit-link:hover {
    border-color: var(--accent-terracotta);
    color: var(--accent-terracotta-light);
}
.research-confirm .confirm-metrics,
.research-confirm .confirm-message-strip {
    max-width: 760px;
    width: 100%;
    margin: .2rem auto 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    border-top: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
}
.research-confirm .confirm-metrics div,
.research-confirm .confirm-message-strip span {
    min-width: 0;
    padding: 1rem 1.1rem;
    text-align: center;
    border-left: 1px solid var(--border-subtle);
}
.research-confirm .confirm-metrics div:first-child,
.research-confirm .confirm-message-strip span:first-child {
    border-left: 0;
}
.research-confirm .confirm-metrics span,
.research-confirm .confirm-message-strip span {
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-confirm .confirm-metrics strong {
    display: block;
    margin-top: .25rem;
    color: var(--text-primary);
    font-size: 1.15rem;
    line-height: 1.15;
}
.research-confirm .confirm-layout {
    display: grid;
    grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr);
    gap: 1.15rem;
    align-items: stretch;
    margin-top: .7rem;
}
.research-confirm .confirm-action-panel,
.research-confirm .confirm-coverage-panel {
    background: var(--bg-paper);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: 1.5rem;
    box-shadow: var(--shadow-md);
    overflow: hidden;
}
.research-confirm .confirm-action-panel {
    background:
        radial-gradient(ellipse at top right, rgba(193, 127, 89, 0.08) 0%, transparent 52%),
        var(--bg-paper);
}
.research-confirm .confirm-plan-badge {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    min-height: 1.65rem;
    padding: .35rem .6rem;
    border-radius: 999px;
    background: rgba(125, 154, 125, 0.14);
    border: 1px solid rgba(125, 154, 125, 0.28);
    color: var(--accent-sage);
    font-family: "IBM Plex Mono", monospace;
    font-size: .66rem;
    letter-spacing: .12em;
    text-transform: uppercase;
}
.research-confirm .confirm-plan-badge-muted {
    background: rgba(212, 168, 75, 0.12);
    border-color: rgba(212, 168, 75, 0.26);
    color: var(--accent-gold);
}
.research-confirm .confirm-plan-badge-warning {
    background: rgba(199, 91, 91, 0.12);
    border-color: rgba(199, 91, 91, 0.28);
    color: var(--color-error);
}
.research-confirm .confirm-action-panel h2 {
    margin: .85rem 0 .6rem;
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    line-height: 1.12;
}
.research-confirm .confirm-action-panel p {
    margin: 0;
    color: var(--text-body);
    line-height: 1.55;
}
.research-confirm .confirm-actions {
    display: grid;
    margin-top: 1.25rem;
}
.research-confirm .confirm-actions .btn,
.research-confirm .confirm-choice .btn {
    width: 100%;
}
.research-confirm .confirm-note {
    margin-top: .9rem;
    color: var(--text-muted);
    font-size: .9rem;
    line-height: 1.45;
}
/* Sign-in-wrap Terms notice under every purchase button (confirm + resume). */
.research-confirm .confirm-tos-note,
.research-payment-pending .confirm-tos-note {
    display: block;
    margin-top: .55rem;
    color: var(--text-faint, var(--text-muted));
    font-size: .78rem;
    line-height: 1.4;
}
.research-confirm .confirm-tos-note a,
.research-payment-pending .confirm-tos-note a {
    color: var(--text-muted);
    text-decoration: underline;
}
.research-confirm .confirm-tos-note a:hover,
.research-payment-pending .confirm-tos-note a:hover {
    color: var(--accent-terracotta-light, var(--accent-terracotta));
}
.research-confirm .confirm-choice-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .8rem;
    margin-top: 1.25rem;
}
.research-confirm .confirm-choice {
    min-width: 0;
    display: grid;
    gap: .55rem;
    align-content: start;
    padding: 1rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
}
.research-confirm .confirm-choice span,
.research-confirm .confirm-choice em {
    color: var(--text-muted);
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-style: normal;
    line-height: 1.35;
}
.research-confirm .confirm-choice strong {
    color: var(--text-primary);
    font-size: 1.5rem;
    line-height: 1;
}
.research-confirm .confirm-choice-link {
    color: inherit;
    text-decoration: none;
    transition: border-color .2s ease, background .2s ease, transform .2s ease;
}
.research-confirm .confirm-choice-link:hover {
    border-color: var(--accent-terracotta);
    background: var(--bg-hover);
    transform: translateY(-2px);
}
.research-confirm .confirm-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: .9rem;
    border-bottom: 1px solid var(--border-subtle);
}
.research-confirm .confirm-panel-head .confirm-eyebrow {
    text-align: left;
    color: var(--text-muted);
}
.research-confirm .confirm-panel-head strong {
    color: var(--accent-gold);
    font-family: "IBM Plex Mono", monospace;
    font-size: 1rem;
}
.research-confirm .confirm-coverage-list {
    display: grid;
    gap: 0;
}
.research-confirm .confirm-source-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: .85rem;
    align-items: center;
    padding: .85rem 0;
    border-bottom: 1px solid var(--border-subtle);
}
.research-confirm .confirm-source-row span {
    min-width: 0;
    color: var(--text-primary);
    line-height: 1.25;
}
.research-confirm .confirm-source-row em {
    border-radius: 999px;
    padding: .32rem .58rem;
    background: rgba(193, 127, 89, 0.1);
    border: 1px solid rgba(193, 127, 89, 0.2);
    color: var(--accent-terracotta-light);
    font-family: "IBM Plex Mono", monospace;
    font-size: .66rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    font-style: normal;
    white-space: nowrap;
}
.research-confirm .confirm-next-steps {
    display: grid;
    gap: .75rem;
    margin-top: 1rem;
}
.research-confirm .confirm-next-steps div {
    display: grid;
    grid-template-columns: 5.5rem minmax(0, 1fr);
    gap: .85rem;
    align-items: baseline;
}
.research-confirm .confirm-next-steps strong {
    color: var(--accent-gold);
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
}
.research-confirm .confirm-next-steps span {
    color: var(--text-muted);
    line-height: 1.35;
}
.research-confirm .confirm-short-copy {
    max-width: 680px;
    margin: .25rem auto 0;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.55;
}
.research-confirm .confirm-actions-inline {
    display: flex;
    justify-content: center;
}
.research-confirm .confirm-spotlight-uncovered h1 {
    max-width: 15ch;
}

@media (max-width: 920px) {
    .research-confirm {
        padding-top: 3.5rem;
    }
    .research-confirm .confirm-layout,
    .research-confirm .confirm-choice-grid {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 640px) {
    .research-confirm {
        padding: 3rem 1rem 4rem;
    }
    .research-confirm h1 {
        max-width: 12ch;
    }
    .research-confirm .confirm-address-bar {
        align-items: stretch;
        border-radius: 18px;
        flex-direction: column;
        padding: 1rem;
    }
    .research-confirm .confirm-edit-link {
        width: 100%;
    }
    .research-confirm .confirm-metrics,
    .research-confirm .confirm-message-strip {
        grid-template-columns: 1fr;
    }
    .research-confirm .confirm-metrics div,
    .research-confirm .confirm-message-strip span {
        border-left: 0;
        border-top: 1px solid var(--border-subtle);
    }
    .research-confirm .confirm-metrics div:first-child,
    .research-confirm .confirm-message-strip span:first-child {
        border-top: 0;
    }
    .research-confirm .confirm-source-row {
        grid-template-columns: 1fr;
        gap: .5rem;
    }
    .research-confirm .confirm-source-row em {
        width: fit-content;
        white-space: normal;
    }
    .research-confirm .confirm-next-steps div {
        grid-template-columns: 1fr;
        gap: .25rem;
    }
}

/* ==========================================================================
   Research Payment Pending (research/payment_pending.html) — calm
   resume-checkout page shown when a request is left at PENDING_PAYMENT.
   Scoped under .research-payment-pending; reuses confirm-spotlight tokens.
   ========================================================================== */

.research-payment-pending {
    max-width: 640px;
    margin: 0 auto;
    padding: 5rem 1.25rem 5.5rem;
    color: var(--text-body);
}
.research-payment-pending .pending-spotlight {
    position: relative;
    display: grid;
    gap: 1.35rem;
    text-align: center;
}
.research-payment-pending .pending-spotlight::before {
    content: "";
    position: absolute;
    top: 1rem;
    left: 50%;
    width: 620px;
    height: 620px;
    max-width: 120vw;
    max-height: 120vw;
    transform: translateX(-50%);
    background: radial-gradient(circle, rgba(193, 127, 89, 0.08) 0%, rgba(193, 127, 89, 0.025) 38%, transparent 66%);
    pointer-events: none;
    z-index: 0;
}
.research-payment-pending .pending-spotlight > * {
    position: relative;
    z-index: 1;
}
.research-payment-pending .pending-eyebrow {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--accent-terracotta);
}
.research-payment-pending h1 {
    max-width: 16ch;
    margin: 0 auto .4rem;
    font-family: "Playfair Display", serif;
    font-weight: 500;
    font-size: clamp(2.1rem, 4.8vw, 3.2rem);
    line-height: 1.05;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}
.research-payment-pending .pending-address-bar {
    display: grid;
    gap: .25rem;
    justify-items: center;
    margin: 0 auto;
    padding: 1rem 1.5rem;
    border: 1px solid var(--border-medium);
    border-radius: 14px;
    background: var(--bg-paper);
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.22);
}
.research-payment-pending .pending-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-payment-pending .pending-address-bar strong {
    overflow-wrap: anywhere;
    color: var(--text-primary);
    font-size: 1.08rem;
    line-height: 1.25;
}
.research-payment-pending .pending-copy {
    max-width: 46ch;
    margin: 0 auto;
    color: var(--text-muted);
    line-height: 1.6;
}
.research-payment-pending .pending-actions {
    display: grid;
    justify-items: center;
    gap: .85rem;
    margin: .4rem 0 0;
}
.research-payment-pending .pending-actions .btn {
    min-width: 220px;
}
.research-payment-pending .pending-back-link {
    font-family: "IBM Plex Mono", monospace;
    font-size: .74rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.research-payment-pending .pending-back-link:hover {
    color: var(--accent-terracotta-light);
}
.research-payment-pending .pending-note {
    max-width: 44ch;
    margin: .4rem auto 0;
    font-size: .88rem;
    color: var(--text-muted);
}

/* ==========================================================================
   Research Status (research/status.html) — "Records sweep" redesign.
   All rules scoped under .research-status to avoid collisions with
   dashboard / report styles. Local CSS vars live on the wrapper.
   ========================================================================== */

.research-status {
    --status-ink: #f5ede3;
    --status-muted: rgba(245, 237, 227, 0.7);
    --status-gold: #d7ab5d;
    --status-amber: #c26a34;
    --status-bg: #120f0d;
    --status-line: rgba(255,255,255,0.09);
    max-width: 1040px;
    margin: 0 auto;
    padding: 2.6rem 1.25rem 4rem;
    display: grid;
    gap: 1.75rem;
}

/* ── Zone 1 · Masthead ───────────────────────────────────────────────── */
.research-status .sweep-masthead {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(circle at 85% 12%, rgba(215, 171, 93, 0.18), transparent 42%),
        radial-gradient(circle at 10% 88%, rgba(194, 106, 52, 0.14), transparent 48%),
        linear-gradient(145deg, #120f0d 0%, #201712 46%, #140f0d 100%);
    color: var(--status-ink);
    border-radius: 24px;
    padding: 2.2rem 2.2rem 1.6rem;
    border: 1px solid rgba(255,255,255,.06);
    box-shadow: var(--shadow-md);
}
.research-status .sweep-eyebrow {
    font-family: "IBM Plex Mono", monospace;
    letter-spacing: .22em;
    text-transform: uppercase;
    font-size: .72rem;
    color: var(--status-gold);
    margin: 0 0 1rem;
    display: flex;
    align-items: center;
    gap: .85rem;
}
.research-status .sweep-eyebrow::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, rgba(215,171,93,0.35), transparent);
}
.research-status .sweep-address {
    font-family: "Playfair Display", "Source Serif 4", Georgia, serif;
    font-weight: 400;
    font-size: clamp(1.9rem, 4.2vw, 3rem);
    line-height: 1.04;
    letter-spacing: -0.02em;
    margin: 0 0 .9rem;
    word-break: break-word;
    text-wrap: balance;
    max-width: 22ch;
}
.research-status .sweep-narrative {
    color: var(--status-muted);
    font-size: 1.04rem;
    line-height: 1.55;
    margin: 0 0 1.2rem;
    max-width: 46rem;
}
.research-status .sweep-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .55rem 0;
    padding-top: .85rem;
    border-top: 1px solid rgba(255,255,255,0.06);
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--status-muted);
}
.research-status .sweep-meta-sep { color: rgba(245,237,227,0.25); margin: 0 .85rem; }
.research-status .sweep-meta-item { white-space: nowrap; }
.research-status .sweep-meta-link {
    color: var(--status-gold);
    text-decoration: none;
    border-bottom: 1px dashed rgba(215,171,93,0.35);
    padding-bottom: 1px;
    transition: color .15s ease, border-color .15s ease;
}
.research-status .sweep-meta-link:hover {
    color: #f1c679;
    border-bottom-color: #f1c679;
}
.research-status .sweep-chip {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem .65rem;
    border-radius: 999px;
    background: rgba(215,171,93,0.1);
    color: var(--status-gold);
    white-space: nowrap;
}
.research-status .sweep-chip-pulse {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--status-gold);
    animation: sweepChipPulse 2s ease-in-out infinite;
}
@keyframes sweepChipPulse {
    0%, 100% { opacity: 0.5; transform: scale(1); }
    50%      { opacity: 1;   transform: scale(1.25); }
}
.research-status .sweep-elapsed {
    display: inline-flex;
    align-items: baseline;
    gap: .45rem;
    margin-left: auto;
    color: rgba(245,237,227,0.55);
    font-feature-settings: "tnum" 1;
    white-space: nowrap;
}
.research-status .sweep-elapsed-label { font-size: .68rem; }
.research-status .sweep-elapsed-value { font-size: .88rem; color: var(--status-ink); }

/* ── Zone 2 · Scanner illustration ───────────────────────────────────── */
.research-status .sweep-scanner {
    position: relative;
    background: linear-gradient(160deg, #0f0d0b 0%, #1a1311 100%);
    border: 1px solid rgba(255,255,255,0.06);
    border-radius: 20px;
    padding: 1.5rem;
    color: var(--status-muted);
    overflow: hidden;
}
/* Field log inside the case file — see _svg.html .scan-cf-log.
   Three SVG <g> rows; JS rewrites textContent and toggles is-fresh on
   the bottom row when a new entry lands. Opacity ladder gives reading
   order (oldest dim, newest bright). */
.research-status .scan-cf-log-row { opacity: 0; transition: opacity .35s ease; }
.research-status .scan-cf-log-row[data-row="0"].has-entry { opacity: .38; }
.research-status .scan-cf-log-row[data-row="1"].has-entry { opacity: .68; }
.research-status .scan-cf-log-row[data-row="2"].has-entry { opacity: 1; }
.research-status .scan-cf-log-row.is-fresh .scan-cf-log-verb {
    animation: scanLogInk .55s ease-out;
}
.research-status .scan-cf-log-row.kind-filed .scan-cf-log-bullet,
.research-status .scan-cf-log-row.kind-done-success .scan-cf-log-bullet { fill: #7d9a7d; }
.research-status .scan-cf-log-row.kind-failed .scan-cf-log-bullet,
.research-status .scan-cf-log-row.kind-done-fail .scan-cf-log-bullet { fill: #c17f59; }
.research-status .scan-cf-log-row.kind-done-success .scan-cf-log-verb { fill: #cfe0cf; }
@keyframes scanLogInk {
    0%   { opacity: 0.15; }
    40%  { opacity: 1;    }
    100% { opacity: 1;    }
}
.research-status .sweep-scanner svg.scanner-svg {
    display: block;
    width: 100%;
    height: auto;
}

/* ── Hero illustration choreography ──────────────────────────────────── */
/* All elements scoped under .research-status .scanner-svg so the rules
   never collide with the landing page's hero_building animations. */

/* Generic stroke-reveal pattern with five staggered delay tiers. */
.research-status .scanner-svg .scan-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: scanDrawPath 1.6s ease-out forwards;
}
.research-status .scanner-svg .scan-d1 { animation-delay: 0.2s; }
.research-status .scanner-svg .scan-d2 { animation-delay: 0.6s; }
.research-status .scanner-svg .scan-d3 { animation-delay: 1.1s; }
.research-status .scanner-svg .scan-d4 { animation-delay: 1.7s; }
.research-status .scanner-svg .scan-d5 { animation-delay: 2.4s; }
@keyframes scanDrawPath { to { stroke-dashoffset: 0; } }

/* Sun rays — slow continuous rotation around the disc at (420, 50). */
.research-status .scanner-svg .scan-sun-rays {
    transform-box: fill-box;
    transform-origin: center;
    animation: scanSunRotate 36s linear infinite;
}
@keyframes scanSunRotate { to { transform: rotate(360deg); } }

/* Antenna light — gentle pulse. */
.research-status .scanner-svg .scan-antenna-light {
    animation: scanAntennaPulse 4s ease-in-out infinite;
    animation-delay: 3.2s;
    transform-origin: center;
    transform-box: fill-box;
}
@keyframes scanAntennaPulse {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 1; }
}

/* Chimney smoke wisps — fade in, drift up, fade out. */
.research-status .scanner-svg .scan-smoke {
    transform-box: fill-box;
    transform-origin: bottom center;
}
.research-status .scanner-svg .scan-smoke-1 {
    animation: scanSmokeRise 9s 4.5s ease-in-out infinite;
}
.research-status .scanner-svg .scan-smoke-2 {
    animation: scanSmokeRise 9s 7s ease-in-out infinite;
}
@keyframes scanSmokeRise {
    0%   { opacity: 0; transform: translateY(4px) scale(0.85); }
    20%  { opacity: 0.32; }
    65%  { opacity: 0.22; }
    100% { opacity: 0; transform: translateY(-22px) scale(1.25); }
}

/* Windows are dark by default. They light up only when their
   corresponding scanner returns successfully (.is-lit applied by JS).
   The metaphor: we don't see records inside the property until
   investigators report back. */
.research-status .scanner-svg .scan-window {
    fill: rgba(255,255,255,0.04);
    opacity: 1;
}
.research-status .scanner-svg .scan-window-sweep {
    opacity: 0;
    transform-box: fill-box;
    transform-origin: center;
    pointer-events: none;
}
.research-status .scanner-svg .scan-window-sweep.is-scanning {
    animation: scanWindowSweep 1.15s ease-in-out infinite;
}
.research-status .scanner-svg .scan-window.is-lit {
    animation: scanWindowAppear 0.55s ease-out forwards,
               scanWindowGlow 5.5s 0.6s ease-in-out infinite;
}
.research-status .scanner-svg .scan-window.is-lit-cached {
    /* Cached windows light up sage to differentiate from scraped */
    animation: scanWindowAppearCached 0.55s ease-out forwards,
               scanWindowGlowCached 5.5s 0.6s ease-in-out infinite;
}
@keyframes scanWindowAppear {
    0%   { fill: rgba(255,255,255,0.04); }
    35%  { fill: rgba(255,225,140,1); }
    100% { fill: rgba(225,180,90,0.85); }
}
@keyframes scanWindowGlow {
    0%, 100% { fill: rgba(225,180,90,0.7); }
    50%      { fill: rgba(255,215,120,0.95); }
}
@keyframes scanWindowAppearCached {
    0%   { fill: rgba(255,255,255,0.04); }
    35%  { fill: rgba(190,220,180,1); }
    100% { fill: rgba(150,180,140,0.78); }
}
@keyframes scanWindowGlowCached {
    0%, 100% { fill: rgba(150,180,140,0.6); }
    50%      { fill: rgba(190,220,180,0.85); }
}
@keyframes scanWindowSweep {
    0%   { opacity: 0; transform: translateX(0); }
    18%  { opacity: 0.85; }
    74%  { opacity: 0.55; }
    100% { opacity: 0; transform: translateX(34px); }
}

/* Birds — occasional crossings with long dwell offsets so they don't
   feel like a metronome. */
.research-status .scanner-svg .scan-bird {
    opacity: 0;
    transform-box: fill-box;
    transform-origin: 0 0;
}
.research-status .scanner-svg .scan-bird-1 {
    animation: scanBirdFly1 14s 6.5s ease-in-out infinite;
}
.research-status .scanner-svg .scan-bird-2 {
    animation: scanBirdFly2 18s 12s ease-in-out infinite;
}
@keyframes scanBirdFly1 {
    0%   { opacity: 0; transform: translate(-30px, 35px); }
    10%  { opacity: 0.7; }
    90%  { opacity: 0.7; }
    100% { opacity: 0; transform: translate(510px, 55px); }
}
@keyframes scanBirdFly2 {
    0%   { opacity: 0; transform: translate(510px, 95px); }
    10%  { opacity: 0.55; }
    90%  { opacity: 0.55; }
    100% { opacity: 0; transform: translate(-30px, 75px); }
}

/* ── Case file label + address stamp ────────────────────────────────── */
.research-status .scanner-svg .scan-cf-label-eyebrow {
    opacity: 0;
    animation: scanFadeIn 0.5s 1.7s ease-out forwards;
}
.research-status .scanner-svg .scan-cf-tab-label {
    opacity: 0;
    animation: scanFadeIn 0.5s 1.5s ease-out forwards;
}
.research-status .scanner-svg .scan-cf-address-text {
    opacity: 0;
    /* "Stamp" effect: scale down briefly for the impact, then settle. */
    transform-origin: center;
    transform-box: fill-box;
    animation: scanAddressStamp 0.55s 2.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes scanFadeIn { to { opacity: 0.85; } }
@keyframes scanAddressStamp {
    0%   { opacity: 0; transform: scale(1.6); }
    40%  { opacity: 1; transform: scale(0.94); }
    70%  { transform: scale(1.02); }
    100% { opacity: 1; transform: scale(1); }
}

/* ── Scanner slot architecture ──────────────────────────────────────── */
/*
 * Each <g class="scan-slot"> represents one investigator agent dispatched
 * to the property on behalf of the user. Position is controlled by a
 * transform on the slot itself, with the agent + return-doc as children
 * positioned at (0,0) inside the slot. The slot's transform thus
 * positions both elements simultaneously.
 *
 * Route geometry is emitted by the SVG macro as CSS custom properties so
 * the same keyframes can drive every jurisdiction/window pairing.
 *
 * State classes on the slot drive the return phase:
 *   .state-scraped  — scanner returns trailing a permit document (gold)
 *   .state-empty    — scanner returns a neutral "checked" slip, no permit
 *   .state-cached   — same path, but faster + sage-tinted (we already had it)
 *   .state-failed   — scanner fades at property, no return
 */
.research-status .scanner-svg .scan-slot {
    --start-x: 470px;
    --start-y: 215px;
    --dispatch-delay: 3.6s;
    --target-x: 135px;
    --target-y: 161px;
    --out1-x: 300px;
    --out1-y: 148px;
    --out2-x: 188px;
    --out2-y: 132px;
    --ret1-x: 275px;
    --ret1-y: 137px;
    --ret2-x: 406px;
    --ret2-y: 184px;
    --file-x: 464px;
    --file-y: 208px;
    transform-box: fill-box;
    transform-origin: 0 0;
    opacity: 0;
    /* Default position before dispatch: at the case file. The dispatch
       animation overrides this, but the fallback keeps the agent from
       rendering at the SVG origin if the dispatch animation hasn't fired. */
    transform: translate(var(--start-x), var(--start-y));
    animation: scanDispatch 1.4s var(--dispatch-delay) cubic-bezier(0.4, 0, 0.6, 1) forwards;
}

/*
 * Per-slot-index route geometry. This is a STATIC lookup table — it mirrors
 * `_slot_targets` in app/templates/_svg.html, indexed by data-slot-index, and
 * the dispatch delay is 3.6s + index*0.3s. It lives here (not in an inline
 * style="--var: ..." attribute on the slot) because the production CSP gives
 * style-src a nonce but no 'unsafe-inline', and nonces don't apply to inline
 * style attributes — so an inline style would be dropped, collapsing every
 * slot onto the index-0 default above. If _slot_targets changes, update these
 * rules in lockstep. Indices 0–5 cover the max 6 rendered slots.
 */
.research-status .scanner-svg .scan-slot[data-slot-index="0"] {
    --dispatch-delay: 3.6s;
    --target-x: 135px; --target-y: 161px;
    --out1-x: 300px;   --out1-y: 148px;
    --out2-x: 188px;   --out2-y: 132px;
    --ret1-x: 275px;   --ret1-y: 137px;
    --ret2-x: 406px;   --ret2-y: 184px;
    --file-x: 464px;   --file-y: 208px;
}
.research-status .scanner-svg .scan-slot[data-slot-index="1"] {
    --dispatch-delay: 3.9s;
    --target-x: 245px; --target-y: 161px;
    --out1-x: 356px;   --out1-y: 146px;
    --out2-x: 280px;   --out2-y: 135px;
    --ret1-x: 335px;   --ret1-y: 134px;
    --ret2-x: 432px;   --ret2-y: 186px;
    --file-x: 474px;   --file-y: 208px;
}
.research-status .scanner-svg .scan-slot[data-slot-index="2"] {
    --dispatch-delay: 4.2s;
    --target-x: 135px; --target-y: 207px;
    --out1-x: 305px;   --out1-y: 176px;
    --out2-x: 190px;   --out2-y: 184px;
    --ret1-x: 276px;   --ret1-y: 174px;
    --ret2-x: 412px;   --ret2-y: 197px;
    --file-x: 469px;   --file-y: 211px;
}
.research-status .scanner-svg .scan-slot[data-slot-index="3"] {
    --dispatch-delay: 4.5s;
    --target-x: 165px; --target-y: 161px;
    --out1-x: 322px;   --out1-y: 142px;
    --out2-x: 220px;   --out2-y: 130px;
    --ret1-x: 292px;   --ret1-y: 138px;
    --ret2-x: 420px;   --ret2-y: 184px;
    --file-x: 454px;   --file-y: 211px;
}
.research-status .scanner-svg .scan-slot[data-slot-index="4"] {
    --dispatch-delay: 4.8s;
    --target-x: 215px; --target-y: 161px;
    --out1-x: 346px;   --out1-y: 145px;
    --out2-x: 258px;   --out2-y: 132px;
    --ret1-x: 320px;   --ret1-y: 136px;
    --ret2-x: 430px;   --ret2-y: 188px;
    --file-x: 484px;   --file-y: 211px;
}
.research-status .scanner-svg .scan-slot[data-slot-index="5"] {
    --dispatch-delay: 5.1s;
    --target-x: 245px; --target-y: 207px;
    --out1-x: 360px;   --out1-y: 180px;
    --out2-x: 282px;   --out2-y: 186px;
    --ret1-x: 336px;   --ret1-y: 176px;
    --ret2-x: 432px;   --ret2-y: 200px;
    --file-x: 491px;   --file-y: 213px;
}

.research-status .scanner-svg .scan-slot-trail {
    transform-box: fill-box;
    transform-origin: center;
    stroke-dasharray: 3 4;
    stroke-dashoffset: 0;
    pointer-events: none;
}
.research-status .scanner-svg .scan-slot-trail-return {
    stroke: #d4a84b;
}
.research-status .scanner-svg .scan-slot .scan-slot-trail-out {
    animation: scanTrailOut 1.4s var(--dispatch-delay) ease-out forwards;
}
@keyframes scanTrailOut {
    0%, 10% { opacity: 0; stroke-dashoffset: 10; }
    28%     { opacity: 0.48; }
    75%     { opacity: 0.35; }
    100%    { opacity: 0; stroke-dashoffset: -18; }
}
@keyframes scanTrailReturn {
    0%      { opacity: 0; stroke-dashoffset: 10; }
    18%     { opacity: 0.5; }
    76%     { opacity: 0.35; }
    100%    { opacity: 0; stroke-dashoffset: -18; }
}

@keyframes scanDispatch {
    0%   { opacity: 0; transform: translate(var(--start-x), var(--start-y)) scale(0.9); }
    15%  { opacity: 1; transform: translate(calc(var(--start-x) - 26px), calc(var(--start-y) - 6px)) scale(1); }
    46%  { opacity: 1; transform: translate(var(--out1-x), var(--out1-y)) scale(1.04); }
    78%  { opacity: 1; transform: translate(var(--out2-x), var(--out2-y)) scale(1.02); }
    100% { opacity: 1; transform: translate(var(--target-x), var(--target-y)) scale(1); }
}

/* Agent halo pulses indefinitely — gives the dispatched magnifying
   glass an alive "scanning" feel while waiting at the property for
   state. The lens itself stays steady; only the halo around it pulses. */
.research-status .scanner-svg .scan-agent-halo {
    transform-box: fill-box;
    transform-origin: center;
    animation: scanAgentPulse 1.4s ease-in-out infinite;
    animation-delay: 4s;
}
.research-status .scanner-svg .scan-agent-lens,
.research-status .scanner-svg .scan-agent-handle {
    animation: scanAgentLens 1.4s ease-in-out infinite;
    animation-delay: 4s;
}
.research-status .scanner-svg .scan-return-doc {
    transform-box: fill-box;
    transform-origin: center;
}
.research-status .scanner-svg .scan-return-doc,
.research-status .scanner-svg .scan-case-file {
    will-change: transform, opacity;
}
.research-status .scanner-svg .scan-doc-stack-layer {
    opacity: 0;
}
@keyframes scanAgentPulse {
    0%, 100% { opacity: 0.18; transform: scale(1); }
    50%      { opacity: 0.55; transform: scale(1.6); }
}
@keyframes scanAgentLens {
    0%, 100% { opacity: 0.9; }
    50%      { opacity: 1; }
}

/* ── Variant pulse (Tier 4) ────────────────────────────────────────── */
/*
 * When attempted_variants > 1, JS adds .variant-pulse-N to the slot
 * before its state class arrives. The agent pulses N times at the
 * property to visualize the SimpliCity variant retry. After the pulses
 * complete, the state-driven animation below takes over.
 *
 * IMPORTANT: this block must appear BEFORE the .state-scraped /
 * .state-empty / .state-cached / .state-failed selectors below. These
 * selectors have identical 4-class specificity, so source order breaks the tie.
 * We want a slot that has both .variant-pulse-N and .state-scraped to
 * fall through to .state-scraped's scanAgentCaptured flare, not stay
 * pinned to the now-completed pulse animation.
 */
.research-status .scanner-svg .scan-slot.variant-pulse-2 .scan-agent-halo {
    animation: scanAgentPulse 0.7s ease-in-out 2;
    animation-delay: 0s;
}
.research-status .scanner-svg .scan-slot.variant-pulse-3 .scan-agent-halo {
    animation: scanAgentPulse 0.7s ease-in-out 3;
    animation-delay: 0s;
}
.research-status .scanner-svg .scan-slot.variant-pulse-4 .scan-agent-halo {
    animation: scanAgentPulse 0.7s ease-in-out 4;
    animation-delay: 0s;
}

/* ── State-driven return animations ─────────────────────────────────── */
/*
 * Once JS adds .state-cached / .state-scraped / .state-empty /
 * .state-failed to a slot, the corresponding return animation fires.
 * The return keyframes start
 * at the property window position (where dispatch ended) and translate
 * back to the case file. fill-mode: forwards keeps the slot at the case
 * file once the return completes.
 */

/* Scraped: full round-trip with permit document. Slower than the
   dispatch (2.4s vs 1.4s) so the user has time to register the
   "data captured, returning" beat — that's the value impression.
   No delay — a delay causes the slot to teleport during the delay
   window because the fallback (no animation applied) state is at
   the case file, not at the property window. */
.research-status .scanner-svg .scan-slot.state-scraped {
    animation: scanReturn 2.4s ease-in-out forwards;
}

.research-status .scanner-svg .scan-slot.state-empty {
    animation: scanReturn 2.0s ease-in-out forwards;
}

/* Cached: same path but faster + visual handoff is sage-tinted */
.research-status .scanner-svg .scan-slot.state-cached {
    animation: scanReturn 1.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-lens { stroke: #7d9a7d; }
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-handle { stroke: #7d9a7d; }
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-halo { fill: #7d9a7d; }
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc-seal {
    stroke: #7d9a7d;
    fill: rgba(125,154,125,0.3);
}
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc-glow {
    fill: rgba(125,154,125,0.16);
}
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc-paper {
    stroke: #7d9a7d;
    fill: rgba(42,64,42,0.92);
}
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc-fold {
    stroke: #7d9a7d;
    fill: rgba(125,154,125,0.42);
}
.research-status .scanner-svg .scan-slot.state-cached .scan-doc-stack-layer,
.research-status .scanner-svg .scan-slot.state-empty .scan-doc-stack-layer {
    opacity: 0;
}
.research-status .scanner-svg .scan-slot.state-scraped.permit-stack-few .scan-doc-stack-mid,
.research-status .scanner-svg .scan-slot.state-scraped.permit-stack-many .scan-doc-stack-mid {
    opacity: 1;
}
.research-status .scanner-svg .scan-slot.state-scraped.permit-stack-many .scan-doc-stack-back {
    opacity: 1;
}
.research-status .scanner-svg .scan-slot.state-scraped.permit-stack-many .scan-return-doc-glow {
    fill: rgba(212,168,75,0.26);
}
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-lens {
    stroke: #b8a88e;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-handle {
    stroke: #b8a88e;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-halo {
    fill: #b8a88e;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-slot-trail-return {
    stroke: #b8a88e;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-glow {
    fill: rgba(245,237,227,0.1);
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-paper {
    stroke: #b8a88e;
    fill: rgba(245,237,227,0.18);
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-fold {
    stroke: #b8a88e;
    fill: rgba(245,237,227,0.32);
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-lines {
    opacity: 0.35;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-seal {
    opacity: 0;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-check {
    opacity: 1;
}

/* Return keyframes MUST include opacity:1 — without it, when the
   return animation replaces the dispatch animation, the slot's
   computed opacity falls back to the base .scan-slot rule (opacity:0
   set so the slot is hidden before dispatch runs) and SVG opacity
   stacks multiplicatively, hiding the doc inside even though the doc
   itself is at opacity:1. */
@keyframes scanReturn {
    0%   { opacity: 1; transform: translate(var(--target-x), var(--target-y)) scale(1); }
    42%  { opacity: 1; transform: translate(var(--ret1-x), var(--ret1-y)) scale(1.02); }
    76%  { opacity: 1; transform: translate(var(--ret2-x), var(--ret2-y)) scale(1); }
    100% { opacity: 1; transform: translate(var(--file-x), var(--file-y)) scale(1); }
}

/* During return for scraped/cached/empty:
   1. "Data captured" — agent halo flares brightly for 0.5s at the
      window (cause-effect: investigator found something). The slot
      hasn't started moving yet so the flare reads at the property.
   2. Agent lens+handle fade out at t=0.5s (after the flare).
   3. Return-doc fades in at the same time (visible handoff).
   4. The slot itself is translating back continuously over 2.4s,
      so by the time the doc is fully visible it's already moving.
*/
.research-status .scanner-svg .scan-slot.state-scraped .scan-slot-trail-return,
.research-status .scanner-svg .scan-slot.state-cached .scan-slot-trail-return,
.research-status .scanner-svg .scan-slot.state-empty .scan-slot-trail-return {
    animation: scanTrailReturn 1.2s 0.45s ease-out forwards;
}
.research-status .scanner-svg .scan-slot.state-scraped .scan-agent-halo,
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-halo,
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-halo {
    animation: scanAgentCaptured 0.5s ease-out forwards;
}
.research-status .scanner-svg .scan-slot.state-scraped .scan-agent-lens,
.research-status .scanner-svg .scan-slot.state-scraped .scan-agent-handle,
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-lens,
.research-status .scanner-svg .scan-slot.state-cached .scan-agent-handle,
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-lens,
.research-status .scanner-svg .scan-slot.state-empty .scan-agent-handle {
    animation: scanAgentFadeOut 0.45s 0.4s ease-out forwards;
}
.research-status .scanner-svg .scan-slot.state-scraped .scan-return-doc {
    animation: scanDocHandoff 2.4s ease-in-out forwards;
}
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc {
    animation: scanDocHandoff 2.0s ease-in-out forwards;
}
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc {
    animation: scanDocHandoffCached 1.4s ease-in-out forwards;
}
@keyframes scanAgentCaptured {
    0%   { opacity: 0.4; transform: scale(1); }
    50%  { opacity: 0.95; transform: scale(2.2); }
    100% { opacity: 0; transform: scale(2.5); }
}
@keyframes scanAgentFadeOut {
    to { opacity: 0; }
}
@keyframes scanDocHandoff {
    0%, 16% { opacity: 0; transform: scale(0.84) rotate(-7deg) translateY(0); }
    30%     { opacity: 1; transform: scale(1.03) rotate(-4deg) translateY(-1px); }
    76%     { opacity: 1; transform: scale(1) rotate(2deg) translateY(-2px); }
    92%     { opacity: 1; transform: translate(3px, 1px) scale(0.88) rotate(0deg); }
    100%    { opacity: 0.78; transform: translate(6px, 3px) scale(0.68) rotate(0deg); }
}
@keyframes scanDocHandoffCached {
    0%, 20% { opacity: 0; transform: scale(0.86) rotate(-5deg) translateY(0); }
    42%     { opacity: 1; transform: scale(1.02) rotate(-2deg) translateY(-1px); }
    88%     { opacity: 1; transform: translate(3px, 1px) scale(0.86) rotate(0deg); }
    100%    { opacity: 0.78; transform: translate(6px, 3px) scale(0.68) rotate(0deg); }
}

/* Doc halo glow pulses subtly as the doc travels — gives motion the
   feel of carrying something valuable. */
.research-status .scanner-svg .scan-slot.state-scraped .scan-return-doc-glow,
.research-status .scanner-svg .scan-slot.state-cached .scan-return-doc-glow,
.research-status .scanner-svg .scan-slot.state-empty .scan-return-doc-glow {
    animation: scanDocGlow 1.6s 0.4s ease-in-out infinite;
}
@keyframes scanDocGlow {
    0%, 100% { opacity: 0.18; }
    50%      { opacity: 0.42; }
}

/* "Thunk" pulse on the report folder when a doc arrives. Fires once
   the slot has finished its return animation (~2.4s after state). */
.research-status .scanner-svg .scan-cf-thunk {
    pointer-events: none;
}
.research-status .scanner-svg .scan-case-file.has-arrived .scan-cf-thunk,
.research-status .scanner-svg .scan-case-file.has-arrived-cached .scan-cf-thunk,
.research-status .scanner-svg .scan-case-file.has-arrived-empty .scan-cf-thunk {
    animation: scanCfThunk 0.7s ease-out forwards;
}
.research-status .scanner-svg .scan-case-file.has-arrived,
.research-status .scanner-svg .scan-case-file.has-arrived-cached,
.research-status .scanner-svg .scan-case-file.has-arrived-empty {
    transform-box: fill-box;
    transform-origin: center;
    animation: scanCfCatch 0.42s cubic-bezier(0.16, 1, 0.3, 1);
}
.research-status .scanner-svg .scan-case-file.has-arrived .scan-cf-thunk {
    stroke: #ffd770;
}
.research-status .scanner-svg .scan-case-file.has-arrived-cached .scan-cf-thunk {
    stroke: #9fba9f;
}
.research-status .scanner-svg .scan-case-file.has-arrived-empty .scan-cf-thunk {
    stroke: #b8a88e;
}
@keyframes scanCfThunk {
    0%   { opacity: 0; stroke-width: 1.5; }
    20%  { opacity: 0.95; stroke-width: 4; }
    100% { opacity: 0; stroke-width: 6; }
}
@keyframes scanCfCatch {
    0%   { transform: translateY(0) scale(1); }
    34%  { transform: translateY(1.5px) scale(0.992); }
    100% { transform: translateY(0) scale(1); }
}

/* Failed: agent fades at property with terracotta ripple, no return */
.research-status .scanner-svg .scan-slot.state-failed .scan-agent-lens {
    stroke: #c75b5b;
}
.research-status .scanner-svg .scan-slot.state-failed .scan-agent-handle {
    stroke: #c75b5b;
}
.research-status .scanner-svg .scan-slot.state-failed .scan-agent-halo {
    fill: #c75b5b;
}
.research-status .scanner-svg .scan-slot.state-failed .scan-agent {
    animation: scanFailedFade 1.5s 0.4s ease-out forwards;
}
@keyframes scanFailedFade {
    0%   { opacity: 1; }
    50%  { opacity: 0.8; }
    100% { opacity: 0; }
}

/* ── GENERATING phase animations ────────────────────────────────────── */
/*
 * When status flips to GENERATING (all scrapes complete), the case file
 * "binds" itself shut and a wax seal stamps. This is fired by JS adding
 * a .is-generating class to the .scan-case-file group.
 */
.research-status .scanner-svg .scan-cf-binding {
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
}
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-binding {
    opacity: 0.8;
    animation: scanCfBind 1.0s ease-out forwards;
}
@keyframes scanCfBind { to { stroke-dashoffset: 0; } }

/* Gold → sage crossfade — the case file itself "approves" during the
   drafting phase: folder stroke, tab, and headers transition to sage so
   the whole artifact reads as sealed/ready. The wax seal stays terracotta
   as a contrast accent (it's the stamp, not the file). */
.research-status .scanner-svg .scan-cf-back,
.research-status .scanner-svg .scan-cf-tab,
.research-status .scanner-svg .scan-cf-tab-label,
.research-status .scanner-svg .scan-cf-label-eyebrow,
.research-status .scanner-svg .scan-cf-label-rule {
    transition: stroke 1.1s cubic-bezier(0.4, 0, 0.2, 1),
                fill   1.1s cubic-bezier(0.4, 0, 0.2, 1);
}
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-back,
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-tab,
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-label-rule {
    stroke: #7d9a7d;
}
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-tab {
    fill: rgba(125,154,125,0.14);
}
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-tab-label,
.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-label-eyebrow {
    fill: #7d9a7d;
}

.research-status .scanner-svg .scan-case-file.is-generating .scan-cf-seal {
    animation: scanCfSeal 0.55s 0.95s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    transform-box: fill-box;
    transform-origin: center;
}
@keyframes scanCfSeal {
    0%   { opacity: 0; transform: scale(2.4); }
    58%  { opacity: 1; transform: scale(0.88); }
    76%  { opacity: 0.98; transform: scale(1.08); }
    100% { opacity: 0.95; transform: scale(1); }
}

/* ── End-state overrides — keyed off [data-outcome] ──────────────────── */
/*
 * The scanner illustration responds to the customer-facing OUTCOME, not
 * the raw status enum. A FAILED+empty-clean case (we searched, found
 * nothing) keeps the scene fully lit with a "RECORDS CHECKED" plaque —
 * it should look like a finished investigation, not a broken sweep. Only
 * the truly-interrupted cases (portal hard error) dim the illustration.
 */

/* Hidden-by-default overlays. The inner stroke-drawn frames + text
   need their initial state set HERE (not inside the data-reveal rule)
   so they stay hidden during the reveal animation, even when the
   outer group fades in based on data-outcome. */
.research-status .scanner-svg .scan-complete-flourish,
.research-status .scanner-svg .scan-records-plaque {
    opacity: 0;
    pointer-events: none;
}
/* Plaque frames: invisible by default (full stroke offset) */
.research-status .scanner-svg .scan-plaque-frame,
.research-status .scanner-svg .scan-interrupted-frame {
    stroke-dasharray: 540;
    stroke-dashoffset: 540;
}
.research-status .scanner-svg .scan-plaque-rule,
.research-status .scanner-svg .scan-interrupted-rule {
    stroke-dasharray: 130;
    stroke-dashoffset: 130;
}
.research-status .scanner-svg .scan-plaque-eyebrow,
.research-status .scanner-svg .scan-plaque-result,
.research-status .scanner-svg .scan-interrupted-eyebrow,
.research-status .scanner-svg .scan-interrupted-result {
    opacity: 0;
}
.research-status .scanner-svg .scan-complete-circle {
    stroke-dasharray: 220;
    stroke-dashoffset: 220;
}
.research-status .scanner-svg .scan-complete-check {
    stroke-dasharray: 60;
    stroke-dashoffset: 60;
}

/*
 * Reveal-then-overlay choreography
 * --------------------------------
 * The reveal animation (drawPath strokes + doc arrivals + window flashes)
 * runs from 0–6s on every page load — including direct-loads onto a
 * terminal state. Watching the building draw in is part of the
 * "investigation in progress" UX even when the request already settled.
 *
 * Terminal-state overlays (success flourish, RECORDS CHECKED plaque)
 * are gated on data-reveal="complete", which the page JS sets ~6s after
 * page load. This handles two cases cleanly:
 *
 *   - Direct-load on a terminal state: reveal plays 0–6s, then JS flips
 *     data-reveal=complete, then the overlay animation kicks off with
 *     animation-delay 0.
 *   - Mid-life transition (in-progress → terminal during the poll loop):
 *     by the time the customer's request settles, the page has been open
 *     30+ seconds, so data-reveal=complete has long since fired. The
 *     overlay animation kicks off immediately on the data-outcome flip.
 *
 * Earlier we tried `animation-play-state: paused !important` on terminal
 * scanners — that froze the reveal itself, leaving the page nearly blank.
 * Removed.
 */

/* delivered (COMPLETED / COMPLETED_PARTIAL): success flourish stroke-draws in */
.research-status .sweep-scanner[data-outcome="delivered"] .scan-complete-flourish {
    opacity: 1;
}
.research-status .sweep-scanner[data-outcome="delivered"][data-reveal="complete"] .scan-complete-circle {
    stroke-dasharray: 220;
    stroke-dashoffset: 220;
    animation: scanCompleteCircle 0.85s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="delivered"][data-reveal="complete"] .scan-complete-check {
    stroke-dasharray: 60;
    stroke-dashoffset: 60;
    animation: scanCompleteCheck 0.5s 0.7s ease-out forwards;
}
@keyframes scanCompleteCircle { to { stroke-dashoffset: 0; } }
@keyframes scanCompleteCheck { to { stroke-dashoffset: 0; } }

/* empty-clean (FAILED/REFUNDED, all jurisdictions cleanly searched): the
   scene stays fully lit and finished. The plaque overlays the building
   with a "RECORDS CHECKED · 0 permits on file" inscription — frame
   strokes in, then text fades up. No dimming, no warning vocabulary. */
.research-status .scanner-svg .scan-records-plaque {
    transition: opacity 0.4s ease-out;
}
.research-status .sweep-scanner[data-outcome="empty-clean"][data-reveal="complete"] .scan-records-plaque {
    opacity: 1;
}
.research-status .sweep-scanner[data-outcome="empty-clean"][data-reveal="complete"] .scan-plaque-frame {
    stroke-dasharray: 540;
    stroke-dashoffset: 540;
    animation: scanPlaqueFrame 1.1s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="empty-clean"][data-reveal="complete"] .scan-plaque-rule {
    stroke-dasharray: 130;
    stroke-dashoffset: 130;
    animation: scanPlaqueRule 0.55s 0.75s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="empty-clean"][data-reveal="complete"] .scan-plaque-eyebrow {
    opacity: 0;
    animation: scanPlaqueText 0.55s 1.0s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="empty-clean"][data-reveal="complete"] .scan-plaque-result {
    opacity: 0;
    animation: scanPlaqueText 0.55s 1.2s ease-out forwards;
}
@keyframes scanPlaqueFrame { to { stroke-dashoffset: 0; } }
@keyframes scanPlaqueRule  { to { stroke-dashoffset: 0; } }
@keyframes scanPlaqueText  { to { opacity: 1; } }

/* interrupted (FAILED/REFUNDED with at least one jurisdiction error):
   dim the scene to signal "something went wrong," then overlay a
   terracotta plaque with parallel structure to the empty-clean one.
   The plaque stays at full opacity (overrides the parent dim) so it
   reads as the focal acknowledgment, not just more dimmed line work. */
/* Dim ONLY the scene group, not the SVG root, so terminal-state overlay
   plaques (which live outside .scan-scene) stay at full opacity rather
   than being multiplied by the parent dim. */
.research-status .sweep-scanner[data-outcome="interrupted"] .scan-scene {
    opacity: 0.55;
}
.research-status .scanner-svg .scan-interrupted-plaque {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s ease-out;
}
.research-status .sweep-scanner[data-outcome="interrupted"][data-reveal="complete"] .scan-interrupted-plaque {
    opacity: 1;
}
.research-status .sweep-scanner[data-outcome="interrupted"][data-reveal="complete"] .scan-interrupted-frame {
    stroke-dasharray: 540;
    stroke-dashoffset: 540;
    animation: scanPlaqueFrame 1.1s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="interrupted"][data-reveal="complete"] .scan-interrupted-rule {
    stroke-dasharray: 130;
    stroke-dashoffset: 130;
    animation: scanPlaqueRule 0.55s 0.75s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="interrupted"][data-reveal="complete"] .scan-interrupted-eyebrow {
    opacity: 0;
    animation: scanPlaqueText 0.55s 1.0s ease-out forwards;
}
.research-status .sweep-scanner[data-outcome="interrupted"][data-reveal="complete"] .scan-interrupted-result {
    opacity: 0;
    animation: scanPlaqueText 0.55s 1.2s ease-out forwards;
}

/* ── Zone 3 · Per-jurisdiction cards ─────────────────────────────────── */
.research-status .sweep-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
}
.research-status .sweep-card {
    position: relative;
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 1rem;
    align-items: center;
    padding: 1.1rem 1.25rem;
    background: linear-gradient(155deg, #141110 0%, #1b1513 100%);
    border: 1px solid rgba(255,255,255,0.06);
    border-left: 3px solid rgba(255,255,255,0.08);
    border-radius: 14px;
    color: var(--status-ink);
    opacity: 0;
    transform: translateY(12px);
    animation: sweepCardEnter 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    transition: border-color .3s ease;
}
/* Stagger card entrance via :nth-child (CSP-safe, no inline style="--*"). */
.research-status .sweep-cards .sweep-card:nth-child(1) { animation-delay: 0ms; }
.research-status .sweep-cards .sweep-card:nth-child(2) { animation-delay: 80ms; }
.research-status .sweep-cards .sweep-card:nth-child(3) { animation-delay: 160ms; }
.research-status .sweep-cards .sweep-card:nth-child(4) { animation-delay: 240ms; }
.research-status .sweep-cards .sweep-card:nth-child(5) { animation-delay: 320ms; }
.research-status .sweep-cards .sweep-card:nth-child(6) { animation-delay: 400ms; }
@keyframes sweepCardEnter {
    to { opacity: 1; transform: translateY(0); }
}
.research-status .sweep-card-main { min-width: 0; }
.research-status .sweep-card-label {
    font-family: "Playfair Display", Georgia, serif;
    font-size: 1.12rem;
    line-height: 1.2;
    color: var(--status-ink);
    margin-bottom: .45rem;
    word-break: break-word;
}
.research-status .sweep-card-state {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    margin-bottom: .35rem;
    color: var(--status-muted);
}
.research-status .sweep-card-detail {
    font-size: .85rem;
    color: rgba(245,237,227,0.55);
    line-height: 1.45;
    word-break: break-word;
}
.research-status .sweep-card-variants {
    margin-top: .35rem;
    padding-top: .35rem;
    border-top: 1px dashed rgba(245,237,227,0.12);
    font-family: "IBM Plex Mono", monospace;
    font-size: .68rem;
    letter-spacing: .06em;
    color: rgba(245,237,227,0.5);
    cursor: help;
}
.research-status .sweep-card-variants[hidden] { display: none; }
.research-status .sweep-card-count {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .15rem;
    text-align: right;
    font-feature-settings: "tnum" 1;
}
.research-status .sweep-card-count-value {
    font-family: "Playfair Display", Georgia, serif;
    font-size: 2.1rem;
    line-height: 1;
    color: var(--status-ink);
}
.research-status .sweep-card-count-label {
    font-family: "IBM Plex Mono", monospace;
    font-size: .62rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: rgba(245,237,227,0.45);
}

/* Checkmark & X icons are hidden until terminal card states */
.research-status .sweep-card-check,
.research-status .sweep-card-x {
    position: absolute;
    top: .9rem;
    right: .9rem;
    width: 18px;
    height: 18px;
    opacity: 0;
    pointer-events: none;
}

/* State: searching — pulse the card border itself. A separate pseudo-element
   reads as a detached blinking line around the rounded lower-left corner. */
.research-status .sweep-card.state-searching {
    border-left-color: var(--status-gold);
    box-shadow: inset 2px 0 0 rgba(212,168,75,0.18);
}
.research-status .sweep-card.state-searching .sweep-card-state { color: var(--status-gold); }

/* State: retrieved — sage accent + one-shot checkmark draw */
.research-status .sweep-card.state-retrieved {
    border-left-color: var(--accent-sage, #7d9a7d);
}
.research-status .sweep-card.state-retrieved .sweep-card-state { color: var(--accent-sage, #7d9a7d); }
.research-status .sweep-card.state-retrieved .sweep-card-check {
    opacity: 1;
    color: var(--accent-sage, #7d9a7d);
}
.research-status .sweep-card.state-retrieved .sweep-card-check-path {
    stroke-dasharray: 40;
    stroke-dashoffset: 40;
    animation: sweepCardCheck 0.45s ease-out forwards;
}
@keyframes sweepCardCheck {
    to { stroke-dashoffset: 0; }
}

/* State: cached — same sage accent, "value signal" tone on the detail line */
.research-status .sweep-card.state-cached {
    border-left-color: var(--accent-sage, #7d9a7d);
}
.research-status .sweep-card.state-cached .sweep-card-state { color: var(--accent-sage, #7d9a7d); }
.research-status .sweep-card.state-cached .sweep-card-detail { color: var(--accent-sage, #7d9a7d); }
.research-status .sweep-card.state-cached .sweep-card-check {
    opacity: 1;
    color: var(--accent-sage, #7d9a7d);
}

/* State: failed — terracotta X, static (no pulsing motion on errors) */
.research-status .sweep-card.state-failed {
    border-left-color: var(--color-error, #c75b5b);
}
.research-status .sweep-card.state-failed .sweep-card-state { color: var(--color-error, #c75b5b); }
.research-status .sweep-card.state-failed .sweep-card-detail { color: rgba(199,91,91,0.85); }
.research-status .sweep-card.state-failed .sweep-card-x {
    opacity: 1;
    color: var(--color-error, #c75b5b);
}
.research-status .sweep-card.state-failed .sweep-card-count-value { color: rgba(245,237,227,0.3); }

/* ── Zone 4 · Footnote ───────────────────────────────────────────────── */
.research-status .sweep-footnote {
    margin: 0;
    padding: 0 1rem;
    text-align: center;
    font-size: .88rem;
    line-height: 1.6;
    color: rgba(245,237,227,0.5);
}
.research-status .sweep-footnote a {
    color: var(--status-gold);
    text-decoration: none;
    border-bottom: 1px dashed rgba(215,171,93,0.35);
}
.research-status .sweep-footnote a:hover { color: #f1c679; border-bottom-color: #f1c679; }

/* ── Responsive ──────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .research-status .sweep-masthead { padding: 1.75rem 1.5rem 1.35rem; }
}
/* ── Dispatch plane (ambient) ─────────────────────────────────────────────
   A monoline recon plane tows a parchment "your report is in progress" ribbon
   across the calm upper band of the scanner panel while the sweep runs. Pure
   CSS: shown only while .research-status[data-outcome="in-progress"] (the poll
   keeps that attribute current and flips it / redirects on completion), so it
   needs no JS. The panel is position:relative + overflow:hidden, so the rig
   enters/exits cleanly at the panel's rounded edges. */
/* The rig is a CLIP FRAME inset to the lighter inner illustration (the scanner
   SVG sits inside the panel's 1.5rem padding). overflow:hidden here means the
   plane appears/disappears at the INNER edges, never crossing the near-black
   padding border. */
.research-status .scan-plane-rig {
    position: absolute;
    top: 9%;
    left: 1.5rem;
    right: 1.5rem;
    height: 150px;
    overflow: hidden;
    z-index: 5;
    pointer-events: none;
    display: none;                 /* hidden unless the sweep is in progress */
}
.research-status[data-outcome="in-progress"] .scan-plane-rig { display: block; }
/* The flyer carries the horizontal travel; the bob inside carries the vertical
   bob (two transforms need two elements). */
.research-status .scan-plane-fly {
    position: absolute;
    top: 0;
    right: 0;
    width: min(760px, 100%);
}
.research-status[data-outcome="in-progress"] .scan-plane-fly {
    /* `backwards` fill so during the 3s delay the flyer holds the `from`
       keyframe (off-screen right) instead of its static position — otherwise
       the plane flashes in view mid-panel before the first flight begins. */
    animation: scanPlaneFly 18s linear 3s infinite backwards;
    will-change: transform;
}
.research-status .scan-plane { display: block; width: 100%; height: auto; }
.research-status .scan-plane--mobile { display: none; }  /* wide variant on desktop */
.research-status .scan-plane-bob { animation: scanPlaneBob 5s ease-in-out infinite; }
.research-status .scan-plane-prop {
    transform-box: fill-box; transform-origin: center;
    animation: scanPlaneProp .13s linear infinite;
}
.research-status .scan-plane-ribbon {
    transform-box: fill-box; transform-origin: left center;
    animation: scanPlaneRibbon 2.8s ease-in-out infinite;
}
.research-status .scan-plane-text {
    font-family: "IBM Plex Mono", monospace; font-weight: 500;
    font-size: 14.5px; letter-spacing: .015em; fill: #241a10;
}
/* % values are relative to the flyer's own width; the clip frame bounds it to
   the inner area, so it enters at the inner-right edge and exits at inner-left. */
@keyframes scanPlaneFly { from { transform: translateX(100%); } to { transform: translateX(-130%); } }
@keyframes scanPlaneBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes scanPlaneProp { to { transform: rotate(360deg); } }
@keyframes scanPlaneRibbon { 0%, 100% { transform: rotate(0.35deg); } 50% { transform: rotate(-0.7deg); } }

@media (max-width: 640px) {
    /* The full banner can't fit legibly on a narrow panel, so swap to the
       compact plane + short banner ("Report in progress"). Its smaller viewBox
       means it scales down less, keeping the mono text ~11px. The flyer is
       narrowed to the compact SVG's natural size so the whole thing reads as it
       crosses; the full reassurance still lives in the masthead meta + footnote. */
    .research-status .scan-plane--wide { display: none; }
    .research-status .scan-plane--mobile { display: block; }
    .research-status .scan-plane-fly { width: min(360px, 115%); }
    .research-status { padding: 1.5rem 1rem 3rem; gap: 1.25rem; }
    .research-status .sweep-masthead { padding: 1.4rem 1.2rem 1.2rem; border-radius: 18px; }
    .research-status .sweep-meta { gap: .5rem; font-size: .68rem; }
    .research-status .sweep-meta-sep { display: none; }
    .research-status .sweep-elapsed { margin-left: 0; }
    .research-status .sweep-scanner { padding: 1rem; border-radius: 16px; }
    .research-status .sweep-card { padding: 1rem 1.1rem; border-radius: 12px; }
    .research-status .sweep-card-count-value { font-size: 1.7rem; }
}

/* ── Reduced motion ──────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
	    .research-status .scanner-svg *,
	    .research-status .sweep-chip-pulse,
	    .research-status .scan-cf-log-row,
	    .research-status .sweep-card,
	    .research-status .sweep-card.state-searching,
	    .research-status .sweep-card-check-path {
	        animation: none !important;
	    }
    /* The dispatch plane is motion-only whimsy; drop it entirely (the message
       lives in the masthead meta + footnote). */
    .research-status .scan-plane-rig { display: none !important; }
    /* Make sure cards are visible when their entrance animation is killed */
    .research-status .sweep-card {
        opacity: 1;
        transform: none;
    }
    /* Retrieved/cached checkmarks render in their final state. */
    .research-status .sweep-card.state-retrieved .sweep-card-check-path,
    .research-status .sweep-card.state-cached .sweep-card-check-path {
        stroke-dashoffset: 0 !important;
    }
    /* Scanner illustration: skip motion but show the final composed state. */
    .research-status .scanner-svg .scan-draw,
    .research-status .scanner-svg .scan-complete-circle,
    .research-status .scanner-svg .scan-complete-check,
    .research-status .scanner-svg .scan-cf-binding {
        stroke-dashoffset: 0 !important;
    }
    .research-status .scanner-svg .scan-window {
        opacity: 1 !important;
        fill: rgba(255,255,255,0.04) !important;
    }
    .research-status .scanner-svg .scan-window.is-lit {
        fill: rgba(225,180,90,0.75) !important;
    }
    .research-status .scanner-svg .scan-window.is-lit-cached {
        fill: rgba(150,180,140,0.66) !important;
    }
    .research-status .scanner-svg .scan-window-sweep {
        opacity: 0 !important;
    }
    .research-status .scanner-svg .scan-bird {
        opacity: 0 !important;
    }
    /* Scanner slots: render each slot in its truthful static state. */
    .research-status .scanner-svg .scan-slot {
        opacity: 1 !important;
        transform: translate(var(--target-x), var(--target-y)) !important;
    }
    .research-status .scanner-svg .scan-slot.state-scraped,
    .research-status .scanner-svg .scan-slot.state-cached,
    .research-status .scanner-svg .scan-slot.state-empty {
        transform: translate(var(--file-x), var(--file-y)) !important;
    }
    .research-status .scanner-svg .scan-slot.state-failed {
        opacity: 0.35 !important;
    }
    .research-status .scanner-svg .scan-agent { opacity: 0.4 !important; }
    .research-status .scanner-svg .scan-slot.state-scraped .scan-agent,
    .research-status .scanner-svg .scan-slot.state-cached .scan-agent,
    .research-status .scanner-svg .scan-slot.state-empty .scan-agent {
        opacity: 0 !important;
    }
    .research-status .scanner-svg .scan-return-doc { opacity: 0 !important; }
    .research-status .scanner-svg .scan-slot.state-scraped .scan-return-doc,
    .research-status .scanner-svg .scan-slot.state-cached .scan-return-doc,
    .research-status .scanner-svg .scan-slot.state-empty .scan-return-doc {
        opacity: 0.75 !important;
        transform: translate(6px, 3px) scale(0.68) !important;
    }
    /* Case file label/address: render visible. */
    .research-status .scanner-svg .scan-cf-label-eyebrow,
    .research-status .scanner-svg .scan-cf-tab-label,
    .research-status .scanner-svg .scan-cf-address-text {
        opacity: 1 !important;
        transform: scale(1) !important;
    }
    /* Empty-clean plaque + interrupted plaque + completion: final state. */
    .research-status .scanner-svg .scan-plaque-frame,
    .research-status .scanner-svg .scan-plaque-rule,
    .research-status .scanner-svg .scan-interrupted-frame,
    .research-status .scanner-svg .scan-interrupted-rule {
        stroke-dashoffset: 0 !important;
    }
    .research-status .scanner-svg .scan-plaque-eyebrow,
    .research-status .scanner-svg .scan-plaque-result,
    .research-status .scanner-svg .scan-interrupted-eyebrow,
    .research-status .scanner-svg .scan-interrupted-result {
        opacity: 1 !important;
    }
    .research-status .scanner-svg .scan-cf-seal {
        opacity: 0.95 !important;
        transform: scale(1) !important;
    }
}
