/* ────────────────────────────────────────────────────────────────────────────
   WISEcode Intelligence Reports — unified design system
   Per PRD §2 "Unified Design System": all four report surfaces share these
   classes. No report-specific overrides. Per-report .razor.css should only
   define layout for that report's unique sections.

   Source of truth: PRD §2 for tokens + HTML prototypes for exact pixel values.
   ──────────────────────────────────────────────────────────────────────────── */

:root {
    /* Base palette — PRD §2.3 */
    --rpt-navy:           #0A1628;
    --rpt-blue:           #1A5CFF;
    --rpt-blue-hover:     #1448D6;
    --rpt-ink:            #2B2830;
    --rpt-page-bg:        #F4F6FA;
    --rpt-card-border:    #DDE2EE;
    --rpt-mid-gray:       #71717A;
    --rpt-mute-gray:      #9CA3AF;
    --rpt-text-secondary: #374151;
    --rpt-row-hover-bg:   #F8FAFF;

    /* GRAS classification palette — PRD §2.3 */
    --rpt-gras-text:        #166534;
    --rpt-gras-bg:          #DCFCE7;
    --rpt-gras-color:       #16A34A;
    --rpt-hist-text:        #0F766E;
    --rpt-hist-bg:          #F0FDFA;
    --rpt-hist-color:       #14B8A6;
    --rpt-unknown-text:     #92400E;
    --rpt-unknown-bg:       #FEF3C7;
    --rpt-unknown-color:    #D97706;
    --rpt-unsafe-text:      #991B1B;
    --rpt-unsafe-bg:        #FEE2E2;
    --rpt-unsafe-color:     #DC2626;
    /* GRAS+ middle bands (gras_plus food expression):
       Unknown Flavors = Neutral/Yellow, Unclear = Bad/Orange */
    --rpt-uflavors-text:    #854D0E;
    --rpt-uflavors-bg:      #FEF9C3;
    --rpt-uflavors-color:   #EAB308;
    --rpt-unclear-text:     #9A3412;
    --rpt-unclear-bg:       #FFEDD5;
    --rpt-unclear-color:    #EA580C;

    /* UPF processing-level palette — PRD §2.3 */
    --rpt-pl1: #166534;
    --rpt-pl2: #16A34A;
    --rpt-pl3: #EA580C;
    --rpt-pl4: #DC2626;

    /* WISEscore rating palette — PRD §2.3 */
    --rpt-rating-excellent: #16A34A;
    --rpt-rating-good:      #14B8A6;
    --rpt-rating-ok:        #3B82F6;
    --rpt-rating-fair:      #D97706;
    --rpt-rating-poor:      #DC2626;

    /* Type stacks */
    --rpt-font-body: 'DM Sans', system-ui, sans-serif;
    --rpt-font-mono: ui-monospace, SFMono-Regular, Menlo, 'Courier New', monospace;
}

/* ── Outer report card ──────────────────────────────────────────────────── */
/*  Min-width keeps all three cards in §02 (and the 3-col stats row) on a
    single line at every viewport. Below that floor the browser shows its
    own horizontal scrollbar at the bottom — we don't try to reflow.
    Max-width caps growth on wide displays. PDFs are unaffected (QuestPDF
    renders to a fixed 8.5×11 canvas). */
.report-wrapper {
    /* Base wrapper; per-report modifier classes below pin the max-width
       to the value the matching prototype HTML uses (920–1060 px). */
    min-width: 880px;
    max-width: 980px;
    margin: 0;
}

/*  Hard-clear the fixed sidebar at the tablet breakpoint. design-system.css
    drops `.main-content` margin-left to 6rem in this band on the assumption
    the sidebar auto-collapses to ~6rem too — it doesn't, so the report
    would slide UNDER the 18rem-wide sidebar. Override only for pages that
    render a report card (`body:has(.report-wrapper)`) so we don't disturb
    the rest of the app, which may be designed around the narrower content
    area. */
@media (max-width: 1100px) and (min-width: 769px) {
    /* Only force the wider margin when the sidebar is EXPANDED — when the
       user clicks "Collapse", the sidebar shrinks to ~112px and
       design-system.css's `body:has(.sidebar-collapsed) .main-content`
       (margin-left: 128px) should win unmodified. */
    body:has(.report-wrapper):has(.sidebar-expanded) .main-content {
        margin-left: 304px !important;
    }
}

/*  Force always-visible scrollbars on report pages and keep them anchored
    to the viewport — not the bottom of the document. macOS / iOS auto-hide
    scrollbars unless the system pref "Always show scrollbars" is on, so
    even with a properly-overflowing page users can't see the bottom
    horizontal track until they scroll to the page bottom.

    Strategy: lock <html> and <body> to viewport height with no scrolling
    of their own and turn `.main-content` into the scroll container. Its
    own vertical/horizontal scrollbars sit at the right edge and bottom
    edge of the viewport respectively, so the horizontal scrollbar is
    always reachable without first scrolling to the bottom of the report.
    The fixed sidebar is unaffected — it stays put.

    All rules scoped to `body:has(.report-wrapper)` so the rest of the app
    keeps its normal document-level scrolling. */
html:has(.report-wrapper),
body:has(.report-wrapper) {
    height: 100vh;
    overflow: hidden;
    /* Include any padding (e.g. the 60px mobile-header padding-top
       design-system.css adds at <=768px) in the 100vh budget so
       .main-content's bottom edge — and its horizontal scrollbar — stays
       inside the visible viewport instead of being clipped. */
    box-sizing: border-box;
}

body:has(.report-wrapper) .main-content {
    /* Fill the parent's CONTENT box, not the viewport, so any body
       padding (mobile header reservation, etc.) is respected. */
    height: 100%;
    /* `scroll` (not `auto`) forces classic, always-visible scrollbars even
       when there's no overflow on the axis. Pair with explicit
       ::-webkit-scrollbar styles below — Chrome opts out of overlay
       scrollbars (the macOS auto-hide style) the moment a non-default
       ::-webkit-scrollbar rule is present, but only if scrollbar-width /
       scrollbar-color (Firefox standards) aren't set, which override the
       WebKit pseudo-elements when both exist. */
    overflow-y: scroll;
    overflow-x: scroll;
}

