/* =====================================================================
   signal-2.html — Signals, variation 1a:
   card inventory (scan) + slide-over detail (drill in).

   Loaded AFTER signals.css, so it inherits the whole shared vocabulary —
   sidebar, .cta, .sg-badge, .sg-filt, .sg-weight, the events table, the
   banner, the modals — and only redefines the workbench. Everything new is
   namespaced .v1-* so the master/detail page (index.html) is untouched.

   The layout swap, in one line: on index.html the LIST is a permanent column
   and the detail is always on screen; here the GRID is the resting state and
   the detail is a temporary right-docked overlay you dismiss back out of.
   ===================================================================== */

/* This page scrolls the grid rather than pinning two internal scrollers, so
   the wrap must be allowed to grow past the viewport. */
.v1-app .sg-wrap { min-height: 100%; padding-bottom: var(--sp-6); }

.v1-wb { display: flex; flex-direction: column; gap: 14px; }

/* Filter chips sit above the grid, full-bleed (on index.html they live inside
   the list card, where they stretch to fill the column). Out here they must
   hug their labels instead — hence the flex-start + no-grow reset. */
/* The four chips sit in one pill-shaped container — a single segmented control
   rather than four loose buttons, which is what the pairing with the Sort pill
   on the other end of the row calls for. The chips hug their labels (in the
   baseline they stretch to fill a fixed 280px column; out here that would make
   four enormous buttons). */
.v1-filters {
  display: inline-flex; flex-wrap: wrap; justify-content: flex-start; align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-card);
}
.v1-filters .sg-filt {
  flex: 0 0 auto;
  height: 24px;
  padding: 0 11px;
  border-radius: var(--r-pill);
}

/* At rest every chip is neutral, exactly like `All` — a resting bar of four
   coloured labels is a traffic light nobody asked for, and colour should mean
   "you are here", not "this exists". The type's colour arrives only on hover
   (a preview of what you'd be selecting) and on the active chip, where it ties
   the filter to the badges it is now showing. */
.v1-filters .sg-filt.t-news:hover,
.v1-filters .sg-filt.t-news.on       { color: var(--dot-news); }
.v1-filters .sg-filt.t-jobs:hover,
.v1-filters .sg-filt.t-jobs.on       { color: var(--dot-job); }
.v1-filters .sg-filt.t-job_change:hover,
.v1-filters .sg-filt.t-job_change.on { color: var(--dot-career); }

.v1-filters .sg-filt.t-news.on       { background: color-mix(in srgb, var(--dot-news) 15%, transparent); }
.v1-filters .sg-filt.t-jobs.on       { background: color-mix(in srgb, var(--dot-job) 15%, transparent); }
.v1-filters .sg-filt.t-job_change.on { background: color-mix(in srgb, var(--dot-career) 15%, transparent); }

/* The count follows its chip's colour once that chip is lit. */
.v1-filters .sg-filt.t-news:hover .n,
.v1-filters .sg-filt.t-jobs:hover .n,
.v1-filters .sg-filt.t-job_change:hover .n { color: inherit; opacity: .65; }
.v1-filters .sg-filt.t-news.on .n,
.v1-filters .sg-filt.t-jobs.on .n,
.v1-filters .sg-filt.t-job_change.on .n { color: inherit; opacity: 1; }

.v1-filters .sg-filt.t-news:hover,
.v1-filters .sg-filt.t-jobs:hover,
.v1-filters .sg-filt.t-job_change:hover { background: color-mix(in srgb, currentColor 9%, transparent); }

/* ── Toolbar: filters left, sort right ────────────────────────────── */
.v1-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px;
}

.v1-sort { position: relative; flex-shrink: 0; }
.v1-sort .trg {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px;               /* matches the filter pill on the other end */
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-card);
  font-size: 12px;
  color: var(--fg-2);
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}
.v1-sort .trg:hover { border-color: var(--line-strong); }
.v1-sort .trg.on { border-color: var(--accent-line); background: var(--accent-soft); }
.v1-sort .trg:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: var(--r-pill); }
.v1-sort .trg svg { color: var(--fg-3); flex-shrink: 0; }
.v1-sort .trg .lb { color: var(--fg-3); }
/* The current sort is the point of the control, so it carries the emphasis. */
.v1-sort .trg .val { font-weight: 600; color: var(--fg-1); }
/* `.cv` is also a class in career-options.css, where it means "career verb" and
   carries a top margin. That margin leaks in here and drops the chevron below
   the row's centre line, so it has to be cancelled explicitly. */
