/* ════════════════════════════════════════════════════════════════════════════════════════════════
   THE VIOLATIONS TAB: GROUPS, THEIR INSPECTIONS, AND THE MAP (2026-10-14) — js/modules/violations-board.js
   ════════════════════════════════════════════════════════════════════════════════════════════════
   ONE FAMILY WITH PREDICTIVE'S LIST. The measures, the toolbar, the chips, the count line and the
   sort buttons wear the predictive list's classes as they are (report-detail.css: .pred-basics-table,
   .pred-vt-*, .pred-viol-table), so a change there changes both. What is here is what that list does
   not have: a row that opens, the inspections inside it, the map buttons and the map's dialog —
   and FMCSA's investigation results above the list (2026-10-14).

   Loaded after dark-mode.css (api-tool.html), so its body.theme-dark rules are with each part. Two
   of dark mode's blankets meet these tables: every table cell is striped and painted (!important),
   which an open row and its inspections must not be, and every class holding "-popup" is painted a
   flat box — Leaflet's popup and its tip included. Both are answered at #pageContent / .vb-mapbox
   strength below.

   WHAT FITS IS DECIDED BY THE CARD'S ROOM, NOT THE WINDOW: the page's gutters grow with the window,
   so the table's box is a size container (vbbox) and the narrower layouts follow its width. Phones
   (≤640px) are at the end of each part, not in mobile.css. */

