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

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

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

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

Всего: 1128 Доступных коммитов | Отфильтровано: 1128 Коммиты | Страница: 1 / 113
Сегодня (20.08.2026)
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
Эта неделя (18.08.2026)
Docs: the theme plan is rebuilt on measurement and gains a dark mode it cannot desynchronise
Автор: Eduard Laas | Дата: 22:30 18.08.2026

The etalon plan was audited against the tree and every number in it either verified, corrected or removed. Three token surfaces it never named turned out to break silently on rename, three numeric families had no axis at all, and the spacing ladder was aimed at the minority rhythm. The showcase pages are dropped from the repository: nothing in the application ever reached them.

Core changes:

  1. Plan corrected against the tree (docs/THEME-ETALON-2026.md):
  2. Rename surface grew from five places to eight

    • error.html holds its own :root of 39 tokens and no screenshot covers it
    • editors/toastui/skin.css consumes tokens in both themes
    • EditorWindowTest asserts a token name that batch 1 moves
  3. Ladders derived from measured peaks instead of a nominal rhythm

    • spacing runs on 5/10, not on 4: 237 sites against 142
    • the measured ladder halves the pixel movement at the same step count
  4. Three numeric families had no axis: font-weight, letter-spacing, animation

    • animation duration is recorded as the one family that gets no ladder
  5. Blind spot of the metric was twice its stated size

    • line-height and font-weight are bare numbers too, 222 further sites
  6. Dark mode designed before the API freeze (docs/THEME-ETALON-2026.md):
  7. Both values live in one declaration through light-dark()

    • no second block, no @media, so the modes cannot drift apart
    • the switch is two selectors keyed by data-theme on <html>
  8. 98 sites carry a name that lies under inversion and now fail the audit

    • --sl-color-on-dark alone is 53 of them
  9. Colour ramp steps carry roles, so a collapse is decided by role, not distance
  10. Enforcement made mechanical rather than advisory:
  11. The audit tool gains a fixture test of its own, run before it may write a baseline
  12. Contrast is gated at AA over pairs that actually meet on an element
  13. The ratchet baseline lives under tools/ so it survives a clone
  14. Showcase pages removed (demo/):
  15. 66 files, no code path reaches them, 6499 token references that would have to follow every rename for no shipped benefit

Benefits:

  • Every figure in the plan is reproducible from the tree or marked as derived by the tool
  • Dark mode costs no extra token names and cannot desynchronise from light
  • A wrong classifier in the audit tool is now caught by fixtures instead of by luck

Technical notes:

  • Browser baseline rises to Chrome 123 / Safari 17.5 / Firefox 120 for light-dark()
  • Theme rules and the token contract live in .rules/theme.md, which git does not track
  • No CSS or PHP changed in this commit
Fix: a window is placed by the layout it has and not by the animation still playing over it
Автор: Eduard Laas | Дата: 18:02 18.08.2026

The window canon read its geometry through getBoundingClientRect(), which returns the transformed box while the entry animation still holds the window at scale(0.97). Every placement, pin and clamp now reads offsetWidth, offsetLeft and offsetTop, which ignore transforms. The same class of defect is fixed where editor JavaScript wrote inline geometry over the phone sheet rule of the canon, and the last duplicate of the canon foot is gone.

