Tidy CSS: spacing and color literal fixes

Normalize formatting and small style fixes across frontend CSS. Adds spacing/newlines for readability, tweaks layout/overflow comments, improves accessibility notes, and normalizes white literals (#ffffff → #fff) and a few token mappings in theme files. Affected files include various core, portal and proprietary CSS modules (theme.css, colors.css, primitives.css, tokens.css, accents.css, FilesPage.css, Graph*.css, Pipeline*.css, FormField.css, NodeCard.css, etc.). No functional behavior changes expected.
This commit is contained in:
Ludy87
2026-08-13 16:15:25 +02:00
parent cf65e69f0c
commit e1d16b7856
20 changed files with 71 additions and 24 deletions
+16 -16
View File
@@ -8,7 +8,7 @@
"name": "stirling-pdf",
"version": "1.0.0",
"devDependencies": {
"@stylistic/stylelint-plugin": "^5.2.1",
"@stylistic/stylelint-plugin": "^5.3.0",
"stylelint": "^17.14.1",
"stylelint-config-standard": "^40.0.0"
}
@@ -300,17 +300,17 @@
}
},
"node_modules/@stylistic/stylelint-plugin": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-5.2.1.tgz",
"integrity": "sha512-BMRWJVtO16uADJmKcGi6mreei/QYdOviABXuaCeHEc3T3pxo4wFYYSvnxIoyiPVfDJqX+DxQdnGkuc6KxsRaSw==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-5.3.0.tgz",
"integrity": "sha512-xbyxPeaO9Vns6A8/0MQV6PzZ5nNZCoGV4q1ERaNd5EBAKlWt+YcpaPapNYNUkZaiQg98+xPbikdA58ehquJG3g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0",
"@csstools/media-query-list-parser": "^5.0.0",
"postcss": "^8.5.8",
"postcss-selector-parser": "^7.1.1",
"postcss": "^8.5.26",
"postcss-selector-parser": "^7.1.5",
"postcss-value-parser": "^4.2.0",
"style-search": "^0.1.0"
},
@@ -1041,9 +1041,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.16",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
"integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -1122,9 +1122,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.25",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
"integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"version": "8.5.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
"integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"dev": true,
"funding": [
{
@@ -1142,7 +1142,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.16",
"nanoid": "^3.3.17",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -1178,9 +1178,9 @@
}
},
"node_modules/postcss-selector-parser": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz",
"integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==",
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz",
"integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==",
"dev": true,
"license": "MIT",
"dependencies": {
+1 -1
View File
@@ -6,7 +6,7 @@
"lint:css:fix": "stylelint \"../app/**/src/main/resources/static/css/*.css\" \"../frontend/editor/src/**/*.css\" --config .stylelintrc.json --fix"
},
"devDependencies": {
"@stylistic/stylelint-plugin": "^5.2.1",
"@stylistic/stylelint-plugin": "^5.3.0",
"stylelint": "^17.14.1",
"stylelint-config-standard": "^40.0.0"
}
@@ -348,6 +348,7 @@
}
.files-page-list-row.is-header [data-sortable="true"] {
/* Block so the hit area and hover tint fill the columnheader cell that wraps
it, rather than hugging the label text. */
display: block;
@@ -1134,6 +1135,7 @@
.files-page-details-version-timeline-expand-btn:hover span {
color: var(--c-text);
}
.files-page-details-version-timeline-delta {
font-size: 0.82rem;
color: var(--c-text);
@@ -1145,18 +1147,22 @@
align-items: baseline;
gap: 0.25rem;
}
.files-page-details-version-timeline-delta.is-origin {
font-weight: 400;
color: var(--c-text-subtle);
font-style: italic;
}
.files-page-details-version-timeline-delta-plus {
color: var(--c-accent-text);
font-weight: 700;
}
.files-page-details-version-timeline-spacer {
flex: 1;
}
.files-page-details-version-timeline-chevron {
color: var(--c-text-subtle);
transition: transform 0.15s ease;
@@ -222,6 +222,7 @@
/* Error helper text above the input */
.errorText {
margin-top: 0.25rem;
/* The brand red is a fill; error copy takes the theme's error ink. */
color: var(--color-red-dark);
}
+3 -1
View File
@@ -64,6 +64,7 @@
--gray-100: 243 244 246;
--gray-200: 229 231 235;
--gray-300: 209 213 219;
/* Channel form of gray-400. Only for decorative fills/borders — as text it
reaches 2.3:1, so label copy uses --gray-600. */
--gray-400: 156 163 175;
@@ -138,7 +139,6 @@
--color-yellow-700: var(--p-amber-600);
--color-yellow-800: var(--p-amber-600);
--color-yellow-900: var(--p-amber-600);
--color-red-50: var(--p-red-50);
--color-red-100: var(--p-red-100);
--color-red-200: var(--p-red-200);
@@ -583,6 +583,7 @@
}
/* Plan section card borders - only override in dark mode */
/* Current plan badge - use light mode green in dark mode */
[data-mantine-color-scheme="dark"] .current-plan-badge {
background-color: var(--color-green-300) !important;
@@ -596,6 +597,7 @@
[data-mantine-color-scheme="dark"]
.plan-button:not(:disabled):not([data-disabled]) {
background-color: var(--p-royal-700) !important;
/* The fill is set here, so the label has to be set with it — left alone it
keeps the scheme's default ink and reads as dark-on-deep-blue. */
color: var(--p-white) !important;
+10
View File
@@ -32,6 +32,7 @@ html[data-app-theme="light"] {
--c-success: var(--p-green-600);
--c-danger: var(--p-red-600);
--c-warning: var(--p-amber-600);
/* Solid fills that carry a white label. Deeper than the --c-<tone> values
above, which are picked for surfaces, borders and icons where the 3:1
non-text floor applies. Scheme-independent: a filled badge reads white on
@@ -41,11 +42,13 @@ html[data-app-theme="light"] {
--c-warning-solid: var(--p-amber-700);
--c-neutral-solid: var(--p-gray-600);
--c-accent-solid: var(--p-blue-600);
/* Ink for surfaces that are white in both schemes — a rendered page, a
signature sheet. Scheme-independent for the same reason the fills above
are: the ground does not change, so the ink must not either. */
--c-text-on-light: var(--p-ink);
--c-accent-on-light: var(--p-blue-700);
/* Highlight/flash (search hits, compare jump-to) — same in both themes. */
--c-highlight: var(--p-flash-yellow);
@@ -173,6 +176,7 @@ html[data-app-theme="custom"] {
--c-primary-subtle: color-mix(in srgb, var(--c-primary) 14%, transparent);
--c-text-on-primary: var(--p-white);
--c-accent-fg: var(--c-primary);
/* Accent used as TEXT: --c-primary and its 80% hover both land under
4.5:1 on the accent-tinted surfaces they appear on (chips, links,
outline buttons), so accent copy takes a deeper step of the hue. */
@@ -205,6 +209,7 @@ html[data-app-theme="custom"] {
--color-primary-300: color-mix(in srgb, var(--c-primary) 55%, var(--p-white));
--color-primary-400: color-mix(in srgb, var(--c-primary) 78%, var(--p-white));
--color-primary-500: var(--c-primary);
/* Shade 600 is the ramp's text-capable step — Mantine maps it to shade 6,
which drives link colour and the tuple's default text. At 88% it lands
at 4.2:1 on the page, so it mixes further down. Filled surfaces read
@@ -227,6 +232,7 @@ html[data-app-theme="custom"] {
var(--c-primary) 18%,
transparent
);
/* Text of the light/subtle variants — the fill value only reaches ~3:1 on
its own tint, so accent copy takes the deeper step. */
--mantine-primary-color-light-color: var(--c-accent-text);
@@ -299,10 +305,12 @@ html[data-app-theme="custom"] {
/* ── DARK — editor dark theme: neutral text/borders/icons + accent-tinted surfaces (default override opts out). After :root so it wins for dark. ── */
html[data-app-theme="custom"][data-mantine-color-scheme="dark"] {
--c-accent-text: var(--p-blue-400);
/* Shade 600 is the ramp's text-capable step (Mantine's shade 6 — link colour
and the tuple's default text). The light theme reaches it by mixing toward
black; on a dark ground it has to travel the other way to stay readable. */
--color-primary-600: color-mix(in srgb, var(--c-primary) 85%, var(--p-white));
/* The accent's tint rungs, which back every light-variant surface. The light
theme builds them by mixing toward white; left unmixed for dark they stay a
pale blue and put dark-theme ink on a near-white ground. */
@@ -311,12 +319,14 @@ html[data-app-theme="custom"][data-mantine-color-scheme="dark"] {
--color-primary-200: color-mix(in srgb, var(--c-primary) 35%, var(--c-bg));
--color-primary-300: color-mix(in srgb, var(--c-primary) 55%, var(--c-bg));
--color-primary-400: color-mix(in srgb, var(--c-primary) 78%, var(--c-bg));
/* The inks that sit on those tints. Mixing toward black is what makes them
readable on a pale ground; on the dark tints above they have to travel
toward white for the same reason. */
--color-primary-700: color-mix(in srgb, var(--c-primary) 70%, var(--p-white));
--color-primary-800: color-mix(in srgb, var(--c-primary) 55%, var(--p-white));
--color-primary-900: color-mix(in srgb, var(--c-primary) 40%, var(--p-white));
/* Neutral text / borders / overlay (not accent-tinted). */
--c-text: var(--p-snow);
--c-text-muted: var(--p-zinc-200);
@@ -32,6 +32,7 @@
--p-zinc-600: #333338;
--p-zinc-500: #3f3f46;
--p-zinc-400: #52525b;
/* Subtlest text shade that still clears 4.5:1 on the deepest dark
surfaces; zinc-300 is a border/icon shade and reads at ~3:1 there. */
--p-zinc-250: #9a9aa2;
+5 -2
View File
@@ -46,6 +46,7 @@
var(--p-blue-400) 40%,
var(--p-white)
);
/* The -dark shades are the on-light TEXT colours (accents.css --_text and
status copy). They have to clear 4.5:1 on the tinted -light surfaces they
sit on, not just on the page, which is why they sit well below the base
@@ -114,6 +115,7 @@
--color-tooltip-text: var(--p-gray-50);
/* Navigation */
/* Form/section labels are small uppercase text, so they need a real text
shade: gray-400 only reaches 2.3:1 on the page background. */
--color-section-label: var(--p-gray-600);
@@ -177,6 +179,7 @@
--code-bg-alt: var(--p-c-eef1f4);
--code-bg-header: var(--p-c-eaeef2);
--code-text: var(--p-c-1f2328);
/* Both sit on --code-bg-header, the darkest of the code grounds, so they run
deeper than a plain "dim/muted" pair would on white. */
--code-dim: var(--p-c-656d76);
@@ -198,7 +201,6 @@
/* Bumped from #475569 (fails AA) — see light-theme note. */
--color-text-placeholder: var(--p-gray-600);
--color-blue: var(--p-blue-500);
--color-blue-light: var(--p-zinc-750);
--color-blue-border: var(--p-zinc-600);
@@ -218,6 +220,7 @@
--color-red: var(--p-red-400);
--color-red-light: var(--p-zinc-800);
--color-red-border: var(--p-red-600);
/* The -dark shades are this theme's TEXT colours. On the dark card and
raised surfaces red-500 only reaches ~3.9:1, so error copy runs a step
lighter than the base hue. */
@@ -251,7 +254,6 @@
/* Uppercase 12px label text: the light theme's grey only reaches 2.3:1
on the dark surfaces, so this theme takes a real on-dark shade. */
--color-section-label: var(--p-zinc-200);
--color-search-border-hover: var(--p-gray-600);
--color-search-text: var(--p-gray-500);
--color-usage-text: var(--p-gray-500);
@@ -275,6 +277,7 @@
--code-bg-alt: var(--p-c-1e293b);
--code-bg-header: var(--p-c-1a2332);
--code-text: var(--p-gray-250);
/* Sits on the code header, the lightest of the dark code grounds, where
the mid-slate only reaches 3.3:1. */
--code-dim: var(--p-c-8b9bb4);
@@ -14,6 +14,7 @@
}
.sui-field__required {
/* The base red is a fill colour; as text on the form background it only
reaches 3.4:1. */
color: var(--color-red-dark);
+1
View File
@@ -64,6 +64,7 @@
.sui-node-card__detail {
font-size: 0.6875rem;
/* --c-text-subtle does not clear 4.5:1 at this size in either theme (axe: 4.39 light, 3.66
dark); --c-text-muted is the next rung up and does. */
color: var(--c-text-muted);
+10 -4
View File
@@ -9,6 +9,7 @@
var(--c-btn-inverse)
);
--_on: var(--c-btn-inverse);
/* Deeper than --c-primary-hover, which lands at 4.28:1 on the accent tint. */
--_text: var(--c-accent-text);
--_bd: color-mix(in srgb, var(--c-primary) 38%, var(--c-surface));
@@ -28,11 +29,13 @@
/* Danger is pinned to a fixed deep red (not the theme-lightened coral), so the
fill and the outline/text are the SAME red in both light and dark. */
.sui-acc-danger {
/* One step deeper than the base red so the white label on the filled
variant clears 4.5:1. */
--_solid: var(--p-red-600);
--_solid-hover: var(--p-red-700);
--_on: #ffffff;
--_on: #fff;
/* Theme-aware like the other accents: the mid red only clears 3.6:1 as text
on a light surface, so light mode needs the deeper shade while dark mode
needs the lighter one. */
@@ -42,22 +45,24 @@
}
.sui-acc-success {
/* The base green is a tint/border colour; as a fill behind white text it
only reaches 2.3:1, so the solid variant uses the deeper shade. */
--_solid: var(--p-green-700);
--_solid-hover: var(--p-green-800);
--_on: #ffffff;
--_on: #fff;
--_text: var(--color-green-dark);
--_bd: var(--color-green-border);
--_tint: color-mix(in srgb, var(--color-green) 12%, transparent);
}
.sui-acc-warning {
/* Deepened so the white label clears 4.5:1, matching how danger and success
resolve the same problem — every filled accent reads white-on-colour. */
--_solid: var(--p-amber-700);
--_solid-hover: var(--p-amber-800);
--_on: #ffffff;
--_on: #fff;
--_text: var(--color-amber-dark);
--_bd: var(--color-amber-border);
--_tint: color-mix(in srgb, var(--color-amber) 12%, transparent);
@@ -123,7 +128,8 @@
var(--p-blue-500) 72%,
var(--p-cyan-400) 100%
);
--_on: #ffffff;
--_on: #fff;
/* The gradient's mid indigo is a fill colour; as text on the light surface
it only reaches 4.1:1 (3.6:1 on its own tint). */
--_text: var(--p-indigo-600);
@@ -26,6 +26,7 @@
flex: 1 1 auto;
min-height: 0; /* scroll instead of growing past the viewport */
overflow-y: auto;
/* Hold the scrollbar's width whether or not it is showing. Without this, a page that grows past
the viewport (an editor panel filling in, say) makes the bar appear and shunts everything
sideways as it does. */
@@ -148,6 +148,7 @@
.portal-pf__node--soon {
background: transparent;
border-style: dashed;
/* The dashed border and muted ink mark this as not-yet-available; fading the
whole node with opacity would drop its label below the contrast floor. */
color: var(--c-text-muted);
@@ -10,6 +10,7 @@
background: var(--c-surface);
border: 1px solid var(--c-border-subtle);
border-radius: var(--radius-lg);
/* The builder caps its columns so the page itself does not scroll, which means a settings form
taller than the viewport has to scroll in here - otherwise its lower half is unreachable. */
max-height: 100%;
@@ -5,12 +5,14 @@
.portal-graph-edge {
position: absolute;
/* A wide drop target: the wire is a thin line, but a dragged step can be released anywhere across
the row, so the whole band between the nodes catches it. `left` is the column centre, so pull
back by half to keep the band centred on it. Line, insert and warning are placed absolutely
within. */
width: 16rem;
transform: translateX(-50%);
--edge-color: var(--c-border-strong);
}
@@ -47,6 +49,7 @@
.portal-graph-edge__insert.sui-ai {
position: absolute;
top: 50%;
/* Beside the wire: the column centre is 50%, nudge clear of the line and centre on the row. */
left: 50%;
transform: translate(0.6rem, -50%);
@@ -128,6 +131,7 @@
padding: 0.0625rem 0.375rem;
border-radius: var(--radius-pill);
border: 1px solid var(--c-warning);
/* Matches the shared Banner's warning treatment: tinted ground, amber border and glyph, ordinary
text. Amber words would not clear 4.5:1 at this size, and the tint is what makes the neutral
text read as part of a warning rather than as stray body copy. */
@@ -36,6 +36,7 @@
.portal-graph-node__remove.sui-ai {
position: absolute;
top: -0.4375rem;
/* Logical, so in RTL the remove sits on the card's trailing (left) corner rather than on top of
the leading icon badge. */
inset-inline-end: -0.4375rem;
@@ -128,6 +129,7 @@
100% {
opacity: 0.35;
}
50% {
opacity: 1;
}
@@ -9,10 +9,12 @@
align-items: center;
gap: 0.75rem;
padding: 1.5rem 1rem;
/* Grows with the chain up to whatever the page gives it, then scrolls rather than pushing the
inspector out of reach. A short chain still hugs its content, so there is no empty canvas. */
max-height: 100%;
overflow: auto;
/* The canvas must sit below the node cards on the surface ladder so they read as raised off it in
both themes. --c-surface-sunken is the only rung darker than --c-surface in light *and* dark;
the legacy --color-bg-subtle collapsed into the page in dark, and --c-bg-raised is lighter than
@@ -26,6 +28,7 @@
.portal-graph__drag-hint {
position: absolute;
margin: 0;
/* `left` is the column centre; clear the wire's hit area before the text starts. */
transform: translate(1.75rem, -50%);
white-space: nowrap;
@@ -36,6 +36,7 @@
display: grid;
grid-template-columns: 1.4fr 1fr;
gap: 1.25rem;
/* Takes whatever the header leaves, and pins the row to exactly that. `minmax(0, 1fr)` rather
than the implicit `auto` row is what makes the columns' `max-height: 100%` mean anything: an
auto row is sized BY its tallest item, so a long settings form would size the row to itself and
@@ -76,6 +77,7 @@
}
/* Tool picker */
/* The picker fills the modal hosting it rather than sitting in a card of its own: same surface,
same radius, so a bordered box in here would frame nothing. Its rows carry the structure, and
they run to the panel's edges - which is what lets the search divider span the full width. */
@@ -70,6 +70,7 @@
}
.portal-policies__card--locked {
/* Recede via surface and ink rather than opacity, which would fade the
card's own text below the contrast floor. */
background: var(--c-surface-sunken);
@@ -16,6 +16,7 @@
}
.text-divider .text-divider__label {
/* A single channel triple cannot follow the colour scheme, and the old
fallback only reached 3.8:1 on the dark page. The muted text token carries
the readable shade for each scheme; the opacity hook is kept separate. */