Журнал изменений

Официальный сайт SLAED CMS

Журнал изменений

Фильтр и поиск

Всего: 1131 Доступных коммитов | Отфильтровано: 1131 Коммиты | Страница: 1 / 114
Сегодня (20.08.2026)
Docs: the two questions batch 7 left about the rig are written down where they will be found
Автор: Eduard Laas | Дата: 18:11 20.08.2026

Both are about what the gates can see rather than about either theme, and neither blocks the freeze. They are recorded in the risk that names them, in the description of the walk that would change, and as a step of batch 8 that has to answer them.

Core changes:

  1. The dark-mode risk carries what batch 7 measured (docs/THEME-ETALON-2026.md):
  2. Two dark breaks shipped green through every gate and were found by looking

    • The headline over the photo band flipped from white to near-black, because the band
is a photograph with no dark variant while --sl-on-solid turns over
  • The footer wordmark vanished when the band under it inverted, because the wordmark
is an image with white baked into it
  • Both pass AA in both modes, so no contrast pair could report either
  • Until modes gains dark, a batch that touches colour opens the pages in dark, looks at them, and says in its report that it did

  • The walk's sheer-fill reading is named as a half answer (docs/THEME-ETALON-2026.md):
  • Passing through a fill under 0.5 alpha removed exactly two false readings in batch 7
  • It also leaves the honest ones unmeasured: white text on a twenty per cent veil over a photograph now reports nothing rather than something wrong

  • Compositing is the whole answer, about twenty lines in getContrastPairs(), and needs both halves of the registry re-generated in one run

  • Batch 8 gains the step that decides them (docs/THEME-ETALON-2026.md):
  • The cost of each is stated: 168 images and about 72 MB against the only gate that would have caught either break; twenty lines against a registry that may surface new pairs

Benefits:

  • A question asked once is not asked again from scratch, and its cost is already priced
  • The next colour batch knows it owes a look in dark until the manifest covers it

Technical notes:

  • Documentation only; no code, no theme and no gate changes
Feature: the second etalon closes, and the site learns to turn its own lights
Автор: Eduard Laas | Дата: 17:59 20.08.2026

Batch 7 of docs/THEME-ETALON-2026.md. Lite's last 386 untokenised decisions reach a token, its whole palette gains a second half through light-dark(), and the frontend gains the colour-mode switch on the plumbing the panel already had. Both themes now report zero on every count they control, in both modes.

