@samva/markup 0.1.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 (124) hide show
  1. package/AGENTS.md +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +41 -0
  4. package/dist/ast-DAhnAvQN.d.ts +120 -0
  5. package/dist/ast.d.ts +2 -0
  6. package/dist/ast.js +159 -0
  7. package/dist/ast.js.map +1 -0
  8. package/dist/candidate.d.ts +29 -0
  9. package/dist/candidate.js +88 -0
  10. package/dist/candidate.js.map +1 -0
  11. package/dist/checks-CW0nFj5n.js +58922 -0
  12. package/dist/checks-CW0nFj5n.js.map +1 -0
  13. package/dist/checks.d.ts +26 -0
  14. package/dist/checks.js +2 -0
  15. package/dist/classes.d.ts +27 -0
  16. package/dist/classes.js +184 -0
  17. package/dist/classes.js.map +1 -0
  18. package/dist/compile-sms.d.ts +28 -0
  19. package/dist/compile-sms.js +44 -0
  20. package/dist/compile-sms.js.map +1 -0
  21. package/dist/compile-whatsapp.d.ts +56 -0
  22. package/dist/compile-whatsapp.js +186 -0
  23. package/dist/compile-whatsapp.js.map +1 -0
  24. package/dist/compile.d.ts +93 -0
  25. package/dist/compile.js +938 -0
  26. package/dist/compile.js.map +1 -0
  27. package/dist/components.d.ts +289 -0
  28. package/dist/components.js +106 -0
  29. package/dist/components.js.map +1 -0
  30. package/dist/conditionals.d.ts +10 -0
  31. package/dist/conditionals.js +42 -0
  32. package/dist/conditionals.js.map +1 -0
  33. package/dist/diagnostics-oveE-laV.d.ts +79 -0
  34. package/dist/diagnostics.d.ts +2 -0
  35. package/dist/diagnostics.js +62 -0
  36. package/dist/diagnostics.js.map +1 -0
  37. package/dist/emit.d.ts +50 -0
  38. package/dist/emit.js +151 -0
  39. package/dist/emit.js.map +1 -0
  40. package/dist/footer.d.ts +66 -0
  41. package/dist/footer.js +90 -0
  42. package/dist/footer.js.map +1 -0
  43. package/dist/interpolate.d.ts +27 -0
  44. package/dist/interpolate.js +61 -0
  45. package/dist/interpolate.js.map +1 -0
  46. package/dist/jsx-dev-runtime.d.ts +10 -0
  47. package/dist/jsx-dev-runtime.js +7 -0
  48. package/dist/jsx-dev-runtime.js.map +1 -0
  49. package/dist/jsx-runtime-fSxcvlx4.d.ts +57 -0
  50. package/dist/jsx-runtime.d.ts +2 -0
  51. package/dist/jsx-runtime.js +102 -0
  52. package/dist/jsx-runtime.js.map +1 -0
  53. package/dist/lexer.d.ts +60 -0
  54. package/dist/lexer.js +269 -0
  55. package/dist/lexer.js.map +1 -0
  56. package/dist/model.d.ts +39 -0
  57. package/dist/model.js +90 -0
  58. package/dist/model.js.map +1 -0
  59. package/dist/ops.d.ts +208 -0
  60. package/dist/ops.js +546 -0
  61. package/dist/ops.js.map +1 -0
  62. package/dist/parser-yzjUOGhc.d.ts +387 -0
  63. package/dist/parser.d.ts +2 -0
  64. package/dist/parser.js +821 -0
  65. package/dist/parser.js.map +1 -0
  66. package/dist/predicate-DTtVtLK7.d.ts +49 -0
  67. package/dist/predicate.d.ts +2 -0
  68. package/dist/predicate.js +417 -0
  69. package/dist/predicate.js.map +1 -0
  70. package/dist/presets/category-mapping.d.ts +13 -0
  71. package/dist/presets/category-mapping.js +49 -0
  72. package/dist/presets/category-mapping.js.map +1 -0
  73. package/dist/presets/public-gallery.d.ts +490 -0
  74. package/dist/presets/public-gallery.js +563 -0
  75. package/dist/presets/public-gallery.js.map +1 -0
  76. package/dist/presets/public-handoff.d.ts +68 -0
  77. package/dist/presets/public-handoff.js +105 -0
  78. package/dist/presets/public-handoff.js.map +1 -0
  79. package/dist/presets/public-preview-artifacts.d.ts +41 -0
  80. package/dist/presets/public-preview-artifacts.js +109 -0
  81. package/dist/presets/public-preview-artifacts.js.map +1 -0
  82. package/dist/presets/public-preview.d.ts +1168 -0
  83. package/dist/presets/public-preview.js +1158 -0
  84. package/dist/presets/public-preview.js.map +1 -0
  85. package/dist/presets/sources.d.ts +7 -0
  86. package/dist/presets/sources.js +54 -0
  87. package/dist/presets/sources.js.map +1 -0
  88. package/dist/presets.d.ts +350 -0
  89. package/dist/presets.js +1251 -0
  90. package/dist/presets.js.map +1 -0
  91. package/dist/printer.d.ts +6 -0
  92. package/dist/printer.js +122 -0
  93. package/dist/printer.js.map +1 -0
  94. package/dist/registry.d.ts +42 -0
  95. package/dist/registry.js +646 -0
  96. package/dist/registry.js.map +1 -0
  97. package/dist/render-template.d.ts +42 -0
  98. package/dist/render-template.js +74 -0
  99. package/dist/render-template.js.map +1 -0
  100. package/dist/sms-segments-y4FpPilJ.d.ts +13 -0
  101. package/dist/sms-segments.d.ts +2 -0
  102. package/dist/sms-segments.js +46 -0
  103. package/dist/sms-segments.js.map +1 -0
  104. package/dist/theme-6ApjjiBo.d.ts +116 -0
  105. package/dist/theme-css.d.ts +24 -0
  106. package/dist/theme-css.js +509 -0
  107. package/dist/theme-css.js.map +1 -0
  108. package/dist/theme.d.ts +2 -0
  109. package/dist/theme.js +95 -0
  110. package/dist/theme.js.map +1 -0
  111. package/dist/tokens.d.ts +6 -0
  112. package/dist/tokens.js +417 -0
  113. package/dist/tokens.js.map +1 -0
  114. package/dist/variables-3NGLpNTB.d.ts +77 -0
  115. package/dist/variables.d.ts +2 -0
  116. package/dist/variables.js +141 -0
  117. package/dist/variables.js.map +1 -0
  118. package/dist/version-BITr58kk.js +96 -0
  119. package/dist/version-BITr58kk.js.map +1 -0
  120. package/generated/sml-agent-contract.json +917 -0
  121. package/generated/sml-email-agent-contract.json +790 -0
  122. package/generated/sml-email-language-reference.md +160 -0
  123. package/generated/sml-language-reference.md +220 -0
  124. package/package.json +203 -0
