mosaic-headless 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -29,6 +29,7 @@ fractional-index の文字列。エディタはこのモデルの一クライア
29
29
  python tools/mo.py type accordion-content # 1 つの型を、全ライブスイープに接続して表示
30
30
  python tools/mo.py check div text button # 危険な型・未知の型があれば exit 1
31
31
  python tools/mo.py style --grouped # 単独設定では必ず効かない 20 個
32
+ python tools/mo.py states --verified # 実測でコンパイルされた状態だけ
32
33
  ```
33
34
 
34
35
  そのうえでページを見る。Mosaic の失敗の仕方は 4 通りあり、
@@ -59,7 +60,10 @@ URL に対応するテンプレなし HTTP 406、未ログインには空の b
59
60
  | **スタイルプロパティ** | 98 / 98 を実ページに書き、コンパイル済み CSS と照合:58 COMPILED、18 ABSENT、21 SKIPPED |
60
61
  | **ノードプロパティ** | 181 / 181 を、各プロパティ自身の validator chain から導いた値で再測定:35 APPLIED、42 NO_EFFECT、55 NO_HOST、47 SKIPPED |
61
62
  | **レスポンシブ** | 2 サイト計 576 件の `_t`/`_m` 宣言を、サイトが実際に配信したスタイルシートに対して 1 件ずつ断言 — 全件検証済み |
62
- | **ブラウザ** | 配信されたページを Chromium の 3 つのビューポートで計算スタイル 2,237 件読み取り:1,661 件が一致、576 件は比較不能として明示、**上書き 0 件** |
63
+ | **スタイル状態** | 53 状態のうち 52 を実ページに書き、テーブルが約束するセレクタと照合:**36 件が完全一致**、12 件 NO_HOST、3 件 SKIPPED、1 件 BROKE_PAGE。どの要素にも使えるグローバル 7 状態はすべて検証済み |
64
+ | **インタラクション** | JS アニメーション経路を、ネガティブコントロール付きで保存行を読み戻しながら検証:`propertyMetas` は**受理され保存される**。プロパティ値は依然としてバインドされないが、その境界は厳密になった |
65
+ | **入場アニメーション** | ページ読み込み後の 10 時点をサンプリングし 7 項目を断言 — 再生されること、アニメーションする `@property` カウンタが 100 に達すること、ベールがヒットテストから外れること、ビューポート内に opacity 0 のまま取り残された要素がないこと、実際のクリックが文書に届くこと、そして `prefers-reduced-motion` ではベールがそもそも存在しないこと |
66
+ | **ブラウザ** | 配信されたページを Chromium の 3 つのビューポートで計算スタイル 2,282 件読み取り:1,676 件が一致、606 件は比較不能として明示、**上書き 0 件** |
63
67
  | **デザイン監査** | コントラスト、フォントフォールバック、CJK の字送り、横溢れ、テキストの切れ、1 行の文字数 — ブラウザ上で実行、**指摘 0 件** |
64
68
  | **テーマの書き出し/読み込み** | 往復検証済み:テーマ全体を書き出し、コピーとして読み込み、そのコピーがバイト単位で同一のページを配信 |
65
69
  | **実測** | REST ルート 114、element class 151、条件サブジェクト 59、23 テーブル / 206 カラム |
package/README.ko.md CHANGED
@@ -29,6 +29,7 @@ fractional-index 문자열이다. 에디터는 이 모델의 한 클라이언트
29
29
  python tools/mo.py type accordion-content # 타입 하나를 모든 라이브 스윕과 연결해 출력
30
30
  python tools/mo.py check div text button # 위험하거나 존재하지 않는 타입이면 exit 1
31
31
  python tools/mo.py style --grouped # 단독으로 설정하면 반드시 무효인 20개
32
+ python tools/mo.py states --verified # 실측으로 컴파일이 확인된 상태만
32
33
  ```
33
34
 
34
35
  그리고 페이지를 확인한다. Mosaic의 실패 방식은 네 가지이고,
@@ -59,7 +60,10 @@ URL에 맞는 템플릿 없음 HTTP 406, 로그인하지 않은 사용자
59
60
  | **스타일 속성** | 98 / 98을 실제 페이지에 쓰고 컴파일된 CSS와 대조: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
60
61
  | **노드 속성** | 181 / 181을 각 속성 자신의 validator chain에서 도출한 값으로 재측정: 35 APPLIED, 42 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
61
62
  | **반응형** | 두 사이트 합쳐 576개의 `_t`/`_m` 선언을, 사이트가 실제로 내보낸 스타일시트에 대해 하나씩 단언 — 전부 검증됨 |
62
- | **브라우저** | 전달된 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일 2,237건 판독: 1,661건 일치, 576건은 비교 불가로 명시, **덮어쓰기 0건** |
63
+ | **스타일 상태** | 53개 상태 중 52개를 실제 페이지에 쓰고 표가 약속한 셀렉터와 대조: **36개가 정확히 일치**, 12개 NO_HOST, 3개 SKIPPED, 1개 BROKE_PAGE. 어떤 요소에나 쓸 수 있는 전역 7개 상태는 전부 검증됨 |
64
+ | **인터랙션** | JS 애니메이션 경로를 음성 대조군과 함께, 저장된 행을 되읽으며 검증: `propertyMetas`는 **수용되고 저장된다**. 속성 값은 여전히 바인딩되지 않지만 그 경계는 이제 정확하다 |
65
+ | **인트로 애니메이션** | 페이지 로드 후 10개 시점을 샘플링해 7가지를 단언 — 재생될 것, 애니메이션되는 `@property` 카운터가 100에 도달할 것, 베일이 히트 테스트에서 빠질 것, 뷰포트 안에 opacity 0으로 갇힌 요소가 없을 것, 실제 클릭이 문서에 닿을 것, 그리고 `prefers-reduced-motion`에서는 베일이 아예 존재하지 않을 것 |
66
+ | **브라우저** | 전달된 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일 2,282건 판독: 1,676건 일치, 606건은 비교 불가로 명시, **덮어쓰기 0건** |
63
67
  | **디자인 감사** | 명암비, 폰트 폴백, CJK 자간, 가로 넘침, 텍스트 잘림, 한 줄 글자 수 — 브라우저에서 실행, **지적 0건** |
