/* ==========================================================================
   MASAR — 4-data.css  (cards, KPIs, tables, lists, timelines, charts, pager)
   The surfaces that carry operational data.
   ========================================================================== */

/* ============================================================== CARD */

/* the one card language, everywhere: a subtle line and a whisper of
   shadow — the frame recedes and the content carries the page */
.m-card{
  display:flex;flex-direction:column;min-width:0;
  background:var(--surface);
  border:1px solid var(--line-subtle);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-xs);
}
.m-card--flat{box-shadow:none}
.m-card--raised{box-shadow:var(--sh-md)}
.m-card--fill{height:100%}

/* a card in a fixed-height region is a flex column: without this the head
   is the first thing the layout squeezes, and its subtitle ends up under
   the sticky table header below it */
.m-card__head{
  flex:0 0 auto;
  display:flex;align-items:center;gap:var(--s-3);
  padding:9px var(--card-pad-lg);min-height:42px;
  border-bottom:1px solid var(--line-subtle);
}
.m-card__title{display:flex;flex-direction:column;gap:1px;min-width:0}
.m-card__title h3{font:var(--ty-h2);color:var(--text)}
.m-card__title span{font:var(--ty-caption);color:var(--text-2)}
.m-card__tools{display:flex;align-items:center;gap:var(--s-2);margin-inline-start:auto;flex:0 0 auto}
.m-card__body{padding:var(--card-pad-lg);flex:1 1 auto;min-height:0}
.m-card__body--tight{padding:var(--s-3) 0}
.m-card__body--flush{padding:0}
.m-card__body--scroll{overflow:auto;overscroll-behavior:contain}

/* A HEAD THAT CARRIES ONLY A TOOL IS NOT A HEAD.
   A card whose title is empty — a queue, a register, a log, where the page
   title has already said what the table is — was still drawing a 42px band
   with a search box floated to its far end and nothing else in it. It
   becomes a thin toolbar, and the tool moves to the start of the line where
   the reading begins rather than to the opposite corner. */
.m-card__head:has(.m-card__title h3:empty){padding:5px 10px;min-height:0}
.m-card__head:has(.m-card__title h3:empty) .m-card__title{display:none}
.m-card__head:has(.m-card__title h3:empty) .m-card__tools{
  margin-inline:0 auto;flex:1 1 auto;
}

/* THE ONE SCROLLING REGION.
   A page marks the block that owns the leftover height with .m-fit. It
   takes the space the header and the tabs did not use, and the card inside
   it scrolls in its body only — so the card's own head, its toolbar and
   its footer stay put while the rows move under them. */
