251 buttons across the 7 pages, counted in the browser with every wizard step,
creator section and tool panel forced visible. Two thirds of them are
display:none at load, so a static grep sees about eighty and misses the rest.
FOUR ROLES, defined once in theme-light.css as --wp-btn-*, and no fifth:
primary the one action the screen exists for. Filled accent.
secondary every other real action. White, --border-strong, accent on hover.
tertiary navigating or undoing. No fill, no border, accent text.
danger destructive. Outlined red; filled red only where the control is too
small for an outline to read - the 28px x on a sequence row.
Every button class is mapped to a role in docs/reference/tokens.md section 12.
No value is new: these are the fills the sheets already rendered, given one
definition so that "primary" means one thing.
GREEN IS A STATUS COLOUR AND NO LONGER FILLS A BUTTON. A5 names two green action
buttons; there are four. .use-btn and the launcher's completed-SOP card button
never render green in the default fixture, so the review could not have seen
them - the SOP has to be finished and a suggested value has to be offered first.
.nav-btn.primary "SOP complete" wizard
.btn.btn-generate "Save & view" creator
.use-btn creator
.card.complete .card-button launcher
The green did not go anywhere. .cstatus button.on-cleared, .toggle-btn.enabled,
.wp-nav-dot.ok, .rb-ready, .badge-R and the launcher card's own left border and
status line all still carry it, and every one of those is a state rather than an
action. The launcher card in particular still says "complete" twice after this
change; it just no longer says it on the button.
SENTENCE CASE, applied to buttons and field labels only, which is the scope A5
sets. First word capitalised, the rest lowercased, acronyms and external proper
nouns left alone (SOP, QC, WP, UPN, PM/APM/CM/QM, PDF, JSON, CSV, BIM, MIMO,
Excel, Acumatica).
~30 button labels across launcher, wizard, creator, admin and two scripts
46 field labels
text-transform:uppercase removed from 4 rules - .btn and .add-btn (creator
buttons), label and .cmt-namebar label (creator field labels)
Labels carrying markup - a .req asterisk, a .help-tip chip - had only their text
nodes transformed, so the markup survives and "first word" means the first word
of the label rather than of each fragment. The creator's mono face, 10px size and
tracking are its idiom and are untouched; only the forced uppercase goes.
help.js was updated too. It names "Load Sample" and "SOP Complete" in prose, so
renaming the buttons without it would have left the help centre describing
controls that no longer exist. That coupling is the only place in the app where
button text is referenced by name.
Verified by re-running the inventory: 0 green action buttons, 0 uppercase button
labels, 251 buttons still present - nothing was lost in the rename.
console.css card headers are unchanged, confirmed by diff: the only six lines
this task touches in that file are token substitutions on button/button.primary/
button.danger, none of them within twenty lines of .card h2.
f_items 5 FIXED / F6 REPRODUCES. browser_check 71/71.
Left alone and logged: .step-tab is still uppercase (BL-015) - it is a stepper
tab, neither a button nor a field label, and A4/S9 rebuild the stepper. Table
headers, section eyebrows and headings keep their case throughout. BL-008 and
BL-009 were re-targeted from T3.5 to wave 9: both are colour merges on a field
fill and a status pill, and this task is scoped to buttons.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
210 lines
16 KiB
CSS
210 lines
16 KiB
CSS
/* Shared styling for the suite's dense admin pages — the Admin Console and the
|
|
User Directory. Both are mostly tables and toolbars, which is a different job
|
|
from the wizard pages, so they carry this sheet instead of theme-light.css's
|
|
form-heavy one. The palette, the square corners and the type are still Carbon's,
|
|
so the pages read as one product with the rest of the suite.
|
|
|
|
Two scales do all the spacing and all the control sizing; nothing that uses this
|
|
sheet should invent its own. Page-specific rules (per-ID scroll boxes, column
|
|
exceptions) stay in the page that owns them.
|
|
|
|
══ TOKENS ══════════════════════════════════════════════════════════════════
|
|
Names only. Every value comes from theme-light.css, which every page loads
|
|
first — this sheet declares nothing of its own (T3.2 / S5 / C3). The names
|
|
stay because admin.js and users.js read 21 of them from JavaScript, where a
|
|
rename fails silently: no build error, no console warning, just an unstyled
|
|
element. See docs/reference/tokens.md section 9. */
|
|
:root{ --bg:var(--cds-background); --surface:var(--cds-layer); --border:var(--cds-border-subtle);
|
|
--border-strong:var(--cds-border-strong); --text:var(--cds-text-primary);
|
|
--muted:var(--cds-text-secondary); --dim:var(--cds-ui-04); --accent:var(--cds-interactive-01);
|
|
--accent-hover:var(--cds-hover-primary); --accent-soft:var(--cds-highlight);
|
|
--green:var(--cds-support-success); --green-bg:var(--wp-status-success-bg);
|
|
--red:var(--cds-support-error); --red-bg:var(--wp-status-error-bg);
|
|
--amber:var(--wp-status-warning-text); --amber-bg:var(--wp-status-warning-bg);
|
|
--head-bg:var(--cds-layer-accent);
|
|
/* --zebra is six points lighter than --head-bg, not equal to it: collapsing
|
|
the two erases the striping on a nine-column table, which is the one place
|
|
striping is load-bearing. --row-hover is deliberately NOT --accent-soft;
|
|
see the note above table.grid tbody tr:hover. Both are one-offs and both
|
|
are named in docs/reference/tokens.md section 8-A/8-B. */
|
|
--zebra:var(--wp-table-zebra); --row-hover:var(--wp-table-row-hover);
|
|
/* The narrow mono stack, kept as-is: widening it changes the rendered face on
|
|
any machine without IBM Plex Mono installed, and this sheet's two pages are
|
|
the ones a font change would show up on. T3.5 picks one stack (8-H). */
|
|
--mono:var(--wp-font-mono-2);
|
|
--s1:var(--wp-s1); --s2:var(--wp-s2); --s3:var(--wp-s3);
|
|
--s4:var(--wp-s4); --s5:var(--wp-s5); --s6:var(--wp-s6);
|
|
--ctl:var(--wp-ctl); /* every button / input / select that sits in a form row */
|
|
--ctl-sm:var(--wp-ctl-sm); } /* every control that sits inside a table cell */
|
|
*{ box-sizing:border-box; }
|
|
body{ margin:0; font-family:var(--wp-font-sans-2); background:var(--bg); color:var(--text); }
|
|
|
|
/* ══ PAGE ══════════════════════════════════════════════════════════════════════
|
|
1240px, not 860: the user table is nine columns wide and at 860 it spilled
|
|
straight out of its own white card. Wide enough for that table, still a
|
|
readable measure for the prose, which is capped separately. */
|
|
.wrap{ max-width:1240px; margin:0 auto; padding:var(--s6) var(--s5) 80px; }
|
|
h1{ font-size:20px; line-height:1.2; margin:0 0 2px; }
|
|
.sub{ color:var(--muted); font-size:13px; line-height:1.5; margin:0 0 var(--s3); max-width:96ch; }
|
|
a.home{ color:var(--accent); font-size:13px; text-decoration:none; white-space:nowrap; }
|
|
a.home:hover{ text-decoration:underline; }
|
|
|
|
/* ══ CARDS ═════════════════════════════════════════════════════════════════════ */
|
|
.card{ background:var(--surface); border:1px solid var(--border); border-radius:0;
|
|
padding:var(--s4) var(--s5) var(--s5); margin-bottom:var(--s4); }
|
|
/* One card header everywhere: small uppercase accent label on a hairline. The
|
|
scripts also emit h2 for sub-sections inside a card with an inline margin-top —
|
|
the same treatment reads correctly as a divider there, so both get it. */
|
|
.card h2{ font-size:12px; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
|
|
color:var(--accent); margin:0 0 var(--s3); padding-bottom:var(--s2); border-bottom:1px solid var(--border); }
|
|
.wrap code{ font-family:var(--mono); font-size:.92em; background:var(--bg); padding:1px 4px; }
|
|
|
|
/* ══ CONTROLS ══════════════════════════════════════════════════════════════════
|
|
Every button, input and select in a form row is exactly --ctl tall, so a
|
|
toolbar is one clean band instead of a ragged one. */
|
|
button{ font:inherit; font-size:13px; font-weight:600; line-height:1; white-space:nowrap;
|
|
height:var(--ctl); padding:0 var(--s3); border-radius:0; cursor:pointer;
|
|
border:1px solid var(--wp-btn-secondary-border); background:var(--wp-btn-secondary-bg); color:var(--wp-btn-secondary-fg); }
|
|
button:hover{ border-color:var(--wp-btn-secondary-hover-fg); color:var(--wp-btn-secondary-hover-fg); }
|
|
button:focus-visible{ outline:2px solid var(--accent); outline-offset:-3px; }
|
|
button:disabled, button:disabled:hover{ color:var(--dim); border-color:var(--border); background:var(--surface); cursor:default; }
|
|
button.primary{ background:var(--wp-btn-primary-bg); border-color:var(--wp-btn-primary-bg); color:var(--wp-btn-primary-fg); }
|
|
button.primary:hover{ background:var(--wp-btn-primary-hover); border-color:var(--wp-btn-primary-hover); color:var(--wp-btn-primary-fg); }
|
|
button.danger{ border-color:var(--wp-btn-danger-border); color:var(--wp-btn-danger-fg); }
|
|
button.danger:hover{ background:var(--wp-btn-danger-soft-bg); border-color:var(--wp-btn-danger-border); color:var(--wp-btn-danger-fg); }
|
|
.row{ display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center; }
|
|
/* The filter / search / button strip at the top of a card. */
|
|
.toolbar{ display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center; margin:0 0 var(--s3); }
|
|
.toolbar + .banner{ margin-top:0; }
|
|
.urow{ display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center; }
|
|
/* Checkboxes are excluded: they are drawn by the platform and want none of a
|
|
text field's height, padding or border. */
|
|
.toolbar input:not([type=checkbox]), .toolbar select,
|
|
.urow input:not([type=checkbox]), .urow select{
|
|
height:var(--ctl); padding:0 var(--s2); font:inherit; font-size:13px; line-height:normal;
|
|
border:1px solid var(--border-strong); border-radius:0; background:var(--surface); color:var(--text); }
|
|
.toolbar select, .urow select{ cursor:pointer; padding-right:var(--s1); }
|
|
.toolbar input:focus-visible, .toolbar select:focus-visible,
|
|
.urow input:focus-visible, .urow select:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }
|
|
.toolbar > input{ flex:1 1 240px; min-width:150px; }
|
|
.urow input:not([type=checkbox]){ flex:1 1 140px; min-width:0; }
|
|
/* Inline checkbox + label, sized to sit on the same line as the buttons. */
|
|
.chk{ display:inline-flex; align-items:center; gap:var(--s2); height:var(--ctl); padding:0 var(--s1);
|
|
font-size:13px; color:var(--muted); white-space:nowrap; cursor:pointer; }
|
|
.chk input{ width:16px; height:16px; margin:0; accent-color:var(--accent); cursor:pointer; }
|
|
|
|
/* ══ FEEDBACK: banners, notes, console output, key/value ════════════════════════ */
|
|
.banner{ margin:var(--s3) 0 0; padding:9px var(--s3); border-radius:0; font-size:13px; font-weight:600;
|
|
line-height:1.4; border:1px solid var(--border); border-left:3px solid var(--border-strong);
|
|
background:var(--surface); color:var(--text); }
|
|
.banner.ok{ background:var(--green-bg); color:var(--green); border-color:var(--wp-status-success-border-a); border-left-color:var(--green); }
|
|
.banner.bad{ background:var(--red-bg); color:var(--red); border-color:var(--wp-status-error-border-a); border-left-color:var(--red); }
|
|
.banner.warn{ background:var(--amber-bg); color:var(--amber); border-color:var(--wp-status-warning-border-a); border-left-color:var(--amber); }
|
|
/* --muted, not --dim: #8d8d8d on white is 3.3:1, under the 4.5:1 floor at 12px,
|
|
and the boxes the scripts fill are themselves .note — their primary toggle
|
|
labels inherit this colour. */
|
|
.note{ font-size:12px; line-height:1.55; color:var(--muted); margin-top:var(--s2); }
|
|
.note strong, .note em{ color:var(--text); }
|
|
pre.out{ background:var(--wp-term-bg); color:var(--wp-term-fg); border-radius:0; padding:var(--s3) var(--s4); font-family:var(--mono);
|
|
font-size:12px; line-height:1.55; white-space:pre-wrap; max-height:340px; overflow:auto; margin:var(--s3) 0 0; }
|
|
pre.out .p{ color:var(--wp-term-pass); font-weight:700; } pre.out .f{ color:var(--wp-term-fail); font-weight:700; }
|
|
table.kv{ border-collapse:collapse; font-size:13px; margin-top:var(--s2); }
|
|
table.kv th{ text-align:left; padding:var(--s1) var(--s5) var(--s1) 0; color:var(--muted); font-weight:600; white-space:nowrap; }
|
|
table.kv td{ padding:var(--s1) 0; font-variant-numeric:tabular-nums; font-weight:700; color:var(--text); }
|
|
|
|
/* ══ DATA TABLES ═══════════════════════════════════════════════════════════════
|
|
table.users is the name admin.js already emits; table.grid is the same object
|
|
under the shared name. One rule set serves both, so existing markup picks up the
|
|
dense styling without being rewritten. border-collapse is separate rather than
|
|
collapse because a collapsed border does not travel with a sticky header. */
|
|
table.grid, table.users{ width:100%; border-collapse:separate; border-spacing:0;
|
|
font-size:13px; color:var(--text); background:var(--surface); }
|
|
table.grid th, table.users th{ position:sticky; top:0; z-index:2; background:var(--head-bg);
|
|
text-align:left; padding:var(--s2) var(--s3); white-space:nowrap;
|
|
font-size:11px; font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--muted);
|
|
box-shadow:inset 0 -1px 0 var(--border); }
|
|
/* Cells never wrap: a wrapped cell turns one user into a 100px tall band and the
|
|
table stops reading as rows. Anything genuinely long truncates (.ell) or is
|
|
exempted by name in the page that owns the table. */
|
|
table.grid td, table.users td{ padding:var(--s1) var(--s3); border-bottom:1px solid var(--border);
|
|
vertical-align:middle; white-space:nowrap; }
|
|
table.grid tbody tr:last-child td, table.users tbody tr:last-child td{ border-bottom:none; }
|
|
table.grid tbody tr:nth-child(even) td, table.users tbody tr:nth-child(even) td{ background:var(--zebra); }
|
|
/* A neutral hover, not --accent-soft: that is .tag.admin's fill, and an "all
|
|
projects" pill sitting on its own colour disappears the moment you hover it. */
|
|
table.grid tbody tr:hover td, table.users tbody tr:hover td{ background:var(--row-hover); }
|
|
/* A row for an account this caller may see but not change. Dimmed as a whole so
|
|
the disabled controls aren't the only clue. */
|
|
table.grid tbody tr.is-locked td, table.users tbody tr.is-locked td{ color:var(--muted); }
|
|
/* Truncation has to hang off a block INSIDE the cell. max-width on a <td> is
|
|
advisory under table-layout:auto — the cell just grows to fit and the ellipsis
|
|
never appears, which is the usual reason this trick looks like it works in the
|
|
stylesheet and doesn't on the page. The scripts emit <td class="ell"><span>. */
|
|
.ell{ max-width:240px; }
|
|
.ell > span{ display:block; max-width:240px; overflow:hidden; text-overflow:ellipsis;
|
|
white-space:nowrap; }
|
|
/* Every action cell the scripts render is a .cellactions, and it must not wrap:
|
|
unwrapped, the three buttons stack and the row grows fourfold. */
|
|
.cellactions{ display:flex; flex-wrap:nowrap; align-items:center; gap:var(--s1); white-space:nowrap; }
|
|
/* Controls that live in a cell are one step smaller, which is what keeps a row at
|
|
~34px instead of ~100px. .chk is form-row sized by default, so it needs saying
|
|
again here or checkbox rows stand 6px taller than the rest. */
|
|
button.mini{ height:var(--ctl-sm); padding:0 var(--s2); font-size:12px; }
|
|
table.grid td .chk, table.users td .chk{ height:var(--ctl-sm); }
|
|
select.role-select{ height:var(--ctl-sm); max-width:170px; padding:0 var(--s1) 0 var(--s2);
|
|
font:inherit; font-size:12px; border:1px solid var(--border-strong); border-radius:0;
|
|
background:var(--surface); color:var(--text); cursor:pointer; }
|
|
select.role-select:hover{ border-color:var(--accent); }
|
|
select.role-select.is-admin{ color:var(--accent); border-color:var(--accent); font-weight:600; }
|
|
select.role-select:disabled{ color:var(--dim); border-color:var(--border); background:var(--bg); cursor:default; }
|
|
.tag{ display:inline-block; padding:1px 8px; border-radius:11px; font-size:11px; font-weight:600;
|
|
line-height:1.55; white-space:nowrap; vertical-align:middle; }
|
|
.tag.admin{ background:var(--accent-soft); color:var(--accent); }
|
|
.tag.super{ background:var(--wp-tag-super-bg); color:var(--wp-tag-super-text); }
|
|
.tag.user{ background:var(--cds-layer-hover); color:var(--muted); }
|
|
.tag.on{ background:var(--green-bg); color:var(--green); }
|
|
.tag.off{ background:var(--red-bg); color:var(--red); }
|
|
.tag.archived{ background:var(--amber-bg); color:var(--amber); }
|
|
.me-tag{ font-size:11px; color:var(--dim); margin-left:6px; white-space:nowrap; }
|
|
|
|
/* A wide table scrolls inside its own box so the page never scrolls sideways, and
|
|
the capped height is what gives the sticky header something to do. */
|
|
.tscroll{ overflow:auto; max-height:min(70vh,640px); overscroll-behavior:contain; }
|
|
|
|
/* ══ MODALS ════════════════════════════════════════════════════════════════════
|
|
The project-access dialog, shared by both pages. */
|
|
.modal-ov{ position:fixed; inset:0; background:var(--wp-scrim-cool-modal); display:flex; align-items:center;
|
|
justify-content:center; z-index:10002; padding:var(--s5); }
|
|
.modal-box{ background:var(--surface); border-radius:0; max-width:660px; width:100%; max-height:82vh;
|
|
display:flex; flex-direction:column; overflow:hidden; box-shadow:var(--wp-shadow-modal); }
|
|
.modal-head{ padding:var(--s3) var(--s4); border-bottom:1px solid var(--border); font-weight:700; }
|
|
.modal-body{ padding:var(--s3) var(--s4); overflow:auto; }
|
|
.modal-foot{ padding:var(--s3) var(--s4); border-top:1px solid var(--border);
|
|
display:flex; gap:var(--s2); justify-content:flex-end; }
|
|
.pickrow{ display:flex; align-items:center; gap:var(--s3); padding:var(--s2) var(--s1);
|
|
border-bottom:1px solid var(--border); font-size:13px; }
|
|
.pickrow:last-child{ border-bottom:none; }
|
|
.pickrow > label{ display:flex; align-items:center; gap:var(--s2); flex:1; min-width:0; cursor:pointer; }
|
|
.pickrow > label > span{ overflow:hidden; text-overflow:ellipsis; }
|
|
|
|
/* ══ GATES & WARNINGS ══════════════════════════════════════════════════════════ */
|
|
.gate-overlay{ position:fixed; inset:0; background:var(--bg); display:flex; align-items:center; justify-content:center; padding:var(--s5); z-index:9999; }
|
|
.gate-box{ background:var(--surface); border:1px solid var(--border); border-radius:0; padding:var(--s6); max-width:380px; width:100%; box-shadow:var(--wp-shadow-gate); }
|
|
.gate-box h2{ margin:0 0 var(--s1); padding:0; border:0; font-size:17px; text-transform:none; letter-spacing:0; color:var(--text); }
|
|
.gate-box p{ color:var(--muted); font-size:13px; margin:0 0 var(--s4); }
|
|
.gate-msg{ color:var(--red); font-size:12px; min-height:16px; margin-bottom:var(--s2); }
|
|
.secwarn{ background:var(--amber-bg); color:var(--amber); border:1px solid var(--amber); border-radius:0; padding:9px 13px; font-size:12px; margin-bottom:var(--s4); }
|
|
|
|
/* ══ NARROW SCREENS ════════════════════════════════════════════════════════════
|
|
The page itself must never scroll sideways; the wide tables scroll inside their
|
|
own box instead, and there they get the full page height to do it. */
|
|
@media (max-width:900px){
|
|
.wrap{ padding:var(--s4) var(--s3) 60px; }
|
|
.card{ padding:var(--s3) var(--s4) var(--s4); }
|
|
.toolbar > input{ flex:1 1 100%; }
|
|
.tscroll{ max-height:none; }
|
|
}
|
|
@media (max-width:620px){
|
|
.urow input, .urow select, .urow button{ flex:1 1 100%; }
|
|
}
|