mosaic-headless 1.17.2 → 1.18.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.
Files changed (64) hide show
  1. package/README.ja.md +17 -10
  2. package/README.ko.md +17 -10
  3. package/README.md +16 -9
  4. package/README.zh-TW.md +15 -9
  5. package/SKILL.md +96 -40
  6. package/assets/templates/platforms/claude-ai.json +1 -1
  7. package/assets/templates/platforms/claude-code.json +1 -1
  8. package/assets/templates/platforms/codex-cli.json +1 -1
  9. package/assets/templates/platforms/copilot.json +1 -1
  10. package/assets/templates/platforms/gemini-cli.json +1 -1
  11. package/bin/check-release.mjs +1 -1
  12. package/data/accordion-verification.csv +1 -1
  13. package/data/browser-verification.csv +906 -906
  14. package/data/conversion-verification.csv +1 -1
  15. package/data/db-columns.csv +40 -36
  16. package/data/design-audit-acknowledged.csv +1 -0
  17. package/data/design-audit.csv +1 -1
  18. package/data/intro-verification.csv +7 -7
  19. package/data/loop-verification.csv +5 -5
  20. package/data/node-properties.csv +4 -3
  21. package/data/node-property-verification.csv +81 -80
  22. package/data/node-type-notes.csv +1 -1
  23. package/data/node-types.csv +9 -9
  24. package/data/node-verification.csv +100 -100
  25. package/data/rest-routes.csv +1 -1
  26. package/data/style-properties.csv +1 -1
  27. package/data/style-state-verification.csv +48 -48
  28. package/data/style-states.csv +32 -32
  29. package/data/style-verification.csv +1 -1
  30. package/data/theme-zip-verification.csv +10 -10
  31. package/data/variants.csv +153 -0
  32. package/evals/accordion-is-not-broken/graders/criteria.md +1 -1
  33. package/evals/grid-child-placement/graders/criteria.md +3 -3
  34. package/package.json +1 -1
  35. package/references/data-model.md +7 -6
  36. package/references/design-system.md +28 -16
  37. package/references/interactions.md +1 -1
  38. package/references/responsive.md +6 -6
  39. package/references/styling.md +23 -14
  40. package/references/upgrading.md +182 -0
  41. package/references/vs-elementor-gutenberg.md +1 -1
  42. package/references/write-protocol.md +1 -1
  43. package/sites/_moksa.py +67 -62
  44. package/sites/moksa.json +219 -219
  45. package/tools/bootstrap_probe_theme.php +1 -1
  46. package/tools/build_page.py +17 -11
  47. package/tools/build_site.py +1 -1
  48. package/tools/capture_live.py +42 -6
  49. package/tools/data_upgrade.py +74 -0
  50. package/tools/extract_node_types.py +1 -1
  51. package/tools/from_elementor.py +3 -3
  52. package/tools/mo.py +10 -9
  53. package/tools/probe.py +1 -1
  54. package/tools/sweep_components.py +1 -1
  55. package/tools/sweep_interactions.py +3 -3
  56. package/tools/sweep_node_properties.py +1 -1
  57. package/tools/sweep_node_types.py +20 -0
  58. package/tools/sweep_style_properties.py +6 -7
  59. package/tools/sweep_style_states.py +2 -2
  60. package/tools/theme_export.php +2 -2
  61. package/tools/theme_zip_compare.php +2 -2
  62. package/tools/verify_browser.py +6 -5
  63. package/tools/verify_rwd.py +17 -15
  64. package/data/element-classes.csv +0 -152
package/sites/_moksa.py CHANGED
@@ -78,11 +78,11 @@ def T(tag, text, _t=None, _m=None, **st):
78
78
  # The keyboard is a state too.
79
79
  #
80
80
  # `focus-visible` was verified by sweep_style_states.py to compile to
81
- # `.M_EL<n>:FOCUS-VISIBLE` - note the UPPERCASE pseudo-class Mosaic emits, which is
81
+ # `._<token>:FOCUS-VISIBLE` - note the UPPERCASE pseudo-class Mosaic emits, which is
82
82
  # why grepping a delivered stylesheet for ":focus-visible" finds nothing at all. Of
83
83
  # the seven globally usable states this page used exactly one, `hover`, which means
84
84
  # every route through it was invisible to anyone not using a mouse.
85
- FOCUS_RING = {"customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"}
85
+ FOCUS_RING = {"customDeclarations": "outline:2px solid rgb(255,90,54);outline-offset:3px;"}
86
86
 
87
87
 
88
88
  def box(attr, style, children, hover=None, focus=None, _t=None, _m=None):