64
68
  | **테마 내보내기/가져오기** | 왕복 검증: 테마 전체를 내보내 사본으로 가져왔고, 사본이 바이트 단위로 동일한 페이지를 제공 |
65
69
  | **실측** | REST 라우트 114개, element class 151개, 조건 주체 59개, 23개 테이블 / 206개 컬럼 |
package/README.md CHANGED
@@ -29,6 +29,7 @@ reduces the whole public page to a 54-byte error string.
29
29
  python tools/mo.py type accordion-content # one type, joined to every live sweep
30
30
  python tools/mo.py check div text button # exits 1 on an unsafe or unknown type
31
31
  python tools/mo.py style --grouped # the 20 that are inert set on their own
32
+ python tools/mo.py states --verified # the states measured to compile
32
33
  ```
33
34
 
34
35
  Then check the page. Mosaic has four failure modes and **only one of them changes the
@@ -60,7 +61,10 @@ factories, so Pro types register and render regardless.
60
61
  | **style properties** | 98 / 98 written to a live page and checked against the compiled CSS: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
61
62
  | **node properties** | 181 / 181 re-probed with a value shaped by each property's own validator chain: 35 APPLIED, 42 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
62
63
  | **responsive** | 576 `_t`/`_m` declarations across two sites asserted against the stylesheet the site actually served — all verified |
63
- | **browser** | 2,237 computed-style readings on the delivered page in Chromium at three viewports: 1,661 compared and agreed, 576 not-comparable and labelled, **0 overridden** |
64
+ | **style states** | 52 of the 53 states written to a live page and matched against the selector the table promises: **36 compiled exactly**, 12 NO_HOST, 3 SKIPPED, 1 BROKE_PAGE. All seven globally usable states verified |
65
+ | **interactions** | the JS animation path probed with negative controls and the row read back: `propertyMetas` **is** accepted and stored; the property values still do not bind, and the boundary is now exact |
66
+ | **entrance animation** | the page-load sequence sampled at ten timestamps and asserted on seven counts — it plays, its animated `@property` counter reaches 100, the veil leaves hit-testing, nothing in the viewport is stranded at opacity 0, a real click reaches the document, and under `prefers-reduced-motion` the veil never exists at all |
67
+ | **browser** | 2,282 computed-style readings on the delivered page in Chromium at three viewports: 1,676 compared and agreed, 606 not-comparable and labelled, **0 overridden** |
64
68
  | **design audit** | contrast, font fallback, CJK tracking, overflow, clipped text, line measure — run in the browser, **0 findings** |
65
69
  | **theme export/import** | round-tripped: a full theme exported, re-imported as a copy, and the copy served byte-identical pages |
66
70
  | **measured live** | 114 REST routes, 151 element classes, 59 condition subjects, 23 tables / 206 columns |
package/README.zh-TW.md CHANGED
@@ -25,6 +25,7 @@ Mosaic 把一個頁面放在 **23 張自訂資料表**裡,不在 `post_content
25
25
  python tools/mo.py type accordion-content # 一個型別,接上所有線上掃描結果
26
26
  python tools/mo.py check div text button # 型別不安全或不存在就 exit 1
27
27
  python tools/mo.py style --grouped # 那 20 個單獨設定必然無效的屬性
