@csszyx/mcp-server 0.10.12 → 0.11.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 (2) hide show
  1. package/llms-full.txt +151 -82
  2. package/package.json +4 -4
package/llms-full.txt CHANGED
@@ -92,7 +92,10 @@ font-variant-numeric (`ordinal`, `tabularNums`), default-or-value (`grow`,
92
92
  ```tsx
93
93
  <div sz={{ color: "--ds-primary", p: "--spacing-4" }} />
94
94
  // → className="text-(--ds-primary) p-(--spacing-4)"
95
- // Sugar: any value starting with -- is auto-wrapped in ()
95
+ // Plain --tokens use CSS-variable (); --functions(...) use arbitrary []
96
+
97
+ <div sz={{ text: "--spacing(4)" }} />
98
+ // → className="text-[--spacing(4)]"
96
99
  ```
97
100
 
98
101
  ### Color with opacity
@@ -332,11 +335,26 @@ Composing multiple classes for a single effect.
332
335
 
333
336
  Mapping precise, non-theme values to JIT syntax (Arbitrary Properties or Values).
334
337
 
335
- | Concept | CSS Property | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
336
- | :------------------ | :---------------------------- | :----------------------------- | :---------------------------------- | :---------------------------------------- |
337
- | **Arbitrary Color** | `background-color: #316ff6` | `bg-[#316ff6]` | `{ bg: '#316ff6' }` | Preferred over inline styles for caching. |
338
- | **Arbitrary Size** | `width: 333px` | `w-[333px]` | `{ w: '333px' }` | Explicit unit required string. |
339
- | **Data Prop** | `content: attr(data-content)` | `content-[attr(data-content)]` | `{ content: 'attr(data-content)' }` | Complex arbitrary strings. |
338
+ | Concept | CSS Property | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
339
+ | :------------------- | :---------------------------------------------------------- | :----------------------------------- | :----------------------------------------- | :------------------------------------------------ |
340
+ | **Arbitrary Color** | `background-color: #316ff6` | `bg-[#316ff6]` | `{ bg: '#316ff6' }` | Preferred over inline styles for caching. |
341
+ | **Arbitrary Size** | `width: 333px` | `w-[333px]` | `{ w: '333px' }` | Explicit unit required string. |
342
+ | **Data Prop** | `content: attr(data-content)` | `content-[attr(data-content)]` | `{ content: 'attr(data-content)' }` | Complex arbitrary strings. |
343
+ | **CSS Variable** | `padding: var(--gap)` | `p-(--gap)` | `{ p: '--gap' }` | Bare `--name` → **parenthesized** var sugar. |
344
+ | **Build-Time Fn** | `font-size: calc(var(--spacing) * 4)` | `text-[--spacing(4)]` | `{ text: '--spacing(4)' }` | `--name(...)` → **bracketed** arbitrary (v4.3.2). |
345
+ | **Alpha Fn (color)** | `color: color-mix(in oklab, var(--brand) 50%, transparent)` | `text-[--alpha(var(--brand)_/_50%)]` | `{ color: '--alpha(var(--brand) / 50%)' }` | Tailwind color function; same `--fn(...)` rule. |
346
+
347
+ **`--` prefix — the one rule that decides parens vs brackets** (applies to EVERY
348
+ value position — `p`, `bg`, `m`, `w`, `text`, …, not just font-size):
349
+
350
+ - A **bare** `--name` (no call) is a **CSS variable** → `x-(--name)`.
351
+ `{ bg: '--brand' }` → `bg-(--brand)`. **Never** `bg-[--brand]`.
352
+ - A **`--name(...)`** shaped value (a balanced function call spanning the whole
353
+ value) is a **Tailwind build-time function** → `x-[--name(...)]` (v4.3.2+).
354
+ `{ p: '--spacing(2)' }` → `p-[--spacing(2)]`. Works for any function
355
+ (`--spacing()`, `--alpha()`, …), not a fixed list.
356
+ - Either way you write **no brackets and no parens in `sz`** — the compiler picks
357
+ the right wrapper from the value's shape.
340
358
 
341
359
  **Global Parsing Rule**: The compiler **MUST normalize whitespace** in arbitrary variant _keys_ before generation.
342
360
 
@@ -408,19 +426,19 @@ Styling based on descendants.
408
426
 
409
427
  Styling children based on parent `group` class.
410
428
 
411
- | Concept | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
412
- | :--------------------------- | :------------------------------------ | :---------------------------------------------------------------- | :----------------------------------- |
413
- | **Group Hover** | `group-hover:text-white` | `{ group: { hover: { color: 'white' } } }` | **Sugar**: Nested scope. |
414
- | **Group Focus** | `group-focus:text-white` | `{ group: { focus: { color: 'white' } } }` | |
415
- | **Group Active** | `group-active:text-white` | `{ group: { active: { color: 'white' } } }` | |
416
- | **Nested Groups** | `group-hover/name:text-white` | `{ group: { name: { hover: { color: 'white' } } } }` | **Sugar**: Scope name as nested key. |
417
- | **Arbitrary Groups** | `group-[.is-published]:block` | `{ group: { '.is-published': { display: 'block' } } }` | |
418
- | **Group Has** | `group-has-[a]:block` | `{ group: { has: { a: { display: 'block' } } } }` | |
419
- | **Group Data** | `group-data-[active]:text-blue` | `{ group: { data: { active: { color: 'blue' } } } }` | **Sugar**: Nested `data` key. |
420
- | **Group Data (named)** | `group-data-[active]/card:text-blue` | `{ group: { card: { data: { active: { color: 'blue' } } } } }` | Name before `data` key. |
421
- | **Group Data (value match)** | `group-data-[state=open]:block` | `{ group: { data: { 'state=open': { display: 'block' } } } }` | `=` in key → bracket form always. |
422
- | **Group ARIA** | `group-aria-expanded:block` | `{ group: { aria: { expanded: { display: 'block' } } } }` | Standard states: bare form. |
423
- | **Group ARIA (arbitrary)** | `group-aria-[current=page]:font-bold` | `{ group: { aria: { 'current=page': { weight: 'bold' } } } }` | Non-standard: bracket form. |
429
+ | Concept | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
430
+ | :--------------------------- | :------------------------------------ | :------------------------------------------------------------- | :----------------------------------- |
431
+ | **Group Hover** | `group-hover:text-white` | `{ group: { hover: { color: 'white' } } }` | **Sugar**: Nested scope. |
432
+ | **Group Focus** | `group-focus:text-white` | `{ group: { focus: { color: 'white' } } }` | |
433
+ | **Group Active** | `group-active:text-white` | `{ group: { active: { color: 'white' } } }` | |
434
+ | **Nested Groups** | `group-hover/name:text-white` | `{ group: { name: { hover: { color: 'white' } } } }` | **Sugar**: Scope name as nested key. |
435
+ | **Arbitrary Groups** | `group-[.is-published]:block` | `{ group: { '.is-published': { display: 'block' } } }` | |
436
+ | **Group Has** | `group-has-[a]:block` | `{ group: { has: { a: { display: 'block' } } } }` | |
437
+ | **Group Data** | `group-data-[active]:text-blue` | `{ group: { data: { active: { color: 'blue' } } } }` | **Sugar**: Nested `data` key. |
438
+ | **Group Data (named)** | `group-data-[active]/card:text-blue` | `{ group: { card: { data: { active: { color: 'blue' } } } } }` | Name before `data` key. |
439
+ | **Group Data (value match)** | `group-data-[state=open]:block` | `{ group: { data: { 'state=open': { display: 'block' } } } }` | `=` in key → bracket form always. |
440
+ | **Group ARIA** | `group-aria-expanded:block` | `{ group: { aria: { expanded: { display: 'block' } } } }` | Standard states: bare form. |
441
+ | **Group ARIA (arbitrary)** | `group-aria-[current=page]:font-bold` | `{ group: { aria: { 'current=page': { weight: 'bold' } } } }` | Non-standard: bracket form. |
424
442
 
425
443
  ## Styling based on sibling state (Peers)
426
444
 
@@ -627,16 +645,16 @@ Strategy for static analysis vs runtime generation.
627
645
 
628
646
  **Core Decision**: `CSSzyx` uses **AST Parsing**, not Regex Scanning. This allows for smarter static extraction and shake-tree logic.
629
647
 
630
- | Concept | Tailwind Scanner (Regex) | `sz` Compiler (AST) | Note |
631
- | :---------------------------- | :----------------------- | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
632
- | **String Interpolation** | ❌ Fails `bg-${color}` | ✅ **Runtime Support** | Compiler marks as dynamic, handled at runtime via variable injection. |
633
- | **Conditionals** | ❌ Fails logic | ✅ **Static Extraction** | `{ bg: active ? 'blue' : 'gray' }` and `{ scale: shrunk ? 75 : 100 }` → both branches compiled to static Tailwind classes at build time. CSS variable fallback only when a branch is a runtime expression (not a literal). |
634
- | **Variable reference** | ❌ Not applicable | ✅ **Build time** | `sz={myVar}` — pass variable directly when no override needed. Compiler resolves the binding to its object literal initializer (incl. `as const`, `satisfies`, explicit type annotation). |
635
- | **Object Spread** | ❌ Fails spread | ✅ **Static Analysis** | `sz={{ ...baseProps, key: val }}` — use spread only when overriding/adding; last key wins. Resolved at build time for local literals. Multiple/nested spreads supported. Imported vars fall back to `_sz()` — no crash. |
636
- | **Array variable items** | ❌ Not applicable | ✅ **Build time** | `sz={[varA, varB]}` and `sz={[varA, cond && varB]}` — variable array elements resolved at build time. Static elements merged to single string; conditional elements use `_szMerge` at runtime. |
637
- | **Ternary variable branches** | ❌ Not applicable | ✅ **Build time** | `sz={cond ? varA : varB}` — both branches compiled to static strings when variables are local literals. |
638
- | **Chained variables** | ❌ Not applicable | ✅ **Build time** | `const b = { ...a, key: val }; <div sz={b} />` — compiler resolves the chain recursively. |
639
- | **Safelist** | Required for dynamic | **Not Required** | Auto-detected for static logic; Auto-injected for runtime values. |
648
+ | Concept | Tailwind Scanner (Regex) | `sz` Compiler (AST) | Note |
649
+ | :---------------------------- | :----------------------- | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
650
+ | **String Interpolation** | ❌ Fails `bg-${color}` | ✅ **Runtime Support** | Compiler marks as dynamic, handled at runtime via variable injection. |
651
+ | **Conditionals** | ❌ Fails logic | ✅ **Static Extraction** | `{ bg: active ? 'blue' : 'gray' }` and `{ scale: shrunk ? 75 : 100 }` → both branches compiled to static Tailwind classes at build time. CSS variable fallback only when a branch is a runtime expression (not a literal). |
652
+ | **Variable reference** | ❌ Not applicable | ✅ **Build time** | `sz={myVar}` — pass variable directly when no override needed. Compiler resolves the binding to its object literal initializer (incl. `as const`, `satisfies`, explicit type annotation). |
653
+ | **Object Spread** | ❌ Fails spread | ✅ **Static Analysis** | `sz={{ ...baseProps, key: val }}` — use spread only when overriding/adding; last key wins. Resolved at build time for local literals. Multiple/nested spreads supported. Imported vars fall back to `_sz()` — no crash. |
654
+ | **Array variable items** | ❌ Not applicable | ✅ **Build time** | `sz={[varA, varB]}` and `sz={[varA, cond && varB]}` — LATER WINS composition. All-static-object arrays deep-merge at build (later leaf wins per key path, sibling keys survive) into one className; arrays with strings/conditions/dynamic elements emit `_szcn(...)` — a compiler-injected helper (`_` = generated code, never hand-authored; the unmemoized twin of `szcn`) applying the same later-wins rule per property group at runtime; dynamic elements (e.g. a forwarded `szsc` slot) pass through `_szPart` (string passthrough / sz-object compile). |
655
+ | **Ternary variable branches** | ❌ Not applicable | ✅ **Build time** | `sz={cond ? varA : varB}` — both branches compiled to static strings when variables are local literals. |
656
+ | **Chained variables** | ❌ Not applicable | ✅ **Build time** | `const b = { ...a, key: val }; <div sz={b} />` — compiler resolves the chain recursively. |
657
+ | **Safelist** | Required for dynamic | **Not Required** | Auto-detected for static logic; Auto-injected for runtime values. |
640
658
 
641
659
  **Performance Rule**: Prefer **Static Strings** in `sz` objects.
642
660
 
@@ -656,17 +674,17 @@ Two independent layers:
656
674
  runtime as long as the component forwards `className` down to a host element.
657
675
  - **Type** — only auto-typed when the component's props derive from host attributes.
658
676
 
659
- | Component props type | `sz` typed? |
660
- | :--------------------------------------------------------- | :------------------ |
661
- | `{ title: string }` (fresh type) | ❌ TS error |
662
- | `ComponentProps<'div'>` / `extends HTMLAttributes<T>` | ✅ inherited |
663
- | `{ title: string } & Pick<ComponentProps<'div'>, 'sz'>` | ✅ just `sz` |
677
+ | Component props type | `sz` typed? |
678
+ | :------------------------------------------------------ | :----------- |
679
+ | `{ title: string }` (fresh type) | ❌ TS error |
680
+ | `ComponentProps<'div'>` / `extends HTMLAttributes<T>` | ✅ inherited |
681
+ | `{ title: string } & Pick<ComponentProps<'div'>, 'sz'>` | ✅ just `sz` |
664
682
 
665
683
  Add `sz` to a fresh props type by picking it (no import needed) or declaring it:
666
684
 
667
685
  ```tsx
668
- import type { ComponentProps } from 'react';
669
- type Props = { title: string } & Pick<ComponentProps<'div'>, 'sz'>;
686
+ import type { ComponentProps } from "react";
687
+ type Props = { title: string } & Pick<ComponentProps<"div">, "sz">;
670
688
  // equivalent: import type { SzPropValue } from '@csszyx/types'; then `sz?: SzPropValue`
671
689
  ```
672
690
 
@@ -689,8 +707,8 @@ a normal `sz`. So style a compound component's parts by giving each part its own
689
707
 
690
708
  ```tsx
691
709
  <Card sz={{ p: 4 }}>
692
- <Card.Header sz={{ bg: 'gray-100', font: 'bold' }}>Title</Card.Header>
693
- <Card.Body sz={{ text: 'sm' }}>Body</Card.Body>
710
+ <Card.Header sz={{ bg: "gray-100", font: "bold" }}>Title</Card.Header>
711
+ <Card.Body sz={{ text: "sm" }}>Body</Card.Body>
694
712
  </Card>
695
713
  // → each part compiled to className at build time; all classes safelisted.
696
714
  ```
@@ -712,17 +730,23 @@ is scanned (`build.scanCss`); classes written in plain CSS register via
712
730
 
713
731
  For parts a component renders ITSELF (no consumer content), `szs` maps slot names
714
732
  to sz values. The transform compiles each VALUE to its class string (key kept),
715
- safelisting + mangling like `sz`; the component forwards `props.szs?.<slot>` into
716
- the matching child's `className`.
733
+ safelisting + mangling like `sz`, and rewrites the attribute to `szsc` ("szs,
734
+ compiled") — the string-typed prop the component reads. Consumers WRITE `szs`,
735
+ components READ `szsc`; declare both from one slot union with `SzsProps`.
717
736
 
718
737
  ```tsx
719
- type CardProps = { szs?: Szs<'header' | 'icon'> }; // Szs from @csszyx/types
720
- <Card szs={{ header: { bg: 'gray-100' }, icon: { color: 'red-500' } }} />
721
- // → <Card szs={{ header: "bg-gray-100", icon: "text-red-500" }} />
722
- // component: <header className={szsClass(props.szs?.header)} />
723
- // szsClass (from @csszyx/runtime) narrows the compiled slot to string | undefined —
724
- // slots TYPE as sz values but ARE class strings after the transform; the helper
725
- // is also fail-safe (uncompiled slot -> undefined, never "[object Object]").
738
+ // INSIDE the component declare slots, READ `szsc` (compiled strings):
739
+ type CardProps = { title: string } & SzsProps<"header" | "icon">; // from @csszyx/types
740
+ function Card({ szsc }: CardProps) {
741
+ return <header className={szsc?.header} />; // plain string — no cast, no szsClass
742
+ }
743
+
744
+ // OUTSIDE at the call site consumer WRITES `szs` (sz objects):
745
+ <Card szs={{ header: { bg: "gray-100" }, icon: { color: "red-500" } }} />;
746
+ // build rewrites the call → <Card szsc={{ header: "bg-gray-100", icon: "text-red-500" }} />
747
+ // szs = write side (consumer). szsc = read side (component). Never swap them;
748
+ // never hand-write szsc. szsc?.slot is undefined when the consumer didn't style
749
+ // that slot or the call wasn't compiled (build warns) — an object never reaches className.
726
750
  ```
727
751
 
728
752
  Rules: custom components only (host element → dev warn, unchanged). Slot values
@@ -731,6 +755,25 @@ identifiers/conditionals/spreads leave the attribute unchanged with a dev warnin
731
755
  Keys are identifiers. `sz` styles the element itself; `szs` styles its internal
732
756
  parts — a component can take both.
733
757
 
758
+ **AI contract (do exactly this):**
759
+
760
+ - Type props with `SzsProps<'a' | 'b'>` from `@csszyx/types` (intersect for
761
+ extra props: `{ title: string } & SzsProps<'a'>`). Read `props.szsc?.<slot>`
762
+ in the component; the consumer passes `szs={{ … }}`.
763
+ - `szsc?.<slot>` is ALREADY a `string | undefined`. Forward it straight:
764
+ `className={szsc?.icon}`, or compose defaults with an array `sz={[{…}, szsc?.icon]}`.
765
+ - Compose slot + default with `sz={[default, szsc?.slot]}` (array = later-wins).
766
+ Do NOT wrap it in `szcn(...)` in `className` — that pattern is obsolete.
767
+ - `szsClass()` was REMOVED — do not emit it. `_szcn`/`_szPart` are
768
+ compiler-injected (the `_` marks generated code) — never write, import, or
769
+ suggest them; they appear only in compiler OUTPUT.
770
+ - Never emit `szsc={{…}}` yourself — the compiler produces it from `szs`.
771
+ Author `szs`, read `szsc`.
772
+
773
+ Migration from ≤0.10: `className={szcn('font-medium', szsClass(szs?.title))}`
774
+ → `sz={[{ weight: 'medium' }, szsc?.title]}` (and props `Szs<'title'>` →
775
+ `SzsProps<'title'>`, read `szsc` not `szs`).
776
+
734
777
 
735
778
  # Backgrounds
736
779
 
@@ -1693,27 +1736,29 @@ Controlling auto-placement algorithm.
1693
1736
 
1694
1737
  Controlling implicit column sizing.
1695
1738
 
1696
- | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Canonical) |
1697
- | :--------------- | :------------------------------------ | :-------------------------- | :------------------------------ |
1698
- | **Auto** | `grid-auto-columns: auto` | `auto-cols-auto` | `{ autoCols: 'auto' }` |
1699
- | **Min** | `grid-auto-columns: min-content` | `auto-cols-min` | `{ autoCols: 'min' }` |
1700
- | **Max** | `grid-auto-columns: max-content` | `auto-cols-max` | `{ autoCols: 'max' }` |
1701
- | **Fr** | `grid-auto-columns: minmax(0, 1fr)` | `auto-cols-fr` | `{ autoCols: 'fr' }` |
1702
- | **Arbitrary** | `grid-auto-columns: minmax(0, 2fr)` | `auto-cols-[minmax(0,2fr)]` | `{ autoCols: 'minmax(0,2fr)' }` |
1703
- | **CSS Variable** | `grid-auto-columns: var(--auto-cols)` | `auto-cols-(--auto-cols)` | `{ autoCols: '--auto-cols' }` |
1739
+ | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Canonical) |
1740
+ | :------------------- | :--------------------------------------------- | :-------------------------- | :------------------------------ |
1741
+ | **Auto** | `grid-auto-columns: auto` | `auto-cols-auto` | `{ autoCols: 'auto' }` |
1742
+ | **Min** | `grid-auto-columns: min-content` | `auto-cols-min` | `{ autoCols: 'min' }` |
1743
+ | **Max** | `grid-auto-columns: max-content` | `auto-cols-max` | `{ autoCols: 'max' }` |
1744
+ | **Fr** | `grid-auto-columns: minmax(0, 1fr)` | `auto-cols-fr` | `{ autoCols: 'fr' }` |
1745
+ | **Spacing (v4.3.2)** | `grid-auto-columns: calc(var(--spacing) * 12)` | `auto-cols-12` | `{ autoCols: 12 }` |
1746
+ | **Arbitrary** | `grid-auto-columns: minmax(0, 2fr)` | `auto-cols-[minmax(0,2fr)]` | `{ autoCols: 'minmax(0,2fr)' }` |
1747
+ | **CSS Variable** | `grid-auto-columns: var(--auto-cols)` | `auto-cols-(--auto-cols)` | `{ autoCols: '--auto-cols' }` |
1704
1748
 
