/* css/08-incident-card.css — .inc-card — shared by Drive, Verify, sheet.
   Split from the index.html <style> block (REFACTOR-PLAN Phase 2). Load order = cascade order; do not reorder. */
/* ---------- THE INCIDENT CARD (.inc-card) ---------------------------------
   wave13. ONE component, ONE shape, everywhere:

     [evidence thumb 96 + AI box] | row1 glyph + type name (17px/700, ellipsis)
                                  | row2 severity chip
                                  | row3 street · camera · time
                                  | row4 #id · nn% confidence (mono)
                                  | row5 status line (+ SLA chip, wraps)
     ------------------------------------------------------------------
     full-width foot: [✓ Valid][✕ Invalid][⏱ Decide later]  — or, once the
     incident is decided, ONE 40 px status bar with Undo.

   The expanded/compact distinction is GONE: the same markup and the same CSS
   classes render the Drive panel, the Verify list and the Incident Details
   sheet's action row, because two shapes reading differently is what made the
   driver's column feel like four unrelated components.

   Severity is the chip plus a 3 px left rule — never a full coloured outline.
   The numbered pin badge is gone from the card; the MAP pins keep their
   numbers and pin↔card linking is by data-id.

   Every single-line field carries min-width:0 + ellipsis, which is what fixed
   the old rows clipping to "C", "#4" and "Awaiting your …". */
.card-slot{flex:0 0 auto;min-height:0}
.card-slot:empty{display:none}
.card{flex:0 0 auto;position:relative;border-radius:var(--r-sm);
  background:rgba(10,15,17,.62);border:1px solid var(--hair);
  overflow:hidden;transition:transform .18s var(--ease),opacity .18s;transform-origin:top}
/* wave14 §4: the entrance is NO LONGER on every .card. The list is rebuilt on
   every arrival, every decision and every filter change, so a blanket
   `cardin` meant sixty seeded incidents flashing in at boot and the whole
   column twitching on each repaint. Only the ONE live arrival animates, via
   `.card.arrive` below; seeds and re-renders are silent. */
/* Wave 6, axe: the entrance used to ramp the card's OPACITY from 0, which for
   240 ms put the whole card — Valid button included — behind a partial alpha.
   The rise alone reads as the same arrival, and no frame is low-contrast. */
/* translate ONLY: a scale here shrank the row's thumb button below its hit
   target for the 240 ms of the entrance (and what EX12 measures). */
@keyframes cardin{from{transform:translateY(12px)}}
/* wave14 §3 — the third beat. A LIVE arrival's card enters 300 ms after the
   tile's dot pop and 150 ms after the pin drop, so the three surfaces read as
   one event unfolding rather than three independent repaints. The delay is on
   the ANIMATION (fill-mode backwards), not on the render: state, ARIA and the
   decision buttons are all in the DOM from t=0. */
/* revamp 5 — THE ARRIVAL IS THE ONLY THING THAT HAPPENS ON THIS SIDE.
   With the panel gone until a detection lands (.dpanel.ghost, css/06), the
   card's entrance is not a list insertion any more: it is the moment the
   cockpit's left half comes alive. ~480 ms, three staggered beats, all on the
   ONE live arrival (renderList sets .arrive; seeds and re-renders are silent):
     t=300  the card slides in from the left (-28 px) and settles from .96
     t=300  a 2 px accent line sweeps down the evidence plate (600 ms)
     t=550  the severity chip pops from 1.15
   The 300 ms head start is the existing stagger against the pin drop, so pin,
   tile and card still read as one event unfolding. */
.card.arrive{animation:cardarrive .48s cubic-bezier(.2,.8,.2,1) .3s backwards;
  transform-origin:left center}
@keyframes cardarrive{from{transform:translateX(-28px) scale(.96);opacity:0}}
/* the scan sweep: an accent hairline with a soft gradient behind it, travelling
   the height of the plate once. ::after on the thumb button so it sits over the
   frame and under nothing. Hero plates only -- a 44 px row thumb is an
   identifier, not evidence, and a sweep on it would just be noise. */
/* NB: .card .thumb::after is also the (currently display:none) AI-box overlay
   below, so every one of its properties is reset here -- display and border
   included, or the sweep inherits a hidden box with a 1.5 px green outline. */