.m-fit{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
/* whatever view is showing inside the region takes all of it */
.m-fit > *{flex:1 1 auto;min-height:0}
.m-fit > [hidden]{display:none !important}
.m-fit > div:not(.m-grid):not(.m-card){display:flex;flex-direction:column}
.m-fit .m-card{min-height:0}
.m-fit .m-card > .m-card__body{overflow:auto;overscroll-behavior:contain;min-height:0}
/* A page that does not mark its region gets the rule anyway: the last block
   on the page owns the leftover height and is the one thing that scrolls. */
.m-page > :last-child{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}
.m-page > .m-card:last-child{overflow:hidden}
.m-page > .m-card:last-child > .m-card__body{overflow:auto;overscroll-behavior:contain;min-height:0}
/* and nothing inside it scrolls on its own — one surface moving, not three */
.m-page > :last-child .m-card__body--scroll{overflow:visible}
/* A region holding exactly one card gives that card its full height: a card
   that stops two-thirds down the screen with empty grey under it reads as a
   page that failed to load. A region that lays out its own children — a
   grid, a board — is left alone. */
.m-page > :last-child > .m-card:only-child,
.m-fit > div:not([hidden]) > .m-card:only-child{min-height:100%}

/* A two-column region — a list with a rail beside it — keeps both columns
   in place and scrolls the COLUMN, not the page: the rail stays readable
   while the list moves, which is the whole point of putting it there. The
   single row is pinned to the region's height, or the row grows with its
   content and the columns never learn what height they have. */
.m-page > .m-grid--main-rail:last-child,.m-page > .m-grid--rail-main:last-child,
.m-fit > .m-grid--main-rail:not([hidden]),.m-fit > .m-grid--rail-main:not([hidden]){
  min-height:0;overflow:hidden;grid-template-rows:minmax(0,1fr);
}
.m-page > .m-grid--main-rail:last-child > *,.m-page > .m-grid--rail-main:last-child > *,
.m-fit > .m-grid--main-rail > *,.m-fit > .m-grid--rail-main > *{
  min-height:0;overflow:auto;overscroll-behavior:contain;
}
.m-page > .m-grid--main-rail:last-child > .m-card,.m-page > .m-grid--rail-main:last-child > .m-card,
.m-fit > .m-grid--main-rail > .m-card,.m-fit > .m-grid--rail-main > .m-card{overflow:hidden}
.m-page > .m-grid--main-rail:last-child > .m-card > .m-card__body,
.m-page > .m-grid--rail-main:last-child > .m-card > .m-card__body,
.m-fit > .m-grid--main-rail > .m-card > .m-card__body,
.m-fit > .m-grid--rail-main > .m-card > .m-card__body{
  overflow:auto;overscroll-behavior:contain;min-height:0;
}
/* a table inside that body scrolls WITH it, not against it */
.m-fit .m-table-wrap,.m-page > .m-card:last-child .m-table-wrap{overflow:visible}
.m-fit .m-table thead th,.m-page > .m-card:last-child .m-table thead th{position:sticky;top:0}
.m-card__foot{
  flex:0 0 auto;
  display:flex;align-items:center;gap:var(--s-3);
  padding:10px var(--card-pad-lg);border-top:1px solid var(--line-subtle);
  font:var(--ty-caption);color:var(--text-2);
}

/* A row of cards that must share one height — overflow scrolls inside the
   card rather than ragging the bottom of the row. */
.m-band{display:grid;gap:var(--s-4)}
.m-band > .m-card{height:var(--band,auto);min-height:0}
.m-band > .m-card > .m-card__body{overflow:auto}

/* ============================================================== KPI */

/* Six cards on one line at 1500px gave each label 120px, so half of them
   were drawn as "Collections complet…". A KPI whose name is truncated is not
   a KPI. The track is wider, the label is allowed a second line, and every
   card in the row keeps the same height. */
.m-kpis{
  display:grid;gap:var(--s-3);align-items:stretch;
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr));
}
.m-kpi{
  display:flex;align-items:center;gap:12px;
  padding:11px var(--card-pad);min-width:0;
  background:var(--surface);border:1px solid var(--line-subtle);
  border-radius:14px;box-shadow:0 1px 2px rgba(9,30,54,.05);
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease),
             transform var(--t-fast) var(--ease);
}
a.m-kpi:hover,button.m-kpi:hover{
  border-color:var(--line-strong);box-shadow:0 6px 18px rgba(9,30,54,.10);
  transform:translateY(-1px);text-decoration:none;
}
.m-kpi__ic{
  flex:0 0 auto;width:36px;height:36px;border-radius:11px;
  display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent-press);
}
.m-kpi__ic svg{width:17px;height:17px}
.m-kpi--ok   .m-kpi__ic{background:var(--ok-soft);color:var(--ok)}
.m-kpi--warn .m-kpi__ic{background:var(--warn-soft);color:var(--warn)}
.m-kpi--crit .m-kpi__ic{background:var(--crit-soft);color:var(--critical)}
.m-kpi--live .m-kpi__ic{background:var(--live-soft);color:var(--live)}
.m-kpi--chain .m-kpi__ic{background:var(--chain-soft);color:var(--chain)}
.m-kpi--identity .m-kpi__ic{background:var(--identity-soft);color:var(--identity)}
.m-kpi__x{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto;text-align:start}
.m-kpi__l{
  font:var(--ty-label-sm);font-size:10px;font-weight:600;
  letter-spacing:.05em;text-transform:uppercase;
  color:var(--text-3);min-width:0;overflow-wrap:anywhere;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.m-kpi__v{
  font:var(--ty-metric-sm);font-size:19px;color:var(--text);letter-spacing:var(--track-tight);
  display:flex;align-items:baseline;gap:4px;
}
.m-kpi__v small{font:var(--ty-label);color:var(--text-3);font-weight:550}
.m-kpi__v em{font-style:normal;color:var(--text-3);font-weight:500;font-size:.62em}
.m-kpi__d{display:flex;align-items:center;gap:5px;font:var(--ty-caption);color:var(--text-3);min-width:0}
.m-kpi__d b{display:inline-flex;align-items:center;gap:2px;font-weight:600}
.m-kpi__d b svg{width:11px;height:11px}
.m-kpi__d .up{color:var(--ok)} .m-kpi__d .dn{color:var(--critical)}
.m-kpi__d .up-bad{color:var(--critical)} .m-kpi__d .dn-good{color:var(--ok)}
.m-kpi__d .flat{color:var(--text-3)}
.m-kpi__d span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the trend line beside the figure — the card's own tone, never a second
   colour, and never large enough to become the subject of the card */
.m-kpi__g{flex:0 0 auto;display:flex;align-items:center;margin-inline-start:2px}
.m-kpi__g svg{display:block}
/* a card whose number is a WARNING says so in the number, not only in its
   glyph: on a wall screen the 34px figure is what is read from across the
   room, and a tinted square at its side is not */
.m-kpi--warn .m-kpi__v{color:var(--warn)}
.m-kpi--crit .m-kpi__v{color:var(--critical)}
.m-kpi--lg .m-kpi__v{font:var(--ty-metric)}
.m-kpi--lg .m-kpi__ic{width:44px;height:44px}

/* the one hero figure a page is allowed */
.m-hero-metric{display:flex;flex-direction:column;gap:5px;min-width:0}
.m-hero-metric__l{font:var(--ty-label);color:var(--text-2)}
.m-hero-metric__v{font:var(--ty-display);color:var(--text);letter-spacing:-.02em;display:flex;align-items:baseline;gap:6px}
.m-hero-metric__v small{font:var(--ty-h2);color:var(--text-3)}
.m-hero-metric__s{font:var(--ty-body-sm);color:var(--text-2)}

/* ============================================================== PROGRESS / METER */

.m-bar{
  position:relative;height:6px;border-radius:var(--r-full);
  background:var(--surface-sunken);overflow:hidden;direction:ltr;
}
.m-bar > i{
  display:block;height:100%;border-radius:var(--r-full);
  background:var(--accent-fill,var(--accent));
  transition:width var(--t-slow) var(--ease);
}
.m-bar--lg{height:9px}
.m-bar--ok  > i{background:var(--ok-fill)}
.m-bar--warn> i{background:var(--warn-fill)}
.m-bar--crit> i{background:var(--crit-fill)}
.m-bar--live> i{background:var(--live-fill)}
/* the target tick — a percentage is never shown without what it is measured against */
.m-bar > u{
  position:absolute;top:-2px;width:2px;height:10px;border-radius:1px;
  background:var(--text-2);opacity:.65;text-decoration:none;
}
.m-meter{display:flex;flex-direction:column;gap:5px;min-width:0}
.m-meter__t{display:flex;align-items:baseline;gap:8px;font:var(--ty-label-sm);color:var(--text-2)}
.m-meter__t b{margin-inline-start:auto;color:var(--text);font-weight:600}

/* ============================================================== TABLE */

/* ONE LIST LANGUAGE FOR THE WHOLE PRODUCT. Every table is a stack of soft
   row-cards on a quiet ground — the same shape as the request queue, the
   missed list and the fleet list, so a register reads the same wherever it
   appears. The header floats as a line of micro-labels above the stack. */
.m-table-wrap{overflow:auto;overscroll-behavior:contain;min-height:0;background:var(--surface-subtle)}
.m-table{
  width:100%;font:var(--ty-body-sm);
  border-collapse:separate;border-spacing:0 6px;
  padding:0 12px 10px;
}
.m-table thead th{
  position:sticky;top:0;z-index:2;
  height:30px;padding:0 14px;white-space:nowrap;text-align:start;
  background:var(--surface-subtle);
  font:var(--ty-label-sm);font-size:10px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-3);font-weight:600;
}
.m-table th .m-th{display:inline-flex;align-items:center;gap:4px}
.m-table th.num .m-th{justify-content:flex-end;width:100%}
.m-table th.is-sortable{cursor:pointer;user-select:none}
.m-table th.is-sortable:hover{color:var(--text)}
.m-table th .m-sort{display:inline-flex;opacity:0;transition:opacity var(--t-fast) var(--ease)}
.m-table th.is-sortable:hover .m-sort{opacity:.5}
.m-table th[aria-sort]{color:var(--text)}
.m-table th[aria-sort] .m-sort{opacity:1;color:var(--accent)}
.m-table th .m-sort svg{width:11px;height:11px}