1705
1749
  ## Grid Auto Rows
1706
1750
 
1707
1751
  Controlling implicit row sizing.
1708
1752
 
1709
- | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Canonical) |
1710
- | :--------------- | :--------------------------------- | :-------------------------- | :------------------------------ |
1711
- | **Auto** | `grid-auto-rows: auto` | `auto-rows-auto` | `{ autoRows: 'auto' }` |
1712
- | **Min** | `grid-auto-rows: min-content` | `auto-rows-min` | `{ autoRows: 'min' }` |
1713
- | **Max** | `grid-auto-rows: max-content` | `auto-rows-max` | `{ autoRows: 'max' }` |
1714
- | **Fr** | `grid-auto-rows: minmax(0, 1fr)` | `auto-rows-fr` | `{ autoRows: 'fr' }` |
1715
- | **Arbitrary** | `grid-auto-rows: minmax(0, 2fr)` | `auto-rows-[minmax(0,2fr)]` | `{ autoRows: 'minmax(0,2fr)' }` |
1716
- | **CSS Variable** | `grid-auto-rows: var(--auto-rows)` | `auto-rows-(--auto-rows)` | `{ autoRows: '--auto-rows' }` |
1753
+ | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Canonical) |
1754
+ | :------------------- | :------------------------------------------ | :-------------------------- | :------------------------------ |
1755
+ | **Auto** | `grid-auto-rows: auto` | `auto-rows-auto` | `{ autoRows: 'auto' }` |
1756
+ | **Min** | `grid-auto-rows: min-content` | `auto-rows-min` | `{ autoRows: 'min' }` |
1757
+ | **Max** | `grid-auto-rows: max-content` | `auto-rows-max` | `{ autoRows: 'max' }` |
1758
+ | **Fr** | `grid-auto-rows: minmax(0, 1fr)` | `auto-rows-fr` | `{ autoRows: 'fr' }` |
1759
+ | **Spacing (v4.3.2)** | `grid-auto-rows: calc(var(--spacing) * 16)` | `auto-rows-16` | `{ autoRows: 16 }` |
1760
+ | **Arbitrary** | `grid-auto-rows: minmax(0, 2fr)` | `auto-rows-[minmax(0,2fr)]` | `{ autoRows: 'minmax(0,2fr)' }` |
1761
+ | **CSS Variable** | `grid-auto-rows: var(--auto-rows)` | `auto-rows-(--auto-rows)` | `{ autoRows: '--auto-rows' }` |
1717
1762
 