#cardSlot .card.arrive button.thumb::after{content:"";display:block;position:absolute;
  inset:auto;left:0;right:0;top:0;bottom:auto;height:36%;border:0;border-radius:0;
  pointer-events:none;z-index:3;
  background:linear-gradient(180deg,rgba(34,200,130,0) 0%,rgba(34,200,130,.16) 72%,rgba(34,200,130,.34) 97%,var(--acc) 100%);
  /* `both`, not `backwards`: .arrive is never taken off the card, so a
     `backwards` fill would leave the band parked at the top of the plate for
     the rest of the session. The `to` frame is opacity 0, so `both` hides it
     before the delay and again after the sweep. */
  animation:evscan .6s cubic-bezier(.3,.7,.3,1) .3s both}
@keyframes evscan{from{transform:translateY(-100%);opacity:0}
  18%{opacity:1} 82%{opacity:1} to{transform:translateY(278%);opacity:0}}
.card.arrive .sev{animation:sevpop .2s cubic-bezier(.2,.8,.2,1) .55s backwards}
@keyframes sevpop{from{transform:scale(1.15)}}
@media (prefers-reduced-motion: reduce){
  /* opacity only -- no travel, no scale, no sweep */
  .card.arrive{animation:cardarrivereduced .2s linear .1s backwards}
  @keyframes cardarrivereduced{from{opacity:0}}
  #cardSlot .card.arrive button.thumb::after{display:none}
  .card.arrive .sev{animation:none}
}
/* revamp 5 — THE HERO SHOWS ONLY WHAT THE DECISION NEEDS.
   Plate, class + severity, KPI, Valid / Invalid. The meta line (camera + time)
   is provenance, which belongs to the compact row and the incident sheet, not
   to the two seconds in which an inspector decides; and "Awaiting decision"
   above two buttons labelled Valid and Invalid was the screen narrating
   itself. Both come back the moment the card has a LIFECYCLE to report
   (.lclive, set in buildCard): then the line IS the information. */
#view-drive #cardSlot .inc-card .meta{display:none}
#view-drive #cardSlot .inc-card:not(.lclive) .status{display:none}
/* wave15 — THE HYBRID FEED. There is no "n new" chip and no collapsed
   "n new detections" row any more: every report is a standard card that lands
   on top while the cards under it slide down (FLIP, see renderList). A card
   leaving the current filter (it was just decided) fades for 200 ms first. */
.card.feed-out,.pomsg.feed-out{opacity:0;pointer-events:none;
  transition:opacity .2s var(--ease)!important}
/* the "Show older" ghost row at the foot of the capped feed */
.feed-more{flex:0 0 auto;-webkit-appearance:none;appearance:none;width:100%;
  min-height:44px;border-radius:12px;background:rgba(255,255,255,.03);
  border:1px dashed var(--hair);color:var(--tx3);font:inherit;font-size:var(--fz-body);
  font-weight:600;display:flex;align-items:center;justify-content:center;gap:8px}
.card::before{display:none}
.card .bracket{display:none}          /* the reticle brackets were the hero's alone */

/* --- the two-column grid: 96 px evidence thumb + the five-row text stack ---
   wave13: there is no longer a pin-badge column and no longer an action
   column. Every incident card is this grid plus a full-width foot. */
.card .top{display:grid;grid-template-columns:96px minmax(0,1fr);
  gap:12px;padding:12px 14px 0;align-items:start}