Core changes:

  1. The canon engine (plugins/system/slaed.js):
  2. setWindowPlace centres on the layout width instead of the drawn one

    • an 880px window was written to left 293px instead of 280px, measured at 1440
    • the error was always the width times 1.5%, and invisible under prefers-reduced-motion
  3. The drag pins the layout position rather than the transformed one

    • grabbing the head during the opening animation jumped the window 13.2px by X and 24.0px by Y
    • the jump then stuck, because data-sl-moved stops the canon re-centring the window
  4. setWindowBounds clamps against the layout width for the same reason
  5. The emoji panel (plugins/editors/toastui/assets/editor-emoji.js):
  6. place() and sizePanel() stand down on a phone

    • both wrote inline geometry that beat the sheet rule of the canon and pushed the panel past the edge
    • the owner is now written before that turn is taken, or a second press stops closing the panel
  7. The editor fullscreen (plugins/editors/toastui/assets/editor-tags.js):
  8. Escape reaches the fullscreen only when no window stands in front of it

    • one press used to close the file manager and drop the fullscreen at once
  9. The window foot (templates//assets/editors/toastui/skin.css, templates//partials/editor-toastui-files.html):
  10. The file manager takes the canon foot, buttons and status line

    • 74 lines per theme that restated the canon values under sl-fm-* names are deleted
    • the foot now follows --sl-modal-pad, so on a phone it agrees with every other window
  11. The canon gains :hover:not([disabled]) on both foot buttons

    • the guard existed only in the deleted copy, so a disabled button lit up in every other window
  12. Sizes and names (templates/*/assets/css/theme.css, templates/lite/fragments/window-share.html):
  13. sl-modal-md is deleted: it restated the default 560px and the default needs no class
  14. Documentation (docs/WINDOW.md, demo/window-canon.html):
  15. docs/WINDOW.md describes the window as it is: structure, four axes, tokens, data attributes, JavaScript API, naming, where each window lives, traps and a check list

  16. docs/WINDOW-CANON-2026.md is removed; it was a work plan and its work is done
  17. The reference page drops a dead sl-toastui-shot class, draws its gallery with the shipped sl-shot-* rules instead of an inline grid, and states what is rather than what was

Benefits:

  • A window opens where it is meant to, and a hand that reaches for it at once is not punished
  • One declaration of the foot, so a change to the canon reaches the file manager too
  • The reference page cannot show a layout the system does not ship

Technical notes:

  • Visible change in the admin theme: the primary foot button of the file manager now darkens on hover (#076698) where it used to lighten (#207fb6), because the canon derives the hover from --sl-modal-tone while the deleted copy used --sl-color-primary-hover. It now behaves as every other canon button in that theme

  • .sl-modal-info collapses when empty, which the deleted .sl-fm-foot-info did not; the foot keeps its right alignment either way

  • .sl-fm-foot in the admin theme is untouched: it belongs to the file browser, which is not a window
  • Verified in both themes at 1440x900 and 390x844: 37 checks green, centring error 0px, drag jump 0x0, console clean; 829 tests pass

Refactor: nine dialogs of the system become one window with four axes
Автор: Eduard Laas | Дата: 15:23 18.08.2026

Every dialog of the project is now the same native <dialog> under one set of class names, so a window is described once and every theme only sets its own values for it. The program is recorded in docs/WINDOW-CANON-2026.md, which now describes what ships rather than what to do.

Core changes:

  1. The canon (templates/*/assets/css/theme.css):
  2. One block, byte-identical in both themes, replaces five different chromes

    • head plate 42px, ghost action cluster, body with its own scroll, foot with a status line
    • values copied from the editor file manager, which is the window that already worked
  3. Four axes and nothing else

    • size sm 420 / md 560 / lg 880 / xl 1120 / full
    • presentation: modal by default, data-sl-window stands beside the page
    • tone: danger, warn, success paint the icon, the stripe and the primary button
    • foot: present or simply not written
  4. .sl-modal-close and .sl-modal-wide are gone with the markup that needed them
  5. The engine (plugins/system/slaed.js):
  6. The focus trap, the top layer and the return of the focus are the browser's work now
  7. What the platform does not give is written once: setWindowOpen, setWindowClose, setWindowFront, setWindowPlace, setWindowExpand, setWindowBounds, setWindowRelease, setFirstFocus, setPageLock, isWindowModal

  8. Three Escape handlers became one, and it still lets an open speed dial win
  9. The page under a modal window stops scrolling and does not shift sideways
  10. One gallery instead of four (templates/*/partials/window-gallery.html):
  11. The editor gallery of two themes, the admin browser gallery and the lightbox built as a string in JavaScript are now one fragment with three renders

  12. Three sets of data attributes became the data-sl-shot family
  13. core/admin.php and plugins/editors/toastui/driver.php pass data to the same fragment
  14. The file manager and the emoji panel (plugins/editors/toastui/):
  15. Both are dialogs beside the page; the manual aria-hidden, the manual focus return, the manual drag and the fixed z-index ladder 31 / 10020 / 10050 are deleted

  16. skin.css keeps no sl-toastui-window-* rule at all
  17. The panel of the emoji opens above its button when there is no room below it
  18. Windows renamed to one rule (templates//fragments, templates//partials):
  19. confirm-modal, share-dialogs and icon-picker-modal become window-confirm, window-share, window-qr and window-icons

  20. The id sl_icon_modal becomes sl-icon-window; no id of the canon uses an underscore

Benefits:

  • A window is one structure, so a new one costs markup and no CSS
  • The gallery is one file, so a fix to it reaches the editor, the browser and the site
  • Themes stay independent: the block is shared, the values come from tokens

Technical notes:

  • --sl-space-xl is declared in base.css of both themes; .sl-toast consumed it undeclared, which left the toast at its static position and out of sight

  • DeskKeysTest follows the focus and Escape rule into the canon it moved to
  • demo/window-canon.html is one file with no stylesheet and no script of its own, so it cannot drift from what ships

  • No behaviour of the file manager changed except its placing, which the canon owns

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

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

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