1718
1763
  ## Gap
1719
1764
 
@@ -3229,24 +3274,25 @@ Controlling the font family.
3229
3274
 
3230
3275
  Controlling the font size.
3231
3276
 
3232
- | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
3233
- | :--------------- | :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------- | :---------------------------------------------------------------- |
3234
- | **Scale** | `font-size: (size); line-height: (leading)` | `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, `text-7xl`, `text-8xl`, `text-9xl` | `{ text: 'xs' }`, `{ text: 'sm' }` etc. | Sets size & leading. |
3235
- | **Number** | `font-size: 16px` | `text-[16px]` | `{ text: '16px' }` | `text` is the single canonical key. |
3236
- | **Arbitrary** | `font-size: 1.5rem` | `text-[1.5rem]` | `{ text: '1.5rem' }` | |
3237
- | **CSS Variable** | `font-size: var(--size)` | `text-(length:--size)` | `{ text: '--size' }` | **Sugar**: Auto-detects `--`. Type hint disambiguates from color. |
3277
+ | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
3278
+ | :------------------- | :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------- | :----------------------------------------------------------------------------------------- |
3279
+ | **Scale** | `font-size: (size); line-height: (leading)` | `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, `text-7xl`, `text-8xl`, `text-9xl` | `{ text: 'xs' }`, `{ text: 'sm' }` etc. | Sets size & leading. |
3280
+ | **Number** | `font-size: 16px` | `text-[16px]` | `{ text: '16px' }` | `text` is the single canonical key. |
3281
+ | **Arbitrary** | `font-size: 1.5rem` | `text-[1.5rem]` | `{ text: '1.5rem' }` | |
3282
+ | **CSS Variable** | `font-size: var(--size)` | `text-(length:--size)` | `{ text: '--size' }` | **Sugar**: Auto-detects `--`. Type hint disambiguates from color. |
3283
+ | **Spacing Function** | `font-size: calc(var(--spacing) * 4)` | `text-[--spacing(4)]` | `{ text: '--spacing(4)' }` | v4.3.2: build-time functions are auto-classified as arbitrary values; no brackets in `sz`. |
3238
3284
 