.vb [hidden] { display: none !important; }
.vb-state { margin: 0; font-size: var(--fs-base); color: var(--text-soft, #566274); }
.vb-muted { color: var(--text-soft, #566274); }
/* A second line in a cell — a plate, the inspection site. Small, and never the figure. */
.vb-sub { display: block; font-size: var(--fs-xs); color: var(--text-soft, #566274); }

/* ── The grouped table ─────────────────────────────────────────────────────────────────────── */
.vb-scroll { container: vbbox / inline-size; }
table.vb-groups td.vb-c-name { min-width: 15rem; white-space: normal; }
table.vb-groups td.vb-c-basic { white-space: nowrap; }
table.vb-groups th.vb-num, table.vb-groups td.vb-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
table.vb-groups th.vb-c-date, table.vb-groups td.vb-c-date { white-space: nowrap; font-variant-numeric: tabular-nums; }
table.vb-groups th.vb-c-map, table.vb-groups td.vb-c-map { width: 1%; text-align: right; white-space: nowrap; }
table.vb-groups td.vb-count { font-weight: 700; color: var(--text, #0f172a); }
table.vb-groups tr.vb-grp { cursor: pointer; }
/* Inline, not inline-block: a BASIC on two lines keeps its first on the row's line. */
.vb-basic { white-space: nowrap; }
.vb-basic + .vb-basic { margin-left: 0.6rem; }

/* THE ROW IS A DISCLOSURE: its name is the button (Enter and Space), with a caret that turns. */
.vb-toggle {
    appearance: none; border: 0; background: none; margin: 0 0 0 -0.2rem; padding: 0.05rem 0.2rem;
    display: inline-flex; align-items: flex-start; gap: 0.45rem; border-radius: 4px;
    font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.vb-caret {
    flex: 0 0 auto; width: 0; height: 0; margin-top: 0.42em;
    border-left: 5px solid currentColor; border-top: 4px solid transparent; border-bottom: 4px solid transparent;
    transition: transform var(--dur-fast, 120ms) ease;
}
.vb-toggle[aria-expanded="true"] .vb-caret { transform: rotate(90deg); }
/* anywhere, not break-word: a long unbroken token (a code run together, a pasted string) must not
   set the column's floor. */
.vb-name { font-weight: 600; color: var(--text, #0f172a); overflow-wrap: anywhere; }
.vb-toggle:hover .vb-name { text-decoration: underline; text-underline-offset: 3px; }
/* Its codes under it, lined up with the name rather than the caret. */
.vb-codes {
    display: block; margin: 0.12rem 0 0 1.05rem; font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
    color: var(--text-soft, #566274);
}

/* The map buttons: the predictive toolbar's quiet button, with a pin. */
.vb-mapbtn {
    appearance: none; display: inline-flex; align-items: center; gap: 0.35rem; height: 2rem; padding: 0 0.6rem;
    font: inherit; font-size: var(--fs-sm); font-weight: 600; line-height: 1; white-space: nowrap;
    color: var(--accent-ink, #1d4ed8); background: var(--surface-alt, #fff);
    border: 1px solid var(--border, #dbe1ea); border-radius: var(--radius-xs, 6px); cursor: pointer;
}
.vb-mapbtn:hover { border-color: var(--accent, #2563eb); }
.vb-mapbtn-sm { height: 1.75rem; padding: 0 0.45rem; }
.vb-pin-ico { flex: 0 0 auto; }
.vb-map-short { display: none; }

/* An open row and what it opens read as one block: the same tint, an accent line down the side. */
#pageContent table.vb-groups > tbody > tr.vb-grp.is-open > td { background: var(--surface, #f4f6fa); }
#pageContent table.vb-groups > tbody > tr.vb-detail:hover { background: transparent; }
#pageContent table.vb-groups > tbody > tr.vb-detail > td.vb-detail-cell {
    padding: 0.05rem 0.6rem 0.85rem 1.55rem; background: var(--surface, #f4f6fa); cursor: default;
}
/* THE OPEN ROW'S INSPECTIONS TAKE THE BOX'S WIDTH, NOT THE TABLE'S: they never widen the groups
   table through the cell they span, and when that table is wider than its box they stay in view
   (sticky) while it scrolls under them. If they need more than the box has, they scroll in here. */
.vb-detail-wrap {
    position: sticky; left: 1.55rem; width: calc(100cqw - 2.15rem); box-sizing: border-box; overflow-x: auto;
    padding-left: 0.85rem; box-shadow: inset 3px 0 0 var(--accent-soft-border, #c7d9fb);
}

/* ── An open row's inspections ─────────────────────────────────────────────────────────────── */
/* One <tbody> per inspection: its date, report and place span its rows, a row per violation. */
table.vb-insp { width: 100%; }
#pageContent table.vb-insp th { position: static; background: transparent; white-space: nowrap; }
#pageContent table.vb-insp > tbody > tr > td { vertical-align: top; border-bottom: 0; }
#pageContent table.vb-insp > tbody + tbody > tr:first-child > td { border-top: 1px solid var(--border, #dbe1ea); }
#pageContent table.vb-insp > tbody > tr + tr > td { border-top: 1px dashed var(--border, #dbe1ea); }
#pageContent table.vb-insp > tbody > tr:hover { background: transparent; }
#pageContent table.vb-insp > tbody:hover > tr > td { background: var(--accent-soft, #eff4ff); }
table.vb-insp th.vb-num, table.vb-insp td.vb-num { text-align: right; font-variant-numeric: tabular-nums; }
table.vb-insp td.vb-i-date, table.vb-insp td.vb-i-report,
table.vb-insp td.vb-i-code, table.vb-insp td.vb-i-tw { white-space: nowrap; }
table.vb-insp td.vb-i-date { font-variant-numeric: tabular-nums; }
table.vb-insp td.vb-i-code { font-weight: 600; }
/* THE WHOLE DESCRIPTION, ALWAYS: it wraps, between words, and its column takes the slack. */
table.vb-insp td.vb-i-desc { min-width: 14rem; white-space: normal; overflow-wrap: break-word; }
table.vb-insp td.vb-i-loc { min-width: 9rem; max-width: 18rem; white-space: normal; overflow-wrap: break-word; }
table.vb-insp td.vb-i-veh { min-width: 6rem; }
table.vb-insp th.vb-i-map, table.vb-insp td.vb-i-map { width: 1%; text-align: right; white-space: nowrap; }
table.vb-insp .pred-insp-report-link { font-size: inherit; color: var(--accent-ink, #1d4ed8); }
/* The report's state beside its number, as the predictive list writes it (2026-10-15). */
.vb-i-st { color: var(--text-muted, #475569); }
/* NOTHING TO MAP, NO MAP COLUMN (2026-10-15): no row in the table has an address (only states), and
   the locations have answered. While they are on their way the column keeps its place. */
table.vb-groups.vb-nomap > thead > tr > th.vb-c-map, table.vb-groups.vb-nomap > tbody > tr > td.vb-c-map,
table.vb-insp.vb-nomap > thead > tr > th.vb-i-map, table.vb-insp.vb-nomap > tbody > tr > td.vb-i-map { display: none !important; }

/* Every control shows where the keyboard is. */
.vb-toggle:focus-visible, .vb-mapbtn:focus-visible, table.vb-insp .vb-report:focus-visible,
.vb-mapclose:focus-visible, .vb-mapbox .leaflet-container a:focus-visible {
    outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px;
}

/* Dark mode: no stripes or painted cells under these rows (dark-mode.css paints every table cell),
   the open block a step darker than the card, the hover a faint blue. */
body.theme-dark #pageContent table.vb-groups > tbody > tr > td,
body.theme-dark #pageContent table.vb-insp > tbody > tr > td { background-color: transparent !important; }
body.theme-dark #pageContent table.vb-groups > tbody > tr:hover,
body.theme-dark #pageContent table.vb-insp > tbody > tr:hover { background: transparent !important; }
body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-grp:hover > td,
body.theme-dark #pageContent table.vb-insp > tbody:hover > tr > td { background-color: rgba(var(--accent-ink-rgb), 0.08) !important; }
body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-grp.is-open > td,
body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-detail > td.vb-detail-cell { background-color: var(--surface, #202023) !important; }
body.theme-dark #pageContent table.vb-insp thead th { background: transparent !important; }
body.theme-dark .vb-detail-wrap { box-shadow: inset 3px 0 0 var(--accent-soft-border, #2f4a76); }
body.theme-dark .vb-mapbtn { border-color: var(--border-strong, #565663); }

/* ── Less room than a wide screen's (the box under 1080px, a phone aside) ───────────────────── */
/* The headings, a group's name and BASIC and an inspection's road may take two lines, the
   descriptions give up some of their floor and "View on map" says "Map": the groups fit from about
   a 1000px window. Narrower still, the table scrolls in its box with Map pinned to the right edge —
   as Predictive pins Remove — and the page itself never does. */
@media (min-width: 641px) {
    @container vbbox (max-width: 1080px) {
        table.vb-groups th, table.vb-groups th.vb-num, table.vb-groups th.vb-c-date { white-space: normal; }
        table.vb-groups td.vb-c-name { min-width: 8rem; }
        table.vb-groups td.vb-c-basic, table.vb-groups td.vb-c-basic .vb-basic { white-space: normal; }
        .vb-groups .vb-map-long { display: none; }
        .vb-groups .vb-map-short { display: inline; }
        #pageContent table.vb-insp th { white-space: normal; }
        table.vb-insp td.vb-i-desc { min-width: 9rem; }
        table.vb-insp td.vb-i-loc { min-width: 7rem; max-width: none; }
        table.vb-groups th.vb-c-map, table.vb-groups td.vb-c-map { position: sticky; right: 0; box-shadow: inset 1px 0 0 var(--border, #dbe1ea); }
        table.vb-groups th.vb-c-map { z-index: 2; }
        #pageContent table.vb-groups > tbody > tr.vb-grp > td.vb-c-map { z-index: 1; background: var(--surface-alt, #fff); }
        #pageContent table.vb-groups > tbody > tr.vb-grp:hover > td.vb-c-map { background: var(--accent-soft, #eff4ff); }
        #pageContent table.vb-groups > tbody > tr.vb-grp.is-open > td.vb-c-map { background: var(--surface, #f4f6fa); }
        body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-grp > td.vb-c-map { background-color: var(--surface-alt, #26262a) !important; box-shadow: inset 1px 0 0 var(--border-strong, #565663); }
        body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-grp:hover > td.vb-c-map { background-color: var(--tone-2c3039, #2c3039) !important; }
        body.theme-dark #pageContent table.vb-groups > tbody > tr.vb-grp.is-open > td.vb-c-map { background-color: var(--surface, #202023) !important; }
    }
    /* A TABLET, UPRIGHT (the box under about 880px, 2026-10-14): the table no longer fit, and the
       pinned Map column covered "Most recent" — the order the list is in — at 820px and hid it at
       768. The BASIC goes under the group's name instead of in a column of its own. */
    @container vbbox (max-width: 880px) {
        table.vb-groups .vb-c-basic { display: none; }
        table.vb-groups td.vb-c-name { min-width: 7rem; }
        table.vb-groups .vb-basic-sub { display: block; }
    }
}
.vb-basic-sub { display: none; margin: 0.12rem 0 0 1.05rem; font-size: var(--fs-xs); color: var(--text-soft, #566274); }
.vb-basic-sub .vb-basic { white-space: normal; }

/* FMCSA'S SUMMARY ALONE (no inspection rows came with the report, 2026-10-14): a row per code or
   group with its count, severity and OOS, and nothing behind it to open, date or map. */
table.vb-groups.vb-summary > thead > tr > th.vb-c-insp, table.vb-groups.vb-summary > tbody > tr > td.vb-c-insp,
table.vb-groups.vb-summary > thead > tr > th.vb-c-date, table.vb-groups.vb-summary > tbody > tr > td.vb-c-date,
table.vb-groups.vb-summary > thead > tr > th.vb-c-map, table.vb-groups.vb-summary > tbody > tr > td.vb-c-map { display: none !important; }
table.vb-groups.vb-summary tr.vb-grp { cursor: default; }
table.vb-groups.vb-summary .vb-codes, table.vb-groups.vb-summary .vb-basic-sub { margin-left: 0; }

/* AN INSPECTION AS A CARD, when its ten columns no longer fit the box (under 950px, a phone
   included): the date and the map button on top, the report, the state and time weight, the
   vehicle and the place, and each violation — code and severity, its description under them.
   Cards sit side by side where there is room. (Its own layout: mobile-tables.js leaves a
   [data-no-reflow] table alone, and its row spans would not survive the generic phone cards.) */
@container vbbox (max-width: 949px) {
    table.vb-insp { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: 8px; width: 100%; }
    table.vb-insp > thead { display: none; }
    table.vb-insp > tbody.vb-insp-group {
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-flow: row dense; align-content: start; gap: 6px 12px;
        padding: 10px 12px; border: 1px solid var(--border, #dbe1ea); border-radius: 10px; background: var(--surface-alt, #fff);
    }
    table.vb-insp > tbody > tr { display: contents; }
    #pageContent table.vb-insp > tbody > tr > td {
        display: block; min-width: 0; max-width: none; padding: 0; border: 0; background: transparent;
        text-align: left; white-space: normal; overflow-wrap: break-word;
    }
    #pageContent table.vb-insp > tbody:hover > tr > td { background: transparent; }
    /* The desktop's lines between inspections and between violations outrank the reset above;
       a card draws its own (below). */
    #pageContent table.vb-insp > tbody + tbody > tr:first-child > td,
    #pageContent table.vb-insp > tbody > tr + tr > td { border-top: 0; }
    table.vb-insp > tbody > tr > td::before {
        content: attr(data-label); display: inline; margin-right: 0.4em;
        font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.02em; color: var(--text-muted, #475569);
    }
    table.vb-insp td.vb-i-date { order: -10; grid-column: 1; align-self: center; font-weight: 700; }
    table.vb-insp td.vb-i-map { order: -9; grid-column: 2; justify-self: end; width: auto; }
    table.vb-insp td.vb-i-report { order: -8; grid-column: 1 / -1; }
    /* A line of its own (2026-10-15): its partner was the State cell, now beside the report, and a
       half-row left free took the first violation's code out of its place beside its severity. */
    table.vb-insp td.vb-i-tw { order: -6; grid-column: 1 / -1; }
    table.vb-insp td.vb-i-veh { order: -5; grid-column: 1 / -1; }
    /* A report number is one thing: it never breaks across lines. */
    table.vb-insp td.vb-i-report a { white-space: nowrap; }
    #pageContent table.vb-insp td.vb-i-loc { order: -4; grid-column: 1 / -1; padding-bottom: 6px; border-bottom: 1px solid var(--border-subtle, #e8ecf3); }
    table.vb-insp td.vb-i-code { grid-column: 1; }
    table.vb-insp td.vb-i-sev { grid-column: 2; }
    table.vb-insp td.vb-i-desc { grid-column: 1 / -1; }
    #pageContent table.vb-insp > tbody > tr:not(:last-child) > td.vb-i-desc { padding-bottom: 6px; border-bottom: 1px dashed var(--border, #dbe1ea); }
    table.vb-insp td.vb-i-date::before, table.vb-insp td.vb-i-map::before, table.vb-insp td.vb-i-desc::before { display: none; }
    table.vb-insp .vb-sub { display: inline; margin-left: 0.35em; }
    table.vb-insp td.vb-i-loc .vb-sub::before { content: "· "; }
    body.theme-dark table.vb-insp > tbody.vb-insp-group { border-color: var(--border-strong, #565663); }
    /* A CARD IS ONE SURFACE (2026-10-14): the desktop's dark hover tint (above, !important) painted
       each of a hovered card's cells — a slab behind every value, and on a touch screen it stayed
       after the tap. No tint here, as in light mode. */
    body.theme-dark #pageContent table.vb-insp > tbody:hover > tr > td { background-color: transparent !important; }
}

/* ── Phones: cards ─────────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    /* mobile-tables.js makes each group a card (the name its title); the map button gets a line. */
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-map { grid-column: 1 / -1; text-align: left; }
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-map::before { display: none; }
    table.vb-groups[data-m-reflow] td.vb-c-name { min-width: 0; }
    /* THE NAME IS STILL THE CARD'S TITLE (2026-10-15): the row leads with the date now, in the
       predictive list's order, and mobile.css makes a card's first cell its title. */
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-name { order: -1; grid-column: 1 / -1; font-weight: 600; }
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-name::before { display: none; }
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-date { grid-column: auto; font-weight: 400; }
    table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td.vb-c-date::before { display: inline; }
    #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-grp.is-open { border-color: var(--accent-soft-border, #c7d9fb) !important; }
    #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-grp.is-open > td { background: transparent !important; }
    /* Under an open card, its inspections — one card each — hang off an accent line. mobile.css sets
       a card's first cell in 600; here that cell holds every inspection card. */
    #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-detail > td.vb-detail-cell {
        padding: 0 0 0 10px !important; background: transparent !important; font-weight: 400;
        box-shadow: inset 3px 0 0 var(--accent-soft-border, #c7d9fb);
    }
    .vb-detail-wrap { position: static; width: auto; overflow: visible; padding-left: 0; box-shadow: none; }
    body.theme-dark .vb-detail-wrap { box-shadow: none; }
    /* DARK, A CARD IS ONE SURFACE TOO (2026-10-14): the desktop's dark rules for an open, hovered
       or tapped row (above, !important, at #pageContent strength) out-ranked mobile.css's card
       reset and this block's own, and painted each value of the card — and the strip its
       inspections hang from — a slab of its own. */
    body.theme-dark #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-grp > td,
    body.theme-dark #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-grp:hover > td,
    body.theme-dark #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-grp.is-open > td,
    body.theme-dark #pageContent table.vb-groups[data-m-reflow] > tbody > tr.vb-detail > td.vb-detail-cell { background-color: transparent !important; }
}

/* ── Investigation results (2026-10-14) ───────────────────────────────────────────────────────── */
/* FMCSA's acute and critical findings from investigations, between the measures and the roadside
   list, in the same table family (.violations-table, .pred-viol-table for the sort arrows). What
   carries colour has a class of its own: dark mode flattens the background of any class holding
   "pred", and paints any holding "-results" — so no class here says either. */
.vb-inv {
    margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border-subtle, #e8ecf3);
    scroll-margin-top: calc(var(--measured-header-height, var(--app-header-height, 80px)) + 0.75rem);
}
/* Landed on from a BASIC's "Investigation" chip: a tint that fades, so the eye finds it. */
@keyframes vb-inv-arrive { from { background-color: var(--accent-soft, #eff4ff); } to { background-color: transparent; } }
.vb-inv.is-arrived { animation: vb-inv-arrive 1.4s ease-out; }
@media (prefers-reduced-motion: reduce) { .vb-inv.is-arrived { animation: none; } }
/* A sub-heading of the card: design-system.css sizes every #pageContent h3 for a page. The count
   reads as its second half; card-sources.js floats "Source: …" at its right end. */
#pageContent .vb-inv-title {
    margin: 0 0 0.5rem; font-size: var(--fs-base, 1rem); font-weight: 700; line-height: 1.4; letter-spacing: 0;
    color: var(--text, #0f172a); text-wrap: pretty;
}
.vb-inv-sum { font-weight: 400; color: var(--text-soft, #566274); }
/* A PHONE'S TITLE HAS NO ROOM FOR THE SOURCE (2026-10-14): card-sources.js then pins the line at
   the section's foot (is-foot, absolute), where it sat over the last line — "(Compliance Review)"
   at 390px with a two-digit count. The foot gets a line of its own, at the content's edge. */
.vb-inv.has-source-foot { padding-bottom: 1.35rem; }
.vb-inv > .card-source.is-foot { right: 0; }
/* Its lines are lists and labels, not prose: no 78ch measure (design-system.css #pageContent p),
   which broke "Most recent investigations" into three lines on a wide card. */
#pageContent .vb-inv p { max-width: none; }
.vb-inv-lede { margin: -0.3rem 0 0.55rem; font-size: var(--fs-sm); color: var(--text-soft, #566274); }
.vb-inv-scroll { overflow-x: auto; container: vbinv / inline-size; }
table.vb-inv-table td { vertical-align: baseline; }
table.vb-inv-table td.vb-inv-c-date, table.vb-inv-table td.vb-inv-c-code { white-space: nowrap; font-variant-numeric: tabular-nums; }
table.vb-inv-table td.vb-inv-c-basic, table.vb-inv-table td.vb-inv-c-kind { white-space: nowrap; }
/* THE INVESTIGATION MAY WRAP (2026-10-14, review): on one line, FMCSA's "Onsite Comprehensive
   Investigation" ran the table 42px past its card at 1024 and cut off the chip. Its floor (the
   cell is border-box, padding included) keeps "Compliance Review" and "Non-Ratable Review" on one
   line, with room for a wider system font than this machine's. */
table.vb-inv-table td.vb-inv-c-inv { white-space: normal; min-width: 10.75em; }
/* A wrapped heading lines up with its column (a <button> centres its lines), here and in the
   groups below. */
table.vb-inv-table .pred-vt-sort, table.vb-groups .pred-vt-sort { text-align: inherit; }
/* THE WHOLE DESCRIPTION: it wraps between words and its column takes the slack. anywhere, not
   break-word (2026-10-14, review), as .vb-name: a long unbroken token must not set its floor — one
   ran the rows 57px past the card at 660. */
table.vb-inv-table td.vb-inv-c-desc { width: 100%; min-width: 14rem; white-space: normal; overflow-wrap: anywhere; }
.vb-inv-code { font-weight: 600; color: var(--text, #0f172a); }
/* "×4": FMCSA lists the finding once per time it was cited, the way a group counts violations. */
.vb-inv-times { margin-left: 0.35rem; font-weight: 700; color: var(--text, #0f172a); }

/* Acute red, critical amber-red; one FMCSA left unsaid is outlined in the red. 13px, 5.6:1 and
   better on their fills. */
.vb-kind {
    display: inline-block; padding: 0 0.5rem; font-size: var(--fs-xs); font-weight: 700; line-height: 1.5;
    white-space: nowrap; border: 1px solid transparent; border-radius: var(--radius-pill, 999px);
}
.vb-kind-acute { color: #b91c1c; background: #fdecec; border-color: #f3b8b8; }
.vb-kind-critical { color: #9a3412; background: #fff1e6; border-color: #f5c9a8; }
.vb-kind-either { color: #b91c1c; background: transparent; border-color: #f3b8b8; }
/* The measures' chip beside a BASIC FMCSA marks "Acute/Critical Violations Discovered". */
.vb-inv-flag {
    appearance: none; margin: 0 0 0 0.45rem; padding: 0 0.45rem; vertical-align: baseline;
    font: inherit; font-size: var(--fs-xs); font-weight: 700; line-height: 1.5; white-space: nowrap;
    color: #b91c1c; background: #fdecec; border: 1px solid #f3b8b8; border-radius: var(--radius-pill, 999px); cursor: pointer;
}
/* UNDER THE NAME, ALWAYS, past a phone (2026-10-14, review): beside it, the chips of the longer
   names wrapped at laptop widths and the shorter did not — at 1366 two beside, two under, those
   lined up with neither the square nor the name. Here each starts where its name does (the
   indent .vb-codes uses); a phone's card keeps it beside the name. */
@media (min-width: 641px) {
    .vb-measures-table .vb-inv-flag { display: block; width: fit-content; margin: 0.15rem 0 0 1.05rem; }
}
.vb-inv-flag:hover { border-color: #b91c1c; }
.vb-inv-flag:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px; }

/* The quiet line, and the recent investigations under the rows (FMCSA's icon where it has one). */
.vb-inv-line, .vb-inv-recent { margin: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-soft, #566274); }
.vb-inv-scroll:not([hidden]) ~ .vb-inv-line, .vb-inv-recent { margin-top: 0.5rem; }
.vb-inv-mark { display: inline-flex; margin-left: 0.3rem; vertical-align: -2px; color: #b91c1c; }
@media (min-width: 641px) { .vb-inv-past { white-space: nowrap; } }

/* LESS ROOM (the card under ~860px, an upright tablet): at 820 the six columns ran 3px past the
   card and "Hours-of-Service" broke at its hyphens. The BASIC goes under the description, as the
   groups put it under the name, the headings may take two lines and the investigation gives up
   its floor. */
.vb-inv-basic-sub { display: none; margin-top: 0.15rem; font-size: var(--fs-xs); color: var(--text-soft, #566274); }
/* Its BASIC may wrap, as the groups' does: on one line it set the description's floor. */
.vb-inv-basic-sub .vb-basic { white-space: normal; }
@media (min-width: 641px) {
    @container vbinv (max-width: 860px) {
        table.vb-inv-table th { white-space: normal; }
        table.vb-inv-table td.vb-inv-c-inv { min-width: 0; }
        table.vb-inv-table .vb-inv-c-basic { display: none; }
        table.vb-inv-table .vb-inv-basic-sub { display: block; }
        table.vb-inv-table td.vb-inv-c-desc { min-width: 10rem; }
    }
    /* A window between a phone and ~700px (half a 1366 laptop): the rows ran up to 37px past the
       card and cut off their chips (2026-10-14, review). The description gives up more floor. */
    @container vbinv (max-width: 640px) {
        table.vb-inv-table td.vb-inv-c-desc { min-width: 7rem; }
    }
}

/* Dark mode: no stripes or painted cells (dark-mode.css paints every table cell, !important), a
   faint blue hover, and the chips in the dark palette's red and amber — all 5.4:1 and better. */
body.theme-dark .vb-inv { border-top-color: var(--border-subtle, #303036); }
body.theme-dark #pageContent table.vb-inv-table > tbody > tr > td { background-color: transparent !important; }
body.theme-dark #pageContent table.vb-inv-table > tbody > tr:hover { background: transparent !important; }
body.theme-dark #pageContent table.vb-inv-table > tbody > tr:hover > td { background-color: rgba(var(--accent-ink-rgb), 0.08) !important; }
body.theme-dark .vb-kind-acute, body.theme-dark .vb-inv-flag { color: #fca5a5; background: rgba(239, 68, 68, 0.14); border-color: rgba(248, 113, 113, 0.45); }
body.theme-dark .vb-kind-critical { color: #fb923c; background: rgba(249, 115, 22, 0.14); border-color: rgba(251, 146, 60, 0.45); }
body.theme-dark .vb-kind-either { color: #fca5a5; background: transparent; border-color: rgba(248, 113, 113, 0.45); }
body.theme-dark .vb-inv-flag:hover { border-color: #fca5a5; }
body.theme-dark .vb-inv-mark { color: #f87171; }

/* A phone: mobile-tables.js makes each finding a card (six columns). The date and its chip head
   it; the investigation, the code and the BASIC each a line under their names; the description
   in full without one. Nothing in a card is a link, so it takes no hover tint either. */
@media (max-width: 640px) {
    table.vb-inv-table[data-m-reflow] > tbody > tr { grid-template-columns: minmax(0, 1fr) auto; }
    table.vb-inv-table[data-m-reflow] > tbody > tr > td { grid-column: 1 / -1; }
    table.vb-inv-table[data-m-reflow] > tbody > tr > td.vb-inv-c-date { grid-column: 1; grid-row: 1; align-self: center; }
    table.vb-inv-table[data-m-reflow] > tbody > tr > td.vb-inv-c-kind { grid-column: 2; grid-row: 1; justify-self: end; align-self: center; }
    table.vb-inv-table[data-m-reflow] > tbody > tr > td.vb-inv-c-kind::before,
    table.vb-inv-table[data-m-reflow] > tbody > tr > td.vb-inv-c-desc::before { display: none; }
    #pageContent table.vb-inv-table[data-m-reflow] > tbody > tr:hover { background: var(--surface-alt, #fff); }
    body.theme-dark #pageContent table.vb-inv-table[data-m-reflow] > tbody > tr,
    body.theme-dark #pageContent table.vb-inv-table[data-m-reflow] > tbody > tr:hover,
    body.theme-dark #pageContent table.vb-inv-table[data-m-reflow] > tbody > tr > td,
    body.theme-dark #pageContent table.vb-inv-table[data-m-reflow] > tbody > tr:hover > td { background-color: transparent !important; }
}

/* ── View on map: the dialog ──────────────────────────────────────────────────────────────────── */
/* Over the page and under the header, as the report dialog is (main.css .modal) — one step below
   it, so a report opened from a pin comes up over the map. */
.vb-mapmodal {
    position: fixed; inset: 0; z-index: 1990;
    display: flex; align-items: flex-start; justify-content: center;
    padding: calc(var(--measured-header-height, var(--app-header-height, 80px)) + 1rem) 1.5rem 1.5rem;
    background: rgba(var(--slate-900-rgb), 0.62); overflow-y: auto; overscroll-behavior: contain;
}
.vb-mapbox {
    position: relative; width: min(1000px, 100%); display: flex; flex-direction: column; gap: 0.65rem;
    padding: 1rem 1.25rem 1.1rem; color: var(--text-body, #1e293b); background: var(--surface-alt, #fff);
    border: 1px solid var(--border, #dbe1ea); border-radius: var(--radius-lg, 16px);
    box-shadow: 0 25px 80px rgba(var(--slate-900-rgb), 0.25);
}
.vb-maphead { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.vb-maptitles { min-width: 0; }
.vb-maptitle { margin: 0; font-size: var(--fs-lg); font-weight: 700; line-height: 1.3; color: var(--text, #0f172a); overflow-wrap: anywhere; }
.vb-mapsub { margin: 0.15rem 0 0; font-size: var(--fs-sm); color: var(--text-soft, #566274); overflow-wrap: anywhere; }
.vb-mapclose {
    appearance: none; flex: 0 0 auto; width: 40px; height: 40px; padding: 0; border-radius: 999px;
    font: inherit; font-size: 1.5rem; line-height: 1; color: var(--text-body, #1e293b);
    background: var(--surface, #f1f5f9); border: 1px solid var(--border, #dbe1ea); cursor: pointer;
}
.vb-mapclose:hover { border-color: var(--accent, #2563eb); }
.vb-mapcanvas {
    position: relative; height: min(60vh, 560px); min-height: 280px; overflow: hidden;
    border: 1px solid var(--border, #dbe1ea); border-radius: 12px; background: var(--surface, #f4f6fa);
}
.vb-mapmsg { margin: 0; padding: 1rem; font-size: var(--fs-sm); color: var(--text-soft, #566274); }
.vb-mapnotes { display: flex; flex-direction: column; gap: 0.2rem; }
.vb-mapnote { margin: 0; font-size: var(--fs-sm); line-height: 1.45; color: var(--text-soft, #566274); }
.vb-mapsource { margin: 0; font-size: var(--fs-xs); color: var(--text-soft, #566274); }

/* A pin's popup: the place, then each inspection there — date, report, road, its violations. */
.vb-mapbox .leaflet-container { font-family: inherit; }
.vb-mapbox .vb-mappop .leaflet-popup-content-wrapper { border-radius: 10px; }
.vb-mapbox .vb-mappop .leaflet-popup-content { margin: 12px 26px 12px 14px; font-size: var(--fs-sm); line-height: 1.4; color: var(--text-body, #1e293b); }
.vb-pop-place { margin-bottom: 0.35rem; font-weight: 700; color: var(--text, #0f172a); }
.vb-pop-list, .vb-pop-viols { list-style: none; margin: 0; padding: 0; }
.vb-pop-list { max-height: 240px; overflow-y: auto; }
.vb-pop-insp + .vb-pop-insp { margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border-subtle, #e8ecf3); }
.vb-pop-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.1rem 0.5rem; }
.vb-pop-date { font-weight: 600; font-variant-numeric: tabular-nums; }
.vb-mapbox .leaflet-container a.vb-pop-report { color: var(--accent-ink, #1d4ed8); font-weight: 600; }
.vb-pop-loc { font-size: var(--fs-xs); color: var(--text-muted, #475569); }
.vb-pop-viols { margin-top: 0.2rem; }
.vb-pop-viols li { margin: 0.1rem 0; }
.vb-pop-code { font-weight: 700; }
.vb-pop-sev { font-size: var(--fs-xs); white-space: nowrap; color: var(--text-soft, #566274); }

/* Dark mode. dark-mode.css paints every "-popup" class a flat #26262a (!important): the popup's
   own box and the tip's container must stay clear, or the rounded popup sits on a square and its
   tip on a bar. And its link colour (every <a>, !important) left the zoom buttons and the
   attribution light blue on white. */
body.theme-dark .vb-mapbox { border-color: var(--border-strong, #565663); box-shadow: 0 25px 80px rgba(0, 0, 0, 0.6); }
body.theme-dark .vb-mapclose { color: var(--text, #ececee); border-color: var(--border-strong, #565663); }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup,
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup-tip-container,
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup-content { background-color: transparent !important; }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup-content-wrapper,
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup-tip { background-color: var(--surface-alt) !important; color: var(--text-body, #d4d4d8); box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55); }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-popup-content { color: var(--text-body, #d4d4d8); }
body.theme-dark .vb-mapbox .vb-mapcanvas a.leaflet-popup-close-button { color: var(--text-body) !important; background-color: transparent !important; }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-bar { border-color: var(--zinc-700); }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-bar a { background-color: var(--surface-alt) !important; color: var(--zinc-200) !important; border-bottom-color: var(--zinc-700) !important; }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-control-attribution { background: rgba(var(--tone-202023-rgb, 32, 32, 35), 0.9) !important; color: var(--text-body) !important; }
body.theme-dark .vb-mapbox .vb-mapcanvas .leaflet-control-attribution a { color: var(--accent-300) !important; }
body.theme-dark .vb-pop-insp + .vb-pop-insp { border-top-color: var(--zinc-700); }

@media (max-width: 640px) {
    .vb-mapmodal { padding: calc(var(--measured-header-height, var(--app-header-height, 80px)) + 0.5rem) 0.5rem 0.5rem; }
    .vb-mapbox { padding: 0.75rem; border-radius: var(--radius-md, 12px); }
    .vb-mapcanvas { height: 55vh; min-height: 240px; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════
   THE INSPECTIONS & CRASHES TABLES (2026-10-25) — js/modules/incidents-board.js
   ════════════════════════════════════════════════════════════════════════════════════════════════
   The owner: "Redesign the tables to look like the violations table", and a row's report "expand its
   details inline". Both tables ARE the board's groups table (.vb-groups, .vb-grp, .vb-toggle,
   .vb-detail, .pred-sorthead, .vb-scroll's container), so every rule above — the open row's tint,
   the detail's accent line, the narrower boxes, the phone's cards, dark mode — is theirs too. Here
   only what an inspection or a crash has that a violation group does not: the report and its
   state, the vehicle and the figures, the not-preventable chip, and the report a row opens onto. */
/* The count beside the title, in its line: card-sources.js floats the source to the line's right end.
   THE TITLE HOLDS ITS FLOAT (2026-10-26, review): on a phone the source has no room beside the title
   and drops under it, which a float does without making the title taller — card-sources.js, which
   foots a line that grows its title, saw nothing, and the line hung beside the description. */
.ib-section .analytics-tool-title { display: flow-root; }
.ib-section .analytics-tool-title > .incident-title-count { margin-left: 0.5rem; }
/* Said, not shown: the box's live region (incidents-board.js, say). */
.ib-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* The phone's Sort (it has no header to click); the predictive bar's own select, full width. */
.ib > .ib-bar.pred-vt { display: none; margin: 0 0 0.5rem; padding: 0; border: 0; }
.ib .ib-meta { margin-top: 0; }
/* THE SORT ON A TABLET TOO (2026-10-25, review: four sorts could not be reached). Where the box hides
   the vehicle, a crash's plate, tow-away and release with their headings (below), the orders — and
   the one the list is in — are the select's, as on a phone. The box is a size container of its own
   for it (ibbox): the bar sits outside the table's (vbbox), at the same width. */
.ib { container: ibbox / inline-size; }
@media (min-width: 641px) {
    @container ibbox (max-width: 880px) {
        .ib > .ib-bar.pred-vt { display: block; }
        .ib > .ib-bar .pred-vt-sortsel { display: block; width: auto; max-width: 100%; }
    }
}
/* A report number is not a group's name: the board's 15rem floor would take a third of the row.
   ANYWHERE, THE WHOLE CELL (2026-10-26, review): a 35-character report number run together scrolled
   the table 8px at 641 — break-word, inherited, lowers no column's floor. */
table.vb-groups.ib-table td.vb-c-name { min-width: 10.5rem; overflow-wrap: anywhere; }
/* AN INSPECTION'S SEVERITY WEIGHT, BASIC BY BASIC (2026-10-26, review; incidents-board.js sevHtml):
   each BASIC the board's swatch and name with its capped figure, one to a line in the table — the
   highest on top, so the column reads down like the figures beside it — and run on with " · " in a
   phone's card. Each part is whole on its line; a clean inspection is the board's plain "—". */
table.ib-table td.ib-c-sevb { white-space: normal; }
table.ib-table td.ib-c-sevb .ib-sevb { display: block; white-space: nowrap; font-variant-numeric: tabular-nums; }
table.ib-table td.ib-c-sevb .ib-sevsep { display: none; }
table.ib-table td.ib-c-sevb .ib-unknown { cursor: help; }
/* WHO AND WHAT ON THE LEFT, THE FIGURES ON THE RIGHT (2026-10-25, review): on a wide box the report
   column took the spare width, each vehicle about 450px from its report. The report keeps room for a
   line of codes, the vehicle sits beside it, and the spare goes in front of the figures. */
@container vbbox (min-width: 1081px) {
    table.ib-table-insp th.vb-c-date, table.ib-table-insp th.ib-c-sev, table.ib-table-insp th.ib-c-tw { width: 1%; }
    table.ib-table-insp th.ib-c-report { width: 34%; }
    table.ib-table-insp th.ib-c-veh { width: 16%; }
}
/* anywhere, as .vb-name: a vehicle written as one long token must not set the column's floor. */
table.ib-table td.ib-c-veh { min-width: 7rem; white-space: normal; overflow-wrap: anywhere; }
table.ib-table td.ib-c-yn { white-space: nowrap; }
/* A PLATE KEEPS TO ITS LINE, AND ONE RUN TOGETHER WRAPS (2026-10-25, review: a 30-character plate,
   nowrap, pushed the crash table 114px past its card at 1024). The floor holds a real plate and its
   state whole; the space before the state does not break (plateText). */
table.ib-table td.ib-c-plate { min-width: 7rem; overflow-wrap: anywhere; }
/* Yes and no centred under their headings: left-aligned beside the right-aligned injuries, "2 Yes"
   read as one figure (2026-10-25, review). */
table.ib-table th.ib-c-yn, table.ib-table td.ib-c-yn { text-align: center; }
/* Show all, under the rows at their left, as Predictive's: the box is a flex column, which would
   stretch the button across it and centre its words. */
.ib > .ib-more { align-self: flex-start; }
/* FMCSA's text where a figure belongs, as it came: it may wrap — the cell does not (figHtml). */
table.ib-table .ib-raw { white-space: normal; overflow-wrap: anywhere; }
.ib-st { margin-left: 0.3rem; }
/* A code is one thing: "396.3(a)(1)" never breaks before its "(1)"; the line breaks between codes —
   and "+8 more" is one too. */
.ib-code { white-space: nowrap; }
/* The columns a tablet has no room for, under the report instead (as the board puts the BASIC). */
.ib-alt { display: none; margin: 0.12rem 0 0 1.05rem; font-size: var(--fs-xs); color: var(--text-soft, #566274); overflow-wrap: anywhere; }
/* A TABLET, UPRIGHT (the box under about 880px): the six inspection columns needed 736px of a 657px
   box at 768, the nine crash columns 878px. The vehicle goes under the report, and so do a crash's
   plate, tow-away and release; the figures keep their columns and their sorts. */
@media (min-width: 641px) {
    @container vbbox (max-width: 880px) {
        table.ib-table .ib-c-veh, table.ib-table .ib-c-plate, table.ib-table .ib-c-yn { display: none; }
        table.ib-table .ib-alt { display: block; }
        table.vb-groups.ib-table td.vb-c-name { min-width: 8rem; }
    }
}
.ib-hit { font-weight: 700; color: var(--text, #0f172a); }
/* A clean inspection says so under its number, quietly. */
.ib-clean { font-style: italic; }
/* FMCSA's ruling, a chip under the report: green, as the old table's badge was; 6.9:1 and better. */
.ib-np {
    display: inline-block; padding: 0 0.5rem; font-size: var(--fs-xs); font-weight: 700; line-height: 1.5; white-space: nowrap; font-style: normal;
    color: #166534; background: #dcfce7; border: 1px solid #a7e3bd; border-radius: var(--radius-pill, 999px);
}
/* Landed on from the map's state panel: under the header, and a tint that fades so the eye finds it.
   A shadow, not a background: dark mode paints these cells with !important, which no animation beats. */
table.ib-table > tbody > tr.vb-grp { scroll-margin-top: calc(var(--measured-header-height, var(--app-header-height, 80px)) + 0.75rem); }
@keyframes ib-arrive { from { box-shadow: inset 0 0 0 100vmax var(--accent-soft, #eff4ff); } to { box-shadow: inset 0 0 0 100vmax transparent; } }
#pageContent table.ib-table > tbody > tr.vb-grp.is-arrived > td { animation: ib-arrive 1.4s ease-out; }
@media (prefers-reduced-motion: reduce) { #pageContent table.ib-table > tbody > tr.vb-grp.is-arrived > td { animation: none; } }

/* ── An open row's report ──────────────────────────────────────────────────────────────────── */
/* Its lines are labels and facts, not prose: no 78ch measure (design-system.css #pageContent p). */
#pageContent .ib-detail p { max-width: none; }
.ib-line { margin: 0.35rem 0 0.55rem; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-soft, #566274); }
.ib-line .ib-retry { padding: 0 0.15rem; }
.ib-spin {
    display: inline-block; width: 0.95em; height: 0.95em; margin-right: 0.5rem; vertical-align: -0.15em;
    border: 2px solid var(--border, #dbe1ea); border-top-color: var(--accent, #2563eb); border-radius: 50%;
    animation: ib-spin 0.8s linear infinite;
}
@keyframes ib-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ib-spin { animation: none; border-top-color: var(--border, #dbe1ea); } }
/* The facts in groups side by side, sharing the row (auto-fit: two groups take half each, not a
   quarter); the vehicles and violations the full width. */
.ib-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); gap: 0.85rem 1.5rem; padding: 0.4rem 0 0.35rem; }
.ib-group { min-width: 0; }
.ib-tables { display: grid; gap: 0.85rem; padding: 0.4rem 0 0.35rem; }
.ib-facts + .ib-tables { padding-top: 0.5rem; }
.ib-group-title {
    margin: 0 0 0.35rem; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted, #475569);
}
.ib-dl { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: 0.4rem 1rem; margin: 0; }
.ib-fact { min-width: 0; }
/* A VIN HAS A LINE OF ITS OWN AT EVERY WIDTH (2026-10-26, review): in a 136px column, at 1440, 1100
   and 768, it broke before its last character. */
.ib-dl > .ib-fact.ib-wide { grid-column: 1 / -1; }
.ib-fact dt { font-size: var(--fs-xs); font-weight: 600; color: var(--text-soft, #566274); }
/* anywhere: a VIN or an address run together must not set the column's floor. */
.ib-fact dd { margin: 0.05rem 0 0; font-size: var(--fs-sm); color: var(--text-body, #1e293b); overflow-wrap: anywhere; }
.ib-none { margin: 0; font-size: var(--fs-sm); color: var(--text-soft, #566274); }
.ib-sub-scroll { overflow-x: auto; }
/* Should a value still be too wide, Chrome stops the keyboard on the box that scrolls: ringed. */
.ib-sub-scroll:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px; }
#pageContent table.ib-sub th { position: static; background: transparent; }
/* ANYWHERE, NOT BREAK-WORD (2026-10-26, review): break-word lowers no column's floor, so a VIN or a
   plate run together, or a 90-character word, widened the record's tables past the record and sent
   SMS, BASIC and Reason behind a sideways scroll at 768 and from 900 to 1440. A code still keeps to
   its line (ib-whole). */
table.ib-sub td { vertical-align: top; white-space: normal; overflow-wrap: anywhere; }
table.ib-sub td.ib-whole { white-space: nowrap; }
/* …BUT A WORD STAYS WHOLE (2026-10-26, review): anywhere in every cell let a narrow column split its
   words, "Vehicl|e Maint." at 390 and "HOS Compli|ance" at 900–980. A column of short words keeps
   them whole (ib-words, incidents-board.js tableHtml), its longest word its floor; the long values
   above, and a token run together in any column, still break anywhere. */
table.ib-sub td.ib-words { overflow-wrap: break-word; }
#pageContent table.ib-sub > tbody > tr:hover { background: transparent; }
#pageContent table.ib-sub > tbody > tr:hover > td { background: var(--accent-soft, #eff4ff); }
.ib-fmcsa { margin: 0.55rem 0 0.1rem; font-size: var(--fs-sm); }
#pageContent .ib-fmcsa a { color: var(--accent-ink, #1d4ed8); font-weight: 600; }
.ib-retry:focus-visible, .ib-fmcsa a:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px; }
/* A RECORD NARROWER THAN ITS TABLES SHOWS THEIR ROWS AS CARDS (2026-10-26, review): from 641 to 800px
   (an iPad upright) the eight columns of an inspection's violations needed 641px of a 507–638px record
   and scrolled sideways, the last column cut mid-word — as the board cards its inspections under a
   950px box. The record is the size container; under 720px of it each row is a card, as a phone's
   (mobile.css draws those, ≤640px), each value under its column's name (data-label), two to a line,
   the first the card's title and the long ones (ib-wide) a line of their own; the cards side by side
   where there is room. */
.ib-detail { container: ibrec / inline-size; }
@media (min-width: 641px) {
    @container ibrec (max-width: 720px) {
        .ib-detail table.ib-sub { display: block; width: 100%; }
        .ib-detail table.ib-sub > thead { display: none; }
        .ib-detail table.ib-sub > tbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 8px; }
        #pageContent .ib-detail table.ib-sub > tbody > tr {
            display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; gap: 6px 12px;
            padding: 10px 12px; border: 1px solid var(--border, #dbe1ea); border-radius: 10px; background: var(--surface-alt, #fff);
        }
        #pageContent .ib-detail table.ib-sub > tbody > tr > td {
            display: block; min-width: 0; padding: 0; border: 0; background: transparent; text-align: left; white-space: normal; overflow-wrap: anywhere;
        }
        /* A LABEL AND A ONE-WORD VALUE MAY PART (2026-10-26, review): drawn in front of its value with no
           space between, "Make" and "FREIGHTLINER" were one word to the line, and in half a card the
           make broke "FREIGHTLINE|R" (here at 700, on a phone at 360). A zero-width space after the
           label lets the value go under it whole. */
        .ib-detail table.ib-sub > tbody > tr > td::before {
            content: attr(data-label) "\200B"; margin-right: 0.4em; font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.02em; color: var(--text-muted, #475569);
        }
        #pageContent .ib-detail table.ib-sub > tbody > tr > td:first-child { grid-column: 1 / -1; font-weight: 600; }
        .ib-detail table.ib-sub > tbody > tr > td:first-child::before { display: none; }
        #pageContent .ib-detail table.ib-sub > tbody > tr > td.ib-wide { grid-column: 1 / -1; }
        #pageContent .ib-detail table.ib-sub > tbody > tr:hover > td { background: transparent; }
        body.theme-dark #pageContent .ib-detail table.ib-sub > tbody > tr { border-color: var(--border-strong, #565663); }
        body.theme-dark #pageContent .ib-detail table.ib-sub > tbody > tr:hover > td { background-color: transparent !important; }
    }
}

/* Dark mode: the chip in the dark palette's green (8.9:1), the count pill a step off the card, and
   no stripes or painted cells in the report's tables (dark-mode.css paints every table cell). */
body.theme-dark .ib-np { color: #86efac; background: rgba(34, 197, 94, 0.14); border-color: rgba(74, 222, 128, 0.42); }
body.theme-dark .ib-section .incident-title-count { color: var(--accent-200); background: rgba(var(--accent-400-rgb), 0.18); }
body.theme-dark .ib-spin { border-color: var(--border-strong, #565663); border-top-color: var(--accent, #7aa9f7); }
body.theme-dark #pageContent table.ib-sub > tbody > tr > td { background-color: transparent !important; }
body.theme-dark #pageContent table.ib-sub > tbody > tr:hover { background: transparent !important; }
body.theme-dark #pageContent table.ib-sub > tbody > tr:hover > td { background-color: rgba(var(--accent-ink-rgb), 0.08) !important; }
body.theme-dark #pageContent table.ib-sub thead th { background: transparent !important; }
/* The map's state panel, dark (2026-10-25): its count pills kept the light palette's ink, 6
   inspections at 2.1:1 on the dark card (review; so before the rename too). The dark palette's. */
body.theme-dark .incident-state-panel .state-count-badge.inspection { color: #93c5fd; background: rgba(96, 165, 250, 0.16); }
body.theme-dark .incident-state-panel .state-count-badge.crash { color: #fca5a5; background: rgba(248, 113, 113, 0.16); }
/* A REPORT THE TABLES DO NOT LIST, NAMED BUT NOT LINKED (2026-10-26, review; app.js
   renderStateIncidentPanel): the link's weight, the body's ink. */
.incident-state-panel .incident-report-name { font-weight: 700; color: var(--text, #0f172a); overflow-wrap: anywhere; }
/* THE MAP'S OWN LINE IN DARK MODE (2026-10-26, review): with no map drawn in it — a report on its way,
   one without FMCSA's detail — the box kept Leaflet's light grey (#ddd, leaflet.css) under the dark
   palette's soft grey, 2:1 (so on HEAD too). A dark well instead, 6:1; light mode keeps its look. */
body.theme-dark #incidentMap:not(:has(.leaflet-pane)) { background: var(--surface, #202023); }
/* THE INSPECTIONS & CRASHES MAP'S CONTROLS IN DARK MODE (2026-10-27; the owner: "take screenshots accross the
   website pages in dark mode to spot bad contrast text, cards and fix it"): the dark Leaflet rules above were
   written for the board's map dialog only, so this map kept white zoom buttons whose +/- dark-mode.css's link
   rule turned #7aa9f7 (2.37:1), a white attribution with its link at 2.24:1, and Leaflet's #ddd ground round
   the tiles. The dialog's twins, for this map; the tiles are the map and stay as they are. */
body.theme-dark #incidentMap.leaflet-container { background: var(--surface, #202023); }
body.theme-dark #incidentMap .leaflet-bar { border-color: var(--zinc-700); }
body.theme-dark #incidentMap .leaflet-bar a { background-color: var(--surface-alt) !important; color: var(--zinc-200) !important; border-bottom-color: var(--zinc-700) !important; }
body.theme-dark #incidentMap .leaflet-bar a:hover { background-color: var(--tone-33333a, #33333a) !important; }
body.theme-dark #incidentMap .leaflet-control-attribution { background: rgba(var(--tone-202023-rgb, 32, 32, 35), 0.9) !important; color: var(--text-body) !important; }
body.theme-dark #incidentMap .leaflet-control-attribution a { color: var(--accent-300) !important; }
body.theme-dark #incidentMap .leaflet-popup,
body.theme-dark #incidentMap .leaflet-popup-tip-container,
body.theme-dark #incidentMap .leaflet-popup-content { background-color: transparent !important; }
body.theme-dark #incidentMap .leaflet-popup-content-wrapper,
body.theme-dark #incidentMap .leaflet-popup-tip { background-color: var(--surface-alt) !important; color: var(--text-body, #d4d4d8); box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55); }
body.theme-dark #incidentMap a.leaflet-popup-close-button { color: var(--text-body) !important; background-color: transparent !important; }
/* The board's map dialog: its slate scrim (rgba(15,23,42,.62)) dimmed nothing on the dark page (1.01:1). */
body.theme-dark .vb-mapmodal { background: rgba(0, 0, 0, 0.6); }

/* Phones: mobile-tables.js makes each row a card (the report its title, as the board's name is) and
   each of the report's tables too; the facts two to a line, and Sort above the cards. */
@media (max-width: 640px) {
    .ib > .ib-bar.pred-vt { display: block; }
    .ib > .ib-bar .pred-vt-bar { grid-template-columns: minmax(0, 1fr); }
    .ib-facts { grid-template-columns: minmax(0, 1fr); gap: 0.75rem; }
    .ib-dl { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    table.vb-groups.ib-table[data-m-reflow] td.vb-c-name { min-width: 0; }
    /* A REPORT NUMBER RUN TOGETHER BREAKS INSIDE ITS CARD (2026-10-25, review: one of 42 characters
       ran past the card at 360). mobile.css's break-word for a card's spans outranks .vb-name's
       anywhere, and the toggle's flexbox took the whole token's width. */
    table.ib-table[data-m-reflow] td .vb-name { overflow-wrap: anywhere; min-width: 0; }
    table.ib-table[data-m-reflow] td .vb-toggle { max-width: 100%; }
    /* A VIN, and a plate number behind its label, on a line of their own: in half of one the VIN
       broke mid-string and the label over two lines (2026-10-25, review). A crash's VIN fact has its
       line at every width since 2026-10-26 (above). */
    #pageContent table.ib-sub[data-m-reflow] > tbody > tr > td.ib-wide { grid-column: 1 / -1; }
    /* ONE VALUE TO A LINE ON THE NARROWEST PHONES (2026-10-26, review): a record's card is two values to
       a line, and at 320 half of it is 101px — "INTERNATIONAL" alone is wider. Two to a line while
       each half holds 7rem (as at 360), one to a line under that. NEVER MORE THAN TWO (2026-10-26,
       review): a track for each 7rem put three values on a line at 480 and four at 600–640, wrapping
       beside empty tracks, where the rows' cards, the record's facts and mobile.css's are two. Each
       track at least 40% of the card: room for two, never three. */
    #pageContent .ib-detail table.ib-sub[data-m-reflow] > tbody > tr { grid-template-columns: repeat(auto-fit, minmax(max(7rem, 40%), 1fr)); }
    /* 44px to tap: Try again, the FMCSA link and Show all (2026-10-25, review). A flexbox drops the
       space before the link's arrow, so the gap stands in for it. */
    .ib .ib-retry, .ib .ib-fmcsa a, .ib > .ib-more { display: inline-flex; align-items: center; min-height: 44px; column-gap: 0.3em; }
    /* TRY AGAIN ON A LINE OF ITS OWN (2026-10-26, review): 44px tall on the last line of FMCSA's
       sentence, it opened 10px more above that line than between the others. */
    .ib .ib-line .ib-retry { display: flex; width: fit-content; margin-top: 0.25rem; }
    /* …and the map panel's reports (2026-10-26, review): 21px tall, and now the map's only way into
       the rows. A REPORT NAMED, NOT LINKED, IN THE SAME BOX (2026-10-26, review): it sat 11px lower
       than a linked one beside it. */
    .incident-state-panel a.incident-report-link,
    .incident-state-panel .incident-report-name { display: inline-flex; align-items: center; min-height: 44px; }
    /* An inspection's severity weight in its card: the BASICs run on, " · " between them, each whole;
       two or more take the card's line (incidents-board.js sevHtml). mobile.css lets every span in a
       card wrap, !important; a BASIC and its figure must not part. */
    table.ib-table[data-m-reflow] td.ib-c-sevb .ib-sevb { display: inline; white-space: nowrap !important; }
    table.ib-table[data-m-reflow] td.ib-c-sevb .ib-sevsep { display: inline; }
    table.ib-table[data-m-reflow] > tbody > tr.vb-grp > td.ib-c-sevb:has(.ib-sevsep) { grid-column: 1 / -1; }
    /* …and one BASIC keeps its half (2026-10-26): its note for a screen reader (sevPartHtml) is text
       mobile-tables.js counts, and past 28 characters that gives a cell the card's whole line. */
    table.ib-table[data-m-reflow] > tbody > tr.vb-grp > td.ib-c-sevb:not(:has(.ib-sevsep)) { grid-column: auto; }
    /* THE NOTE STAYS ON ONE LINE (2026-10-26, review): mobile.css lets every span in a card wrap,
       !important, and in its 1px box ", capped at 30: …" fell a letter or two to a line, 34 lines —
       text VoiceOver can join without its spaces. Kept out of that rule. */
    .ib table[data-m-reflow] td .ib-sr { white-space: nowrap !important; overflow-wrap: normal !important; }
    /* A label and a one-word value may part on a phone too, in the rows' cards and the record's (the
       zero-width space of the record's cards from 641px, above). */
    .ib table[data-m-reflow] > tbody > tr > td::before { content: attr(data-label) "\200B"; }
    /* The report's own tables, carded inside the open card: no second frame of their own. */
    #pageContent table.ib-sub[data-m-reflow] > tbody > tr:hover > td,
    body.theme-dark #pageContent table.ib-sub[data-m-reflow] > tbody > tr:hover > td { background-color: transparent !important; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════
   TOP VIOLATIONS BY CATEGORY (2026-10-27) — js/modules/top-violations.js, on Analytics
   ════════════════════════════════════════════════════════════════════════════════════════════════
   The owner: "Rework top violations by category to resemble the data more clearly, adhear to the new
   website styling". The card IS the board's groups table (.vb-groups, .vb-grp, .vb-toggle, .vb-detail,
   .pred-sorthead, .vb-scroll's container) with a <tbody> per BASIC, so every rule above is its own too:
   the open row's tint, the detail's accent line, the phone's cards, dark mode. Here: a BASIC's head
   row, the share's bar, an open group's codes, Show all, and the lines saying where the figures come
   from. Its classes say tv-, never "analytics-" or "pred" (dark mode flattens those) nor "-card" or
   "-popup" (dark mode paints those). */
.tv { container: tvbox / inline-size; }
.tv-basis, .tv-note { margin: 0 0 0.5rem; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-soft, #566274); }
.tv-basis strong { font-weight: 600; color: var(--text, #0f172a); }
.tv-none { margin: 0.6rem 0 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-soft, #566274); }
/* The Sort select: on a phone, and where the card is too narrow for Most recent (below) — the
   predictive bar's own select, as the Inspections & Crashes tables show it. */
.tv > .tv-sortbar.pred-vt { display: none; margin: 0 0 0.5rem; padding: 0; border: 0; }

/* A BASIC'S HEAD: a band across the table, as the measures read on the Violations tab — the swatch and
   name, where it stands (a red Alert chip, the board's acute chip, at or over its line), then its
   measure and counts at the right. Not the sticky, capitalised column head design-system.css gives
   every th. */
#pageContent table.tv-table > tbody > tr.tv-head > th {
    position: static; padding: 0.6rem 0.6rem 0.5rem; white-space: normal; text-transform: none; letter-spacing: 0;
    font-size: var(--fs-sm); font-weight: 400; line-height: 1.45; color: var(--text-soft, #566274);
    background: var(--surface, #f4f6fa); border-top: 1px solid var(--border-strong, #b6c1d1); border-bottom: 1px solid var(--border, #dbe1ea);
}
#pageContent table.tv-table > tbody > tr.tv-head:hover { background: transparent; }
.tv-hrow { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.9rem; }
.tv-hname { font-size: var(--fs-base); font-weight: 700; color: var(--text, #0f172a); white-space: nowrap; }
.tv-hname .pred-cat-swatch { margin-right: 0.45rem; }
.tv-hstand { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.45rem; }
.tv-stand-fig { font-weight: 700; color: var(--text, #0f172a); font-variant-numeric: tabular-nums; }
.tv-stand-fig.is-over { color: var(--danger-ink, #b91c1c); }
.tv-line, .tv-fig { white-space: nowrap; }
.tv-hfigs { margin-left: auto; font-variant-numeric: tabular-nums; }

/* A GROUP'S ROW. The name keeps room for a line of codes; the share is a bar on its BASIC's 0–100%,
   the figure beside it, and what that is of FMCSA's measure under it. */
table.tv-table td.tv-c-name { min-width: 13rem; }
table.tv-table th.tv-c-share { width: 28%; }
table.tv-table td.tv-c-share { min-width: 10rem; }
.tv-share { display: flex; align-items: center; gap: 0.55rem; }
.tv-meter { flex: 1 1 auto; min-width: 3.5rem; height: 0.55rem; overflow: hidden; border-radius: 999px; background: var(--border-subtle, #e8ecf3); }
.tv-fill { display: block; height: 100%; border-radius: inherit; }
.tv-pct { flex: 0 0 auto; min-width: 2.6rem; text-align: right; font-weight: 700; color: var(--text, #0f172a); font-variant-numeric: tabular-nums; }
.tv-of { font-variant-numeric: tabular-nums; }
/* The date under the name, where the card has no room for its column (below). */
.tv-alt { display: none; margin: 0.12rem 0 0 1.05rem; font-size: var(--fs-xs); color: var(--text-soft, #566274); }
/* FMCSA'S SUMMARY ALONE has no dates: no Most recent column, at any width. */
table.tv-table.tv-summary .tv-c-date, table.tv-table.tv-summary .tv-alt { display: none !important; }

/* SHOW ALL, BASIC BY BASIC: under its rows at their left, with what the groups it leaves out hold. */
#pageContent table.tv-table > tbody > tr.tv-more-row > td { padding: 0.15rem 0.6rem 0.55rem; }
#pageContent table.tv-table > tbody > tr.tv-more-row:hover { background: transparent; }
.tv-more.pred-vt-more { margin: 0; }
.tv-more-note { margin-left: 0.5rem; font-size: var(--fs-sm); color: var(--text-soft, #566274); }

/* AN OPEN GROUP'S CODES: each with its description in full, then its figures. */
table.tv-codes { width: 100%; }
#pageContent table.tv-codes th { position: static; background: transparent; white-space: nowrap; }
#pageContent table.tv-codes > tbody > tr > td { vertical-align: top; }
#pageContent table.tv-codes > tbody > tr:last-child > td { border-bottom: 0; }
#pageContent table.tv-codes > tbody > tr:hover { background: transparent; }
#pageContent table.tv-codes > tbody > tr:hover > td { background: var(--accent-soft, #eff4ff); }
table.tv-codes th.vb-num, table.tv-codes td.vb-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
table.tv-codes td.tv-k-code { white-space: nowrap; font-weight: 600; color: var(--text, #0f172a); }
/* A CODE KEEPS ITS LINE, BUT NOT PAST THE CARD (2026-10-27, verify round 1: one run together pushed the
   Share column 27px out of the open group at 1440). The library's longest codes are 22 characters
   ("393.47D1-BPTAD-SA-1/16") and stay whole; one over 24 (top-violations.js marks it) breaks. */
/* 8REM, NOT 12 (2026-10-27, verify round 2): at 768 the open group's 12rem code and 12rem description left its
   Share 34px past the scroller. */
table.tv-codes td.tv-k-code.is-long { min-width: 8rem; white-space: normal; overflow-wrap: anywhere; }
/* THE SAME FOR A GROUP ROW'S CHIP (2026-10-27, verify round 2: at 1024 and 768 a 65-character chip
   widened the table 110px inside its scroller, Highest severity and Most recent out of view). */
table.tv-table .vb-codes .ib-code.is-long { white-space: normal; overflow-wrap: anywhere; }
/* anywhere, as .vb-name: a description run together must not set the column's floor. */
table.tv-codes td.tv-k-desc { width: 100%; min-width: 12rem; white-space: normal; overflow-wrap: anywhere; }
table.tv-codes td.tv-k-share { font-weight: 700; color: var(--text, #0f172a); }
.tv-detail { container: tvrec / inline-size; }

/* A NARROW CARD (under about 760px of it, a tablet upright or half a laptop): Most recent goes under the
   name, and the orders are the Sort select's, as on a phone. */
@media (min-width: 641px) {
    @container tvbox (max-width: 760px) {
        table.tv-table .tv-c-date { display: none; }
        table.tv-table .tv-alt { display: block; }
        table.tv-table td.tv-c-name { min-width: 9rem; }
        table.tv-table td.tv-c-share { min-width: 8rem; }
        .tv > .tv-sortbar.pred-vt { display: block; }
        .tv > .tv-sortbar .pred-vt-sortsel { display: block; width: auto; max-width: 100%; }
    }
}
/* AN OPEN GROUP NARROWER THAN ITS CODES' COLUMNS (under 560px of it, a phone included): each code a
   block — the code and its share on top, the description, then its figures named. */
@container tvrec (max-width: 560px) {
    table.tv-codes, table.tv-codes > tbody { display: block; width: 100%; }
    table.tv-codes > thead { display: none; }
    #pageContent table.tv-codes > tbody > tr {
        display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 1rem; padding: 0.5rem 0;
        border-top: 1px solid var(--border-subtle, #e8ecf3);
    }
    #pageContent table.tv-codes > tbody > tr:first-child { border-top: 0; }
    #pageContent table.tv-codes > tbody > tr > td {
        display: block; min-width: 0; padding: 0; border: 0; background: transparent; text-align: left; white-space: normal;
    }
    #pageContent table.tv-codes > tbody > tr:hover > td { background: transparent; }
    table.tv-codes td.tv-k-code { order: 1; flex: 1 1 auto; overflow-wrap: anywhere; }
    table.tv-codes td.tv-k-share { order: 2; }
    table.tv-codes td.tv-k-desc { order: 3; flex: 1 1 100%; min-width: 0; }
    table.tv-codes td.tv-k-sev { order: 4; }
    table.tv-codes td.tv-k-count { order: 5; }
    table.tv-codes td.tv-k-oos { order: 6; }
    table.tv-codes td.tv-k-sev::before, table.tv-codes td.tv-k-count::before, table.tv-codes td.tv-k-oos::before, table.tv-codes td.tv-k-share::before {
        content: attr(data-label); margin-right: 0.35em; font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted, #475569);
    }
}

/* Dark mode: the band a step off the card, the track a faint line, no painted cells under the codes
   (dark-mode.css paints every table cell), and the red of the dark palette. */
body.theme-dark #pageContent table.tv-table > tbody > tr.tv-head > th {
    background-color: var(--surface, #202023) !important; color: var(--text-soft, #9d9da6) !important;
    border-top-color: var(--border-strong, #565663) !important; border-bottom-color: var(--border, #3a3a42) !important;
}
body.theme-dark .tv-meter { background: rgba(255, 255, 255, 0.1); }
body.theme-dark #pageContent table.tv-codes > tbody > tr > td { background-color: transparent !important; }
body.theme-dark #pageContent table.tv-codes > tbody > tr:hover { background: transparent !important; }
body.theme-dark #pageContent table.tv-codes > tbody > tr:hover > td { background-color: rgba(var(--accent-ink-rgb), 0.08) !important; }
body.theme-dark #pageContent table.tv-codes thead th { background: transparent !important; }
body.theme-dark #pageContent table.tv-table > tbody > tr.tv-more-row:hover > td { background-color: transparent !important; }

/* Phones: mobile-tables.js makes each group a card (its name the title, its share a whole line); a
   BASIC's head reads as a heading over its cards, not a card of its own; Sort above them. */
@media (max-width: 640px) {
    .tv > .tv-sortbar.pred-vt { display: block; }
    .tv > .tv-sortbar .pred-vt-bar { grid-template-columns: minmax(0, 1fr); }
    table.tv-table[data-m-reflow] > tbody + tbody { margin-top: 0.85rem; }
    table.tv-table[data-m-reflow] > tbody > tr.tv-head {
        display: block !important; padding: 0 0 0.4rem !important; margin: 0 0 8px !important;
        border: 0 !important; border-bottom: 1px solid var(--border, #dbe1ea) !important; border-radius: 0; background: transparent !important;
    }
    #pageContent table.tv-table[data-m-reflow] > tbody > tr.tv-head > th {
        display: block !important; padding: 0 !important; border: 0 !important; background: transparent !important;
    }
    table.tv-table[data-m-reflow] > tbody > tr.tv-head > th::before { display: none; }
    .tv-hfigs { margin-left: 0; flex-basis: 100%; }
    table.tv-table[data-m-reflow] td.tv-c-name { min-width: 0; }
    /* A NAME OR CODE RUN TOGETHER BREAKS INSIDE ITS CARD (2026-10-27, verify round 1: one of 94
       characters ran 689px past the card at 390), the Inspections & Crashes cards' fix: mobile.css's
       break-word for a card's spans outranks .vb-name's anywhere, and the toggle took the token's width. */
    table.tv-table[data-m-reflow] td .vb-name, table.tv-table[data-m-reflow] td .ib-code { overflow-wrap: anywhere; min-width: 0; }
    table.tv-table[data-m-reflow] td .vb-toggle { max-width: 100%; }
    /* SHOW ALL'S HIDDEN WORDS ON ONE LINE (2026-10-27, verify round 3): mobile.css lets every span in a
       card wrap, !important, and in its 1px box "in Vehicle Maintenance" fell a letter or two to a line,
       20 lines, text VoiceOver can join without its spaces. The Inspections & Crashes cards' guard
       (.ib, above), for this card. */
    table.tv-table[data-m-reflow] td .ib-sr { white-space: nowrap !important; overflow-wrap: normal !important; }
    /* …AND A CODE CHIP WHOLE: the same rule broke "393.9A-LSML" at its hyphen and "+1 more" at its
       space. A chip is at most 24 characters here (top-violations.js marks a longer one is-long, which
       still breaks anywhere, above); the chips wrap between themselves. */
    table.tv-table[data-m-reflow] td .vb-codes .ib-code:not(.is-long) { white-space: nowrap !important; }
    table.tv-table[data-m-reflow] > tbody > tr.vb-grp > td.tv-c-share { grid-column: 1 / -1; min-width: 0; }
    /* The share's bar and figure stay on one line in the card: mobile.css lets every span in a card
       wrap, and the figure fell under its bar. */
    table.tv-table[data-m-reflow] .tv-share { display: flex !important; }
    table.tv-table[data-m-reflow] .tv-pct { white-space: nowrap !important; }
    /* MOST RECENT IS ONE LABEL: in half a card it broke "Most" over "recent 04/13/2026". Kept whole (a
       no-break space), the date going under it whole when they do not fit on one line (a zero-width
       space after it, as the Inspections & Crashes cards have it). */
    table.tv-table[data-m-reflow] > tbody > tr.vb-grp > td.tv-c-date::before { content: "Most\00a0recent\200B"; }
    /* 44px to tap: Show all. Its note is a note: mobile.css sets a card's first cell in 600. */
    table.tv-table .tv-more { display: inline-flex; align-items: center; min-height: 44px; }
    .tv-more-note { display: block; margin: 0 0 0.25rem; font-weight: 400; }
    body.theme-dark table.tv-table[data-m-reflow] > tbody > tr.tv-head { border-bottom-color: var(--border-strong, #565663) !important; }
    /* …and no band in dark mode either: the desktop's dark band (above) out-ranked the reset. */
    body.theme-dark #pageContent table.tv-table[data-m-reflow] > tbody > tr.tv-head > th { background-color: transparent !important; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════
   THE OVERVIEW'S SHARED EQUIPMENT (2026-10-27) — js/modules/incidents-board.js, kind shared
   ════════════════════════════════════════════════════════════════════════════════════════════════
   The owner (2026-10-26): "Change the shared equipment from individual cards to a table, similar to
   inspection and crashes. In the table also show a report number that opens inline when clicked."
   It IS the Inspections & Crashes table (.ib, .ib-table, every rule above): a row per unit and other
   carrier, its report the toggle. Here only what a shared unit has that an inspection does not: the
   VIN, the weak match, the carrier, its status and Last ours, and the note over an older save. */
.se-box { margin-top: 0.85rem; }
/* THE BOARD'S LINES, NOT THE DOSSIER'S VALUES (2026-10-27): report-detail.css sets every .ov-detail p
   and its spans in the card's large value size, with its own margins — the note, an open row's lines
   and their spinner read 18px beside a 14px table. The board's size and spacing back, at #pageContent
   strength. */
#pageContent .ov-detail .se-box p, #pageContent .ov-detail .se-box p span { font-size: var(--fs-sm); line-height: 1.5; }
#pageContent .ov-detail .se-box p.ib-line { margin: 0.35rem 0 0.55rem; }
#pageContent .ov-detail .se-box p.ib-fmcsa { margin: 0.55rem 0 0.1rem; }
#pageContent .ov-detail .se-box p.ib-none { margin: 0; }
#pageContent .ov-detail .se-box p.se-note { margin: 0 0 0.6rem; }
/* A VIN IN THE TABLE'S INK (2026-10-27): a bare <code> is azia's pink in light mode, and the old cards'
   VINs and names were link blue in dark mode without being links. Monospace, so VINs line up. */
.se-vin { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; font-size: 0.95em; color: var(--text, #0f172a); white-space: nowrap; }
.se-name { color: var(--text, #0f172a); }
/* The carrier takes the spare width and wraps; the longest real name is 74 characters. */
table.ib-table-shared td.se-c-carrier { min-width: 12rem; white-space: normal; overflow-wrap: anywhere; }
table.ib-table-shared td.se-c-unit, table.ib-table-shared td.se-c-status { white-space: nowrap; }
/* THE VIN SETS THE UNIT'S WIDTH, NOT THE LINE UNDER IT (2026-10-27, review): its words and its other
   carriers wrap, so a long unit word does not push the table past its box. */
table.ib-table-shared td.se-c-unit .vb-sub { white-space: normal; overflow-wrap: anywhere; }
table.ib-table-shared th.se-c-status { width: 1%; }
/* The census status in the old cards' badge and colours (components.css, report-detail.css, dark-mode.css),
   at a chip's size beside 14px cells, as the board's not-preventable chip is. */
table.ib-table-shared .chameleon-status-badge { padding: 0 0.5rem; font-size: var(--fs-xs); line-height: 1.5; white-space: nowrap; }
/* A unit number where the VIN goes: amber, as a caution is; 7:1 and better. */
.se-weak {
    display: inline-block; margin-left: 0.35rem; padding: 0 0.45rem; font-size: var(--fs-xs); font-weight: 700; line-height: 1.5; white-space: nowrap;
    color: #92400e; background: #fef3c7; border: 1px solid #fcd34d; border-radius: var(--radius-pill, 999px); cursor: help;
}
/* A ROW WITH NOTHING TO OPEN (an older save's): no pointer, no toggle — its words where the report goes. */
table.ib-table-shared > tbody > tr.vb-grp.is-static { cursor: default; }
/* Show all puts the keyboard on a row with no button (incidents-board.js showAll, 2026-10-27): it shows. */
table.ib-table > tbody > tr.vb-grp[tabindex]:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: -2px; }
.se-noreport { font-style: italic; }
table.ib-table-shared td.ib-c-report .se-noreport ~ .ib-alt { margin-left: 0; }
/* The status again beside the carrier, for a box with no room for its column (below). */
.se-alt-status { display: none; }
/* Whose inspection an open row is, above FMCSA's record. */
.ib-detail .se-context { color: var(--text-body, #1e293b); }
/* THE NOTE OVER AN OLDER SAVE, AND ITS UPDATE (incidents-board.js syncSharedNote). */
.se-note {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.75rem; margin: 0 0 0.6rem; padding: 0.5rem 0.75rem;
    font-size: var(--fs-sm); line-height: 1.5; color: var(--text-body, #1e293b);
    background: var(--warning-soft, #fdf2e5); border: 1px solid #f5d9a8; border-radius: var(--radius-xs, 6px);
}
#pageContent .se-note { max-width: none; }
.se-update[aria-disabled="true"] { opacity: 0.7; cursor: progress; }
.se-update:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px; }
/* A TABLET, UPRIGHT (the box under about 880px): six columns needed more than the card has at 768. Last
   ours goes under the report and the status beside the carrier; their sorts stay in the select. */
@media (min-width: 641px) {
    @container vbbox (max-width: 880px) {
        table.ib-table-shared .se-c-ours, table.ib-table-shared .se-c-status { display: none; }
        table.ib-table-shared .se-alt-status { display: block; margin-top: 0.2rem; }
        table.ib-table-shared td.se-c-carrier { min-width: 9rem; }
    }
}
body.theme-dark .se-weak { color: #fcd34d; background: rgba(245, 158, 11, 0.14); border-color: rgba(251, 191, 36, 0.42); }
body.theme-dark .se-note { border-color: rgba(240, 182, 87, 0.35); }
/* Phones: mobile-tables.js makes each row a card, the report its title; a VIN may break inside a
   narrow card rather than run past it. */
@media (max-width: 640px) {
    table.ib-table-shared[data-m-reflow] td .se-vin { white-space: normal !important; overflow-wrap: anywhere !important; }
    .se-note { padding: 0.5rem 0.65rem; }
    .se-note .se-update { min-height: 44px; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════
   THE VIOLATIONS LIBRARY (2026-10-27) — js/modules/violation-library.js
   ════════════════════════════════════════════════════════════════════════════════════════════════
   The owner: "Rework the violations library in violations to the new table format, also add filtering
   with dropdowns". The table IS the board's groups table (.vb-groups, .vb-grp, .vb-toggle, .vb-detail,
   .pred-sorthead, .vb-scroll's container) and an open row holds the Inspections & Crashes record's
   groups of facts (.ib-facts, .ib-group, .ib-dl), so their rules (light and dark, the narrower boxes,
   the phone's cards) are its own too. Here only what a library code has that they do not: its
   columns, the toolbar of dropdowns, the chip that says the carrier was cited, and the lines a
   narrower box puts under the code. Every ink is a token, which dark mode redefines: the old card's
   #596882 read 2.72:1 on the dark card. */
.vlib { container: vlibbox / inline-size; }
.vlib-state { display: flex; align-items: center; flex-wrap: wrap; gap: 0.25rem 0.5rem; }
/* The card's own toolbar, under its title: no rule above it, as the predictive list has. */
.vlib > .vlib-tools.pred-vt { margin-top: 0; padding-top: 0; border-top: 0; }
/* A closed dropdown never wider than this: its longest group would set it at 18rem. The search
   gives way, so the five dropdowns and the search take one line at 1440 (the predictive bar's
   15rem basis put the last dropdown on a line of its own). A phone's bar is a grid (report-detail.css). */
@media (min-width: 641px) {
    #pageContent .vlib .pred-vt-bar select.vlib-sel { max-width: 15rem; }
    /* The group's own: at 15rem eight group names were cut when chosen (Jumping OOS/Driving Fatigued);
       at 17.5rem only the longest, Clearance Identification Lamps/Other (2026-10-27, review). */
    #pageContent .vlib .pred-vt-bar select.vlib-sel[data-vlib-filter="group"] { max-width: 17.5rem; }
    .vlib .pred-vt-bar .pred-vt-search { flex: 1 1 9rem; max-width: 22rem; }
}
.vlib > .vlib-meta { margin-top: 0.6rem; }
/* The code is one piece; one past a code's size (markup, junk) wraps instead of widening the table. */
table.vlib-table td.vlib-c-code { white-space: nowrap; }
table.vlib-table .vlib-code { white-space: nowrap; }
table.vlib-table .vlib-code.is-long { white-space: normal; overflow-wrap: anywhere; }
/* THE WHOLE DESCRIPTION, ALWAYS: it wraps between words and its column takes the slack. */
table.vlib-table td.vlib-c-desc { width: 100%; min-width: 14rem; white-space: normal; overflow-wrap: break-word; }
table.vlib-table td.vlib-c-basic, table.vlib-table td.vlib-c-dsms { white-space: nowrap; }
table.vlib-table td.vlib-c-group { min-width: 8rem; white-space: normal; overflow-wrap: break-word; }
/* No report citing a code: no This carrier column (violation-library.js, vlib-nocarrier). */
table.vlib-table.vlib-nocarrier .vlib-c-cited { display: none; }
/* Cited: the count, and the OOS under it, quiet. */
table.vlib-table td.vlib-c-cited .vlib-oos { white-space: nowrap; }
/* The chip beside the code, and the lines under it: for the boxes that hide those columns (below). */
.vlib-chip {
    display: none; margin-left: 0.45rem; padding: 0 0.45rem; vertical-align: baseline;
    font-size: var(--fs-xs); font-weight: 700; line-height: 1.5; white-space: nowrap;
    color: var(--accent-ink, #1d4ed8); background: var(--accent-soft, #eff4ff);
    border: 1px solid var(--accent-soft-border, #c7d9fb); border-radius: var(--radius-pill, 999px);
}
.vlib-alt { display: none; margin: 0.12rem 0 0 1.05rem; font-size: var(--fs-xs); white-space: normal; color: var(--text-soft, #566274); overflow-wrap: break-word; }
.vlib-alt .vb-basic { white-space: normal; }
/* SHOW IN THE VIOLATIONS ABOVE lands the board's list under the sticky header, not behind it. */
.vb-list { scroll-margin-top: calc(var(--measured-header-height, var(--app-header-height, 80px)) + 0.75rem); }

/* ── An open code ──────────────────────────────────────────────────────────────────────────── */
/* Its lines are labels and facts, not prose: no 78ch measure (design-system.css #pageContent p). */
#pageContent .vlib-detail p { max-width: none; }
/* The reports and the way to the board under the fact groups, the record's whole width. */
.vlib-after { display: grid; gap: 0.6rem; padding: 0.5rem 0 0.35rem; }
.vlib-reports { display: flex; flex-wrap: wrap; gap: 0.2rem 1.25rem; margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); color: var(--text-body, #1e293b); }
.vlib-rep-date { font-variant-numeric: tabular-nums; color: var(--text-soft, #566274); }
.vlib-rep-num { font-weight: 600; color: var(--text, #0f172a); overflow-wrap: anywhere; }
.vlib-actions { margin: 0; }
#pageContent .vlib-detail a { color: var(--accent-ink, #1d4ed8); font-weight: 600; }
.vlib-detail a:focus-visible, .vlib-jump:focus-visible, .vlib-more:focus-visible { outline: var(--focus-outline, 2px solid #2563eb); outline-offset: 2px; }

/* ── Less room (the box under 1080px, a phone aside) ───────────────────────────────────────── */
/* The BASIC may take two lines, and the description gives up some of its floor. A TABLET, UPRIGHT
   (the box under about 880px): the seven columns needed about 780px. The group and the Driver SMS
   flag go under the code instead of in columns of their own, and the orders are the Sort select's,
   as on a phone (the Inspections & Crashes rule: no sort out of reach). */
@media (min-width: 641px) {
    @container vlibbox (max-width: 1080px) {
        table.vlib-table td.vlib-c-basic, table.vlib-table td.vlib-c-basic .vb-basic { white-space: normal; }
        table.vlib-table td.vlib-c-desc { min-width: 10rem; }
    }
    @container vlibbox (max-width: 880px) {
        table.vlib-table .vlib-c-group, table.vlib-table .vlib-c-dsms { display: none; }
        table.vlib-table .vlib-alt-tab { display: block; }
        table.vlib-table td.vlib-c-desc { min-width: 8rem; }
        /* The search on its own line and the six dropdowns two to a line: wrapped as they came, they
           took three ragged lines at 768, and three to a line cut the BASIC and the group chosen
           (2026-10-27, review). */
        .vlib .pred-vt-bar { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
        .vlib .pred-vt-bar .pred-vt-search { grid-column: 1 / -1; max-width: 26rem; }
        #pageContent .vlib .pred-vt-bar select.pred-vt-select,
        #pageContent .vlib .pred-vt-bar select.vlib-sel[data-vlib-filter="group"] { width: 100%; max-width: none; }
        .vlib .pred-vt-bar .pred-vt-sortsel { display: block; }
        .vlib .pred-vt-bar .pred-vt-clear { justify-self: start; }
    }
}
/* EVERY DROPDOWN NAMES WHAT IS CHOSEN, ITS COUNT TOO (2026-10-27, review): a select's text cannot wrap,
   and a phone's half read Vehicle Maintena…, Brakes, All Oth…, Cited for this c…. Under 600px the
   BASIC, the group and This carrier take the line; under 420px (every phone upright) every dropdown
   does. Severity, Driver SMS and Sort stay two to a line while a half holds them. */
@container vlibbox (max-width: 600px) {
    .vlib .pred-vt-bar > .vlib-sel[data-vlib-filter="basic"],
    .vlib .pred-vt-bar > .vlib-sel[data-vlib-filter="group"],
    .vlib .pred-vt-bar > .vlib-sel[data-vlib-filter="mine"] { grid-column: 1 / -1; }
}
@container vlibbox (max-width: 420px) {
    .vlib .pred-vt-bar { grid-template-columns: minmax(0, 1fr); }
}

/* ── Phones: a compact card per code ───────────────────────────────────────────────────────── */
/* mobile-tables.js makes each row a card (seven columns), its code the title. The card holds the
   code, the cited chip, one quiet line (the BASIC, group, weight and Driver SMS flag) and the
   description in full; the cells those came from are hidden, so a card is three or four lines, not
   seven values two to a line. */
@media (max-width: 640px) {
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-basic,
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-group,
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-sev,
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-dsms,
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-cited { display: none !important; }
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-desc { grid-column: 1 / -1; font-weight: 400; }
    table.vlib-table[data-m-reflow] > tbody > tr.vb-grp > td.vlib-c-desc::before { display: none; }
    table.vlib-table[data-m-reflow] .vlib-chip { display: inline-block; white-space: nowrap !important; }
    table.vlib-table[data-m-reflow] .vlib-alt-phone { display: block; font-weight: 400; }
    /* mobile.css lets every span in a card wrap (!important): a code keeps to its line, as does a
       BASIC's swatch and name. */
    table.vlib-table[data-m-reflow] td .vlib-code:not(.is-long) { white-space: nowrap !important; }
    table.vlib-table[data-m-reflow] td.vlib-c-code { white-space: normal; }
    /* 44px to tap: Show more, Try again and Show in the violations above. */
    .vlib .vlib-more, .vlib .vlib-jump, .vlib [data-vlib-retry] { display: inline-flex; align-items: center; min-height: 44px; }
    .vlib-reports { flex-direction: column; gap: 0.15rem; }
}