.v1-sort .trg .cv {
  margin: 0;
  flex-shrink: 0;
  transition: transform .14s ease;
}
.v1-sort .trg .cv.up { transform: rotate(180deg); }

.v1-sort .pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
  min-width: 260px;
  padding: 4px;
  background: var(--bg-popover, var(--bg-card));
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-menu, 0 14px 34px -14px rgba(0, 0, 0, .38));
}
.v1-sort .pop button {
  display: flex; align-items: flex-start; gap: 8px;
  width: 100%;
  padding: 8px 9px;
  border: 0; border-radius: 8px;
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.v1-sort .pop button:hover { background: var(--bg-well); }
.v1-sort .pop button .tk {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; min-height: 17px; flex-shrink: 0;
  color: var(--accent-text);
}
.v1-sort .pop button .bd { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.v1-sort .pop button .t { font-size: 13px; color: var(--fg-1); }
/* The hint carries the actual rule — "Most active" alone doesn't say active by
   what, over what window. */
.v1-sort .pop button .h { font-size: 11px; line-height: 1.4; color: var(--fg-3); }
.v1-sort .pop button.on .t { font-weight: 600; color: var(--accent-text); }

/* ── Scan tier: the card inventory ────────────────────────────────────
   Three per row, fixed. auto-fill would re-flow to 4-up on a wide monitor and
   pack the row tighter than the eye can scan; three columns hold a stable
   rhythm and give each gist a measure it can breathe in. Cards widen with the
   viewport rather than multiplying — and stepping down below 1080 keeps the
   gist from collapsing into slivers. */
.v1-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  align-items: stretch;
}
@media (max-width: 1080px) { .v1-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px)  { .v1-grid { grid-template-columns: minmax(0, 1fr); } }

.v1-card {
  display: flex; flex-direction: column; gap: 8px;
  min-height: 148px;
  padding: 14px;
  text-align: left;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
  cursor: pointer;
  transition: border-color .14s ease, box-shadow .14s ease, transform .14s ease, background .14s ease;
}
.v1-card:hover {
  border-color: var(--line-strong);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px -12px rgba(0, 0, 0, .28);
}
.v1-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Selected = the card whose detail is open behind/under the slide-over. Keeps
   the anchor obvious when the panel is dismissed. */
.v1-card.on {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}
/* Never-fired signals recede — the rule exists, but there's nothing to read. */
.v1-card.idle { background: var(--bg-well); }
.v1-card.idle:not(.on) .nm { color: var(--fg-2); }

/* The badge sits BESIDE the name, not flung to the card's right edge. It is a
   property of the signal ("this one is a jobs rule"), so it reads as part of
   the title; parked at the far edge it looked like a separate column and the
   eye had to travel to bind it back to the name it describes.
   The name only grows to fit its text — it truncates rather than pushing the
   badge away. */
.v1-card-top { display: flex; align-items: center; justify-content: flex-start; gap: 7px; min-width: 0; }
.v1-card-top .nm {
  flex: 0 1 auto; min-width: 0;
  font-size: 14px; font-weight: 600; line-height: 1.35;
  color: var(--fg-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v1-card-top .sg-badge { flex-shrink: 0; }

/* ── Overflow menu, top-right ─────────────────────────────────────────
   The card is clipped (`overflow: hidden` is not set) so the popover can hang
   past the card's edge; it is positioned against the card corner rather than
   the page, which keeps it glued to its owner while the grid scrolls. */
.v1-card-menu { position: relative; margin-left: auto; flex-shrink: 0; }
.v1-card-menu .trg {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  margin: -2px -4px -2px 0;   /* optical: pull the glyph to the card's corner */
  border: 1px solid transparent;
  border-radius: 50%;         /* circular hover target, matching the dot stack */
  background: transparent;
  color: var(--fg-2);
  cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
/* Hover/open: the brand accent on a soft wash of itself, no border — the circle
   is drawn by the fill, so an outline would just double it. */
.v1-card-menu .trg:hover,
.v1-card-menu .trg.on {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: transparent;
  color: var(--accent);
}
.v1-card-menu .trg:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 50%; }

.v1-card-menu .pop {
  position: absolute; top: calc(100% + 5px); right: 0; z-index: 20;
  min-width: 156px;
  padding: 4px;
  background: var(--bg-popover, var(--bg-card));
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-menu, 0 12px 28px -12px rgba(0, 0, 0, .35));
}
.v1-card-menu .pop button {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 7px 9px;
  border: 0; border-radius: 7px;
  background: transparent;
  font-size: 13px; color: var(--fg-1);
  text-align: left;
  cursor: pointer;
}
.v1-card-menu .pop button:hover { background: var(--bg-well); }
.v1-card-menu .pop button svg { color: var(--fg-2); flex-shrink: 0; }

/* .v1-card-slug is gone from the card — the slug lives in the drawer now. */

.v1-card-gist {
  margin: 0; flex: 1;
  font-size: 13px; line-height: 1.5;
  color: var(--fg-2);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The rule runs edge to edge: negative margins cancel the card's 14px padding,
   and the padding is re-applied inside so the content still lines up with the
   name and gist above it. A rule that stops short of the edges reads as an
   underline on the text rather than as the card's own footer. */
.v1-card-foot {
  display: flex; align-items: center; gap: 8px;
  margin: 0 -14px;
  padding: 9px 14px 0;
  border-top: 1px solid var(--line);
  font-size: 12px; color: var(--fg-2);
}
.v1-card-foot .ct { font-variant-numeric: tabular-nums; }

/* Dot first, count next, action pushed to the far edge. */
.v1-card-foot .v1-rec { gap: 0; }
.v1-card-foot .v1-card-def { margin-left: auto; }

/* Visually hidden, still read aloud — the dot's meaning cannot live in colour
   and a mouse-only tooltip alone. */
.v1-rec .sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* The card's second door. Quiet by default — the card itself is the primary
   target — and it only gains a surface on hover/focus, so 27 cards don't read
   as 27 buttons. */
/* Same type size and line box as the count and the recency label either side of
   it, so the three read as one horizontal row rather than a button wedged
   between two labels. The box is transparent until hover, so it adds no height
   of its own. */
.v1-card-def {
  display: inline-flex; align-items: center; gap: 5px;
  height: 18px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent;
  font-size: 12px; font-weight: 500; line-height: 18px;
  color: var(--fg-3);
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s ease, background .12s ease, color .12s ease, border-color .12s ease;
}
.v1-card:hover .v1-card-def,
.v1-card:focus-within .v1-card-def,
.v1-card-def:focus-visible { opacity: 1; }
.v1-card-def:hover { background: var(--bg-well); border-color: var(--line); color: var(--fg-1); }

/* The arrow trails the label and leans into the direction it promises. */
.v1-card-def svg { transition: transform .14s ease; }
.v1-card:hover .v1-card-def svg { transform: translateX(2px); }
@media (prefers-reduced-motion: reduce) { .v1-card-def svg { transition: none; } }
.v1-card-def:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Touch and keyboard-only users never hover, so don't hide it from them. */
@media (hover: none) { .v1-card-def { opacity: 1; } }
.v1-card-foot .ct strong { color: var(--fg-1); font-weight: 600; }
.v1-card-foot .ct .zero { color: var(--fg-3); }

/* ── Recency dot ──────────────────────────────────────────────────────
   Four coarse states, not a timestamp: hot (fired in the last 48h) · warm
   (this week) · cool (this month) · cold (older) · never. The dot carries the
   state; the label is the confirmation, so colour is never the only cue. */
.v1-rec {
  display: inline-flex; align-items: center; gap: 6px;
  flex-shrink: 0;
  font-size: 12px; color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}
.v1-rec .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--fg-3); }
.v1-rec.hot   .dot { background: var(--accent-emerald-500); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-emerald-500) 18%, transparent); }
.v1-rec.warm  .dot { background: var(--accent-emerald-400); }
.v1-rec.cool  .dot { background: var(--accent-amber-500); }
.v1-rec.cold  .dot { background: var(--fg-3); }
.v1-rec.never .dot { background: transparent; border: 1px solid var(--line-strong); }
.v1-rec.never { color: var(--fg-3); }