3239
3285
  ## Font Weight
3240
3286
 
3241
3287
  Controlling the font weight.
3242
3288
 
3243
- | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
3244
- | :--------------- | :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ | :----------------------------------------------------------------- |
3289
+ | Concept | CSS Rule | Tailwind v4 Class | `sz` Prop (Object Syntax) | Note |
3290
+ | :--------------- | :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------- | :----------------------------------------------------------------- |
3245
3291
  | **Keywords** | `font-weight: 100-900` | `font-thin`, `font-extralight`, `font-light`, `font-normal`, `font-medium`, `font-semibold`, `font-bold`, `font-extrabold`, `font-black` | `{ weight: 'thin' }`, `{ weight: 'extralight' }` etc. | |
3246
3292
  | **Number** | `font-weight: 100-900` | `font-100`, `font-200`, `font-300`, `font-400`, `font-500`, `font-600`, `font-700`, `font-800`, `font-900` | `{ weight: 100 }`, `{ weight: 200 }` etc. | v4 shorthand. |
3247
- | **Alias** | (Sugar) | `font-bold` | `{ weight: 'bold' }` | Sugar for `weight`. |
3248
- | **Arbitrary** | `font-weight: 550` | `font-[550]` | `{ weight: 550 }` | |
3249
- | **CSS Variable** | `font-weight: var(--w)` | `font-(weight:--w)` | `{ weight: '--w' }` | **Sugar**: Auto-detects `--`. Type hint disambiguates from family. |
3293
+ | **Alias** | (Sugar) | `font-bold` | `{ weight: 'bold' }` | Sugar for `weight`. |
3294
+ | **Arbitrary** | `font-weight: 550` | `font-[550]` | `{ weight: 550 }` | |
3295
+ | **CSS Variable** | `font-weight: var(--w)` | `font-(weight:--w)` | `{ weight: '--w' }` | **Sugar**: Auto-detects `--`. Type hint disambiguates from family. |
3250
3296
 