body:has(.report-wrapper) .main-content::-webkit-scrollbar          { width: 14px; height: 14px; }
body:has(.report-wrapper) .main-content::-webkit-scrollbar-track    { background: #F1F3F8; }
body:has(.report-wrapper) .main-content::-webkit-scrollbar-thumb    { background: #B5B9C4; border: 3px solid #F1F3F8; border-radius: 7px; }
body:has(.report-wrapper) .main-content::-webkit-scrollbar-thumb:hover { background: #8E94A8; }
body:has(.report-wrapper) .main-content::-webkit-scrollbar-corner   { background: #F1F3F8; }

.report-card {
    background: #FFFFFF;
    border: 1px solid var(--rpt-card-border);
    border-radius: 6px;
    /* overflow:visible (was: hidden) so Syncfusion tooltips that swing past
       the card edge — e.g. the right-side donut on Portfolio GRAS §02 —
       aren't clipped. The navy topbar and footer below carry their own
       corner radii to preserve the rounded-card look. */
    overflow: visible;
    box-shadow: 0 4px 28px rgba(10, 22, 40, .10);
    font-family: var(--rpt-font-body);
    color: var(--rpt-ink);
}

/* In PDF render mode (Playwright print emulation) the footer flows in normal
   block order after the last section.

   We used to make .report-card a `display:flex` column with `min-height:100vh`
   and pin the footer via `margin-top:auto` (to glue it to the bottom on
   single-page reports). That pin is unsafe for multi-page reports: headless
   Chromium mis-fragments a flex container whose last child has an auto top
   margin — on the final page it pulls the footer UP and clips the row that
   should precede it (the last Health Outcomes metric, "Diabetes Friendly", was
   being dropped entirely; .report-card's overflow:hidden then hid the
   overflow). Plain block flow paginates reliably across pages, so the footer
   simply lands right after the final row. The minor cost is that a short,
   single-page report no longer has its footer glued to the very bottom edge of
   the page, which is an acceptable trade for never dropping content. */
@media print {
    /* Match the PdfAsync page size set in PrintToPdfHelper. Margin 0 because
       the report card owns its own padding edge-to-edge. */
    @page {
        size: letter portrait;
        margin: 0;
    }

    /* Force every element inside the report to preserve its background and
       text colors when rasterized to PDF. Chrome's print emulation defaults
       to `print-color-adjust: economy`, which strips backgrounds for
       ink-saving — without this opt-in the navy section headers, status
       badges, gradient bars, and "What is GRAS?" card all print
       white-on-white. -webkit- prefix is still needed for headless Chromium. */
    .report-card,
    .report-card * {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .rpt-footer {
        /* Override the base `margin-top:auto` (inert off-flex) so nothing pins
           the footer; it flows right after the last section. */
        margin-top: 0;
        /* Keep the footer on the same page as its preceding content. */
        break-before: avoid;
        page-break-before: avoid;
    }

    /* Pagination guards — keep atomic UI units intact across page breaks.
       Only includes classes that the Razor components actually emit; verify
       any addition with grep before committing. */
    .chart-card,
    .metric-row,
    .pi-metric-row,
    .product-row,
    .product-table tr,
    .pi-table tr,
    .pi-heatmap tr,
    .top5-card,
    .top5-row,
    .code-top5-row,
    .ingredient-row,
    .group-row,
    .verdict-card,
    .gras-verdict-card,
    .upf-verdict-card,
    .upf-shield-bar,
    .what-is-gras-card {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* Section headers and chart titles must stay with their bodies. */
    .section-header,
    .section-title,
    .pa-card-title,
    .report-brand-header {
        break-after: avoid;
        page-break-after: avoid;
    }

    /* Repeat product-table headers on every printed page so tables that
       span multiple pages still carry their column labels. */
    .product-table thead,
    .pi-table thead {
        display: table-header-group;
    }
    .product-table tfoot,
    .pi-table tfoot {
        display: table-footer-group;
    }
}

/* ── Header (navy, full-width) — mirrors the food spec-sheet header
       (Components/Shared/SpecSheetView.razor.css §── Header ──) for visual
       parity across every WISEcode artefact. ─────────────────────────────── */
.rpt-hdr {
    background: var(--rpt-navy);
    color: #FFFFFF;
    padding: 18px 32px 14px;
    border-radius: 6px 6px 0 0;
    position: relative;
}
.rpt-hdr-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}
.rpt-hdr-brand {
    display: flex;
    align-items: center;
    gap: 14px;
}
.rpt-hdr-logoblock {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.rpt-hdr-logo {
    height: 28px;
    width: auto;
    filter: brightness(0) invert(1); /* force white */
}
.rpt-hdr-intelligence {
    font-size: 7pt;
    font-weight: 400;
    letter-spacing: 0.18em;
    color: rgba(255, 255, 255, 0.60);
    margin-top: 2px;
    margin-left: 36px;
}
.rpt-hdr-divider {
    width: 1px;
    height: 22px;
    background: rgba(255, 255, 255, 0.22);
    flex-shrink: 0;
}
.rpt-hdr-doctype {
    font-size: 9.5pt;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}
.rpt-hdr-doctype span {
    display: block;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.60);
    letter-spacing: 0.14em;
    font-size: 8pt;
    margin-top: 2px;
}
.rpt-hdr-meta {
    display: flex;
    gap: 24px;
    align-items: center;
}
.rpt-hdr-meta-item { text-align: right; }
.rpt-hdr-meta-item .k {
    font-size: 7.5pt;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    font-weight: 700;
    line-height: 1;
}
.rpt-hdr-meta-item .v {
    font-size: 10pt;
    color: #FFFFFF;
    font-weight: 700;
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
}
.rpt-hdr-stripe {
    height: 3px;
    background: var(--rpt-blue);
}

/* ── Brand header ───────────────────────────────────────────────────────── */
.report-brand-header {
    padding: 22px 28px 18px;
    border-bottom: 1px solid var(--rpt-card-border);
}

.brand-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--rpt-blue);
    margin-bottom: 4px;
}

.report-title {
    font-size: 24px;
    font-weight: 800;
    color: var(--rpt-navy);
    line-height: 1.2;
    margin-bottom: 4px;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.report-subtitle {
    font-size: 12px;
    color: var(--rpt-mid-gray);
}

/* ── Section structure ─────────────────────────────────────────────────── */
.report-section { border-top: 1px solid var(--rpt-card-border); }

.section-rule {
    height: 3px;
    background: var(--rpt-blue);
}

.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 28px;
    background: var(--rpt-navy);
}

.section-header-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.section-num {
    font-size: 10px;
    font-weight: 700;
    color: rgba(255, 255, 255, .35);
    font-family: var(--rpt-font-mono);
}

.section-title {
    font-size: 12px;
    font-weight: 700;
    color: #FFFFFF;
    text-transform: uppercase;
    letter-spacing: .10em;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.section-subtitle {
    font-size: 11px;
    color: rgba(255, 255, 255, .40);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 420px;
}

.section-body { padding: 22px 28px; }

/* ── Stats row (3 stat boxes) ──────────────────────────────────────────── */
.stats-row {
    display: grid;
    /* Wraps to a single column once a stat box would fall below ~220px wide. */
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
}

.stat-box {
    background: var(--rpt-page-bg);
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    padding: 18px 20px;
    text-align: center;
}

.stat-number {
    font-size: 40px;
    font-weight: 900;
    color: var(--rpt-navy);
    line-height: 1;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.stat-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .10em;
    color: var(--rpt-mid-gray);
    margin-top: 6px;
}

/* ── Charts grid + cards ───────────────────────────────────────────────── */
.charts-grid {
    display: grid;
    /* 3 → 2 → 1 columns as the viewport narrows. Each chart card retains a
       usable size (≥ 280px) instead of shrinking to an unreadable strip. */
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 20px;
    align-items: start;
}

.chart-card {
    background: #FFFFFF;
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    padding: 18px;
}

.chart-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--rpt-ink);
    margin-bottom: 2px;
}

.chart-count {
    font-size: 11px;
    color: var(--rpt-mid-gray);
    margin-bottom: 12px;
}

.chart-wrap {
    position: relative;
    height: 160px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.chart-wrap canvas {
    max-width: 100%;
    max-height: 100%;
}

/* Pure-SVG donut (replaces Syncfusion SfAccumulationChart so the chart
   renders reliably in the static-SSR print path). Square viewBox, height
   bounded by the chart-wrap. */
.donut-svg {
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    display: block;
    aspect-ratio: 1 / 1;
}
.donut-empty {
    color: var(--rpt-mute-gray);
    font-size: 12px;
}

/* Pure-SVG bar chart (replaces Syncfusion SfChart). Fills the chart-wrap;
   viewBox uses preserveAspectRatio=none so columns stretch to the
   container's aspect ratio without distorting label text (text rendering
   is unaffected by viewBox stretch in modern browsers). */
.bar-svg {
    width: 100%;
    height: 100%;
    display: block;
}

.donut-center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    text-align: center;
}

.donut-pct {
    font-size: 28px;
    font-weight: 900;
    line-height: 1;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.donut-sub {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--rpt-mid-gray);
    margin-top: 1px;
}

/* ── Chart legends ─────────────────────────────────────────────────────── */
.chart-legend {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.legend-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 11.5px;
}

.legend-left {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

.legend-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

.legend-label {
    color: var(--rpt-text-secondary);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.legend-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.legend-pct {
    color: var(--rpt-mid-gray);
    font-size: 11px;
}

.legend-count {
    font-weight: 700;
    color: var(--rpt-ink);
    font-size: 11px;
    font-family: var(--rpt-font-mono);
    min-width: 24px;
    text-align: right;
}

/* ── Two-column section + top-5 ingredient cards ───────────────────────── */
.two-col {
    display: grid;
    /* Stacks to a single column once each card would fall below ~360px. */
    grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
    gap: 20px;
}

.top5-card {
    background: #FFFFFF;
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    padding: 18px;
}

.top5-title {
    font-size: 13px;
    font-weight: 700;
    margin-bottom: 4px;
}

.top5-subtitle {
    font-size: 11px;
    color: var(--rpt-mid-gray);
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--rpt-card-border);
}

.col-headers {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rpt-card-border);
    margin-bottom: 10px;
}

.col-header-text {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--rpt-mid-gray);
}

.ing-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

.ing-row:last-child { margin-bottom: 0; }

.ing-rank {
    font-size: 11px;
    font-weight: 700;
    color: var(--rpt-mute-gray);
    font-family: var(--rpt-font-mono);
    width: 16px;
    flex-shrink: 0;
    text-align: right;
}

.ing-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--rpt-ink);
    width: 160px;
    flex-shrink: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ing-bar-wrap {
    flex: 1;
    background: var(--rpt-page-bg);
    border-radius: 999px;
    height: 10px;
    overflow: hidden;
    border: 1px solid var(--rpt-card-border);
}

.ing-bar {
    height: 100%;
    border-radius: 999px;
    min-width: 2px;
}

.ing-pct {
    font-size: 12px;
    font-weight: 700;
    font-family: var(--rpt-font-mono);
    width: 36px;
    text-align: right;
    flex-shrink: 0;
}

/* Empty-state card — PRD §4.4: centered, italicized, dashed border */
.empty-card-note {
    text-align: center;
    padding: 16px;
    margin-top: 6px;
    color: var(--rpt-mute-gray);
    font-size: 12px;
    font-style: italic;
    background: var(--rpt-page-bg);
    border-radius: 8px;
    border: 1px dashed var(--rpt-card-border);
}

/* Footer "no further detected" — when 1–4 of top-5 are shown */
.no-further-note {
    padding: 12px 0 4px;
    font-size: 11px;
    color: var(--rpt-mute-gray);
    font-style: italic;
    text-align: center;
}