button.thumb{-webkit-appearance:none;appearance:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer}
button.thumb:active{transform:scale(.97)}
.card .thumb{width:96px;height:96px;border-radius:10px;
  background:color-mix(in oklab, var(--sev,var(--s3)) 18%, #0C1214);
  display:grid;place-items:center;position:relative;overflow:hidden;flex:0 0 auto;
  border:1px solid var(--hair)}
.card .thumb svg{width:32px;height:32px;stroke:var(--tx)}
/* revamp task 2: the evidence frame is EVIDENCE, so wherever there is room to
   show it whole it is CONTAINED at its own ratio (the wide plates below and in
   13-coverage.css) over a blurred copy of itself. A 96 px or 44 px SQUARE
   thumb is not that place — the frames run 0.98:1 to 2.16:1, and containing a
   2:1 frame in a square is a 40 px strip in a black box. Square thumbs stay a
   crop: there they are an identifier, not the evidence. */
.card .thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:#070A0B}
/* the backdrop copy: off everywhere by default, switched on only by the rules
   that make the thumb a wide plate (below, and 13-coverage.css for Drive) */
.card .thumb img.evbg{display:none;background:none;object-fit:cover;
  filter:blur(20px) saturate(.5) brightness(.55);transform:scale(1.18)}
/* the AI bounding box the detection was made on, as a static overlay */
.card .thumb::after{display:none;content:"";position:absolute;inset:22% 26%;border:1.5px solid rgba(34,200,130,.62);border-radius:3px;pointer-events:none}
.card.sev-crit .thumb::after{border-color:rgba(255,90,95,.72)}
.card.sev-med .thumb::after{border-color:rgba(255,159,67,.72)}
.card.review .thumb::after{display:none}

/* the newest undecided incident leads with a LARGE image: split-second
   valid/invalid reads while driving (meeting: image should be big). revamp
   task 2: it is now a TRUE-RATIO 16:9 plate, not a 158 px crop — the frame is
   shown whole, on its own black field, capped so it can never push the two
   decisions below the fold. (On Drive the first feed item lives in #cardSlot
   and 13-coverage.css owns it; this rule covers every other host.) */
#list .inc-card:first-child:is(.sev-crit,.sev-med,.sev-minor):not(.valid):not(.invalid):not(.verified):not(.lc):not(.esp) .top{grid-template-columns:1fr;gap:8px}
#list .inc-card:first-child:not(.valid):not(.invalid):not(.verified):not(.lc):not(.esp) .thumb{width:100%;height:auto;aspect-ratio:16/9;max-height:200px;border-radius:12px;background:#070A0B}
#list .inc-card:first-child:not(.valid):not(.invalid):not(.verified):not(.lc):not(.esp) .thumb img{object-fit:contain}
#list .inc-card:first-child:not(.valid):not(.invalid):not(.verified):not(.lc):not(.esp) .thumb img.evbg{display:block;object-fit:cover}
/* --- the text stack: five rows, none of which may ever clip --- */
.card .body{min-width:0;display:flex;flex-direction:column;gap:4px}
/* row 1 — the type glyph and the type name, ONE line with an ellipsis. The
   severity chip moved to its own row (row 2), so the name gets the whole
   column width and no longer has to wrap mid-word to make space for a pill. */
.card .clsrow{display:flex;align-items:flex-start;gap:8px;min-width:0}
.card .clsic{margin-top:1px}
.card .clsic{width:20px;height:20px;flex:0 0 auto;stroke:var(--sev,var(--tx2));stroke-width:1.9}
.card .cls{font-size:var(--fz-btn);font-weight:700;line-height:1.18;letter-spacing:-.015em;
  flex:1 1 auto;min-width:0;
  white-space:normal;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
/* row 2 — severity, and the KPI chip beside it (revamp task 2). Two different
   registers on purpose: severity is a COLOURED judgement, the KPI is a neutral
   hairline reference to the municipal metric the street is scored on. */
.card .sevrow{display:flex;align-items:center;gap:6px;min-width:0;flex-wrap:wrap;row-gap:4px}
/* revamp 10: the KPI is a LABELLED FACT, not a pill. Two spans -- a small-caps
   "KPI" and the metric name -- so the same element can be a compact bordered
   chip in the 44 px list rows and the Verify column, and a full-width row of
   real type on the hero card (13-coverage) and in the details sheet (15). The
   icon is gone: a label that says KPI does not also need a glyph that says
   KPI. */
.card .kpichip{display:inline-flex;align-items:baseline;gap:7px;min-width:0;flex:0 1 auto;
  padding:3px 10px;border-radius:999px;
  border:1px solid var(--hair2);background:rgba(255,255,255,.035);
  font-size:var(--fz-meta);font-weight:600;letter-spacing:.005em;line-height:1.3;color:var(--tx2)}
.card .kpichip .kl{flex:0 0 auto;font-size:var(--fz-cap);font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;color:var(--tx3)}
.card .kpichip .kv{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card .meta{font-size:var(--fz-body);color:var(--tx2);min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.25}
.card .meta b{color:var(--tx);font-weight:600}
/* wave18: the Verify list column is only ~174px wide, so a one-line meta cut
   the STREET itself ("Sheikha Fatima Bint Mu…") — a decision-critical word.
   Only in that column does the meta get two lines; the Drive feed keeps its
   single line (there the street fits and the ellipsis only takes the trailing
   timestamp), so cards-per-glance on Drive is unchanged. */
#vlist .card .meta{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;line-height:1.35}
.card .compass{font-family:var(--mono);font-size:var(--fz-meta);font-weight:700;color:var(--tx3);letter-spacing:.06em}
/* row 5 — the status line. wave13: it WRAPS, so the amber "Still open · one
   reminder only" chip drops to its own line in a narrow column instead of
   squeezing the status text into an ellipsis (task-5 sweep). */
.card .status{font-size:var(--fz-body);color:var(--tx2);display:flex;gap:7px;align-items:center;
  min-width:0;line-height:1.25;flex-wrap:wrap;row-gap:5px}
.card .status>span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card .status i{width:7px;height:7px;border-radius:50%;background:var(--info);flex:0 0 auto}
.card.valid .status i{background:var(--acc)}.card.invalid .status i{background:var(--crit)}.card.draft .status i{background:var(--minor)}
.card.verified .status i{background:var(--acc)}
.card .reason{display:inline-flex;align-items:center;gap:6px;font-size:var(--fz-meta);font-weight:700;color:var(--minor);background:rgba(255,209,102,.12);border:1px solid rgba(255,209,102,.32);padding:3px 8px;border-radius:8px;flex:0 0 auto}
.card .qd{width:14px;height:14px;stroke:var(--minor);flex:0 0 auto}
.card .undo{height:44px;padding:0 12px;border-radius:10px;background:rgba(255,255,255,.06);border:1px solid var(--hair2);color:var(--tx);font-size:var(--fz-body);font-weight:700;display:flex;align-items:center;gap:6px;flex:0 0 auto;margin-inline-start:auto}
.card .undo svg{width:16px;height:16px}
.shead .h .confline{font-family:var(--mono);font-size:var(--fz-meta);color:var(--tx3);font-weight:600;
  letter-spacing:.02em;margin-top:3px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* --- severity chip --- */
/* wave18: severity is THE decision-critical word on a card, so it sits on the
   body step, not the caption one; and the rule carried line-height twice —
   the later `1` was winning, which put the pill under the 1.3-1.5 floor. */
.sev{display:inline-flex;align-items:center;gap:6px;font-size:var(--fz-body);letter-spacing:.01em;font-weight:700;
  padding:3px 9px;border-radius:999px;line-height:1.3;color:var(--sevtx,var(--tx2));flex:0 0 auto;
  border:1px solid var(--sevtx,var(--tx3));background:var(--sevbg,transparent)}
.sev::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.card.sev-crit{--sevtx:var(--crit);--sevbg:rgba(255,90,95,.10)}
.card.sev-med{--sevtx:var(--med);--sevbg:rgba(255,159,67,.10)}
.card.sev-minor{--sevtx:var(--minor);--sevbg:rgba(255,209,102,.10)}
.conf{font-size:var(--fz-meta);color:var(--tx3)}.conf b{font-size:var(--fz-md);color:var(--tx);font-weight:700;font-family:var(--mono)}

/* --- the card foot: the decision row, full width, on EVERY card ---------
   wave13. There is no "expanded" and no "compact" variant any more: the three
   labelled decisions run the card's full width wherever the incident appears
   (the Drive panel, the Verify list, the Incident Details sheet), because the
   two shapes reading differently is exactly what made the column feel like
   four unrelated components. Never icon-only: a 25 km/h glance needs the word.
   -------------------------------------------------------------------------- */
.card .cardfoot{padding:12px 14px 14px}
.card .acts{display:flex;flex-direction:row;gap:10px}
.btn{height:58px;border-radius:16px;display:flex;align-items:center;justify-content:center;gap:8px;font-size:var(--fz-btn);font-weight:700;letter-spacing:-.01em;transition:transform .16s var(--ease),filter .16s,background .16s}
.btn:active{transform:scale(.975);filter:brightness(1.08)}
.btn svg{width:22px;height:22px;stroke-width:2.4}
.btn.valid{background:var(--acc);color:var(--on-acc)}
.btn.invalid{background:rgba(240,85,77,.12);color:#F0554D;border:1px solid rgba(240,85,77,.42)}
.btn.later{background:rgba(255,255,255,.05);border:1px solid var(--hair2);color:var(--tx2)}
/* equal flex widths, 48 px, labels always */
.card .acts .btn{flex:1 1 0;min-width:0;height:48px;min-height:48px;font-size:var(--fz-md-lg);
  border-radius:13px;gap:6px;padding:0 6px;white-space:nowrap;overflow:hidden}
/* wave18: with the Drive panel at 35% the three buttons are ~120px each and
   "Decide later" — the widest label, and a decision-critical one — was the
   only one being ellipsised. The third button now takes a proportionally
   larger share; Valid/Invalid have the slack to give. */
.card .acts .btn.later{flex:1.28 1 0}
.btn.later,#incLater{display:none!important}
.card .acts .btn svg{width:19px;height:19px;flex:0 0 auto}
.card .acts .btn span{overflow:hidden;text-overflow:ellipsis}
/* a decided card replaces the decision row with ONE 40 px status bar carrying
   the decision, its time and — inside the window — Undo */
.card .statusbar{display:flex;align-items:center;gap:8px;height:40px;padding:0 12px;
  border-radius:11px;font-size:var(--fz-body);font-weight:700;min-width:0;
  background:rgba(255,255,255,.05);border:1px solid var(--hair);color:var(--tx2)}
.card .statusbar>span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card .statusbar svg{width:15px;height:15px;stroke-width:2.4;flex:0 0 auto}
.card .statusbar .ul{-webkit-appearance:none;appearance:none;background:none;border:0;
  font:inherit;color:var(--tx);font-weight:700;text-decoration:underline;
  padding:0 6px;margin-inline-start:auto;flex:0 0 auto;height:38px;cursor:pointer}
.card.valid .statusbar,.card.verified .statusbar{color:var(--acc);border-color:rgba(34,200,130,.34);background:var(--acc-dim)}
.card.invalid .statusbar{color:#F0554D;border-color:rgba(240,85,77,.30);background:rgba(240,85,77,.10)}
.card.draft .statusbar{color:var(--minor);border-color:rgba(255,209,102,.30);background:rgba(255,209,102,.10)}
/* the ONE card: severity is the chip plus a 3 px left rule, never a full
   coloured outline (wave13 task 1) */
.card.inc-card{display:flex;flex-direction:column;
  border:1px solid rgba(255,255,255,.10);border-left:3px solid var(--sev,var(--acc))}
.card.valid,.card.invalid{opacity:.86}
.card.review{border-left-style:dashed}
.card.rowfocus{border-color:var(--acc);border-left-color:var(--acc);background:rgba(34,200,130,.10)}
/* pin->card link (wave14): a transient 1600ms pulse independent of the
   persistent .rowfocus selection state, so a repeated pin tap re-triggers the
   glow even when the card is already the selected row. */
.card.is-focus{outline:2px solid var(--acc);outline-offset:1px;
  box-shadow:0 0 0 6px rgba(34,200,130,.22),0 0 22px rgba(34,200,130,.35);
  transition:box-shadow .5s ease,outline-color .5s ease}
.card.is-focus.is-focus-out{outline-color:rgba(34,200,130,0);box-shadow:0 0 0 0 rgba(34,200,130,0),0 0 0 rgba(34,200,130,0)}
/* narrow column: the labels stay, the type drops one step (task 1) */
@container dpanel (max-width:340px){
  .card .acts .btn{font-size:var(--fz-md)}
}
/* wave15: the stacked-detections pill is gone. Coalescing is now an AUDIO
   policy only (one tone per burst, Alerts.stackFor) — the list itself is a
   plain hybrid feed of standard cards, newest on top. */


/* ---------- pass 23 (client): THE PIN-FOCUSED CARD -------------------------
   "When the user clicks on the map to view the incidents, automatically expand
   it on the left side the info window, only show the selected one and give a
   close button."

   While S.pinFocus holds an id the panel renders that incident alone, on
   #cardSlot, in the full hero shape — so the only thing this needs to add is
   the way OUT. A 44 px control (the in-vehicle touch floor), top-right, over
   the evidence plate's own corner where nothing else lives, on the same glass
   as the rest of the cockpit's icon buttons so it reads as chrome rather than
   as a fourth decision. The card takes the accent edge the selected row takes,
   so the link from the tapped pin to the open card is visible at a glance. */
.card.inc-card.pinfocus{border-color:rgba(34,200,130,.45);border-left-color:var(--acc)}
.card.inc-card.pinfocus .pinclose{position:absolute;top:8px;right:8px;z-index:3;
  width:44px;height:44px;display:grid;place-items:center;
  border-radius:12px;border:1px solid var(--hair);color:var(--tx);
  background:var(--glass-solid);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:var(--sh-lg);transition:background .18s var(--ease),color .18s var(--ease)}
.card.inc-card.pinfocus .pinclose .i{width:20px;height:20px}
.card.inc-card.pinfocus .pinclose:hover{background:rgba(255,255,255,.10)}
.card.inc-card.pinfocus .pinclose:active{transform:scale(.94)}
/* the class name must not run under the control */
.card.inc-card.pinfocus .top .body .clsrow{padding-right:46px}
/* focused means SELECTED, not "needs a look": the transient pin->card pulse
   would otherwise sit on the card for its whole life on screen. */
.card.inc-card.pinfocus.is-focus{outline:none;box-shadow:none}