Core changes:

  1. Every decision left in lite reaches one address (templates/lite/assets/css/*.css):
  2. Size, animation, shadow, background, border and outline take a component token

    • A figure sizing a control, an icon or a page region has one name, as admin has
    • An animation carries its own dur and ease; a shadow is one whole value at one name
  3. Four laws replaced four zoos rather than renaming them

    • The tinted pill: six tone classes and eight state marks read one --sl-chip-bg
    • The focus ring: outline and box-shadow draw one --sl-ring-width in one --sl-ring-bg,
and a status ring mixes its own colour at --sl-ring-mix
  • The tile: --sl-ico-bg and --sl-ico-border read currentColor, and only the ratio is
hoisted where the tone is itself scoped
  • The arrow: every CSS triangle in the theme reads one --sl-arrow-width
  • The colour tail folded onto the roles it had been spelling by hand

    • --sl-color-brand and -banner onto --sl-primary-subtle, -strong onto --sl-primary-strong
    • --sl-color-text-ink onto --sl-text, -link and --sl-login-link-hover-color onto -strong
    • The eight --sl-changelog-* and the two service tones of the social icons onto roles
  • Lite carries both modes (templates/lite/assets/css/base.css):
  • color-scheme on :root, light-dark() through the palette, two data-theme selectors under the marker; no rule outside the API block names the mode

  • A tint step is a ground and nothing else: every mark that read one takes the base tone of its family, which turns over by itself

  • What a token cannot repaint stays fixed: the footer band carries the wordmark and the flag as images with white baked in, the page head carries a photograph, and the text standing on them reads --sl-band-text

  • Contrast fell 53 to 0 in light and dark together, each value derived from the luminance the ratio allows against the worst ground it really meets

  • The colour mode switch reaches the site (core/system.php, index.php, templates/lite):
  • getAdminModeSwitch() becomes getThemeModeSwitch($action) for the panel and the site alike, and one setThemeMode() writes the cookie for both handlers

  • index.php answers op=mode on the token scope the panel uses; lite's four document templates carry data-theme and the site header carries the toggle

  • A visitor who picked a mode is not cacheable: the page-cache key is the route alone, so a stored copy would hand the next visitor someone else's mode

  • Two measuring tools were wrong and are fixed (tools/ui-audit.php, tools/ui-shots.mjs):
  • getValueKind() could not read a shadow whose colour or length arrives through a token, so one name held two kinds across the themes for no visible reason; isShadowValue() reads it now, with tests/Fixtures/ui/shadow.css under it

  • The contrast walk read a mostly transparent fill as a solid surface and reported a failure against a colour nobody can see; it passes through to the ancestor that paints, at the threshold its own gradient rule already used

Benefits:

  • A new theme is one copied directory and one repainted API block, in two modes
  • Every visual decision in both shipped themes has exactly one address
  • The whole site meets AA in light and dark, measured on pairs that really meet on screen
  • dup falls 266 to 246 and scoped 103 to 92 as the folds land

Technical notes:

  • tools/ui-audit-baseline.json re-stored at the new lows; the ratchet holds them
  • tools/ui-contrast.json regenerated with credentials: 442 pairs, admin's 124 unchanged
  • 84 baseline images re-captured in one pass and verified stable on a second run
  • The mode cookie is written only through setCookies(); the toggle posts with a CSRF token that rides the dynamic-region contract on cacheable pages

  • Backward compatible: no schema, route or template contract changes
Refactor: every scale in lite lands on the ladder, and the type ladder grows the step a hero was standing on
Автор: Eduard Laas | Дата: 10:37 20.08.2026

Batch 6 of docs/THEME-ETALON-2026.md. Lite's untokenised visual decisions fall from 1209 to 386 and its bare numbers from 107 to zero: font size, line height, weight, tracking, opacity, radius and every rhythm step now reach their value through a token, and the last of the legacy scale names is retired.

Core changes:

  1. The scales of lite (templates/lite/assets/css/base.css, theme.css):
  2. 823 decisions snapped onto the shared ladders and named

    • font-weight, line-height, opacity and letter-spacing leave the bare check at zero
    • h1 to h5 take the same token per element as admin, so the heading ladder is
strictly descending at 24 / 20 / 18 / 16 / 14
  • --sl-space-xs..xl, --sl-radius-control, --sl-radius-card and the four
--sl-overlay-* are gone; the overlays are two --sl-scrim-* steps
  • the login geometry loses six names of four and five segments
  • every viewport breakpoint sits on 560 / 768 / 900 / 1200, and a query above a
step is spelled (width > step) so no pixel belongs to both branches
  • three placements written as a negative half-width margin become one left: calc(50% - n), which is the same pixel at one address

  • the thumbnail column of a list row and the padding of the login profile now say what they make room for instead of holding a figure

  • Two contract changes (tools/ui-contract.php):
  • --sl-font-hero at 48px above display: a slider headline and a dashboard number are the largest type a page carries, and folding them onto display would size a hero like an h1

  • --sl-space-9, -10 and -11 at 32 / 40 / 48: lite carries a second rhythm between the sections of a page that admin has not one atom of

  • Three figures the audit had been counting are not decisions (tools/ui-audit.php):
  • a descriptor block holds no rule, because var() is invalid inside @font-face
  • the middle of a clamp() is the rate between two bounds that are decisions themselves, and no ladder step in the contract can carry it

  • a percentage gap is measured against the width of the container, not against the rhythm of the page

  • each is covered by a fixture in tests/Fixtures/ui/ and a test that reads the answer off the fixture

Benefits:

  • one address per visual decision across every scale lite owns
  • the two etalons now share the same ladders, values included, which is what batch 8 reconciles the rest against

  • the audit stops reporting a figure that could never have been tokenised at all

Technical notes:

  • the top menu wrapped onto a second row at 900px when its gutter took the upward tie from 15 to 16; it takes the step below at 12 instead. A geometry probe over the screenshot manifest caught it, and no count could see it

  • tools/ui-baseline is re-captured for the frontend states; profile and private render in lite and need a run with SLAED_UI_USER and SLAED_UI_PASS to follow

  • the admin theme is untouched and every count it holds is still zero
Feature: lite gains the three axes it had no name for, and every motion in it lands on the ladder
Автор: Eduard Laas | Дата: 00:12 20.08.2026

Batch 5 of the theme etalon gives lite the motion, layer and gradient axes admin already carried. Not one transition, one layer or one gradient in the theme had an address of its own, so a theme author could not restyle any of them without forking rules. All three now read the same names admin does, the untokenised metric falls from 1396 to 1209 and the grammar violations from 99 to 44.

Core changes:

  1. Motion (templates/lite/assets/css/base.css, theme.css):
  2. 81 duration parts over 13 spellings snap onto --sl-time-fast, --sl-time-base and --sl-time-slow; 32 were already on a step, 31 move by 20ms or less and 18 move further

    • the two longest, the poll bar filling at 0.8s and the profile ring drawing
itself at 0.9s, take --sl-time-slow with the rest: an exception granted by
argument is how a zoo grows back, so the ladder has none in this theme
  • admin still spells its own ring --sl-knob-dur: 1s, and that divergence is
batch 8's to settle in the direction lite has taken
  • of the five curve spellings ease stays, linear is allowlisted, cubic-bezier(0.2, 0.8, 0.2, 1) folds onto --sl-ease-in-out and cubic-bezier(0.2, 0.7, 0.3, 1) onto --sl-ease-out

  • the overshoot cubic-bezier(0.3, 1.6, 0.5, 1) becomes --sl-vote-ease, because a curve leaving the 0-1 range is a different kind of motion and no ladder holds it

  • the speed dial's five hand-written delays become calc(var(--sl-dial-dur) * n) on a 0.05s step, which is the spelling admin already used

  • Layers (templates/lite/assets/css/base.css, theme.css):
  • twelve values over 26 sites become seven roles: --sl-z-base, -raised, -overlay, -dropdown, -popover, -modal and -toast

    • 0, 1, 30, 3000 and the image popup at 1000 were already a role's own value
    • 2 and 5 both mean "painted over the box it sits in" and merge into -overlay;
the only place the two sets meet is the user card, where the tool chip sits
at top: -38px and the online badge at top: 20px
  • 4, the session panel, goes up to -dropdown to stay above that badge; it
clears the tool chip by 12px, which is measured and not argued
  • four orders change and each is recorded in the plan: the header login form and the top-menu submenu fall to -dropdown and keep their old order by tie and document position, the tooltip's anchored panel and the image popup rise past the submenu, and the two fixed edge tabs fall to -popover where the footer's document position still resolves the tie their way

  • --sl-z-sticky stays undeclared, because nothing in lite reads it and a step nothing reads is a dead token

  • Gradients (templates/lite/assets/css/base.css, theme.css):
  • --sl-line-gradient becomes --sl-grad-line and --sl-bg-hover-gloss becomes --sl-grad-gloss, which drops the last name stacking a state on an axis

  • the five --sl-progress-fill-* triples fold into the categorical --sl-progress-1..5 and the five --sl-grad-progress-*, and the track into --sl-progress-bg, -border, -radius and -height; the fill height is now calc(var(--sl-progress-height) - 1px - 1px) and the flat fallback under each gradient, which no browser in the baseline ever painted, is gone

  • the three gradients one component owns take that component's address: --sl-changelog-date-bg, --sl-feedback-bg and --sl-idea-bg

  • the button bevel is composed: --sl-btn-bg holds the face, --sl-btn-text the label and one --sl-btn-shadow both edges and the lift under them, which retires the two scoped internals .sl-but had been setting on itself

  • --sl-grad-info-start/-end were a colour under a gradient prefix and one of them also painted the search button flat, so they take colour names --sl-info-subtle and --sl-info-muted; --sl-grad-success-start proved to be --sl-success-subtle spelled twice and collapses onto it, its partner becoming --sl-success-muted

  • The contract and the baseline (tools/ui-contract.php, tools/ui-audit-baseline.json):

  • the components changelog-date, feedback and idea are declared
  • the baseline is re-stored: count 1209, bare 107, names 44, scoped 107, tokens 213, with admin unchanged at zero

  • The plan (docs/THEME-ETALON-2026.md):
  • the batch 5 section is deleted rather than marked done, and the status moves to batch 6

  • every figure it touched is re-derived from the tool: the metric tables, the baseline table, the transition and layer ladder rows, the cross-theme selector count and the grammar violation split

  • the merge reasoning for the layers and the three colour names minted here are written down, because the batches after this one inherit them and no counter would recover them

Benefits:

  • a theme author can now restyle every transition, every stacking layer and every gradient in lite by editing the API block, which is what the etalon promises

  • the layer roles replace fourteen numbers picked to win one argument each, so a new overlay has a role to take instead of a number to outbid

  • one duration ladder across both themes means a motion change is one edit, not a search for eight spellings of the same fifth of a second

Technical notes:

  • durations move on purpose: 0.5s and 0.6s fall to 0.35s at seven fade and zoom sites, and the poll bar and profile ring fall to it from 0.8s and 0.9s

  • no screenshot sees a duration, so motion is verified by reading computed transition-duration, -delay and -timing-function off the rendered page: 843 transitioning elements over five lite pages, all on the ladder

  • layers are verified the same way, by resolving every computed z-index on those pages against the named roles

  • all 42 tokens this batch added or renamed resolve on the live page to the values they held before it

  • lite screenshots are identical to the stored baseline; the admin diffs the rig reports are the stand's own data, and admin renders from files this batch does not touch

  • the button label highlight is now spelled with color-mix() at --sl-btn-mix: 85%, which is the same paint as the rgba() it replaces

Вчера (19.08.2026)
Feature: the admin theme reaches zero and learns the second half of every colour it owns
Автор: Eduard Laas | Дата: 21:15 19.08.2026

Batch 4 of the theme etalon closes admin: every visual decision in its three CSS files now has exactly one address in the API block, and every colour in that block carries both modes in one declaration, so a page follows the operating system or the button in its toolbar without a second rule anywhere.

Core changes:

  1. The remaining 302 decisions (templates/admin/assets/css/base.css, theme.css, editors/toastui/skin.css):

  2. the API block grows from 135 names to 291, from --sl-form-width to the eleven --sl-col-*-width that are the track list of a fixed list table

    • a size that names a control, a panel or a column is a token; a figure that
only repeats a neighbour is a calc of it, which is why the second editor on a
form says calc(var(--sl-editor-height) * 2) and the coarse-pointer button
says calc(var(--sl-modal-act-width) + var(--sl-space-3))
  • animation duration and curve are the character of one element and become
--sl-loading-dur, --sl-drift-dur, --sl-row-dur, --sl-led-dur, --sl-alert-dur,
--sl-skel-dur, --sl-flash-dur, --sl-modal-dur and --sl-modal-ease
  • the three alert durations collapse to one, and the modal close takes the
transition ladder's fast step
  • the nine shadows and ring colours that fitted no role are settled: --sl-wrap-shadow, --sl-bar-shadow, --sl-check-ring, --sl-check-shadow, --sl-switch-ring, and one law for every focus ring -- --sl-ring-width, --sl-ring-gap, --sl-ring-mix and --sl-ring-bg

  • the two colour tails fold: --sl-color-primary-hover-soft onto --sl-primary-strong, --sl-color-text-soft onto --sl-text

  • skin.css is migrated once and copied to lite byte for byte, and lite's API block gains exactly the 41 names the copy reads

  • Light and dark (templates/admin/assets/css/base.css):
  • every colour token carries light-dark(); color-scheme is declared and the two :root[data-theme] selectors switch it

  • a shadow or a gradient stop keeps its own colour and puts the mode inside it, so the light values the screenshot baseline holds are untouched

  • --sl-on-solid turns over with the mode: in light the solid fill is the dark one and its text is white, in dark the ramp reverses and its text goes dark

  • the thirteen rules that painted text on a solid fill with var(--sl-bg) now say the role they mean; in light the two names are the same white, and only inversion tells them apart

  • The mode plumbing (core/system.php, core/security.php, core/admin.php, admin/index.php, templates/admin/layouts/*.html):

  • getThemeMode() reads the mode cookie through getCookies() and answers auto to everything it does not recognise

  • $adminvars, $sitevars and the message page core/security.php builds itself all carry the key; a render path missing it would flash the wrong mode

  • getAdminModeSwitch() renders one POST button with a CSRF token, and op=mode stores the choice through setCookies(); setCookies() marks the cookie httponly, so a script toggle could never have worked

  • both admin layouts write data-theme="{{ mode }}" on <html>
  • The contrast registry (tools/ui-shots.mjs, tools/ui-shots.json, tools/ui-contrast.json):

  • the walk drives light and dark through the cookie the CMS really reads, and files a pair once when its two colours are the same in both modes

  • a pair whose foreground equals its background is dropped: it is an element between the text and the ground the walk could not follow, not a reading

  • admin's 124 pairs replace its old 53; lite's 150 are left for its own batch
  • the seventeen failures found are closed by five darker light values and one role, and admin is at zero below AA in both modes

  • The audit tool (tools/ui-audit.php, tools/ui-contract.php):
  • color-mix() and light-dark() are walked instead of counted whole, and the mix ratio is a decision of its own kind

  • getValueKind() reads both as colours; getRgbValues() resolves light-dark() to the half asked for, or every categorical check silently measures nothing

  • the prop list gains min-width, max-width, min-height, max-height, ease and mix; the colour axis gains the tint role; vertical-align, contain-intrinsic-size and linear join the allowlist with their reasons

Benefits:

  • a new admin-like theme is made by editing one block: 291 tokens, no literal below the marker, and both modes in the same declarations

  • dark mode costs no second stylesheet and cannot drift from light, because the two values sit in one declaration and no rule outside the API block names them

  • every focus ring, tint and scrim in the theme has one address instead of nine near-identical rgba() values

Technical notes:

  • browser baseline rises to Chrome 123 / Safari 17.5 / Firefox 120 for light-dark(), above the :has() baseline already assumed

  • five light values move for contrast: --sl-primary-strong, --sl-success, --sl-success-strong, --sl-text-muted and --sl-danger are each darkened to the luminance the ratio 4.5 allows against the worst ground they really meet

  • the admin toolbar row wraps instead of squeezing, so the menu, the flags and the new toggle all keep their labels

  • the sidebar gains the 4px row gap and 20px line box its scoped set had asked for and never declared

  • screenshot baselines re-captured; only admin states moved, and the frontend is refreshed against the stand as it is today

  • lite is untouched except for the skin copy and the names it declares for it
Refactor: every scale in admin lands on the ladder, and two paddings learn to say the control they make room for
Автор: Eduard Laas | Дата: 19:11 19.08.2026

Batch 3 of docs/THEME-ETALON-2026.md. Twenty-eight font sizes, sixty-two spacings and fifteen radii were not a system, so a theme author could not change one of them without reading every rule that spelled it. They now reach one address each, and the first batch that moves pixels on purpose leaves a record of every value that moved and why.

Core changes:

  1. The type, opacity and icon ladders (templates/admin/assets/css/base.css):
  2. Eight font sizes, three line heights, four weights and one tracking role replace forty-one spellings; every em value is resolved against the size it really inherited

    • h1..h5 leave em for the ladder: 25.2/21/18.9/16.8/15.4px become 24/20/18/16/14
    • h5 takes --sl-font-body rather than the nearer 16, which keeps the heading ladder
strictly descending against h4
  • --sl-monitor-size-sm/-md/-lg/-kpi dissolve into the ladder they duplicated
  • The icon scale is admin's and lite's from here: 16/18/24/32, plus icon-xl at 48

    • --sl-size-tile-icon and --sl-img-placeholder-icon-size had no step and now have one
    • --sl-size-icon-md was read by skin.css and declared nowhere; it is declared here
  • --sl-hover-opacity becomes --sl-fade-subtle, beside --sl-fade-muted and -disabled
  • Spacing and radius (base.css, theme.css, editors/toastui/skin.css):
  • --sl-space-xs/-sm/-md/-lg and --sl-radius-control/-panel/-soft/-card are renamed and snapped in one step onto --sl-space-1..8 and --sl-radius-1..3, -pill, -circle

    • on spacing and radius a tie goes up: 3 to 4, 6 to 8, 9 to 10, 11 to 12, 14 to 16
    • on the type ladder the tie is broken by the siblings, so 11px goes down to 10 at all
twelve caption sites and 13px goes up to 14 at nine and down to 12 at five
  • --sl-thumb-radius held 30px on a 48px box, which the browser already clamped to a
circle, so it is --sl-radius-circle with no pixel moved
  • Negative margins keep their step through calc(var(--sl-space-n) * -1)
  • Three places where the layout bends and the ladder does not (theme.css, skin.css):
  • The module grid counted its own gutters as a literal 21px that no longer matched the snapped gap and dropped four columns to three; it now reads the gap it uses

  • The card of a module and the caption of a file tile held a right padding sized to clear the speed dial standing over them, and a snap to 24px ran the title under the button

    • both now say calc(var(--sl-size-chip) + var(--sl-space-3) * 2), the spelling the
sidebar block link already used
  • a padding that makes room for an absolutely positioned control is not a rhythm step,
and no count can tell the two apart
  1. Breakpoints (theme.css, skin.css):
  2. Eight widths become the four of the ladder: 1100 to 1200, 700 and 720 to 768, and 600 down to 560, because sending it up would have widened the rule by 168px instead of 40

  3. The editor skin and its copy in lite (editors/toastui/skin.css, lite/assets/css/base.css):
  4. EditorWindowTest compares the two files byte for byte, so admin's migrated skin is copied to lite in the same commit

  5. lite declares exactly the nineteen ladder names the copy reads and no more, because a step nothing reads is a dead token and dead is ratcheted at zero

  6. The contract and the gate (tools/ui-contract.php, tools/ui-audit-baseline.json):
  7. icon-xl joins the size axis; -1px and -9999px join the allowlist with their reasons
  8. Six duplicate groups the snap created under unrelated selectors are entered with the reason each is not merged, rather than merged into a list that scatters a component

  9. The baseline is re-stored: no ratcheted count grew, thirteen fell

Benefits:

  • 531 untokenised decisions leave admin: 833 to 302, with font-size, padding, margin, gap, border-radius, line-height, font-weight, opacity and letter-spacing at zero

  • Bare numbers fall from 91 to 3, and the three left are the layers of skin.css batch 4 owns
  • Grammar violations fall from 33 to 20, and every remaining one belongs to batch 4
  • lite loses 159 decisions it did not pay for, because the skin arrives migrated

Technical notes:

  • 309 values moved, each one measured: the report of every changed declaration resolved to pixels is what found the two paddings a screenshot at xl could not show

  • The frontend moved by 0.001% to 0.024% between the two captures, which is noise; all twenty admin states are re-captured and reviewed

  • The committed screenshot baseline had gone stale against the stand's own data before this batch began, so the pristine tree was captured first and the batch compared its own two runs; the same is written into the plan for the next batch

  • tools/ui-contrast.json is left untouched on purpose. Re-generated it reports 266 pairs against the committed 203, and 23 more below AA, all of them on pages the earlier walk never saw. No snap in this batch crossed the 18.66px or 14px-bold threshold, so the growth is coverage and not a regression; batches 4 and 7 own it

  • admin-monitor-knob-hover at lg does not settle between runs and stays outside the gate
Refactor: the three axes that had no names in admin get them, and the gate learns the silent half of a dead token
Автор: Eduard Laas | Дата: 15:18 19.08.2026

Batch 2 of docs/THEME-ETALON-2026.md. Motion, layers and gradients were the axes where admin reached not one value through a token, so a theme author could not restyle them without forking rules. They now have one address each, and the audit gains the check that catches a name a theme reads and declares nowhere.

Core changes:

  1. Motion (templates/admin/assets/css/base.css, theme.css):
  2. Three durations and two curves replace twelve spellings

    • 0.14/0.15/0.16s take --sl-time-fast, 0.18/0.2/0.22/0.24s --sl-time-base, 0.35/0.5s --sl-time-slow
    • ease becomes --sl-ease-out and cubic-bezier(0.2, 0.8, 0.2, 1) collapses onto --sl-ease-in-out
  3. Two motions carry the character of one element and stay component tokens

    • --sl-knob-dur holds the second-long sweep of a gauge
    • --sl-dial-dur is one stagger step and each fan item multiplies it in calc()
  4. Layers (templates/admin/assets/css/base.css, theme.css):
  5. Ten values become eight named roles from --sl-z-base to --sl-z-modal

    • the raised action cell of a hovered row joins the fan it anchors, three rules into one
    • the mark and the button of a tile join --sl-z-raised, a role the layer axis gains here
    • --sl-z-toast waits for batch 4, because the fullscreen editor of skin.css is its only occupant
  6. Gradients (templates/admin/assets/css/base.css, theme.css):
  7. Every gradient reaches one address

    • --sl-grad-line, --sl-grad-stripe and --sl-grad-progress-1..5 replace the names that spelled their values
    • the rule under the admin header moves into --sl-header-bg, taking ten literal stops with it
    • --sl-color-primary-center dissolves into the two gradients that were its only readers
  8. The level meter (templates/admin/assets/css/base.css, theme.css):
  9. Twenty-three names become fourteen

    • the track takes --sl-progress-bg, -border, -radius and -height
    • the fill is the track less its own hairline on each side, so its height has no second address
    • the five tones become a categorical set, told apart by colour and never by rank
  10. The silent half of a dead token (tools/ui-audit.php, tools/ui-contract.php):
  11. checkUnmetNames() reports a name read and declared nowhere

    • CSS answers an unknown var() by dropping the declaration, with no error and no pixel that says why
    • a read is met by the API block, a scoped declaration, a fallback at the read, or the data list
    • ratcheted at admin 7 and lite 2, so the number can only fall
  12. tests/Fixtures/ui/unmet.css holds all four ways a name is met and the one that is met by none

Benefits:

  • 170 untokenised decisions leave admin: 1003 to 833, with transition and z-index gone from the theme entirely
  • Grammar violations fall from 71 to 33, and every remaining one belongs to a batch that has not run
  • Five undeclared names and one placement bug are now visible to a gate instead of to nobody

Technical notes:

  • Values move verbatim except where the ladder collapses them: durations shift by up to 40ms, the preview thumbnail by 150ms, and the fan stagger by 10ms per item. None of it is visible to a screenshot, so it was measured on the rendered page instead

  • 84 of 84 screenshot baselines match; the dial fan and the float panel were driven by hand, because the manifest opens neither

  • skin.css is untouched on purpose: its copy in lite is byte-identical and lite has none of these tokens yet
Refactor: the theme tokens take the names the canon gives them, and the gate starts comparing what it names
Автор: Eduard Laas | Дата: 14:15 19.08.2026

Batch 1 of docs/THEME-ETALON-2026.md, token hygiene. Later batches create hundreds of new references, so a polluted API would have to be re-touched at every one of them, and once themes ship against it the names can no longer be corrected. This moves both API blocks onto the grammar, folds what only duplicated a value, and fixes the screenshot rig, which had been signing in over a scheme its own session cookie forbids.

Core changes:

  1. The API blocks (templates/admin/assets/css/base.css, templates/lite/assets/css/base.css):
  2. Every colour, size, shadow and component name that had a home under the grammar took it; 118 names left the two blocks and 84 took their place

    • --sl-color-* dropped the prefix onto roles: --sl-bg, --sl-surface,
--sl-border, --sl-text, --sl-primary, --sl-success and their steps
  • --sl-color-on-dark is --sl-on-solid, --sl-h1..h4 are --sl-font-h1..h4,
--sl-container / -sidebar / -gutter / -grid-gap are --sl-layout-*
  • 27 --sl-login- became 12 component tokens: --sl-login-, --sl-drop-*,
--sl-size-avatar, --sl-avatar-border
  • --sl-shadow-soft split by kind, which is what it always was in two themes:
a colour in admin becomes --sl-shadow-color, a shadow in lite --sl-shadow-xs
  • Dead tokens deleted: --sl-space-xl in admin, --sl-content and --sl-h3 in lite
  • Every name left unregistered carries the comment that says which batch owns
its value, because a rename is not free until that batch moves the value
  1. The consumers (theme.css, editors/toastui/skin.css, admin/modules/monitor.php, admin/modules/admins.php, templates/lite/{fragments,partials}, plugins/system/slaed.js, plugins/editors/toastui/assets/editor-upload.js, tests/Unit/EditorWindowTest.php):

  2. Each rename crossed every place in this commit, because a miss fails silently: a stray custom property is not an error and JavaScript falls through

    • Values written from outside CSS carry --sl-d-*: comment depth, profile level
and ring, group colour, session shares, arrow offset, scroll pair, dial count
  • The monitor series is categorical and lives in the API block now:
--sl-chart-up / -down / -cpu / -ram, read by the SVG monitor.php assembles
  • Twin tokens folded into what they aliased, and the four that only carried a
transform or a filter argument became the literal the allowlist already calls
structure
  • The two editor skins are byte-identical again, and admin's stopped reading
two names only lite ever declared: five backgrounds and one shadow now paint
  1. The window canon (theme.css of both themes, docs/WINDOW.md):
  2. Its theme values left the :root block that sat inside theme.css and moved into the API block as --sl-modal-width, -height, -gap and -pad-x

    • The internals the axis classes set moved onto the .sl-modal root, where a
scoped property is allowed to live
  1. The screenshot rig (tools/ui-shots.json, tools/ui-shots.mjs, tools/ui-baseline):
  2. The manifest names https, and both contexts ignore the certificate a stand signs itself

    • setCookies() marks the session cookie secure whenever homeurl is https, so
every run over http was handed a cookie the browser drops - the page came
back carrying the login block and no error to read
  • Every site baseline had been captured that way, logged out under names that
say otherwise, and profile and private had no baseline at all
  • The 84 baselines are re-captured from the pre-batch tree, so they measure the
theme and not who was signed in
  1. The audit (tools/ui-audit.php, tests/Unit/UiAuditTest.php, tests/Fixtures/ui/names.css):
  2. The state law no longer fires on a registered name: focus is a declared shadow role, so --sl-shadow-focus names a ring and not a state

    • The fixture carries the case and the test asserts it, because a wrong
classifier writes a plausible number into the baseline and everything
downstream trusts it

Benefits:

  • Grammar violations fall from 160 to 71 in admin and from 198 to 102 in lite, and every one that remains is a name waiting on the batch that owns its value

  • Dead tokens, alias chains, tokens that cannot satisfy their property and names holding two kinds across the themes are all at zero

  • Names that cannot survive inversion are gone from both themes, which is what dark mode needs before it can be a second value in one declaration

  • A theme author reads 105 and 154 tokens instead of 121 and 169, and the API block says which batch still owes the rest

Technical notes:

  • Rendering is unchanged: node tools/ui-shots.mjs --check reports no difference over 84 states, four breakpoints, both sessions and the hover and focus states the manifest drives

  • The exception is the editor skin in admin, which no manifest page opens: it gains the five backgrounds and the one shadow the file always meant to paint

  • Six groups of identical rule bodies were merged into selector lists to keep the duplicate count from rising where folding a twin token created them; no caller combines those classes today, and the class inventory stays batch 8 work

  • tools/ui-audit-baseline.json re-stored: the ratchet holds count 1003 and 1637, names 71 and 102, dup 181 and 276, scoped 88 and 109

  • No engine change: no filter added, no grammar extended, getFile() and checkFile() untouched

Feature: the theme work gets a contract that is measured and a baseline that cannot be raised
Автор: Eduard Laas | Дата: 09:52 19.08.2026

Batch 0 of docs/THEME-ETALON-2026.md. Nothing in the theme plan was enforceable before this: the rules lived in gitignored files, every figure was folklore, and no batch that moves pixels had a picture to compare against. This lands the tracked contract, the tool that measures it, the committed ratchet, the screenshot rig and the two gates that survive a clone.

Core changes:

  1. The machine contract (tools/ui-contract.php):
  2. Axes, ladders, categorical sets, declared components, the ramp and the ratchet list, tracked because .rules/, .agents/ and .claude/ are not

    • Every allowlist entry carries a written reason, and a test asserts it does
    • The markup scan excludes every lang/ directory: markup inside a translated
sentence is part of that text and moves with the translation
  1. The audit (tools/ui-audit.php):
  2. --count --bare --dist --dup --names --ramp --cross --markup, plus --file and --migrating for the edit hook, --strict and --store

    • Loads as a library as well, so its own test drives it on fixtures
    • Every violation names the token that replaces it, because an error that only
says "literal found" gets switched off
  • Reports dead tokens, alias chains, a token that cannot satisfy its property,
one name declared twice, one name holding two kinds across the themes
  1. The ratchet (tools/ui-audit-baseline.json):
  2. Committed, and the tool refuses to store while a ratcheted count is above it

    • tokens and single are recorded but not held: extracting an axis raises both
on purpose, and a component token read once is correct
  1. The screenshot rig (tools/ui-shots.json, tools/ui-shots.mjs):
  2. 19 states over four breakpoints, with the hover and focus states the manifest drives, diffed on a canvas inside the page so the rig needs no image library

    • Every state is rendered twice and the difference stored as its noise floor,
so a page nobody managed to stabilise is visibly unguarded
  • Credentials come from the environment and are never stored here
  1. The contrast gate (tools/ui-contrast.json):
  2. 203 pairs that really meet on screen, collected by walking the manifest and resolving each text colour through its ancestors and through the worst stop of a gradient; the PHP tool checks them offline on every run

    • Not the cross product of every text token against every surface token, which
reports pairs that appear nowhere and is switched off in a day
  1. The gates (tests/Unit/UiAuditTest.php, tests/Unit/ThemeContractTest.php):
  2. 55 tests hold the tool against fixtures whose answers are read off the fixture, and 10 hold both themes against the stored baseline

    • That table caught z-index: 0 being swallowed by the neutral-value allowlist
before the bare-number rule could see it - a stacking context is a decision
  1. The marker (templates/*/assets/css/base.css):
  2. / --- end tokens --- / closes the API block in both themes, one line each