3251
3297
  ## Font Stretch
3252
3298
 
@@ -3435,17 +3481,29 @@ Works inside `dynamic()` at runtime.
3435
3481
 
3436
3482
  ## sz Array Syntax
3437
3483
 
3438
- Pass an array to the `sz` prop to compose multiple sz objects with conditional items.
3439
- Static items are pre-computed at build time; conditional items use `_szMerge` at runtime:
3484
+ Pass an array to the `sz` prop to compose styles with LATER-WINS semantics: on
3485
+ the same property, a later element overrides an earlier one. All-static-object
3486
+ arrays deep-merge at build time (later leaf wins per key path, sibling keys
3487
+ survive) into one className with zero runtime. Arrays containing class strings,
3488
+ `cond && …` guards, or dynamic values compose at runtime through `_szcn(...)`
3489
+ — a compiler-injected helper (the `_` prefix marks generated code you never
3490
+ hand-author; it is the unmemoized twin of the authorable `szcn`), applying the
3491
+ same later-wins rule per property group, mangle-safe; dynamic elements (e.g. a
3492
+ forwarded `szsc` slot) pass through `_szPart`:
3440
3493
 
3441
3494
  ```tsx
3495
+ <div sz={[{ text: "base", p: 4 }, { text: "lg" }]} />
3496
+ // → className="text-lg p-4" (text-lg overrode text-base at build)
3497
+
3442
3498
  <div
3443
3499
  sz={[
3444
- { display: "flex", items: "center", p: 4 }, // always — extracted at build time
3500
+ { display: "flex", items: "center", p: 4 }, // always — compiled at build time
3445
3501
  isActive && { bg: "blue-500" }, // runtime conditional
3446
- isDisabled && { opacity: 50, cursor: "not-allowed" },
3502
+ szsc?.title, // dynamic resolved by _szPart, merged by _szcn
3447
3503
  ]}
3448
3504
  />
3505
+ // slot-default one-liner in a compound component:
3506
+ <h3 sz={[{ weight: "semibold", text: "base" }, szsc?.title]} />
3449
3507
  ```