/* Rows get air and ONE rule. No vertical grid and no zebra: both of them cut
   a row into pieces the eye then has to reassemble. */
/* A cell says one line. Wrapping "Rear-loader compactor" onto three lines
   made a 42px row 80px tall and the table twice as long as the screen; the
   full value stays in the row's own record. */
.m-table tbody td{
  height:var(--row-h);padding:5px 14px;
  background:var(--surface);
  border-block:1px solid var(--line-subtle);
  color:var(--text);vertical-align:middle;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:0;
  transition:border-color var(--t-fast) var(--ease),background var(--t-fast) var(--ease);
}
.m-table tbody td:first-child{
  border-inline-start:1px solid var(--line-subtle);
  border-start-start-radius:11px;border-end-start-radius:11px;
}
.m-table tbody td:last-child{
  border-inline-end:1px solid var(--line-subtle);
  border-start-end-radius:11px;border-end-end-radius:11px;
}
.m-table tbody td.shrink,.m-table tbody td.num{max-width:none}
/* a lozenge is not text to be clipped: it either fits or the column is
   widened — an ellipsis rendered over a pill read as a stray full stop */
.m-table tbody td .m-pill{max-width:100%}
.m-table tbody tr.is-clickable{cursor:pointer}
.m-table tbody tr.is-clickable:hover td{border-color:var(--line-strong)}
.m-table tbody tr.is-selected td{background:var(--accent-soft);border-color:var(--accent)}
.m-table .num{text-align:end;font-variant-numeric:tabular-nums}
.m-table .shrink{width:1%;white-space:nowrap}
.m-table--comfy tbody td{height:var(--row-h-lg)}
.m-table--striped tbody tr:nth-child(even) td{background:var(--surface)}