Benefits:

  • Every count in the plan now names the command that produced it, and six figures that could not be reproduced were corrected against the tool

  • A regression cannot pass unnoticed: phpunit fails on any grown count, and the screenshot check fails past each state's own measured floor

  • A theme author can tell API from element styles by the marker alone

Technical notes:

  • Baseline: admin 1005 and lite 1637 untokenised decisions, 458 redundant rule blocks, 78 contrast pairs below AA, 143 occurrences of markup hardcoded in PHP

  • The image set is 36 MB and batches 3 and 6 re-capture it whole
  • The IP column of the user list and the mail fields of the configuration are masked: committed baselines are published, and a layout guard has no business carrying anyone's address into the repository

  • The profile and private-message states have no baseline; the site login does not take with the credentials this machine has and the rig says so

  • No runtime code changed, so nothing in the CMS behaves differently
Docs: three audits close the theme plan's gaps, and the switch that could never have worked
Автор: Eduard Laas | Дата: 00:08 19.08.2026

Three independent reviews found fifty-eight defects in the etalon plan, most of them mine. The gravest was silent: the dark-mode toggle was specified as a script writing a cookie, but setCookies() sets httponly, so it could not have worked at all. Every checkable claim was re-derived from the tree, and every number in the plan now names the command that produces it.