@@ -157,7 +157,7 @@ def figure(attr, num, size="56px", t="44px", m="34px"):
157
157
  return {"type": "div", "data": {"attrID": attr},
158
158
  "style": {"&": {"_": {"display": "flex", "alignItems": "baseline",
159
159
  "columnGap": "0px",
160
- "customStyles":
160
+ "customDeclarations":
161
161
  "font-variant-numeric:tabular-nums;"}}},
162
162
  "children": [
163
163
  {"type": "div", "data": {"attrID": attr + "-d%d" % j},
@@ -166,7 +166,7 @@ def figure(attr, num, size="56px", t="44px", m="34px"):
166
166
  # in the stylesheet, correct, and computed to `block` anyway -
167
167
  # which is exactly the class of dead code verify_browser.py exists
168
168
  # to find, and it found this one.
169
- "style": {"&": {"_": {"customStyles":
169
+ "style": {"&": {"_": {"customDeclarations":
170
170
  "overflow:hidden;"
171
171
  "--d:%dms;" % (j * 70)}}},
172
172
  "children": [T("h3", ch, color={"token": "--mk-ink"}, fontSize=size,
@@ -186,7 +186,7 @@ def clause(num, en, zh, attr):
186
186
  return box(attr, {"display": "grid", "gridCols": "84px 1fr",
187
187
  "columnGap": "0px", "alignItems": "start",
188
188
  "paddingTop": "22px",
189
- "customStyles": "border-top:1px solid " + RULE + ";"},
189
+ "customDeclarations": "border-top:1px solid " + RULE + ";"},
190
190
  _m={"gridCols": "48px 1fr"},
191
191
  children=[
192
192
  mono("§" + num, size="12px", color="--mk-accent-ink",
@@ -239,7 +239,7 @@ def mask_line(attr, text, tag="h1", **st):
239
239
  newline gives the browser one box and nothing to slide behind.
240
240
  """
241
241
  return {"type": "div", "data": {"attrID": attr + "-mask"},
242
- "style": {"&": {"_": {"customStyles":
242
+ "style": {"&": {"_": {"customDeclarations":
243
243
  "overflow:hidden;padding-bottom:.08em;"}}},
244
244
  "children": [T(tag, text, **st)]}
245
245
 
@@ -839,21 +839,26 @@ def motion_css():
839
839
  # ── opened ──────────────────────────────────────────────────────
840
840
  # The item itself becomes the overlay. Nothing above it is styled, so
841
841
  # no `:has()` is needed and no ancestor has to know this state exists.
842
- "#mk-plate-item.M_EL_AccordionItem--opened{position:fixed;inset:0;"
842
+ # The state class is the runtime's, and its spelling is the plugin's, not
843
+ # ours: 1.0.7 toggled `M_EL_AccordionItem--opened`, 1.0.8 renamed every
844
+ # emitted class (`m-accordion-item--opened`) and the tap-to-enlarge silently
845
+ # stopped working on upgrade until this selector followed. Any CSS that
846
+ # names an emitted class is coupled to the plugin version.
847
+ "#mk-plate-item.m-accordion-item--opened{position:fixed;inset:0;"
843
848
  "z-index:200;width:auto;border:none;background:rgba(250,250,247,.97);"
844
849
  "display:grid;align-content:center;justify-items:center;"
845
850
  "padding:24px}",
846
- "#mk-plate-item.M_EL_AccordionItem--opened::after{display:none}",
847
- "#mk-plate-item.M_EL_AccordionItem--opened #mk-plate-title{"
851
+ "#mk-plate-item.m-accordion-item--opened::after{display:none}",
852
+ "#mk-plate-item.m-accordion-item--opened #mk-plate-title{"
848
853
  "cursor:zoom-out;width:min(760px,88vw);"
849
854
  "border:1px solid rgb(214,214,206)}",
850
- "#mk-plate-item.M_EL_AccordionItem--opened #mk-loop-bar{"
855
+ "#mk-plate-item.m-accordion-item--opened #mk-loop-bar{"
851
856
  "padding:8px 12px 9px}",
852
- "#mk-plate-item.M_EL_AccordionItem--opened #mk-plate-body{"
857
+ "#mk-plate-item.m-accordion-item--opened #mk-plate-body{"
853
858
  "width:min(760px,88vw)}",
854
- "#mk-plate-item.M_EL_AccordionItem--opened #mk-loop-seal{"
859
+ "#mk-plate-item.m-accordion-item--opened #mk-loop-seal{"
855
860
  "inset:auto 16px 14px auto;width:38px;height:38px}",
856
- "#mk-plate-item.M_EL_AccordionItem--opened #mk-loop-seal::after{"
861
+ "#mk-plate-item.m-accordion-item--opened #mk-loop-seal::after{"
857
862
  "font-size:21px}",
858
863
  "@media (max-width:1079px){#mk-loop{right:24px;width:154px}}",
859
864
  # the phone gets the plate too, tucked above the scroll cue and small
@@ -1257,7 +1262,7 @@ def motion_css():
1257
1262
  # ── the shared shell ──────────────────────────────────────────────────────────
1258
1263
  HEADER = box("mk-shell-top", {}, [
1259
1264
  # a `code` node with insertLocation "head" is the only way to get @keyframes into
1260
- # the document - customStyles is emitted inside a rule and cannot hold one
1265
+ # the document - customDeclarations is emitted inside a rule and cannot hold one
1261
1266
  {"type": "code", "data": {"attrID": "mk-motion-css", "insertLocation": "head",
1262
1267
  "content": motion_css(), "processShortcodes": "0"}},
1263
1268
  # the fill and the track are separate elements: nested, the fill's width is a
@@ -1403,11 +1408,11 @@ FOOTER = box("mk-footer",
1403
1408
  ]),
1404
1409
  box("mk-f-legal",
1405
1410
  {"paddingTop": "18px",
1406
- "customStyles": "border-top:1px solid " + RULE_DARK + ";"},
1411
+ "customDeclarations": "border-top:1px solid " + RULE_DARK + ";"},
1407
1412
  [{"type": "div", "data": {"attrID": "mk-f-legal-row"},
1408
1413
  "style": bp({"display": "flex", "justifyContent": "space-between",
1409
1414
  "columnGap": "20px", "rowGap": "6px",
1410
- "customStyles": "flex-wrap:wrap;"}, None, None),
1415
+ "customDeclarations": "flex-wrap:wrap;"}, None, None),
1411
1416
  "children": [
1412
1417
  mono("© 2026 MOKSA WEB — ALL RIGHTS RESERVED", size="10px",
1413
1418
  color="rgb(128,130,138)", track="0.1em"),
@@ -1449,7 +1454,7 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
1449
1454
  # the document's own header block: what this is, where it is from, which revision
1450
1455
  box("mk-mast-meta",
1451
1456
  {"display": "flex", "justifyContent": "space-between", "columnGap": "20px",
1452
- "rowGap": "6px", "customStyles": "flex-wrap:wrap;"},
1457
+ "rowGap": "6px", "customDeclarations": "flex-wrap:wrap;"},
1453
1458
  [mono("MOKSA WEB — STUDIO PROFILE", color="--mk-ink", track="0.16em"),
1454
1459
  mono("TAICHUNG, TW", track="0.16em"),
1455
1460
  mono("REV. 2026.09", track="0.16em")]),
@@ -1490,18 +1495,18 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
1490
1495
  "color": {"token": "--mk-ink"},
1491
1496
  "paddingLeft": "22px", "paddingRight": "22px",
1492
1497
  "paddingTop": "13px", "paddingBottom": "13px",
1493
- "customStyles": "border:1px solid rgb(255,90,54);"}
1498
+ "customDeclarations": "border:1px solid rgb(255,90,54);"}
1494
1499
  if n == 1 else
1495
1500
  {"backgroundColor": "rgba(0,0,0,0)", "color": {"token": "--mk-ink"},
1496
1501
  "paddingLeft": "0px", "paddingRight": "0px",
1497
1502
  "paddingTop": "13px", "paddingBottom": "13px",
1498
- "customStyles": "border:1px solid rgba(0,0,0,0);"
1503
+ "customDeclarations": "border:1px solid rgba(0,0,0,0);"
1499
1504
  "border-bottom-color:rgb(22,24,28);"},
1500
1505
  fontSize="13px", fontFamily=MONO, letterSpacing="0.1em",
1501
1506
  radius="0px", cursor="pointer", transitionAll="180ms ease")},
1502
1507
  "focus-visible": {"_": FOCUS_RING},
1503
1508
  "hover": {"_": ({"backgroundColor": {"token": "--mk-ink"},
1504
- "customStyles": "border:1px solid rgb(22,24,28);"}
1509
+ "customDeclarations": "border:1px solid rgb(22,24,28);"}
1505
1510
  if n == 1
1506
1511
  else {"color": {"token": "--mk-accent"}})}},
1507
1512
  "text": text}
@@ -1512,14 +1517,14 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
1512
1517
  # the right-hand column: what a spec sheet puts in its header block
1513
1518
  box("mk-mast-side",
1514
1519
  {"display": "grid", "rowGap": "0px",
1515
- "customStyles": "border-top:1px solid " + RULE_INK + ";"},
1516
- _m={"customStyles": "border-top:1px solid " + RULE + ";"},
1520
+ "customDeclarations": "border-top:1px solid " + RULE_INK + ";"},
1521
+ _m={"customDeclarations": "border-top:1px solid " + RULE + ";"},
1517
1522
  children=[
1518
1523
  box("mk-mast-side-%d" % i,
1519
1524
  {"display": "grid", "gridCols": "1fr auto",
1520
1525
  "columnGap": "14px", "alignItems": "baseline",
1521
1526
  "paddingTop": "11px", "paddingBottom": "11px",
1522
- "customStyles": ("" if i == 0
1527
+ "customDeclarations": ("" if i == 0
1523
1528
  else "border-top:1px solid " + RULE + ";")},
1524
1529
  [mono(k, size="10px", color="--mk-faint", track="0.18em"),
1525
1530
  mono(v, size="12px", color="--mk-ink", track="0.02em")])
@@ -1533,14 +1538,14 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
1533
1538
  box("mk-spec-%d" % i,
1534
1539
  {"paddingRight": "22px",
1535
1540
  "paddingLeft": "0px" if i == 0 else "22px",
1536
- "customStyles": ("" if i == 0
1541
+ "customDeclarations": ("" if i == 0
1537
1542
  else "border-left:1px solid " + RULE + ";")},
1538
1543
  # at two-up the rule falls on the odd cells instead, and
1539
1544
  # `border-left:0` has to be set explicitly - omitting it leaves the
1540
1545
  # four-up rule standing
1541
1546
  _t={"paddingTop": "18px", "paddingBottom": "18px",
1542
1547
  "paddingLeft": "0px" if i % 2 == 0 else "18px",
1543
- "customStyles": ("border-left:0;" if i % 2 == 0
1548
+ "customDeclarations": ("border-left:0;" if i % 2 == 0
1544
1549
  else "border-left:1px solid " + RULE + ";")
1545
1550
  + ("border-top:1px solid " + RULE + ";" if i > 1
1546
1551
  else "border-top:0;")},
@@ -1564,12 +1569,12 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
1564
1569
 
1565
1570
  TICKER_BAND = box("mk-ticker",
1566
1571
  {"backgroundColor": {"token": "--mk-ink"}, "paddingTop": "11px",
1567
- "paddingBottom": "11px", "customStyles": "overflow:hidden;"},
1572
+ "paddingBottom": "11px", "customDeclarations": "overflow:hidden;"},
1568
1573
  [box("mk-ticker-track", {"display": "flex", "columnGap": "0px"},
1569
1574
  # duplicated so the loop can translate exactly -50% and never show a seam
1570
1575
  [T("p", w, color="rgb(250,250,247)", fontSize="11px", fontWeight="400",
1571
1576
  letterSpacing="0.2em", fontFamily=MONO,
1572
- customStyles=("padding:0 22px;white-space:nowrap;"
1577
+ customDeclarations=("padding:0 22px;white-space:nowrap;"
1573
1578
  "border-right:1px solid rgba(250,250,247,.22);"))
1574
1579
  for w in TICKER * 2])])
1575
1580
 
@@ -1598,7 +1603,7 @@ SERVICE_ROW = box("svc-row",
1598
1603
  {"display": "grid", "gridCols": "84px 1fr 1.35fr",
1599
1604
  "columnGap": "24px", "alignItems": "start",
1600
1605
  "paddingTop": "26px", "paddingBottom": "26px",
1601
- "customStyles": "border-top:1px solid " + RULE + ";"},
1606
+ "customDeclarations": "border-top:1px solid " + RULE + ";"},
1602
1607
  _t={"gridCols": "72px 1fr 1.2fr", "columnGap": "18px"},
1603
1608
  _m={"gridCols": "repeat(1, 1fr)", "rowGap": "10px",
1604
1609
  "paddingTop": "20px", "paddingBottom": "20px"},
@@ -1652,7 +1657,7 @@ PROCESS_SEC = section("process", [wrap("mk-proc-in", [
1652
1657
  grid("mk-proc-grid", 4, "24px", tcols=2, mcols=1, children=[
1653
1658
  box("mk-proc-%d" % i,
1654
1659
  {"paddingTop": "26px", "paddingRight": "18px",
1655
- "customStyles": "border-top:1px solid " + RULE + ";"},
1660
+ "customDeclarations": "border-top:1px solid " + RULE + ";"},
1656
1661
  _m={"paddingTop": "20px", "paddingRight": "0px"},
1657
1662
  children=[
1658
1663
  box("mk-proc-dot-%d" % i, {}, []),
@@ -1688,7 +1693,7 @@ STACK_SEC = section("stack", [wrap("mk-stack-in", [
1688
1693
  # animation-range further down the scroll rather than by a
1689
1694
  # delay: a scroll-driven animation has no clock to delay
1690
1695
  # against, so the offset has to live in the range.
1691
- "customStyles":
1696
+ "customDeclarations":
1692
1697
  "border-top:1px solid " + RULE + ";"
1693
1698
  "animation:mk-rise both;animation-timeline:view();"
1694
1699
  "animation-range:entry %d%% cover %d%%;"
@@ -1699,9 +1704,9 @@ STACK_SEC = section("stack", [wrap("mk-stack-in", [
1699
1704
  mono(group, size="10px", color="--mk-faint", track="0.18em"),
1700
1705
  box("mk-stack-tags-%d" % i,
1701
1706
  {"display": "flex", "columnGap": "8px", "rowGap": "8px",
1702
- "customStyles": "flex-wrap:wrap;"},
1707
+ "customDeclarations": "flex-wrap:wrap;"},
1703
1708
  [box("mk-tag-%d-%d" % (i, j),
1704
- {"customStyles":
1709
+ {"customDeclarations":
1705
1710
  "border:1px solid " + RULE + ";"
1706
1711
  "padding:5px 10px;"
1707
1712
  "transition:border-color .2s ease,"
@@ -1726,7 +1731,7 @@ WORK_SEC = section("works", [wrap("mk-works-in", [
1726
1731
  box("mk-works-thead",
1727
1732
  {"display": "grid", "gridCols": "60px 1.4fr 1fr 1fr",
1728
1733
  "columnGap": "20px", "paddingBottom": "12px",
1729
- "customStyles":
1734
+ "customDeclarations":
1730
1735
  "border-bottom:1px solid rgba(22,24,28,.34);"},
1731
1736
  _m={"display": "none"},
1732
1737
  children=[
@@ -1744,7 +1749,7 @@ WORK_SEC = section("works", [wrap("mk-works-in", [
1744
1749
  "columnGap": "20px", "alignItems": "baseline",
1745
1750
  "paddingTop": "17px", "paddingBottom": "17px",
1746
1751
  "cursor": "pointer",
1747
- "customStyles": "border-bottom:1px solid " + RULE + ";"},
1752
+ "customDeclarations": "border-bottom:1px solid " + RULE + ";"},
1748
1753
  _m={"gridCols": "1fr", "rowGap": "5px",
1749
1754
  "paddingTop": "15px", "paddingBottom": "15px"},
1750
1755
  children=[
@@ -1777,7 +1782,7 @@ PRODUCT_SEC = section("products", [wrap("mk-prod-in", [
1777
1782
  box("mk-prod-head",
1778
1783
  {"display": "grid", "gridCols": "84px 1fr", "columnGap": "0px",
1779
1784
  "alignItems": "start", "paddingTop": "22px",
1780
- "customStyles": "border-top:1px solid " + RULE_DARK + ";"},
1785
+ "customDeclarations": "border-top:1px solid " + RULE_DARK + ";"},
1781
1786
  _m={"gridCols": "48px 1fr"},
1782
1787
  children=[
1783
1788
  mono("§05", size="12px", color="--mk-accent", track="0.06em"),
@@ -1796,7 +1801,7 @@ PRODUCT_SEC = section("products", [wrap("mk-prod-in", [
1796
1801
  {"display": "grid", "gridCols": "84px 1fr 1.3fr",
1797
1802
  "columnGap": "24px", "alignItems": "start",
1798
1803
  "paddingTop": "26px", "paddingBottom": "26px",
1799
- "customStyles": "border-top:1px solid " + RULE_DARK + ";"},
1804
+ "customDeclarations": "border-top:1px solid " + RULE_DARK + ";"},
1800
1805
  _t={"gridCols": "72px 1fr 1.2fr", "columnGap": "18px",
1801
1806
  "rowGap": "14px"},
1802
1807
  _m={"gridCols": "repeat(1, 1fr)", "rowGap": "12px",
@@ -1816,7 +1821,7 @@ PRODUCT_SEC = section("products", [wrap("mk-prod-in", [
1816
1821
  # the 72px number gutter on row two at tablet
1817
1822
  box("mk-prod-s-%d" % i,
1818
1823
  {"marginTop": "14px",
1819
- "customStyles":
1824
+ "customDeclarations":
1820
1825
  "border:1px solid rgba(255,90,54,.6);"
1821
1826
  "padding:5px 10px;display:inline-block;"
1822
1827
  "width:max-content;"},
@@ -1838,16 +1843,16 @@ VOICE_SEC = section("mk-voices", [wrap("mk-voice-in", [
1838
1843
  box("mk-voice-%d" % i,
1839
1844
  {"paddingTop": "26px", "paddingRight": "28px", "paddingBottom": "26px",
1840
1845
  "paddingLeft": "0px" if i == 0 else "28px",
1841
- "customStyles": "border-top:1px solid " + RULE + ";"
1846
+ "customDeclarations": "border-top:1px solid " + RULE + ";"
1842
1847
  + ("" if i == 0
1843
1848
  else "border-left:1px solid " + RULE + ";")},
1844
1849
  # one column: the column rule and the gutter both have to be switched
1845
1850
  # off explicitly - omitting them leaves the three-up rule standing
1846
1851
  _t={"paddingLeft": "0px", "paddingRight": "0px",
1847
- "customStyles": "border-top:1px solid " + RULE + ";"
1852
+ "customDeclarations": "border-top:1px solid " + RULE + ";"
1848
1853
  "border-left:0;"},
1849
1854
  _m={"paddingLeft": "0px", "paddingRight": "0px",
1850
- "customStyles": "border-top:1px solid " + RULE + ";"
1855
+ "customDeclarations": "border-top:1px solid " + RULE + ";"
1851
1856
  "border-left:0;"},
1852
1857
  children=[
1853
1858
  mono("“", size="24px", color="--mk-accent-ink", track="0"),
@@ -1870,7 +1875,7 @@ CONTACT = section("contact", [wrap("mk-contact-in", [
1870
1875
  box("mk-contact-head",
1871
1876
  {"display": "grid", "gridCols": "84px 1fr", "columnGap": "0px",
1872
1877
  "alignItems": "start", "paddingTop": "22px",
1873
- "customStyles": "border-top:1px solid " + RULE + ";"},
1878
+ "customDeclarations": "border-top:1px solid " + RULE + ";"},
1874
1879
  _m={"gridCols": "48px 1fr"},
1875
1880
  children=[
1876
1881
  mono("§07", size="12px", color="--mk-accent-ink",
@@ -1895,7 +1900,7 @@ CONTACT = section("contact", [wrap("mk-contact-in", [
1895
1900
  {"display": "grid", "gridCols": "150px 1fr",
1896
1901
  "columnGap": "20px", "alignItems": "baseline",
1897
1902
  "paddingTop": "15px", "paddingBottom": "15px",
1898
- "customStyles":
1903
+ "customDeclarations":
1899
1904
  "border-top:1px solid " + RULE + ";"},
1900
1905
  _m={"gridCols": "84px 1fr", "columnGap": "12px"},
1901
1906
  children=[
@@ -1938,7 +1943,7 @@ def flap(attr, items, cell, size, family=MONO, weight="500", colour="--mk-paper"
1938
1943
  n/(n+1) of the strip's own height, which the CSS computes from the same count.
1939
1944
  """
1940
1945
  return box(attr,
1941
- dict({"customStyles": "overflow:hidden;height:%s;" % cell}, **st),
1946
+ dict({"customDeclarations": "overflow:hidden;height:%s;" % cell}, **st),
1942
1947
  [box(attr + "-s", {},
1943
1948
  [box("%s-i-%d" % (attr, j), {},
1944
1949
  [T("p", v, color={"token": colour} if colour.startswith("--")
@@ -1955,14 +1960,14 @@ BOARD = section("board", [wrap("mk-board-in", [
1955
1960
  box("mk-board-head",
1956
1961
  {"display": "flex", "justifyContent": "space-between",
1957
1962
  "columnGap": "20px", "rowGap": "8px",
1958
- "customStyles": "flex-wrap:wrap;"},
1963
+ "customDeclarations": "flex-wrap:wrap;"},
1959
1964
  [mono("BOARD 01 — WHERE WE WORK", size="10px",
1960
1965
  color="--mk-accent", track="0.22em"),
1961
1966
  mono("REMOTE / %d DESTINATIONS" % len(CITIES), size="10px",
1962
1967
  color="rgb(140,142,150)", track="0.2em")]),
1963
1968
  box("mk-board-row",
1964
1969
  {"display": "flex", "alignItems": "center", "columnGap": "26px",
1965
- "marginTop": "34px", "customStyles": "flex-wrap:wrap;"},
1970
+ "marginTop": "34px", "customDeclarations": "flex-wrap:wrap;"},
1966
1971
  _m={"columnGap": "14px", "marginTop": "24px"},
1967
1972
  children=[
1968
1973
  # the three letter windows, transposed out of the code list
@@ -1973,7 +1978,7 @@ BOARD = section("board", [wrap("mk-board-in", [
1973
1978
  flap("mk-flap-%d" % k,
1974
1979
  [c[0][k] for c in CITIES],
1975
1980
  "86px", "74px", weight="600",
1976
- customStyles="overflow:hidden;height:86px;"
1981
+ customDeclarations="overflow:hidden;height:86px;"
1977
1982
  "background:rgb(30,32,37);"
1978
1983
  "padding:0 16px;"
1979
1984
  "border:1px solid rgba(250,250,247,.14);")
@@ -1998,7 +2003,7 @@ PAN_WORDS = ["WEB", "COMMERCE", "AUTOMATION", "AI", "ERP", "SEO", "SOFTWARE"]
1998
2003
  PAN = box("mk-pan",
1999
2004
  {"backgroundColor": {"token": "--mk-accent"},
2000
2005
  "paddingTop": "34px", "paddingBottom": "34px",
2001
- "customStyles": "overflow:hidden;"},
2006
+ "customDeclarations": "overflow:hidden;"},
2002
2007
  _m={"paddingTop": "22px", "paddingBottom": "22px"},
2003
2008
  children=[
2004
2009
  # Two nested motions, because one transform cannot do both jobs.
@@ -2006,11 +2011,11 @@ PAN = box("mk-pan",
2006
2011
  # its own clock so the band is still moving when nobody is scrolling.
2007
2012
  # The word list is emitted TWICE and the loop travels exactly half its
2008
2013
  # own width, which is what makes the wrap invisible.
2009
- box("mk-pan-track", {"customStyles": "width:max-content;"}, [
2014
+ box("mk-pan-track", {"customDeclarations": "width:max-content;"}, [
2010
2015
  box("mk-pan-loop",
2011
2016
  {"display": "flex", "columnGap": "56px",
2012
2017
  "alignItems": "baseline",
2013
- "customStyles": "white-space:nowrap;width:max-content;"},
2018
+ "customDeclarations": "white-space:nowrap;width:max-content;"},
2014
2019
  _m={"columnGap": "30px"},
2015
2020
  children=[
2016
2021
  node for c in range(2)
@@ -2067,7 +2072,7 @@ MATRIX_SEC = section("matrix", [wrap("mk-mx-in", [
2067
2072
  box("mk-mx-head",
2068
2073
  {"display": "flex", "justifyContent": "space-between",
2069
2074
  "columnGap": "20px", "rowGap": "8px", "alignItems": "baseline",
2070
- "customStyles": "flex-wrap:wrap;"},
2075
+ "customDeclarations": "flex-wrap:wrap;"},
2071
2076
  [mono("TABLE 01 — CAPABILITY", size="10px",
2072
2077
  color="--mk-accent-ink", track="0.22em"),
2073
2078
  mono("● 標準 ◐ 選配 ○ 不含", size="10px",
@@ -2077,7 +2082,7 @@ MATRIX_SEC = section("matrix", [wrap("mk-mx-in", [
2077
2082
  {"display": "grid", "gridCols": "1fr repeat(3, 78px)",
2078
2083
  "columnGap": "10px", "alignItems": "end", "marginTop": "26px",
2079
2084
  "paddingBottom": "10px",
2080
- "customStyles": "border-bottom:1px solid " + RULE_INK + ";"},
2085
+ "customDeclarations": "border-bottom:1px solid " + RULE_INK + ";"},
2081
2086
  _m={"gridCols": "1fr repeat(3, 46px)", "columnGap": "6px"},
2082
2087
  children=[mono("CAPABILITY", size="10px", color="--mk-faint",
2083
2088
  track="0.18em")]
@@ -2090,14 +2095,14 @@ MATRIX_SEC = section("matrix", [wrap("mk-mx-in", [
2090
2095
  {"display": "grid", "gridCols": "1fr repeat(3, 78px)",
2091
2096
  "columnGap": "10px", "alignItems": "center",
2092
2097
  "paddingTop": "13px", "paddingBottom": "13px",
2093
- "customStyles": "border-bottom:1px solid " + RULE + ";"},
2098
+ "customDeclarations": "border-bottom:1px solid " + RULE + ";"},
2094
2099
  _m={"gridCols": "1fr repeat(3, 46px)", "columnGap": "6px",
2095
2100
  "paddingTop": "11px", "paddingBottom": "11px"},
2096
2101
  children=[
2097
2102
  box("mk-mx-n-%d" % i,
2098
2103
  {"display": "flex", "columnGap": "12px",
2099
2104
  "alignItems": "baseline", "rowGap": "2px",
2100
- "customStyles": "flex-wrap:wrap;"},
2105
+ "customDeclarations": "flex-wrap:wrap;"},
2101
2106
  [T("p", zh, color={"token": "--mk-ink"},
2102
2107
  fontSize="14px", _m={"fontSize": "12.5px"}),
2103
2108
  mono(en, size="9px", color="--mk-faint",
@@ -2120,7 +2125,7 @@ def flow_cell(attr, zh, en):
2120
2125
  return box(attr,
2121
2126
  {"paddingTop": "14px", "paddingBottom": "14px",
2122
2127
  "paddingLeft": "16px", "paddingRight": "16px",
2123
- "customStyles": "border:1px solid " + RULE + ";"},
2128
+ "customDeclarations": "border:1px solid " + RULE + ";"},
2124
2129
  [mono(en, size="9px", color="--mk-faint", track="0.18em"),
2125
2130
  T("p", zh, color={"token": "--mk-ink"}, fontSize="14px",
2126
2131
  marginTop="6px", _m={"fontSize": "13px"})])
@@ -2131,7 +2136,7 @@ def arrow(attr):
2131
2136
  "alignItems": "center"},
2132
2137
  [T("p", "→", color={"token": "--mk-accent-ink"}, fontSize="15px",
2133
2138
  fontFamily=MONO)],
2134
- _m={"customStyles": "transform:rotate(90deg);"})
2139
+ _m={"customDeclarations": "transform:rotate(90deg);"})
2135
2140
 
2136
2141
 
2137
2142
  FIGURE_SEC = section("figure", [wrap("mk-fig2-in", [
@@ -2141,7 +2146,7 @@ FIGURE_SEC = section("figure", [wrap("mk-fig2-in", [
2141
2146
  box("mk-fig2-head",
2142
2147
  {"display": "flex", "justifyContent": "space-between",
2143
2148
  "columnGap": "20px", "rowGap": "8px",
2144
- "customStyles": "flex-wrap:wrap;"},
2149
+ "customDeclarations": "flex-wrap:wrap;"},
2145
2150
  [mono("FIGURE 01 — A WORKFLOW", size="10px",
2146
2151
  color="--mk-accent-ink", track="0.22em"),
2147
2152
  mono("INPUT → PROCESS → OUTPUT", size="10px",
@@ -2195,7 +2200,7 @@ PLATE = section("plate", [wrap("mk-plate-in", [
2195
2200
  # stroke that clears it. It was invisible until the audit
2196
2201
  # learned to read `-webkit-text-stroke-color` instead of
2197
2202
  # giving up at a transparent `color`.
2198
- customStyles="-webkit-text-stroke:1px rgba(22,24,28,.52);",
2203
+ customDeclarations="-webkit-text-stroke:1px rgba(22,24,28,.52);",
2199
2204
  _t={"fontSize": "104px"}, _m={"fontSize": "68px"})]),
2200
2205
  box("mk-plate-t", {}, [
2201
2206
  mono("PLATE 01 — POSITION", size="10px", color="--mk-accent-ink",
@@ -2239,7 +2244,7 @@ SPECIMEN = section("specimen", [wrap("mk-spec2-in", [
2239
2244
  box("mk-spec2-head",
2240
2245
  {"display": "flex", "justifyContent": "space-between",
2241
2246
  "columnGap": "20px", "rowGap": "8px",
2242
- "customStyles": "flex-wrap:wrap;"},
2247
+ "customDeclarations": "flex-wrap:wrap;"},
2243
2248
  [mono("TYPE SPECIMEN", size="10px", color="--mk-accent",
2244
2249
  track="0.22em"),
2245
2250
  mono("THREE FACES / ONE SCALE", size="10px",
@@ -2251,7 +2256,7 @@ SPECIMEN = section("specimen", [wrap("mk-spec2-in", [
2251
2256
  {"display": "grid", "gridCols": "1fr auto",
2252
2257
  "columnGap": "28px", "alignItems": "baseline",
2253
2258
  "paddingTop": "20px", "paddingBottom": "20px",
2254
- "customStyles":
2259
+ "customDeclarations":
2255
2260
  "border-top:1px solid " + RULE_DARK + ";"},
2256
2261
  _m={"gridCols": "1fr", "rowGap": "6px",
2257
2262
  "paddingTop": "14px", "paddingBottom": "14px"},
@@ -2779,7 +2784,7 @@ ACCOUNT_TREE = {"type": "div", "data": {"attrID": "mk-acct"}, "children": [
2779
2784
  box("mk-acct-head",
2780
2785
  {"display": "grid", "gridCols": "84px 1fr", "columnGap": "0px",
2781
2786
  "alignItems": "start", "paddingTop": "22px",
2782
- "customStyles": "border-top:1px solid " + RULE + ";"},
2787
+ "customDeclarations": "border-top:1px solid " + RULE + ";"},
2783
2788
  _m={"gridCols": "48px 1fr"},
2784
2789
  children=[
2785
2790
  mono("§A", size="12px", color="--mk-accent-ink",
@@ -2803,7 +2808,7 @@ ACCOUNT_TREE = {"type": "div", "data": {"attrID": "mk-acct"}, "children": [
2803
2808
  {"display": "grid", "gridCols": "150px 1fr",
2804
2809
  "columnGap": "20px", "alignItems": "baseline",
2805
2810
  "paddingTop": "13px", "paddingBottom": "13px",
2806
- "customStyles":
2811
+ "customDeclarations":
2807
2812
  "border-top:1px solid " + RULE + ";"},
2808
2813
  _m={"gridCols": "84px 1fr", "columnGap": "12px"},
2809
2814
  children=[
@@ -2844,7 +2849,7 @@ SITE = {
2844
2849
  "variables": TOKENS,
2845
2850
  # Element classes are theme-global, and this install carries two brands,
2846
2851
  # so the type system is baked into the nodes by apply_type() instead.
2847
- "elementClasses": {},
2852
+ "variants": {},
2848
2853
  },
2849
2854
  "shell": {"header": apply_type(HEADER, DISPLAY, CJK, "600"),
2850
2855
  "footer": apply_type(FOOTER, DISPLAY, CJK, "600")},