/* Column priority. A column says the narrowest layout it survives in; below
   that it is not drawn. Nine columns squeezed into a laptop are nine columns
   of stubs — the answer is five columns that can be read and the rest in the
   record's own panel. */
@media (max-width:1560px){ .m-table .min-xl{display:none} }
@media (max-width:1320px){ .m-table .min-lg{display:none} }
@media (max-width:1100px){ .m-table .min-md{display:none} }

/* COLOUR INSIDE A TABLE.
   Two tinted columns — a priority chip and a status chip on every row —
   put forty coloured lozenges on one screen, and the eye cannot tell which
   of them is the one that matters. Inside a table a state is a coloured DOT
   with plain text next to it; the tint is kept for the one state an
   operator must not miss. */
.m-table .m-pill{background:transparent;border-color:transparent;color:var(--text-2);padding-inline:0;gap:7px}
.m-table .m-pill__dot{background:var(--neutral-fill)}
.m-table .m-pill--ok   .m-pill__dot{background:var(--ok-fill)}
.m-table .m-pill--warn .m-pill__dot{background:var(--warn-fill)}
.m-table .m-pill--info .m-pill__dot{background:var(--info-fill)}
.m-table .m-pill--live .m-pill__dot{background:var(--live-fill)}
.m-table .m-pill--chain .m-pill__dot{background:var(--chain)}
.m-table .m-pill--crit{
  background:var(--crit-soft);color:var(--critical);
  border-color:var(--crit-line);padding-inline:9px;
}
.m-table .m-pill--crit .m-pill__dot{background:currentColor}

