Move the console onto ReUI PRO

Install ReUI (MCP, skill, @reui registry, Tailwind v4, shadcn base-nova) and move
the shared UI onto it: Button, Tag, Check, Input/Textarea, Segmented, Alert, Panel,
Dialog, Tooltip, Menu and Select (Popover), Toast (sonner), the Table frame
(DataGrid), the Dashboard KPI strip, the shnt Ops palette, Geist and the type scale.

Design only: behaviour, texts and roles are unchanged. Tests that asserted the old
DOM were updated; the tests now format numbers in English wherever they run.
docs/reui-migration-plan.md records the plan and its decisions.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-27 00:06:06 +07:00
commit f3531c64f9
680 files changed
+139836

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
/* The status block: a mark, two lines, the control. */
.status { display: flex; align-items: center; gap: var(--s-9); }
.mark { display: grid; place-items: center; width: var(--s-12); height: var(--s-12); border-radius: var(--r-3); flex: none; }
.on { background: var(--ok-bg); border: 1px solid var(--ok-bd); color: var(--ok); }
.paused { background: var(--acc-bg); border: 1px solid var(--acc-bd); color: var(--acc-ink); }
.off { background: var(--pan2); border: 1px solid var(--line); color: var(--mute); }
.statusText { flex: 1; min-width: 0; }
.statusTitle { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-5); font-size: var(--t-5); font-weight: 600; }
.statusSub { color: var(--mute); margin-top: var(--s-1); }
/* Top tables: name, a bar for the share, the hits, the row menu. */
/* The name wraps at its dots only (`ui/DomainName`), never inside a label. */
.name { font-family: var(--font-mono); }
.hits { font-family: var(--font-mono); text-align: right; white-space: nowrap; }
/* The header over the hits sits where the figures end, not where they would begin.
Written to outweigh `.table thead th` of ui/Table, which sets every header left. */
thead > tr > th.hitsHead { text-align: right; }
/* A block, not the span's inline box: an inline element ignores `height`. */
.share { display: block; position: relative; height: var(--s-3); min-width: var(--s-12); border-radius: var(--r-1); background: var(--line2); }
.share > i { position: absolute; inset: 0 auto 0 0; border-radius: var(--r-1); }
.shareBlocked > i { background: var(--ch-block); }
.shareTotal > i { background: var(--ch-total); }
.time { font-family: var(--font-mono); color: var(--faint); white-space: nowrap; }
/* Where Recently Blocked's rows stack (`stack` in ui/Table: always below 560), the time
no longer has to share a line with the domain and keeps its one line. It used to
wrap there, `2026-10-` / `16` / `09:42:52`, beside a domain a few characters wide. */
.mono { font-family: var(--font-mono); }
/* The node after Recently Blocked's title: part of the title, quieter than it. */
.where { color: var(--mute); font-weight: 400; }
/*
Muted, not `--warn`: on this screen the paused mark is `--acc`, and tokens.css
measures the two ambers as indistinguishable. The sentence and its icon say it.
*/
.partial { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-5) var(--s-9); color: var(--mute); }
/*
A figure's trend, beside its text and as tall as it (`.kpi` in Blocking.module.css):
the text keeps its width, so its three lines stay level with the other cards', and the
trend takes what is left, up to half the card. Size containment drops the drawing's own
100:32 shape, so a wide screen cannot make the trend, and with it the card, taller.
*/
.spark {
display: block;
flex: 1 1 0;
align-self: stretch;
min-width: var(--s-12);
max-width: 50%;
height: auto;
contain: size;
}
/*
`--bp-stack`. Two cards a row leave no room beside the text, so the trend drops to the
card's foot and runs to its edges, as the drawing has it: the body's padding
(`--s-9`, ui/Panel) is given back on three sides and the panel's rounded corners clip
it. The two cards with a trend share the first row, so no card in a row has a band
the other lacks.
*/
@media (max-width: 560px) {
.trended { flex-wrap: wrap; }
.spark {
flex-basis: calc(100% + 2 * var(--s-9));
max-width: none;
height: var(--s-12);
margin: 0 calc(-1 * var(--s-9)) calc(-1 * var(--s-9));
}
}
.sparkTotal { color: var(--ch-total); }
.sparkBlocked { color: var(--ch-block); }
/* The ring, with the share written in its hole. */
.ring { position: relative; }
.ringValue { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; font-family: var(--font-mono); font-size: var(--t-6); font-weight: 600; pointer-events: none; }
.ringLabel { display: block; font-family: var(--font-ui); font-size: var(--t-1); font-weight: var(--text-weight); letter-spacing: var(--text-tracking); text-transform: uppercase; color: var(--mute); }
/*
The status block and "Check, block or allow a domain" share a row, and the grid
stretches both to the taller one. Before any check that is what balances the row:
the status block is the shorter, and its content sits in its middle (`.centred`).
Once the check panel holds something under its field (the wait, the verdict, or why
there is none), stretching would leave the status block a tall box with one line
floating in it, so it keeps its own height instead, top-aligned. The check panel's
answer region is empty (`:empty`) until then.
*/
.checkRow:has([aria-live]:not(:empty)) > :first-child { align-self: start; }