Core changes:

  1. Facts corrected against the tree (docs/THEME-ETALON-2026.md):
  2. --sl-shadow-soft was attributed to the wrong themes

    • admin holds a colour, lite a whole shadow, not the reverse
    • the "ten dead shadows" built on that mistake do not exist; both themes are correct
  3. --sl-color-primary-hover is not dead in lite: four uses in toastui/skin.css
  4. the monitor series are upload, download, CPU and RAM; there is no disk
  5. <html> lives in lite's partials/site-header.html, which opens every public page
  6. RSS carries six locale files and its index renders a real HTML page
  7. Contradictions inside the plan resolved:
  8. component tokens were forbidden literals while being the answer to a unique value
  9. breakpoints cannot be themed at all, which contradicted "edit one block"
  10. the metric claimed every batch lowers it, false for four batches of ten
  11. the ratchet baseline was written once, so a regression passed against an old figure
  12. batch 0 required the tool it builds
  13. Dark mode made buildable rather than described:
  14. the cookie goes through getCookies/setCookies with the $conf['user_c'] prefix
  15. the toggle is a POST with CSRF, because httponly blocks any script
  16. light-dark() returns a colour, so shadows compose from colour tokens instead
  17. admin plumbing lands in batch 4, lite roots and the site toggle in batch 7
  18. Gates made honest about what they can prove:
  19. contrast pairs are crawled from computed styles, not multiplied token by token
  20. the duplicate gate allowlists what a machine cannot judge
  21. theme creation is two gates, static and HTTP, sharing one lifecycle
  22. the markup scan tokenises PHP, since a grep misses concatenation and heredocs

Benefits:

  • Every figure is reproducible: eight audit flags, one per measurement
  • A snap that looks wrong now bends the layout, never the ladder
  • The machine-readable contract moves to tools/, so a clone inherits it

Technical notes:

  • Browser baseline rises to Chrome 123 / Safari 17.5 / Firefox 120
  • Plan compressed from 1085 to 867 lines with no decision dropped
  • No CSS or PHP changed in this commit

Всего: 1131 на 114 страницах по 10 на каждой странице

1 2 3 4 5 6 7 8 9 10 114
Хотите опробовать SLAED CMS в действии?
Идеи и предложения
Обратная связь
Подтверждение

Поделиться
QR-код