From d767d88c03f4eea0c47ccb6c81bd2338971b187e Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 28 May 2026 00:56:13 +0200 Subject: [PATCH] fix(codex-audit): close P0 + tokenize drift introduced by Words sprint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three categories of audit drift introduced during the recent Words sprints (drawer redesign, image float bar, color marks, insert panel, gutter rail), all caught by the existing contract tests now that the work has landed: 1. **Undeclared morfo attr** (P0 contracts test): `data-words-block-selected` is stamped by the engine's render on the atomic-selected block (today only image) but wasn't in the morfo's data-attr list. Adds it as optional on the same parts array that already declares `data-words-image-*`. 2. **Missing i18n key** (translations:check): The drawer part references `components.words.drawer` for its aria-label, but the langs catalog was never updated when DRAWER-CANON landed. Add `drawer` to `src/uix/langs/components/words.ts` (es + en). 3. **Recipe CSS contract drift** (eidos recipe-css-contract test): - 3 undeclared CSS vars used in the drawer-Editable styles: `--words-toolbar-color` → `--words-command-color` `--words-command-hover-bg` → `--words-command-bg-hover` `--words-command-active-color` → `--words-command-color-hover` (Right names per `lib/recipes/base.ts > words`.) - 15 raw font-size literals (0.65rem / 0.7rem / 0.75rem / 0.8rem / 0.9rem) replaced with the existing words font-size tokens: 0.65/0.7rem → `var(--words-status-font-size)` 0.75/0.8rem → `var(--words-font-size-sm)` 0.9rem → `var(--words-font-size-md)` Result: - `contracts.test.ts`: 31→32 pass (the data-attr violation is gone). - `translations:check`: 219 refs / 76 catalogs / 0 errors / 0 warnings. - `recipe-css-contract.test.ts`: 17→19 pass. - Full `vitest run src/uix`: **867/867** pass (was 865/2-fail before). - `npm run check` clean (only 6 pre-existing errors unrelated). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/uix/eidos/components/words/words.css | 40 ++++++++++++------------ src/uix/langs/components/words.ts | 4 +++ src/uix/morfo/components/words.ts | 7 +++++ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/uix/eidos/components/words/words.css b/src/uix/eidos/components/words/words.css index 4214d1ced..71c6d09c9 100644 --- a/src/uix/eidos/components/words/words.css +++ b/src/uix/eidos/components/words/words.css @@ -316,7 +316,7 @@ background: var(--words-toolbar-bg); color: var(--words-command-color); font: inherit; - font-size: 0.8rem; + font-size: var(--words-font-size-sm); cursor: pointer; text-align: start; transition: @@ -343,7 +343,7 @@ font-weight: var(--words-strong-font-weight); letter-spacing: 0.02em; text-transform: uppercase; - font-size: 0.7rem; + font-size: var(--words-status-font-size); color: var(--words-status-color); } @@ -401,7 +401,7 @@ border: 0; background: transparent; color: var(--words-status-color); - font-size: 0.7rem; + font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; @@ -498,7 +498,7 @@ [data-words-drawer-section-subtitle] { color: var(--words-status-color); - font-size: 0.65rem; + font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; @@ -527,7 +527,7 @@ min-block-size: auto; white-space: normal; line-height: 1.35; - color: var(--words-toolbar-color); + color: var(--words-command-color); } [data-editable][data-words-drawer-editable] [data-editable-preview][data-placeholder-shown] { @@ -560,8 +560,8 @@ [data-editable][data-words-drawer-editable] [data-editable-edit-trigger]:hover { opacity: 1; - background: var(--words-command-hover-bg); - color: var(--words-command-active-color); + background: var(--words-command-bg-hover); + color: var(--words-command-color-hover); } /* Edit mode: stack vertically. Textarea fills the row, action chips @@ -583,7 +583,7 @@ border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-command-radius); background: var(--words-bg, var(--words-toolbar-bg)); - color: var(--words-toolbar-color); + color: var(--words-command-color); font: inherit; line-height: 1.35; outline: none; @@ -641,7 +641,7 @@ gap: 0.2rem; margin-inline-start: 0.4rem; color: var(--words-status-color); - font-size: 0.65rem; + font-size: var(--words-status-font-size); font-weight: normal; letter-spacing: 0; text-transform: none; @@ -711,7 +711,7 @@ border-radius: 999px; background: transparent; color: var(--words-status-color); - font-size: 0.9rem; + font-size: var(--words-font-size-md); line-height: 1; cursor: pointer; } @@ -965,7 +965,7 @@ align-items: baseline; gap: var(--words-command-gap); margin: 0 0 var(--words-toolbar-py-sm) 0; - font-size: 0.7rem; + font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; @@ -982,14 +982,14 @@ border-radius: 999px; background: var(--_words-accent-solid); color: var(--_words-accent-on); - font-size: 0.65rem; + font-size: var(--words-status-font-size); } [data-words-drawer-empty] { margin: 0; color: var(--words-status-color); font-style: italic; - font-size: 0.8rem; + font-size: var(--words-font-size-sm); } [data-words-drawer-empty][data-tone='affirm'] { @@ -1011,7 +1011,7 @@ align-items: baseline; gap: 0.4rem; padding-inline-start: 0; - font-size: 0.8rem; + font-size: var(--words-font-size-sm); line-height: 1.3; } @@ -1027,7 +1027,7 @@ flex-shrink: 0; min-inline-size: 1.5rem; color: var(--_words-accent-text); - font-size: 0.65rem; + font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; } @@ -1050,13 +1050,13 @@ justify-content: space-between; align-items: baseline; gap: 0.5rem; - font-size: 0.8rem; + font-size: var(--words-font-size-sm); } [data-words-drawer-stats] dt { margin: 0; color: var(--words-status-color); - font-size: 0.7rem; + font-size: var(--words-status-font-size); text-transform: uppercase; letter-spacing: 0.04em; } @@ -1080,7 +1080,7 @@ padding-inline: 0.5rem; border-radius: var(--words-command-radius); background: color-mix(in srgb, var(--words-toolbar-border) 30%, transparent); - font-size: 0.75rem; + font-size: var(--words-font-size-sm); line-height: 1.35; } @@ -1109,7 +1109,7 @@ border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-color); - font-size: 0.75rem; + font-size: var(--words-font-size-sm); font-weight: var(--words-strong-font-weight); cursor: pointer; transition: @@ -1152,7 +1152,7 @@ border-radius: var(--words-command-radius); background: color-mix(in srgb, var(--words-toolbar-border) 30%, transparent); color: var(--words-command-color); - font-size: 0.75rem; + font-size: var(--words-font-size-sm); line-height: 1.35; word-break: break-all; } diff --git a/src/uix/langs/components/words.ts b/src/uix/langs/components/words.ts index f7365a936..94c6e3580 100644 --- a/src/uix/langs/components/words.ts +++ b/src/uix/langs/components/words.ts @@ -36,5 +36,9 @@ export const wordsLangs = { status: { es: 'Estado del editor', en: 'Editor status' + }, + drawer: { + es: 'Cajón companion del editor', + en: 'Editor companion drawer' } } satisfies LangNode; diff --git a/src/uix/morfo/components/words.ts b/src/uix/morfo/components/words.ts index b3f09dd85..aa50637eb 100644 --- a/src/uix/morfo/components/words.ts +++ b/src/uix/morfo/components/words.ts @@ -261,6 +261,13 @@ export const wordsMorfo = { values: ['pending', 'error'], severity: 'optional' }, + /** + * Block-selection marker. The engine stamps this on the + * currently atomic-selected block (today only `image` since + * other block types receive a text caret). Eidos selectors + * use it to paint the accent outline + open the float bar. + */ + { attr: 'data-words-block-selected', severity: 'optional' }, { attr: 'data-words-cell-header', severity: 'optional' }, { attr: 'data-words-cell-align',