/* ── SKU table ─────────────────────────────────────────────────────────── */
.product-table {
    width: 100%;
    border-collapse: collapse;
    /* `fixed` layout respects the column widths we set below — it stops the
       browser from ballooning the table beyond its container just because
       the Product name on one row is long. That, combined with widths set
       on the trailing 5 columns and width:auto on the Product column, gives
       the wrap priority the user described:
         • UPC (and the others, in principle) wrap before Product, because
           Product gets all the leftover width.
         • Product wraps only when the available width is shorter than what
           the product name + the fixed-width columns would need on a single
           line. */
    table-layout: fixed;
}

.product-table th {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: .09em;
    font-weight: 700;
    color: var(--rpt-mid-gray);
    text-align: left;
    padding: 8px 12px;
    border-bottom: 2px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
}

.product-table td {
    padding: 9px 12px;
    border-bottom: 1px solid var(--rpt-card-border);
    font-size: 13px;
    color: var(--rpt-ink);
    vertical-align: middle;
    /* Default: cells stay on one line. Wrapping is opt-in per column
       (only the UPC cell does so below). Status / "N ingredients" /
       View Report button cells are short enough that they never need
       to wrap. */
    white-space: nowrap;
}

.product-table th { white-space: nowrap; }

/* Product (first) column: takes whatever width the trailing columns
   don't claim. With table-layout: fixed and explicit widths on the
   other columns (below), Product is effectively "width: auto" — it
   eats the leftover space. White-space normal so the product name
   can wrap as a LAST resort when even the UPC column wrapping isn't
   enough to fit everything in the table. */
.product-table td:first-child,
.product-table th:first-child {
    white-space: normal;
    width: auto;
}

/* UPC column: 140px is just wide enough for "8 10207 71198 8" on
   one line at the 11px JetBrains Mono font. White-space normal +
   the non-breaking spaces in UpcFormatter mean if the cell ever
   wraps, it does so at the middle space ("8 10207" / "71198 8").
   In practice, the fixed 140px width keeps it single-line. */
.product-table td:nth-child(2),
.product-table th:nth-child(2) {
    white-space: normal;
    width: 140px;
}

.product-table td:nth-child(3), .product-table th:nth-child(3) { width: 130px; }
.product-table td:nth-child(4), .product-table th:nth-child(4) { width: 160px; }
.product-table td:nth-child(5), .product-table th:nth-child(5) { width: 170px; }
.product-table td:nth-child(6), .product-table th:nth-child(6) { width: 130px; }

/* Last-column tweak: View Report button column hugs the right edge. */
.product-table td:last-child,
.product-table th:last-child {
    text-align: right;
}

.product-table tr.product-row {
    cursor: pointer;
    transition: background-color .12s ease;
}

.product-table tr.product-row:hover td {
    background: var(--rpt-row-hover-bg);
}

/* Paywall-locked rows: muted name + no hover affordance (not a click target). */
.product-table tr.product-row.is-locked { cursor: default; }
.product-table tr.product-row.is-locked .product-name { color: var(--rpt-mid-gray); }
.product-table tr.product-row.is-locked:hover td { background: transparent; }

/* Admin override (task 230): a locked row an internal admin may still open —
   amber name + clickable + hover restored, so it reads as "gated, but open as admin". */
.product-table tr.product-row.is-locked.is-admin-override { cursor: pointer; }
.product-table tr.product-row.is-locked.is-admin-override .product-name { color: var(--rpt-unknown-text); }
.product-table tr.product-row.is-locked.is-admin-override:hover td { background: var(--rpt-row-hover-bg); }

.product-table tr:last-child td { border-bottom: none; }

.product-name { font-weight: 600; text-transform: capitalize; }

.product-upc {
    font-family: var(--rpt-font-mono);
    font-size: 11px;
    color: var(--rpt-mid-gray);
}

/* ── Drill button (View Report) ────────────────────────────────────────── */
.drill-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    background: var(--rpt-page-bg);
    border: 1px solid var(--rpt-card-border);
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    color: var(--rpt-blue);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    font-family: var(--rpt-font-body);
}

.drill-btn:hover { background: var(--rpt-card-border); }

.drill-btn svg {
    width: 11px;
    height: 11px;
    flex-shrink: 0;
}

/* Locked-food affordance — replaces the "View Report" drill for discovered foods
   below the free top-N (paywall: claim to unlock). Shared by every report product
   table (Code Insights, GRAS, UPF) so the lock treatment stays consistent, and
   matches the report food-picker's muted lock. */
.report-lock-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--rpt-mid-gray);
    cursor: default;
    /* Reset so the admin-override variant can render as a <button> with no
       default chrome while the customer (locked) variant stays a <span>. */
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
}

.report-lock-badge .material-icons {
    font-size: 16px;
    line-height: 1;
}

/* Admin paywall override (task 230): the SAME lock glyph, amber-tinted and
   clickable. Shown only to internal Identity Admins who may open a per-food
   report that is still locked for the brand — never a plain-unlocked drill, so
   the admin always sees the row is gated behind a claim. */
.report-lock-badge--override {
    color: var(--rpt-unknown-color);
    cursor: pointer;
}

.report-lock-badge--override:hover { color: var(--rpt-unknown-text); }

/* ── GRAS status badges ────────────────────────────────────────────────── */
.gras-badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.gras-badge-gras           { background: var(--rpt-gras-bg);     color: var(--rpt-gras-text); }
.gras-badge-historical     { background: var(--rpt-hist-bg);     color: var(--rpt-hist-text); }
.gras-badge-unknownflavors { background: var(--rpt-uflavors-bg); color: var(--rpt-uflavors-text); }
.gras-badge-unclear        { background: var(--rpt-unclear-bg);  color: var(--rpt-unclear-text); }
.gras-badge-unknown        { background: var(--rpt-unknown-bg);  color: var(--rpt-unknown-text); }
.gras-badge-nongras        { background: var(--rpt-unsafe-bg);   color: var(--rpt-unsafe-text); }