28
+ python tools/mo.py states --verified # 實測會編譯出來的狀態
28
29
  ```
29
30
 
30
31
  然後去看頁面。Mosaic 有四種失效模式,**其中只有一種會改變 HTTP 狀態碼**:
@@ -52,7 +53,10 @@ commit 時 PHP fatal HTTP 500 (122 種型別裡有 15 種,光放在 div
52
53
  | **樣式屬性** | 98 / 98 寫進真實頁面並對照編譯後的 CSS:58 COMPILED、18 ABSENT、21 SKIPPED |
53
54
  | **節點屬性** | 181 / 181,用每個屬性自己的 validator chain 推導出的值重測:35 APPLIED、42 NO_EFFECT、55 NO_HOST、47 SKIPPED |
54
55
  | **響應式** | 兩個站共 576 條 `_t`/`_m` 宣告,對照網站實際送出的樣式表逐條斷言——全數通過 |
55
- | **瀏覽器** | 在 Chromium 三個視窗寬度上對交付頁面做 2,237 次計算樣式讀取:1,661 條比對相符、576 條標為無法比對、**0 條被覆蓋** |
56
+ | **樣式狀態** | 53 個狀態中的 52 個寫進真實頁面,對照表格承諾的選擇器逐一比對:**36 個完全吻合**、12 個 NO_HOST、3 個 SKIPPED、1 個 BROKE_PAGE。七個可用於任何元素的狀態全數驗證 |
57
+ | **互動動畫** | 帶負對照組並讀回儲存列來探測 JS 動畫路徑:`propertyMetas` **確實**會被接受並儲存;屬性值仍然無法綁定,但界線現在很精確 |
58
+ | **入口動畫** | 在載入後十個時間點取樣並做七項斷言——它有播、被動畫的 `@property` 計數器跑到 100、遮罩退出點擊判定、視窗內沒有任何內容卡在 opacity 0、真實點擊落在文件上,而在 `prefers-reduced-motion` 下遮罩根本不存在 |
59
+ | **瀏覽器** | 在 Chromium 三個視窗寬度上對交付頁面做 2,282 次計算樣式讀取:1,676 條比對相符、606 條標為無法比對、**0 條被覆蓋** |
56
60
  | **設計稽核** | 對比度、字體回退、CJK 字距、水平溢出、文字裁切、每行字數——在瀏覽器裡跑,**0 項發現** |
57
61
  | **主題匯出/匯入** | 完整來回驗證:匯出整個主題、以副本身分匯入,副本送出的頁面逐位元組相同 |
58
62
  | **線上量測** | 114 條 REST 路由、151 個 element class、59 個條件主體、23 張表 / 206 個欄位 |
package/SKILL.md CHANGED
@@ -4,7 +4,7 @@ description: |
4
4
  Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface with `mo.py`, which joins every source table to the live sweeps so a lookup leads with the measured verdict rather than the declaration (122 node types, 181 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 151 element classes, 74 dynamic variables, 12 interaction triggers, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, the design-token and element-class layers verified against compiled CSS, the @VAR() dynamic language verified against rendered output, nine designed pages built through the tables themselves, and the delivered page re-read in Chromium at three viewports so a rule that is present, correct and still wrong cannot pass.
5
5
  license: "MIT"
6
6
  author: "moksa (https://moksaweb.com)"
7
- version: "1.3.0"
7
+ version: "1.5.0"
8
8
  ---
9
9
 
10
10
  # Headless Mosaic
@@ -38,6 +38,7 @@ python tools/mo.py props --shared # the ones every element carries
38
38
  python tools/mo.py style --grouped # the 20 that are inert set on their own
39
39
  python tools/mo.py css border-radius # which Mosaic key drives this CSS
40
40
  python tools/mo.py states --grep hover # state IDs and their selector templates
41
+ python tools/mo.py states --verified # only the ones measured to compile
41
42
  python tools/mo.py vars --namespace post # the @VAR() surface
42
43
  python tools/mo.py classes --grep Heading # element classes (theme-global)
43
44
  python tools/mo.py routes --grep template
@@ -139,9 +140,31 @@ PROPERTIES 170 probes over the declared property surface, each value asserted
139
140
  against the delivered markup and the compiled CSS separately.
140
141
  data/property-verification.csv
141
142
 
142
- BROWSER 2,237 computed-style readings on the delivered page in Chromium, at
143
+ STATES 52 of the 53 style states written to a live page and matched against
144
+ the selector `data/style-states.csv` promises: 36 COMPILED exactly,
145
+ 1 BROKE_PAGE, 12 NO_HOST (their node type cannot be committed safely),
146
+ 3 SKIPPED. All seven globally usable states verified - and the
147
+ pseudo-classes are emitted UPPERCASE (`.M_EL9:HOVER`), so grepping a
148
+ stylesheet for `:hover` finds nothing. data/style-state-verification.csv
149
+
150
+ INTERACTION the JS animation path, probed with negative controls and the row read
151
+ back: `propertyMetas` IS accepted and stored (the earlier claim that it
152
+ never survived was wrong), `uuid` per item is optional on create and
153
+ required on update, and the property VALUES still do not bind - not on
154
+ a second commit, not on one that changes `propertyMetas/order`, and not
155
+ written straight into the table with caches flushed.
156
+ data/interaction-verification.csv
157
+
158
+ INTRO the page-load sequence sampled at ten timestamps across its life and
159
+ asserted on seven counts - it plays, the animated `@property` counter
160
+ reaches 100, the veil leaves hit-testing, no in-viewport content is
161
+ stranded at opacity 0, a real click reaches the document, and under
162
+ `prefers-reduced-motion` the veil never exists at all. All pass.
163
+ data/intro-verification.csv
164
+
165
+ BROWSER 2,282 computed-style readings on the delivered page in Chromium, at
143
166
  three viewports: every declared property vs `getComputedStyle` on the
144
- node it targets. 1,661 compared and agreed, 576 not-comparable and
167
+ node it targets. 1,676 compared and agreed, 606 not-comparable and
145
168
  labelled as such, 0 overridden. Plus a design audit that only a browser
146
169
  can run - font fallback, tracking against script, text contrast,
147
170
  horizontal overflow, clipped text, line measure - currently 0 findings.
@@ -232,9 +255,17 @@ so the pattern is in the data, not just in this paragraph.
232
255
  All four are real entries in `data/style-properties.csv`, under `gridChildPosition`.
233
256
  Measured: 16 `gridColumnStart` declarations committed, zero occurrences of
234
257
  `grid-column` in the delivered CSS. Change the template; you cannot place a child.
235
- - **Interaction property binding is unsolved.** The trigger, action slot and keyframe
236
- timing all reach the browser; `propertyMetas` and per-keyframe `properties` do not.
237
- Animate with the CSS transition/state path, which is fully verified.
258
+ - **Interaction property binding is unsolved, but the boundary is now exact.** The
259
+ trigger, action slot, keyframe timing **and `propertyMetas`** all reach the
260
+ browser - the earlier claim that `propertyMetas` never survived was wrong, and the
261
+ missing field was the per-item `uuid` a `DataArray` needs. What still does not bind
262
+ is `initial` and the keyframes' `properties`, and not for want of the right shape:
263
+ they are absent after a second commit, after one that changes `propertyMetas/order`,
264
+ and after writing them **straight into `wp_mosaic_nodes` with every cache flushed**.
265
+ The gate is `KeyframePropertiesDataSub::exportForInteraction()`, which emits only
266
+ properties whose descriptor exists, and those are created during sync on a
267
+ `DataMeta` that starts empty. Animate with the CSS state path, which is fully
268
+ verified: 36 of 37 probed states compile to exactly the promised selector.
238
269
  - Committing a **condition** has not been driven end to end. The grammar in
239
270
  `references/templates-and-conditions.md` is read from source and from the live
240
271
  metas; an element carrying one rendered as hidden, which is consistent with the
@@ -280,9 +311,12 @@ so the pattern is in the data, not just in this paragraph.
280
311
  | `data/node-property-verification.csv` | 181 | **swept live** — each property probed with a value shaped by its own validator chain, on a type that declares it |
281
312
  | `data/style-verification.csv` | 98 | **swept live** — every style property written to a page and checked against the compiled CSS, with its group beside the result |
282
313
  | `data/rwd-verification.csv` | 576 | **checked live** - every `_t`/`_m` declaration vs the served stylesheet, with status per row |
283
- | `data/browser-verification.csv` | 2237 | **computed in Chromium** - declared vs `getComputedStyle` at three viewports, `not-comparable` labelled per row |
314
+ | `data/browser-verification.csv` | 2282 | **computed in Chromium** - declared vs `getComputedStyle` at three viewports, `not-comparable` labelled per row |
284
315
  | `data/design-audit.csv` | 0 | **computed in Chromium** - contrast, font fallback, CJK tracking, overflow, measure. Empty means it ran and found nothing |
285
316
  | `data/data-class-hierarchy.csv` | 121 | source - every data class and its parent, so a type's inherited properties can be resolved |
317
+ | `data/style-state-verification.csv` | 52 | **swept live** - each state written on a host of its own type and matched against its promised selector |
318
+ | `data/interaction-verification.csv` | 7 | **probed live** - interaction animation shapes, with negative controls and the stored row beside the payload |
319
+ | `data/intro-verification.csv` | 7 + 10 | **sampled live** - the entrance sequence over ten timestamps, plus the seven assertions about it |
286
320
  | `data/element-classes.csv` | 151 | **live** — the built-in class metas; their IDs are what an `elementClass` record must use |
287
321
  | `data/dynamic-variables.csv` | 74 | source — every `@VAR('ns/name')` expression, by namespace |
288
322
  | `data/evaluator-functions.csv` | 19 | source — the `@` functions with their arity |
@@ -383,9 +417,12 @@ post — `build_all.py` resets first for that reason.
383
417
  | `build_site.py` | a whole site: one master with the shell, one document per page |
384
418
  | `verify_rwd.py` | does every `_t`/`_m` declaration reach the served stylesheet? |
385
419
  | `verify_browser.py` | does the **browser** compute what the stylesheet promised - and does the result pass a design audit? |
420
+ | `verify_intro.py` | does the page-load animation play, and - the part that matters - does it END and hand the page back? |
386
421
  | `sweep_node_types.py` | commit every node type one per document and assert the delivered HTML |
387
422
  | `sweep_style_properties.py` | write every style property and check the compiled CSS |
388
423
  | `sweep_node_properties.py` | probe every node property with a value from its own validator chain |
424
+ | `sweep_style_states.py` | write every style state and check the selector it compiled to |
425
+ | `sweep_interactions.py` | which interaction animation shapes survive to the frontend payload |
389
426
  | `theme_export.php` / `theme_import.php` | move a whole theme across installs, ids intact |
390
427
  | `copy_styles.py` | push one node's style onto others, by attrID or prefix |
391
428
  | `bootstrap_probe_theme.php` | a licence-free scratch theme |
@@ -410,9 +447,14 @@ python tools/sweep_node_types.py --config sweep.json --setup
410
447
  python tools/sweep_node_types.py --config sweep.json --sweep --edition all
411
448
  python tools/sweep_properties.py --config sweep.json
412
449
  python tools/verify_rwd.py --config sweep.json --site sites/moksa.json --csv data/rwd-verification.csv
413
- python tools/verify_browser.py --config sweep.json --site sites/moksa.json --csv data/browser-verification.csv --audit data/design-audit.csv
450
+ python tools/verify_browser.py --config sweep.json --site sites/moksa.json \
451
+ --csv data/browser-verification.csv --audit data/design-audit.csv
452
+ python tools/verify_intro.py --config sweep.json --site sites/moksa.json \
453
+ --csv data/intro-verification.csv --frames shots/intro/
414
454
  python tools/sweep_style_properties.py --config sweep.json --page moksa --csv data/style-verification.csv
415
455
  python tools/sweep_node_properties.py --config sweep.json --page moksa --csv data/node-property-verification.csv
456
+ python tools/sweep_style_states.py --config sweep.json --post 20 --slug probe-lab --csv data/style-state-verification.csv
457
+ python tools/sweep_interactions.py --config sweep.json --post 20 --slug probe-lab --csv data/interaction-verification.csv
416
458
  wp eval-file tools/theme_export.php active > theme.json
417
459
  wp eval-file tools/theme_import.php theme.json "Copy" rebind activate
418
460
  python tools/probe.py --config lab.json --cases cases.json # ad-hoc measurement
@@ -20,7 +20,7 @@
20
20
  "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
21
  "license": "MIT",
22
22
  "author": "moksa (https://moksaweb.com)",
23
- "version": "1.3.0"
23
+ "version": "1.5.0"
24
24
  },
25
25
  "loaderBehaviour": "Upload via Settings -> Skills -> Upload. Claude.ai parses SKILL.md frontmatter and surfaces the skill in your library. The extraction tool (extract-block-schema.php) needs a live WP-CLI connection and won't run in the sandbox; use it from a local terminal against your own site instead.",
26
26
  "uploadSteps": [
@@ -20,7 +20,7 @@
20
20
  "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
21
  "license": "MIT",
22
22
  "author": "moksa (https://moksaweb.com)",
23
- "version": "1.3.0"
23
+ "version": "1.5.0"
24
24
  },
25
25
  "loaderBehaviour": "Auto-loads on session start when SKILL.md frontmatter parses successfully.",
26
26
  "verified": true,
@@ -20,7 +20,7 @@
20
20
  "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
21
  "license": "MIT",
22
22
  "author": "moksa (https://moksaweb.com)",
23
- "version": "1.3.0"
23
+ "version": "1.5.0"
24
24
  },
25
25
  "loaderBehaviour": "Confirmed (2026-07-11): Codex CLI natively supports the SKILL.md spec. Place SKILL.md under .codex/skills/<name>/ (project) or ~/.codex/skills/<name>/ (personal) and Codex loads the name+description at session start, then the full body on demand. A parallel, broader convention .agents/skills/ (searched from cwd up to repo root, then ~/.agents/skills/) also exists across multiple tools - if your Codex CLI version prioritizes that path instead, mirror the same SKILL.md there.",
26
26
  "verified": true,
@@ -20,7 +20,7 @@
20
20
  "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
21
  "license": "MIT",
22
22
  "author": "moksa (https://moksaweb.com)",
23
- "version": "1.3.0"
23
+ "version": "1.5.0"
24
24
  },
25
25
  "loaderBehaviour": "CHANGED as of 2026-07-11: GitHub Copilot added a proper '.github/skills/' Agent Skills directory (December 2025), alongside the older single-file .github/copilot-instructions.md convention. This config targets the new skills-directory form. If your Copilot version predates this (pre Dec 2025), use the instructions-append fallback instead (see fallback below).",
26
26
  "fallback": {
@@ -20,7 +20,7 @@
20
20
  "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
21
  "license": "MIT",
22
22
  "author": "moksa (https://moksaweb.com)",
23
- "version": "1.3.0"
23
+ "version": "1.5.0"
24
24
  },
25
25
  "loaderBehaviour": "CHANGED as of 2026-07-11: Gemini CLI now natively supports the same SKILL.md standard as Claude Code and Codex CLI - the same directory-based skill works unmodified. Gemini CLI discovers skills in this precedence order: built-in, extension skills, ~/.gemini/skills/ (personal), .gemini/skills/ (project, shared via version control). At session start Gemini injects each discovered skill's name+description into the system prompt and calls activate_skill when a task matches.",
26
26
  "verified": true,
@@ -79,7 +79,9 @@ const counts = {
79
79
  "data/style-verification.csv": 98,
80
80
  "data/node-property-verification.csv": 181,
81
81
  "data/rwd-verification.csv": 576,
82
- "data/browser-verification.csv": 2237,
82
+ "data/browser-verification.csv": 2282,
83
+ "data/style-state-verification.csv": 52,
84
+ "data/interaction-verification.csv": 7,
83
85
  "data/data-class-hierarchy.csv": 121,
84
86
  };
85
87
  for (const [file, expected] of Object.entries(counts)) {
@@ -108,6 +110,18 @@ if (browser.includes("OVERRIDDEN"))
108
110
 
109
111
  // The design audit ships even when it is empty, and empty has to mean "ran and found
110
112
  // nothing" rather than "was never run", so the header alone is the proof.
113
+ // The intro table is two tables in one file - the checks and the timeline readings -
114
+ // so a row count says nothing useful about it. What matters is that every check
115
+ // passed, because a shipped example whose entrance animation never lifts is a blank
116
+ // page for every visitor.
117
+ const intro = read("data/intro-verification.csv");
118
+ if (!intro.startsWith("check,result,detail"))
119
+ fail("data/intro-verification.csv is not the table verify_intro.py writes");
120
+ for (const need of ["PLAYS", "ENDS", "NO_TRAP", "CLEARS", "DEGRADES"])
121
+ if (!new RegExp(`^${need},PASS`, "m").test(intro))
122
+ fail(`intro-verification.csv: ${need} did not pass`);
123
+ if (/,FAIL,/.test(intro)) fail("data/intro-verification.csv carries a failed check");
124
+
111
125
  const audit = read("data/design-audit.csv");
112
126
  if (!audit.startsWith("url,breakpoints,check,level"))
113
127
  fail("data/design-audit.csv is not the audit table verify_browser.py writes");
@@ -352,6 +352,9 @@ https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,alignItems,baseline,baseline,ok
352
352
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,paddingTop,18px,18px,ok
353
353
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,paddingBottom,18px,18px,ok
354
354
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
355
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,customStyles:animation,mk-rise both,no computed value,not-comparable
356
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,customStyles:animation-timeline,view(),view(),ok
357
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-0,customStyles:animation-range,entry 2% cover 18%,no computed value,not-comparable
355
358
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,display,grid,grid,ok
356
359
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,gridCols,160px 1fr,160px 1056px,ok
357
360
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,columnGap,24px,24px,ok
@@ -359,6 +362,9 @@ https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,alignItems,baseline,baseline,ok
359
362
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,paddingTop,18px,18px,ok
360
363
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,paddingBottom,18px,18px,ok
361
364
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
365
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,customStyles:animation,mk-rise both,no computed value,not-comparable
366
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,customStyles:animation-timeline,view(),view(),ok
367
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-1,customStyles:animation-range,entry 6% cover 22%,no computed value,not-comparable
362
368
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,display,grid,grid,ok
363
369
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,gridCols,160px 1fr,160px 1056px,ok
364
370
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,columnGap,24px,24px,ok
@@ -366,6 +372,9 @@ https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,alignItems,baseline,baseline,ok
366
372
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,paddingTop,18px,18px,ok
367
373
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,paddingBottom,18px,18px,ok
368
374
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
375
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,customStyles:animation,mk-rise both,no computed value,not-comparable
376
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,customStyles:animation-timeline,view(),view(),ok
377
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-2,customStyles:animation-range,entry 10% cover 26%,no computed value,not-comparable
369
378
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,display,grid,grid,ok
370
379
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,gridCols,160px 1fr,160px 1056px,ok
371
380
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,columnGap,24px,24px,ok
@@ -373,6 +382,9 @@ https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,alignItems,baseline,baseline,ok
373
382
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,paddingTop,18px,18px,ok
374
383
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,paddingBottom,18px,18px,ok
375
384
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
385
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,customStyles:animation,mk-rise both,no computed value,not-comparable
386
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,customStyles:animation-timeline,view(),view(),ok
387
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-3,customStyles:animation-range,entry 14% cover 30%,no computed value,not-comparable
376
388
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,display,grid,grid,ok
377
389
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,gridCols,160px 1fr,160px 1056px,ok
378
390
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,columnGap,24px,24px,ok
@@ -380,6 +392,9 @@ https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,alignItems,baseline,baseline,ok
380
392
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,paddingTop,18px,18px,ok
381
393
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,paddingBottom,18px,18px,ok
382
394
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
395
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,customStyles:animation,mk-rise both,no computed value,not-comparable
396
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,customStyles:animation-timeline,view(),view(),ok
397
+ https://mosaic.moksaweb.com/moksa/,_,mk-stack-4,customStyles:animation-range,entry 18% cover 34%,no computed value,not-comparable
383
398
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-head,display,grid,grid,ok
384
399
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-head,gridCols,84px 1fr,84px 1156px,ok
385
400
  https://mosaic.moksaweb.com/moksa/,_,mk-stack-head,columnGap,0px,0px,ok
@@ -1096,6 +1111,9 @@ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,alignItems,baseline,baseline,ok
1096
1111
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,paddingTop,18px,18px,ok
1097
1112
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,paddingBottom,18px,18px,ok
1098
1113
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1114
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,customStyles:animation,mk-rise both,no computed value,not-comparable
1115
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,customStyles:animation-timeline,view(),view(),ok
1116
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-0,customStyles:animation-range,entry 2% cover 18%,no computed value,not-comparable
1099
1117
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,display,grid,grid,ok
1100
1118
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,gridCols,160px 1fr,160px 660px,ok
1101
1119
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,columnGap,24px,24px,ok
@@ -1103,6 +1121,9 @@ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,alignItems,baseline,baseline,ok
1103
1121
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,paddingTop,18px,18px,ok
1104
1122
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,paddingBottom,18px,18px,ok
1105
1123
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1124
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,customStyles:animation,mk-rise both,no computed value,not-comparable
1125
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,customStyles:animation-timeline,view(),view(),ok
1126
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-1,customStyles:animation-range,entry 6% cover 22%,no computed value,not-comparable
1106
1127
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,display,grid,grid,ok
1107
1128
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,gridCols,160px 1fr,160px 660px,ok
1108
1129
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,columnGap,24px,24px,ok
@@ -1110,6 +1131,9 @@ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,alignItems,baseline,baseline,ok
1110
1131
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,paddingTop,18px,18px,ok
1111
1132
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,paddingBottom,18px,18px,ok
1112
1133
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1134
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,customStyles:animation,mk-rise both,no computed value,not-comparable
1135
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,customStyles:animation-timeline,view(),view(),ok
1136
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-2,customStyles:animation-range,entry 10% cover 26%,no computed value,not-comparable
1113
1137
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,display,grid,grid,ok
1114
1138
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,gridCols,160px 1fr,160px 660px,ok
1115
1139
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,columnGap,24px,24px,ok
@@ -1117,6 +1141,9 @@ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,alignItems,baseline,baseline,ok
1117
1141
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,paddingTop,18px,18px,ok
1118
1142
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,paddingBottom,18px,18px,ok
1119
1143
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1144
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,customStyles:animation,mk-rise both,no computed value,not-comparable
1145
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,customStyles:animation-timeline,view(),view(),ok
1146
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-3,customStyles:animation-range,entry 14% cover 30%,no computed value,not-comparable
1120
1147
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,display,grid,grid,ok
1121
1148
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,gridCols,160px 1fr,160px 660px,ok
1122
1149
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,columnGap,24px,24px,ok
@@ -1124,6 +1151,9 @@ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,alignItems,baseline,baseline,ok
1124
1151
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,paddingTop,18px,18px,ok
1125
1152
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,paddingBottom,18px,18px,ok
1126
1153
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1154
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,customStyles:animation,mk-rise both,no computed value,not-comparable
1155
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,customStyles:animation-timeline,view(),view(),ok
1156
+ https://mosaic.moksaweb.com/moksa/,_t,mk-stack-4,customStyles:animation-range,entry 18% cover 34%,no computed value,not-comparable
1127
1157
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-head,display,grid,grid,ok
1128
1158
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-head,gridCols,84px 1fr,84px 760px,ok
1129
1159
  https://mosaic.moksaweb.com/moksa/,_t,mk-stack-head,columnGap,0px,0px,ok
@@ -1841,6 +1871,9 @@ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,alignItems,baseline,baseline,ok
1841
1871
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,paddingTop,16px,16px,ok
1842
1872
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,paddingBottom,16px,16px,ok
1843
1873
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1874
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,customStyles:animation,mk-rise both,no computed value,not-comparable
1875
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,customStyles:animation-timeline,view(),view(),ok
1876
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,customStyles:animation-range,entry 2% cover 18%,no computed value,not-comparable
1844
1877
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-0,rowGap,10px,10px,ok
1845
1878
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,display,grid,grid,ok
1846
1879
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,gridCols,1fr,354px,ok
@@ -1849,6 +1882,9 @@ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,alignItems,baseline,baseline,ok
1849
1882
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,paddingTop,16px,16px,ok
1850
1883
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,paddingBottom,16px,16px,ok
1851
1884
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1885
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,customStyles:animation,mk-rise both,no computed value,not-comparable
1886
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,customStyles:animation-timeline,view(),view(),ok
1887
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,customStyles:animation-range,entry 6% cover 22%,no computed value,not-comparable
1852
1888
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-1,rowGap,10px,10px,ok
1853
1889
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,display,grid,grid,ok
1854
1890
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,gridCols,1fr,354px,ok
@@ -1857,6 +1893,9 @@ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,alignItems,baseline,baseline,ok
1857
1893
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,paddingTop,16px,16px,ok
1858
1894
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,paddingBottom,16px,16px,ok
1859
1895
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1896
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,customStyles:animation,mk-rise both,no computed value,not-comparable
1897
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,customStyles:animation-timeline,view(),view(),ok
1898
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,customStyles:animation-range,entry 10% cover 26%,no computed value,not-comparable
1860
1899
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-2,rowGap,10px,10px,ok
1861
1900
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,display,grid,grid,ok
1862
1901
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,gridCols,1fr,354px,ok
@@ -1865,6 +1904,9 @@ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,alignItems,baseline,baseline,ok
1865
1904
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,paddingTop,16px,16px,ok
1866
1905
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,paddingBottom,16px,16px,ok
1867
1906
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1907
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,customStyles:animation,mk-rise both,no computed value,not-comparable
1908
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,customStyles:animation-timeline,view(),view(),ok
1909
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,customStyles:animation-range,entry 14% cover 30%,no computed value,not-comparable
1868
1910
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-3,rowGap,10px,10px,ok
1869
1911
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,display,grid,grid,ok
1870
1912
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,gridCols,1fr,354px,ok
@@ -1873,6 +1915,9 @@ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,alignItems,baseline,baseline,ok
1873
1915
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,paddingTop,16px,16px,ok
1874
1916
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,paddingBottom,16px,16px,ok
1875
1917
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,customStyles:border-top,"1px solid rgba(22,24,28,.16)",no computed value,not-comparable
1918
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,customStyles:animation,mk-rise both,no computed value,not-comparable
1919
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,customStyles:animation-timeline,view(),view(),ok
1920
+ https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,customStyles:animation-range,entry 18% cover 34%,no computed value,not-comparable
1876
1921
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-4,rowGap,10px,10px,ok
1877
1922
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-head,display,grid,grid,ok
1878
1923
  https://mosaic.moksaweb.com/moksa/,_m,mk-stack-head,gridCols,48px 1fr,48px 306px,ok
@@ -0,0 +1,8 @@
1
+ candidate,note,status,evidence,stored
2
+ metas-with-uuid,the hypothesis: DataArray items carry their own uuid,TIMING_ONLY,"1 keyframes, no properties","stored: 1 metas, 0 property values"
3
+ metas-without-uuid,NEGATIVE CONTROL - identical but the meta has no uuid,TIMING_ONLY,"1 keyframes, no properties","stored: 1 metas, 0 property values"
4
+ properties-keyed-by-meta-uuid,"NEGATIVE CONTROL - properties keyed by the meta's uuid, not name",TIMING_ONLY,"1 keyframes, no properties","stored: 1 metas, 0 property values"
5
+ no-initial,does the initial block have to be there?,TIMING_ONLY,"1 keyframes, no properties","stored: 1 metas, 0 property values"
6
+ two-properties,"more than one meta, and a transform among them",TIMING_ONLY,"1 keyframes, no properties","stored: 2 metas, 0 property values"
7
+ two-keyframes,a real timeline rather than a single step,TIMING_ONLY,"2 keyframes, no properties","stored: 1 metas, 0 property values"
8
+ timed-trigger,the timed family rather than the progress family,NO_PAYLOAD,no entry for this trigger selector,"stored: 0 metas, 0 property values"
@@ -0,0 +1,20 @@
1
+ check,result,detail
2
+ PLAYS,PASS,17 of 17 intro elements changed state
3
+ COUNTS,PASS,--mk-n reached 100
4
+ ENDS,PASS,veil is out of hit-testing from 3200ms
5
+ NO_TRAP,PASS,"0 content elements still at opacity 0 in the viewport (34 below the fold awaiting their own scroll timeline, 1 mid-blink)"
6
+ CLEARS,PASS,a real click landed on 'mk-caret-row'
7
+ DEGRADES,PASS,with reduced motion the veil is display:none throughout
8
+ READABLE,PASS,0 elements invisible at 120ms with reduced motion
9
+
10
+ t_ms,counter,veil_visibility,veil_clip,veil_covers_centre,hit_centre,invisible_content
11
+ 120,,,,False,html.no-js,0
12
+ 350,0,visible,none,True,mk-boot,7
13
+ 700,56,visible,none,True,mk-boot,7
14
+ 1100,94,visible,none,True,mk-boot,7
15
+ 1500,100,visible,none,True,mk-boot,4
16
+ 1750,100,visible,inset(0px 0px 2.37106%),True,mk-boot,2
17
+ 2050,100,visible,inset(0px 0px 99.6708%),False,mk-caret-row,2
18
+ 2400,100,hidden,inset(0px 0px 100%),False,mk-caret-row,0
19
+ 3200,100,hidden,inset(0px 0px 100%),False,mk-caret-row,0
20
+ 4500,100,hidden,inset(0px 0px 100%),False,mk-caret-row,0
@@ -0,0 +1,53 @@
1
+ state,scope,host,selector_template,status,evidence
2
+ focus,global,div,&:FOCUS,COMPILED,.M_EL7:FOCUS
3
+ focus-visible,global,div,&:FOCUS-VISIBLE,COMPILED,.M_EL8:FOCUS-VISIBLE
4
+ hover,global,div,&:HOVER,COMPILED,.M_EL9:HOVER
5
+ hover-on-link,global,div,":where(a[href]:not([disabled]),button:not([disabled])):HOVER &",COMPILED,":where(a[href]:not([disabled]),button:not([disabled])):HOVER .M_EL10"
6
+ hover-on-tab,global,div,:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER &,COMPILED,:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER .M_EL11
7
+ hover-tab,global,div,&:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER,COMPILED,.M_EL12:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER
8
+ hover-when-link,global,div,"&:where([tabindex]:not([tabindex=""-1""]),a[href]:not([disabled]),button:not([disabled])):HOVER",COMPILED,".M_EL13:where([tabindex]:not([tabindex=""-1""]),a[href]:not([disabled]),button:not([disabled"
9
+ ____loop_pagination_number--active,node-type,loop-pagination-number,&.M_EL_LoopPaginationNumber--active,NO_HOST,host loop-pagination-number is COMMIT_500 - committing it breaks the page
10
+ ____loop_pagination_number_ellipsis,node-type,loop-pagination-number,&.M_EL_LoopPaginationNumber_ellipsis,NO_HOST,host loop-pagination-number is COMMIT_500 - committing it breaks the page
11
+ ___arrow_hidden,node-type,,&:where(.M_EL_SliderArrow--hidden),SKIPPED,no node type declares Mosaic/NodeTypes/Pro/Slider/SliderArrow/SliderArrowElementTypeFactoryAbstract.php
12
+ ___checkbox-input--checked,node-type,checkbox-input,&:checked,NO_HOST,host checkbox-input is BROKE_PAGE - committing it breaks the page
13
+ ___checkbox-input--checkmark,node-type,checkbox-input,&:checked::before,NO_HOST,host checkbox-input is BROKE_PAGE - committing it breaks the page
14
+ ___choice--checked,node-type,choice,&:has(:where(input):checked),COMPILED,.M_EL7:has(:where(input):checked)
15
+ ___choice--checked-within,node-type,choice,.M_EL_Choice:where(:has(input:checked)) &,COMPILED,.M_EL_Choice:where(:has(input:checked)) .M_EL8
16
+ ___choice--focus-visible,node-type,choice,&:has(:where(input):focus-visible),COMPILED,.M_EL9:has(:where(input):focus-visible)
17
+ ___choice-field--invalid,node-type,choice-field,&:has(:user-invalid),COMPILED,.M_EL7:has(:user-invalid)
18
+ ___choice-field--invalid-within,node-type,choice-field,.M_EL_ChoiceField:where(:has(:user-invalid)) &,COMPILED,.M_EL_ChoiceField:where(:has(:user-invalid)) .M_EL10
19
+ ___dropdown--opening,node-type,,.M_EL_Dropdown:where(.dropdown--opening) &,SKIPPED,no node type declares Mosaic/NodeTypes/Menu/Dropdown/DropdownElementTypeFactoryAbstract.php
20
+ ___dropdown-toggle--current,node-type,dropdown-toggle,&.M_EL_DropdownToggle--current,COMPILED,.M_EL7.M_EL_DropdownToggle--current
21
+ ___dropdown-toggle--current-within,node-type,dropdown-toggle,".M_EL_Dropdown:where(:has(.M_EL_MenuLink--current,.M_EL_DropdownToggle--current)) > &",COMPILED,".M_EL_Dropdown:where(:has(.M_EL_MenuLink--current,.M_EL_DropdownToggle--current)) > .M_EL8"
22
+ ___field--focus-visible,node-type,field,"&:has(:where(input, textarea, select):focus-visible)",COMPILED,".M_EL7:has(:where(input, textarea, select):focus-visible)"
23
+ ___field--invalid,node-type,field,&:has(:user-invalid),COMPILED,.M_EL8:has(:user-invalid)
24
+ ___field--invalid-focus-visible,node-type,field,&:has(:user-invalid:focus-visible),COMPILED,.M_EL9:has(:user-invalid:focus-visible)
25
+ ___field--invalid-within,node-type,field,.M_EL_Field:where(:has(:user-invalid)) &,COMPILED,.M_EL_Field:where(:has(:user-invalid)) .M_EL10
26
+ ___field-set--invalid,node-type,fieldset,&:has(:user-invalid),COMPILED,.M_EL7:has(:user-invalid)
27
+ ___fileupload-input--selector-button,node-type,fileupload-input,&::file-selector-button,COMPILED,.M_EL7::file-selector-button
28
+ ___fileupload-input--selector-button-hover,node-type,fileupload-input,&::file-selector-button:hover,COMPILED,.M_EL8::file-selector-button:hover
29
+ ___form--error,node-type,form-wrapper,"&[data-form-state=""error""]",COMPILED,".M_EL7[data-form-state=""error""]"
30
+ ___form--invalid-within,node-type,form-wrapper,.M_EL_FormWrapper:where(:has(:user-invalid)) &,COMPILED,.M_EL_FormWrapper:where(:has(:user-invalid)) .M_EL10
31
+ ___input--placeholder,node-type,text-input,&.M_EL_InputText::placeholder,COMPILED,.M_EL7.M_EL_InputText::placeholder
32
+ ___loop_element_no_result,node-type,loop,&.M_EL_Loop--no-result,NO_HOST,host loop is COMMIT_500 - committing it breaks the page
33
+ ___loop_pagination_button--disabled,node-type,loop-pagination-button-next,&.M_EL_LoopPaginationButton--disabled,BROKE_PAGE,this host's page did not render
34
+ ___menu-link--current,node-type,menu-link,&.M_EL_MenuLink--current,COMPILED,.M_EL7.M_EL_MenuLink--current
35
+ ___navbar--dropdown-mode,node-type,navbar,"&:where(.M_EL_Navbar.dropdown-mode,.M_EL_Navbar.dropdown-mode &)",COMPILED,".M_EL7:where(.M_EL_Navbar.dropdown-mode,.M_EL_Navbar.dropdown-mode .M_EL7)"
36
+ ___navbar--opened,node-type,navbar,.dropdown-mode:where(.M_EL_Navbar.dropdown--opened) &,COMPILED,.dropdown-mode:where(.M_EL_Navbar.dropdown--opened) .M_EL8
37
+ ___navbar--opening,node-type,navbar,.dropdown-mode:where(.M_EL_Navbar.dropdown--opening) &,COMPILED,.dropdown-mode:where(.M_EL_Navbar.dropdown--opening) .M_EL9
38
+ ___nested_dropdown_mode,node-type,,"&:where(.dropdown-mode .M_EL_Navigation .M_EL_Dropdown &, .M_EL_Dropdown .M_EL_Dropdown &):not(x)",SKIPPED,no node type declares Mosaic/NodeTypes/Menu/Dropdown/DropdownElementTypeFactoryAbstract.php
39
+ ___radio-input--checked,node-type,radio-input,&:checked,NO_HOST,host radio-input is BROKE_PAGE - committing it breaks the page
40
+ ___radio-input--checkmark,node-type,radio-input,&:checked::before,NO_HOST,host radio-input is BROKE_PAGE - committing it breaks the page
41
+ ___select-input-option,node-type,select-input,"&.M_EL_Select:where(:has(option:not(:disabled):checked)), &.M_EL_Select :where(option)",COMPILED,".M_EL7.M_EL_Select:where(:has(option:not(:disabled):checked)), .M_EL7.M_EL_Select :where(o"
42
+ ___select-input-option--disabled,node-type,select-input,"&.M_EL_Select:where(:has(option:disabled:checked)), &.M_EL_Select :where(option:disabled)",COMPILED,".M_EL8.M_EL_Select:where(:has(option:disabled:checked)), .M_EL8.M_EL_Select :where(option:"
43
+ ___slide--active,node-type,slider-slide,.M_EL_SliderSlide--active > &,NO_HOST,host slider-slide is BROKE_PAGE - committing it breaks the page
44
+ ___slider_navigation_bullet--active,node-type,slider-navigation-bullet,&.M_EL_SliderNavigationBullet--active,NO_HOST,host slider-navigation-bullet is COMMIT_500 - committing it breaks the page
45
+ ___slider_navigation_bullet--hover,node-type,slider-navigation-bullet,&:not(.M_EL_SliderNavigationBullet--active):HOVER,NO_HOST,host slider-navigation-bullet is COMMIT_500 - committing it breaks the page
46
+ ___step--active,node-type,form-multi-steps-step,&.M_EL_Step--active,COMPILED,.M_EL7.M_EL_Step--active
47
+ ___step--active___descendants,node-type,form-multi-steps-step,.M_EL_Step--active &,COMPILED,.M_EL_Step--active .M_EL8
48
+ ___step--completed,node-type,form-multi-steps-step,&.M_EL_Step--completed,COMPILED,.M_EL9.M_EL_Step--completed
49
+ ___step--completed___descendants,node-type,form-multi-steps-step,.M_EL_Step--completed &,COMPILED,.M_EL_Step--completed .M_EL10
50
+ ___submit-button--busy,node-type,submit-button,"&[aria-busy=""true""]",COMPILED,".M_EL7[aria-busy=""true""]"
51
+ ___tab--active,node-type,tabs-tab,&.M_EL_Tab--active,NO_HOST,host tabs-tab is BROKE_PAGE - committing it breaks the page
52
+ ___tab--active___descendants,node-type,tabs-tab,.M_EL_Tab--active &,NO_HOST,host tabs-tab is BROKE_PAGE - committing it breaks the page
53
+ ___textarea-input--placeholder,node-type,textarea-input,&.M_EL_TextArea::placeholder,COMPILED,.M_EL7.M_EL_TextArea::placeholder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mosaic-headless",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "AI-agent skill: build Mosaic Pro (Nextend) WordPress sites by writing the underlying data model directly - 23 custom tables, no visual editor, no DOM. Every node type, style property and node property swept against a live install and asserted on the delivered HTML and compiled CSS. Installs into Claude Code, Cursor, Codex CLI, Gemini CLI, Copilot, Continue, Windsurf and Claude.ai.",
5
5
  "keywords": [
6
6
  "wordpress",