@motir/design-system 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -10
- package/dist/components/theme/StyleVignette.js +24 -4
- package/dist/components/theme/StyleVignette.js.map +1 -1
- package/dist/components/ui/Checkbox.d.ts +84 -0
- package/dist/components/ui/Checkbox.js +70 -0
- package/dist/components/ui/Checkbox.js.map +1 -0
- package/dist/components/ui/Combobox.d.ts +7 -1
- package/dist/components/ui/Combobox.js +21 -3
- package/dist/components/ui/Combobox.js.map +1 -1
- package/dist/components/ui/ErrorState.js +1 -1
- package/dist/components/ui/ErrorState.js.map +1 -1
- package/dist/components/ui/Input.d.ts +33 -0
- package/dist/components/ui/Input.js +17 -6
- package/dist/components/ui/Input.js.map +1 -1
- package/dist/components/ui/MultiSelectPicker.js +1 -1
- package/dist/components/ui/MultiSelectPicker.js.map +1 -1
- package/dist/components/ui/Pill.d.ts +7 -4
- package/dist/components/ui/Pill.js +21 -1
- package/dist/components/ui/Pill.js.map +1 -1
- package/dist/components/ui/Segmented.js +22 -3
- package/dist/components/ui/Segmented.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/specimen/TokensSpecimen.js +41 -10
- package/dist/specimen/TokensSpecimen.js.map +1 -1
- package/package.json +7 -2
- package/theme.css +753 -48
package/theme.css
CHANGED
|
@@ -290,7 +290,24 @@
|
|
|
290
290
|
(<html>) is dark — the symmetric counterpart to [data-theme='dark'], mirroring
|
|
291
291
|
how [data-palette]/[data-style]/[data-type] already re-skin a subtree. The
|
|
292
292
|
onboarding design step (MOTIR-1040) uses it to preview the user's project in
|
|
293
|
-
light regardless of Motir's own theme. Values mirror the @theme light base.
|
|
293
|
+
light regardless of Motir's own theme. Values mirror the @theme light base.
|
|
294
|
+
|
|
295
|
+
⚠️ On a NESTED element this block is only HALF the mechanism (MOTIR-2077).
|
|
296
|
+
`--el-*` are declared `--el-x: var(--color-y)` and var() substitutes where the
|
|
297
|
+
property is DECLARED, so re-asserting Tier-0 here cannot retroactively change
|
|
298
|
+
the `--el-*` a component reads — those resolved at :root and merely inherit
|
|
299
|
+
down. Pair this with `data-appearance-scope` on the same element (below), which
|
|
300
|
+
re-emits the Tier-3 layer locally so its var()s see these overrides. That
|
|
301
|
+
attribute is axis-agnostic — a nested [data-palette]/[data-style] needs it too
|
|
302
|
+
— which is why light has no duplicated `--el-*` companion block the way dark
|
|
303
|
+
does; dark's exists only for its two concrete-hex tokens, not to scope a
|
|
304
|
+
subtree.
|
|
305
|
+
|
|
306
|
+
⚠️ KEEP AT PARITY with [data-theme='dark'] above. A Tier-0 token dark declares
|
|
307
|
+
and this block omits keeps its DARK value in a forced-light subtree no matter
|
|
308
|
+
what scopes it: with nothing local to shadow it, the inherited value stands.
|
|
309
|
+
That was MOTIR-2077's defect (`--color-canvas`, added below).
|
|
310
|
+
tests/theme/forcedThemeSubtree.test.ts asserts the parity both ways. */
|
|
294
311
|
[data-theme='light'] {
|
|
295
312
|
color-scheme: light;
|
|
296
313
|
|
|
@@ -298,6 +315,7 @@
|
|
|
298
315
|
--color-foreground: #1a1a1a;
|
|
299
316
|
--color-surface: #f6f5f4;
|
|
300
317
|
--color-surface-soft: #fafaf9;
|
|
318
|
+
--color-canvas: #ecebe7; /* recessed board behind raised cards (planning canvas) */
|
|
301
319
|
|
|
302
320
|
--color-ink: #1a1a1a;
|
|
303
321
|
--color-charcoal: #37352f;
|
|
@@ -1213,15 +1231,22 @@
|
|
|
1213
1231
|
inset 0 1px 0 0 rgba(255, 255, 255, 0.55),
|
|
1214
1232
|
0 1px 3px rgba(15, 15, 15, 0.08),
|
|
1215
1233
|
0 8px 18px -8px rgba(15, 15, 15, 0.22);
|
|
1216
|
-
/* The column is `h-[calc(100dvh-
|
|
1217
|
-
the `overflow-x-auto` row that
|
|
1218
|
-
rounded BOTTOM corner + its drop
|
|
1219
|
-
and get sheared flat (the reported
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1234
|
+
/* The column is `h-[calc(100dvh - 10.5rem - var(--shell-bottom-clearance))]` —
|
|
1235
|
+
sized to fill the board area. In the `overflow-x-auto` row that
|
|
1236
|
+
exactly-filling height means the column's rounded BOTTOM corner + its drop
|
|
1237
|
+
shadow sit at the overflow-clip boundary and get sheared flat (the reported
|
|
1238
|
+
"sharp bottom corner"). Trim the height by a further 2.5rem so the rounded
|
|
1239
|
+
corner + shadow clear the clip and the column reads as a fully-rounded
|
|
1240
|
+
floating card. Also clip the column's OWN children to its radius so a flush
|
|
1241
|
+
inner surface can't square a corner — the board cards pop on hover but the
|
|
1242
|
+
DragOverlay clone is portaled, so nothing 3D is lost.
|
|
1243
|
+
|
|
1244
|
+
⚠️ This tracks BoardColumn's height and must keep spending the same
|
|
1245
|
+
`--shell-bottom-clearance` the shell sets (MOTIR-2763), not a flat number:
|
|
1246
|
+
a stylesheet cannot read the `showPlanWithAi` prop, so the custom property
|
|
1247
|
+
is the only way this stays conditional on the orb actually mounting. The
|
|
1248
|
+
13rem below is 10.5rem of chrome + this style's own 2.5rem trim. */
|
|
1249
|
+
height: calc(100dvh - 13rem - var(--shell-bottom-clearance, 1.5rem));
|
|
1225
1250
|
overflow: hidden;
|
|
1226
1251
|
}
|
|
1227
1252
|
[data-style='3d-immersive'] [data-board-scroll] {
|
|
@@ -1230,26 +1255,84 @@
|
|
|
1230
1255
|
padding-top: 0.25rem;
|
|
1231
1256
|
}
|
|
1232
1257
|
|
|
1233
|
-
/* ── 3D / Immersive —
|
|
1258
|
+
/* ── 3D / Immersive — CONTROL DEPTH: every control sits on a named plane ────
|
|
1234
1259
|
In a 3D design a button is not flat: it has visible THICKNESS (a solid base
|
|
1235
1260
|
edge) and presses DOWN onto it on click (translateY + the base compresses) —
|
|
1236
|
-
the standard 3D/skeuomorphic button.
|
|
1237
|
-
the
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1261
|
+
the standard 3D/skeuomorphic button. §4's plane ladder in
|
|
1262
|
+
docs/styles/3d-immersive.md is the spec; this block is its implementation.
|
|
1263
|
+
|
|
1264
|
+
⚠️ THE ROLE DECIDES THE PLANE, AND A RADIUS UTILITY DOES NOT CARRY THE ROLE
|
|
1265
|
+
(MOTIR-3522). This rule used to match `.rounded-(--radius-btn)` alone, on the
|
|
1266
|
+
reasoning that the button radius identifies a button. It does not: the app
|
|
1267
|
+
emits SEVEN radius utilities on interactive tags, and each of the other six
|
|
1268
|
+
mixes families that want opposite treatments —
|
|
1269
|
+
|
|
1270
|
+
`--radius-badge` is worn by 3 hero action buttons (Plan with AI, Re-plan,
|
|
1271
|
+
the build-in-public link) AND by 9 filter/tag chips and segmented tabs,
|
|
1272
|
+
which §4 says stay flat pills;
|
|
1273
|
+
`--radius-control` is worn by ~63 square icon buttons (real keys) AND by
|
|
1274
|
+
~51 menu / option / full-width list rows AND by inline text
|
|
1275
|
+
affordances that only ever wanted a focus ring;
|
|
1276
|
+
`rounded-full` is worn by the Plan-with-AI orb (a key) AND by two Switch
|
|
1277
|
+
tracks, a colour swatch, an avatar and a tag remove-×.
|
|
1278
|
+
|
|
1279
|
+
So widening the old rule by radius would have raised switches, swatches,
|
|
1280
|
+
avatars and chips. Depth is keyed on the ROLE instead, which reaches the
|
|
1281
|
+
element two ways:
|
|
1282
|
+
|
|
1283
|
+
1. `data-depth` — the EXPLICIT hook, and the one to reach for. `key` puts a
|
|
1284
|
+
control on the raised plane, `flat` takes it off. Emitted by the
|
|
1285
|
+
primitives that know their own role and set by hand on the handful of
|
|
1286
|
+
hand-rolled controls the default below gets wrong.
|
|
1287
|
+
2. a RADIUS DEFAULT for the un-annotated majority, chosen so the default is
|
|
1288
|
+
SAFE: the button radii and the square icon-button shape are keys;
|
|
1289
|
+
everything else interactive is QUIET (flat at rest, but it still
|
|
1290
|
+
presses). A control that should be raised and is not looks understated;
|
|
1291
|
+
one raised that should not be looks broken.
|
|
1292
|
+
|
|
1293
|
+
`tests/theme/immersive-control-depth.test.ts` enumerates the radius utilities
|
|
1294
|
+
the codebase actually emits on interactive tags and fails when one has no
|
|
1295
|
+
classification here — the promise is bound to class names, so something has
|
|
1296
|
+
to break when a new control class appears.
|
|
1297
|
+
|
|
1298
|
+
The GLOBAL baseline edge is a neutral `--el-border-strong` (it suits the
|
|
1299
|
+
outline/toolbar buttons); FILLED variants override it with a colour-matched
|
|
1300
|
+
edge (primary → `--el-accent-pressed`, danger → a darkened `--el-danger` —
|
|
1301
|
+
palette-derived, so the axes stay disjoint); ghost stays flat (the quiet
|
|
1302
|
+
button). box-shadow is not a colour-painting property, so the material-rule
|
|
1303
|
+
test skips these. The press overrides the base `active:scale` with a more
|
|
1304
|
+
physical translateY.
|
|
1305
|
+
|
|
1306
|
+
⚠️ SPECIFICITY: the key set is wrapped in `:where()` so it contributes
|
|
1307
|
+
NOTHING beyond the `[data-style]` attribute (0,1,0). That is deliberate — the
|
|
1308
|
+
`[data-variant]` overrides below are (0,2,0) and the flat overrides after
|
|
1309
|
+
them are (0,2,0), so both still win. Adding a plain `:is()` here silently
|
|
1310
|
+
inverts that. */
|
|
1311
|
+
|
|
1312
|
+
/* THE KEY SET — controls that carry real thickness.
|
|
1313
|
+
`button.rounded-(--radius-input)` catches DROPDOWN-TRIGGER buttons styled as
|
|
1314
|
+
an input (the board switcher, combobox / picker triggers) — scoped to
|
|
1315
|
+
`button` so a real <input>/<textarea> text field (same radius) is NEVER
|
|
1316
|
+
raised; it is RECESSED instead, below.
|
|
1317
|
+
The `.justify-center` limb is the square icon-button shape: a centred control
|
|
1318
|
+
on the control radius is a key (the 3-dots trigger, the fullscreen toggle,
|
|
1319
|
+
every close ×). A row is never centred — it is `w-full` and `text-left`. */
|
|
1320
|
+
[data-style='3d-immersive']
|
|
1321
|
+
:where(
|
|
1322
|
+
.rounded-\(--radius-btn\),
|
|
1323
|
+
button.rounded-\(--radius-input\),
|
|
1324
|
+
:is(button, a).rounded-\(--radius-control\).justify-center,
|
|
1325
|
+
[data-depth='key']
|
|
1326
|
+
):not(
|
|
1327
|
+
:where(
|
|
1328
|
+
[role='switch'],
|
|
1329
|
+
[role='radio'],
|
|
1330
|
+
[role='checkbox'],
|
|
1331
|
+
[role='menuitem'],
|
|
1332
|
+
[role='option'],
|
|
1333
|
+
[data-depth='flat']
|
|
1334
|
+
)
|
|
1335
|
+
) {
|
|
1253
1336
|
box-shadow:
|
|
1254
1337
|
0 3px 0 0 var(--el-border-strong),
|
|
1255
1338
|
0 5px 10px -3px rgba(15, 15, 15, 0.18);
|
|
@@ -1272,10 +1355,37 @@
|
|
|
1272
1355
|
[data-style='3d-immersive'] [data-variant='ghost'] {
|
|
1273
1356
|
box-shadow: none;
|
|
1274
1357
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1358
|
+
|
|
1359
|
+
/* THE FLAT SET — rows, chips and switches, which §4 keeps on their parent's
|
|
1360
|
+
plane. These come AFTER the key set and carry (0,2,0), so they win over its
|
|
1361
|
+
(0,1,0) wherever the two overlap (a centred control inside an open menu, a
|
|
1362
|
+
`data-depth='flat'` icon button). A menu row raised inside an already-floating
|
|
1363
|
+
popover reads as debris, not depth — the overlay is the thing that floats. */
|
|
1364
|
+
[data-style='3d-immersive']
|
|
1365
|
+
:is(
|
|
1366
|
+
[role='menuitem'],
|
|
1367
|
+
[role='option'],
|
|
1368
|
+
[role='menuitemcheckbox'],
|
|
1369
|
+
[role='menuitemradio'],
|
|
1370
|
+
[role='switch'],
|
|
1371
|
+
[data-depth='flat']
|
|
1372
|
+
),
|
|
1373
|
+
[data-style='3d-immersive']
|
|
1374
|
+
:is([data-surface='popover'], [data-menu-surface])
|
|
1375
|
+
:is(button, a).rounded-\(--radius-control\),
|
|
1376
|
+
[data-style='3d-immersive'] :is(button, a).w-full.rounded-\(--radius-control\) {
|
|
1377
|
+
box-shadow: none;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
/* THE PRESS — the raised set drops by its thickness and the base edge
|
|
1381
|
+
compresses, like a real key. Overrides the base `active:scale`. */
|
|
1382
|
+
[data-style='3d-immersive']
|
|
1383
|
+
:where(
|
|
1384
|
+
.rounded-\(--radius-btn\),
|
|
1385
|
+
button.rounded-\(--radius-input\),
|
|
1386
|
+
:is(button, a).rounded-\(--radius-control\).justify-center,
|
|
1387
|
+
[data-depth='key']
|
|
1388
|
+
):active:not(:disabled) {
|
|
1279
1389
|
transform: translateY(3px);
|
|
1280
1390
|
box-shadow:
|
|
1281
1391
|
0 1px 0 0 var(--el-border-strong),
|
|
@@ -1295,6 +1405,67 @@
|
|
|
1295
1405
|
box-shadow: none;
|
|
1296
1406
|
}
|
|
1297
1407
|
|
|
1408
|
+
/* THE QUIET PRESS — a control with no resting thickness still has to answer the
|
|
1409
|
+
pointer, or the style reads as flat wherever it is not a key: menu rows, list
|
|
1410
|
+
rows, nav links, inline affordances, the ghost button. One pixel of travel is
|
|
1411
|
+
the whole treatment; it is what separates "quiet" from "inert". */
|
|
1412
|
+
[data-style='3d-immersive']
|
|
1413
|
+
:where(:is(button, a).rounded-\(--radius-control\), [data-variant='ghost']):active:not(
|
|
1414
|
+
:disabled
|
|
1415
|
+
) {
|
|
1416
|
+
transform: translateY(1px);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
/* THE RECESSED SET — text fields are pressed INTO the surface, not raised off
|
|
1420
|
+
it. §4's "on the face" left them with a 1px border and no depth at all on a
|
|
1421
|
+
page where every panel carries a four-layer float, which is the other half of
|
|
1422
|
+
what MOTIR-3522 reported (the roadmap's search box). A raised text field is
|
|
1423
|
+
wrong — you type into a well — so this is the inverse of the key treatment,
|
|
1424
|
+
not a copy of it. `[data-surface='input']` is the Input primitive's shell;
|
|
1425
|
+
the bare element selectors catch the hand-rolled fields. Checkbox and radio
|
|
1426
|
+
are excluded: they are chips, not wells. */
|
|
1427
|
+
[data-style='3d-immersive']
|
|
1428
|
+
:where(
|
|
1429
|
+
[data-surface='input'],
|
|
1430
|
+
input:not([type='checkbox'], [type='radio'], [type='range'], [type='color']),
|
|
1431
|
+
textarea,
|
|
1432
|
+
select
|
|
1433
|
+
) {
|
|
1434
|
+
box-shadow:
|
|
1435
|
+
inset 0 2px 6px -2px rgba(15, 15, 15, 0.26),
|
|
1436
|
+
inset 0 1px 2px 0 rgba(15, 15, 15, 0.05);
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/* Hero controls paint their own shadow in an INLINE style, which beats every
|
|
1440
|
+
rule above — an inline declaration is not something a style layer can reach.
|
|
1441
|
+
So the two of them read their shadow from a variable instead, with the base
|
|
1442
|
+
look as the `var()` fallback, and this is where the key's base edge is added
|
|
1443
|
+
to it. Palette-derived throughout; the colour axis stays disjoint.
|
|
1444
|
+
Consumed by components/planning/PlanWithAILauncher.tsx (--plan-hero-shadow)
|
|
1445
|
+
and components/planning/PlanWithAIFab.tsx (--plan-orb-shadow).
|
|
1446
|
+
|
|
1447
|
+
⚠️ ON `body`, NOT ON THE BARE `[data-style]` TOKEN BLOCK. Both values READ
|
|
1448
|
+
`--el-*`, and `tests/theme/styleRegistry.test.ts` holds a bare token block to
|
|
1449
|
+
the colour/style axis split — a `[data-style='…'] { … }` block may set only
|
|
1450
|
+
shape/feel tokens, never anything naming a palette token, and
|
|
1451
|
+
`tests/theme/shapeSwapLint.test.ts` additionally requires such a block to
|
|
1452
|
+
override every shape role. A descendant rule is neither, which is where the
|
|
1453
|
+
immersive background (which reads `--el-*` for the same reason) already
|
|
1454
|
+
lives. Custom properties inherit, so every control below `body` sees these. */
|
|
1455
|
+
[data-style='3d-immersive'] body {
|
|
1456
|
+
--plan-hero-shadow:
|
|
1457
|
+
0 4px 0 0 var(--el-accent-pressed),
|
|
1458
|
+
inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 38%, transparent),
|
|
1459
|
+
inset 0 0 0 1px color-mix(in srgb, var(--el-accent-text) 18%, transparent),
|
|
1460
|
+
0 9px 18px -5px color-mix(in srgb, var(--el-accent) 75%, transparent),
|
|
1461
|
+
0 0 22px -3px color-mix(in srgb, var(--el-highlight) 50%, transparent);
|
|
1462
|
+
--plan-orb-shadow:
|
|
1463
|
+
0 5px 0 0 var(--el-accent-pressed),
|
|
1464
|
+
inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 40%, transparent),
|
|
1465
|
+
0 12px 24px -6px color-mix(in srgb, var(--el-accent) 80%, transparent),
|
|
1466
|
+
0 0 28px -2px color-mix(in srgb, var(--el-highlight) 55%, transparent);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1298
1469
|
/* ── 3D / Immersive — DROPDOWNS / POPOVERS / MENUS unfold in 3D ──────────────
|
|
1299
1470
|
A flat fade-in is the "still not 3D" tell on overlays. The standard 3D
|
|
1300
1471
|
dropdown UNFOLDS: it swings open from its top edge over a perspective
|
|
@@ -2226,17 +2397,31 @@
|
|
|
2226
2397
|
/* ── Text scale (the warm-charcoal hierarchy, named by ROLE) ────── */
|
|
2227
2398
|
--el-text: var(--color-foreground); /* primary ink */
|
|
2228
2399
|
--el-text-strong: var(--color-charcoal); /* emphasis / AA-safe text on tints */
|
|
2229
|
-
--el-text-secondary: var(--color-slate); /* secondary copy */
|
|
2400
|
+
--el-text-secondary: var(--color-slate); /* secondary copy — AA on EVERY surface */
|
|
2401
|
+
/* ⚠️ AA-SAFE ONLY ON THE WHITE PAGE/CARD, and by 0.04 (4.54:1). On
|
|
2402
|
+
--el-surface it is 4.17, on --el-muted 4.12, on --el-surface-soft 4.34 —
|
|
2403
|
+
all under AA. A muted caption belongs inside a card, never on a panel.
|
|
2404
|
+
(MOTIR-2455; light theme is the binding one — every ink clears AA on dark.) */
|
|
2230
2405
|
--el-text-muted: var(--color-muted-foreground); /* muted / captions */
|
|
2231
2406
|
--el-text-tertiary: var(--color-steel); /* tertiary / footers */
|
|
2232
|
-
|
|
2407
|
+
/* ⚠️ NEVER CARRIES TEXT WCAG MEASURES — 2.37–2.82:1 on every surface in BOTH
|
|
2408
|
+
themes, so there is no context in which it passes. It is for DECORATIVE
|
|
2409
|
+
glyphs (aria-hidden, or a role="img" whose label carries the meaning) and
|
|
2410
|
+
for DISABLED / inactive text, which WCAG 1.4.3 exempts. Active
|
|
2411
|
+
informational text takes --el-text-secondary. (MOTIR-2455) */
|
|
2412
|
+
--el-text-faint: var(--color-stone); /* faint labels — decoration + disabled ONLY */
|
|
2233
2413
|
--el-text-inverted: var(--color-background); /* text on an ink / accent fill */
|
|
2234
2414
|
|
|
2235
2415
|
/* ── Accent (active CTA identity) + brand highlight ─────────────── */
|
|
2236
2416
|
/* --el-accent is the FILL behind --el-accent-text (white): filled buttons,
|
|
2237
2417
|
badges, toggles. --el-accent-on-surface is the accent used AS text/icon on
|
|
2238
2418
|
a page surface. They diverge in dark theme (fill darkens for white-text AA;
|
|
2239
|
-
text stays brand-bright for AA on the near-black canvas) — MOTIR-757.
|
|
2419
|
+
text stays brand-bright for AA on the near-black canvas) — MOTIR-757.
|
|
2420
|
+
⚠️ --el-accent-on-surface is OVERRIDDEN in the [data-theme='dark'] block
|
|
2421
|
+
further down: brand-bright-on-the-canvas is not the same claim as AA on the
|
|
2422
|
+
tinted surfaces that sit above it, and the ink was 4.24-4.41:1 on all three
|
|
2423
|
+
for as long as the dark theme has shipped (MOTIR-3745). The light
|
|
2424
|
+
declaration below is unchanged and is what the Tier-0-alias guards read. */
|
|
2240
2425
|
--el-accent: var(--color-primary-fill);
|
|
2241
2426
|
--el-accent-text: var(--color-primary-foreground);
|
|
2242
2427
|
--el-accent-on-surface: var(--color-primary);
|
|
@@ -2260,8 +2445,32 @@
|
|
|
2260
2445
|
--el-link-pressed: var(--color-link-pressed);
|
|
2261
2446
|
|
|
2262
2447
|
/* ── Semantic status ───────────────────────────────────────────── */
|
|
2448
|
+
/* THREE danger tokens, and the middle one is the trap (MOTIR-3663).
|
|
2449
|
+
--el-danger is the FILL. --el-danger-text is the ink FOR that fill, so it
|
|
2450
|
+
is legal ONLY on an element that also carries bg-(--el-danger) — the
|
|
2451
|
+
Button danger variant, and nothing else. Painted on a page instead it is
|
|
2452
|
+
1.00:1 in the light theme of ALL TEN palettes (the ink and the page are
|
|
2453
|
+
the same white) and 1.00:1 in six of the ten dark ones; in the other four
|
|
2454
|
+
it renders near-white, indistinguishable from --el-text, so the DANGER
|
|
2455
|
+
SIGNAL is lost rather than the text. Both halves are the same defect, and
|
|
2456
|
+
`tests/theme/inkContrastLint.test.ts`'s danger arm now holds the rule at
|
|
2457
|
+
zero over the same four roots.
|
|
2458
|
+
--el-danger-on-surface is the ink for danger text ON a page: the palette's
|
|
2459
|
+
own danger hue pulled 30% toward that theme's body ink, which is the
|
|
2460
|
+
smallest move that clears AA everywhere. Raw --el-danger does NOT — it is
|
|
2461
|
+
4.25:1 (base), 4.11:1 (cobalt) and 4.24:1 (graphite) on the DARK page, and
|
|
2462
|
+
under 4.5 on most tints in both themes.
|
|
2463
|
+
DERIVED rather than listed, deliberately: both inputs are tokens, so it
|
|
2464
|
+
re-skins with data-palette and a new palette is covered on the day it is
|
|
2465
|
+
added instead of the day somebody remembers to extend a table. Measured
|
|
2466
|
+
across all 20 palette x theme combinations against page/card, --el-surface,
|
|
2467
|
+
--el-surface-soft, --el-muted, --el-tint-rose and --el-danger-surface, the
|
|
2468
|
+
worst pair is 4.77:1 and it stays perceptually red (deltaE 6.8-14.6 from
|
|
2469
|
+
the base hue, 23.8-39.2 from the body ink). The table is asserted, not
|
|
2470
|
+
asserted-once: inkContrastLint recomputes it from this file. */
|
|
2263
2471
|
--el-danger: var(--color-destructive);
|
|
2264
2472
|
--el-danger-text: var(--color-destructive-foreground);
|
|
2473
|
+
--el-danger-on-surface: color-mix(in srgb, var(--el-danger) 70%, var(--el-text));
|
|
2265
2474
|
--el-success: var(--color-success);
|
|
2266
2475
|
--el-warning: var(--color-warning);
|
|
2267
2476
|
--el-info: var(--color-info);
|
|
@@ -2288,6 +2497,27 @@
|
|
|
2288
2497
|
lib/workflows/defaultWorkflow.ts. */
|
|
2289
2498
|
--el-status-todo: var(--color-stone); /* neutral grey — not started */
|
|
2290
2499
|
--el-status-in-progress: var(--color-info); /* blue — active */
|
|
2500
|
+
--el-status-planning: var(--color-accent-teal); /* teal — being RE-PLANNED, not being worked */
|
|
2501
|
+
/* BUILT, waiting on checks (MOTIR-3003) — a DESATURATED In Review, and the
|
|
2502
|
+
mix is the meaning: this card is what In Review will be once CI says so, and
|
|
2503
|
+
has not earned the brand hue yet. Both inputs are palette-tuned status
|
|
2504
|
+
tokens, so it needs no per-palette block and it TRACKS a palette that moves
|
|
2505
|
+
`in_review` — measured at ΔE2000 >= 10 against every other status in all ten
|
|
2506
|
+
palettes x both themes (tests/theme/statusHueSeparation.test.ts).
|
|
2507
|
+
⚠️ It is NOT --color-accent, which `design/boards/implemented-column.mock.html`
|
|
2508
|
+
originally specified: that reads clean in the base palette and collides in
|
|
2509
|
+
five of the ten (amber/candy/citrine/graphite/sienna, ΔE as low as 0.0). The
|
|
2510
|
+
asset carries the correction and the measurement. */
|
|
2511
|
+
/* pink — BUILT, waiting on checks (MOTIR-3003). The one saturated Tier-0 hue
|
|
2512
|
+
no other STATUS spends; sharing a hue across FAMILIES is this file's own
|
|
2513
|
+
convention (--el-type-epic is also --color-accent). ΔE 33.2 / 26.2 from its
|
|
2514
|
+
nearest neighbour in this palette.
|
|
2515
|
+
⚠️ FIVE palettes re-map --color-accent onto something a status already uses,
|
|
2516
|
+
so each carries its own override below — the same per-palette follow-up
|
|
2517
|
+
--el-status-planning needed in citrine and candy (MOTIR-2425). Measured by
|
|
2518
|
+
tests/theme/statusHueSeparation.test.ts, which now folds a color-mix rather
|
|
2519
|
+
than throwing on one. */
|
|
2520
|
+
--el-status-implemented: var(--color-accent);
|
|
2291
2521
|
--el-status-in-review: var(--color-primary); /* brand — differentiate from in-progress */
|
|
2292
2522
|
--el-status-done: var(--color-success); /* green — resolved */
|
|
2293
2523
|
--el-status-blocked: var(--color-warning); /* amber — can't proceed (gap fixed) */
|
|
@@ -2341,6 +2571,9 @@
|
|
|
2341
2571
|
--el-role-admin: var(--color-tint-lavender);
|
|
2342
2572
|
--el-role-member: var(--color-tint-sky);
|
|
2343
2573
|
--el-role-viewer: var(--color-tint-mint);
|
|
2574
|
+
/* A project's OWN role (MOTIR-2485) — peach, the next free slot: the members
|
|
2575
|
+
surface had already spent lavender / sky / mint on the three built-ins. */
|
|
2576
|
+
--el-role-custom: var(--color-tint-peach);
|
|
2344
2577
|
--el-org-role-owner: var(--color-tint-lavender);
|
|
2345
2578
|
--el-org-role-admin: var(--color-tint-sky);
|
|
2346
2579
|
--el-org-role-member: var(--color-tint-mint);
|
|
@@ -2374,6 +2607,13 @@
|
|
|
2374
2607
|
--el-notif-commented: var(--color-info); /* was --el-type-task */
|
|
2375
2608
|
--el-notif-assigned: var(--color-accent-green); /* was --el-type-story */
|
|
2376
2609
|
--el-notif-transitioned: var(--color-accent-teal); /* was --el-type-subtask */
|
|
2610
|
+
/* The EXECUTOR badge on a Home row's assignee avatar (Story MOTIR-2649 ·
|
|
2611
|
+
Subtask MOTIR-2653, per design/home/design-notes.md §"The agent state").
|
|
2612
|
+
Same mapping form as --el-notif-mentioned above and for the same reason:
|
|
2613
|
+
it resolves to the accent fill today, but owning its own slot means a
|
|
2614
|
+
palette can move agent badges without dragging the CTA with them. The
|
|
2615
|
+
third pillar becoming visible is worth a token of its own. */
|
|
2616
|
+
--el-executor-agent: var(--color-primary-fill);
|
|
2377
2617
|
/* AI model dots (promote to a named family; deepseek was borrowing --el-type-subtask).
|
|
2378
2618
|
opus keeps the accent fill, same --color-primary-fill reasoning as mentioned. */
|
|
2379
2619
|
--el-model-opus: var(--color-primary-fill); /* the accent fill (matches prior --el-accent) */
|
|
@@ -2427,6 +2667,33 @@
|
|
|
2427
2667
|
--el-card: var(--color-background); /* untinted card surface — fixes the bg-card orphan */
|
|
2428
2668
|
--el-input-border: var(--color-hairline-strong); /* input outline (was --el-border-strong) */
|
|
2429
2669
|
--el-button-border: var(--color-hairline-strong); /* secondary-button outline */
|
|
2670
|
+
|
|
2671
|
+
/* ── Non-editable field states (MOTIR-2495) ──
|
|
2672
|
+
A field that cannot be typed into used to be drawn with `opacity-50` on the
|
|
2673
|
+
whole wrapper, which composites its CHILDREN — value, placeholder, and the
|
|
2674
|
+
`addonStart`/`addonEnd` affixes — against the page and roughly halves
|
|
2675
|
+
whatever contrast the palette guaranteed them. Contrast is a property of a
|
|
2676
|
+
PAIR (theme.css's own colour rule); opacity quietly makes it a property of
|
|
2677
|
+
a triple, so no ink choice can be checked and none can be fixed: the org
|
|
2678
|
+
URL's affix was already `--el-text-secondary`, the darkest caption ink, and
|
|
2679
|
+
still measured below AA. These four tokens express the two states as
|
|
2680
|
+
COLOUR instead, so every ink over them is AA-checkable and palette-swappable.
|
|
2681
|
+
Measured on the base palette, light (the binding theme; dark clears by more):
|
|
2682
|
+
disabled value/affix --color-slate on --color-muted = 6.18:1 ✓
|
|
2683
|
+
read-only value --color-foreground on --color-surface = 15.98:1 ✓
|
|
2684
|
+
read-only affix --color-slate on --color-surface = 6.24:1 ✓
|
|
2685
|
+
The DISABLED border is deliberately softer than the enabled one — the state
|
|
2686
|
+
reads through fill + ink + edge together, so it survives a surface-material
|
|
2687
|
+
style (glassmorphism repaints [data-surface='input'], and its rule outranks
|
|
2688
|
+
a utility class) that erases the fill alone. */
|
|
2689
|
+
--el-input-disabled-bg: var(--color-muted); /* disabled field fill (replaces opacity-50) */
|
|
2690
|
+
--el-input-disabled-border: var(--color-hairline); /* disabled field edge — softer than enabled */
|
|
2691
|
+
--el-input-disabled-text: var(
|
|
2692
|
+
--color-slate
|
|
2693
|
+
); /* disabled value/placeholder/affix ink — AA on the fill above */
|
|
2694
|
+
--el-input-readonly-bg: var(
|
|
2695
|
+
--color-surface
|
|
2696
|
+
); /* read-only field fill — not editable, but focusable + full ink */
|
|
2430
2697
|
--el-count-bg: var(--color-muted); /* count-badge fill (shipped value; see note above) */
|
|
2431
2698
|
--el-count-text: var(--color-slate); /* count-badge ink (was --el-text-secondary) */
|
|
2432
2699
|
|
|
@@ -2460,6 +2727,21 @@
|
|
|
2460
2727
|
--el-type-manual: var(--color-stone); /* stone — human provisioning */
|
|
2461
2728
|
--el-type-chore: var(--color-slate); /* slate — housekeeping */
|
|
2462
2729
|
|
|
2730
|
+
/* The four members ADR Amendment 1 (MOTIR-2629) admitted, per MOTIR-2631's
|
|
2731
|
+
design (design/work-items/design-notes.md, "Q2"). The block above spent
|
|
2732
|
+
ALL SEVEN mutually distinct saturated hues and all three greys at ten
|
|
2733
|
+
members, and there is no eighth — inventing one is forbidden. So each
|
|
2734
|
+
newcomer POINTS AT the Tier-0 hue of the member the amendment named as its
|
|
2735
|
+
NEAREST NEIGHBOUR, and the GLYPH carries the difference (the chip renders
|
|
2736
|
+
its label too, so hue was never the sole carrier — finding #35).
|
|
2737
|
+
Each keeps its OWN token so a future palette can split them without
|
|
2738
|
+
touching a component, and so WORK_ITEM_TYPE_META's per-member `hueVar`
|
|
2739
|
+
shape holds. Hue names the FAMILY; the glyph names the member. */
|
|
2740
|
+
--el-type-copy: var(--color-accent-teal); /* teal — with content (Author) */
|
|
2741
|
+
--el-type-translate: var(--color-accent-teal); /* teal — with content (Author) */
|
|
2742
|
+
--el-type-verification: var(--color-accent-orange); /* orange — with review (Investigate) */
|
|
2743
|
+
--el-type-legal: var(--color-charcoal); /* ink — with decision (Govern) */
|
|
2744
|
+
|
|
2463
2745
|
/* ── Chart series (Story 4.6 · the reusable viz Story 6.3 reuses) ──
|
|
2464
2746
|
Every chart colour routes through one of these, NEVER a raw --color-*
|
|
2465
2747
|
in chart code (the per-component growth pattern). They map to Tier-0
|
|
@@ -2537,8 +2819,14 @@
|
|
|
2537
2819
|
--el-diff-moved: var(--color-tint-sky);
|
|
2538
2820
|
--el-chat-bubble-user: var(--color-primary-fill); /* text stays --el-accent-text */
|
|
2539
2821
|
--el-chat-bubble-ai: var(--color-surface-soft); /* text stays --el-text */
|
|
2540
|
-
--el-canvas
|
|
2541
|
-
|
|
2822
|
+
/* Canvas dependency edges ride the RECESSED --el-canvas, not a raised surface, so
|
|
2823
|
+
they use INK tokens (--color-slate / -charcoal), NOT the hairline-on-a-card
|
|
2824
|
+
--color-border / -hairline-strong which are near-invisible there (~1.0-1.9:1 vs
|
|
2825
|
+
the canvas in every palette — MOTIR-1564). Ink clears WCAG 1.4.11 (≥3:1) on the
|
|
2826
|
+
canvas across all palettes/themes while still re-tinting per palette; solid vs
|
|
2827
|
+
dashed + the arrowhead marker carry the committed/pending distinction. */
|
|
2828
|
+
--el-canvas-edge-pending: var(--color-slate); /* dashed, not-yet-committed edge (quiet ink) */
|
|
2829
|
+
--el-canvas-edge-committed: var(--color-charcoal); /* solid, settled edge (emphasis ink) */
|
|
2542
2830
|
--el-station-tier-discovery: var(--color-tint-sky);
|
|
2543
2831
|
--el-station-tier-vision: var(--color-tint-lavender);
|
|
2544
2832
|
--el-station-tier-feasibility: var(--color-tint-mint);
|
|
@@ -2602,6 +2890,53 @@
|
|
|
2602
2890
|
one-shade-darker. */
|
|
2603
2891
|
[data-theme='dark'] {
|
|
2604
2892
|
--el-sidebar-item-bg-hover: #222222;
|
|
2893
|
+
/* THE DARK ACCENT INK (MOTIR-3745). Light keeps the plain
|
|
2894
|
+
var(--color-primary) alias declared in the Tier-3 block above, byte for
|
|
2895
|
+
byte — this is a DARK-ONLY lift, and deliberately so: the light accent
|
|
2896
|
+
already clears AA on every surface (6.29:1 on --el-surface-soft in the
|
|
2897
|
+
base palette), so there is nothing there to buy and a re-tint would cost
|
|
2898
|
+
the brand hue for no contrast.
|
|
2899
|
+
|
|
2900
|
+
What it fixes: the dark --color-primary was chosen for AA on the near-black
|
|
2901
|
+
CANVAS (#0f0f0f, 4.67:1 — see the Tier-1 comment at --color-primary, and
|
|
2902
|
+
MOTIR-757) and was never measured against anything else. Every tinted
|
|
2903
|
+
surface in dark sits ABOVE the canvas, so the ink arrives there with less
|
|
2904
|
+
contrast, not more: 4.24:1 on --el-surface / --el-muted (#1a1a1a) and
|
|
2905
|
+
4.41:1 on --el-surface-soft (#161616), across all sixteen --el-* aliases of
|
|
2906
|
+
those three fills. 13.5px semibold is not WCAG large text, so 1.4.3 asks
|
|
2907
|
+
4.5:1 and ExploreTopBar's current-page nav item missed it by 0.09 on
|
|
2908
|
+
/explore and /docs — both public, both reachable signed out.
|
|
2909
|
+
|
|
2910
|
+
Why the mix and not a hex: DERIVED from two tokens, exactly like
|
|
2911
|
+
--el-danger-on-surface above, so it re-skins with data-palette and an
|
|
2912
|
+
eleventh palette is covered the day it lands rather than the day somebody
|
|
2913
|
+
remembers a table.
|
|
2914
|
+
|
|
2915
|
+
Why 82%: it is sized against a WIDER set than the guard measures. On the
|
|
2916
|
+
surface vocabulary the accent arm asserts (the page white and the three
|
|
2917
|
+
greys, every alias) the worst dark pair at 82% is 5.53:1. The binding
|
|
2918
|
+
constraint is --el-tint-lavender — the accent family's own tint, which the
|
|
2919
|
+
arm does not measure but which the tree paints accent text on in ten files:
|
|
2920
|
+
84% is the largest primary share that clears it (4.57:1) and 82% is one
|
|
2921
|
+
2% step further, for headroom (4.68:1). MOTIR-3774 carries the LIGHT half
|
|
2922
|
+
of that pair, which no dark override can reach. Pulling further still would
|
|
2923
|
+
eventually cost the accent its signal rather than buy contrast, so the
|
|
2924
|
+
distance from --el-text is asserted too (22.6-54.5 deltaE, floor 10).
|
|
2925
|
+
|
|
2926
|
+
Why HERE and not on the Tier-3 alias: --el-accent-on-surface's light
|
|
2927
|
+
declaration is a load-bearing Tier-0 ALIAS. tests/theme/
|
|
2928
|
+
iconTextSurfaceTokens + interactionAgileTokens pin --el-icon-active and
|
|
2929
|
+
--el-tabnav-active as zero-change aliases OF it, and brand-tile-contrast
|
|
2930
|
+
resolves it to a --color-* by name. A dark-only override leaves all three
|
|
2931
|
+
reading the base declaration they were written about, and leaves
|
|
2932
|
+
--color-primary's eleven other Tier-3 consumers (plus --focus-ring-color)
|
|
2933
|
+
where they are — including --el-vote-active-bg, which is a FILL and would
|
|
2934
|
+
have LOST contrast against its white ink. Move the ink, not the fill
|
|
2935
|
+
(MOTIR-3664).
|
|
2936
|
+
|
|
2937
|
+
The table is asserted, not asserted-once: inkContrastLint's accent arm
|
|
2938
|
+
recomputes it from this file over every palette x theme. */
|
|
2939
|
+
--el-accent-on-surface: color-mix(in srgb, var(--color-primary) 82%, var(--el-text));
|
|
2605
2940
|
/* The modal scrim deepens in dark (MOTIR-1275 · 1266.4): on a near-black
|
|
2606
2941
|
canvas a 40% scrim barely separates the dialog, so dark uses ~65% — the
|
|
2607
2942
|
other concrete-hex --el-* alongside the sidebar hover. Light value (40%,
|
|
@@ -2609,6 +2944,83 @@
|
|
|
2609
2944
|
--el-overlay-scrim: #000000a6;
|
|
2610
2945
|
}
|
|
2611
2946
|
|
|
2947
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
2948
|
+
RECIPE KNOBS — the SCALARS a component's own colour recipe reads
|
|
2949
|
+
(MOTIR-3207)
|
|
2950
|
+
|
|
2951
|
+
Not part of the Tier-3 layer above and deliberately not named `--el-*`:
|
|
2952
|
+
that layer is a COLOUR contract (every member aliases a Tier-0 --color-*
|
|
2953
|
+
and is asserted palette-dependent by tests/theme/paletteTokenCoverage).
|
|
2954
|
+
A knob here is a NUMBER inside a color-mix() — one value for every
|
|
2955
|
+
palette and both themes — so it fails both halves of that contract while
|
|
2956
|
+
being exactly the thing that has to be expressed once.
|
|
2957
|
+
|
|
2958
|
+
Declared on a plain `:root` rule rather than in @theme so the property is
|
|
2959
|
+
emitted unconditionally: its only consumer is a `var()` inside a JS style
|
|
2960
|
+
object, which Tailwind's source scan has no reason to keep a theme
|
|
2961
|
+
variable alive for.
|
|
2962
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
2963
|
+
:root {
|
|
2964
|
+
/* THE ORB's lit-sphere highlight — how much --el-accent-text is mixed into
|
|
2965
|
+
--el-accent at the first stop of `PlanWithAIFab`'s radial gradient, which
|
|
2966
|
+
is the gradient's LIGHTEST point and therefore where the white glyph over
|
|
2967
|
+
it is closest to disappearing (design/ai-chat/design-notes.md § B).
|
|
2968
|
+
|
|
2969
|
+
26%, not the 32% that shipped, and ONE number rather than a per-theme
|
|
2970
|
+
pair. At 32% the glyph misses WCAG 1.4.11's 3:1 for a non-text graphic in
|
|
2971
|
+
FOUR of the twenty palette x theme contexts — default dark 2.78:1, cobalt
|
|
2972
|
+
dark 2.86:1, spectrum dark 3.00:1 (2.999, i.e. under the bar) and,
|
|
2973
|
+
contrary to the finding that filed this, evergreen LIGHT at 2.94:1. So
|
|
2974
|
+
"light has headroom" is a property of the DEFAULT PALETTE, not of light:
|
|
2975
|
+
a `[data-theme='dark']` override of this stop would have left evergreen's
|
|
2976
|
+
light orb failing. At 26% the worst context is 3.09:1 and all twenty
|
|
2977
|
+
clear the bar.
|
|
2978
|
+
|
|
2979
|
+
Mixing the glyph's own colour INTO its backdrop is monotonic — a larger
|
|
2980
|
+
number is always less contrast — so this is a CEILING, and lowering it
|
|
2981
|
+
further is always safe for legibility and only ever costs the lit look.
|
|
2982
|
+
tests/theme/orb-glyph-contrast.test.ts measures every context from these
|
|
2983
|
+
tokens and fails if a future palette or a raised knob crosses 3:1. */
|
|
2984
|
+
--orb-lit-mix: 26%;
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
2988
|
+
MOTION FLOOR — the reduced-motion guard the PACKAGE owns (MOTIR-3844)
|
|
2989
|
+
|
|
2990
|
+
Not an axis and not a tier: a floor every consumer of this stylesheet gets
|
|
2991
|
+
whichever palette, style or type it applies. The style axis already gates
|
|
2992
|
+
its OWN motion (the `aurora` canvas drift and the `3d-immersive` tilt /
|
|
2993
|
+
menu unfold, all `prefers-reduced-motion`-gated in their Tier-2 blocks
|
|
2994
|
+
above), because that motion is decorative and belongs to the style that
|
|
2995
|
+
introduced it. `animate-spin` belongs to no style: `Spinner` paints it on
|
|
2996
|
+
ordinary interactive surfaces, and `<Button loading>` substitutes a Spinner
|
|
2997
|
+
for the left icon — so it renders under every axis combination, and nothing
|
|
2998
|
+
guarded it. Tailwind v4 defines `--animate-spin: spin 1s linear infinite`
|
|
2999
|
+
with no media query anywhere near it, and neither consumer's `globals.css`
|
|
3000
|
+
carried an override.
|
|
3001
|
+
|
|
3002
|
+
STOP THE ROTATION, KEEP THE GLYPH. A spinner is not decoration a reader can
|
|
3003
|
+
do without — it is the only signal that a control is working — so this sets
|
|
3004
|
+
`animation` and nothing else: the ring keeps its size, its border and its
|
|
3005
|
+
`role="status"`, and a reader who asked for less motion still sees that
|
|
3006
|
+
something is in flight. (`motir-marketing`'s own `.motir-spin` reaches the
|
|
3007
|
+
same shape by hand, and pairs it with a label change — with the animation
|
|
3008
|
+
stilled, the word is the whole of the state. A consumer whose only motion
|
|
3009
|
+
cue is the rotation should do the same.)
|
|
3010
|
+
|
|
3011
|
+
WHY IT WINS THE CASCADE. `.animate-spin` is emitted by Tailwind inside
|
|
3012
|
+
`@layer utilities`; this rule is UNLAYERED, and an unlayered declaration
|
|
3013
|
+
outranks a layered one whatever their specificity. That is the whole of the
|
|
3014
|
+
mechanism — it does not depend on source order or on this file's position in
|
|
3015
|
+
the `@import` list. Measured, not reasoned: tests/theme/reducedMotionSpinner
|
|
3016
|
+
reads it back off the COMPILED stylesheet for both consumer shapes.
|
|
3017
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
3018
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3019
|
+
.animate-spin {
|
|
3020
|
+
animation: none;
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
|
|
2612
3024
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
2613
3025
|
AXIS 1 (COLOUR) — data-palette overrides (Subtask 7.3.48)
|
|
2614
3026
|
Registry: lib/theme/palettes.ts. A named palette re-skins the app by
|
|
@@ -2663,6 +3075,7 @@
|
|
|
2663
3075
|
--color-foreground: #0f1b2e; /* cool navy ink */
|
|
2664
3076
|
--color-surface: #eef2f8; /* cool slate section background */
|
|
2665
3077
|
--color-surface-soft: #f7f9fc; /* quieter cool division */
|
|
3078
|
+
--color-canvas: #e3e9f2; /* recessed planning board — a cool-slate step under --color-surface */
|
|
2666
3079
|
|
|
2667
3080
|
/* text scale — cool slate hierarchy */
|
|
2668
3081
|
--color-ink: #0f1b2e;
|
|
@@ -2708,6 +3121,26 @@
|
|
|
2708
3121
|
/* sidebar hover is a concrete hex in Tier 3 (not a --color-* ref), so the
|
|
2709
3122
|
palette overrides it directly — one shade darker than the cool surface. */
|
|
2710
3123
|
--el-sidebar-item-bg-hover: #e4e9f1;
|
|
3124
|
+
|
|
3125
|
+
/* Status ramp — in_review vs in_progress (MOTIR-2075, the MOTIR-2073 class).
|
|
3126
|
+
`--el-status-in-progress` rides --color-info (Radix Blue 11 #0d63b8) and
|
|
3127
|
+
`--el-status-in-review` rides --color-primary (the Indigo accent #3a57cf);
|
|
3128
|
+
Cobalt is an institutional-BLUE palette, so its two blues sit ΔE2000 8.4
|
|
3129
|
+
apart — different hexes, one dot. The ramp takes its own deeper step of the
|
|
3130
|
+
SAME indigo instead of a new hue: Radix Indigo 12. Separation from
|
|
3131
|
+
in_progress ΔE 20.9; contrast 11.8:1 surface / 13.2:1 card. */
|
|
3132
|
+
--el-status-in-review: #1f2d5c; /* Radix Indigo 12 — deep accent step */
|
|
3133
|
+
|
|
3134
|
+
/* Priority ramp — highest vs high (MOTIR-2085, the MOTIR-2075 class one
|
|
3135
|
+
family over). `--el-priority-highest` rides --color-destructive (#d3322f)
|
|
3136
|
+
and `--el-priority-high` rides --color-warning (#c2410c); Cobalt's warning
|
|
3137
|
+
is a RED-leaning burnt orange, so the two land ΔE2000 9.9 apart — under the
|
|
3138
|
+
ΔE 10 bar a coloured priority GLYPH needs. The semantic identity is kept
|
|
3139
|
+
(danger stays danger, warning stays warning); the PRIORITY ramp takes its
|
|
3140
|
+
own step of a hue Cobalt already owns — Radix Amber 11, one of the palette's
|
|
3141
|
+
documented Radix sources. Separation from highest ΔE 24.3; contrast 4.6:1
|
|
3142
|
+
card / 4.1:1 surface, past the 3:1 icon/UI bar. */
|
|
3143
|
+
--el-priority-high: #ab6400; /* Radix Amber 11 — the ramp's own amber step */
|
|
2711
3144
|
}
|
|
2712
3145
|
|
|
2713
3146
|
/* Cobalt — dark companion. A cool navy canvas (not the base near-black);
|
|
@@ -2718,6 +3151,7 @@
|
|
|
2718
3151
|
--color-foreground: #e7edf6;
|
|
2719
3152
|
--color-surface: #131d2c;
|
|
2720
3153
|
--color-surface-soft: #0f1825;
|
|
3154
|
+
--color-canvas: #070c16; /* recessed planning board — a step under the navy page */
|
|
2721
3155
|
|
|
2722
3156
|
--color-ink: #e7edf6;
|
|
2723
3157
|
--color-charcoal: #d3deec;
|
|
@@ -2762,6 +3196,18 @@
|
|
|
2762
3196
|
|
|
2763
3197
|
/* sidebar hover — one shade lighter than the dark cool surface */
|
|
2764
3198
|
--el-sidebar-item-bg-hover: #1c2840;
|
|
3199
|
+
|
|
3200
|
+
/* Dark keeps the indigo primary — the two blues are already ΔE 10.4 apart
|
|
3201
|
+
here. Re-asserted (not omitted) because the light block above would
|
|
3202
|
+
otherwise inherit onto this canvas: the palette block and
|
|
3203
|
+
[data-theme='dark'] tie on specificity and the palette block wins by
|
|
3204
|
+
source order. Pairing every status override is the rule, not the value. */
|
|
3205
|
+
--el-status-in-review: var(--color-primary);
|
|
3206
|
+
|
|
3207
|
+
/* Dark keeps the brightened warning orange — highest/high are already ΔE 25.8
|
|
3208
|
+
apart here. Re-asserted for the same pairing reason as the status override
|
|
3209
|
+
above: an unpaired light override leaks onto this canvas (MOTIR-2085). */
|
|
3210
|
+
--el-priority-high: var(--color-warning);
|
|
2765
3211
|
}
|
|
2766
3212
|
|
|
2767
3213
|
/* ── Palette: Graphite (data-palette="graphite") — Subtask 7.3.51 ───────────
|
|
@@ -2809,6 +3255,7 @@
|
|
|
2809
3255
|
--color-foreground: #16191d; /* cool near-black ink */
|
|
2810
3256
|
--color-surface: #eef0f3; /* cool slate section background */
|
|
2811
3257
|
--color-surface-soft: #f8f9fa; /* quieter cool division */
|
|
3258
|
+
--color-canvas: #e6e8ed; /* recessed planning board — a cool-slate step under --color-surface */
|
|
2812
3259
|
|
|
2813
3260
|
/* text scale — cool slate hierarchy (Radix Slate 11→9 below body) */
|
|
2814
3261
|
--color-ink: #16191d;
|
|
@@ -2855,6 +3302,42 @@
|
|
|
2855
3302
|
/* sidebar hover is a concrete hex in Tier 3 (not a --color-* ref), so the
|
|
2856
3303
|
palette overrides it directly — one shade darker than the cool surface. */
|
|
2857
3304
|
--el-sidebar-item-bg-hover: #e6e8ec;
|
|
3305
|
+
|
|
3306
|
+
/* Status ramp — the one place the mono identity COLLIDES with the Tier-0
|
|
3307
|
+
indirection (MOTIR-2073). `--el-status-in-progress` rides --color-info and
|
|
3308
|
+
`--el-status-in-review` rides --color-primary; every other palette keeps
|
|
3309
|
+
those two sources apart, but Graphite deliberately unifies them (info =
|
|
3310
|
+
the accent, above), which re-collapsed in_review onto in_progress — the
|
|
3311
|
+
exact differentiation MOTIR-1273 delivered. The fix keeps BOTH deliberate
|
|
3312
|
+
choices by giving the status ramp its own SECOND STEP of the same accent
|
|
3313
|
+
ramp rather than a second hue: Radix Blue 12, one step deeper than the
|
|
3314
|
+
accent (Blue 11-ish #155bc4). Still one chromatic accent, two depths —
|
|
3315
|
+
the same light/dark inversion the ink CTA already uses. Separation from
|
|
3316
|
+
in-progress: ΔE2000 16.9, contrast 2.0:1 — well clear of this palette's
|
|
3317
|
+
tightest deliberate status pair (todo/cancelled, ΔE 11.8). */
|
|
3318
|
+
--el-status-in-review: #113264; /* Radix Blue 12 — deep accent step */
|
|
3319
|
+
|
|
3320
|
+
/* Priority ramp — highest vs high (MOTIR-2094, the MOTIR-2085 shape in a
|
|
3321
|
+
second palette). `--el-priority-highest` rides --color-destructive
|
|
3322
|
+
(#c92a2a) and `--el-priority-high` rides --color-warning (#c2410c);
|
|
3323
|
+
Graphite's warning is a RED-leaning burnt orange sitting beside its danger
|
|
3324
|
+
red, so the two land ΔE2000 10.02 apart. That PASSES the ΔE 10 bar a
|
|
3325
|
+
coloured priority GLYPH needs — by 0.02, which is rounding, not margin: the
|
|
3326
|
+
two marks are at the perceptual minimum, and any future nudge to either
|
|
3327
|
+
semantic tips the pair under the floor. Nothing about this is the monochrome
|
|
3328
|
+
identity (the chrome is greyscale; semantic hues stay chromatic on purpose),
|
|
3329
|
+
so it is a collision to fix, not a choice to document.
|
|
3330
|
+
The fix is Cobalt's: neither semantic moves — danger stays danger, warning
|
|
3331
|
+
stays warning — and the PRIORITY ramp takes its own step of a hue Graphite
|
|
3332
|
+
already owns, Radix Amber 11, one of this palette's documented Radix
|
|
3333
|
+
sources. Separation from highest ΔE 24.7 (nearest other step, medium, ΔE
|
|
3334
|
+
32.2); contrast 4.6:1 card / 4.0:1 surface, past the 3:1 icon/UI bar. */
|
|
3335
|
+
--el-priority-high: #ab6400; /* Radix Amber 11 — the ramp's own amber step */
|
|
3336
|
+
/* implemented (MOTIR-3003) — Graphite's --color-accent is its blue accent, a
|
|
3337
|
+
step from the same family as --el-status-in-progress. The ink step is free
|
|
3338
|
+
here and reads as "not yet coloured in", which is what the state is:
|
|
3339
|
+
ΔE 15.9 light / 11.8 dark from the nearest status. */
|
|
3340
|
+
--el-status-implemented: var(--color-charcoal);
|
|
2858
3341
|
}
|
|
2859
3342
|
|
|
2860
3343
|
/* Graphite — dark companion. A cool near-black slate canvas; the CTA fill
|
|
@@ -2866,6 +3349,7 @@
|
|
|
2866
3349
|
--color-foreground: #edeef0;
|
|
2867
3350
|
--color-surface: #18191c; /* cool slate section */
|
|
2868
3351
|
--color-surface-soft: #141517; /* quieter cool division */
|
|
3352
|
+
--color-canvas: #08090b; /* recessed planning board — a step under the near-black page */
|
|
2869
3353
|
|
|
2870
3354
|
--color-ink: #edeef0;
|
|
2871
3355
|
--color-charcoal: #d7d9dd; /* emphasis / AA-safe on tints */
|
|
@@ -2911,6 +3395,26 @@
|
|
|
2911
3395
|
|
|
2912
3396
|
/* sidebar hover — one shade lighter than the dark cool surface */
|
|
2913
3397
|
--el-sidebar-item-bg-hover: #202226;
|
|
3398
|
+
|
|
3399
|
+
/* Status ramp — the dark companion of the light block's in_review step
|
|
3400
|
+
(MOTIR-2073). Same idea, inverted like the CTA fill: on near-black the
|
|
3401
|
+
"deeper" step is the PALER one, so in_review takes Radix Blue 12 dark —
|
|
3402
|
+
one step lighter than the dark accent (Blue 11-ish #7db1ff). Separation
|
|
3403
|
+
from in-progress: ΔE2000 15.3, contrast 1.67:1; on the dark canvas
|
|
3404
|
+
14.9:1. Every palette block that sets a var must set it in BOTH themes —
|
|
3405
|
+
a light-only override keeps its LIGHT value on the dark canvas (the
|
|
3406
|
+
palette block outranks the base [data-theme='dark'] block). */
|
|
3407
|
+
--el-status-in-review: #c2e6ff; /* Radix Blue 12 dark — pale accent step */
|
|
3408
|
+
|
|
3409
|
+
/* Dark keeps the brightened warning orange — highest/high are already ΔE 25.8
|
|
3410
|
+
apart here, so only light needed the amber step. Re-asserted (not omitted)
|
|
3411
|
+
for the same pairing reason as the status override above: an unpaired light
|
|
3412
|
+
override leaks onto this canvas, where it was never measured (MOTIR-2094). */
|
|
3413
|
+
--el-priority-high: var(--color-warning);
|
|
3414
|
+
/* implemented — the dark half of the light override above; declared in BOTH
|
|
3415
|
+
themes so the light value cannot cascade into dark (the cascade trap this
|
|
3416
|
+
suite checks for). */
|
|
3417
|
+
--el-status-implemented: var(--color-charcoal);
|
|
2914
3418
|
}
|
|
2915
3419
|
|
|
2916
3420
|
/* ── Palette: Evergreen (data-palette="evergreen") — Subtask 7.3.50 ──────────
|
|
@@ -2932,17 +3436,23 @@
|
|
|
2932
3436
|
Concrete-hex --el-* tokens that do NOT resolve through --color-*
|
|
2933
3437
|
(--el-sidebar-item-bg-hover) are re-skinned explicitly below. */
|
|
2934
3438
|
[data-palette='evergreen'] {
|
|
2935
|
-
/* Brand / primary — emerald CTA (white label text clears AA on the fill)
|
|
2936
|
-
|
|
3439
|
+
/* Brand / primary — emerald CTA (white label text clears AA on the fill).
|
|
3440
|
+
--color-primary is the emerald used AS text/icon; --color-primary-fill is
|
|
3441
|
+
the CTA fill. They were the same hex until MOTIR-3774 deepened the INK by
|
|
3442
|
+
1.5% lightness (same hue 158.2, same 82.1% saturation) so it clears AA on
|
|
3443
|
+
the palette's own pastel tints; the FILL is untouched, which is what the
|
|
3444
|
+
picker swatch and every white-on-emerald label read. */
|
|
3445
|
+
--color-primary: #0b714c; /* deepened emerald as text/icon (6.03:1 on white) */
|
|
2937
3446
|
--color-primary-foreground: #ffffff;
|
|
2938
3447
|
--color-primary-pressed: #095f40;
|
|
2939
|
-
--color-primary-fill: #0c7a52;
|
|
3448
|
+
--color-primary-fill: #0c7a52; /* emerald CTA fill — the signature; white-on AA */
|
|
2940
3449
|
|
|
2941
3450
|
/* Surfaces — lightly cooled (green-leaning) neutrals over a white canvas */
|
|
2942
3451
|
--color-background: #ffffff;
|
|
2943
3452
|
--color-foreground: #14201b;
|
|
2944
3453
|
--color-surface: #eef3f0;
|
|
2945
3454
|
--color-surface-soft: #f6faf8;
|
|
3455
|
+
--color-canvas: #e4ebe7; /* recessed planning board — a green-grey step under --color-surface */
|
|
2946
3456
|
|
|
2947
3457
|
/* Text scale — cooled forest-charcoal ink hierarchy */
|
|
2948
3458
|
--color-ink: #14201b;
|
|
@@ -2991,6 +3501,19 @@
|
|
|
2991
3501
|
/* Concrete-hex --el token (does not resolve through --color-*) — cool hover
|
|
2992
3502
|
lift one shade darker than the cooled light surface */
|
|
2993
3503
|
--el-sidebar-item-bg-hover: #e4ebe7;
|
|
3504
|
+
|
|
3505
|
+
/* Status ramp — in_review vs done (MOTIR-2075). `--el-status-in-review` rides
|
|
3506
|
+
--color-primary (emerald #0c7a52) and `--el-status-done` rides
|
|
3507
|
+
--color-success (grass #127c3e): two greens ΔE2000 5.5 apart, and this
|
|
3508
|
+
palette's own comment claimed they "read apart". They do not. The ramp takes
|
|
3509
|
+
its own deeper step of the palette's JADE — Radix Jade 12 — so review reads
|
|
3510
|
+
as a deep jade against the grass done. Separation ΔE 19.2; contrast 10.9:1
|
|
3511
|
+
surface / 12.2:1 card. */
|
|
3512
|
+
--el-status-in-review: #1d3b31; /* Radix Jade 12 — deep jade step */
|
|
3513
|
+
|
|
3514
|
+
/* cancelled is unchanged in light (ΔE 17.9 from todo); re-asserted to pair
|
|
3515
|
+
the dark override below — see the cascade note in the dark block. */
|
|
3516
|
+
--el-status-cancelled: var(--color-steel);
|
|
2994
3517
|
}
|
|
2995
3518
|
|
|
2996
3519
|
/* Evergreen — dark companion. Bright emerald on a deep-forest canvas
|
|
@@ -3006,6 +3529,7 @@
|
|
|
3006
3529
|
--color-foreground: #e8efe9;
|
|
3007
3530
|
--color-surface: #141d18;
|
|
3008
3531
|
--color-surface-soft: #101713;
|
|
3532
|
+
--color-canvas: #080d0a; /* recessed planning board — a step under the deep-forest page */
|
|
3009
3533
|
|
|
3010
3534
|
--color-ink: #e8efe9;
|
|
3011
3535
|
--color-charcoal: #d6e0d9;
|
|
@@ -3044,6 +3568,18 @@
|
|
|
3044
3568
|
|
|
3045
3569
|
/* hover lift one shade *lighter* than the dark surface (mirrors base recipe) */
|
|
3046
3570
|
--el-sidebar-item-bg-hover: #1e2a23;
|
|
3571
|
+
|
|
3572
|
+
/* Status ramp (MOTIR-2075) — two collisions in this theme.
|
|
3573
|
+
in_review vs done: emerald #3ddc97 against grass #34d27a, ΔE2000 4.7. Same
|
|
3574
|
+
fix as light, inverted: Radix Jade 12's DARK step, pale rather than deep —
|
|
3575
|
+
the light/dark inversion Graphite's accent step already uses. ΔE 17.2;
|
|
3576
|
+
contrast 13.3:1 surface / 14.5:1 card.
|
|
3577
|
+
todo vs cancelled: --color-stone #5a6b62 against --color-steel #6f8077,
|
|
3578
|
+
ΔE 8.3 — this palette's neutral ramp is compressed against the base's
|
|
3579
|
+
(which keeps the pair ~12 apart). cancelled takes the palette's own next
|
|
3580
|
+
step up, --color-slate. ΔE 22.4; contrast 7.1:1 / 7.7:1. */
|
|
3581
|
+
--el-status-in-review: #adf0d4; /* Radix Jade 12 dark — pale jade step */
|
|
3582
|
+
--el-status-cancelled: #9aaaa1; /* Evergreen's own slate — the next neutral step */
|
|
3047
3583
|
}
|
|
3048
3584
|
|
|
3049
3585
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
@@ -3122,6 +3658,7 @@
|
|
|
3122
3658
|
--color-foreground: #1a1626; /* cool near-black ink with a faint violet cast */
|
|
3123
3659
|
--color-surface: #f4f2fb; /* cool violet-tinted section background */
|
|
3124
3660
|
--color-surface-soft: #faf9fe; /* quieter cool division */
|
|
3661
|
+
--color-canvas: #ece8f7; /* recessed planning board — a violet-tinted step under --color-surface */
|
|
3125
3662
|
|
|
3126
3663
|
/* text scale — cool violet-neutral hierarchy */
|
|
3127
3664
|
--color-ink: #1a1626;
|
|
@@ -3169,6 +3706,20 @@
|
|
|
3169
3706
|
/* sidebar hover is a concrete hex in Tier 3 (not a --color-* ref), so the
|
|
3170
3707
|
palette overrides it directly — one shade darker than the cool surface. */
|
|
3171
3708
|
--el-sidebar-item-bg-hover: #ece8f8;
|
|
3709
|
+
|
|
3710
|
+
/* Priority ramp — highest vs high, the third instance of the Cobalt
|
|
3711
|
+
(MOTIR-2085) / Graphite (MOTIR-2094) collision, found once the floor was
|
|
3712
|
+
measured on the CHIP rather than the source (MOTIR-2107).
|
|
3713
|
+
`--el-priority-highest` rides --color-destructive (#d92e2b) and
|
|
3714
|
+
`--el-priority-high` rides --color-warning (#ea580c); Spectrum's warning is
|
|
3715
|
+
a red-leaning orange, so the two source hues land ΔE2000 14.5 apart — over
|
|
3716
|
+
the glyph bar, while the 14% chip `Pill` paints rendered only ΔE 4.2, under
|
|
3717
|
+
cobalt's own pre-fix 3.8 in feel. Neither semantic moves; the PRIORITY ramp
|
|
3718
|
+
takes its own step of a hue Spectrum already owns — Radix Amber 11, one of
|
|
3719
|
+
the palette's documented Radix sources. Source separation from highest
|
|
3720
|
+
ΔE 24.3, rendered chip ΔE 8.6; contrast 4.6:1 card / 4.2:1 surface, past
|
|
3721
|
+
the 3:1 icon/UI bar. */
|
|
3722
|
+
--el-priority-high: #ab6400; /* Radix Amber 11 — the ramp's own amber step */
|
|
3172
3723
|
}
|
|
3173
3724
|
|
|
3174
3725
|
/* Spectrum — dark companion. A deep cool-violet canvas (not the base
|
|
@@ -3179,6 +3730,7 @@
|
|
|
3179
3730
|
--color-foreground: #ece9f6;
|
|
3180
3731
|
--color-surface: #1d1830;
|
|
3181
3732
|
--color-surface-soft: #181426;
|
|
3733
|
+
--color-canvas: #0f0c18; /* recessed planning board — a step under the cool-violet page */
|
|
3182
3734
|
|
|
3183
3735
|
--color-ink: #ece9f6;
|
|
3184
3736
|
--color-charcoal: #ddd8ee;
|
|
@@ -3216,7 +3768,19 @@
|
|
|
3216
3768
|
--color-success: #36c977;
|
|
3217
3769
|
--color-warning: #fb8b4c;
|
|
3218
3770
|
--color-destructive: #f0555f; /* reads AS text on the dark canvas (AA ~5.5:1) */
|
|
3219
|
-
|
|
3771
|
+
/* The FILL ink, not a page ink — this is what `Button`'s danger variant paints
|
|
3772
|
+
ON `--color-destructive` above. Dark lightened the red to #f0555f so it would
|
|
3773
|
+
read AS text on the violet canvas, and left the ink at #ffffff: two
|
|
3774
|
+
individually reasonable decisions that are wrong together, at 3.40:1 — the
|
|
3775
|
+
only one of ten palettes x two themes under AA (MOTIR-3664). A lighter red
|
|
3776
|
+
needs darker ink, which is what amber / candy / citrine / evergreen / garnet
|
|
3777
|
+
/ sienna already do in their own dark blocks, each with the palette's own
|
|
3778
|
+
near-black. Spectrum's is the deep cool-violet canvas above: white -> #14111f
|
|
3779
|
+
takes the pairing 3.40 -> 5.46:1, mid-range among those six (5.14-8.81).
|
|
3780
|
+
`--color-destructive` itself does NOT move — it is also the border/glyph hue
|
|
3781
|
+
(5.03-5.68:1 on every dark surface here) and the source of
|
|
3782
|
+
--el-priority-highest / --el-type-bug / --el-type-deploy / --el-overdue. */
|
|
3783
|
+
--color-destructive-foreground: #14111f;
|
|
3220
3784
|
--color-info: #6fa8ff;
|
|
3221
3785
|
|
|
3222
3786
|
--color-link: #8fb8ff;
|
|
@@ -3224,6 +3788,15 @@
|
|
|
3224
3788
|
|
|
3225
3789
|
/* sidebar hover — one shade lighter than the dark cool surface */
|
|
3226
3790
|
--el-sidebar-item-bg-hover: #261f3d;
|
|
3791
|
+
|
|
3792
|
+
/* Priority ramp — the dark half of the light block's amber step (MOTIR-2107).
|
|
3793
|
+
UNLIKE cobalt and graphite (whose dark hues were already far enough apart to
|
|
3794
|
+
re-assert the source here), Spectrum's dark destructive #f0555f and warning
|
|
3795
|
+
#fb8b4c render a chip only ΔE 4.8 apart, so dark carries its own amber too:
|
|
3796
|
+
the brighter #fbab4c the other dark palettes already use, which reads as an
|
|
3797
|
+
icon on the violet canvas. Source separation from highest ΔE 33.9, rendered
|
|
3798
|
+
chip ΔE 8.1; contrast 9.8:1 card / 9.0:1 surface. */
|
|
3799
|
+
--el-priority-high: #fbab4c; /* on-dark amber — the ramp's own step */
|
|
3227
3800
|
}
|
|
3228
3801
|
|
|
3229
3802
|
/* ── Palette: Amber (data-palette="amber") — Subtask 8.8.34 (MOTIR-1252) ─────
|
|
@@ -3251,7 +3824,7 @@
|
|
|
3251
3824
|
[data-palette='amber'] {
|
|
3252
3825
|
/* brand & primary — Binance Gold. The FILL carries DARK ink labels (yellow
|
|
3253
3826
|
trap); --color-primary is a darkened gold used AS text/icon on a surface. */
|
|
3254
|
-
--color-primary: #
|
|
3827
|
+
--color-primary: #7d6000; /* darkened gold as text/icon (5.92:1 on white — MOTIR-3774) */
|
|
3255
3828
|
--color-primary-foreground: #181a20; /* Binance near-black on the gold fill (AA ~9.6:1) */
|
|
3256
3829
|
--color-primary-pressed: #d4a30a;
|
|
3257
3830
|
--color-primary-fill: #f0b90b; /* Binance Gold — the signature; dark-on AA */
|
|
@@ -3261,6 +3834,7 @@
|
|
|
3261
3834
|
--color-foreground: #181a20; /* Binance near-black ink */
|
|
3262
3835
|
--color-surface: #f4f5f7; /* cool graphite section background */
|
|
3263
3836
|
--color-surface-soft: #fafbfc; /* quieter cool division */
|
|
3837
|
+
--color-canvas: #eaecf0; /* recessed planning board — a graphite step under --color-surface */
|
|
3264
3838
|
|
|
3265
3839
|
/* text scale — Binance cool-grey hierarchy */
|
|
3266
3840
|
--color-ink: #181a20;
|
|
@@ -3285,7 +3859,10 @@
|
|
|
3285
3859
|
--color-accent-green: #0a8f57; /* darkened Binance buy-green for light AA */
|
|
3286
3860
|
|
|
3287
3861
|
/* card tints — gold-leaning warm washes + cool feature hues */
|
|
3288
|
-
|
|
3862
|
+
/* peach leans ORANGE, not gold: gold-leaning every warm tint had collapsed
|
|
3863
|
+
peach onto the Block-gold yellow at ΔE2000 4.3 light / 1.7 dark — the two
|
|
3864
|
+
most-used washes reading as one chip (MOTIR-2085). */
|
|
3865
|
+
--color-tint-peach: #fbdfc0;
|
|
3289
3866
|
--color-tint-rose: #f7dde2;
|
|
3290
3867
|
--color-tint-mint: #d6ecdf;
|
|
3291
3868
|
--color-tint-lavender: #e2e4ee;
|
|
@@ -3305,6 +3882,11 @@
|
|
|
3305
3882
|
|
|
3306
3883
|
/* sidebar hover — one shade darker than the cool surface */
|
|
3307
3884
|
--el-sidebar-item-bg-hover: #eceef1;
|
|
3885
|
+
/* implemented (MOTIR-3003) — Amber's --color-accent sits beside its brand
|
|
3886
|
+
amber, i.e. next to --el-status-in-review. Its red is unspent by any status
|
|
3887
|
+
in this palette (blocked rides the amber), so it takes it: ΔE 21.2 light /
|
|
3888
|
+
33.7 dark from the nearest status. */
|
|
3889
|
+
--el-status-implemented: var(--color-destructive);
|
|
3308
3890
|
}
|
|
3309
3891
|
|
|
3310
3892
|
/* Amber — dark companion: the AUTHENTIC Binance trading floor. Cool near-black
|
|
@@ -3316,6 +3898,7 @@
|
|
|
3316
3898
|
--color-foreground: #eaecef;
|
|
3317
3899
|
--color-surface: #1e2329; /* Binance "Shark" card surface */
|
|
3318
3900
|
--color-surface-soft: #181a20; /* Binance app background — quieter division */
|
|
3901
|
+
--color-canvas: #07090c; /* recessed planning board — a step under the trading-floor black */
|
|
3319
3902
|
|
|
3320
3903
|
--color-ink: #eaecef;
|
|
3321
3904
|
--color-charcoal: #d1d6dd;
|
|
@@ -3338,7 +3921,8 @@
|
|
|
3338
3921
|
--color-primary-fill: #fcd535;
|
|
3339
3922
|
|
|
3340
3923
|
/* tints dimmed for the trading-floor black */
|
|
3341
|
-
|
|
3924
|
+
/* the dark twin of the light orange wash — see the light block's note. */
|
|
3925
|
+
--color-tint-peach: #331f10;
|
|
3342
3926
|
--color-tint-rose: #2f1a22;
|
|
3343
3927
|
--color-tint-mint: #102a1e;
|
|
3344
3928
|
--color-tint-lavender: #1c2030;
|
|
@@ -3361,6 +3945,9 @@
|
|
|
3361
3945
|
|
|
3362
3946
|
/* sidebar hover — one shade lighter than the dark "Shark" surface */
|
|
3363
3947
|
--el-sidebar-item-bg-hover: #262d35;
|
|
3948
|
+
/* implemented — the dark half of the light override above; declared in BOTH
|
|
3949
|
+
themes so the light value cannot cascade into dark. */
|
|
3950
|
+
--el-status-implemented: var(--color-destructive);
|
|
3364
3951
|
}
|
|
3365
3952
|
|
|
3366
3953
|
/* ── Palette: Sienna (data-palette="sienna") — Subtask 8.8.34 (MOTIR-1252) ───
|
|
@@ -3383,7 +3970,7 @@
|
|
|
3383
3970
|
[data-palette='sienna'] {
|
|
3384
3971
|
/* brand & primary — Mistral's flame. The FILL is Mistral Orange #fa520f with
|
|
3385
3972
|
DARK ink labels; --color-primary is a darkened flame used AS text/icon. */
|
|
3386
|
-
--color-primary: #
|
|
3973
|
+
--color-primary: #b53b09; /* darkened Mistral flame as text/icon (5.60:1 on the cream — MOTIR-3774) */
|
|
3387
3974
|
--color-primary-foreground: #2a1205; /* DARK warm ink on the flame fill (AA ~5.3:1) */
|
|
3388
3975
|
--color-primary-pressed: #cc3a05; /* Mistral primary-deep */
|
|
3389
3976
|
--color-primary-fill: #fa520f; /* Mistral Orange — the signature flame; dark-on AA */
|
|
@@ -3393,6 +3980,7 @@
|
|
|
3393
3980
|
--color-foreground: #1f1f1f; /* Mistral Black ink */
|
|
3394
3981
|
--color-surface: #fbf1d3; /* warm cream section background (Mistral cream ramp) */
|
|
3395
3982
|
--color-surface-soft: #fdf6e0; /* quieter warm cream division */
|
|
3983
|
+
--color-canvas: #f5e9cb; /* recessed planning board — a warm-cream step under --color-surface */
|
|
3396
3984
|
|
|
3397
3985
|
/* text scale — Mistral warm-charcoal hierarchy */
|
|
3398
3986
|
--color-ink: #1f1f1f;
|
|
@@ -3421,7 +4009,11 @@
|
|
|
3421
4009
|
--color-tint-rose: #fbdfd2;
|
|
3422
4010
|
--color-tint-mint: #e3ead0;
|
|
3423
4011
|
--color-tint-lavender: #ece6d6;
|
|
3424
|
-
|
|
4012
|
+
/* sky is a muted wash of the palette's OWN teal accent (#0e8f86), not another
|
|
4013
|
+
olive: warming every cool tint had collapsed sky onto mint at ΔE2000 3.4
|
|
4014
|
+
light / 1.3 dark — one colour doing two jobs in a six-chip ramp (MOTIR-2085).
|
|
4015
|
+
Still Mediterranean, just the sea rather than the hillside. */
|
|
4016
|
+
--color-tint-sky: #d9e8e4;
|
|
3425
4017
|
--color-tint-yellow: #ffe295; /* Mistral Block Gold */
|
|
3426
4018
|
|
|
3427
4019
|
/* semantic — Mistral documents none; added warm-consistent + AA-safe */
|
|
@@ -3437,6 +4029,20 @@
|
|
|
3437
4029
|
|
|
3438
4030
|
/* sidebar hover — one shade deeper than the cream surface */
|
|
3439
4031
|
--el-sidebar-item-bg-hover: #f5e9c4;
|
|
4032
|
+
|
|
4033
|
+
/* Status ramp — blocked vs in_review (MOTIR-2075). Mistral ships NO semantic
|
|
4034
|
+
colours, so this palette's warning was added warm-consistent (#b45309) —
|
|
4035
|
+
which lands it next to the darkened Mistral flame --color-primary #c4400a:
|
|
4036
|
+
ΔE2000 7.1, amber against flame. Rather than move the brand flame, blocked
|
|
4037
|
+
takes the palette's own amber accent step, which reads as a warning without
|
|
4038
|
+
being the primary. ΔE 14.2; contrast 3.8:1 surface / 4.1:1 card. */
|
|
4039
|
+
--el-status-blocked: var(--color-accent);
|
|
4040
|
+
|
|
4041
|
+
/* implemented (MOTIR-3003) — Sienna re-maps --el-status-blocked onto
|
|
4042
|
+
--color-accent (directly above), so the base pink would collide with it
|
|
4043
|
+
here. The ink step is free: ΔE 21.1 light / 22.6 dark from the nearest
|
|
4044
|
+
status. */
|
|
4045
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3440
4046
|
}
|
|
3441
4047
|
|
|
3442
4048
|
/* Sienna — dark companion. Mistral is light-dominant (few dark tokens: Mistral
|
|
@@ -3447,6 +4053,7 @@
|
|
|
3447
4053
|
--color-foreground: #f5efe2;
|
|
3448
4054
|
--color-surface: #1f1d17;
|
|
3449
4055
|
--color-surface-soft: #1a1712;
|
|
4056
|
+
--color-canvas: #100d08; /* recessed planning board — a step under the warm near-black page */
|
|
3450
4057
|
|
|
3451
4058
|
--color-ink: #f5efe2;
|
|
3452
4059
|
--color-charcoal: #e6ddcb;
|
|
@@ -3471,7 +4078,8 @@
|
|
|
3471
4078
|
--color-tint-rose: #321c16;
|
|
3472
4079
|
--color-tint-mint: #23271a;
|
|
3473
4080
|
--color-tint-lavender: #272318;
|
|
3474
|
-
|
|
4081
|
+
/* the dark twin of the light teal wash — see the light block's note. */
|
|
4082
|
+
--color-tint-sky: #1b2622;
|
|
3475
4083
|
--color-tint-yellow: #332b12;
|
|
3476
4084
|
|
|
3477
4085
|
--color-accent: #ffa110; /* Mistral Sunshine-700 amber on dark */
|
|
@@ -3490,6 +4098,14 @@
|
|
|
3490
4098
|
|
|
3491
4099
|
/* sidebar hover — one shade lighter than the warm-dark surface */
|
|
3492
4100
|
--el-sidebar-item-bg-hover: #292619;
|
|
4101
|
+
|
|
4102
|
+
/* Dark's amber and flame are already ΔE 11.9 apart. Re-asserted to pair the
|
|
4103
|
+
light override above — see the cascade note in cobalt/dark. */
|
|
4104
|
+
--el-status-blocked: var(--color-warning);
|
|
4105
|
+
/* implemented — the dark half of the light override above; declared in BOTH
|
|
4106
|
+
themes so the light value cannot cascade into dark (this palette's
|
|
4107
|
+
--el-status-blocked note above is the same pairing). */
|
|
4108
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3493
4109
|
}
|
|
3494
4110
|
|
|
3495
4111
|
/* ── Palette: Garnet (data-palette="garnet") — Subtask 8.8.34 (MOTIR-1252) ───
|
|
@@ -3517,6 +4133,7 @@
|
|
|
3517
4133
|
--color-foreground: #111111; /* Pinterest "Cod Gray" ink */
|
|
3518
4134
|
--color-surface: #efefef; /* Pinterest light-gray section background */
|
|
3519
4135
|
--color-surface-soft: #f7f7f7; /* quieter neutral division */
|
|
4136
|
+
--color-canvas: #e7e7e7; /* recessed planning board — a neutral step under --color-surface */
|
|
3520
4137
|
|
|
3521
4138
|
/* text scale — Pinterest neutral-grey hierarchy */
|
|
3522
4139
|
--color-ink: #111111;
|
|
@@ -3561,6 +4178,14 @@
|
|
|
3561
4178
|
|
|
3562
4179
|
/* sidebar hover — one shade darker than the neutral surface */
|
|
3563
4180
|
--el-sidebar-item-bg-hover: #e6e6e6;
|
|
4181
|
+
|
|
4182
|
+
/* Status ramp — todo vs cancelled (MOTIR-2075). Pinterest's neutrals are
|
|
4183
|
+
true-neutral greys and its documented ramp puts --color-stone #767676 and
|
|
4184
|
+
--color-steel #5f5f5f close together: ΔE2000 8.8, where the base keeps the
|
|
4185
|
+
pair ~12 apart. cancelled drops to Pinterest's next documented grey,
|
|
4186
|
+
#444444 (the palette's own --color-slate). ΔE 18.1; contrast 8.5:1 surface
|
|
4187
|
+
/ 9.7:1 card. */
|
|
4188
|
+
--el-status-cancelled: #444444; /* Pinterest grey — one documented step deeper */
|
|
3564
4189
|
}
|
|
3565
4190
|
|
|
3566
4191
|
/* Garnet — dark companion. Pinterest's Cod-Gray near-black canvas; the red
|
|
@@ -3571,6 +4196,7 @@
|
|
|
3571
4196
|
--color-foreground: #efefef;
|
|
3572
4197
|
--color-surface: #1a1a1a;
|
|
3573
4198
|
--color-surface-soft: #161616;
|
|
4199
|
+
--color-canvas: #090909; /* recessed planning board — a step under the Cod-Gray page */
|
|
3574
4200
|
|
|
3575
4201
|
--color-ink: #efefef;
|
|
3576
4202
|
--color-charcoal: #e0e0e0;
|
|
@@ -3615,6 +4241,10 @@
|
|
|
3615
4241
|
|
|
3616
4242
|
/* sidebar hover — one shade lighter than the dark surface */
|
|
3617
4243
|
--el-sidebar-item-bg-hover: #232323;
|
|
4244
|
+
|
|
4245
|
+
/* Dark's greys are already ΔE 11.6 apart. Re-asserted to pair the light
|
|
4246
|
+
override above — see the cascade note in cobalt/dark. */
|
|
4247
|
+
--el-status-cancelled: var(--color-steel);
|
|
3618
4248
|
}
|
|
3619
4249
|
|
|
3620
4250
|
/* ── Palette: Citrine (data-palette="citrine") — Subtask 8.8.34 (MOTIR-1252) ──
|
|
@@ -3651,6 +4281,7 @@
|
|
|
3651
4281
|
--color-foreground: #050038; /* Miro Stratos navy ink */
|
|
3652
4282
|
--color-surface: #f3f4f6; /* Mirotone gray-100 section background */
|
|
3653
4283
|
--color-surface-soft: #f6f7f9; /* Mirotone gray-50 — quieter division */
|
|
4284
|
+
--color-canvas: #ebecf0; /* recessed planning board — Mirotone gray-150, a step under gray-100 */
|
|
3654
4285
|
|
|
3655
4286
|
/* text scale — Mirotone gray ramp */
|
|
3656
4287
|
--color-ink: #050038;
|
|
@@ -3696,6 +4327,37 @@
|
|
|
3696
4327
|
|
|
3697
4328
|
/* sidebar hover — Mirotone gray-150, one step off the surface */
|
|
3698
4329
|
--el-sidebar-item-bg-hover: #ebecf0;
|
|
4330
|
+
|
|
4331
|
+
/* Status ramp (MOTIR-2075) — two collisions, both from Mirotone's ramps.
|
|
4332
|
+
blocked vs in_review: --color-warning is yellow-650 #91771e and
|
|
4333
|
+
--color-primary is yellow-700 #746019 — ADJACENT steps of one gold ramp,
|
|
4334
|
+
ΔE2000 9.7. Miro is a 5-hue system with NO orange ramp (see the block
|
|
4335
|
+
header), and the golds that clear AA on a light surface are exactly those
|
|
4336
|
+
two, so the gold cannot separate itself. The status ramp therefore takes
|
|
4337
|
+
Miro's OTHER brand hue at its own depth — the action blue, blue-650 — which
|
|
4338
|
+
leaves blocked on the warning gold where its semantics belong. Note
|
|
4339
|
+
in_progress rides blue-500 #3859ff: same family, two depths, ΔE 17.0 apart,
|
|
4340
|
+
the Graphite idiom. Contrast 9.2:1 surface / 10.2:1 card.
|
|
4341
|
+
todo vs cancelled: gray-450 #7f8497 vs gray-500 #656b81, ΔE 10.0 — one step
|
|
4342
|
+
apart on Mirotone's gray ramp. cancelled drops to gray-600. ΔE 20.6;
|
|
4343
|
+
contrast 7.5:1 / 8.3:1. */
|
|
4344
|
+
--el-status-in-review: #243797; /* Mirotone blue-650 — deep action blue */
|
|
4345
|
+
/* Status ramp — planning vs the two blues (MOTIR-2427, the MOTIR-2073 class).
|
|
4346
|
+
Citrine is a deliberate 5-hue Miro palette and it re-skins
|
|
4347
|
+
`--color-accent-teal` to Mirotone BLUE, so the base teal source lands on
|
|
4348
|
+
top of in_progress here. Mirotone red-500 is the only remaining documented
|
|
4349
|
+
family: `Planning` means the card was found WRONG and is being re-planned,
|
|
4350
|
+
which is the one status where an attention hue is honest — and `cancelled`
|
|
4351
|
+
stays deliberately grey, so red is not overloaded. */
|
|
4352
|
+
--el-status-planning: #d8182c; /* Mirotone red-500 — the attention family */
|
|
4353
|
+
--el-status-cancelled: #4a4e5e; /* Mirotone gray-600 — one step deeper */
|
|
4354
|
+
/* implemented (MOTIR-3003) — Citrine spends --color-accent on a hue its
|
|
4355
|
+
--el-status-in-progress is already in the family of, and its red is
|
|
4356
|
+
--el-status-planning. The ink step is what is left: ΔE 17.8 light / 10.0
|
|
4357
|
+
dark. ⚠️ The dark figure sits EXACTLY on the ΔE 10 floor, against
|
|
4358
|
+
in_review — a palette change that moves either one needs re-measuring
|
|
4359
|
+
rather than nudging. */
|
|
4360
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3699
4361
|
}
|
|
3700
4362
|
|
|
3701
4363
|
/* Citrine — dark companion. A Mirotone gray-ramp near-black canvas (black
|
|
@@ -3707,6 +4369,7 @@
|
|
|
3707
4369
|
--color-foreground: #f6f7f9; /* gray-50 */
|
|
3708
4370
|
--color-surface: #1a1b1e; /* gray-900 */
|
|
3709
4371
|
--color-surface-soft: #18191c; /* gray-950 */
|
|
4372
|
+
--color-canvas: #040404; /* recessed planning board — a step under Miro black */
|
|
3710
4373
|
|
|
3711
4374
|
--color-ink: #f6f7f9;
|
|
3712
4375
|
--color-charcoal: #ebecf0; /* gray-150 */
|
|
@@ -3751,6 +4414,26 @@
|
|
|
3751
4414
|
|
|
3752
4415
|
/* sidebar hover — Mirotone gray-800, one step lighter than the surface */
|
|
3753
4416
|
--el-sidebar-item-bg-hover: #24262c;
|
|
4417
|
+
|
|
4418
|
+
/* Status ramp (MOTIR-2075) — the worst collision in the whole set:
|
|
4419
|
+
blocked #ffd850 against in_review #ffd02f is ΔE2000 3.0. Two Sunglow golds
|
|
4420
|
+
one hex apart; no one can tell them apart on a 10px dot. Same fix as light,
|
|
4421
|
+
inverted — the action blue at its PALE step, Mirotone blue-200, rather than
|
|
4422
|
+
the deep blue-650 (which sits at 1.7:1 on this near-black surface and would
|
|
4423
|
+
fail the 3:1 icon bar). Separation from in_progress (blue-400 #7a90fe)
|
|
4424
|
+
ΔE 18.4; contrast 13.1:1 surface / 15.1:1 card.
|
|
4425
|
+
cancelled is unchanged here (ΔE 17.8 from todo) and re-asserted only to
|
|
4426
|
+
pair the light block's override — see the cascade note in cobalt/dark. */
|
|
4427
|
+
--el-status-in-review: #d9dffc; /* Mirotone blue-200 — pale action blue */
|
|
4428
|
+
/* The dark twin of the planning override above — declared in BOTH themes even
|
|
4429
|
+
though it is the same family, because an unpaired light override loses to
|
|
4430
|
+
the later palette block (the cascade trap). Brightened one step, as this
|
|
4431
|
+
palette does with every semantic on dark. */
|
|
4432
|
+
--el-status-planning: #ff6b78; /* Mirotone red-400 — brightened for dark */
|
|
4433
|
+
--el-status-cancelled: var(--color-steel);
|
|
4434
|
+
/* implemented — the dark half of the light override above; declared in BOTH
|
|
4435
|
+
themes so the light value cannot cascade into dark. */
|
|
4436
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3754
4437
|
}
|
|
3755
4438
|
|
|
3756
4439
|
/* ── Palette: Candy (data-palette="candy") — Subtask 8.8.34 (MOTIR-1252) ──────
|
|
@@ -3774,7 +4457,7 @@
|
|
|
3774
4457
|
[data-palette='candy'] {
|
|
3775
4458
|
/* brand & primary — a LIGHT bubblegum pink (Radix Pink). FILL is a light pink
|
|
3776
4459
|
with DARK berry labels; --color-primary is the Pink-11 text step. */
|
|
3777
|
-
--color-primary: #
|
|
4460
|
+
--color-primary: #b72682; /* Radix Pink-11 88% toward Pink-12 (5.81:1 on white — MOTIR-3774) */
|
|
3778
4461
|
--color-primary-foreground: #651249; /* Radix Pink-12 berry ink on the light-pink fill (~7.6:1) */
|
|
3779
4462
|
--color-primary-pressed: #e7acd0; /* Radix Pink-7 */
|
|
3780
4463
|
--color-primary-fill: #efbfdd; /* Radix Pink-6 — the light bubblegum pink */
|
|
@@ -3784,6 +4467,7 @@
|
|
|
3784
4467
|
--color-foreground: #211f26; /* Radix Mauve-12 ink */
|
|
3785
4468
|
--color-surface: #fee9f5; /* Radix Pink-3 — candy-pink section */
|
|
3786
4469
|
--color-surface-soft: #fef7fb; /* Radix Pink-2 — quieter candy wash */
|
|
4470
|
+
--color-canvas: #fbdcef; /* recessed planning board — Radix Pink-4, a step under the Pink-3 surface */
|
|
3787
4471
|
|
|
3788
4472
|
/* text scale — Radix Mauve neutral + a Pink-12 berry emphasis */
|
|
3789
4473
|
--color-ink: #211f26;
|
|
@@ -3822,12 +4506,21 @@
|
|
|
3822
4506
|
--color-destructive-foreground: #ffffff;
|
|
3823
4507
|
--color-info: #00749e; /* Sky-11 */
|
|
3824
4508
|
|
|
4509
|
+
/* Status ramp — planning, the LIGHT twin of the dark override below (the
|
|
4510
|
+
cascade trap: an unpaired light override loses to the later palette block).
|
|
4511
|
+
Same documented Plum family, at the light scale step. */
|
|
4512
|
+
--el-status-planning: #ab4aba; /* Plum-9 — the documented berry accent */
|
|
4513
|
+
|
|
3825
4514
|
/* links — Radix Sky-11 candy blue, distinct from the pink primary */
|
|
3826
4515
|
--color-link: #00749e;
|
|
3827
4516
|
--color-link-pressed: #1d3e56; /* Sky-12 */
|
|
3828
4517
|
|
|
3829
4518
|
/* sidebar hover — one shade deeper than the candy-pink surface (Pink-4) */
|
|
3830
4519
|
--el-sidebar-item-bg-hover: #fbdcef;
|
|
4520
|
+
/* implemented (MOTIR-3003) — Candy's --color-accent is the berry family its
|
|
4521
|
+
--el-status-planning already occupies (ΔE 0.0 with the base value). The ink
|
|
4522
|
+
step is free: ΔE 20.0 light / 16.2 dark from the nearest status. */
|
|
4523
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3831
4524
|
}
|
|
3832
4525
|
|
|
3833
4526
|
/* Candy — dark companion. A pink-tinted near-black canvas (Radix Pink dark
|
|
@@ -3839,6 +4532,7 @@
|
|
|
3839
4532
|
--color-foreground: #eeeef0; /* Mauve dark-12 */
|
|
3840
4533
|
--color-surface: #37172f; /* Pink dark-3 — candy-plum section */
|
|
3841
4534
|
--color-surface-soft: #21121d; /* Pink dark-2 — quieter division */
|
|
4535
|
+
--color-canvas: #120c11; /* recessed planning board — a step under the Pink dark-1 page */
|
|
3842
4536
|
|
|
3843
4537
|
--color-ink: #eeeef0;
|
|
3844
4538
|
--color-charcoal: #fdd1ea; /* Pink dark-12 — pink emphasis / AA on dark tints */
|
|
@@ -3878,11 +4572,22 @@
|
|
|
3878
4572
|
--color-destructive-foreground: #191114; /* dark ink on the bright danger */
|
|
3879
4573
|
--color-info: #75c7f0; /* Sky dark-11 */
|
|
3880
4574
|
|
|
4575
|
+
/* Status ramp — planning vs done (MOTIR-2427, the MOTIR-2073 class). Candy's
|
|
4576
|
+
`--color-accent-teal` is Jade dark-11 (#1fd8a4) and its `--color-success` is
|
|
4577
|
+
Grass dark-11 (#71d083): two bright dark-mode greens ΔE2000 9.2 apart, which
|
|
4578
|
+
is one dot at a glance. The ramp takes the palette's own documented BERRY
|
|
4579
|
+
instead of a fourth green — Plum, which candy.md names as its accent family
|
|
4580
|
+
and which nothing else in the status ramp uses. */
|
|
4581
|
+
--el-status-planning: #ab4aba; /* Plum-9 — the documented berry accent */
|
|
4582
|
+
|
|
3881
4583
|
--color-link: #75c7f0;
|
|
3882
4584
|
--color-link-pressed: #c2f3ff; /* Sky dark-12 */
|
|
3883
4585
|
|
|
3884
4586
|
/* sidebar hover — one shade lighter than the candy-plum surface (Pink dark-4) */
|
|
3885
4587
|
--el-sidebar-item-bg-hover: #4b143d;
|
|
4588
|
+
/* implemented — the dark half of the light override above; declared in BOTH
|
|
4589
|
+
themes so the light value cannot cascade into dark. */
|
|
4590
|
+
--el-status-implemented: var(--color-charcoal);
|
|
3886
4591
|
}
|
|
3887
4592
|
|
|
3888
4593
|
[data-type='grotesk'] {
|