/* ── UPF processing-level badges (5 tiers per PRD §2.3) ────────────────── */
.upf-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.upf-badge-min    { background: #DCFCE7; color: #166534; }
.upf-badge-light  { background: #D1FAE5; color: #065F46; }
.upf-badge-mod    { background: #FEF3C7; color: #92400E; }
.upf-badge-ultra  { background: #FFF7ED; color: var(--rpt-pl3); }
.upf-badge-super  { background: #FEE2E2; color: var(--rpt-pl4); }
.upf-badge-nonupf { background: #DCFCE7; color: #166534; }

/* ── Shield status pills (Non-UPF Verified / Pre-Qualified / Ineligible) */
.status-pill {
    display: inline-flex;
    align-items: center;
    padding: 3px 11px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    border: 1px solid;
    white-space: nowrap;
}

.status-pill-pass { background: #F0FDF4; color: #166534; border-color: #86EFAC; }
.status-pill-preq { background: #E8E8FA; color: #1E4368; border-color: #C9C8F0; }
.status-pill-fail { background: #FEE2E2; color: #991B1B; border-color: #FCA5A5; }

/* ── Top-10 high-processing ingredient list (Portfolio UPF §03) ────────── */
.top10-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rpt-card-border);
    margin-bottom: 12px;
}

.top10-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ingredient-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.ingredient-rank {
    font-size: 11px;
    font-weight: 700;
    color: var(--rpt-mute-gray);
    font-family: var(--rpt-font-mono);
    width: 20px;
    flex-shrink: 0;
    text-align: right;
}

.ingredient-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--rpt-ink);
    width: 200px;
    flex-shrink: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ingredient-bar-wrap {
    flex: 1;
    background: var(--rpt-page-bg);
    border-radius: 999px;
    height: 10px;
    overflow: hidden;
    border: 1px solid var(--rpt-card-border);
}

.ingredient-bar {
    height: 100%;
    border-radius: 999px;
    transition: width .3s ease;
    min-width: 2px;
}

.ingredient-pct {
    font-size: 12px;
    font-weight: 700;
    color: var(--rpt-ink);
    font-family: var(--rpt-font-mono);
    width: 40px;
    text-align: right;
    flex-shrink: 0;
}

.pl-badge {
    padding: 2px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    width: 36px;
    text-align: center;
    flex-shrink: 0;
    white-space: nowrap;
}

.pl-badge-pl4 { background: #FEE2E2; color: var(--rpt-pl4); }
.pl-badge-pl3 { background: #FFF7ED; color: var(--rpt-pl3); }
.pl-badge-pl2 { background: #F0FDFA; color: var(--rpt-hist-text); }
.pl-badge-pl1 { background: #DCFCE7; color: #166534; }

/* ── UPC Product Header — PRD §5.1 / §6.1 ─────────────────────────────── */
/* UPC GRAS / UPF / Insights wrapper. The Insights variant is wider
   per the prototype (1020 px vs 920 px), so it picks up an extra
   modifier below. */
.upc-wrapper { min-width: 880px; max-width: 920px; }
.upc-wrapper.upc-insights-wrapper { max-width: 1020px; }

.upc-product-header {
    padding: 24px 28px 20px;
    border-bottom: 1px solid var(--rpt-card-border);
    display: grid;
    grid-template-columns: 110px 1fr auto;
    gap: 24px;
    align-items: start;
}

.upc-image {
    width: 110px;
    height: 110px;
    border-radius: 8px;
    border: 1px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
    overflow: hidden;
}

.upc-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 7px;
}

.upc-image-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
}

.upc-text { display: flex; flex-direction: column; gap: 5px; }

.upc-text .brand-name-line {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--rpt-blue);
    margin-bottom: 5px;
}

.upc-text .product-name-line {
    font-size: 26px;
    font-weight: 800;
    color: var(--rpt-navy);
    line-height: 1.15;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.upc-badges {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
    margin-top: 6px;
}

.upc-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    border: 1px solid;
}

/* Proto colours: Non-UPF Verified is a green pill (verified status pop), Brand
   Claimed is an indigo pill. Only rendered when Identity.NonUpfVerified /
   Identity.BrandClaimed is true. */
.upc-badge-claimed { background: #ECF1F6; color: #163450; border-color: #CBD9E8; }
.upc-badge-shield  { background: #DCFCE7; color: #166534; border-color: #BBF7D0; }
.upc-badge-check   { font-weight: 700; line-height: 1; }

/* ── Shared UPC / GTIN block (Components/Shared/Reports/ReportUpcBlock.razor)
       Mirrors .ss-product-id from the food spec sheet so the barcode strip
       reads identically across artefacts. ─────────────────────────────── */
.rpt-upc-block {
    text-align: right;
    font-variant-numeric: tabular-nums;
    min-width: 160px;
}
.rpt-upc-block .lbl {
    font-size: 7.5pt;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--rpt-mid-gray);
    font-weight: 700;
}
.rpt-upc-block .val {
    font-size: 12pt;
    font-weight: 700;
    color: var(--rpt-ink);
    margin-top: 2px;
}
.rpt-upc-barcode {
    margin-top: 6px;
    height: 56px;
    width: auto;
    max-width: 200px;
    display: inline-block;
}
.rpt-upc-barcode:not([src]),
.rpt-upc-barcode[src=""] { display: none; }

/* ── UPC GRAS S01: three-column layout ─────────────────────────────────── */
.upc-gras-s1-grid {
    display: grid;
    /* Verdict / donut / What-is-GRAS panel — stack to fewer columns when
       any card would shrink below 260px. */
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 20px;
    align-items: start;
}

.gras-verdict-card {
    border-radius: 10px;
    padding: 18px 14px;
    border: 1px solid;
    text-align: center;
}

.gras-verdict-card.gras-verdict-pass    { background: var(--rpt-gras-bg);     border-color: #86EFAC; }
.gras-verdict-card.gras-verdict-neutral { background: var(--rpt-uflavors-bg); border-color: #FDE047; }
.gras-verdict-card.gras-verdict-fail    { background: var(--rpt-unsafe-bg);   border-color: #FCA5A5; }

.gras-verdict-icon {
    font-size: 26px;
    margin-bottom: 6px;
    line-height: 1;
}

.gras-verdict-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .10em;
    color: var(--rpt-mid-gray);
    margin-bottom: 4px;
}

.gras-verdict-value {
    font-size: 18px;
    font-weight: 800;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.gras-verdict-value.is-pass    { color: var(--rpt-gras-text); }
.gras-verdict-value.is-neutral { color: var(--rpt-uflavors-text); }
.gras-verdict-value.is-fail    { color: var(--rpt-unsafe-text); }

.gras-verdict-sub {
    font-size: 10.5px;
    color: var(--rpt-mid-gray);
    margin-top: 5px;
    line-height: 1.4;
}

.donut-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}

.donut-side-legend {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    max-width: 260px;
}

/* ── "What is GRAS?" navy card ─────────────────────────────────────────── */
.what-is-gras-card {
    background: var(--rpt-navy);
    border-radius: 10px;
    padding: 18px;
    color: #FFFFFF;
}

.what-is-gras-card .wig-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: rgba(255, 255, 255, .40);
    margin-bottom: 8px;
}

.what-is-gras-card .wig-title {
    font-size: 13px;
    font-weight: 700;
    color: #FFFFFF;
    margin-bottom: 10px;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.what-is-gras-card .wig-body {
    font-size: 12px;
    color: rgba(255, 255, 255, .72);
    line-height: 1.65;
}

.what-is-gras-card .wig-divider {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, .12);
}

.what-is-gras-card .wig-defs {
    font-size: 11px;
    color: rgba(255, 255, 255, .50);
    line-height: 1.55;
}

.what-is-gras-card .wig-defs strong {
    color: rgba(255, 255, 255, .70);
    font-weight: 700;
}

/* ── Ingredient group labels (UPC GRAS §02) ────────────────────────────── */
.ingredient-group-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .10em;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ── UPC GRAS ingredient table ─────────────────────────────────────────── */
.gras-ingredient-table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 4px;
}

.gras-ingredient-table th {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-weight: 700;
    color: var(--rpt-mid-gray);
    text-align: left;
    padding: 8px 12px;
    border-bottom: 2px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
}

.gras-ingredient-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--rpt-card-border);
    font-size: 12.5px;
    color: var(--rpt-ink);
    vertical-align: top;
}

.gras-ingredient-table tr:last-child td { border-bottom: none; }

.ing-cell-name {
    font-weight: 700;
    color: var(--rpt-ink);
}

.ing-cell-explanation {
    font-size: 11.5px;
    color: var(--rpt-text-secondary);
    line-height: 1.55;
}

/* ── UPC UPF S01: shield bar + verdict cards ───────────────────────────── */
.upf-shield-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--rpt-page-bg);
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    padding: 10px 16px;
    margin-bottom: 16px;
}

.upf-shield-bar-left {
    display: flex;
    align-items: center;
    gap: 10px;
}

.upf-shield-bar-meta {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.upf-shield-bar-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .10em;
    color: var(--rpt-mid-gray);
}

.upf-shield-bar-desc {
    font-size: 12px;
    color: var(--rpt-text-secondary);
    line-height: 1.4;
}

.upf-verdict-row {
    display: grid;
    /* WISEcode Classification + Processing Level cards — stack vertically
       when either would fall below 320px. */
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 16px;
}

.upf-verdict-card {
    border-radius: 8px;
    padding: 16px 18px;
    border: 1px solid;
}

.upf-verdict-card.upf-verdict-pass {
    background: #F0FDF4;
    border-color: #86EFAC;
}

.upf-verdict-card.upf-verdict-amber {
    background: #FEF3C7;
    border-color: #FCD34D;
}

.upf-verdict-card.upf-verdict-fail {
    background: var(--rpt-unsafe-bg);
    border-color: #FCA5A5;
}

.upf-verdict-top {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.upf-verdict-icon {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 700;
    flex-shrink: 0;
    color: #FFFFFF;
}

.upf-verdict-icon.vi-pass  { background: #16A34A; }
.upf-verdict-icon.vi-amber { background: #D97706; }
.upf-verdict-icon.vi-fail  { background: var(--rpt-unsafe-color); }

.upf-verdict-kicker {
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: .10em;
    font-weight: 700;
}

.upf-verdict-kicker.vk-pass  { color: var(--rpt-gras-text); }
.upf-verdict-kicker.vk-amber { color: #92400E; }
.upf-verdict-kicker.vk-fail  { color: var(--rpt-unsafe-text); }

.upf-verdict-value {
    font-size: 18px;
    font-weight: 800;
    color: var(--rpt-navy);
    margin-top: 1px;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

.upf-verdict-why {
    font-size: 11.5px;
    color: var(--rpt-text-secondary);
    line-height: 1.55;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(0, 0, 0, .07);
}

/* ── UPC UPF S02: processing ingredient table ──────────────────────────── */
.upf-ingredient-table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 4px;
}

.upf-ingredient-table th {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-weight: 700;
    color: var(--rpt-mid-gray);
    text-align: left;
    padding: 8px 12px;
    border-bottom: 2px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
}

.upf-ingredient-table th .col-subtitle {
    font-size: 9px;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: var(--rpt-mute-gray);
    display: block;
}

.upf-ingredient-table td {
    padding: 9px 12px;
    border-bottom: 1px solid var(--rpt-card-border);
    font-size: 12.5px;
    color: var(--rpt-ink);
    vertical-align: top;
}

.upf-ingredient-table tr:last-child td { border-bottom: none; }

.upf-ingredient-table .group-row td {
    background: var(--rpt-page-bg);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--rpt-mid-gray);
    padding: 6px 12px;
}

.level-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    white-space: nowrap;
}

.level-pill.lp-high { background: #FEE2E2; color: var(--rpt-unsafe-text); }
.level-pill.lp-mod  { background: #FFF7ED; color: var(--rpt-pl3); }
.level-pill.lp-low  { background: #F0FDF4; color: var(--rpt-gras-text); }

.score-num {
    font-family: var(--rpt-font-mono);
    font-size: 13px;
    font-weight: 700;
}

.score-num.score-high { color: var(--rpt-pl4); }
.score-num.score-mod  { color: var(--rpt-pl3); }
.score-num.score-low  { color: var(--rpt-pl2); }

/* ── Footer — mirrors the spec-sheet footer (small WISEcode bug + report
       summary on the left, ID / generated / wisecode.ai on the right). The
       light-grey colour scheme departs from the report's earlier navy footer
       so the artefact-style typography reads cleanly at print sizes. ─── */
.rpt-footer {
    margin-top: auto;
    padding: 14px 32px 18px;
    border-top: 1px solid var(--rpt-card-border);
    background: #FFFFFF;
    border-radius: 0 0 6px 6px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 8pt;
    color: var(--rpt-mid-gray);
    flex-wrap: wrap;
    gap: 8px 18px;
}
.rpt-footer-left {
    display: flex;
    align-items: center;
    gap: 10px;
    /* min-width: 0 lets the left side shrink instead of bullying the right
       side off the row; once the container can't fit both, flex-wrap moves
       the right side to a second row (still right-aligned via margin-left). */
    min-width: 0;
    flex: 1 1 auto;
}
.rpt-footer-left > span {
    min-width: 0;
}
.rpt-footer-logo {
    height: 16px;
    width: auto;
    flex-shrink: 0;
}
.rpt-footer strong {
    color: var(--rpt-ink);
    font-weight: 700;
}
.rpt-footer-right {
    display: flex;
    gap: 18px;
    align-items: center;
    flex-wrap: wrap;
    /* Keeps the right side pinned right even after flex-wrap pushes it onto
       its own row — without this, `justify-content: space-between` only
       right-aligns it WITHIN a row, so the wrapped row left-aligns. */
    margin-left: auto;
}
.rpt-footer-right a {
    color: var(--rpt-blue);
    font-weight: 700;
    text-decoration: none;
}

/* ──────────────────────────────────────────────────────────────────────────
   UPC Insights Report
   Per the HTML prototype: §02 WISEscore (left score pane + right radar
   chart) and §03/§04/§05 metric tables with score / rating / position-
   bar / vs-brand-avg / drill-button columns.
   ──────────────────────────────────────────────────────────────────────── */

/* ── §02 WISEscore grid: 320px score pane + flex radar pane ───────────── */
.ws-grid {
    display: grid;
    grid-template-columns: 320px 1fr;
    background: #FFFFFF;
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    overflow: hidden;
}
.ws-score-pane { padding: 22px 24px; border-right: 1px solid var(--rpt-card-border); }
.ws-top { display: flex; align-items: center; gap: 18px; margin-bottom: 14px; }
.ws-ring {
    width: 96px; height: 96px;
    border-radius: 50%;
    border: 5px solid;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    flex-shrink: 0;
}
.ws-num { font-size: 32px; font-weight: 800; color: var(--rpt-navy); line-height: 1; }
.ws-rtg { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; margin-top: 2px; }
.ws-headline { font-size: 14px; font-weight: 700; color: var(--rpt-navy); }
.ws-body { font-size: 12px; color: var(--rpt-mid-gray); line-height: 1.65; margin-top: 5px; }
.ws-pillars-label {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
    color: var(--rpt-mid-gray); margin-bottom: 10px; margin-top: 4px;
}
.ws-pillars { display: flex; flex-direction: column; gap: 8px; }
.ws-pillar-row { display: flex; align-items: center; gap: 10px; }

/* Pill variant of pillars — Portfolio Insights' "chip" layout that
   replaces the horizontal bars when WiseScorePane is rendered with
   PillarsLayout="pills". */
.ws-pillars-pills {
    display: flex;
    flex-direction: row;
    gap: 8px;
    margin-top: 14px;
    flex-wrap: wrap;
}
.ws-pill {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    border-radius: 20px;
    border: 1px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
    font-size: 11px;
}
.pill-name { color: var(--rpt-mid-gray); font-weight: 500; }
.pill-score {
    color: var(--rpt-navy);
    font-weight: 800;
    font-family: var(--rpt-font-mono);
}
.pill-badge {
    font-size: 10px;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
}
.wp-name { font-size: 12px; color: var(--rpt-mid-gray); font-weight: 500; width: 140px; flex-shrink: 0; }
.wp-track { flex: 1; height: 8px; background: #F1F3F7; border-radius: 4px; overflow: visible; position: relative; }
.wp-fill { height: 100%; border-radius: 4px; transition: width .4s; }
.wp-score {
    font-size: 12px; font-weight: 700; color: var(--rpt-navy);
    font-family: var(--rpt-font-mono); width: 28px; text-align: right;
}
.ws-radar-pane { padding: 18px 22px; }

/* ── Polar-area WISEscore chart (WiseScoreRadar.razor) ──────────────────────
   15 wedges sized by score + coloured by pillar, on a shadowed "well" with
   grid rings, spokes, ring-value + rim axis labels. Matches the analytics-
   types prototype's pa-* chart. Pure SVG; native <title> = hover tooltip. */
.pa-card-title {
    font-family: 'Noto Serif', Georgia, 'Times New Roman', serif;
    font-size: 17px; font-weight: 700; color: #111827;
    letter-spacing: -.01em; margin-bottom: 6px;
}
.pa-wrap { width: 100%; max-width: 440px; margin: 4px auto 0; }
.pa-svg { width: 100%; height: auto; display: block; overflow: visible; }
.pa-bg   { fill: #F7F6F1; }   /* warm linen — color-mix(border 60%, surface) */
.pa-grid  { fill: none; stroke: rgba(17, 24, 39, .06); stroke-width: 1; }
.pa-spoke { stroke: rgba(17, 24, 39, .06); stroke-width: 1; }
/* Wedges read as raised, glossy petals: 0.92 fill, white seams, layered
   drop-shadows for depth. Matches the prototype's .pa-wedge exactly. */
.pa-wedge {
    fill-opacity: .92;
    stroke: #FFFFFF; stroke-width: 1.5; stroke-linejoin: round;
    filter: drop-shadow(0 3px 5px rgba(8, 15, 26, .22)) drop-shadow(0 1px 1.5px rgba(8, 15, 26, .16));
    transition: fill-opacity .15s, filter .15s;
    cursor: pointer;
}
/* Hover: the wedge goes fully opaque, brightens, and glows in its OWN colour
   (currentColor, set inline per wedge). No sibling dimming. */
.pa-wedge:hover {
    fill-opacity: 1;
    filter: brightness(1.05) drop-shadow(0 7px 11px rgba(8, 15, 26, .28)) drop-shadow(0 0 6px currentColor);
}
.pa-axis-label { fill: #444B55; font-family: var(--rpt-font-body); font-size: 12px; font-weight: 600; }
.pa-ringval    { fill: #474E58; font-family: var(--rpt-font-body); font-size: 12px; font-weight: 600; }

.pa-legend {
    display: flex; gap: 18px; justify-content: center; margin-top: 14px;
    flex-wrap: wrap; font-size: 13px; color: var(--rpt-text-secondary); font-weight: 500;
}
.pa-legend-item { display: flex; align-items: center; gap: 8px; }
.pa-legend-item strong { font-weight: 700; color: #111827; }
.pa-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; display: inline-block; }

@media print {
    /* Drop-shadow filters can render heavily in headless Chromium — keep the
       hover affordances out of the static PDF. */
    .pa-wedge { transition: none; }

    /* The grid rings and spokes use a 6%-alpha 1px stroke that reads as a
       barely-there hairline on screen. Chromium's PDF rasterizer composites
       thin SEMI-TRANSPARENT strokes far more opaquely than the on-screen GPU
       compositor, so any low-alpha hairline prints noticeably darker — even at
       3% alpha. The rasterizer-proof fix is an OPAQUE colour (no alpha to
       over-composite): #ECEDEF is the visual equivalent of the on-screen
       6%-alpha line on white, so the PDF now matches the light screen look.
       Screen rendering is untouched (this block is print-only). */
    .pa-grid,
    .pa-spoke { stroke: #ECEDEF; stroke-opacity: 1; }
}

/* ── Metric table (§03/§04/§05) ───────────────────────────────────────── */
.metric-tbl-wrap { border: 1px solid var(--rpt-card-border); border-radius: 8px; overflow: hidden; }
.metric-tbl-hdr {
    display: grid;
    grid-template-columns: 200px 72px 98px 1fr 118px 88px;
    background: var(--rpt-page-bg);
    border-bottom: 2px solid var(--rpt-card-border);
    padding: 9px 16px;
}
.metric-tbl-hdr span {
    font-size: 10px; font-weight: 700; color: var(--rpt-mid-gray);
    text-transform: uppercase; letter-spacing: .09em;
}
.metric-tbl-hdr .col-pos-sub { font-size: 9px; opacity: .6; font-weight: 700; }
.metric-row {
    display: grid;
    grid-template-columns: 200px 72px 98px 1fr 118px 88px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--rpt-card-border);
    align-items: center;
    cursor: pointer;
    transition: background .1s ease;
}
.metric-row:last-child { border-bottom: none; }
.metric-row:hover { background: var(--rpt-row-hover-bg); }
.metric-row.sub { background: #F8FAFC; border-bottom: 1px solid #ECF1F6; }
.metric-row.sub:last-child { border-bottom: none; }
.metric-row.sub:hover { background: #F0F4FF; }

.comp-sep {
    background: #EFF6FF; border-top: 1px solid #BFDBFE; border-bottom: 1px solid #BFDBFE;
    padding: 7px 16px 7px 38px; display: flex; align-items: center; gap: 8px;
}
.comp-sep-badge {
    background: #DBEAFE; color: #1D4ED8;
    font-size: 9px; font-weight: 700; padding: 2px 8px; border-radius: 10px;
    letter-spacing: .06em; text-transform: uppercase;
}
.comp-sep-title { font-size: 11px; font-weight: 700; color: #1D4ED8; }

.c-name-wrap { padding-right: 8px; }
.c-name {
    font-size: 13px; font-weight: 700; color: var(--rpt-ink);
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap; line-height: 1.3;
}
.c-tag {
    font-size: 9px; font-weight: 700; padding: 2px 6px; border-radius: 4px;
    letter-spacing: .05em; flex-shrink: 0; text-transform: uppercase;
}
.tag-comp { background: #DBEAFE; color: #1D4ED8; }
.tag-sub  { background: #ECF1F6; color: #163450; }
.c-desc { font-size: 11px; color: var(--rpt-mid-gray); margin-top: 3px; line-height: 1.45; }
.sub-indent { border-left: 3px solid #BFDBFE; padding-left: 10px; margin-left: 2px; }

.c-score {
    font-size: 22px; font-weight: 800; color: var(--rpt-navy);
    font-family: var(--rpt-font-mono); line-height: 1;
}
.c-score-lbl { font-size: 10px; color: var(--rpt-mid-gray); margin-top: 1px; }

.rating-badge {
    display: inline-block; padding: 3px 11px; border-radius: 999px;
    font-size: 11px; font-weight: 700; white-space: nowrap;
}
.rating-excellent { background: #DCFCE7; color: #166534; }
.rating-good      { background: #CCFBF1; color: #0F766E; }
.rating-ok        { background: #DBEAFE; color: #1D4ED8; }
.rating-fair      { background: #FEF3C7; color: #92400E; }
.rating-poor      { background: #FEE2E2; color: #991B1B; }

/* Score position bar — 5-stop gradient with SKU marker (navy) + brand-
   average marker (transparent black). */
.pos-wrap { padding-right: 12px; }
.pos-track {
    height: 10px;
    background: linear-gradient(to right,
        #16A34A 0%, #16A34A 20%,
        #0D9488 20%, #0D9488 40%,
        #2563EB 40%, #2563EB 60%,
        #D97706 60%, #D97706 80%,
        #DC2626 80%, #DC2626 100%);
    opacity: .18;
    border-radius: 5px;
    position: relative;
}
.pos-markers { position: relative; height: 16px; margin-top: -4px; }
.pos-marker-product {
    position: absolute; top: 0;
    width: 3px; height: 14px;
    background: var(--rpt-navy);
    border-radius: 2px;
    transform: translateX(-50%);
}
.pos-marker-avg {
    position: absolute; top: 1px;
    width: 2px; height: 12px;
    background: rgba(0, 0, 0, .25);
    border-radius: 1px;
    transform: translateX(-50%);
}
.pos-labels {
    display: flex; justify-content: space-between;
    font-size: 10px; color: var(--rpt-mute-gray); margin-top: 2px;
}
.pos-label-mid { color: var(--rpt-mid-gray); }

.delta-wrap { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.delta-val { font-size: 13px; font-weight: 800; font-family: var(--rpt-font-mono); }
.delta-lbl {
    font-size: 9px; font-weight: 600; color: var(--rpt-mute-gray);
    text-transform: uppercase; letter-spacing: .05em; text-align: center; line-height: 1.3;
}
.delta-pos { color: #16A34A; }
.delta-neg { color: #DC2626; }
.delta-neu { color: var(--rpt-mute-gray); }

/* ──────────────────────────────────────────────────────────────────────────
   Code Insights Report
   Per the HTML prototype: brand header + §01 portfolio distribution
   (stacked bar + legend + "% Excellent" stat + description note), §02
   top-5 products, §03 full ranked product table.
   ──────────────────────────────────────────────────────────────────────── */

/* Brand header (Code Insights) — name + report title + pillar pill. */
.code-brand-header { padding: 22px 28px 18px; border-bottom: 1px solid var(--rpt-card-border); }
.code-brand-label {
    font-size: 10px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--rpt-blue); margin-bottom: 4px;
}
.code-brand-title {
    font-size: 26px; font-weight: 800; color: var(--rpt-navy);
    font-family: 'Helvetica Neue', Arial, sans-serif; line-height: 1.2;
}
.code-pillar-pill {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: 8px;
    padding: 4px 12px;
    border-radius: 999px;
    border: 1px solid;
    font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
}
.code-pillar-pill-nutrient   { background: #DBEAFE; color: #1D4ED8; border-color: #93C5FD; }
.code-pillar-pill-ingredient { background: #CCFBF1; color: #0F766E; border-color: #5EEAD4; }
.code-pillar-pill-health     { background: #DCFCE7; color: #166534; border-color: #86EFAC; }
.code-pillar-pill-pillar     { background: #E7EEF5; color: #163450; border-color: #CBD9E8; }

/* §01 Portfolio Analysis — left % stat + right stacked-bar + legend. */
.code-analysis-top {
    display: flex; align-items: center; gap: 28px; margin-bottom: 16px;
}
.code-excellent-stat {
    flex-shrink: 0; text-align: center; min-width: 130px;
}
.code-excellent-pct {
    font-size: 64px; font-weight: 900; color: #16A34A;
    font-family: 'Helvetica Neue', Arial, sans-serif; line-height: 1;
}
.code-excellent-label {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .10em; color: #166534; margin-top: 4px;
}
.code-excellent-sub {
    font-size: 11px; color: #166534; margin-top: 2px; opacity: .75;
}

.code-dist-main { flex: 1; }
.code-dist-stack {
    height: 36px; border-radius: 8px; overflow: hidden;
    display: flex; width: 100%; margin-bottom: 14px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .08);
}
.code-dist-seg {
    height: 100%; transition: width .4s ease; position: relative;
    display: flex; align-items: center; justify-content: center;
}
.code-dist-seg-label {
    font-size: 10px; font-weight: 800; color: white; white-space: nowrap;
    overflow: hidden; padding: 0 4px;
}
.code-dist-legend {
    display: flex; gap: 20px; flex-wrap: wrap;
}
.code-legend-item { display: flex; align-items: center; gap: 6px; }
.code-legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.code-legend-text { font-size: 12px; font-weight: 600; }
.code-legend-count { font-size: 12px; color: var(--rpt-mid-gray); margin-left: 2px; }

.code-desc-note {
    font-size: 12px; color: var(--rpt-mid-gray); line-height: 1.6;
    padding: 12px 16px; background: var(--rpt-page-bg);
    border-left: 3px solid var(--rpt-card-border);
    border-radius: 0 6px 6px 0;
}
.code-desc-note strong { color: var(--rpt-ink); font-weight: 700; }

/* §02 Top 5. */
.code-top5-grid { display: flex; flex-direction: column; gap: 10px; }
.code-top5-row {
    display: flex; align-items: center; gap: 16px;
    background: var(--rpt-page-bg);
    border: 1px solid var(--rpt-card-border); border-radius: 8px;
    padding: 12px 16px;
}
.code-top5-row.is-top {
    background: linear-gradient(90deg, #F0FDF4, #FFFFFF);
    border-color: #86EFAC;
}
/* Paywall-locked top-5 card: muted name (not a click target). */
.code-top5-row.is-locked .code-top5-name { color: var(--rpt-mid-gray); }
/* Admin override (task 230): amber name signals "gated, open as admin" (cursor set inline). */
.code-top5-row.is-locked.is-admin-override .code-top5-name { color: var(--rpt-unknown-text); }
.code-top5-rank {
    font-size: 18px; font-weight: 900; color: var(--rpt-navy);
    font-family: 'Helvetica Neue', Arial, sans-serif;
    width: 28px; flex-shrink: 0; text-align: center;
}
.code-top5-rank-1 { color: #B45309; }
.code-top5-rank-2 { color: #78716C; }
.code-top5-rank-3 { color: #92400E; }
.code-top5-name { flex: 1; font-size: 14px; font-weight: 700; color: var(--rpt-ink); text-transform: capitalize; }
.code-top5-score-block { text-align: right; }
.code-top5-score {
    font-size: 28px; font-weight: 900; line-height: 1;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}
.code-top5-rating {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; text-align: right;
}

/* §03 Full table. */
.code-table { width: 100%; border-collapse: collapse; }
.code-table th {
    font-size: 10px; text-transform: uppercase; letter-spacing: .09em;
    font-weight: 700; color: var(--rpt-mid-gray); text-align: left;
    padding: 8px 12px; border-bottom: 2px solid var(--rpt-card-border);
    background: var(--rpt-page-bg);
}
.code-table th.num { text-align: right; }
.code-table td {
    padding: 8px 12px; border-bottom: 1px solid var(--rpt-card-border);
    font-size: 13px; color: var(--rpt-ink); vertical-align: middle;
}
.code-table tr:last-child td { border-bottom: none; }
.code-table tr:hover td { background: var(--rpt-row-hover-bg); }
/* Paywall-locked rows: muted + no hover affordance (not a click target). */
.code-table tr.is-locked .product-name { color: var(--rpt-mid-gray); }
.code-table tr.is-locked:hover td { background: transparent; }
/* Admin override (task 230): amber name + hover restored (cursor set inline). */
.code-table tr.is-locked.is-admin-override .product-name { color: var(--rpt-unknown-text); }
.code-table tr.is-locked.is-admin-override:hover td { background: var(--rpt-row-hover-bg); }
.code-score-cell {
    text-align: right; font-weight: 900; font-size: 16px;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}
.code-score-bar-cell { width: 200px; }
.code-score-bar-wrap {
    background: var(--rpt-page-bg);
    border-radius: 999px; height: 8px; overflow: hidden;
    border: 1px solid var(--rpt-card-border);
}
.code-score-bar { height: 100%; border-radius: 999px; }
.code-table-rank {
    color: var(--rpt-mute-gray);
    font-size: 12px;
    font-family: var(--rpt-font-mono);
    font-weight: 600;
}

/* Rating-driven score / pill colours — share the same name scheme as
   the existing rating-* classes used by UPC Insights. */
.code-score-excellent { color: #16A34A; }
.code-score-good      { color: #0F766E; }
.code-score-ok        { color: #1D4ED8; }
.code-score-fair      { color: #D97706; }
.code-score-poor      { color: #DC2626; }

.code-bar-excellent { background: #16A34A; }
.code-bar-good      { background: #14B8A6; }
.code-bar-ok        { background: #3B82F6; }
.code-bar-fair      { background: #D97706; }
.code-bar-poor      { background: #DC2626; }

.code-seg-excellent { background: #16A34A; }
.code-seg-good      { background: #14B8A6; }
.code-seg-ok        { background: #3B82F6; }
.code-seg-fair      { background: #D97706; }
.code-seg-poor      { background: #DC2626; }

/* ──────────────────────────────────────────────────────────────────────────
   Portfolio Insights Report
   Pixel-perfect translation of Portfolio Insights Report Prototype v2.html.
   §02 reuses .ws-grid/.ws-* from Product Insights. The rest of the rules
   (.pi-*) are unique to this report.
   ──────────────────────────────────────────────────────────────────────── */
.portfolio-insights-wrapper { min-width: 980px; max-width: 1060px; }

/* §01 Brand header */
.pi-brand-header {
    padding: 22px 28px 18px;
    border-bottom: 1px solid var(--rpt-card-border);
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
}
.pi-brand-identity { display: flex; flex-direction: column; gap: 4px; }
.pi-brand-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--rpt-blue);
}
.pi-report-title {
    font-size: 24px;
    font-weight: 800;
    color: var(--rpt-navy);
    line-height: 1.2;
}
.pi-report-tagline {
    font-size: 13px;
    font-weight: 500;
    color: var(--rpt-mid-gray);
    margin-top: 2px;
    font-style: italic;
}
.pi-brand-meta {
    font-size: 12px;
    color: var(--rpt-mid-gray);
    margin-top: 4px;
}

/* Shared §06/§07 chart card chrome */
.pi-section-intro {
    font-size: 13px;
    color: var(--rpt-mid-gray);
    line-height: 1.65;
    margin-bottom: 18px;
    max-width: 760px;
}
.pi-chart-card {
    background: var(--rpt-page-bg);
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    padding: 20px 22px;
}
.pi-chart-legend {
    display: flex;
    gap: 14px;
    justify-content: center;
    margin-top: 10px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--rpt-mid-gray);
}
.pi-chart-legend span {
    display: flex;
    align-items: center;
    gap: 5px;
}

/* §03/§04/§05 metric table */
.pi-tbl-wrap {
    border: 1px solid var(--rpt-card-border);
    border-radius: 8px;
    overflow: hidden;
}
.pi-tbl-hdr {
    display: grid;
    grid-template-columns: 215px 75px 100px 1fr 220px 108px;
    background: var(--rpt-page-bg);
    border-bottom: 2px solid var(--rpt-card-border);
    padding: 9px 16px;
}
.pi-tbl-hdr span {
    font-size: 10px;
    font-weight: 700;
    color: var(--rpt-mid-gray);
    text-transform: uppercase;
    letter-spacing: .09em;
}
.pi-metric-row {
    display: grid;
    grid-template-columns: 215px 75px 100px 1fr 220px 108px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--rpt-card-border);
    align-items: start;
    transition: background .1s;
}
.pi-metric-row:last-child { border-bottom: none; }
.pi-metric-row:hover { background: #F8FAFF; }
.pi-metric-row.is-component { background: #F8FAFC; border-bottom: 1px solid #ECF1F6; }
.pi-metric-row.is-component:hover { background: #F0F4FF; }
.pi-metric-row.is-component:last-child { border-bottom: none; }
.pi-comp-sep {
    background: #EFF6FF;
    border-top: 1px solid #BFDBFE;
    border-bottom: 1px solid #BFDBFE;
    padding: 7px 16px 7px 38px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.pi-comp-sep-badge {
    background: #DBEAFE;
    color: #1D4ED8;
    font-size: 9px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 10px;
    letter-spacing: .06em;
    text-transform: uppercase;
}
.pi-comp-sep-title {
    font-size: 11px;
    font-weight: 700;
    color: #1D4ED8;
}
.pi-c-name-wrap { padding-right: 8px; }
.pi-c-name {
    font-size: 13px;
    font-weight: 700;
    color: var(--rpt-ink);
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    line-height: 1.3;
}
.pi-c-tag {
    font-size: 9px;
    font-weight: 700;
    padding: 2px 6px;
    border-radius: 4px;
    letter-spacing: .05em;
    flex-shrink: 0;
    text-transform: uppercase;
}
.pi-c-desc {
    font-size: 11px;
    color: var(--rpt-mid-gray);
    margin-top: 3px;
    line-height: 1.45;
}
.pi-sub-indent {
    border-left: 3px solid #BFDBFE;
    padding-left: 10px;
    margin-left: 2px;
}
.pi-c-score {
    font-size: 21px;
    font-weight: 800;
    color: var(--rpt-navy);
    font-family: var(--rpt-font-mono);
    line-height: 1.1;
}
.pi-c-score-lbl {
    font-size: 10px;
    color: var(--rpt-mid-gray);
    margin-top: 1px;
}

.pi-dist-wrap { padding-right: 14px; min-width: 0; }
.pi-dist-bar {
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    display: flex;
    margin-bottom: 5px;
}
.pi-dist-leg {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.pi-dl-item {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: 10px;
    color: var(--rpt-mid-gray);
    white-space: nowrap;
}
.pi-dl-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
}

.pi-prods { display: flex; flex-direction: column; gap: 5px; }
.pi-prod-row {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}
.pi-ptag {
    font-size: 9px;
    font-weight: 700;
    padding: 2px 5px;
    border-radius: 4px;
    letter-spacing: .05em;
    flex-shrink: 0;
    text-transform: uppercase;
}
.pi-ptop { background: #DCFCE7; color: #166534; }
.pi-pbot { background: #FEE2E2; color: #991B1B; }
.pi-pname {
    font-size: 11px;
    font-weight: 600;
    color: var(--rpt-ink);
    text-transform: capitalize;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}
.pi-pscore {
    font-size: 10px;
    color: var(--rpt-mid-gray);
    font-family: var(--rpt-font-mono);
    flex-shrink: 0;
    padding-left: 4px;
}

.pi-drill-cell {
    display: flex;
    align-items: flex-start;
    padding-top: 2px;
    padding-left: 14px;
}

/* §06 scatter — pure SVG. Width auto-fits the card; aspect ratio is set
   by the SVG viewBox. The .pi-scatter-tip element is created once and
   reused for hover tooltips on every report's data points. */
.pi-scatter { display: block; width: 100%; height: auto; }
.pi-scatter circle[data-tip]:hover { fill-opacity: 1; }
.pi-scatter-tip {
    position: fixed;
    background: var(--rpt-navy);
    color: #FFFFFF;
    padding: 6px 10px;
    border-radius: 6px;
    font-family: var(--rpt-font-body);
    font-size: 11px;
    line-height: 1.4;
    pointer-events: none;
    z-index: 9999;
    white-space: nowrap;
    box-shadow: 0 4px 12px rgba(10, 22, 40, 0.18);
    display: none;
}

/* Two-line radar hover tooltip used in category mode (Portfolio
   Insights). Short metric label on top, color swatch + full name +
   value on the bottom — matches the prototype's Chart.js tooltip. */
.pi-radar-tip {
    position: fixed;
    background: var(--rpt-navy);
    color: #FFFFFF;
    padding: 8px 12px;
    border-radius: 6px;
    font-family: var(--rpt-font-body);
    line-height: 1.4;
    pointer-events: none;
    z-index: 9999;
    box-shadow: 0 4px 12px rgba(10, 22, 40, 0.18);
    display: none;
    min-width: 180px;
}
.pi-radar-tip-short {
    font-size: 11px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.65);
    margin-bottom: 4px;
}
.pi-radar-tip-full {
    font-size: 12px;
    color: #FFFFFF;
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.pi-radar-tip-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}
.pi-radar-tip-full strong {
    font-family: var(--rpt-font-mono);
    font-weight: 700;
    margin-left: auto;
    padding-left: 8px;
}

/* §07 heat-map */
.pi-heatmap-wrap { overflow-x: auto; }
.pi-heatmap {
    border-collapse: collapse;
    font-family: var(--rpt-font-body);
}
.pi-heatmap thead th { font-weight: 600; }
.pi-hm-name-header {
    width: 280px;
    border-bottom: 2px solid var(--rpt-card-border);
}
.pi-hm-col-header {
    width: 44px;
    height: 72px;
    font-size: 9px;
    text-align: center;
    padding: 0 2px 6px;
    vertical-align: bottom;
    border-bottom: 2px solid var(--rpt-card-border);
}
.pi-hm-col-header span {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    display: inline-block;
}
.pi-hm-name {
    font-size: 12px;
    color: var(--rpt-ink);
    font-weight: 600;
    text-transform: capitalize;
    padding: 4px 14px 4px 0;
    /* Allow long product names ("Purely Elizabeth Organic Original
       Granola") to wrap to multiple lines instead of being truncated
       with an ellipsis. Cells stretch row-height to match. */
    white-space: normal;
    line-height: 1.3;
    max-width: 280px;
    border-bottom: 1px solid #F1F3F7;
    vertical-align: middle;
}
.pi-hm-cell {
    width: 44px;
    height: 28px;
    border: 3px solid #FFFFFF;
    border-radius: 3px;
    opacity: 0.83;
}
.pi-heatmap-legend {
    display: flex;
    gap: 14px;
    margin-top: 12px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--rpt-mid-gray);
    align-items: center;
}
.pi-heatmap-legend span {
    display: flex;
    align-items: center;
    gap: 4px;
}
.pi-hm-swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    display: inline-block;
}
.pi-hm-meta {
    margin-left: auto !important;
    font-size: 11px;
    color: var(--rpt-mute-gray);
}

/* Portfolio Insights uses larger §02 typography per the v2 prototype.
   Product Insights inherits the tighter base sizes above. */
.portfolio-insights-wrapper .ws-ring   { width: 106px; height: 106px; }
.portfolio-insights-wrapper .ws-num    { font-size: 36px; }
.portfolio-insights-wrapper .ws-headline { font-size: 15px; }
.portfolio-insights-wrapper .ws-body   { font-size: 13px; margin-top: 6px; }
.portfolio-insights-wrapper .ws-grid {
    grid-template-columns: 340px 1fr;
}

/* Rating badge — shared by PortfolioMetricRow and the WiseScorePane chip
   pillar layout. Mirrors the prototype's .badge + bE/bG/bO/bF/bP styles.
   Scoped to .report-wrapper so generic `.badge` users elsewhere in the app
   (e.g. SelectOrganization's `<span class="badge badge-info">`) aren't
   clobbered by this report-specific pill chrome. */
.report-wrapper .badge {
    display: inline-block;
    padding: 3px 11px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}
.report-wrapper .bE { background: var(--rpt-gras-bg);     color: var(--rpt-gras-text); }
.report-wrapper .bG { background: var(--rpt-hist-bg);     color: var(--rpt-hist-text); }
.report-wrapper .bO { background: #DBEAFE;                color: #1D4ED8; }
.report-wrapper .bF { background: var(--rpt-unknown-bg);  color: var(--rpt-unknown-text); }
.report-wrapper .bP { background: var(--rpt-unsafe-bg);   color: var(--rpt-unsafe-text); }

.pi-heatmap-empty {
    padding: 28px;
    text-align: center;
    color: var(--rpt-mid-gray);
    font-size: 13px;
}

/* ════════════════════════════════════════════════════════════════════════════
   WEB RESPONSIVENESS (screen only — never the PDF)
   ────────────────────────────────────────────────────────────────────────────
   The base wrapper pins min-width:880px so the web view never reflows; below
   that the browser just shows a horizontal scrollbar. That makes the reports
   unusable on phones/tablets. This block lets the report reflow to the actual
   content width instead.

   PDF safety: the PDF export is rendered by Playwright `page.PdfAsync`, which
   emulates `print` media — so this entire `@media screen` block is EXCLUDED
   from the export. (The print pages also already override the wrapper to
   `min-width:0; max-width:100%`.) Nothing here can affect the 8.5×11 canvas.

   Layout reflow keys off CONTAINER width (the wrapper's own width via
   `container-type: inline-size`), not viewport width, so it adapts correctly
   whether or not the fixed sidebar is eating horizontal space. Report-specific
   reflow lives in reports-skin.css / reports-upf.css under the same `rptw`
   container + `@media screen` guard.
   ════════════════════════════════════════════════════════════════════════════ */
@media screen {
    /* Make the wrapper a size container and drop the 880px floor so it shrinks
       to its parent on narrow viewports. max-width caps still apply on wide
       displays, so desktop is unchanged (parent is wider than the cap there). */
    .report-wrapper {
        container-type: inline-size;
        container-name: rptw;
        min-width: 0;
    }
    /* The `.rpt-skin` and `.upf-report` variant floors live in their own
       (later-loaded) stylesheets, so their relaxation is applied there to win
       on source order at equal specificity. */
    .report-wrapper.upc-wrapper,
    .report-wrapper.upc-wrapper.upc-insights-wrapper,
    .report-wrapper.portfolio-insights-wrapper {
        min-width: 0;
    }

    /* With the wrapper now reflowing, the page no longer overflows horizontally,
       so the always-on horizontal scrollbar (added for the 880px overflow case)
       becomes an empty track. Switch it to auto: wide tables keep their own
       inner scroll containers (.pmx-scroll, .upf-table-wrap), so nothing that
       needs horizontal scroll loses it. */
    body:has(.report-wrapper) .main-content {
        overflow-x: auto;
    }

    /* On touch devices, opt out of the desktop viewport-lock entirely and
       restore native document scrolling.

       The base rules (top of this file) pin html/body to `height:100vh;
       overflow:hidden` and turn `.main-content` into the scroll container so
       desktop gets an always-visible, viewport-anchored scrollbar. On phones
       that mechanism backfires: `100vh` is the LARGE viewport (browser toolbars
       hidden), so `.main-content` (height:100%) is pinned taller than the
       actually-visible area when the browser's bottom bar is showing — its last
       slice ends up behind that bar. And because body is `overflow:hidden`, the
       native document scroll that would let the browser shrink its toolbar and
       reveal the bottom is disabled, so that slice is unreachable.

       Keying off `pointer: coarse` (not just width) is deliberate: the
       always-visible-scrollbar hack only benefits MOUSE users, who actually
       have persistent scrollbars. A phone in LANDSCAPE is wider than 768px, so
       a width-only rule would let the desktop lock (and the trap) come back the
       moment the persistent sidebar layout kicks in. Touch devices never show
       persistent scrollbars and always want native scrolling, at any width, so
       gate on the input type. The `max-width: 768px` arm stays as a fallback
       for narrow non-touch windows. (Media query list = OR.)

       Reverting to normal flow scrolling fixes it: the document scrolls end to
       end and the browser's dynamic toolbar cooperates. */
    @media (pointer: coarse), (max-width: 768px) {
        html:has(.report-wrapper),
        body:has(.report-wrapper) {
            height: auto;
            overflow: visible;
        }
        body:has(.report-wrapper) .main-content {
            height: auto;
            overflow-x: visible;
            overflow-y: visible;
        }
    }

    /* Reclaim the global 2rem MainLayout padding on small screens so the report
       cards get more room. Scoped to report pages only. */
    @media (max-width: 640px) {
        body:has(.report-wrapper) .main-content > .p-8 {
            padding: 12px;
        }
    }
    @media (max-width: 420px) {
        body:has(.report-wrapper) .main-content > .p-8 {
            padding: 8px;
        }
    }
}