3450
3508
 
3451
3509
  ## Reusing Styles
@@ -3520,7 +3578,12 @@ buttonSz({ variant: "invalid" }); // ❌ TS error: '"invalid"' not assignable
3520
3578
  ```
3521
3579
 
3522
3580
  All variant class combinations are catalogued at build time (compiler prescan) — Tailwind
3523
- generates CSS for every combination, no runtime injection needed.
3581
+ generates CSS for every combination, no runtime injection needed. Cataloguing is
3582
+ lenient PER KEY, identically in all three parser engines: an unreadable value (a
3583
+ call, a template string, an imported constant) skips only that key while sibling
3584
+ keys and other variants still reach the safelist; a finite conditional
3585
+ (`p: dense ? 2 : 4`) contributes BOTH branches; `null`/`undefined` mean "key
3586
+ unset"; same-file `const` references and `const` object spreads are followed.
3524
3587
 
3525
3588
  ## @csszyx/dynamic — Runtime CSS Injection
3526
3589
 
@@ -3822,9 +3885,13 @@ compiles to without a build, run `csszyx explain "{ p: 4, bg: 'blue-500' }"`.
3822
3885
 
3823
3886
  ### AST budget guard
3824
3887
 
3825
- Files larger than 50 000 AST nodes throw `ASTBudgetExceededError` at
3826
- build time — pathologically large generated files (json-as-ts fixtures,
3827
- GraphQL schemas) would otherwise hang the build. Raise the cap when you
3888
+ Files larger than 50 000 AST nodes are skipped by the transform with a
3889
+ build warning — pathologically large generated files (json-as-ts fixtures,
3890
+ GraphQL schemas) would otherwise hang the build. A skipped file is left
3891
+ unrewritten and contributes no classes to the safelist. The safelist
3892
+ prescan runs with a 10× cap by default so legitimate large page files keep
3893
+ their CSS; every parser engine (including the native `rust` one) honours
3894
+ the cap and the warning. Raise the cap when a warning names a file you
3828
3895
  need:
3829
3896
 
3830
3897
  ```js