/* a cell that carries an entity: colour rail + name + sub-line */
.m-ent{display:flex;align-items:center;gap:9px;min-width:0}
.m-ent__ic{
  flex:0 0 auto;width:25px;height:25px;border-radius:var(--r-sm);
  display:grid;place-items:center;
  background:var(--surface-sunken);color:var(--text-2);
}
.m-ent__ic svg{width:15px;height:15px}
.m-ent__x{display:flex;flex-direction:column;gap:0;min-width:0}
.m-ent__x b{font:var(--ty-label);color:var(--text);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-ent__x span{font:var(--ty-caption);font-size:10.5px;color:var(--text-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ============================================================== DATA ROW LIST
   The dense list used wherever a table would be too heavy. One shape,
   re-gridded per context with a modifier that sets grid-template-columns. */

/* the same row-card language as the tables above */
.m-rows{display:flex;flex-direction:column;min-width:0;gap:6px;padding:8px 10px}
.m-row-item{
  display:grid;align-items:center;gap:var(--s-3);
  padding:9px 14px;min-height:50px;
  background:var(--surface);border:1px solid var(--line-subtle);
  border-radius:11px;
  text-align:start;width:100%;
  transition:background var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),
             box-shadow var(--t-fast) var(--ease);
}
.m-row-item.is-clickable{cursor:pointer}
.m-row-item.is-clickable:hover{border-color:var(--line-strong);box-shadow:0 3px 10px rgba(9,30,54,.07)}
.m-row-item.is-selected{background:var(--accent-soft);border-color:var(--accent)}
.m-row-item--head{
  min-height:30px;padding-block:0;
  background:var(--surface);border:0;border-radius:0;
  font:var(--ty-label-sm);font-size:10px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-3);font-weight:600;
  position:sticky;top:0;z-index:2;
}
.m-row-item__rail{
  position:absolute;inset-inline-start:0;top:0;bottom:0;width:3px;background:transparent;
}
.m-row-item{position:relative;overflow:hidden}
.m-row-item--crit .m-row-item__rail{background:var(--crit-fill)}
.m-row-item--warn .m-row-item__rail{background:var(--warn-fill)}
.m-row-item--ok   .m-row-item__rail{background:var(--ok-fill)}
.m-row-item--info .m-row-item__rail{background:var(--info-fill)}

/* ============================================================== ACTIVITY / TIMELINE */

.m-activity{display:flex;flex-direction:column}
.m-activity__i{
  position:relative;display:flex;align-items:flex-start;gap:10px;
  padding:10px var(--card-pad-lg);border-bottom:1px solid var(--line-subtle);
}
.m-activity__i:last-child{border-bottom:0}
/* the severity edge — see activity() in js5/ui/kit.js. Only the rows that
   stop a vehicle carry one, so the eye has somewhere to land first. */
.m-activity__i--hot::before{
  content:'';position:absolute;inset-block:8px;inset-inline-start:0;
  width:3px;border-radius:0 3px 3px 0;background:var(--rc,var(--critical));
}
html[dir="rtl"] .m-activity__i--hot::before{border-radius:3px 0 0 3px}
.m-activity__ic{
  flex:0 0 auto;width:26px;height:26px;border-radius:var(--r-sm);
  display:grid;place-items:center;background:var(--surface-sunken);color:var(--text-2);
}
.m-activity__ic svg{width:14px;height:14px}
.m-activity__x{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.m-activity__x b{font:var(--ty-body-sm);color:var(--text);font-weight:550}
.m-activity__x span{font:var(--ty-caption);color:var(--text-3)}
.m-activity__t{flex:0 0 auto;font:var(--ty-caption);color:var(--text-3);font-variant-numeric:tabular-nums}
.m-activity__i--new{animation:m-pulse-once 1.6s var(--ease) 1}

.m-timeline{position:relative;padding-inline-start:22px;display:flex;flex-direction:column;gap:var(--s-4)}
.m-timeline::before{
  content:'';position:absolute;inset-inline-start:7px;top:6px;bottom:6px;
  width:2px;background:var(--line);border-radius:1px;
}
.m-timeline__i{position:relative;display:flex;flex-direction:column;gap:2px;min-width:0}
.m-timeline__i::before{
  content:'';position:absolute;inset-inline-start:-22px;top:5px;
  width:10px;height:10px;border-radius:var(--r-full);
  background:var(--surface);border:2px solid var(--line-strong);
}
.m-timeline__i--done::before{background:var(--ok-fill);border-color:var(--ok-fill)}
.m-timeline__i--now::before{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.m-timeline__i--bad::before{background:var(--crit-fill);border-color:var(--crit-fill)}
.m-timeline__i b{font:var(--ty-label);color:var(--text)}
.m-timeline__i span{font:var(--ty-caption);color:var(--text-2)}
.m-timeline__i time{font:var(--ty-caption);color:var(--text-3);font-variant-numeric:tabular-nums}

/* ============================================================== PROCESS STRIP
   The weighbridge / CRM-to-work-order flow: stages left to right with
   the current one marked. */
.m-process{display:flex;align-items:stretch;gap:0;overflow-x:auto;scrollbar-width:none}
.m-process::-webkit-scrollbar{display:none}
.m-process__s{
  position:relative;flex:1 1 0;min-width:132px;
  display:flex;flex-direction:column;gap:5px;
  padding:12px 14px 12px 20px;
}
html[dir="rtl"] .m-process__s{padding:12px 20px 12px 14px}
.m-process__s::before{
  content:'';position:absolute;inset-inline-start:0;top:14px;bottom:14px;width:2px;
  border-radius:1px;background:var(--line);
}
.m-process__s--done::before{background:var(--ok-fill)}
.m-process__s--now::before{background:var(--accent)}
.m-process__n{font:var(--ty-label-sm);color:var(--text-3)}
.m-process__t{font:var(--ty-label);color:var(--text)}
.m-process__v{font:var(--ty-body-sm);color:var(--text-2)}
.m-process__s--now .m-process__t{color:var(--accent-press);font-weight:650}

/* THE STAGE BAR AS A CONTROL.
   Eleven stages at the reading width of the read-only bar is fourteen
   hundred pixels — a dialog cannot hold it, and a horizontal scrollbar
   makes the last stages invisible. As a control it is a wrapped row of
   stage chips: everything the record has passed, where it is now, and
   everywhere it can be sent, all at once and all clickable. */
.m-process--pick{
  flex-wrap:wrap;overflow:visible;gap:4px;padding:5px;
  background:var(--surface-sunken);border:1px solid var(--line-subtle);
  border-radius:var(--r-md);
}
.m-process--pick .m-process__s{
  flex:0 0 auto;min-width:0;flex-direction:row;align-items:center;gap:6px;
  padding:4px 10px;border-radius:var(--r-full);cursor:pointer;text-align:start;
  background:var(--surface);border:1px solid var(--line-subtle);
  transition:background var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),
             color var(--t-fast) var(--ease);
}
html[dir="rtl"] .m-process--pick .m-process__s{padding:4px 10px}
.m-process--pick .m-process__s::before{display:none}
.m-process--pick .m-process__n{
  min-width:16px;height:16px;border-radius:var(--r-full);
  background:var(--neutral-soft);color:var(--text-3);
  font:600 10px/16px var(--font);text-align:center;
}
.m-process--pick .m-process__t{font:var(--ty-label-sm);color:var(--text-2)}
.m-process--pick .m-process__s:hover{border-color:var(--accent);background:var(--accent-soft)}
.m-process--pick .m-process__s:hover .m-process__t{color:var(--accent-press)}
.m-process--pick .m-process__s--done{background:var(--ok-soft);border-color:transparent}
.m-process--pick .m-process__s--done .m-process__n{background:var(--ok-fill);color:#fff}
.m-process--pick .m-process__s--done .m-process__t{color:var(--ok)}
.m-process--pick .m-process__s--now{background:var(--accent);border-color:transparent}
.m-process--pick .m-process__s--now .m-process__n{background:rgba(255,255,255,.26);color:#fff}
.m-process--pick .m-process__s--now .m-process__t{color:#fff;font-weight:650}
/* the count travels with the stage, so it takes the stage's ink */
.m-process--pick .m-process__v{font:var(--ty-label-sm);color:var(--text);font-weight:650}
.m-process--pick .m-process__s--done .m-process__v{color:var(--ok)}
.m-process--pick .m-process__s--now .m-process__v{color:#fff}
.m-process--pick .m-process__s:hover .m-process__v{color:var(--accent-press)}
.m-process--pick .m-process__s--now:hover .m-process__v{color:#fff}
.m-process--pick .m-process__s--now:hover{background:var(--accent);border-color:transparent}
.m-process--pick .m-process__s--now:hover .m-process__t{color:#fff}

/* ============================================================== CHARTS */

.m-chart{position:relative;width:100%;min-width:0}
.m-chart svg{width:100%;height:auto;display:block;overflow:visible}
.m-chart__grid{stroke:var(--ch-grid);stroke-width:1}
.m-chart__axis{fill:var(--ch-axis);font:var(--ty-caption);font-family:var(--font)}
.m-chart__line{fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.m-chart__rule{stroke:var(--text-2);stroke-width:1.2;stroke-dasharray:5 4;opacity:.75}
.m-chart__hot{fill:transparent;cursor:crosshair}
.m-chart__tip{
  position:absolute;z-index:3;pointer-events:none;
  padding:8px 10px;border-radius:var(--r-sm);
  background:var(--surface-raised);border:1px solid var(--line);
  box-shadow:var(--sh-lg);font:var(--ty-caption);color:var(--text);
  opacity:0;transition:opacity var(--t-fast) var(--ease);min-width:120px;
}
.m-chart__tip.is-on{opacity:1}
.m-chart__tip b{display:block;font:var(--ty-label-sm);margin-bottom:4px;color:var(--text-2)}
.m-chart__tip div{display:flex;align-items:center;gap:6px;line-height:1.7}
.m-chart__tip i{width:8px;height:8px;border-radius:2px;flex:0 0 auto}
.m-chart__tip strong{margin-inline-start:auto;font-variant-numeric:tabular-nums}

.m-legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:10px}
.m-legend span{display:inline-flex;align-items:center;gap:6px;font:var(--ty-caption);color:var(--text-2)}
.m-legend i{width:9px;height:9px;border-radius:3px;flex:0 0 auto}

/* horizontal ranking bars */
.m-hbars{display:flex;flex-direction:column;gap:9px}
.m-hbar{display:flex;align-items:center;gap:10px;min-width:0}
.m-hbar__l{flex:0 0 var(--labelw,116px);font:var(--ty-body-sm);color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-hbar__t{position:relative;flex:1 1 auto;height:8px;border-radius:var(--r-full);background:var(--surface-sunken);direction:ltr}
.m-hbar__t > i{display:block;height:100%;border-radius:var(--r-full);background:var(--ch-1)}
.m-hbar__t > u{position:absolute;top:-2px;width:2px;height:12px;background:var(--text-2);opacity:.6;text-decoration:none}
.m-hbar__v{flex:0 0 auto;font:var(--ty-label-sm);color:var(--text);font-variant-numeric:tabular-nums;min-width:44px;text-align:end}

/* donut + ring gauge */
.m-donut{display:flex;align-items:center;gap:var(--s-5);flex-wrap:wrap}
.m-donut__g{position:relative;flex:0 0 auto}
.m-donut__c{
  position:absolute;inset:0;display:grid;place-content:center;text-align:center;gap:1px;
}
.m-donut__c b{font:var(--ty-metric-sm);color:var(--text)}
.m-donut__c span{font:var(--ty-caption);color:var(--text-3)}
.m-donut__k{display:flex;flex-direction:column;gap:7px;min-width:0;flex:1 1 140px}
.m-donut__k > div{display:flex;align-items:center;gap:8px;font:var(--ty-body-sm);min-width:0}
.m-donut__k i{width:9px;height:9px;border-radius:3px;flex:0 0 auto}
.m-donut__k span{flex:1 1 auto;color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-donut__k b{color:var(--text);font-variant-numeric:tabular-nums}

.m-rings{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:var(--s-4);text-align:center}
.m-ring{display:flex;flex-direction:column;align-items:center;gap:7px}
.m-ring__g{position:relative}
.m-ring__c{position:absolute;inset:0;display:grid;place-content:center}
.m-ring__c b{font:var(--ty-metric-sm);color:var(--text)}
.m-ring__l{font:var(--ty-caption);color:var(--text-2);max-width:12ch;line-height:1.35}

.m-spark{display:block;width:100%;height:30px;overflow:visible}

/* ============================================================== PAGINATION */

.m-pager{
  display:flex;align-items:center;gap:var(--s-2);
  padding:9px var(--card-pad-lg);border-top:1px solid var(--line-subtle);
  font:var(--ty-caption);color:var(--text-2);
}
.m-pager__c b{color:var(--text);font-variant-numeric:tabular-nums}
.m-pager__n{display:flex;align-items:center;gap:2px;margin-inline-start:auto}
.m-pager__p{
  min-width:28px;height:28px;padding:0 7px;border-radius:var(--r-xs);
  display:inline-flex;align-items:center;justify-content:center;
  font:var(--ty-label-sm);color:var(--text-2);
}
.m-pager__p:hover{background:var(--surface-sunken);color:var(--text)}
.m-pager__p[aria-current="page"]{background:var(--accent);color:var(--accent-on)}
.m-pager__p:disabled{opacity:.35;pointer-events:none}
.m-pager__gap{padding:0 3px;color:var(--text-3)}
/* THE PAGER NEVER LEAVES THE SCREEN.
   It is pinned to the bottom of whatever region scrolls the list, so at any
   browser zoom, any window height and any page size the operator can always
   see where they are and move on. */
.m-pager{position:sticky;bottom:0;z-index:3;background:var(--surface);flex:0 0 auto;flex-wrap:wrap;row-gap:6px}
.m-pager__sz{display:inline-flex;align-items:center;gap:2px;margin-inline-start:var(--s-4);
  padding:2px;border:1px solid var(--line);border-radius:var(--r-sm)}
.m-pager__sz > span{padding:0 6px 0 4px;font:var(--ty-caption);color:var(--text-3)}
.m-pager__sz button{height:22px;min-width:26px;padding:0 6px;border-radius:var(--r-xs);
  font:var(--ty-label-sm);color:var(--text-2)}
.m-pager__sz button:hover{background:var(--surface-sunken);color:var(--text)}
.m-pager__sz button[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent-press)}
@media (max-width:900px){ .m-pager__sz{display:none} }

/* A cell is two lines at most. One alarm condition ran to eight lines and
   took the row with it: the table stopped being a table and became a column
   of paragraphs. The full text is in the record's own panel. */
.m-table tbody td > div > span,
.m-table tbody td > span.m-sub{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.m-table tbody td > div > b{
  display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