.v1-empty {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 56px 0;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.v1-empty p { margin: 0; font-size: 14px; color: var(--fg-3); }

/* ── Detail tier: the slide-over ──────────────────────────────────────
   Right-docked, over a scrim. It covers the far edge of the grid, never the
   whole page — the inventory stays visible, so "where am I" survives the
   drill-in. Sits under .sg-overlay (z 60) so the delete/event modals still
   land on top of it. */
.v1-scrim {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(15, 18, 26, .38);
  opacity: 0; pointer-events: none;
  transition: opacity .2s ease;
}
.v1-scrim.on { opacity: 1; pointer-events: auto; }

.v1-over {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 51;
  width: min(560px, 100%);
  display: flex; flex-direction: column;
  background: var(--bg-card);
  border-left: 1px solid var(--line);
  box-shadow: -24px 0 60px -30px rgba(0, 0, 0, .45);
  transform: translateX(100%);
  transition: transform .24s cubic-bezier(.32, .72, 0, 1);
  will-change: transform;
}
/* The events drawer is a table (account · headline · confidence · date) and
   needs the width; the definition drawer is prose and gets worse past a reading
   measure, so they are sized differently rather than sharing one compromise.
   Capped at 78vw so the grid behind it is never fully covered — the whole point
   of 1a is that you can still see where you came from. */
.v1-over.wide { width: min(820px, 78vw); }

.v1-over.on { transform: translateX(0); }
.v1-over:focus { outline: none; }
@media (prefers-reduced-motion: reduce) {
  .v1-over, .v1-scrim { transition: none; }
}

/* Header is fixed; only the body below the tabs scrolls. */
.v1-over-hd {
  flex-shrink: 0;
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px 18px 0;
  border-bottom: 1px solid var(--line);
  background: var(--bg-card);
}
/* Badge beside the title, exactly as on the card — it is a property of the
   signal, not a separate column, and the drawer must not re-arrange what the
   card just taught the eye. The title grows only to fit its text (truncating
   when it can't), and the close button takes the far edge on its own. */
.v1-over-hd .row1 { display: flex; align-items: center; gap: 8px; min-width: 0; }
.v1-over-hd .row1 h2 {
  margin: 0; flex: 0 1 auto; min-width: 0;
  font-family: "Polymath", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 18px; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em;
  color: var(--fg-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v1-over-hd .row1 .sg-badge { flex-shrink: 0; }
.v1-over-hd .row1 .v1-close { margin-left: auto; }
/* Borderless, like the card's ⋯ trigger: a naked glyph that only earns a
   surface when you reach for it. A boxed X in the corner reads as a control you
   must use, which is the opposite of what a dismiss should suggest. */
.v1-close {
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--fg-2);
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.v1-close:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.v1-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The panel opens on the same sentence the card showed, so the drill-in reads
   as a continuation. The long `detects` paragraph waits on the Definition tab. */
.v1-over-gist { margin: -4px 0 0; font-size: 13px; line-height: 1.5; color: var(--fg-2); }
.v1-over-slug {
  display: block; margin: -6px 0 0;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 11px; color: var(--fg-3);
}

/* The three numbers the card promised, restated in one strip so the panel
   opens with continuity rather than a fresh context. */
.v1-stats {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  font-size: 12px; color: var(--fg-2);
}
.v1-stats .st { font-variant-numeric: tabular-nums; }
.v1-stats .st strong { color: var(--fg-1); font-weight: 600; }
.v1-stats .sep { width: 1px; height: 12px; background: var(--line); }

.v1-over-hd .row2 {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px;
}
.v1-over-hd .row2 .acts { display: flex; align-items: center; gap: 6px; }

/* The weight control becomes a pill, like every other control on this page —
   the filter bar, the Sort trigger, the badges. An 8px radius is the odd shape
   out once everything around it is fully rounded. Scoped to the drawer, so
   index.html keeps the baseline shape. */
.v1-over .sg-weight {
  height: 32px;
  padding: 0 6px 0 12px;
  border-radius: var(--r-pill);
}

/* The door between the two drawers. Deliberately a quiet ghost button and not a
   tab strip: tabs imply two views of one thing, and these are two things. */
.v1-switch { display: flex; margin-bottom: 12px; }
.v1-switch .cta { gap: 6px; }
.v1-switch .n {
  margin-left: 2px; padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--bg-well);
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Legacy tab strip — kept only so nothing dangling references it. */
.v1-tabs { display: flex; align-items: center; gap: 2px; margin-top: 2px; }
.v1-tabs button {
  position: relative;
  padding: 9px 12px 11px;
  border: 0; background: transparent;
  font-size: 13px; font-weight: 500;
  color: var(--fg-2);
  cursor: pointer;
  transition: color .12s ease;
}
.v1-tabs button:hover { color: var(--fg-1); }
.v1-tabs button.on { color: var(--fg-1); font-weight: 600; }
.v1-tabs button.on::after {
  content: ""; position: absolute; left: 8px; right: 8px; bottom: -1px;
  height: 2px; border-radius: 2px;
  background: var(--accent);
}
.v1-tabs .n {
  margin-left: 5px; padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--bg-well);
  font-size: 11px; font-weight: 600;
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}
.v1-tabs button.on .n { background: var(--accent-soft); color: var(--accent-text); }

.v1-over-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 18px 24px; }

/* The long `detects` paragraph reads as prose, not as a callout: it is the
   drawer's body text, and boxing it competed with the two tinted boundary cards
   below — which need the enclosure, because they carry a yes/no distinction the
   paragraph doesn't. */
.v1-hero { padding: 0; background: none; border: 0; border-radius: 0; }
.v1-hero p { margin: 0 0 4px; font-size: 13.5px; line-height: 1.65; color: var(--fg-1); }

/* ── Should / should-not match ────────────────────────────────────────
   Each list is its own tinted card — green for what the rule catches, red for
   what it must not. The colour is doing real work here: excludes is the longest
   field on a signal (7–15 items) and, run together with includes as one grey
   bullet list, the reader has to hold "am I in the yes list or the no list?" in
   their head all the way down. Two enclosed, differently-tinted blocks answer
   that from peripheral vision, which is what makes 15 bullets survivable. */
.v1-bounds { display: flex; flex-direction: column; gap: 14px; margin-top: 18px; }

.v1-bounds section {
  padding: 14px 16px;
  border: 1px solid;
  border-radius: 12px;
}
.v1-bounds section:has(.hd.inc) {
  background: color-mix(in srgb, var(--accent-emerald-500) 5%, transparent);
  border-color: color-mix(in srgb, var(--accent-emerald-500) 22%, transparent);
}
.v1-bounds section:has(.hd.exc) {
  background: color-mix(in srgb, var(--accent-red-400) 5%, transparent);
  border-color: color-mix(in srgb, var(--accent-red-400) 22%, transparent);
}

/* The glyph is inline with the label, not a badge — the tinted card already
   carries the colour, so a second coloured chip would be shouting twice. */
.v1-bounds .hd {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.v1-bounds .hd .ic { display: inline-flex; align-items: center; }
.v1-bounds .hd .ic svg { width: 12px; height: 12px; }
.v1-bounds .hd.inc { color: var(--accent-emerald-500); }
.v1-bounds .hd.exc { color: var(--accent-red-400); }
.v1-bounds .hd .n {
  font-weight: 500; letter-spacing: 0; text-transform: none;
  color: color-mix(in srgb, currentColor 55%, transparent);
  font-variant-numeric: tabular-nums;
}

.v1-bounds ul { list-style: none; margin: 11px 0 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.v1-bounds li {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 13px; line-height: 1.5;
  color: var(--fg-1);
}
/* A middot rather than a filled dot: the bullet is a tick mark, not a second
   status colour competing with the card's tint. */
.v1-bounds li .dot {
  flex-shrink: 0;
  width: 4px;
  color: var(--fg-3);
  background: none;
  border-radius: 0;
  line-height: 1.5;
}
.v1-bounds li .dot::before { content: "·"; }

.v1-matched-hd {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 10px;
  font-size: 13px; font-weight: 600; color: var(--fg-1);
}
.v1-matched-hd svg { width: 14px; height: 14px; color: var(--fg-2); }
.v1-matched-hd .sum { margin-left: auto; font-size: 12px; font-weight: 400; color: var(--fg-2); }

/* The shared table truncates the headline to one line, which clips mid-word in a
   narrow panel. Let it wrap — two lines in the widened drawer is enough for all
   but the 300+ character monsters, and those get a third. */
.v1-over .sg-ev td { vertical-align: top; }
.v1-over .sg-ev-title {
  white-space: normal;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
  text-align: left;
}

.v1-ev-empty {
  padding: 40px 16px; text-align: center;
  background: var(--bg-well);
  border: 1px dashed var(--line-strong);
  border-radius: 12px;
}
.v1-ev-empty .t { margin: 0; font-size: 13px; color: var(--fg-2); }
.v1-ev-empty .s { margin: 6px 0 0; font-size: 12px; color: var(--fg-3); }

/* Narrow viewports: the slide-over becomes a full-width sheet. */
@media (max-width: 640px) {
  .v1-over { width: 100%; border-left: 0; }
  .v1-over-hd .row2 { flex-direction: column; align-items: stretch; }
  .v1-over-hd .row2 .acts { justify-content: flex-end; }
}
