123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899(** Shared theme variables for consistent ordering and avoiding conflicts *)moduleCss=Cascade.Css(** Main ordering scheme: 1. Font families (1) - basic font families 2. Colors
(2) - color variables 3. Spacing (3) - spacing variables 4. Breakpoints (4)
\- breakpoint variables 5. Containers (5) - container variables 6.
Typography (6) - text sizes and other typography 7. Border radius (7) -
border radius variables 8. Animation/timing (8) - animation variables 9.
Default fonts (9) - default font family variables *)(** {1 Spacing Variables} *)(* Resolve the optionally-threaded theme, defaulting to the base scheme. *)letresolve_scheme=functionSomes->s|None->Scheme.default(* Shared spacing variable used across padding, margin, positioning, etc.
Tailwind v4 uses a single --spacing: 0.25rem variable and calc() for
values. *)letspacing_var=Var.themeCss.Length"spacing"~runtime:true~order:(3,0)(* The base spacing value: 0.25rem *)letspacing_base:Css.length=Rem0.25(* Create a spacing variable for explicit spacing values (e.g., --spacing-4) *)letspacing_n_varn=Var.themeCss.Length("spacing-"^Pp.intn)~order:(3,n)(* Create a spacing length value. When scheme has explicit spacing for |n|,
returns var(--spacing-|n|) or calc(var(--spacing-|n|) * -1) for negatives.
Otherwise returns calc(var(--spacing) * n). Returns the theme declaration and
the length. *)letspacing_calc?themen:Css.declaration*Css.length=letabs_n=absninletis_negative=n<0inmatchScheme.spacing(resolve_schemetheme)abs_nwith|Someexplicit_length->(* Scheme has explicit spacing: use var(--spacing-|n|) *)letspacing_n=spacing_n_varabs_ninletdecl,spacing_ref=Var.bindingspacing_nexplicit_lengthinifis_negativethen(* Negative: wrap in calc(... * -1) *)letneg_len:Css.length=Css.Calc(Css.Calc.mul(Css.Calc.length(Css.Varspacing_ref))(Css.Calc.float(-1.0)))in(decl,neg_len)else(decl,(Css.Varspacing_ref:Css.length))|None->(* Default: calc(var(--spacing) * n). For the unit multiplier we emit a
bare var(--spacing) rather than calc(var(--spacing) * 1). This shortcut
exists only to match Tailwind core byte-for-byte: the fixture has p-1
producing "padding: var(--spacing)" next to p-4 producing
"calc(var(--spacing) * 4)". Without it our output diverges and the
examples/parity comparisons flag the difference.
Runtime expectation: --spacing must resolve to a single length. That is
the spacing-scale contract (the default 0.25rem and any single-value
@theme override). The shortcut is NOT sound under a multi-term runtime
redefinition such as ".dense { --spacing: 1px + 3px }": bare
var(--spacing) then expands to invalid bare math and falls back to the
initial value, whereas calc(var(--spacing) * 1) would still compute
(4px). We inherit this fragility from Tailwind. cascade must not
perform the equivalent calc(var(--spacing)) -> var(--spacing) rewrite,
because it optimises arbitrary CSS and cannot assume that contract. *)letdecl,spacing_ref=Var.bindingspacing_varspacing_baseinifn=1then(decl,(Css.Varspacing_ref:Css.length))elseletlen:Css.length=Css.Calc(Css.Calc.mul(Css.Calc.length(Css.Varspacing_ref))(Css.Calc.float(float_of_intn)))in(decl,len)(* Create a spacing length value for float multipliers like 2.5. For integer
values, checks scheme for explicit spacing. Otherwise uses calc. This handles
cases like my-2.5 which need calc(var(--spacing) * 2.5). *)letspacing_calc_float?theme(n:float):Css.declaration*Css.length=letabs_n=Float.absninletis_negative=n<0.0in(* Check if this is an integer value that might have explicit spacing *)letis_integer=Float.is_integerabs_ninifis_integerthen(* Use integer version which checks scheme *)spacing_calc?theme(int_of_floatn)else(* Fractional value: always use calc *)letdecl,spacing_ref=Var.bindingspacing_varspacing_baseinletmult=ifis_negativethen-.abs_nelseabs_ninletlen:Css.length=Css.Calc(Css.Calc.mul(Css.Calc.length(Css.Varspacing_ref))(Css.Calc.floatmult))in(decl,len)