@@ -0,0 +1,790 @@
1
+ {
2
+ "version": "0.0.0",
3
+ "qualityBar": [
4
+ "valid Samva compile",
5
+ "visually faithful light render",
6
+ "visually faithful dark render when source has dark mode",
7
+ "editor-friendly classes and semantic tokens",
8
+ "no raw HTML tags",
9
+ "reusable placeholders and template abstractions",
10
+ "repair compile diagnostics before claiming done"
11
+ ],
12
+ "primitives": [
13
+ {
14
+ "channel": "email",
15
+ "tag": "Email",
16
+ "attributes": {
17
+ "lang": {
18
+ "type": "string",
19
+ "required": false
20
+ },
21
+ "dir": {
22
+ "type": "string",
23
+ "required": false
24
+ },
25
+ "width": {
26
+ "type": "number",
27
+ "required": false,
28
+ "min": 1,
29
+ "max": 10000
30
+ },
31
+ "class": {
32
+ "type": "string",
33
+ "required": false
34
+ }
35
+ },
36
+ "children": "Subject?, Preview?, blocks",
37
+ "description": "Email document root. Exactly one root per template; wraps the whole message."
38
+ },
39
+ {
40
+ "channel": "email",
41
+ "tag": "Subject",
42
+ "attributes": {},
43
+ "children": "text, {{vars}}",
44
+ "description": "Email subject line. Text and interpolations only; must appear before body blocks."
45
+ },
46
+ {
47
+ "channel": "email",
48
+ "tag": "Preview",
49
+ "attributes": {},
50
+ "children": "text, {{vars}}",
51
+ "description": "Inbox preview text (hidden in the body). Text and interpolations only."
52
+ },
53
+ {
54
+ "channel": "email",
55
+ "tag": "Container",
56
+ "attributes": {
57
+ "class": {
58
+ "type": "string",
59
+ "required": false
60
+ },
61
+ "backgroundImage": {
62
+ "type": "string",
63
+ "required": false
64
+ },
65
+ "backgroundPosition": {
66
+ "type": "string",
67
+ "required": false,
68
+ "values": ["center", "top", "bottom"]
69
+ },
70
+ "backgroundSize": {
71
+ "type": "string",
72
+ "required": false,
73
+ "values": ["cover", "contain", "auto"]
74
+ }
75
+ },
76
+ "children": "blocks",
77
+ "description": "Centered 600px max-width wrapper. Compiles to a table on the outlook-safe base."
78
+ },
79
+ {
80
+ "channel": "email",
81
+ "tag": "Section",
82
+ "attributes": {
83
+ "class": {
84
+ "type": "string",
85
+ "required": false
86
+ },
87
+ "backgroundImage": {
88
+ "type": "string",
89
+ "required": false
90
+ },
91
+ "backgroundPosition": {
92
+ "type": "string",
93
+ "required": false,
94
+ "values": ["center", "top", "bottom"]
95
+ },
96
+ "backgroundSize": {
97
+ "type": "string",
98
+ "required": false,
99
+ "values": ["cover", "contain", "auto"]
100
+ }
101
+ },
102
+ "children": "blocks",
103
+ "description": "Full-width band. Padding splits onto the inner cell for Outlook/Klaviyo."
104
+ },
105
+ {
106
+ "channel": "email",
107
+ "tag": "Row",
108
+ "attributes": {
109
+ "class": {
110
+ "type": "string",
111
+ "required": false
112
+ }
113
+ },
114
+ "children": "Column+",
115
+ "description": "Horizontal layout. Children must be <Column>. Use instead of flex/grid."
116
+ },
117
+ {
118
+ "channel": "email",
119
+ "tag": "Column",
120
+ "attributes": {
121
+ "class": {
122
+ "type": "string",
123
+ "required": false
124
+ },
125
+ "width": {
126
+ "type": "string",
127
+ "required": false
128
+ },
129
+ "valign": {
130
+ "type": "string",
131
+ "required": false,
132
+ "values": ["top", "middle", "bottom"]
133
+ }
134
+ },
135
+ "children": "blocks",
136
+ "description": "A cell inside a <Row>. `width` is an HTML width (e.g. \"50%\", \"300\")."
137
+ },
138
+ {
139
+ "channel": "email",
140
+ "tag": "Heading",
141
+ "attributes": {
142
+ "level": {
143
+ "type": "number",
144
+ "required": false,
145
+ "min": 1,
146
+ "max": 6
147
+ },
148
+ "class": {
149
+ "type": "string",
150
+ "required": false
151
+ }
152
+ },
153
+ "children": "text, {{vars}}, strong, em, a",
154
+ "description": "Renders <h1>-<h6> by `level` (default 1)."
155
+ },
156
+ {
157
+ "channel": "email",
158
+ "tag": "Text",
159
+ "attributes": {
160
+ "class": {
161
+ "type": "string",
162
+ "required": false
163
+ }
164
+ },
165
+ "children": "text, {{vars}}, strong, em, a",
166
+ "description": "Paragraph. Ships sane font-size/line-height/margin defaults."
167
+ },
168
+ {
169
+ "channel": "email",
170
+ "tag": "Button",
171
+ "attributes": {
172
+ "href": {
173
+ "type": "string",
174
+ "required": true
175
+ },
176
+ "class": {
177
+ "type": "string",
178
+ "required": false
179
+ }
180
+ },
181
+ "children": "text, {{vars}}, strong, em",
182
+ "description": "Link styled as a button. Set padding via classes; the compiler injects the Outlook mso hack."
183
+ },
184
+ {
185
+ "channel": "email",
186
+ "tag": "Image",
187
+ "attributes": {
188
+ "src": {
189
+ "type": "string",
190
+ "required": true
191
+ },
192
+ "alt": {
193
+ "type": "string",
194
+ "required": false
195
+ },
196
+ "width": {
197
+ "type": "number",
198
+ "required": false,
199
+ "min": 0,
200
+ "max": 10000
201
+ },
202
+ "height": {
203
+ "type": "number",
204
+ "required": false,
205
+ "min": 0,
206
+ "max": 10000
207
+ },
208
+ "class": {
209
+ "type": "string",
210
+ "required": false
211
+ }
212
+ },
213
+ "children": "Source?",
214
+ "description": "Responsive image. Always set `alt` for accessibility. Add a <Source scheme=\"dark\"> child to swap the asset in dark mode."
215
+ },
216
+ {
217
+ "channel": "email",
218
+ "tag": "Source",
219
+ "attributes": {
220
+ "scheme": {
221
+ "type": "string",
222
+ "required": true,
223
+ "values": ["dark"]
224
+ },
225
+ "src": {
226
+ "type": "string",
227
+ "required": true
228
+ }
229
+ },
230
+ "children": "void",
231
+ "description": "Image source variant. Inside <Image>, `scheme=\"dark\"` swaps the asset when dark-mode media queries are honored."
232
+ },
233
+ {
234
+ "channel": "email",
235
+ "tag": "Divider",
236
+ "attributes": {
237
+ "class": {
238
+ "type": "string",
239
+ "required": false
240
+ }
241
+ },
242
+ "children": "void",
243
+ "description": "Horizontal rule (border-top)."
244
+ },
245
+ {
246
+ "channel": "email",
247
+ "tag": "Spacer",
248
+ "attributes": {
249
+ "height": {
250
+ "type": "number",
251
+ "required": true,
252
+ "min": 1,
253
+ "max": 2000
254
+ }
255
+ },
256
+ "children": "void",
257
+ "description": "Vertical gap of `height` px."
258
+ },
259
+ {
260
+ "channel": "email",
261
+ "tag": "List",
262
+ "attributes": {
263
+ "type": {
264
+ "type": "string",
265
+ "required": false,
266
+ "values": ["unordered", "ordered"]
267
+ },
268
+ "class": {
269
+ "type": "string",
270
+ "required": false
271
+ }
272
+ },
273
+ "children": "ListItem+",
274
+ "description": "Bulleted or numbered list. `type` is \"unordered\" (default) or \"ordered\". Children must be <ListItem>."
275
+ },
276
+ {
277
+ "channel": "email",
278
+ "tag": "ListItem",
279
+ "attributes": {
280
+ "class": {
281
+ "type": "string",
282
+ "required": false
283
+ }
284
+ },
285
+ "children": "text, {{vars}}, strong, em, a",
286
+ "description": "A single list row. Inline content only (text, {{vars}}, strong/em/a)."
287
+ },
288
+ {
289
+ "channel": "email",
290
+ "tag": "If",
291
+ "attributes": {
292
+ "test": {
293
+ "type": "string",
294
+ "required": true
295
+ }
296
+ },
297
+ "children": "blocks, Else?",
298
+ "description": "Send-time conditional block. `test` is a predicate over declared variables (see \"Send-time conditionals\" below). Content: blocks, then an optional trailing <Else>."
299
+ },
300
+ {
301
+ "channel": "email",
302
+ "tag": "Else",
303
+ "attributes": {},
304
+ "children": "blocks",
305
+ "description": "The false branch of an <If>. Valid only as the last direct child of <If>."
306
+ },
307
+ {
308
+ "channel": "email",
309
+ "tag": "a",
310
+ "attributes": {
311
+ "href": {
312
+ "type": "string",
313
+ "required": true
314
+ },
315
+ "class": {
316
+ "type": "string",
317
+ "required": false
318
+ }
319
+ },
320
+ "children": "text, {{vars}}, strong, em",
321
+ "description": "Inline link. It has deterministic theme-brand color and underline defaults; use safe classes to override either."
322
+ },
323
+ {
324
+ "channel": "email",
325
+ "tag": "strong",
326
+ "attributes": {},
327
+ "children": "text, {{vars}}, strong, em",
328
+ "description": "Bold inline text."
329
+ },
330
+ {
331
+ "channel": "email",
332
+ "tag": "em",
333
+ "attributes": {},
334
+ "children": "text, {{vars}}, strong, em",
335
+ "description": "Italic inline text."
336
+ }
337
+ ],
338
+ "utilityFamilies": [
339
+ {
340
+ "root": "p",
341
+ "syntax": "p-*",
342
+ "descriptions": ["Padding on all sides (p-4 = 16px). Compiles onto table cells for Outlook."]
343
+ },
344
+ {
345
+ "root": "px",
346
+ "syntax": "px-*",
347
+ "descriptions": ["Horizontal padding."]
348
+ },
349
+ {
350
+ "root": "py",
351
+ "syntax": "py-*",
352
+ "descriptions": ["Vertical padding."]
353
+ },
354
+ {
355
+ "root": "pt",
356
+ "syntax": "pt-*",
357
+ "descriptions": ["Top padding."]
358
+ },
359
+ {
360
+ "root": "pr",
361
+ "syntax": "pr-*",
362
+ "descriptions": ["Right padding."]
363
+ },
364
+ {
365
+ "root": "pb",
366
+ "syntax": "pb-*",
367
+ "descriptions": ["Bottom padding."]
368
+ },
369
+ {
370
+ "root": "pl",
371
+ "syntax": "pl-*",
372
+ "descriptions": ["Left padding."]
373
+ },
374
+ {
375
+ "root": "m",
376
+ "syntax": "m-*",
377
+ "descriptions": [
378
+ "Margin on all sides. Warn tier — some clients strip margins. (warn: some clients strip it)"
379
+ ]
380
+ },
381
+ {
382
+ "root": "mx",
383
+ "syntax": "mx-*",
384
+ "descriptions": [
385
+ "Horizontal margin; mx-auto centers block elements. (warn: some clients strip it)"
386
+ ]
387
+ },
388
+ {
389
+ "root": "my",
390
+ "syntax": "my-*",
391
+ "descriptions": ["Vertical margin. (warn: some clients strip it)"]
392
+ },
393
+ {
394
+ "root": "mt",
395
+ "syntax": "mt-*",
396
+ "descriptions": ["Top margin. (warn: some clients strip it)"]
397
+ },
398
+ {
399
+ "root": "mr",
400
+ "syntax": "mr-*",
401
+ "descriptions": ["Right margin. (warn: some clients strip it)"]
402
+ },
403
+ {
404
+ "root": "mb",
405
+ "syntax": "mb-*",
406
+ "descriptions": ["Bottom margin. (warn: some clients strip it)"]
407
+ },
408
+ {
409
+ "root": "ml",
410
+ "syntax": "ml-*",
411
+ "descriptions": ["Left margin. (warn: some clients strip it)"]
412
+ },
413
+ {
414
+ "root": "w",
415
+ "syntax": "w-*",
416
+ "descriptions": ["Width from the spacing scale (w-32 = 128px), w-full, or w-[600px]/w-[50%]."]
417
+ },
418
+ {
419
+ "root": "max-w",
420
+ "syntax": "max-w-*",
421
+ "descriptions": ["Max width from the container scale (max-w-lg = 512px) or max-w-[600px]."]
422
+ },
423
+ {
424
+ "root": "h",
425
+ "syntax": "h-*",
426
+ "descriptions": ["Height from the spacing scale (h-12 = 48px) or h-[80px]."]
427
+ },
428
+ {
429
+ "root": "text",
430
+ "syntax": "text-*",
431
+ "descriptions": [
432
+ "Font size with paired line-height (text-sm = 14px/20px) or bounded px value (text-[15px] = 15px/22.5px). Put an explicit leading-* after it to override line-height.",
433
+ "Text alignment: text-left, text-center, text-right, text-justify.",
434
+ "Text color from the palette (text-gray-700) or text-[#374151]."
435
+ ]
436
+ },
437
+ {
438
+ "root": "leading",
439
+ "syntax": "leading-*",
440
+ "descriptions": [
441
+ "Line height: named ratios (leading-relaxed) or spacing steps (leading-6 = 24px)."
442
+ ]
443
+ },
444
+ {
445
+ "root": "font",
446
+ "syntax": "font-*",
447
+ "descriptions": [
448
+ "Font weight: font-normal, font-medium, font-semibold, font-bold, ...",
449
+ "Font stack: font-sans, font-serif, font-mono."
450
+ ]
451
+ },
452
+ {
453
+ "root": "tracking",
454
+ "syntax": "tracking-*",
455
+ "descriptions": [
456
+ "Letter spacing: tracking-tighter … tracking-widest (em-based; inlines fine in Outlook). Pair tracking-wide/wider with uppercase for eyebrows."
457
+ ]
458
+ },
459
+ {
460
+ "root": "uppercase",
461
+ "syntax": "uppercase",
462
+ "descriptions": ["Uppercase text transform."]
463
+ },
464
+ {
465
+ "root": "underline",
466
+ "syntax": "underline",
467
+ "descriptions": ["Underlined text."]
468
+ },
469
+ {
470
+ "root": "no-underline",
471
+ "syntax": "no-underline",
472
+ "descriptions": [
473
+ "Removes the underline (links render underlined by default in most clients)."
474
+ ]
475
+ },
476
+ {
477
+ "root": "bg",
478
+ "syntax": "bg-*",
479
+ "descriptions": ["Background color from the palette (bg-white, bg-blue-600) or bg-[#0088cc]."]
480
+ },
481
+ {
482
+ "root": "bg-gradient",
483
+ "syntax": "bg-gradient-*",
484
+ "descriptions": [
485
+ "Linear gradient background for hero sections: bg-gradient-to-b/t/l/r with from-{color} and to-{color}. Modern base compiles a CSS linear-gradient (plus a solid from-color fallback); the outlook-safe base degrades to the solid from-color — Outlook for Windows never renders the gradient."
486
+ ]
487
+ },
488
+ {
489
+ "root": "from",
490
+ "syntax": "from-*",
491
+ "descriptions": [
492
+ "Gradient start color (from-indigo-600). Doubles as the solid fallback color on clients without gradient support (Outlook for Windows)."
493
+ ]
494
+ },
495
+ {
496
+ "root": "to",
497
+ "syntax": "to-*",
498
+ "descriptions": ["Gradient end color (to-purple-600)."]
499
+ },
500
+ {
501
+ "root": "border",
502
+ "syntax": "border-*",
503
+ "descriptions": [
504
+ "Solid border width: border (1px), border-2, border-0.",
505
+ "Border color from the palette (border-gray-200)."
506
+ ]
507
+ },
508
+ {
509
+ "root": "rounded",
510
+ "syntax": "rounded-*",
511
+ "descriptions": [
512
+ "Border radius (rounded-md = 6px). Ignored by Outlook for Windows — buttons degrade to square corners."
513
+ ]
514
+ },
515
+ {
516
+ "root": "rounded-t",
517
+ "syntax": "rounded-t-*",
518
+ "descriptions": [
519
+ "Top border radius for card/header blocks (rounded-t-lg). Degrades to square corners in Outlook for Windows."
520
+ ]
521
+ },
522
+ {
523
+ "root": "rounded-r",
524
+ "syntax": "rounded-r-*",
525
+ "descriptions": [
526
+ "Right-side border radius (rounded-r-lg). Degrades to square corners in Outlook for Windows."
527
+ ]
528
+ },
529
+ {
530
+ "root": "rounded-b",
531
+ "syntax": "rounded-b-*",
532
+ "descriptions": [
533
+ "Bottom border radius for card/footer blocks (rounded-b-lg). Degrades to square corners in Outlook for Windows."
534
+ ]
535
+ },
536
+ {
537
+ "root": "rounded-l",
538
+ "syntax": "rounded-l-*",
539
+ "descriptions": [
540
+ "Left-side border radius (rounded-l-lg). Degrades to square corners in Outlook for Windows."
541
+ ]
542
+ },
543
+ {
544
+ "root": "block",
545
+ "syntax": "block",
546
+ "descriptions": ["display: block."]
547
+ },
548
+ {
549
+ "root": "inline-block",
550
+ "syntax": "inline-block",
551
+ "descriptions": ["display: inline-block."]
552
+ },
553
+ {
554
+ "root": "hidden",
555
+ "syntax": "hidden",
556
+ "descriptions": ["display: none. Pair with sm:block for mobile-only content."]
557
+ }
558
+ ],
559
+ "forbiddenUtilities": [
560
+ {
561
+ "match": "flex",
562
+ "message": "display:flex is unsupported in Outlook for Windows (Word engine) — use <Row>/<Column>"
563
+ },
564
+ {
565
+ "match": "inline-flex",
566
+ "message": "display:inline-flex is unsupported in Outlook for Windows — use <Row>/<Column>"
567
+ },
568
+ {
569
+ "match": "grid",
570
+ "message": "display:grid is unsupported in Outlook for Windows and Gmail — use <Row>/<Column>"
571
+ },
572
+ {
573
+ "match": "inline-grid",
574
+ "message": "display:inline-grid is unsupported in Outlook for Windows — use <Row>/<Column>"
575
+ },
576
+ {
577
+ "match": "gap-",
578
+ "message": "gap requires flex/grid, unsupported in Outlook for Windows — use padding on <Column>"
579
+ },
580
+ {
581
+ "match": "space-",
582
+ "message": "space-* margins require selectors Gmail strips — use padding or <Spacer>"
583
+ },
584
+ {
585
+ "match": "items-",
586
+ "message": "flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column>"
587
+ },
588
+ {
589
+ "match": "justify-",
590
+ "message": "flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> and text-center"
591
+ },
592
+ {
593
+ "match": "self-",
594
+ "message": "flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column>"
595
+ },
596
+ {
597
+ "match": "content-",
598
+ "message": "flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column>"
599
+ },
600
+ {
601
+ "match": "order-",
602
+ "message": "flex order is unsupported in Outlook for Windows — reorder the source instead"
603
+ },
604
+ {
605
+ "match": "absolute",
606
+ "message": "CSS position is ignored by Gmail and Outlook — use nested <Section>s"
607
+ },
608
+ {
609
+ "match": "relative",
610
+ "message": "CSS position is ignored by Gmail and Outlook — use nested <Section>s"
611
+ },
612
+ {
613
+ "match": "fixed",
614
+ "message": "CSS position is ignored by Gmail and Outlook — use nested <Section>s"
615
+ },
616
+ {
617
+ "match": "sticky",
618
+ "message": "CSS position is ignored by Gmail and Outlook — use nested <Section>s"
619
+ },
620
+ {
621
+ "match": "static",
622
+ "message": "CSS position is ignored by Gmail and Outlook — remove it"
623
+ },
624
+ {
625
+ "match": "inset-",
626
+ "message": "position offsets are ignored by Gmail and Outlook — use padding"
627
+ },
628
+ {
629
+ "match": "top-",
630
+ "message": "position offsets are ignored by Gmail and Outlook — use padding"
631
+ },
632
+ {
633
+ "match": "right-",
634
+ "message": "position offsets are ignored by Gmail and Outlook — use padding"
635
+ },
636
+ {
637
+ "match": "bottom-",
638
+ "message": "position offsets are ignored by Gmail and Outlook — use padding"
639
+ },
640
+ {
641
+ "match": "left-",
642
+ "message": "position offsets are ignored by Gmail and Outlook — use padding"
643
+ },
644
+ {
645
+ "match": "z-",
646
+ "message": "z-index is ignored by Gmail and Outlook — remove it"
647
+ },
648
+ {
649
+ "match": "float-",
650
+ "message": "float is unreliable across email clients — use <Row>/<Column>"
651
+ },
652
+ {
653
+ "match": "shadow",
654
+ "message": "box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead"
655
+ },
656
+ {
657
+ "match": "shadow-",
658
+ "message": "box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead"
659
+ },
660
+ {
661
+ "match": "opacity-",
662
+ "message": "opacity is unsupported in Outlook for Windows — bake the tint into the color"
663
+ },
664
+ {
665
+ "match": "transform",
666
+ "message": "CSS transforms are unsupported in email clients — remove them"
667
+ },
668
+ {
669
+ "match": "rotate-",
670
+ "message": "CSS transforms are unsupported in email clients — remove them"
671
+ },
672
+ {
673
+ "match": "scale-",
674
+ "message": "CSS transforms are unsupported in email clients — remove them"
675
+ },
676
+ {
677
+ "match": "translate-",
678
+ "message": "CSS transforms are unsupported in email clients — remove them"
679
+ },
680
+ {
681
+ "match": "skew-",
682
+ "message": "CSS transforms are unsupported in email clients — remove them"
683
+ },
684
+ {
685
+ "match": "transition",
686
+ "message": "transitions don't run in email — remove them"
687
+ },
688
+ {
689
+ "match": "transition-",
690
+ "message": "transitions don't run in email — remove them"
691
+ },
692
+ {
693
+ "match": "duration-",
694
+ "message": "transitions don't run in email — remove them"
695
+ },
696
+ {
697
+ "match": "animate-",
698
+ "message": "animations don't run in email — remove them"
699
+ },
700
+ {
701
+ "match": "blur-",
702
+ "message": "CSS filters are unsupported in most email clients — remove them"
703
+ },
704
+ {
705
+ "match": "brightness-",
706
+ "message": "CSS filters are unsupported in most email clients — remove them"
707
+ },
708
+ {
709
+ "match": "grayscale",
710
+ "message": "CSS filters are unsupported in most email clients — remove them"
711
+ },
712
+ {
713
+ "match": "grayscale-",
714
+ "message": "CSS filters are unsupported in most email clients — remove them"
715
+ },
716
+ {
717
+ "match": "truncate",
718
+ "message": "text truncation is unsupported in Outlook for Windows — shorten the copy"
719
+ },
720
+ {
721
+ "match": "line-clamp-",
722
+ "message": "line clamping is unsupported in email clients — shorten the copy"
723
+ },
724
+ {
725
+ "match": "aspect-",
726
+ "message": "aspect-ratio is unsupported in Outlook and Gmail — set width/height on <Image>"
727
+ },
728
+ {
729
+ "match": "overflow-",
730
+ "message": "overflow is unreliable across email clients — restructure the layout"
731
+ }
732
+ ],
733
+ "repairExamples": [
734
+ {
735
+ "from": "flex gap-4",
736
+ "to": "<Row><Column>...</Column><Column>...</Column></Row>",
737
+ "reason": "Email layout must use table-backed Row/Column primitives."
738
+ },
739
+ {
740
+ "from": "md:text-lg",
741
+ "to": "sm:text-lg",
742
+ "reason": "Only sm: responsive enhancement is supported."
743
+ },
744
+ {
745
+ "from": "bg-[var(--brand)]",
746
+ "to": "bg-brand or bg-[#4f46e5]",
747
+ "reason": "Compiled email has no CSS variables; use a token or literal hex."
748
+ },
749
+ {
750
+ "from": "font-[650]",
751
+ "to": "font-semibold",
752
+ "reason": "Use the supported named font-weight utilities instead of arbitrary weights."
753
+ }
754
+ ],
755
+ "recipes": [
756
+ {
757
+ "name": "security-notice",
758
+ "structure": ["Preview", "Container", "Heading", "Text paragraphs", "Button", "Footer Text"],
759
+ "guidance": "Dense, direct copy; strong contrast; explicit dark background/text classes."
760
+ },
761
+ {
762
+ "name": "product-update",
763
+ "structure": ["Preview", "Container", "Heading", "Section rows", "CTA Button", "Footer"],
764
+ "guidance": "Use cards/sections, short headings, and semantic brand tokens."
765
+ },
766
+ {
767
+ "name": "receipt-invoice",
768
+ "structure": [
769
+ "Preview",
770
+ "Container",
771
+ "Heading",
772
+ "Row/Column line items",
773
+ "Divider",
774
+ "total row"
775
+ ],
776
+ "guidance": "Prefer table-backed Row/Column blocks and right-aligned totals."
777
+ },
778
+ {
779
+ "name": "digest",
780
+ "structure": [
781
+ "Preview",
782
+ "Container",
783
+ "Heading",
784
+ "repeated Section/Text/Button rows",
785
+ "Footer"
786
+ ],
787
+ "guidance": "Keep repeated rows compact; use Divider between entries."
788
+ }
789
+ ]
790
+ }