... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. ... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. (.require [library [lux (.except Label All Location and static false true all alias quote) [control ["[0]" maybe]] [data ["[0]" product] [color [pigment (.only Pigment)] ["[0]" rgb (.only RGB)]] ["[0]" text (.only) ["%" \\format (.only Format format)]] [collection ["[0]" list (.use "[1]#[0]" functor)]]] [math [number ["n" nat] ["i" int] ["r" rev] ["f" frac]]] [meta ["[0]" code (.only) ["<[1]>" \\parser]] [macro [syntax (.only syntax)] ["[0]" template]] [type ["[0]" nominal (.except def)]]] [world [net (.only URL)]]]] [// [selector (.only Label)]]) (def text_symbol (syntax (_ [symbol .text]) (in (list (code.local (text.replaced "-" "_" symbol)))))) (def enumeration (template (_ + +) [(nominal.def .public (def .public (-> ) (|>> representation)) (`` (with_template [ ] [(def .public (abstraction ))] (,, (template.spliced +)) )) (template.spliced +))])) (def (%number value) (Format Frac) (let [raw (%.frac value)] (if (f.< +0.0 value) raw (|> raw (text.split_at 1) maybe.trusted product.right)))) (nominal.def .public (Value brand) Text (def .public value (-> (Value Any) Text) (|>> representation)) (with_template [ ] [(def .public Value (abstraction ))] [initial "initial"] [inherit "inherit"] [unset "unset"] ) (nominal.def .public (Numeric kind) Any) (with_template [] [(with_expansions [' (template.symbol [ "'"])] (nominal.def .public ' Any) (type .public (Numeric ')))] [Number] [Length] [Time] [Percentage] ) (with_template [ + +] [(nominal.def .public Any) (`` (with_template [ ] [(def .public (Value ) (abstraction ))] (,, (template.spliced +)))) (with_expansions [ (template.spliced +)] (with_template [] [(`` (def .public (,, (..text_symbol )) (Value ) (abstraction )))] ))] [All [] []] [Thickness [] [["medium"] ["thin"] ["thick"]]] [Slice [[full_slice "fill"]] []] [Alignment [[auto_alignment "auto"]] [["stretch"] ["center"] ["flex-start"] ["flex-end"] ["baseline"] ["space-between"] ["space-around"]]] [Animation [] []] [Animation_Direction [[normal_direction "normal"]] [["reverse"] ["alternate"] ["alternate-reverse"]]] [Animation_Fill [[fill_forwards "forwards"] [fill_backwards "backwards"] [fill_both "both"]] []] [Column_Fill [] [["balance"] ["auto"]]] [Column_Span [] [["all"]]] [Iteration [] [["infinite"]]] [Count [] []] [Play [] [["paused"] ["running"]]] [Timing [] [["linear"] ["ease"] ["ease-in"] ["ease-out"] ["ease-in-out"] ["step-start"] ["step-end"]]] [Visibility [[invisible "hidden"] [collapse_visibility "collapse"]] [["visible"]]] [Attachment [[scroll_attachment "scroll"] [fixed_attachment "fixed"] [local_attachment "local"]] []] [Blend [[normal_blend "normal"]] [["multiply"] ["screen"] ["overlay"] ["darken"] ["lighten"] ["color-dodge"] ["color-burn"] ["difference"] ["exclusion"] ["hue"] ["saturation"] ["color"] ["luminosity"]]] [Span [] [["border-box"] ["padding-box"] ["content-box"]]] [Image [[no_image "none"]] []] [Repeat [[stretch_repeat "stretch"]] [["repeat"] ["repeat-x"] ["repeat-y"] ["no-repeat"] ["space"] ["round"]]] [Location [[left_top "left top"] [left_center "left center"] [left_bottom "left bottom"] [right_top "right top"] [right_center "right center"] [right_bottom "right bottom"] [center_top "center top"] [center_center "center center"] [center_bottom "center bottom"]] []] [Fit [[no_fit "none"]] [["fill"] ["cover"] ["contain"] ["scale-down"]]] [Border [] [["hidden"] ["dotted"] ["dashed"] ["solid"] ["double"] ["groove"] ["ridge"] ["inset"] ["outset"]]] [Collapse [] [["separate"] ["collapse"]]] [Box_Decoration_Break [] [["slice"] ["clone"]]] [Caption [] [["top"] ["bottom"]]] [Float [[float_left "left"] [float_right "right"]] []] [Clear [[clear_left "left"] [clear_right "right"] [clear_both "both"]] []] [Counter [] []] [Content [] [["open-quote"] ["close-quote"] ["no-open-quote"] ["no-close-quote"]]] [Cursor [[horizontal_text "text"] [no_cursor "none"]] [["alias"] ["all-scroll"] ["cell"] ["context-menu"] ["col-resize"] ["copy"] ["crosshair"] ["default"] ["e-resize"] ["ew-resize"] ["grab"] ["grabbing"] ["help"] ["move"] ["n-resize"] ["ne-resize"] ["nesw-resize"] ["ns-resize"] ["nw-resize"] ["nwse-resize"] ["no-drop"] ["not-allowed"] ["pointer"] ["progress"] ["row-resize"] ["s-resize"] ["se-resize"] ["sw-resize"] ["vertical-text"] ["w-resize"] ["wait"] ["zoom-in"] ["zoom-out"]]] [Shadow [] []] [Clip [] []] [Text_Direction [[left_to_right "ltr"] [right_to_left "rtl"]] []] [Display [[grid_display "grid"] [no_display "none"]] [["inline"] ["block"] ["contents"] ["flex"] ["inline-block"] ["inline-flex"] ["inline-grid"] ["inline-table"] ["list-item"] ["run-in"] ["table"] ["table-caption"] ["table-column-group"] ["table-header-group"] ["table-footer-group"] ["table-row-group"] ["table-cell"] ["table-column"] ["table-row"]]] [Empty [] [["show"] ["hide"]]] [Filter [] []] [Flex_Direction [] [["row"] ["row-reverse"] ["column"] ["column-reverse"]]] [Flex_Wrap [[no_wrap "nowrap"]] [["wrap"] ["wrap_reverse"]]] [Font_Kerning [[auto_kerning "auto"] [normal_kerning "normal"] [no_kerning "none"]] []] [Font_Size [[medium_size "medium"] [xx_small_size "xx-small"] [x_small_size "x-small"] [small_size "small"] [large_size "large"] [x_large_size "x-large"] [xx_large_size "xx-large"] [smaller_size "smaller"] [larger_size "larger"]] []] [Font_Stretch [[normal_stretch "normal"]] [["condensed"] ["ultra-condensed"] ["extra-condensed"] ["semi-condensed"] ["expanded"] ["semi-expanded"] ["extra-expanded"] ["ultra-expanded"]]] [Font_Style [[normal_style "normal"]] [["italic"] ["oblique"]]] [Font_Weight [[normal_weight "normal"] [weight_100 "100"] [weight_200 "200"] [weight_300 "300"] [weight_400 "400"] [weight_500 "500"] [weight_600 "600"] [weight_700 "700"] [weight_800 "800"] [weight_900 "900"]] [["bold"]]] [Font_Variant [[normal_font "normal"]] [["small-caps"]]] [Grid [] []] [Grid_Content [[auto_content "auto"]] [["max-content"] ["min-content"]]] [Grid_Flow [[row_flow "row"] [column_flow "column"] [dense_flow "dense"] [row_dense_flow "row dense"] [column_dense_flow "column dense"]] []] [Grid_Span [[auto_span "auto"]] []] [Grid_Template [] []] [Hanging_Punctuation [[no_hanging_punctuation "none"]] [["first"] ["last"] ["allow-end"] ["force-end"]]] [Hyphens [[no_hyphens "none"] [manual_hyphens "manual"] [auto_hyphens "auto"]] []] [Orientation [] [["portrait"] ["landscape"]]] [Resolution [] []] [Scan [] [["interlace"] ["progressive"]]] [Boolean [[false "0"] [true "1"]] []] [Update [[no_update "none"] [slow_update "slow"] [fast_update "fast"]] []] [Block_Overflow [[no_block_overflow "none"] [scroll_block_overflow "scroll"] [optional_paged_block_overflow "optional-paged"] [paged_block_overflow "paged"]] []] [Inline_Overflow [[no_inline_overflow "none"] [scroll_inline_overflow "scroll"]] []] [Display_Mode [] [["fullscreen"] ["standalone"] ["minimal-ui"] ["browser"]]] [Color_Gamut [] [["srgb"] ["p3"] ["rec2020"]]] [Inverted_Colors [[no_inverted_colors "none"] [inverted_colors "inverted"]] []] [Pointer [[no_pointer "none"] [coarse_pointer "coarse"] [fine_pointer "fine"]] []] [Hover [[no_hover "none"]] [["hover"]]] [Light [[dim_light "dim"] [normal_light "normal"] [washed_light "washed"]] []] [Ratio [] []] [Scripting [[no_scripting "none"] [initial_scripting_only "initial-only"] [scripting_enabled "enabled"]] []] [Motion [[no_motion_preference "no-preference"] [reduced_motion "reduce"]] []] [Color_Scheme [[no_color_scheme_preference "no-preference"] [light_color_scheme "light"] [dark_color_scheme "dark"]] []] [Isolation [[auto_isolation "auto"]] [["isolate"]]] [List_Style_Position [] [["inside"] ["outside"]]] [List_Style_Type [[no_list_style "none"]] [["disc"] ["armenian"] ["circle"] ["cjk-ideographic"] ["decimal"] ["decimal-leading-zero"] ["georgian"] ["hebrew"] ["hiragana"] ["hiragana-iroha"] ["katakana"] ["katakana-iroha"] ["lower-alpha"] ["lower-greek"] ["lower-latin"] ["lower-roman"] ["square"] ["upper-alpha"] ["upper-greek"] ["upper-latin"] ["upper-roman"]]] [Color [] []] [Overflow [[visible_overflow "visible"] [hidden_overflow "hidden"] [scroll_overflow "scroll"] [auto_overflow "auto"]] []] [Page_Break [[auto_page_break "auto"] [always_page_break "always"] [avoid_page_break "avoid"] [left_page_break "left"] [right_page_break "right"]] []] [Pointer_Events [[auto_pointer_events "auto"] [no_pointer_events "none"]] []] [Position [] [["static"] ["absolute"] ["fixed"] ["relative"] ["sticky"]]] [Quotes [[no_quotes "none"]] []] [Resize [[resize_none "none"] [resize_both "both"] [resize_horizontal "horizontal"] [resize_vertical "vertical"]] []] [Scroll_Behavior [[auto_scroll_behavior "auto"] [smooth_scroll_behavior "smooth"]] []] [Table_Layout [[auto_table_layout "auto"] [fixed_table_layout "fixed"]] []] [Text_Align [[left_text_align "left"] [right_text_align "right"] [center_text_align "center"] [justify_text_align "justify"]] []] [Text_Align_Last [[auto_text_align_last "auto"] [left_text_align_last "left"] [right_text_align_last "right"] [center_text_align_last "center"] [justify_text_align_last "justify"] [start_text_align_last "start"] [end_text_align_last "end"]] []] [Text_Decoration_Line [[no_text_decoration_line "none"] [underline_text_decoration_line "underline"] [overline_text_decoration_line "overline"] [line_through_text_decoration_line "line-through"]] []] [Text_Decoration_Style [[solid_text_decoration_style "solid"] [double_text_decoration_style "double"] [dotted_text_decoration_style "dotted"] [dashed_text_decoration_style "dashed"] [wavy_text_decoration_style "wavy"]] []] [Text_Justification [[auto_text_justification "auto"] [inter_word_text_justification "inter-word"] [inter_character_text_justification "inter-character"] [no_text_justification "none"]] []] [Text_Overflow [[clip_text_overflow "clip"] [ellipsis_text_overflow "ellipsis"]] []] [Text_Transform [[no_text_transform "none"]] [["capitalize"] ["uppercase"] ["lowercase"]]] [Transform [[no_transform "none"]] []] [Transform_Origin [] []] [Transform_Style [] [["flat"] ["preserve_3d"]]] [Transition [[transition_none "none"] [transition_all "all"]] []] [Bidi [[bidi_normal "normal"] [bidi_embed "embed"] [bidi_isolate "isolate"] [bidi_isolate_override "isolate-override"] [bidi_plaintext "plaintext"]] [["bidi-override"]]] [User_Select [[user_select_auto "auto"] [user_select_none "none"] [user_select_text "text"] [user_select_all "all"]] []] [Vertical_Align [[vertical_align_baseline "baseline"] [vertical_align_sub "sub"] [vertical_align_super "super"] [vertical_align_top "top"] [vertical_align_text_top "text-top"] [vertical_align_middle "middle"] [vertical_align_bottom "bottom"] [vertical_align_text_bottom "text-bottom"]] []] [White_Space [[normal_white_space "normal"] [no_wrap_white_space "nowrap"] [pre_white_space "pre"] [pre_line_white_space "pre-line"] [pre_wrap_white_space "pre-wrap"]] []] [Word_Break [[normal_word_break "normal"]] [["break-all"] ["keep-all"] ["break-word"]]] [Word_Wrap [[normal_word_wrap "normal"] [break_word_word_wrap "break-word"]] []] [Writing_Mode [[top_to_bottom_writing_mode "horizontal-tb"] [left_to_right_writing_mode "vertical-rl"] [right_to_left_writing_mode "vertical-lr"]] []] [Z_Index [] []] ) (def value_separator ",") (def (apply name inputs) (-> Text (List Text) Value) (|> inputs (text.interposed ..value_separator) (text.enclosed ["(" ")"]) (format name) abstraction)) (enumeration Step Text step [[start "start"] [end "end"]] []) (def .public (steps intervals step) (-> Nat Step (Value Timing)) (..apply "steps" (list (%.nat intervals) (..step step)))) (def .public (cubic_bezier p0 p1 p2 p3) (-> Frac Frac Frac Frac (Value Timing)) (|> (list p0 p1 p2 p3) (list#each %number) (..apply "cubic-bezier"))) (with_template [ ] [(def .public (-> Nat (Value )) (|>> %.nat abstraction))] [iteration Iteration] [count Count] [slice_number/1 Slice] [span_line Grid_Span] ) (def .public animation (-> Label (Value Animation)) (|>> abstraction)) (def .public (rgb color) (-> RGB (Value Color)) (..apply "rgb" (list (%.nat (the rgb.#red color)) (%.nat (the rgb.#green color)) (%.nat (the rgb.#blue color))))) (def .public (rgba pigment) (-> Pigment (Value Color)) (let [(open "/[0]") pigment] (..apply "rgba" (list (%.nat (the rgb.#red /#color)) (%.nat (the rgb.#green /#color)) (%.nat (the rgb.#blue /#color)) (if (r.= (of r.interval top) /#alpha) "1.0" (format "0" (%.rev /#alpha))))))) (with_template [ ] [(def .public ( value) (-> Frac (Value Length)) (abstraction (format (%number value) )))] [em "em"] [ex "ex"] [rem "rem"] [ch "ch"] [vw "vw"] [vh "vh"] [vmin "vmin"] [vmax "vmax"] [% "%"] [cm "cm"] [mm "mm"] [in "in"] [px "px"] [pt "pt"] [pc "pc"] [fr "fr"] ) (def (%int value) (Format Int) (if (i.< +0 value) (%.int value) (%.nat (.nat value)))) (with_template [ ] [(def .public ( value) (-> Int (Value Time)) (abstraction (format (if (i.< +0 value) (%.int value) (%.nat (.nat value))) )))] [seconds "s"] [milli_seconds "ms"] ) (def .public thickness (-> (Value Length) (Value Thickness)) (|>> transmutation)) (def slice_separator " ") (def .public (slice_number/2 horizontal vertical) (-> Nat Nat (Value Slice)) (abstraction (format (%.nat horizontal) ..slice_separator (%.nat vertical)))) (nominal.def .public Stop Text (def .public stop (-> (Value Color) Stop) (|>> (representation Value) (abstraction Stop))) (def stop_separator " ") (def .public (single_stop length color) (-> (Value Length) (Value Color) Stop) (abstraction (format (representation Value color) ..stop_separator (representation Value length)))) (def .public (double_stop start end color) (-> (Value Length) (Value Length) (Value Color) Stop) (abstraction (format (representation Value color) ..stop_separator (representation Value start) ..stop_separator (representation Value end)))) (nominal.def .public Hint Text (def .public hint (-> (Value Length) Hint) (|>> (representation Value) (abstraction Hint))) (def (with_hint [hint stop]) (-> [(Maybe Hint) Stop] Text) (when hint {.#None} (representation Stop stop) {.#Some hint} (format (representation Hint hint) ..value_separator (representation Stop stop)))))) (type .public (List/1 a) [a (List a)]) (nominal.def .public Angle Text (def .public angle (-> Angle Text) (|>> representation)) (def .public (turn value) (-> Rev Angle) (abstraction (format (%.rev value) "turn"))) (def degree_limit Nat 360) (def .public (degree value) (-> Nat Angle) (abstraction (format (%.nat (n.% ..degree_limit value)) "deg"))) (with_template [ ] [(def .public Angle (..degree ))] [000 to_top] [090 to_right] [180 to_bottom] [270 to_left] ) (with_template [ ] [(def .public ( angle start next) (-> Angle Stop (List/1 [(Maybe Hint) Stop]) (Value Image)) (let [[now after] next] (..apply (list.partial (representation Angle angle) (with_hint now) (list#each with_hint after)))))] [linear_gradient "linear-gradient"] [repeating_linear_gradient "repeating-linear-gradient"] ) ) (def percentage_limit Nat (.++ 100)) (def .public (%% value) (-> Nat (Value Percentage)) (abstraction (format (%.nat (n.% percentage_limit value)) "%"))) (def .public slice_percent/1 (-> (Value Percentage) (Value Slice)) (|>> transmutation)) (def .public (slice_percent/2 horizontal vertical) (-> (Value Percentage) (Value Percentage) (Value Slice)) (abstraction (format (representation horizontal) ..slice_separator (representation vertical)))) (with_template [
 +]
    [(`` (with_template [ ]
           [(def .public 
              (-> 
                  (Value Filter))
              (|>> 
 (list) (..apply )))]

           (,, (template.spliced +))))]

    [Nat (<| representation ..px n.frac)
     [[blur "blur"]]]
    [Nat (<| ..angle ..degree)
     [[hue_rotate "hue-rotate"]]]
    [(Value Percentage) representation
     [[brightness "brightness"]
      [contrast "contrast"]
      [grayscale "grayscale"]
      [invert "invert"]
      [opacity "opacity"]
      [saturate "saturate"]
      [sepia "sepia"]]]
    )

  (def .public svg_filter
    (-> URL
        (Value Filter))
    (|>> (list) (..apply "url")))

  (def default_shadow_length
    (px +0.0))

  (def .public (drop_shadow horizontal vertical blur spread color)
    (-> (Value Length) (Value Length)
        (Maybe (Value Length)) (Maybe (Value Length))
        (Value Color)
        (Value Filter))
    (|> (list (representation horizontal)
              (representation vertical)
              (|> blur (maybe.else ..default_shadow_length) representation)
              (|> spread (maybe.else ..default_shadow_length) representation)
              (representation color))
        (text.interposed " ")
        (list)
        (..apply "drop-shadow")))

  (def length_separator
    " ")

  (with_template [ ]
    [(def .public ( horizontal vertical)
       (-> (Value Length) (Value Length)
           (Value ))
       (abstraction (format (representation horizontal)
                            ..length_separator
                            (representation vertical))))]

    [location Location]
    [fit Fit]
    )

  (def .public (fit/1 length)
    (-> (Value Length)
        (Value Fit))
    (..fit length length))

  (def .public image
    (-> URL
        (Value Image))
    (|>> %.text
         (list)
         (..apply "url")))

  (enumeration
   Shape
   Text
   shape
   [[ellipse_shape "ellipse"]
    [circle_shape "circle"]]
   [])

  (enumeration
   Extent
   Text
   extent
   [[closest_side "closest-side"]
    [closest_corner "closest-corner"]
    [farthest_side "farthest-side"]
    [farthest_corner "farthest-corner"]]
   [])

  (with_template [ ]
    [(def .public ( shape extent location start next)
       (-> Shape (Maybe Extent) (Value Location)
           Stop (List/1 [(Maybe Hint) Stop])
           (Value Image))
       (let [after_extent (format "at " (representation location))
             with_extent (when extent
                           {.#Some extent}
                           (format (..extent extent) " " after_extent)
                           
                           {.#None}
                           after_extent)
             where (format (..shape shape) " " with_extent)
             [now after] next]
         (..apply  (list.partial (..shape shape)
                                           (with_hint now)
                                           (list#each with_hint after)))))]
    
    [radial_gradient "radial-gradient"]
    [repeating_radial_gradient "repeating-radial-gradient"]
    )

  (def .public (shadow horizontal vertical blur spread color inset?)
    (-> (Value Length) (Value Length)
        (Maybe (Value Length)) (Maybe (Value Length))
        (Value Color) Bit
        (Value Shadow))
    (let [with_inset (if inset?
                       (list "inset")
                       (list))]
      (|> (list.partial (representation horizontal)
                        (representation vertical)
                        (|> blur (maybe.else ..default_shadow_length) representation)
                        (|> spread (maybe.else ..default_shadow_length) representation)
                        (representation color)
                        with_inset)
          (text.interposed " ")
          abstraction)))

  (type .public Rectangle
    (Record
     [#top (Value Length)
      #right (Value Length)
      #bottom (Value Length)
      #left (Value Length)]))

  (def .public (clip rectangle)
    (-> Rectangle
        (Value Clip))
    (`` (..apply "rect" (list (,, (with_template []
                                    [(representation (the  rectangle))]

                                    [#top] [#right] [#bottom] [#left]))))))

  (def .public counter
    (-> Label
        (Value Counter))
    (|>> abstraction))

  (def .public current_count
    (-> (Value Counter)
        (Value Content))
    (|>> representation (list) (..apply "counter")))

  (def .public text
    (-> Text
        (Value Content))
    (|>> %.text abstraction))

  (def .public attribute
    (-> Label
        (Value Content))
    (|>> (list) (..apply "attr")))

  (def .public media
    (-> URL
        (Value Content))
    (|>> (list) (..apply "url")))

  (enumeration
   Font
   Text
   font_name
   [[serif "serif"]
    [sans_serif "sans-serif"]
    [cursive "cursive"]
    [fantasy "fantasy"]
    [monospace "monospace"]]
   [(def .public font
      (-> Text Font)
      (|>> %.text abstraction))

    (def .public (font_family options)
      (-> (List Font) (Value Font))
      (when options
        {.#Item _}
        (|> options
            (list#each ..font_name)
            (text.interposed ",")
            (abstraction Value))
        
        {.#End}
        ..initial))])

  (def .public font_size
    (-> (Value Length)
        (Value Font_Size))
    (|>> transmutation))

  (def .public number
    (-> Frac
        (Value Number))
    (|>> %number abstraction))

  (def .public grid
    (-> Label
        (Value Grid))
    (|>> abstraction))

  (def .public fit_content
    (-> (Value Length)
        (Value Grid_Content))
    (|>> representation (list) (..apply "fit-content")))

  (def .public (min_max min max)
    (-> (Value Grid_Content) (Value Grid_Content)
        (Value Grid_Content))
    (..apply "minmax" (list (representation min)
                            (representation max))))

  (def .public grid_span
    (-> Nat
        (Value Grid_Span))
    (|>> %.nat (format "span ") abstraction))

  (def grid_column_separator " ")
  (def grid_row_separator " ")

  (def .public grid_template
    (-> (List (List (Maybe (Value Grid))))
        (Value Grid_Template))
    (let [empty (is (Value Grid)
                    (abstraction "."))]
      (|>> (list#each (|>> (list#each (|>> (maybe.else empty)
                                           representation))
                           (text.interposed ..grid_column_separator)
                           (text.enclosed ["'" "'"])))
           (text.interposed ..grid_row_separator)
           abstraction)))

  (def .public (resolution dpi)
    (-> Nat
        (Value Resolution))
    (abstraction (format (%.nat dpi) "dpi")))

  (def .public (ratio numerator denominator)
    (-> Nat Nat
        (Value Ratio))
    (abstraction (format (%.nat numerator) "/" (%.nat denominator))))

  (enumeration
   Quote
   Text
   quote_text
   [[double_quote "\0022"]
    [single_quote "\0027"]
    [single_left_angle_quote "\2039"]
    [single_right_angle_quote "\203A"]
    [double_left_angle_quote "\00AB"]
    [double_right_angle_quote "\00BB"]
    [single_left_quote "\2018"]
    [single_right_quote "\2019"]
    [double_left_quote "\201C"]
    [double_right_quote "\201D"]
    [low_double_quote "\201E"]]
   [(def .public quote
      (-> Text Quote)
      (|>> abstraction))])

  (def quote_separator " ")

  (def .public (quotes [left0 right0] [left1 right1])
    (-> [Quote Quote] [Quote Quote]
        (Value Quotes))
    (|> (list left0 right0 left1 right1)
        (list#each (|>> ..quote_text %.text))
        (text.interposed ..quote_separator)
        abstraction))

  (def .public (matrix_2d [a b] [c d] [tx ty])
    (-> [Frac Frac]
        [Frac Frac]
        [Frac Frac]
        (Value Transform))
    (|> (list a b c d tx ty)
        (list#each %number)
        (..apply "matrix")))

  (def .public (matrix_3d [a0 b0 c0 d0] [a1 b1 c1 d1] [a2 b2 c2 d2] [a3 b3 c3 d3])
    (-> [Frac Frac Frac Frac]
        [Frac Frac Frac Frac]
        [Frac Frac Frac Frac]
        [Frac Frac Frac Frac]
        (Value Transform))
    (|> (list a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3)
        (list#each %number)
        (..apply "matrix3d")))

  (with_template [   ]
    [(`` (def .public ( [(,, (template.spliced ))])
           (-> [(,, (template.spliced ))]
               (Value Transform))
           (|> (list (,, (template.spliced )))
               (list#each %number)
               (..apply ))))]

    [translate_2d "translate" [Frac Frac] [x y]]
    [translate_3d "translate3d" [Frac Frac Frac] [x y z]]
    [translate_x "translateX" [Frac] [value]]
    [translate_y "translateY" [Frac] [value]]
    [translate_z "translateZ" [Frac] [value]]

    [scale_2d "scale" [Frac Frac] [x y]]
    [scale_3d "scale3d" [Frac Frac Frac] [x y z]]
    [scale_x "scaleX" [Frac] [value]]
    [scale_y "scaleY" [Frac] [value]]
    [scale_z "scaleZ" [Frac] [value]]

    [perspective "perspective" [Frac] [value]]
    )

  (with_template [   ]
    [(`` (def .public ( [(,, (template.spliced ))])
           (-> [(,, (template.spliced ))]
               (Value Transform))
           (|> (list (,, (template.spliced )))
               (list#each ..angle)
               (..apply ))))]

    [rotate_2d "rotate" [Angle] [angle]]
    [rotate_x "rotateX" [Angle] [angle]]
    [rotate_y "rotateY" [Angle] [angle]]
    [rotate_z "rotateZ" [Angle] [angle]]

    [skew "skew" [Angle Angle] [x_angle y_angle]]
    [skew_x "skewX" [Angle] [angle]]
    [skew_y "skewY" [Angle] [angle]]
    )

  (def .public (rotate_3d [x y z angle])
    (-> [Frac Frac Frac Angle]
        (Value Transform))
    (..apply "rotate3d"
             (list (%number x) (%number y) (%number z) (..angle angle))))

  (def origin_separator " ")

  (def .public (origin_2d x y)
    (-> (Value Length) (Value Length)
        (Value Transform_Origin))
    (abstraction (format (representation x) ..origin_separator
                         (representation y))))

  (def .public (origin_3d x y z)
    (-> (Value Length) (Value Length) (Value Length)
        (Value Transform_Origin))
    (abstraction (format (representation x) ..origin_separator
                         (representation y) ..origin_separator
                         (representation z))))

  (def .public vertical_align
    (-> (Value Length)
        (Value Vertical_Align))
    (|>> transmutation))

  (def .public (z_index index)
    (-> Int
        (Value Z_Index))
    (abstraction (if (i.< +0 index)
                   (%.int index)
                   (%.nat (.nat index)))))

  (with_template [  ]
    [(def .public ( pre post)
       (-> (Value ) (Value )
           (Value ))
       (abstraction (format (representation pre)
                            
                            (representation post))))]

    ["," Image multi_image]
    ["," Shadow multi_shadow]
    [" " Content multi_content]
    )

  ... https://developer.mozilla.org/en-US/docs/Web/CSS/calc()
  (with_template [ ]
    [(def .public ( parameter subject)
       (.All (_ kind)
         (-> (Value ) (Value (Numeric kind))
             (Value (Numeric kind))))
       (|> (format (representation subject)
                   (template.text [" "  " "])
                   (representation parameter))
           (text.enclosed ["calc(" ")"])
           abstraction))]

    [+ (Numeric kind)]
    [- (Numeric kind)]
    [* Number]
    [/ Number]
    )
  )