diff --git a/app/src/components/ThemeSamplePage.js b/app/src/components/ThemeSamplePage.js
index 1b0e10f3..40e55625 100644
--- a/app/src/components/ThemeSamplePage.js
+++ b/app/src/components/ThemeSamplePage.js
@@ -355,8 +355,9 @@ export function ThemeSamplePage() {
Light and dark spend a colour on each. Night and amber have only one hue,
so a role is a step on a brightness ramp instead; that is why an error and
an info toast used to be the same pixel there. Severity climbs in the order
- shown for those two themes, and danger is never quieter than
- ordinary text.
+ shown for those two themes, and both warning and{' '}
+ danger are brighter than ordinary text — with no hue to carry
+ "look at this", brighter is the only thing left.
diff --git a/app/src/components/ui/ui-layout.cy.js b/app/src/components/ui/ui-layout.cy.js
index 340ac4e9..35175ca6 100644
--- a/app/src/components/ui/ui-layout.cy.js
+++ b/app/src/components/ui/ui-layout.cy.js
@@ -298,19 +298,26 @@ describe('semantic roles read as severity in every theme', () => {
});
});
- it(`makes danger at least as loud as ordinary text in ${theme}`, () => {
+ it(`makes warning and danger louder than ordinary text in ${theme}`, () => {
/*
- * Also only here. A light theme's text is near-black at ~14:1 and no danger
- * colour will ever match it; on a single hue the roles and the text are drawn
- * from the same ramp, so the loudest role must not be quieter than the prose.
+ * Only here. A light theme's text is near-black at ~14:1 and no warning colour
+ * will ever match it -- there, hue is what marks a reading as flagged. On a
+ * single hue the roles and the text come off the same ramp, so anything meaning
+ * "look at this" has to outrank the prose or it does not read as flagged at all.
+ *
+ * This is the assertion the Status page needed: an uncoloured load reading
+ * inherits `--text`, and warning used to sit just below it.
*/
cy.mountUI(roles, {theme});
cy.get('.wrolpi-panel').should(() => {
const {panel, text, roles} = roleColours();
- const danger = roles.find(r => r.role === 'danger').colour;
- expect(contrast(danger, panel), 'danger vs --text against the panel')
- .to.be.at.least(contrast(text, panel) * 0.95);
+ const prose = contrast(text, panel);
+ ['warning', 'danger'].forEach((name) => {
+ const role = roles.find(r => r.role === name).colour;
+ expect(contrast(role, panel), `${name} against --text on the panel`)
+ .to.be.greaterThan(prose);
+ });
});
});
});
@@ -366,23 +373,15 @@ describe('a load reading ranks itself in the monochrome themes', () => {
Cypress.$('.wrolpi-panel')[0]).backgroundColor);
expect(new Set([fine, warning, danger]).size, 'three distinct readings').to.equal(3);
+ /*
+ * Both flagged readings outrank a plain one. This is what the ramp change
+ * bought: warning used to sit just UNDER `--text`, so a machine under load
+ * rendered marginally quieter than a healthy one.
+ */
+ expect(contrast(warning, panel), 'warning is louder than a plain reading')
+ .to.be.greaterThan(contrast(fine, panel));
expect(contrast(danger, panel), 'danger is louder than warning')
.to.be.greaterThan(contrast(warning, panel));
- expect(contrast(danger, panel), 'danger is louder than a plain reading')
- .to.be.greaterThan(contrast(fine, panel));
-
- /*
- * NOT asserted: that warning outranks a plain reading. It does not, and that
- * is a live question rather than an oversight -- an uncoloured value inherits
- * `--text`, which in night is 4.98:1 against 4.91:1 for `--warning`. So a
- * machine under load is marginally QUIETER than one that is fine.
- *
- * Lifting warning above text is a palette change, not a call-site one: on a
- * dark panel the only way up is lightness, and night's danger would desaturate
- * from #ff3e3e to about #ff5d5d -- trading the theme's "red only" character
- * for loudness. Worth a deliberate decision, so it is flagged rather than
- * quietly made here.
- */
});
});
});
diff --git a/app/src/themes/tokens.css b/app/src/themes/tokens.css
index ac2597cb..bd346f95 100644
--- a/app/src/themes/tokens.css
+++ b/app/src/themes/tokens.css
@@ -80,8 +80,18 @@ html[data-theme="light"] {
* In the MONOCHROME themes only (night and amber):
* - the order neutral < info < success < warning < danger is strictly increasing in
* contrast against the panel, so severity reads as brightness with no hue to help;
- * - danger reaches that theme's own `--text` brightness, so the loudest role is never
- * quieter than ordinary prose.
+ * - BOTH warning and danger reach that theme's own `--text` brightness. Anything that
+ * means "look at this" has to be louder than the prose around it, and with no hue to
+ * carry the signal, louder means brighter. Warning used to sit just under `--text`
+ * (4.91 against 4.98 in night), so a machine under load rendered marginally quieter
+ * than a healthy one.
+ *
+ * Getting warning and danger above `--text` costs a little saturation, and it is worth
+ * knowing exactly how little: red contributes only 21% of luminance, so in night nothing
+ * above ~4.9:1 can be a pure hue -- `#ff0000` itself is only 4.99:1 there. `--text` is
+ * already `#e04a4a`, carrying 74 of green and blue. The new `--warning` `#f54040` carries
+ * 64, LESS than the text beside it; only `--danger` `#ff5757` goes further, at 87. The
+ * theme's red-only character survives; a pure-hue ramp was never available.
*
* Those last two are NOT true of light and dark and must not be made true. There a role
* is a hue, and the contrast order is an accident of which hues were chosen -- blue is
@@ -174,8 +184,8 @@ html[data-theme="night"] {
--neutral: #992c2c;
--info: #c02929;
--success: #e02323;
- --warning: #ee3434;
- --danger: #ff3e3e;
+ --warning: #f54040;
+ --danger: #ff5757;
}
/* Amber: a monochrome amber terminal palette, same flat style as the rest. */
@@ -215,8 +225,8 @@ html[data-theme="amber"] {
--neutral: #815825;
--info: #b06e1f;
--success: #d37c11;
- --warning: #f18806;
- --danger: #ff9e29;
+ --warning: #fa9f31;
+ --danger: #ffb760;
}
/* ------------------------------------------------------------------------- */