@@ -3885,6 +3952,8 @@ Result: `{ bg: 'brand-500' }` gets autocomplete and type-checking.
3885
3952
  - All spacing values are dynamic (any integer, 0.5-step decimals work bare)
3886
3953
  - Arbitrary values: `{ p: '5px' }` → `p-[5px]` (auto-wrapped)
3887
3954
  - CSS variables: `{ p: '--my-var' }` → `p-(--my-var)` (auto-wrapped)
3955
+ - Build-time functions: `{ text: '--spacing(4)' }` → `text-[--spacing(4)]`
3956
+ - Grid auto-track spacing: `{ autoCols: 12, autoRows: 16 }` → `auto-cols-12 auto-rows-16`
3888
3957
 
3889
3958
  ## Migrate CLI
3890
3959
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@csszyx/mcp-server",
3
- "version": "0.10.12",
3
+ "version": "0.11.0",
4
4
  "description": "Model Context Protocol (MCP) server for csszyx — enables AI agents to understand and generate sz props",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,9 +30,9 @@
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/sdk": "^1.29.0",
32
32
  "zod": "^3.23.8",
33
- "@csszyx/compiler": "0.10.12",
34
- "@csszyx/cli": "0.10.12",
35
- "@csszyx/unplugin": "0.10.12"
33
+ "@csszyx/cli": "0.11.0",
34
+ "@csszyx/compiler": "0.11.0",
35
+ "@csszyx/unplugin": "0.11.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "typescript": "^6.0.3",