[{"name":"Evg","comment":" Draw pictures with shapes, text, and effects, using a friendly, type-safe API.\n\nYou describe a picture as a list of shapes, and the library renders it in the\nbrowser as crisp vector graphics that stay sharp at any size. Positions are\nplain numbers: `(0, 0)` is the top-left corner, x grows to the right, and\ny grows downward.\n\n    import Evg exposing (Evg)\n\n    scene : Html msg\n    scene =\n        Evg.svg []\n            { width = 200, height = 200 }\n            [ Evg.circle\n                [ Evg.fillStr \"tomato\" ]\n                { r = 60, center = ( 100, 100 ) }\n            , Evg.line\n                [ Evg.strokeStr \"navy\" ]\n                ( 20, 20 )\n                ( 180, 180 )\n            ]\n\nThis draws a tomato-colored circle in the middle of a 200 by 200 canvas, with\na navy diagonal line crossing it.\n\nEach shape takes a list of attributes (colors, outlines, effects) followed by\nthe measurements that define it. The type system checks that every attribute\nmakes sense for the shape it is applied to. For example, `cornerRadius` is\naccepted on a rectangle but rejected on a circle at compile time.\n\n\n# Core Types\n\n@docs Evg, Attribute, Supported, Paint, Filter\n\n\n# Coordinate Spaces\n\n@docs CoordinateSpace, objectBoundingBox, userSpace\n\n\n# Rendering\n\n@docs svg\n\n\n# Document Structure\n\n@docs group\n\n\n# Basic Shapes\n\n@docs line, rect, circle, ellipse, polygon, polyline\n\n\n# Drawing Text\n\n@docs text, TextAnchor\n\n\n# Images\n\n@docs image\n\n\n# Paths\n\n@docs path\n\n\n# Attributes\n\n\n## Colors and painting\n\n@docs filter, filterWithCoordinates\n@docs fill, stroke, fillStr, strokeStr, strokeWidth, opacity\n\nFor gradient and pattern constructors, see [`Evg.Paint`](Evg-Paint).\n\n\n## Stroke style\n\n@docs dashPattern, dashOffset\n@docs linecapRound, linecapSquare, linecapButt\n@docs linejoinRound, linejoinBevel, linejoinMiter\n@docs strokeOpacity, fillOpacity\n@docs fillRuleEvenOdd, fillRuleNonZero\n\n\n## Shape options\n\n@docs cornerRadius, fontSize, fontFamily\n\n\n## Accessibility\n\n@docs title, desc\n\n\n## CSS\n\n@docs class, style\n\n\n# Utilities\n\n@docs none, map\n\n\n# Attribute Utilities\n\n@docs batch, noAttr, when\n\n\n# Serialization\n\n@docs toString\n\n","unions":[{"name":"TextAnchor","comment":" Where text sits relative to the position you give it. See\n[`text`](#text) for what each option looks like.\n","args":[],"cases":[["Start",[]],["Middle",[]],["End",[]]]}],"aliases":[{"name":"Attribute","comment":" A setting applied to a shape, such as its color, outline, or an effect.\n\nThe `constraints` type parameter records which shapes an attribute makes sense\non, so mistakes are caught when compiling. For example, `cornerRadius` only\napplies to rectangles, and the compiler will tell you if you put it on a\ncircle.\n\n","args":["constraints","msg"],"type":"Evg.Internal.Attribute constraints msg"},{"name":"CoordinateSpace","comment":" Decides which coordinates an effect (a gradient, pattern, clip path, or\nmask) is measured in.\n\nMost of the time you don't need to think about this, because the default\nfunctions pick a sensible option. The `*WithCoordinates` variants let you\nchoose explicitly, and there are two choices:\n\nObject bounding box coordinates are measured against the shape being painted.\n`(0, 0)` means the shape's own top-left corner and `(1, 1)` its bottom-right,\nno matter where the shape is or how big it is. Use this for effects that\nshould stretch with the shape, like \"fade from left edge to right edge\".\n\nUser space coordinates are the same plain numbers you position shapes with.\nUse this for effects that should stay fixed in the picture no matter which\nshape they are applied to, like one large gradient shared by several bars of\na chart.\n\n","args":[],"type":"Evg.Internal.CoordinateSpace"},{"name":"Evg","comment":" A piece of a picture: a single shape, some text, or a group of other\npieces. Your whole drawing is a tree of these, and [`svg`](#svg) turns that\ntree into `Html`.\n","args":["msg"],"type":"Evg.Internal.Evg msg"},{"name":"Filter","comment":" An image effect that can be applied to a shape, like a blur or a drop\nshadow. Built with the [`Evg.Filter`](Evg-Filter) module and applied with\n[`filter`](#filter).\n","args":[],"type":"Evg.Internal.Filter"},{"name":"Paint","comment":" Describes what a shape is painted with: a solid color, a gradient, a\nrepeating pattern, or nothing at all. Built with the\n[`Evg.Paint`](Evg-Paint) module and used with [`fill`](#fill) and\n[`stroke`](#stroke).\n","args":[],"type":"Evg.Internal.Paint"},{"name":"Supported","comment":" A marker that appears in the `constraints` of an [`Attribute`](#Attribute).\nYou only need it when writing your own type annotations for attribute lists,\nfor example a helper producing attributes that work on any shape with a fill:\n\n    fancyFill :\n        List\n            (Evg.Attribute\n                { a | fill : Evg.Supported }\n                msg\n            )\n\n","args":[],"type":"Evg.Internal.Supported"}],"values":[{"name":"batch","comment":" Bundles several attributes into one, so you can name a reusable style\nand apply it as a single attribute.\n\n    buttonStyle =\n        Evg.batch\n            [ Evg.fillStr \"blue\"\n            , Evg.strokeStr \"navy\"\n            , Evg.strokeWidth 2\n            ]\n\n    view =\n        Evg.rect\n            [ buttonStyle ]\n            { x = 0, y = 0, width = 80, height = 30 }\n\n","type":"List.List (Evg.Attribute a msg) -> Evg.Attribute a msg"},{"name":"circle","comment":" Draws a circle. You give the center point and the radius `r` (the\ndistance from the center to the edge).\n\n![circle example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/circle-example.svg)\n\n    Evg.circle\n        [ Evg.fillStr \"crimson\" ]\n        { r = 40, center = ( 50, 50 ) }\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> { r : Basics.Float, center : ( Basics.Float, Basics.Float ) } -> Evg.Evg msg"},{"name":"class","comment":" Assigns a CSS class name for external styling.\n\n    Evg.rect [ Evg.class \"highlight\" ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\n","type":"String.String -> Evg.Attribute a msg"},{"name":"cornerRadius","comment":" Rounds the corners of a rectangle. The radius is the size of the\nquarter-circle used at each corner, so bigger numbers give softer corners.\nA radius of half the rectangle's height turns the short ends into\nsemicircles, giving a pill shape.\n\n    Evg.rect [ Evg.fillStr \"blue\", Evg.cornerRadius 10 ]\n        { x = 0, y = 0, width = 100, height = 60 }\n\n","type":"Basics.Float -> Evg.Attribute { a | cornerRadius : Evg.Supported } msg"},{"name":"dashOffset","comment":" Slides the dash pattern along the line by the given distance. Animating\nthis value makes the dashes appear to march along the path, the classic\n\"marching ants\" selection effect.\n\n    Evg.dashOffset 5\n\n","type":"Basics.Float -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"dashPattern","comment":" Draws the stroke as dashes instead of a continuous line. The numbers\nalternate between the length of a dash and the length of the gap after it,\nrepeating along the whole line.\n\n    -- 10-unit dashes with 5-unit gaps:\n    Evg.line\n        [ Evg.strokeStr \"black\"\n        , Evg.dashPattern [ 10, 5 ]\n        ]\n        ( 0, 50 )\n        ( 200, 50 )\n\n    -- Dot, gap, dash, gap, repeated:\n    Evg.dashPattern [ 2, 5, 10, 5 ]\n\n","type":"List.List Basics.Float -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"desc","comment":" Adds a longer text description to a shape for assistive technology.\nUnlike `title` it never appears as a tooltip; it exists purely for screen\nreaders, so this is the place to describe what a complex graphic shows.\n\n    Evg.group\n        [ Evg.desc \"Bar chart of monthly revenue\" ]\n        [ ... ]\n\n","type":"String.String -> Evg.Attribute a msg"},{"name":"ellipse","comment":" Draws an ellipse (an oval): like a circle, but with separate radii for\neach direction. `rx` is the distance from the center to the left and right\nedges, `ry` to the top and bottom. A wide `rx` with a small `ry` gives a\nflattened, lying-down oval.\n\n![ellipse example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/ellipse-example.svg)\n\n    Evg.ellipse\n        [ Evg.fillStr \"mediumpurple\" ]\n        { rx = 70, ry = 35, center = ( 80, 50 ) }\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> { rx : Basics.Float, ry : Basics.Float, center : ( Basics.Float, Basics.Float ) } -> Evg.Evg msg"},{"name":"fill","comment":" Paints the inside of a shape. The `Paint` value can be a solid color, a\ngradient, or a repeating pattern; see [`Evg.Paint`](Evg-Paint) for how to\nbuild them.\n\n    import Evg.Paint as Paint\n\n    Evg.rect\n        [ Evg.fill\n            (Paint.solid (Color.rgb255 0 128 255))\n        ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\nIf you just want a color and are happy writing it as a string, `fillStr` is\nshorter.\n\n","type":"Evg.Paint -> Evg.Attribute { a | fill : Evg.Supported } msg"},{"name":"fillOpacity","comment":" Makes just the interior fill translucent, leaving the outline untouched.\n`0.0` is invisible and `1.0` fully solid.\n","type":"Basics.Float -> Evg.Attribute { a | fill : Evg.Supported } msg"},{"name":"fillRuleEvenOdd","comment":" Changes which regions count as \"inside\" a self-overlapping shape.\n\nWhen a path crosses over itself, or one subpath sits within another, the\nbrowser has to decide which enclosed regions get filled. With this rule, a\nregion is filled only if a line drawn from it to the outside crosses the\nshape's edge an odd number of times. In practice: overlapping areas become\nunfilled holes.\n\n","type":"Evg.Attribute { a | fill : Evg.Supported } msg"},{"name":"fillRuleNonZero","comment":" The default rule for deciding which regions of a self-overlapping shape\nget filled: a region is filled unless the strokes enclosing it wind in\nopposite directions and cancel out. In practice: overlaps stay filled, and\nyou cut holes by drawing the inner subpath in the opposite direction from\nthe outer one.\n","type":"Evg.Attribute { a | fill : Evg.Supported } msg"},{"name":"fillStr","comment":" Colors the inside of a shape, using any color notation CSS understands:\nnamed colors, hex codes, `rgb(...)`, and so on. Pass `\"none\"` to leave the\ninside unpainted so anything behind the shape shows through.\n\n    Evg.fillStr \"red\"\n\n    Evg.fillStr \"#FF0000\"\n\n    Evg.fillStr \"none\"\n\n","type":"String.String -> Evg.Attribute { a | fill : Evg.Supported } msg"},{"name":"filter","comment":" Applies an image effect to a shape after it is drawn, like blurring it or\ngiving it a drop shadow. Effects are built with the\n[`Evg.Filter`](Evg-Filter) module.\n\n    import Evg.Filter as Filter\n\n    blur =\n        Filter.sourceGraphic |> Filter.gaussianBlur 3\n\n    -- A circle with softly blurred edges:\n    Evg.circle\n        [ Evg.filter blur ]\n        { r = 50, center = ( 100, 100 ) }\n\n","type":"Evg.Filter -> Evg.Attribute { a | filter : Evg.Supported } msg"},{"name":"filterWithCoordinates","comment":" Like `filter`, but with explicit control over the region the effect is\nallowed to paint into.\n\nEffects often need room beyond the shape's edges: a blur bleeds outward, a\ndrop shadow sits below and to the side. By default the region extends\nslightly past the shape, which suits most cases. If an effect appears cut\noff at a straight edge, widen the region with this function.\n\n    Evg.text\n        [ Evg.filterWithCoordinates\n            (Evg.objectBoundingBox\n                { x = -0.25\n                , y = -0.25\n                , width = 1.5\n                , height = 1.6\n                }\n            )\n            myFilter\n        ]\n        { x = 100, y = 50, anchor = Evg.Middle }\n        \"Hello\"\n\n","type":"Evg.CoordinateSpace -> Evg.Filter -> Evg.Attribute { a | filter : Evg.Supported } msg"},{"name":"fontFamily","comment":" Sets the typeface for text. You can list multiple fonts separated by commas\nas fallbacks, just like in CSS.\n\n    Evg.fontFamily \"'Helvetica Neue', Arial, sans-serif\"\n\n","type":"String.String -> Evg.Attribute { a | font : Evg.Supported } msg"},{"name":"fontSize","comment":" Sets the text size. The number is the height of the font in your\ncoordinate units, so text scales along with the rest of the drawing.\n\n    Evg.fontSize 24\n\n","type":"Basics.Float -> Evg.Attribute { a | font : Evg.Supported } msg"},{"name":"group","comment":" Collects several shapes into one, so you can treat them as a unit. An\nattribute placed on the group applies to everything inside: fade them all out\nwith one `opacity`, move them together with one transform, or listen for\nclicks on any of them with one event handler.\n\n    -- Two overlapping squares, both at half opacity:\n    Evg.group [ Evg.opacity 0.5 ]\n        [ Evg.rect\n            [ Evg.fillStr \"blue\" ]\n            { x = 0\n            , y = 0\n            , width = 100\n            , height = 100\n            }\n        , Evg.rect\n            [ Evg.fillStr \"red\" ]\n            { x = 50\n            , y = 50\n            , width = 100\n            , height = 100\n            }\n        ]\n\nGroups are also handy for structuring a drawing the way you'd structure code,\nwith one function returning the group for each part of the picture.\n\n","type":"List.List (Evg.Attribute { opacity : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> List.List (Evg.Evg msg) -> Evg.Evg msg"},{"name":"image","comment":" Places an image file (PNG, JPG, SVG, and so on) into the drawing. The\n`href` is the image's URL, and the rectangle says where it goes and how big\nto draw it. If the rectangle's proportions don't match the image's, the\nimage is scaled to fit inside without distortion.\n\n    Evg.image []\n        { href = \"photo.png\"\n        , x = 0\n        , y = 0\n        , width = 200\n        , height = 150\n        }\n\n","type":"List.List (Evg.Attribute { opacity : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> { href : String.String, x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.Evg msg"},{"name":"line","comment":" Draws a straight line from one point to another.\n\nA line has no inside to fill, only a stroke (the visible ink drawn along it).\nIf you don't pick a stroke color, you get a thin black line.\n\n![line example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/line.svg)\n\n    Evg.line [] ( 10, 20 ) ( 110, 20 )\n\n    -- A thicker red diagonal:\n    Evg.line\n        [ Evg.strokeStr \"red\", Evg.strokeWidth 3 ]\n        ( 0, 0 )\n        ( 100, 100 )\n\n","type":"List.List (Evg.Attribute { stroke : Evg.Supported, opacity : Evg.Supported, marker : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> ( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> Evg.Evg msg"},{"name":"linecapButt","comment":" Cuts lines off flat exactly at the endpoint. This is the default.\n","type":"Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"linecapRound","comment":" Gives lines rounded ends: a semicircle caps each endpoint, extending\nhalf the stroke width past it. This is what makes thick lines look friendly\nrather than abruptly chopped.\n","type":"Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"linecapSquare","comment":" Gives lines square ends that extend half the stroke width past the\nendpoint. Similar to the default flat end, but the line reaches slightly\nfurther.\n","type":"Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"linejoinBevel","comment":" Flattens the corners where two line segments meet, as if the sharp point\nhad been snipped off.\n","type":"Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"linejoinMiter","comment":" Keeps corners as sharp points. This is the default look.\n\nVery acute angles would produce absurdly long spikes, so the `limit` caps\nhow far the point may extend (as a multiple of the stroke width) before the\ncorner falls back to a flattened bevel. A typical value is 4.\n\n    Evg.linejoinMiter { limit = 4 }\n\n","type":"{ limit : Basics.Float } -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"linejoinRound","comment":" Rounds off the corners where two line segments meet, as if drawn with a\nround pen.\n","type":"Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"map","comment":" Changes the message type of a drawing, just like `Html.map`. Use it to\nembed a drawing whose event handlers produce one message type into a view\nthat uses another.\n","type":"(a -> b) -> Evg.Evg a -> Evg.Evg b"},{"name":"noAttr","comment":" An attribute that does nothing. Useful as a placeholder or default.\n\n    Evg.rect\n        [ if highlighted then\n            Evg.fillStr \"yellow\"\n\n          else\n            Evg.noAttr\n        ]\n        { x = 0, y = 0, width = 50, height = 50 }\n\n","type":"Evg.Attribute a msg"},{"name":"none","comment":" An element that draws nothing. Handy when a branch of your code has\nnothing to show:\n\n    if model.showMarker then\n        Evg.circle [] { r = 4, center = model.position }\n\n    else\n        Evg.none\n\n","type":"Evg.Evg msg"},{"name":"objectBoundingBox","comment":" Coordinates measured against the shape being painted, where `(0, 0)` is\nits top-left corner and `(1, 1)` its bottom-right. The rect says which part\nof the shape the effect covers. Usually you want all of it:\n\n    -- A gradient spanning the whole shape:\n    Evg.objectBoundingBox\n        { x = 0, y = 0, width = 1, height = 1 }\n\n","type":"{ x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.CoordinateSpace"},{"name":"opacity","comment":" Makes a shape translucent. At `1.0` the shape is fully solid, at `0.5`\nwhatever is behind it shows through evenly, and at `0.0` it is invisible\n(though still present, so it can still receive clicks).\n\n    Evg.opacity 0.5\n\n","type":"Basics.Float -> Evg.Attribute { a | opacity : Evg.Supported } msg"},{"name":"path","comment":" Draws a free-form shape from a list of pen movements: place the pen\nsomewhere, then draw straight lines, curves, and arcs from point to point.\nThis is the most flexible shape and the one to reach for when rectangles,\ncircles, and polygons aren't enough. The movements themselves are described\nwith the [`Evg.Path`](Evg-Path) module.\n\nYou pass a list of subpaths. Most shapes need just one; several subpaths\nmake a compound shape, where an inner subpath can cut a hole in an outer one.\n\n    import Evg.Path exposing (Path(..), PathSegment(..))\n\n    -- A smooth arch drawn with a single curve:\n    Evg.path\n        [ Evg.fillStr \"none\", Evg.strokeStr \"black\" ]\n        [ M ( 10, 80 )\n            [ C ( 40, 10 ) ( 65, 10 ) ( 95, 80 ) ]\n        ]\n\n    -- A donut: an outer circle with a smaller\n    -- circular hole cut out:\n    Evg.path [ Evg.fillStr \"gold\" ]\n        [ M ( 50, 10 )\n            [ A 40 40 0 True True ( 50, 90 )\n            , A 40 40 0 True True ( 50, 10 )\n            ]\n        , M ( 50, 25 )\n            [ A 25 25 0 True False ( 50, 75 )\n            , A 25 25 0 True False ( 50, 25 )\n            ]\n        ]\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, marker : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> List.List Evg.Path.Path -> Evg.Evg msg"},{"name":"polygon","comment":" Draws a closed shape by connecting a list of corner points with straight\nlines. The last point connects back to the first automatically, so three\npoints make a triangle, four make a quadrilateral, and so on.\n\n![polygon example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/polygon-example.svg)\n\n    -- A triangle:\n    Evg.polygon [ Evg.fillStr \"limegreen\" ]\n        [ ( 60, 10 ), ( 110, 100 ), ( 10, 100 ) ]\n\nFor shapes with curved edges, see [`path`](#path).\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, marker : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> List.List ( Basics.Float, Basics.Float ) -> Evg.Evg msg"},{"name":"polyline","comment":" Draws a connected series of straight line segments through a list of\npoints, like a line chart. Unlike [`polygon`](#polygon) the shape stays open:\nthe last point does not connect back to the first. It comes out as a thin\nblack line with nothing filled in.\n\n![polyline example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/polyline-example.svg)\n\n    Evg.polyline []\n        [ ( 10, 50 )\n        , ( 30, 10 )\n        , ( 50, 40 )\n        , ( 70, 20 )\n        , ( 90, 45 )\n        , ( 110, 15 )\n        ]\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, marker : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> List.List ( Basics.Float, Basics.Float ) -> Evg.Evg msg"},{"name":"rect","comment":" Draws a rectangle. The `x` and `y` give its top-left corner, and `width`\nand `height` extend it rightward and downward from there. Without a fill\ncolor it comes out solid black.\n\n![rect example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/rect-example.svg)\n\n    Evg.rect\n        [ Evg.fillStr \"navy\" ]\n        { x = 10, y = 10, width = 100, height = 100 }\n\n    -- With rounded corners:\n    Evg.rect [ Evg.fillStr \"navy\", Evg.cornerRadius 10 ]\n        { x = 10, y = 10, width = 100, height = 100 }\n\n","type":"List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, cornerRadius : Evg.Supported, opacity : Evg.Supported, marker : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.Evg msg"},{"name":"stroke","comment":" Paints the stroke of a shape, the visible line drawn along its edge.\nLike `fill`, it takes a `Paint` value, so outlines can be gradients or\npatterns as well as solid colors.\n\n    import Evg.Paint as Paint\n\n    Evg.circle\n        [ Evg.stroke\n            (Paint.solid (Color.rgb255 0 0 0))\n        ]\n        { r = 40, center = ( 50, 50 ) }\n\n","type":"Evg.Paint -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"strokeOpacity","comment":" Makes just the outline translucent, leaving the fill untouched. `0.0` is\ninvisible and `1.0` fully solid.\n","type":"Basics.Float -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"strokeStr","comment":" Colors the stroke of a shape (the line along its edge), using any color\nnotation CSS understands. Pass `\"none\"` to remove the outline.\n\nFor gradient or patterned outlines use [`stroke`](#stroke). For dashes and\nline endings see [`dashPattern`](#dashPattern) and the line cap and join\nfunctions below.\n\n    Evg.strokeStr \"black\"\n\n    Evg.strokeStr \"#FF0000\"\n\n","type":"String.String -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"strokeWidth","comment":" Sets how thick the stroke is drawn, in the same units as your\ncoordinates. The line straddles the shape's edge, half inside and half\noutside.\n\n    Evg.strokeWidth 2\n\n","type":"Basics.Float -> Evg.Attribute { a | stroke : Evg.Supported } msg"},{"name":"style","comment":" Applies inline CSS directly to an element, as one string of\ndeclarations.\n\n    Evg.style \"filter: drop-shadow(2px 2px 2px grey)\"\n\n","type":"String.String -> Evg.Attribute a msg"},{"name":"svg","comment":" Creates the drawing canvas. All shapes go inside here, and the result is\nordinary `Html` you can place anywhere in your view.\n\nThe `width` and `height` set both the size on screen (in pixels) and the\ncoordinate system: child coordinates run from `(0, 0)` at the top-left to\n`(width, height)` at the bottom-right. If CSS later stretches or shrinks the\nelement, your coordinates keep working; the drawing scales as one piece.\n\n    Evg.svg []\n        { width = 300, height = 200 }\n        [ Evg.circle\n            [ Evg.fillStr \"red\" ]\n            { r = 50, center = ( 150, 100 ) }\n        ]\n\n","type":"List.List (Evg.Attribute { viewBox : Evg.Supported, events : Evg.Supported } msg) -> { width : Basics.Float, height : Basics.Float } -> List.List (Evg.Evg msg) -> Html.Html msg"},{"name":"text","comment":" Draws a line of text at a position.\n\nThe `y` coordinate is the text's baseline, the invisible line the letters sit\non, so the characters appear above the point you give (with descenders like\nthe tail of a \"g\" hanging below it). The `anchor` says where the text sits\nhorizontally relative to `x`:\n\n  - `Start`: the text begins at `x` and runs to the right\n  - `Middle`: the text is centered on `x`\n  - `End`: the text ends at `x`, running to the left of it\n\n`Middle` is what you want for labelling a point, like the value above a bar\nin a chart.\n\n    Evg.text [ Evg.fillStr \"black\", Evg.fontSize 24 ]\n        { x = 50, y = 50, anchor = Evg.Start }\n        \"Hello\"\n\nFor multiple styles within one line, or text that flows along a curve, see\nthe [`Evg.Text`](Evg-Text) module.\n\n","type":"List.List (Evg.Attribute { a | text : Evg.Supported } msg) -> { x : Basics.Float, y : Basics.Float, anchor : Evg.TextAnchor } -> String.String -> Evg.Evg msg"},{"name":"title","comment":" Adds a short text label to a shape for screen readers and tooltips.\nBrowsers will typically show this as a tooltip on hover.\n\n    Evg.circle [ Evg.title \"Connection status: online\" ]\n        { r = 5, center = ( 10, 10 ) }\n\n","type":"String.String -> Evg.Attribute a msg"},{"name":"toString","comment":" Render the drawing to a string of SVG markup instead of `Html`. Takes\nthe same arguments as [`svg`](#svg), so a scene can be shown live or written\nto an `.svg` file with the same code.\n\n    Evg.toString []\n        { width = 100, height = 100 }\n        [ Evg.circle []\n            { r = 40, center = ( 50, 50 ) }\n        ]\n\nThe result is a complete SVG document: an `<svg>` root carrying the namespace\nand viewBox, containing a `<circle>` element with the radius and center you\ngave.\n\nUseful for generating image files in scripts, snapshot-testing drawings, or\nrendering on a server. A few things behave differently from live rendering:\n\n  - Event handlers are dropped. Markup is a picture, not a program.\n  - `Evg.Performance.lazy` shapes are computed (there is nothing to cache).\n  - Raw nodes smuggled in from outside the library cannot be read back out\n    of the virtual DOM, so they are omitted.\n\n","type":"List.List (Evg.Attribute { viewBox : Evg.Supported, events : Evg.Supported } msg) -> { width : Basics.Float, height : Basics.Float } -> List.List (Evg.Evg msg) -> String.String"},{"name":"userSpace","comment":" Coordinates in the same units you position shapes with. The rect says\nwhich region of the picture the effect covers.\n\n    -- A gradient pinned to a specific area:\n    Evg.userSpace\n        { x = 0, y = 0, width = 200, height = 100 }\n\n","type":"{ x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.CoordinateSpace"},{"name":"when","comment":" Conditionally include an attribute. When the condition is `False`,\nproduces `noAttr`.\n\n    Evg.rect [ Evg.when isActive (Evg.fillStr \"green\") ]\n        { x = 0, y = 0, width = 50, height = 50 }\n\n","type":"Basics.Bool -> Evg.Attribute a msg -> Evg.Attribute a msg"}],"binops":[]},{"name":"Evg.Advanced","comment":" Escape hatches and advanced features for when the high-level API isn't\nenough.\n\nMost of the time you won't need this module. It's here for the 5% of cases\nwhere you need full control over SVG output.\n\n\n# Viewport Control\n\nA viewport is the rectangular area on screen that a drawing gets rendered\ninto. Normally `Evg.svg` sets it up for you so that one coordinate unit equals\none pixel. The functions here let you change that relationship: show a\ndifferent rectangle of your coordinate system, or control what happens when\nthe drawing and its on-screen area have different shapes.\n\n@docs viewBox, preserveAspectRatio, AlignValue, MeetOrSlice\n\n\n# Escape Hatches\n\n@docs customElement, customAttribute, customFilter\n\n\n# Embedding elm/svg\n\nIf you already have graphics built with [`elm/svg`](https://package.elm-lang.org/packages/elm/svg/latest/),\nfor example an icon exported from a drawing program, you can drop it straight\ninto an Evg drawing rather than porting it.\n\n@docs fromSvg, notSupported\n\n\n# Nested Viewports\n\n@docs nestedSvg\n\n\n# Links\n\n@docs link\n\n\n# Accessibility (ARIA)\n\n@docs role, ariaLabel, ariaHidden\n\n\n# Showing and Hiding Elements\n\n@docs visibility, Visibility\n\n","unions":[{"name":"AlignValue","comment":" Where to place the drawing inside the viewport when\n[`preserveAspectRatio`](#preserveAspectRatio) leaves spare room or has to crop.\n\nThe names read as two halves: the `X` part picks horizontal placement (`Min`\nis left, `Mid` is centre, `Max` is right) and the `Y` part picks vertical\nplacement (`Min` is top, `Mid` is centre, `Max` is bottom). So `XMidYMid`\ncentres the drawing both ways, which is the default and usually what you want.\n\n`AlignNone` is different: instead of positioning the drawing, it stretches it\nto fill the viewport exactly, distorting the shapes if the proportions don't\nmatch.\n\n","args":[],"cases":[["AlignNone",[]],["XMinYMin",[]],["XMidYMin",[]],["XMaxYMin",[]],["XMinYMid",[]],["XMidYMid",[]],["XMaxYMid",[]],["XMinYMax",[]],["XMidYMax",[]],["XMaxYMax",[]]]},{"name":"MeetOrSlice","comment":" What to do when the drawing's proportions don't match the viewport's.\n\n  - `Meet`: scale the drawing until it just fits inside. You see all of it,\n    but there may be empty bands left over on two sides, like the black bars\n    when a widescreen film plays on a square screen.\n  - `Slice`: scale the drawing until it covers the whole viewport. There are\n    no empty bands, but whatever pokes out past the edges gets cropped away.\n\n![meet vs slice](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/preserve-aspect-ratio.svg)\n\n","args":[],"cases":[["Meet",[]],["Slice",[]]]},{"name":"Visibility","comment":" Whether a shape is visible or hidden.\n","args":[],"cases":[["VisibilityVisible",[]],["VisibilityHidden",[]],["VisibilityCollapse",[]]]}],"aliases":[],"values":[{"name":"ariaHidden","comment":" Hides an element from assistive technology. Use for purely decorative\nshapes that add no informational value.\n\n    Evg.group [ Advanced.ariaHidden True ]\n        [ decorativeShapes ]\n\n","type":"Basics.Bool -> Evg.Attribute { a | ariaHidden : Evg.Supported } msg"},{"name":"ariaLabel","comment":" Provides a text label for assistive technology (screen readers).\n\n    Evg.group\n        [ Advanced.ariaLabel \"Sales chart for Q4 2024\" ]\n        [ ... ]\n\n","type":"String.String -> Evg.Attribute { a | ariaLabel : Evg.Supported } msg"},{"name":"customAttribute","comment":" Creates a raw SVG attribute. Use this when you need an attribute that this\nlibrary doesn't provide a dedicated function for.\n\n    Advanced.customAttribute \"data-tooltip\" \"hello\"\n\n","type":"String.String -> String.String -> Evg.Attribute a msg"},{"name":"customElement","comment":" Creates a raw SVG element by tag name. Use this when you need an element\nthat this library doesn't provide a dedicated function for.\n\n    Advanced.customElement \"foreignObject\"\n        [ Advanced.customAttribute \"x\" \"10\"\n        , Advanced.customAttribute \"width\" \"200\"\n        ]\n        []\n\nAny attribute is accepted here, including the ordinary ones from `Evg` and\nits other modules, since the library cannot know what a tag you supply\nyourself understands. That also means nothing is checked for you: it is up to\nyou to only pass attributes the element actually supports.\n\n    Advanced.customElement \"foreignObject\"\n        [ Advanced.customAttribute \"width\" \"200\"\n        , Evg.opacity 0.5\n        ]\n        []\n\n","type":"String.String -> List.List (Evg.Attribute a msg) -> List.List (Evg.Internal.Evg msg) -> Evg.Internal.Evg msg"},{"name":"customFilter","comment":" Make your own filter primitive, for filter effects that `Evg.Filter`\ndoesn't cover.\n\nYou provide a function that receives the identifiers of the input filters (in\nthe same order as the list you pass) and returns a description of the raw\nfilter element to produce:\n\n  - `name`: the SVG tag name, such as `\"feTurbulence\"`\n  - `id` : a unique identifier for this filter step\n  - `args`: attribute name and value pairs for the element\n  - `children`: child elements, each a tag name with its own attribute pairs\n\n","type":"(List.List String.String -> { name : String.String, id : String.String, args : List.List ( String.String, String.String ), children : List.List ( String.String, List.List ( String.String, String.String ) ) }) -> List.List Evg.Internal.Filter -> Evg.Internal.Filter"},{"name":"fromSvg","comment":" Places graphics built with [`elm/svg`](https://package.elm-lang.org/packages/elm/svg/latest/)\ninto an Evg drawing. Useful for icons and other assets exported from a\ngraphics program, which tools convert to `elm/svg` mechanically, so you can\nuse them without porting them by hand.\n\n    import Svg\n    import Svg.Attributes\n\n    Evg.svg []\n        { width = 100, height = 100 }\n        [ Evg.circle [] { r = 40, center = ( 50, 50 ) }\n        , Advanced.fromSvg\n            { id = \"logo\"\n            , svg =\n                Svg.g []\n                    [ Svg.path\n                        [ Svg.Attributes.d \"M0 0 L9 9\" ]\n                        []\n                    ]\n            , fallback = Advanced.notSupported\n            }\n        ]\n\nThe fields:\n\n  - `svg` is the graphic to embed.\n  - `id` names this piece, and must be unique within your drawing. The\n    library cannot look inside an `elm/svg` value, so the name stands in for\n    the content when it needs to tell pieces apart, such as when one is used\n    as a clip stencil. Two pieces sharing a name can be mistaken for each\n    other.\n  - `fallback` is drawn whenever something is asked of the graphic that the\n    library cannot do to an opaque value. Pass\n    [`notSupported`](#notSupported) to get a visible placeholder, `Evg.none`\n    to leave a gap, or draw a real stand-in with Evg if you want the result\n    to look right.\n\nThe fallback stands in for the graphic in these cases, so an unsupported\ncombination shows up rather than failing quietly:\n\n  - [`Evg.toString`](Evg#toString) always uses it, since the embedded markup\n    cannot be read back out of the virtual DOM.\n  - Applying an [`Evg.Animate`](Evg-Animate) function uses it. Animations\n    work by placing an element inside the shape they animate, and the inside\n    of an embedded value is not ours to change.\n\nOne limit has no fallback, because the graphic still draws correctly: event\nhandlers on shapes within it report coordinates in the drawing's own space\nrather than the shape's, since the library does not know what transforms the\nembedded markup applies.\n\nAttributes still work normally, since those go on a wrapper around the\nembedded content, so you can position, fade, or clip an embedded graphic:\n\n    Evg.group [ Evg.opacity 0.5 ]\n        [ Advanced.fromSvg\n            { id = \"logo\"\n            , svg = myIcon\n            , fallback = Advanced.notSupported\n            }\n        ]\n\n","type":"{ id : String.String, svg : Svg.Svg msg, fallback : Evg.Evg msg } -> Evg.Evg msg"},{"name":"link","comment":" Wraps content in a clickable link.\n\n    Advanced.link \"https://example.com\"\n        (Evg.text [ Evg.fillStr \"blue\" ]\n            { x = 10, y = 20, anchor = Evg.Start }\n            \"Click me\"\n        )\n\n","type":"String.String -> Evg.Evg msg -> Evg.Internal.Evg msg"},{"name":"nestedSvg","comment":" Creates a smaller drawing area inside the current one, with its own\ncoordinate system starting at `(0, 0)` in its own top-left corner. The record\nsays where the area sits and how big it is, in the parent's coordinates.\n\nThis is useful for embedding a self-contained sub-scene: the children position\nthemselves relative to the nested area, so you can move the whole thing around\nby changing `x` and `y` without touching any child coordinates.\n\n    Advanced.nestedSvg []\n        { x = 50, y = 50, width = 100, height = 100 }\n        [ Evg.circle [ Evg.fillStr \"red\" ]\n            { r = 50, center = ( 50, 50 ) }\n        ]\n\nA nested area can also carry its own [`viewBox`](#viewBox), which rescales\nwhatever the children draw to fit the area. That makes it a window onto a\nsub-scene: here a drawing that uses coordinates up to 1000 is shown inside a\n100 by 100 box, letterboxed if the proportions differ.\n\n    Advanced.nestedSvg\n        [ Advanced.viewBox 0 0 1000 1000\n        , Advanced.preserveAspectRatio\n            Advanced.XMidYMid\n            Advanced.Meet\n        ]\n        { x = 50, y = 50, width = 100, height = 100 }\n        [ bigSubScene ]\n\n","type":"List.List (Evg.Attribute { viewBox : Evg.Supported, opacity : Evg.Supported, filter : Evg.Supported, events : Evg.Supported } msg) -> { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> List.List (Evg.Internal.Evg msg) -> Evg.Internal.Evg msg"},{"name":"notSupported","comment":" A visible \"not supported\" placeholder: a red box with white lettering,\nsized to fill whatever area it is placed in. Use it as the `fallback` for\n[`fromSvg`](#fromSvg) so that anything the library cannot serialize shows up\nobviously in an exported file rather than silently leaving a hole.\n\nThe red box fills whatever area it is given, whether that is wide, tall, or\nsquare, and the lettering stays readable at any of those shapes:\n\n![the placeholder shown in a wide area and a tall one](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/not-supported.svg)\n\n","type":"Evg.Evg msg"},{"name":"preserveAspectRatio","comment":" Controls what happens when the window's shape doesn't match the drawing's\nshape. If the [`viewBox`](#viewBox) rectangle is, say, wide and short but the\non-screen area is tall and narrow, something has to give. The choices are:\n\n  - letterbox it (`Meet`): show the whole drawing and leave empty bands\n  - crop it (`Slice`): fill the whole area and cut off the overflow\n  - stretch it (`AlignNone`): distort the drawing to fit exactly\n\nThe [`AlignValue`](#AlignValue) says where the drawing sits within the\nviewport (centred, pushed to the top-left, and so on), and the\n[`MeetOrSlice`](#MeetOrSlice) picks between letterboxing and cropping.\n\n    -- The default behaviour: centred and letterboxed.\n    Advanced.preserveAspectRatio\n        Advanced.XMidYMid\n        Advanced.Meet\n\n","type":"Evg.Advanced.AlignValue -> Evg.Advanced.MeetOrSlice -> Evg.Attribute { a | viewBox : Evg.Supported } msg"},{"name":"role","comment":" Sets the ARIA role for assistive technology.\n\n    Evg.group [ Advanced.role \"img\" ] [ ... ]\n\n","type":"String.String -> Evg.Attribute { a | role : Evg.Supported } msg"},{"name":"viewBox","comment":" Sets which rectangle of your coordinate system gets shown. Think of the\nviewBox as a window onto your drawing: everything inside the rectangle\n`(minX, minY)` to `(minX + width, minY + height)` is scaled to fill the\nelement's on-screen area, and everything outside it falls out of view.\n\n    -- Show the region from (0, 0) to (1000, 1000),\n    -- whatever the on-screen size of the element is:\n    Advanced.viewBox 0 0 1000 1000\n\nThis means you can draw in whatever numbers are convenient (say, data values\nfrom 0 to 1000) and let the viewBox map them onto the pixels available.\nChanging `minX` and `minY` over time pans the window across the drawing, and\nshrinking `width` and `height` zooms in.\n\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Evg.Attribute { a | viewBox : Evg.Supported } msg"},{"name":"visibility","comment":" Controls whether a shape is drawn. A hidden shape still occupies its\nplace in the drawing, and animations on it keep running, so making it\nvisible again shows it exactly where and how it would have been.\n\nBy default a hidden shape does not respond to pointer events. If you need an\ninvisible shape that still catches clicks, combine this with\n`Evg.Events.pointerEvents` set to `Painted` or `All`.\n\n    Advanced.visibility Advanced.VisibilityHidden\n\n","type":"Evg.Advanced.Visibility -> Evg.Attribute { a | visibility : Evg.Supported } msg"}],"binops":[]},{"name":"Evg.Animate","comment":" Declarative animations that don't require any messages or subscriptions.\n\nYou describe the animation as part of your view and the browser plays it on\nits own. There is no Elm update loop involved: no subscriptions, no\n`Time`-based messages, no re-rendering every frame.\n\nThe vocabulary used throughout this module:\n\n  - durations and keyframe times are in seconds\n  - keyframes are snapshots of a value at points in time; the browser smoothly\n    blends between them\n  - easing is the speed profile of the motion between two keyframes, such as\n    starting slow and finishing fast\n\nHere is a small example:\n\n    import Evg\n    import Evg.Animate as Animate\n\n    -- Animate a circle's radius with easing:\n    Evg.circle\n        [ Evg.fillStr \"tomato\" ]\n        { r = 20, center = ( 50, 50 ) }\n        |> Animate.animate [ Animate.repeatIndefinite ]\n            \"r\"\n            [ ( 0.5, Animate.easeInOut, \"40\" )\n            , ( 1.5, Animate.easeLinear, \"20\" )\n            ]\n\nThis shows a red circle that endlessly swells and shrinks back.\n\n\n# Options\n\n@docs AnimationOption\n@docs repeatIndefinite, repeatCount, repeatFor, duration, delay, fillFreeze\n@docs easing, stepped, paced\n@docs additive, accumulateRepeats\n\n\n# Triggers and restarting\n\n@docs beginOn, endOn, Trigger, click, mouseOver, mouseOut, manualStart\n@docs restartWhenNotActive, restartNever\n\n\n# Reacting to animations\n\n@docs onBegin, onEnd, onRepeat\n\n\n# Easing Curves\n\n@docs Easing, easeLinear, easeInOut, easeIn, easeOut, cubicBezier\n\n\n# Animation Builders\n\n@docs animate, set, keyframes, sampled\n\n\n# Animating transforms\n\n@docs rotate, rotateAround, scale, scaleXY, translate, skewX, skewY\n\n\n# Motion along a path\n\n@docs motion, motionKeyframes\n@docs upright, orientReverse, orientAngle\n\n\n# Sequencing\n\n@docs sequence, Step, step, stepRotateAround, stepTranslate, stepScale\n\n","unions":[{"name":"AnimationOption","comment":" Options that control animation timing, repetition, triggering and how an\nanimation reports back into your program.\n","args":["msg"],"cases":[]},{"name":"Easing","comment":" The speed profile of the motion between two keyframes: whether it moves at\na constant rate, starts slow and speeds up, or the reverse. The values covered\nare the same either way; easing only changes how fast the animation travels\nthrough them at each moment.\n","args":[],"cases":[]},{"name":"Step","comment":" A single stage of a `sequence`. Build one with `step`, `stepRotateAround`,\n`stepTranslate` or `stepScale`.\n","args":["msg"],"cases":[]},{"name":"Trigger","comment":" Something that can start or stop an animation, such as a click or a mouse\nhover on the animated element itself.\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"accumulateRepeats","comment":" Each repeat builds on the end of the previous one instead of starting over.\nFor example a `translate` that moves 10 to the right will end up 20 to the right\nafter two repeats, 30 after three, and so on.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"additive","comment":" Add this animation on top of any other transforms already on the element,\nrather than replacing them. Transform animations (`rotate`, `scale`, and\nfriends) always do this automatically.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"animate","comment":" Animates a single attribute of a shape between keyframe values with easing.\n\nEach keyframe is a tuple of `( time, easing, value )` where:\n\n  - `time` is seconds from the start of the animation when this value is reached\n  - `easing` is the speed profile of the motion leading TO this value\n  - `value` is the attribute value at this keyframe (as a string)\n\nThe initial value comes from the element's own attributes.\n\n    -- Pulse a rectangle's corner radius:\n    Evg.rect [ Evg.cornerRadius 30, Evg.fillStr \"navy\" ]\n        { x = 10, y = 10, width = 100, height = 100 }\n        |> Animate.animate [ Animate.repeatIndefinite ]\n            \"rx\"\n            [ ( 0.8, Animate.easeLinear, \"50\" )\n            , ( 1.8, Animate.easeInOut, \"20\" )\n            , ( 3.0, Animate.easeLinear, \"30\" )\n            ]\n\nThis shows a navy square whose corners continuously round off and sharpen\nagain.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> String.String -> List.List ( Basics.Float, Evg.Animate.Easing, String.String ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"beginOn","comment":" Start the animation when the given event happens on the element, instead of\nright away. Give it more than once to start on any of several events.\n\n    Animate.animate [ Animate.beginOn Animate.click ]\n        \"r\"\n        [ ( 0.4, Animate.easeOut, \"40\" ) ]\n\nNothing moves until the shape is clicked; then it quickly grows.\n\n","type":"Evg.Animate.Trigger -> Evg.Animate.AnimationOption msg"},{"name":"click","comment":" The element is clicked.\n","type":"Evg.Animate.Trigger"},{"name":"cubicBezier","comment":" A custom speed profile defined by a cubic bezier curve, the same format\nused by CSS `cubic-bezier(...)` timing functions. The four numbers are the two\ncontrol points `(x1, y1)` and `(x2, y2)`.\n\n    Animate.cubicBezier 0.68 -0.55 0.265 1.55\n\nThis one makes the motion pull back slightly, race forward, overshoot the\ntarget and settle, like a spring.\n\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Evg.Animate.Easing"},{"name":"delay","comment":" Delay before the animation starts, in seconds.\n\nIf you also give a trigger with `beginOn`, the trigger wins and this delay is\nignored.\n\n","type":"Basics.Float -> Evg.Animate.AnimationOption msg"},{"name":"duration","comment":" The total duration of one animation cycle in seconds.\n","type":"Basics.Float -> Evg.Animate.AnimationOption msg"},{"name":"easeIn","comment":" Starts slow, then speeds up.\n","type":"Evg.Animate.Easing"},{"name":"easeInOut","comment":" Starts slow, speeds up, then slows down at the end.\n","type":"Evg.Animate.Easing"},{"name":"easeLinear","comment":" Constant speed from start to finish.\n","type":"Evg.Animate.Easing"},{"name":"easeOut","comment":" Starts fast, then slows down.\n","type":"Evg.Animate.Easing"},{"name":"easing","comment":" Sets the easing (the speed profile of the motion) used between all\nkeyframes.\n\n    Animate.keyframes\n        [ Animate.repeatIndefinite\n        , Animate.easing Animate.easeInOut\n        ]\n        [ ( 0\n          , Evg.circle []\n                { r = 10, center = ( 50, 50 ) }\n          )\n        , ( 1\n          , Evg.circle []\n                { r = 40, center = ( 50, 50 ) }\n          )\n        ]\n\nThis shows a circle growing and shrinking, gently accelerating out of each\nextreme and slowing into the next.\n\n","type":"Evg.Animate.Easing -> Evg.Animate.AnimationOption msg"},{"name":"endOn","comment":" End the animation early when the given event happens on the element.\n","type":"Evg.Animate.Trigger -> Evg.Animate.AnimationOption msg"},{"name":"fillFreeze","comment":" When the animation ends, the element stays at its final state rather than\nsnapping back to the start.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"keyframes","comment":" Animates between complete shapes at specified times. Each entry is a\nsnapshot of the whole shape at a moment in seconds; the library works out\nwhich attributes change across snapshots and generates synchronized\nanimations for each one, and the browser blends between them.\n\nThis is the highest-level animation API: you describe what the shape looks\nlike at each moment, and the library handles the rest.\n\n    import Evg\n    import Evg.Animate as Animate\n\n    pulsingCircle =\n        Animate.keyframes\n            [ Animate.repeatIndefinite\n            , Animate.easing Animate.easeInOut\n            ]\n            [ ( 0.0\n              , Evg.circle\n                    [ Evg.fillStr \"rgb(20,60,20)\" ]\n                    { r = 10, center = ( 50, 50 ) }\n              )\n            , ( 0.6\n              , Evg.circle\n                    [ Evg.fillStr \"rgb(20,180,20)\" ]\n                    { r = 40, center = ( 50, 50 ) }\n              )\n            , ( 1.0\n              , Evg.circle\n                    [ Evg.fillStr \"rgb(20,60,20)\" ]\n                    { r = 10, center = ( 50, 50 ) }\n              )\n            ]\n\nThis shows a circle repeatedly growing while brightening to a vivid green,\nthen shrinking and darkening back.\n\nIf frames have different element types, the shapes are swapped out at the\nright moments instead of smoothly blended.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Internal.Evg msg ) -> Evg.Internal.Evg msg"},{"name":"manualStart","comment":" The animation never starts on its own. It waits to be started by another\nanimation in a `sequence`.\n","type":"Evg.Animate.Trigger"},{"name":"motion","comment":" Moves an element along a path over the animation's duration. By default the\nelement also turns to face the direction it is travelling.\n\n    import Evg.Path exposing (Path(..), PathSegment(..))\n\n    -- A circle repeatedly gliding along a curve:\n    Evg.circle\n        [ Evg.fillStr \"red\" ]\n        { r = 5, center = ( 0, 0 ) }\n        |> Animate.motion\n            [ Animate.repeatIndefinite\n            , Animate.duration 3\n            ]\n            [ M ( 10, 80 )\n                [ C ( 40, 10 ) ( 65, 10 ) ( 95, 80 ) ]\n            ]\n\nThis shows a small red dot swooping up and over an arc, then starting again.\n\nUse `upright`, `orientReverse` or `orientAngle` to change how the element is\nturned as it moves.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List Evg.Path.Path -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"motionKeyframes","comment":" Moves an element along a path like `motion`, but lets you control how far\nalong the path the element is at each moment. Each keyframe is\n`( time, easing, progress )`, where `progress` is a fraction from `0` (start of\nthe path) to `1` (end).\n\nThis lets you speed up, slow down, pause or even reverse along a fixed path.\n\n    import Evg.Path exposing (Path(..), PathSegment(..))\n\n    Evg.circle\n        [ Evg.fillStr \"red\" ]\n        { r = 5, center = ( 0, 0 ) }\n        |> Animate.motionKeyframes\n            [ Animate.repeatIndefinite\n            , Animate.duration 4\n            ]\n            [ M ( 10, 80 )\n                [ C ( 40, 10 ) ( 65, 10 ) ( 95, 80 ) ]\n            ]\n            [ ( 1, Animate.easeInOut, 0.5 )\n            , ( 4, Animate.easeInOut, 1 )\n            ]\n\nThe dot rushes to the middle of the curve in the first second, then drifts\nslowly through the rest.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List Evg.Path.Path -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"mouseOut","comment":" The pointer moves off the element.\n","type":"Evg.Animate.Trigger"},{"name":"mouseOver","comment":" The pointer moves onto the element.\n","type":"Evg.Animate.Trigger"},{"name":"onBegin","comment":" Send a message the moment the animation starts.\n\nA browser support caveat: browsers only started delivering these animation\nmilestone events reliably in versions released after late 2025. Older Safari\n(including iOS) may never send them, even though the animation itself plays\nfine. Don't gate critical state changes on receiving one; if you must support\nolder browsers, a timer matching the animation's timing (e.g. `Process.sleep`)\nis the dependable alternative. This applies equally to `onEnd` and `onRepeat`.\n\n","type":"msg -> Evg.Animate.AnimationOption msg"},{"name":"onEnd","comment":" Send a message the moment the animation ends. Never sent by animations\nthat repeat forever.\n\nSee `onBegin` for a browser support caveat: on older browsers (notably\nSafari before late 2025) this message may never arrive, so avoid relying on\nit for critical state changes. For example, prefer a timer over `onEnd` for\nremoving an element after its exit animation.\n\n","type":"msg -> Evg.Animate.AnimationOption msg"},{"name":"onRepeat","comment":" Send a message each time the animation completes a repeat.\n\nSee `onBegin` for a browser support caveat that also applies here.\n\n","type":"msg -> Evg.Animate.AnimationOption msg"},{"name":"orientAngle","comment":" For `motion` and `motionKeyframes`: hold the element at a fixed angle (in\ndegrees) as it travels, regardless of the path's direction.\n","type":"Basics.Float -> Evg.Animate.AnimationOption msg"},{"name":"orientReverse","comment":" For `motion` and `motionKeyframes`: turn the element to face backwards along\nits direction of movement.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"paced","comment":" Move at a constant speed across the whole animation, spacing the keyframes\nso that equal distances take equal time. Any keyframe times and easings you gave\nare ignored in favor of this even pacing.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"repeatCount","comment":" The animation repeats a fixed number of times. Fractional counts are\nallowed, so `2.5` runs the animation two and a half times.\n","type":"Basics.Float -> Evg.Animate.AnimationOption msg"},{"name":"repeatFor","comment":" The animation keeps repeating until the given number of seconds has\nelapsed, then stops, even if that means cutting a cycle short.\n","type":"Basics.Float -> Evg.Animate.AnimationOption msg"},{"name":"repeatIndefinite","comment":" The animation repeats forever.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"restartNever","comment":" The animation can only run once; later triggers are ignored.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"restartWhenNotActive","comment":" If the animation is triggered again while it is already running, ignore the\nnew trigger. A fresh trigger only takes effect once the current run has\nfinished.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"rotate","comment":" Spins a shape by a number of degrees. Each keyframe is\n`( time, easing, angle )`, where `angle` is in degrees. Positive angles turn\nclockwise.\n\nThe rotation is added on top of any transforms already on the element, and it\nturns around the coordinate system's origin (the top-left corner). To spin a\nshape in place, use `rotateAround`.\n\n    -- A shape spinning a full turn every 2 seconds:\n    Evg.rect\n        [ Evg.fillStr \"teal\" ]\n        { x = 40, y = 40, width = 20, height = 20 }\n        |> Animate.rotate [ Animate.repeatIndefinite ]\n            [ ( 2, Animate.easeLinear, 360 ) ]\n\nThis shows a square sweeping around the top-left corner of the drawing in a\nwide circle.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"rotateAround","comment":" Like `rotate`, but spins around a chosen center point `( cx, cy )`. This\nis the usual way to rotate a shape \"in place\".\n\n    -- Spin a square around its center at (50, 50):\n    Evg.rect\n        [ Evg.fillStr \"teal\" ]\n        { x = 40, y = 40, width = 20, height = 20 }\n        |> Animate.rotateAround\n            [ Animate.repeatIndefinite ]\n            ( 50, 50 )\n            [ ( 2, Animate.easeLinear, 360 ) ]\n\nThis shows a square smoothly turning in place, completing a revolution every\ntwo seconds.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> ( Basics.Float, Basics.Float ) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"sampled","comment":" Creates an animation by sampling a function at regular intervals.\n\nThe function receives a value from 0.0 to 1.0 representing progress through\nthe animation, and should return the shape at that point in time. The library\ngenerates keyframes by evaluating the function at evenly-spaced sample points.\n\n    -- A progress bar that fills from left to right:\n    Animate.sampled [ Animate.repeatIndefinite ]\n        { samples = 10, duration = 3 }\n        (\\progress ->\n            Evg.rect [ Evg.fillStr \"green\" ]\n                { x = 0\n                , y = 40\n                , width = progress * 200\n                , height = 20\n                }\n        )\n\nThis shows a green bar repeatedly stretching from empty to full width over\nthree seconds.\n\nMore samples means smoother animation but larger DOM output. For most\nanimations, 6 to 12 samples is sufficient.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> { samples : Basics.Int, duration : Basics.Float } -> (Basics.Float -> Evg.Internal.Evg msg) -> Evg.Internal.Evg msg"},{"name":"scale","comment":" Grows or shrinks a shape uniformly. A factor of `1` is the original size,\n`2` is double, `0.5` is half. Each keyframe is `( time, easing, factor )`.\n\n    -- A pulsing \"heartbeat\" scale:\n    Evg.circle\n        [ Evg.fillStr \"crimson\" ]\n        { r = 20, center = ( 50, 50 ) }\n        |> Animate.scale [ Animate.repeatIndefinite ]\n            [ ( 0.3, Animate.easeOut, 1.3 )\n            , ( 0.6, Animate.easeInOut, 1 )\n            ]\n\nThis shows a circle throbbing larger and back like a heartbeat.\n\nNote that scaling happens relative to the coordinate system origin, so shapes\naway from the top-left corner also drift as they grow.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"scaleXY","comment":" Like `scale`, but with separate horizontal and vertical factors. Each\nkeyframe value is a pair `( sx, sy )`.\n\n    Evg.rect\n        [ Evg.fillStr \"teal\" ]\n        { x = 40, y = 40, width = 20, height = 20 }\n        |> Animate.scaleXY [ Animate.repeatIndefinite ]\n            [ ( 1, Animate.easeInOut, ( 2, 0.5 ) ) ]\n\nThis shows a square repeatedly squashing into a wide, flat rectangle.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, ( Basics.Float, Basics.Float ) ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"sequence","comment":" Runs a list of animation steps one after another on the same element. Each\nstep waits for the previous one to finish before it starts.\n\n    Evg.rect\n        [ Evg.fillStr \"teal\" ]\n        { x = 40, y = 40, width = 20, height = 20 }\n        |> Animate.sequence [ Animate.fillFreeze ]\n            [ Animate.stepTranslate\n                [ Animate.duration 1 ]\n                [ ( 1, Animate.easeOut, ( 40, 0 ) ) ]\n            , Animate.stepRotateAround\n                [ Animate.duration 1 ]\n                ( 50, 50 )\n                [ ( 1, Animate.easeInOut, 180 ) ]\n            ]\n\nThis shows a square sliding to the right, then rotating a half turn once the\nslide has finished.\n\nIf you start the sequence with a trigger (`beginOn Animate.click`), the whole\nchain waits for that event and then runs step by step. Repeating an\nevent-triggered sequence is not supported.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List (Evg.Animate.Step msg) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"set","comment":" Instantly sets an attribute to a value at a chosen moment, with no smooth\ntransition. Handy for toggling something on at a delay or on a click.\n\n    -- Turn a circle red the moment it is clicked:\n    Evg.circle\n        [ Evg.fillStr \"gray\" ]\n        { r = 20, center = ( 50, 50 ) }\n        |> Animate.set\n            [ Animate.beginOn Animate.click ]\n            \"fill\"\n            \"red\"\n\nThe circle stays gray until clicked, then instantly turns red.\n\nSince nothing is blended, the `easing` option has no effect here. The\n`duration` option means something different: it is how long the set value\nlasts, after which the value snaps back (unless you also use `fillFreeze`).\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> String.String -> String.String -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"skewX","comment":" Slants a shape sideways by an angle in degrees (its top edge leans left or\nright). Each keyframe is `( time, easing, angle )`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"skewY","comment":" Slants a shape vertically by an angle in degrees (its side edges lean up or\ndown). Each keyframe is `( time, easing, angle )`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"step","comment":" A sequence step that animates a single attribute, exactly like `animate`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> String.String -> List.List ( Basics.Float, Evg.Animate.Easing, String.String ) -> Evg.Animate.Step msg"},{"name":"stepRotateAround","comment":" A sequence step that rotates around a center point, like `rotateAround`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> ( Basics.Float, Basics.Float ) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Animate.Step msg"},{"name":"stepScale","comment":" A sequence step that grows or shrinks the element, like `scale`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, Basics.Float ) -> Evg.Animate.Step msg"},{"name":"stepTranslate","comment":" A sequence step that slides the element, like `translate`.\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, ( Basics.Float, Basics.Float ) ) -> Evg.Animate.Step msg"},{"name":"stepped","comment":" Jump instantly from one keyframe value to the next with no smooth\nin-between motion, like a slideshow of frames. Per-keyframe easings are ignored.\n","type":"Evg.Animate.AnimationOption msg"},{"name":"translate","comment":" Slides a shape by a horizontal and vertical offset. Each keyframe value is a\npair `( dx, dy )`, added on top of the element's own position.\n\n    -- Slide 100 to the right and back:\n    Evg.circle\n        [ Evg.fillStr \"orange\" ]\n        { r = 10, center = ( 20, 50 ) }\n        |> Animate.translate\n            [ Animate.repeatIndefinite ]\n            [ ( 1, Animate.easeInOut, ( 100, 0 ) )\n            , ( 2, Animate.easeInOut, ( 0, 0 ) )\n            ]\n\nThis shows a circle gliding to the right and back again, over and over.\n\n","type":"List.List (Evg.Animate.AnimationOption msg) -> List.List ( Basics.Float, Evg.Animate.Easing, ( Basics.Float, Basics.Float ) ) -> Evg.Internal.Evg msg -> Evg.Internal.Evg msg"},{"name":"upright","comment":" For `motion` and `motionKeyframes`: keep the element upright as it travels\nalong the path, instead of turning to face its direction of movement.\n","type":"Evg.Animate.AnimationOption msg"}],"binops":[]},{"name":"Evg.Clip","comment":" Show only part of a shape by cutting away the rest.\n\nA clip path works like a stencil: you provide a second shape, and only the\nparts of the first shape that fall inside it are drawn. Everything outside\nis cut away completely, leaving a hard edge, as if you had taken scissors\nto the picture.\n\nIf you want soft, gradual edges instead of a clean cut, see `Evg.Mask`.\n\n    import Evg\n    import Evg.Clip as Clip\n\n    -- Show only the part of the photo inside a circle,\n    -- producing a round photo cutout:\n    Evg.image\n        [ Clip.clip\n            (Evg.circle []\n                { r = 50, center = ( 50, 50 ) }\n            )\n        ]\n        { href = \"photo.jpg\"\n        , x = 0\n        , y = 0\n        , width = 100\n        , height = 100\n        }\n\n![clip example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/clip-example.svg)\n\nA colorful rectangle clipped by a circle: the corners are cut away and the\ncircle's edge is crisp.\n\n\n# Clipping\n\n@docs clip, clipWithCoordinates\n\n","unions":[],"aliases":[],"values":[{"name":"clip","comment":" Cuts a shape down using another shape as a stencil. Only the parts inside\nthe stencil shape stay visible; everything outside disappears. The stencil\nshape itself is never drawn, it only decides what shows.\n\nThe stencil is positioned using the same coordinates as the rest of the\npicture, so a circle centered at `(50, 50)` cuts around that point of the\npicture.\n\n    -- A photo cropped to a circle:\n    Evg.image\n        [ Clip.clip\n            (Evg.circle []\n                { r = 50, center = ( 50, 50 ) }\n            )\n        ]\n        { href = \"photo.jpg\"\n        , x = 0\n        , y = 0\n        , width = 100\n        , height = 100\n        }\n\n    -- A blue square cropped to a triangle:\n    Evg.rect\n        [ Clip.clip\n            (Evg.polygon []\n                [ ( 50, 0 ), ( 100, 100 ), ( 0, 100 ) ]\n            )\n        , Evg.fillStr \"blue\"\n        ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\n","type":"Evg.Evg msg -> Evg.Internal.Attribute a msg"},{"name":"clipWithCoordinates","comment":" Like `clip`, but you choose how the stencil's coordinates are measured.\n\nWith `clip`, the stencil is positioned in the picture's own coordinates.\nUse `Evg.objectBoundingBox` to measure the stencil against the shape being\nclipped instead: `(0, 0)` is that shape's top-left corner and `(1, 1)` its\nbottom-right, so the same stencil adapts to shapes of any size.\n\n    -- Show the left half, whatever the shape's size:\n    Evg.rect\n        [ Clip.clipWithCoordinates\n            (Evg.objectBoundingBox\n                { x = 0, y = 0, width = 1, height = 1 }\n            )\n            (Evg.rect []\n                { x = 0\n                , y = 0\n                , width = 0.5\n                , height = 1\n                }\n            )\n        , Evg.fillStr \"red\"\n        ]\n        { x = 20, y = 20, width = 160, height = 160 }\n\n","type":"Evg.CoordinateSpace -> Evg.Evg msg -> Evg.Internal.Attribute a msg"}],"binops":[]},{"name":"Evg.Events","comment":" Handle mouse, touch, and pen interactions on shapes.\n\nEvent handlers receive coordinates in _your_ coordinate space, not raw screen\npixels. There are three spaces a position can live in, and the library converts\nbetween them for you:\n\n  - **local**: the numbers you used to draw _this_ element. If the shape lives\n    inside `Evg.group [ Transform.translate 50 0 ]`, local coordinates already\n    have that translation undone. The simple handlers (like `onClick`) give you\n    this, so a click at the visual centre of a shape reports the centre in the\n    shape's own numbers no matter how it's been moved, scaled, or rotated.\n  - **scene**: the root coordinate system of your `Evg.svg`, meaning the same\n    numbers you'd use without any transforms. This is the space to do drag\n    maths in, because it doesn't move when the thing you're dragging moves.\n  - **client**: raw browser pixels, measured from the top-left corner of the\n    browser window. An escape hatch, and the currency of window-level drag\n    tracking.\n\nWhen you use no transforms, local and scene are identical, so you can ignore the\ndistinction until you need it.\n\n    import Evg\n    import Evg.Events as Events\n\n    Evg.circle\n        [ Evg.fillStr \"blue\"\n        , Events.onClick (\\point -> ClickedAt point)\n        ]\n        { r = 30, center = ( 50, 50 ) }\n\n\n# Simple handlers\n\nThese report a single `( x, y )` position in the element's local coordinate\nspace. They work for mouse, touch, and pen alike.\n\n@docs onClick, onPointerDown, onPointerUp, onPointerMove\n@docs onPointerEnter, onPointerLeave, onPointerCancel\n\n\n# Detailed handlers\n\nSometimes a position isn't enough: you also want the input device, which\nbutton was pressed, which keyboard modifiers were held, or the\n[`Frame`](#Frame) for window-level drag tracking. These handlers hand you a\n[`Pointer`](#Pointer) record with all of that.\n\n@docs onClickWith, onPointerDownWith, onPointerUpWith, onPointerMoveWith\n@docs Pointer, PointerType, Button, Modifiers\n\n\n# Scroll and zoom\n\n@docs onWheel, Wheel\n\n\n# Dragging beyond the element\n\nA mouse drag that leaves the element stops sending events to it, because the\nbrowser delivers them to whatever is now under the cursor. To keep following\nthe pointer you listen on the window instead, but a window event can't tell\nyou where your drawing is. A [`Frame`](#Frame), captured during an ordinary\nhandler while that information is still available, bridges the gap.\n\n@docs Frame, frameToScene, whileDragging\n\n\n# Pointer behaviour\n\n@docs touchAction, TouchActionValue\n@docs pointerEvents, PointerEventsValue\n@docs cursor, CursorValue\n\n","unions":[{"name":"Button","comment":" Which button was pressed. For touch and pen this is normally `Main`.\n","args":[],"cases":[["Main",[]],["Middle",[]],["Secondary",[]],["Back",[]],["Forward",[]],["NoButton",[]]]},{"name":"CursorValue","comment":" The mouse cursor shape when hovering over the element.\n","args":[],"cases":[["Default",[]],["PointerCursor",[]],["Move",[]],["Crosshair",[]],["Text",[]],["NotAllowed",[]],["Grab",[]],["Grabbing",[]]]},{"name":"Frame","comment":" A snapshot of the conversion from client pixels to scene coordinates,\ncaptured at the moment of a pointer event. Pass it to\n[`whileDragging`](#whileDragging) to convert the window-level events that follow.\n\nYou get one on every [`Pointer`](#Pointer) and [`Wheel`](#Wheel) record; store it\nin your model when a drag starts.\n\n","args":[],"cases":[]},{"name":"PointerEventsValue","comment":" Controls which parts of a shape respond to pointer events.\n","args":[],"cases":[["VisiblePainted",[]],["Visible",[]],["Painted",[]],["All",[]],["PointerEventsNone",[]]]},{"name":"PointerType","comment":" The kind of device that produced a pointer event.\n","args":[],"cases":[["Mouse",[]],["Touch",[]],["Pen",[]]]},{"name":"TouchActionValue","comment":" How the browser should treat touch gestures on this element.\n","args":[],"cases":[["None",[]],["PanX",[]],["PanY",[]],["Manipulation",[]]]}],"aliases":[{"name":"Modifiers","comment":" Which modifier keys were held during the event.\n","args":[],"type":"{ shift : Basics.Bool, ctrl : Basics.Bool, alt : Basics.Bool, meta : Basics.Bool }"},{"name":"Pointer","comment":" Everything known about a pointer event.\n\n  - `local`: position in this element's own coordinate space (see the module\n    intro).\n  - `scene`: position in the root `Evg.svg` coordinate space.\n  - `client`: raw browser pixels, measured from the top-left corner of the\n    browser window.\n  - `frame`: a snapshot of how to convert client pixels to scene coordinates,\n    for use with [`whileDragging`](#whileDragging).\n  - `pointerType`: whether this was a mouse, touch, or pen.\n  - `pointerId`: a number identifying this pointer, so you can track several\n    fingers independently during a multi-touch gesture.\n  - `isPrimary`: `True` for the first pointer in a multi-pointer gesture.\n  - `button`: which button triggered the event.\n  - `modifiers`: which keyboard modifier keys were held.\n\n","args":[],"type":"{ local : ( Basics.Float, Basics.Float ), scene : ( Basics.Float, Basics.Float ), client : ( Basics.Float, Basics.Float ), frame : Evg.Events.Frame, pointerType : Evg.Events.PointerType, pointerId : Basics.Int, isPrimary : Basics.Bool, button : Evg.Events.Button, modifiers : Evg.Events.Modifiers }"},{"name":"Wheel","comment":" A mouse-wheel or trackpad scroll event.\n\n  - `local` / `scene`: where the pointer was, in the two coordinate spaces.\n  - `delta`: how far it scrolled, normalised to pixels (positive is\n    down/right).\n  - `pinch`: `True` when this is a trackpad pinch-to-zoom rather than a plain\n    scroll. Browsers report pinches as a scroll with the Ctrl key implicitly\n    held, which is what this detects.\n  - `frame`: as on [`Pointer`](#Pointer).\n  - `modifiers`: modifier keys held. Note `ctrl` reads `True` during a\n    trackpad pinch even if the physical key isn't down; use `pinch` to tell\n    them apart.\n\n","args":[],"type":"{ local : ( Basics.Float, Basics.Float ), scene : ( Basics.Float, Basics.Float ), delta : ( Basics.Float, Basics.Float ), pinch : Basics.Bool, frame : Evg.Events.Frame, modifiers : Evg.Events.Modifiers }"}],"values":[{"name":"cursor","comment":" Sets the mouse cursor appearance when hovering over the shape.\n\n    -- hand cursor, indicating clickable:\n    Events.cursor Events.PointerCursor\n\n","type":"Evg.Events.CursorValue -> Evg.Attribute { a | events : Evg.Supported } msg"},{"name":"frameToScene","comment":" Convert a client-pixel position to scene coordinates using a captured\n[`Frame`](#Frame).\n","type":"Evg.Events.Frame -> ( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float )"},{"name":"onClick","comment":" Fires when the element is clicked. Reports the click position in the\nelement's local coordinate space.\n","type":"(( Basics.Float, Basics.Float ) -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onClickWith","comment":" Like [`onClick`](#onClick), but hands you the full [`Pointer`](#Pointer)\nrecord.\n","type":"(Evg.Events.Pointer -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerCancel","comment":" Fires when the browser takes over an in-progress gesture, for example when\na touch turns into a page scroll. Treat it like an interrupted `onPointerUp`:\nend whatever drag was in progress.\n","type":"msg -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerDown","comment":" Fires when a pointer (mouse button, finger, or pen) is pressed on the\nelement. This is where a drag or gesture usually begins.\n\nFor touch and pen the browser keeps sending `onPointerMove`/`onPointerUp` to\nthis element even if the pointer leaves it (browsers call this \"pointer\ncapture\": the element that received the press keeps receiving the follow-up\nevents). So touch and pen gestures work without any extra setup. Mouse drags\nneed [`whileDragging`](#whileDragging) to follow the cursor off the element.\nPair this with [`touchAction`](#touchAction) `None` so the browser doesn't\ntreat a touch-drag as a scroll.\n\n","type":"(( Basics.Float, Basics.Float ) -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerDownWith","comment":" Like [`onPointerDown`](#onPointerDown), but hands you the full\n[`Pointer`](#Pointer) record. This is where you'd grab `.frame` and `.pointerId`\nto set up a drag.\n","type":"(Evg.Events.Pointer -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerEnter","comment":" Fires once when a pointer enters the element.\n","type":"msg -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerLeave","comment":" Fires once when a pointer leaves the element.\n","type":"msg -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerMove","comment":" Fires continuously as a pointer moves over the element. Use sparingly,\nsince it generates many messages.\n","type":"(( Basics.Float, Basics.Float ) -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerMoveWith","comment":" Like [`onPointerMove`](#onPointerMove), but hands you the full\n[`Pointer`](#Pointer) record.\n","type":"(Evg.Events.Pointer -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerUp","comment":" Fires when a pressed pointer is released over the element.\n","type":"(( Basics.Float, Basics.Float ) -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onPointerUpWith","comment":" Like [`onPointerUp`](#onPointerUp), but hands you the full\n[`Pointer`](#Pointer) record.\n","type":"(Evg.Events.Pointer -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"onWheel","comment":" Fires when the mouse wheel or trackpad scrolls over the element. Calls\n`preventDefault`, so the page won't scroll while the pointer is over your\ndrawing. That is handy for zoom, but don't attach it to something the user\nneeds to be able to scroll past.\n\n    Events.onWheel (\\wheel -> Zoomed wheel)\n\n","type":"(Evg.Events.Wheel -> msg) -> Evg.Internal.Attribute { a | events : Evg.Internal.Supported } msg"},{"name":"pointerEvents","comment":" Sets which parts of a shape can receive pointer events.\n\n  - `VisiblePainted`: only the painted (filled/stroked) visible areas (default)\n  - `Visible`: the entire visible area, even transparent parts\n  - `Painted`: all painted areas, even if hidden\n  - `All`: the entire area regardless of visibility or paint\n  - `PointerEventsNone`: the shape ignores all pointer events\n\n","type":"Evg.Events.PointerEventsValue -> Evg.Attribute { a | events : Evg.Supported } msg"},{"name":"touchAction","comment":" Declares which touch gestures the browser may handle itself, before your\nhandlers see them. Set this to `None` on anything you drag or zoom with touch,\nso the browser doesn't scroll or pinch the page instead.\n\n    Events.touchAction Events.None\n\n","type":"Evg.Events.TouchActionValue -> Evg.Attribute { a | events : Evg.Supported } msg"},{"name":"whileDragging","comment":" Track a mouse drag across the whole window, converting each position to\nscene coordinates via a [`Frame`](#Frame) you captured on `onPointerDown`.\n\nSubscribe to it only while a drag is in progress, and only for mouse drags.\nTouch and pen keep firing on the element itself, so they don't need it:\n\n    subscriptions model =\n        case model.drag of\n            Just { frame, pointerType } ->\n                if pointerType == Events.Mouse then\n                    Events.whileDragging frame\n                        { onMove = DragMoved\n                        , onEnd = DragEnded\n                        }\n\n                else\n                    Sub.none\n\n            Nothing ->\n                Sub.none\n\nThe `Frame` is a snapshot taken when the drag began. If the page scrolls or your\n`Evg.svg` moves during the drag, the converted positions will be off by that\nmuch; capture a fresh `Frame` if that matters. A `Frame` also assumes the `svg`\nelement itself carries no CSS `transform` (ordinary positioning is fine).\n\n","type":"Evg.Events.Frame -> { onMove : ( Basics.Float, Basics.Float ) -> msg, onEnd : ( Basics.Float, Basics.Float ) -> msg } -> Platform.Sub.Sub msg"}],"binops":[]},{"name":"Evg.Filter","comment":" Build image processing pipelines by composing filter operations.\n\nA filter is an image effect applied to a shape after it has been drawn, much\nlike stacking adjustment layers in a photo editor. A blur softens the edges, a\ndrop shadow draws a dark blurred copy behind the shape, turbulence generates\ncloudy noise, and a displacement map warps a shape using another image as the\nguide.\n\n    import Evg\n    import Evg.Filter as Filter\n\n\n    -- A simple drop shadow:\n    shadow =\n        Filter.merge\n            [ Filter.sourceAlpha\n                |> Filter.gaussianBlur 3\n                |> Filter.offset 2 2\n            , Filter.sourceGraphic\n            ]\n\nWhen run, this shows the original shape with a soft dark copy of itself\npeeking out behind and slightly below it.\n\nThe key idea: each filter takes one or two input images and produces an output\nimage that can be piped into the next filter using `|>`.\n\n\n# Basics\n\n@docs Filter\n\n\n## Modifying filter primitives\n\n@docs withinSubregion, withinSRGB\n\n\n# Sources\n\nThese represent ways to get an input image into the filter pipeline:\n\n@docs sourceAlpha, sourceGraphic\n@docs image, imageAspectRatio\n\n\n# Filter Primitives\n\n\n## Color fills\n\n@docs flood, floodStr\n\n\n## Blurring\n\n@docs gaussianBlur, gaussianBlurXY\n\n\n## Noise generation\n\n@docs fractalNoise, turbulence\n\n\n## Displacement\n\n@docs displacementMap, displacementMapWithChannelSelector, Channel\n\n\n## Color manipulation\n\n@docs colorMatrix, saturate, hueRotate, luminanceToAlpha\n@docs componentTransfer, RemappingFunction, identity, table, discrete, linear, gamma\n\n\n## Compositing and blending\n\n@docs compositeIn, compositeOut, compositeAtop, compositeOver, compositeXor, compositeArithmetic\n@docs blend, BlendMode\n@docs merge\n\n\n## Positioning\n\n@docs offset, dropShadow\n\n\n## Morphology\n\n@docs erode, erodeXY, dilate, dilateXY\n\n\n## Tiling\n\n@docs tile\n\n\n## Convolution\n\n@docs convolve, ConvolveOption, divisor, bias, targetXY, edgeDuplicate, edgeWrap, edgeNone, preserveAlpha\n\n\n## Lighting\n\n@docs specularLighting, diffuseLighting, Light, pointLight, distantLight, spotLight\n\n","unions":[{"name":"BlendMode","comment":" How the colors of two overlapping images mix, matching the blend modes\nfound in photo editors:\n\n![blend modes](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-blend.svg)\n\n  - `Normal`: the top image simply covers the bottom one\n  - `Multiply`: colors combine to get darker, like overlapping stained glass\n  - `Screen`: colors combine to get lighter, like two projections on a screen\n  - `Darken`: keeps whichever pixel is darker\n  - `Lighten`: keeps whichever pixel is lighter\n  - `Overlay`: darkens dark areas and lightens light ones, boosting contrast\n\n","args":[],"cases":[["Normal",[]],["Multiply",[]],["Screen",[]],["Darken",[]],["Lighten",[]],["Overlay",[]]]},{"name":"Channel","comment":" Selects which color channel of the guide image a displacement map reads\nfrom:\n\n  - `Red`\n  - `Green`\n  - `Blue`\n  - `Alpha`\n\n","args":[],"cases":[["Red",[]],["Green",[]],["Blue",[]],["Alpha",[]]]},{"name":"ConvolveOption","comment":" An option for configuring the `convolve` filter.\n","args":[],"cases":[]},{"name":"Light","comment":" A light source for use with `specularLighting` and `diffuseLighting`.\nBuild one with `pointLight`, `distantLight` or `spotLight`.\n","args":[],"cases":[]},{"name":"RemappingFunction","comment":" Describes how one color channel's values are remapped in\n`componentTransfer`. Build one with `identity`, `table`, `discrete`, `linear`\nor `gamma`.\n","args":[],"cases":[]}],"aliases":[{"name":"Filter","comment":" One step in a filter pipeline, producing an image that can be fed into the\nnext step. Attach a finished pipeline to a shape with `Evg.filter`.\n","args":[],"type":"Evg.Internal.Filter"}],"values":[{"name":"bias","comment":" Adds a constant value to the result after the kernel is applied.\nDefaults to 0. Useful for shifting negative results into visible range\n(e.g., for edge detection).\n\n    Filter.convolve [ Filter.bias 0.5 ] edgeKernel input\n\n","type":"Basics.Float -> Evg.Filter.ConvolveOption"},{"name":"blend","comment":" Mixes the colors of two inputs where they overlap, using one of the\n`BlendMode`s. Unlike the composite operations, which decide which image wins\nin the overlap, blending mixes the colors of both.\n\n![blend modes](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-blend.svg)\n\n    Filter.blend Filter.Multiply foreground background\n\nWhere the images overlap the colors combine and darken, as if drawn with\noverlapping marker pens.\n\n","type":"Evg.Filter.BlendMode -> Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"colorMatrix","comment":" Recolors the input by computing each output color channel as a weighted\nmix of the input channels. This is the general-purpose color tool: greyscale,\nsepia, channel swaps, tints and transparency tricks are all particular\nmatrices. For the common cases, `saturate`, `hueRotate` and `luminanceToAlpha`\nare easier to use.\n\nThe matrix transformation applied is:\n\n    | R' |     | a00 a01 a02 a03 a04 |   | R |\n    | G' |     | a10 a11 a12 a13 a14 |   | G |\n    | B' |  =  | a20 a21 a22 a23 a24 | * | B |\n    | A' |     | a30 a31 a32 a33 a34 |   | A |\n    | 1  |     |  0   0   0   0   1  |   | 1 |\n\non the RGBA color and alpha values of every pixel on the input graphics to produce a result with a new set of RGBA color and alpha values.\n\nThe calculations are performed on non-premultiplied color values.\n\nThe input here is the above matrix in row order `[[ a00, a01, ...], [ a10, a11, ...], ...]`. This is a 4x5 list of lists. Extra values will be ignored and missing values will be substituted for the identity matrix. So\n\n    Filter.colorMatrix\n        [ [ 0.12 ]\n        , [ 0, 0.12 ]\n        , [ 1, 0, 0, 0, 0, 0.12 ]\n        ]\n\nis equivalent to:\n\n    Filter.colorMatrix\n        [ [ 0.12, 0, 0, 0, 0 ]\n        , [ 0, 0.12, 0, 0, 0 ]\n        , [ 1, 0, 0, 0, 0 ]\n        , [ 0, 0, 0, 1, 0 ]\n        , [ 0, 0, 0, 0, 1 ]\n        ]\n\n","type":"List.List (List.List Basics.Float) -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"componentTransfer","comment":" Adjusts each color channel independently by passing its values through a\nremapping function, much like the \"curves\" or \"levels\" tools in a photo\neditor. This is how you do brightness adjustment, contrast adjustment, color\nbalance, or posterization (reducing colors to a few flat bands).\n\n![component transfer functions](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-component-transfer.svg)\n\n    -- Increase contrast on all color channels:\n    Filter.sourceGraphic\n        |> Filter.componentTransfer\n            { r = Filter.table [ 0, 0.1, 0.9, 1 ]\n            , g = Filter.table [ 0, 0.1, 0.9, 1 ]\n            , b = Filter.table [ 0, 0.1, 0.9, 1 ]\n            , a = Filter.identity\n            }\n\nDark areas of the shape get darker and bright areas brighter.\n\n","type":"{ r : Evg.Filter.RemappingFunction, g : Evg.Filter.RemappingFunction, b : Evg.Filter.RemappingFunction, a : Evg.Filter.RemappingFunction } -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeArithmetic","comment":" Combines two inputs pixel by pixel using the formula\n`result = k1*in1*in2 + k2*in1 + k3*in2 + k4`, applied to each color channel.\nThis gives precise numeric control when none of the ready-made composite\noperations do what you need, such as adding a lighting result onto a base\nimage.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n    -- Add lighting to a base image:\n    Filter.compositeArithmetic 0 1 1 0 base lighting\n\nThe brightness of the two images adds together, making lit areas glow.\n\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeAtop","comment":" Draws the first input on top of the second, but only where the second is\nvisible; anything hanging over the edge of the second image is trimmed away.\nUseful for painting decoration onto a shape without spilling outside it.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeIn","comment":" Keeps only the parts of the first input that overlap the second, like\nusing the second image as a cookie cutter on the first. A common use is\nrecoloring a silhouette: cut a `flood` color down to the shape's outline.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n    Filter.compositeIn foreground mask\n\nOnly the parts of `foreground` that sit over `mask` remain visible.\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeOut","comment":" Keeps only the parts of the first input that do not overlap the second,\npunching a hole in the first image wherever the second one is. Useful for\ncut-out and outline effects.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeOver","comment":" Stacks the first input over the second, like laying one photo on top of\nanother; the second shows through wherever the first is transparent. For\nstacking more than two layers, `merge` is more convenient.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"compositeXor","comment":" Keeps only the parts of each input that do not overlap the other; the\noverlap itself disappears. Where two shapes cross, this leaves a hole.\n\n![composite operators](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-composite.svg)\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"convolve","comment":" Recomputes each pixel as a weighted mix of itself and its neighbors, using\nthe grid of weights (the kernel) you supply. Depending on the kernel this can\nsharpen, emboss, detect edges, or blur; use it when you need a pixel-level\neffect that none of the other filters provide.\n\n![convolve example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-convolve.svg)\n\nThe kernel dimensions are derived automatically from the list of lists.\n\n    -- 3x3 sharpen kernel:\n    Filter.sourceGraphic\n        |> Filter.convolve []\n            [ [ 0, -1, 0 ]\n            , [ -1, 5, -1 ]\n            , [ 0, -1, 0 ]\n            ]\n\n    -- Edge detection with custom options:\n    Filter.sourceGraphic\n        |> Filter.convolve\n            [ Filter.edgeDuplicate, Filter.bias 0.5 ]\n            [ [ -1, -1, -1 ]\n            , [ -1, 8, -1 ]\n            , [ -1, -1, -1 ]\n            ]\n\nThe first example makes details crisper; the second turns the image dark with\nbright lines tracing the edges.\n\n","type":"List.List Evg.Filter.ConvolveOption -> List.List (List.List Basics.Float) -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"diffuseLighting","comment":" Renders soft, matte shading, as if the input were a rough 3D surface lit\nby a lamp, with no shiny glints. Like `specularLighting`, it treats the\ninput's transparency as a height map; the result is an evenly lit embossed\nlook, good for paper, stone or fabric effects.\n\n![lighting example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-lighting.svg)\n\n`surfaceScale` sets how tall the imaginary bumps are and `diffuseConstant` the\noverall brightness.\n\n    Filter.sourceGraphic\n        |> Filter.diffuseLighting\n            { surfaceScale = 1\n            , diffuseConstant = 1\n            , lightingColor = Color.white\n            }\n            (Filter.distantLight\n                { azimuth = 45, elevation = 55 }\n            )\n\nThis shows the shape evenly lit from the upper left with a gently embossed\nlook.\n\n","type":"{ surfaceScale : Basics.Float, diffuseConstant : Basics.Float, lightingColor : Color.Color } -> Evg.Filter.Light -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"dilate","comment":" Grows every edge of the image outward by the given radius, so filled\nareas expand and thin lines get fatter. Useful for making text look bolder or\nfor building an outline (dilate the silhouette, then subtract the original).\n\n    Filter.sourceGraphic |> Filter.dilate 1\n\nThe shape appears slightly fatter all around.\n\n![dilate example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-dilate.svg)\n\n","type":"Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"dilateXY","comment":" Like `dilate`, but with separate horizontal and vertical radii.\n\n    Filter.sourceGraphic |> Filter.dilateXY 2 1\n\n","type":"Basics.Float -> Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"discrete","comment":" For discrete, the function is defined by the step function defined by the values given, which provides a list of n values (i.e., v0 to vn-1) in order to identify a step function consisting of n steps.\n\n![component transfer functions](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-component-transfer.svg)\n\nLet's look at an example:\n\n    Filter.discrete [ 0, 0.6, 0.8, 1 ]\n\nIn this case we have 4 values, so we have 4 equal regions:\n\n    0.0 - 0.25 ==> 0.0\n\n    0.25 - 0.5 ==> 0.6\n\n    0.5 - 0.75 ==> 0.8\n\n    0.75 - 1.0 ==> 1\n\nSo for instance if I get a color value of 0.6, this falls in the third region, and so will get remapped to the third value, which is 0.8.\n\n","type":"List.List Basics.Float -> Evg.Filter.RemappingFunction"},{"name":"displacementMap","comment":" Warps the first input using the second input as a guide image. Each pixel\nof the first image is nudged sideways and up or down by an amount read from\nthe corresponding pixel of the guide, so straight edges come out wavy and\nwobbly. Use it with noise as the guide for water ripples, heat shimmer, or a\nhand-drawn look. Higher `scale` values produce more extreme distortion.\n\nThe first filter argument is the image to warp; the second (or the one piped\nin with `|>`) is the guide image.\n\n    -- Wavy distortion effect:\n    Filter.fractalNoise\n        { baseFrequency = 0.05\n        , numOctaves = 1\n        , seed = 1\n        , stitchTiles = False\n        }\n        |> Filter.displacementMap { scale = 20 }\n            Filter.sourceGraphic\n\nThis makes the shape's edges ripple as if seen through wavy glass.\n\n![displacement example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-displacement.svg)\n\n","type":"{ scale : Basics.Float } -> Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"displacementMapWithChannelSelector","comment":" Like `displacementMap`, but lets you pick which color channel of the guide\nimage drives the horizontal shift and which drives the vertical shift. By\ndefault browsers use the alpha channel for both, which is rarely what you want\nwith colorful guide images like noise.\n","type":"{ scale : Basics.Float, xChannelSelector : Evg.Filter.Channel, yChannelSelector : Evg.Filter.Channel } -> Evg.Filter.Filter -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"distantLight","comment":" A light source infinitely far away, like the sun, so its rays hit the\nwhole image from the same direction. `azimuth` is the compass direction the\nlight comes from and `elevation` is how high it sits above the horizon, both\nin degrees.\n\n    Filter.distantLight { azimuth = 45, elevation = 60 }\n\n","type":"{ azimuth : Basics.Float, elevation : Basics.Float } -> Evg.Filter.Light"},{"name":"divisor","comment":" Sets the divisor for the convolution. By default, the divisor is the sum of\nall kernel values (normalizing the result). Override this when you want to\ncontrol brightness.\n\n    Filter.convolve [ Filter.divisor 1 ] kernel input\n\n","type":"Basics.Float -> Evg.Filter.ConvolveOption"},{"name":"dropShadow","comment":" Draws a dark, blurred copy of the input behind it, making the shape look\nlike it floats above the page. This is the one-step version of the classic\nblur, offset and merge pipeline.\n\n    Filter.sourceGraphic\n        |> Filter.dropShadow\n            { offset = ( 3, 3 )\n            , blur = 4\n            , color = Color.black\n            }\n\nThe shape appears with a soft black shadow peeking out below and to the right.\n\n![drop shadow example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-drop-shadow.svg)\n\n","type":"{ offset : ( Basics.Float, Basics.Float ), blur : Basics.Float, color : Color.Color } -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"edgeDuplicate","comment":" At the edges of the image, duplicate the nearest border pixels outward.\nThis avoids dark or transparent borders.\n\n    Filter.convolve [ Filter.edgeDuplicate ]\n        kernel\n        input\n\n","type":"Evg.Filter.ConvolveOption"},{"name":"edgeNone","comment":" At the edges of the image, use transparent black (zero) for out-of-bounds\npixels. This is the default behavior.\n\n    Filter.convolve [ Filter.edgeNone ] kernel input\n\n","type":"Evg.Filter.ConvolveOption"},{"name":"edgeWrap","comment":" At the edges of the image, wrap around to the opposite side (tiling).\n\n    Filter.convolve [ Filter.edgeWrap ] kernel input\n\n","type":"Evg.Filter.ConvolveOption"},{"name":"erode","comment":" Shaves the given radius off every edge of the image, so filled areas\nshrink and thin lines get thinner or disappear. Use it to make strokes or text\nlook lighter, or to shrink a silhouette before building an inset effect.\n\n    Filter.sourceGraphic |> Filter.erode 0.5\n\nThe shape appears slightly thinner all around.\n\n![erode example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-erode.svg)\n\n","type":"Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"erodeXY","comment":" Like `erode`, but with separate horizontal and vertical radii.\n\n    Filter.sourceGraphic |> Filter.erodeXY 1 0.5\n\n","type":"Basics.Float -> Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"flood","comment":" Fills the whole filter area with a single solid color. On its own it just\npaints a colored rectangle over the shape; it becomes useful when combined\nwith other filters, for example recoloring a silhouette with `compositeIn`.\n\n![flood example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-flood.svg)\n\n    Filter.flood (Color.rgb255 255 0 0)\n\nThis produces a solid red rectangle covering the filter area.\n\n","type":"Color.Color -> Evg.Filter.Filter"},{"name":"floodStr","comment":" Like `flood`, but takes the color as a CSS color string.\n\n![flood example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-flood.svg)\n\n    Filter.floodStr \"#FA32CA\"\n\nThis produces a solid pink rectangle covering the filter area.\n\n","type":"String.String -> Evg.Filter.Filter"},{"name":"fractalNoise","comment":" Generates soft, organic, cloud-like noise, filling the filter area with\nrandom smoky color. Use it as a texture (clouds, marble, water) or as the\nguide image for `displacementMap` to make things look warped or hand-drawn.\n\n![noise types comparison](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-noise-types.svg)\n\n    Filter.fractalNoise\n        { baseFrequency = 0.05\n        , numOctaves = 3\n        , seed = 1\n        , stitchTiles = False\n        }\n\nThis fills the area with a colorful, smoky cloud texture.\n\nNote that the texture is generated from nothing: whatever shape you apply\nthis to is replaced by noise rather than textured. To affect a shape, feed\nthe noise into [`displacementMap`](#displacementMap).\n\nThe options:\n\n  - `baseFrequency` controls how fine the noise is (smaller values give larger features)\n  - `numOctaves` adds layers of detail (more layers give a more intricate pattern)\n  - `seed` picks a different random pattern for each value\n  - `stitchTiles`, when `True`, makes the noise pattern tile seamlessly at the edges\n\n","type":"{ baseFrequency : Basics.Float, numOctaves : Basics.Int, seed : Basics.Int, stitchTiles : Basics.Bool } -> Evg.Filter.Filter"},{"name":"gamma","comment":" For gamma, the function is defined by the following exponential function:\n\n    C' = amplitude * C  ^ exponent + offset\n\nWhere C is the input value and C' is the output value.\n\n![component transfer functions](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-component-transfer.svg)\n\n","type":"{ amplitude : Basics.Float, exponent : Basics.Float, offset : Basics.Float } -> Evg.Filter.RemappingFunction"},{"name":"gaussianBlur","comment":" Softens the input image, smearing sharp edges into a gentle haze, like an\nout-of-focus photograph. Use it to de-emphasize background elements, soften\nedges, or as the blurry ingredient of a drop shadow or glow.\n\nThe number is the blur radius: larger values give a blurrier result.\n\n    Filter.sourceGraphic\n        |> Filter.gaussianBlur 3\n\n![blur example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-blur.svg)\n\n","type":"Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"gaussianBlurXY","comment":" Like `gaussianBlur`, but with separate horizontal and vertical blur radii.\nBlurring only horizontally gives a motion-streak look; only vertically gives a\nsmeared, dripping look.\n","type":"Basics.Float -> Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"hueRotate","comment":" Shifts every color around the color wheel by the given angle in degrees,\nso for example reds can become greens and greens become blues. Brightness and\ntransparency are unaffected. Useful for producing color variations of the same\nartwork.\n\n![hue rotate example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-hue-rotate.svg)\n\n    -- Shift all colors by 90 degrees:\n    Filter.sourceGraphic\n        |> Filter.hueRotate 90\n\nEvery color in the shape changes to a different one, while the drawing itself stays put.\n\n","type":"Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"identity","comment":" Leaves the channel unchanged.\n","type":"Evg.Filter.RemappingFunction"},{"name":"image","comment":" Loads an external image (by URL) to use as a filter input, for example as\na texture to blend over the shape. The image is stretched to fill the filter\narea.\n\n    Filter.image \"texture.png\"\n        |> Filter.blend Filter.Screen\n            Filter.sourceGraphic\n\nThe shape appears lightened by the bright parts of the texture image.\n\n","type":"String.String -> Evg.Filter.Filter"},{"name":"imageAspectRatio","comment":" Like `image`, but with explicit control over how the image scales to fit\nthe filter area, so it can keep its proportions instead of stretching. `Meet`\nfits the whole image inside the area (possibly leaving gaps), `Slice` fills\nthe area completely (possibly cropping), and the align value picks which part\nof the image stays anchored.\n\n    import Evg.Advanced\n        exposing\n            ( AlignValue(..)\n            , MeetOrSlice(..)\n            )\n\n    Filter.imageAspectRatio XMidYMid Slice \"photo.jpg\"\n\n","type":"Evg.Advanced.AlignValue -> Evg.Advanced.MeetOrSlice -> String.String -> Evg.Filter.Filter"},{"name":"linear","comment":" For linear, the function is defined by the following linear equation:\n\n    C' = slope * C + intercept\n\nWhere C is the input value and C' is the output value.\n\n![component transfer functions](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-component-transfer.svg)\n\n","type":"{ slope : Basics.Float, intercept : Basics.Float } -> Evg.Filter.RemappingFunction"},{"name":"luminanceToAlpha","comment":" Turns brightness into transparency: bright areas of the input become\nopaque and dark areas become see-through, while all color is discarded. Useful\nfor building masks from colored content, where you then use the result to hide\nor reveal parts of another image.\n\n![luminance to alpha example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-luminance-to-alpha.svg)\n\n    -- Use brightness as transparency:\n    Filter.sourceGraphic\n        |> Filter.luminanceToAlpha\n\nThe result is a black image whose opacity follows the brightness of the original.\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"merge","comment":" Stacks any number of filter results on top of each other, first in the\nlist at the back, last at the front. This is typically the final step of a\nfilter, for example placing the original shape back on top of its shadow.\n\n    Filter.merge [ background, middleLayer, foreground ]\n\n","type":"List.List Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"offset","comment":" Slides the input image by the given horizontal and vertical distance,\nleaving it otherwise unchanged. This is the usual way to push a shadow copy\nout from under the original shape.\n\n![offset example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-offset.svg)\n\n    Filter.sourceAlpha\n        |> Filter.gaussianBlur 3\n        |> Filter.offset 4 4\n\nThis produces a soft dark blob shifted down and to the right of where the\nshape sits.\n\n","type":"Basics.Float -> Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"pointLight","comment":" A light source at a specific position in 3D space, shining in all\ndirections like a bare light bulb hovering over the image. Areas near the\nlight appear brighter than areas far away.\n\n![lighting example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-lighting.svg)\n\n    Filter.pointLight { x = 50, y = 50, z = 200 }\n\n","type":"{ x : Basics.Float, y : Basics.Float, z : Basics.Float } -> Evg.Filter.Light"},{"name":"preserveAlpha","comment":" When set, only the alpha channel is convolved; the RGB channels are passed\nthrough unchanged. Useful for blurring transparency without affecting colors.\n\n    Filter.convolve [ Filter.preserveAlpha ]\n        blurKernel\n        input\n\n","type":"Evg.Filter.ConvolveOption"},{"name":"saturate","comment":" Adjusts how vivid the colors are. A value of `1` leaves colors unchanged,\n`0` drains all color away leaving grey, and values above `1` make colors more\nintense. Use it to mute a background or make an element pop.\n\n    -- Desaturate to greyscale:\n    Filter.sourceGraphic\n        |> Filter.saturate 0\n\nThe shape keeps its brightness but loses all color, appearing in shades of grey.\n\n![saturate example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-saturate.svg)\n\n    -- Vivid, over-saturated colors:\n    Filter.sourceGraphic\n        |> Filter.saturate 2.5\n\nColors come out noticeably more intense than the original.\n\n","type":"Basics.Float -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"sourceAlpha","comment":" A black silhouette of the shape the filter is applied to. It keeps the\nshape's outline and transparency (including soft anti-aliased edges) but\nreplaces all its colors with black.\n\nThis is the usual starting point for drop shadows, since a shadow is a dark\ncopy of the shape's outline. It is also handy as a mask for cutting other\nimages down to the shape's silhouette.\n\n","type":"Evg.Filter.Filter"},{"name":"sourceGraphic","comment":" The shape the filter is applied to, exactly as it would have been drawn\nwith no filter, in full color. Use this when you want the original shape to\nappear somewhere in the final result, for example drawn on top of its own\nshadow.\n","type":"Evg.Filter.Filter"},{"name":"specularLighting","comment":" Renders shiny highlights, as if the input were a glossy 3D surface\nreflecting a light. The input's transparency is treated as a height map, so\nthe shape appears embossed with bright glints where the light catches it. Use\nit for glass, metal or plastic button effects, usually added onto the original\nshape with `compositeArithmetic` or `compositeIn`.\n\n![lighting example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-lighting.svg)\n\n`surfaceScale` sets how tall the imaginary bumps are, `specularConstant` the\noverall brightness of the reflection, and `specularExponent` how tightly\nfocused the glints are (higher means smaller, sharper highlights).\n\n    Filter.sourceGraphic\n        |> Filter.specularLighting\n            { surfaceScale = 5\n            , specularConstant = 0.75\n            , specularExponent = 20\n            , lightingColor = Color.white\n            }\n            (Filter.pointLight\n                { x = 50, y = 50, z = 200 }\n            )\n\nThis shows a bright glint on the shape's edges nearest the light, fading to\nblack elsewhere.\n\n","type":"{ surfaceScale : Basics.Float, specularConstant : Basics.Float, specularExponent : Basics.Float, lightingColor : Color.Color } -> Evg.Filter.Light -> Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"spotLight","comment":" A cone-shaped spotlight, like a desk lamp: it sits at `(x, y, z)`, aims at\nthe `pointsAt` position, and only lights what falls inside its cone.\n`limitingConeAngle` (in degrees) controls how wide the cone is.\n","type":"{ x : Basics.Float, y : Basics.Float, z : Basics.Float, pointsAtX : Basics.Float, pointsAtY : Basics.Float, pointsAtZ : Basics.Float, limitingConeAngle : Basics.Float } -> Evg.Filter.Light"},{"name":"table","comment":" For table, the function is defined by linear interpolation between the values given. The table has n+1 values (i.e., v0 to vn) specifying the start and end values for n evenly sized interpolation regions.\n\n![component transfer functions](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-component-transfer.svg)\n\nLet's look at an example:\n\n    Filter.table [ 0, 0.6, 0.8, 1 ]\n\nIn this case we have 4 values, so we have 3 equal regions:\n\n    0.0 - 0.33 ==> 0.0 - 0.6\n\n    0.33 - 0.66 ==> 0.6 - 0.8\n\n    0.66 - 1.0 ==> 0.8 - 1.0\n\nSo for instance if I get a color value of 0.5, this falls in the middle of the second region, and so will get remapped to the middle of the output region, which is 0.7.\n\n","type":"List.List Basics.Float -> Evg.Filter.RemappingFunction"},{"name":"targetXY","comment":" Sets which pixel in the kernel aligns with the source pixel being computed.\nDefaults to the center of the kernel (`floor(orderX/2)`, `floor(orderY/2)`).\n\n    -- Aim the effect at the kernel's top-left:\n    Filter.convolve [ Filter.targetXY 0 0 ] kernel input\n\n","type":"Basics.Int -> Basics.Int -> Evg.Filter.ConvolveOption"},{"name":"tile","comment":" Fills the whole filter area by repeating the input image side by side,\nlike bathroom tiles. Usually combined with `withinSubregion` to pick out the\nsmall patch that gets repeated.\n\n![tile example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-tile.svg)\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"turbulence","comment":" Generates swirling, marble-like noise that fills the filter area. Compared\nto `fractalNoise` it looks sharper and more vein-like, resembling flames,\nmarble or rippling water rather than soft clouds. Use it as a texture or as\nthe guide image for `displacementMap`. The options mean the same as in\n`fractalNoise`.\n\n![noise types comparison](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-noise-types.svg)\n\n    Filter.turbulence\n        { baseFrequency = 0.05\n        , numOctaves = 2\n        , seed = 1\n        , stitchTiles = False\n        }\n\nThis fills the area with a sharp, swirling colored texture.\n\nNote that the texture is generated from nothing: whatever shape you apply\nthis to is replaced by noise rather than textured. To affect a shape, feed\nthe noise into [`displacementMap`](#displacementMap), which uses it to push\nthe shape's pixels around.\n\n![turbulence as a displacement guide](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-turbulence.svg)\n\n","type":"{ baseFrequency : Basics.Float, numOctaves : Basics.Int, seed : Basics.Int, stitchTiles : Basics.Bool } -> Evg.Filter.Filter"},{"name":"withinSRGB","comment":" Forces a filter operation to do its color math in the sRGB color space.\n\nBy default, SVG filters compute in a color space called linearRGB, which can\nproduce unexpected results. For example, a Gaussian blur in linearRGB tends to\ndarken colors and create muddy midtones. Using sRGB often gives results closer\nto what you would expect from photo editors or CSS filters.\n\n    -- A blur that preserves perceived brightness:\n    Filter.sourceGraphic\n        |> Filter.gaussianBlur 4\n        |> Filter.withinSRGB\n\nThis is especially noticeable for blurring, blending and compositing\noperations, where linearRGB math can produce visible color shifts.\n\n","type":"Evg.Filter.Filter -> Evg.Filter.Filter"},{"name":"withinSubregion","comment":" Restricts a filter operation to a rectangular part of the filter area.\n\nEach filter operation normally covers the entire filter area. `withinSubregion`\nconfines the previous operation's input and output to a smaller rectangle.\nThis is useful for limiting expensive effects to where they are needed, or\ncreatively, for confining a blur or a color fill to just part of the image.\n\n![subregion example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/filter-subregion.svg)\n\nThe coordinates are fractions of the filter area (which defaults to the\nelement's bounding box plus some padding). So `{ x = 0, y = 0, width = 1, height = 1 }`\ncovers the full filter area, and `{ x = 0.25, y = 0.25, width = 0.5, height = 0.5 }`\ncovers the center quarter.\n\n    -- Blur only the bottom half:\n    Filter.merge\n        [ Filter.sourceGraphic\n        , Filter.sourceGraphic\n            |> Filter.gaussianBlur 5\n            |> Filter.withinSubregion\n                { x = 0\n                , y = 0.5\n                , width = 1\n                , height = 0.5\n                }\n        ]\n\nThis renders the original shape with a blurred strip across its bottom half.\nAnything a restricted operation produces outside its rectangle is clipped\naway, so without the `merge` the top half would simply be empty.\n\n","type":"{ x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.Filter.Filter -> Evg.Filter.Filter"}],"binops":[]},{"name":"Evg.Marker","comment":" Stamp small symbols, like arrowheads or dots, onto the ends and corners\nof lines.\n\nA marker is a little reusable drawing that gets stamped at chosen points of\na line, polyline, or path: at its start, at its end, or at each corner along\nthe way. The classic example is an arrowhead at the end of a line, but a\nmarker can be any shape you like.\n\n    import Evg\n    import Evg.Marker as Marker\n\n    -- A triangular arrowhead:\n    arrow =\n        Marker.marker []\n            { width = 10\n            , height = 10\n            , refX = 10\n            , refY = 5\n            }\n            Marker.AutoOrientation\n            (Evg.polygon [ Evg.fillStr \"black\" ]\n                [ ( 0, 0 ), ( 10, 5 ), ( 0, 10 ) ]\n            )\n\n    -- A horizontal line ending in the arrowhead:\n    Evg.line [ Marker.markerEnd arrow ]\n        ( 20, 50 )\n        ( 180, 50 )\n\n![marker arrow example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/marker-arrow-example.svg)\n\n\n# Creating Markers\n\n@docs Marker, marker, markerUserSpace, Orientation\n\n\n# Applying Markers\n\n@docs markerStart, markerMid, markerEnd\n\n","unions":[{"name":"Marker","comment":" A small reusable drawing that can be stamped at the start, the corners,\nor the end of lines and paths. Build one with `marker` or `markerUserSpace`,\nthen attach it with `markerStart`, `markerMid`, or `markerEnd`.\n","args":["msg"],"cases":[]},{"name":"Orientation","comment":" Controls how the marker turns to follow the line it sits on.\n\n  - `AutoOrientation`: the marker rotates to point along the direction the\n    line is traveling at that point. This is what you want for arrowheads.\n  - `AutoStartReverse`: like `AutoOrientation`, except a marker placed at the\n    start of the line points backward, away from the line. Useful for a\n    double-headed arrow built from one arrowhead shape.\n  - `Fixed angle`: the marker is always drawn turned clockwise by this many\n    degrees, regardless of the line's direction. `Fixed 0` keeps it upright.\n\n","args":[],"cases":[["AutoOrientation",[]],["AutoStartReverse",[]],["Fixed",["Basics.Float"]]]}],"aliases":[],"values":[{"name":"marker","comment":" Creates a marker that grows and shrinks with the thickness of the line\nit decorates. A marker given `width = 10` on a line drawn 2 units thick is\nstamped 20 units wide, so arrowheads stay in proportion to their line. This\nis usually what you want.\n\nThe record describes the marker's own little canvas. `width` and `height`\nare its size, and `refX` and `refY` are the anchor point: the spot inside the\nmarker that lands exactly on the line's endpoint or corner. In the arrowhead\nexample below, the anchor `(10, 5)` is the arrow's tip, so the tip touches\nthe very end of the line.\n\nThe first argument is a list of extra attributes for the marker's canvas.\nYou can pass a `viewBox` to give the marker's content its own convenient\ncoordinate system, or `preserveAspectRatio` to control how it stretches.\n\n    -- A simple arrowhead whose tip lands\n    -- on the line's end:\n    Marker.marker []\n        { width = 10, height = 10, refX = 10, refY = 5 }\n        Marker.AutoOrientation\n        (Evg.polygon [ Evg.fillStr \"black\" ]\n            [ ( 0, 0 ), ( 10, 5 ), ( 0, 10 ) ]\n        )\n\n    -- The same arrowhead, drawn in 0 to 100\n    -- coordinates for convenience:\n    Marker.marker [ Advanced.viewBox 0 0 100 100 ]\n        { width = 10\n        , height = 10\n        , refX = 100\n        , refY = 50\n        }\n        Marker.AutoOrientation\n        (Evg.polygon [ Evg.fillStr \"black\" ]\n            [ ( 0, 0 ), ( 100, 50 ), ( 0, 100 ) ]\n        )\n\n","type":"List.List (Evg.Attribute { viewBox : Evg.Supported, preserveAspectRatio : Evg.Supported } Basics.Never) -> { width : Basics.Float, height : Basics.Float, refX : Basics.Float, refY : Basics.Float } -> Evg.Marker.Orientation -> Evg.Internal.Evg msg -> Evg.Marker.Marker msg"},{"name":"markerEnd","comment":" Stamps a marker at the last point of a line, polyline, or path. This is\nthe usual place for an arrowhead.\n\n    Evg.line [ Marker.markerEnd arrow ]\n        ( 20, 50 )\n        ( 180, 50 )\n\n","type":"Evg.Marker.Marker msg -> Evg.Internal.Attribute { a | marker : Evg.Internal.Supported } msg"},{"name":"markerMid","comment":" Stamps a marker at every corner of a polyline or path between the first\nand last points. In the example below, the dot appears only at the middle\nbend, not at either end.\n\n    Evg.polyline [ Marker.markerMid dot ]\n        [ ( 10, 10 ), ( 50, 80 ), ( 90, 10 ) ]\n\n![markerMid example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/marker-mid-example.svg)\n\n","type":"Evg.Marker.Marker msg -> Evg.Internal.Attribute { a | marker : Evg.Internal.Supported } msg"},{"name":"markerStart","comment":" Stamps a marker at the first point of a line, polyline, or path.\n\n    Evg.polyline [ Marker.markerStart dot ]\n        [ ( 10, 10 ), ( 90, 90 ) ]\n\n","type":"Evg.Marker.Marker msg -> Evg.Internal.Attribute { a | marker : Evg.Internal.Supported } msg"},{"name":"markerUserSpace","comment":" Creates a marker with a fixed size. Unlike `marker`, its size does not\nfollow the thickness of the line it decorates: a marker given `width = 10`\nis always stamped 10 units wide, whether the line is hairline-thin or very\nthick. Use this when markers should stay the same size across lines of\ndifferent weights.\n\n    -- A small red dot, always 8 units across:\n    Marker.markerUserSpace []\n        { width = 8, height = 8, refX = 4, refY = 4 }\n        Marker.AutoOrientation\n        (Evg.circle [ Evg.fillStr \"red\" ]\n            { r = 4, center = ( 4, 4 ) }\n        )\n\n","type":"List.List (Evg.Attribute { viewBox : Evg.Supported, preserveAspectRatio : Evg.Supported } Basics.Never) -> { width : Basics.Float, height : Basics.Float, refX : Basics.Float, refY : Basics.Float } -> Evg.Marker.Orientation -> Evg.Internal.Evg msg -> Evg.Marker.Marker msg"}],"binops":[]},{"name":"Evg.Mask","comment":" Fade parts of a shape in and out using another shape as a mask.\n\nA mask is like a stencil with soft edges. Where a clip path (see `Evg.Clip`)\neither shows or hides each part of a shape with a hard boundary, a mask can\nshow a part at any strength in between. You draw a second shape (the mask),\nand each point of the masked shape becomes as visible as the mask is\n\"strong\" at that point. Paint the mask with a gradient and the shape fades\nout gradually instead of being cut off.\n\n    import Evg\n    import Evg.Mask as Mask\n\n    -- A blue square showing only inside a circle:\n    Evg.rect\n        [ Mask.alpha\n            (Evg.circle [ Evg.fillStr \"white\" ]\n                { r = 50, center = ( 50, 50 ) }\n            )\n        , Evg.fillStr \"blue\"\n        ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\n![clip versus mask example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/clip-vs-mask-example.svg)\n\nThe same colorful square shown twice: on the left cut by a clip path (hard\ncircular edge), on the right faded by a mask painted with a soft-edged\ncircle (the edge melts away gradually).\n\nThere are two ways a mask's \"strength\" can be measured, and each has its own\npair of functions below.\n\n\n# Alpha Masks\n\nThe mask's own transparency controls visibility. Where the mask shape is\nfully opaque (any color), the masked shape shows completely; where the mask\nis transparent or absent, the shape is hidden; in between, it is partially\nsee-through.\n\n@docs alpha, alphaWithCoordinates\n\n\n# Luminance Masks\n\nThe mask's brightness controls visibility. White areas show the shape fully,\nblack areas hide it, and greys show it partially. Use this when you want to\npaint the mask with light and dark colors, for example a white-to-black\ngradient or a photograph.\n\n@docs luminance, luminanceWithCoordinates\n\n","unions":[],"aliases":[],"values":[{"name":"alpha","comment":" Masks a shape using another shape's transparency. Wherever the mask\nshape is opaque, the masked shape shows; wherever the mask is transparent\nor there is no mask shape at all, it is hidden; partially see-through areas\nof the mask show the shape partially.\n\n    -- A red square, visible only inside the circle:\n    Evg.rect\n        [ Mask.alpha\n            (Evg.circle [ Evg.fillStr \"white\" ]\n                { r = 40, center = ( 50, 50 ) }\n            )\n        , Evg.fillStr \"red\"\n        ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\n","type":"Evg.Evg msg -> Evg.Internal.Attribute a msg"},{"name":"alphaWithCoordinates","comment":" Like `alpha`, but you choose how the mask shape's coordinates are\nmeasured. Use `Evg.objectBoundingBox` to measure the mask against the shape\nbeing masked (where `(0, 0)` is its top-left corner and `(1, 1)` its\nbottom-right), or `Evg.userSpace` to pin the mask to a fixed region of the\npicture.\n\n    Evg.rect\n        [ Mask.alphaWithCoordinates\n            (Evg.userSpace\n                { x = 0\n                , y = 0\n                , width = 200\n                , height = 200\n                }\n            )\n            (Evg.circle [ Evg.fillStr \"white\" ]\n                { r = 100, center = ( 100, 100 ) }\n            )\n        , Evg.fillStr \"red\"\n        ]\n        { x = 0, y = 0, width = 200, height = 200 }\n\n","type":"Evg.CoordinateSpace -> Evg.Evg msg -> Evg.Internal.Attribute a msg"},{"name":"luminance","comment":" Masks a shape using another shape's brightness. White areas of the mask\nshow the shape fully, black areas hide it, and greys show it partially.\nPainting the mask with a white-to-black gradient makes the shape fade out\nsmoothly.\n\n    -- A red square, visible inside the white circle:\n    Evg.rect\n        [ Mask.luminance\n            (Evg.circle [ Evg.fillStr \"white\" ]\n                { r = 40, center = ( 50, 50 ) }\n            )\n        , Evg.fillStr \"red\"\n        ]\n        { x = 0, y = 0, width = 100, height = 100 }\n\n","type":"Evg.Evg msg -> Evg.Internal.Attribute a msg"},{"name":"luminanceWithCoordinates","comment":" Like `luminance`, but you choose how the mask shape's coordinates are\nmeasured. Use `Evg.objectBoundingBox` to measure the mask against the shape\nbeing masked, or `Evg.userSpace` to pin the mask to a fixed region of the\npicture.\n\n    Evg.rect\n        [ Mask.luminanceWithCoordinates\n            (Evg.userSpace\n                { x = 0\n                , y = 0\n                , width = 200\n                , height = 200\n                }\n            )\n            (Evg.circle [ Evg.fillStr \"white\" ]\n                { r = 100, center = ( 100, 100 ) }\n            )\n        , Evg.fillStr \"red\"\n        ]\n        { x = 0, y = 0, width = 200, height = 200 }\n\n","type":"Evg.CoordinateSpace -> Evg.Evg msg -> Evg.Internal.Attribute a msg"}],"binops":[]},{"name":"Evg.Paint","comment":" Choose the colors that shapes are drawn with.\n\nEvery shape has two paintable parts: the fill (the color inside the shape)\nand the stroke (the outline drawn along the shape's edge). A `Paint` value\ndescribes what to put there. It can be a solid color, a gradient (a smooth\nblend between colors), a pattern (a small tile repeated to fill the shape),\nor nothing at all. You apply a `Paint` with `Evg.fill` or `Evg.stroke`.\n\nColors are provided using the [`avh4/elm-color`](https://package.elm-lang.org/packages/avh4/elm-color/latest/) package.\n\n    import Color\n    import Evg\n    import Evg.Paint as Paint\n\n    -- A rectangle that fades from red on the left\n    -- to blue on the right:\n    Evg.rect\n        [ Evg.fill\n            (Paint.linearGradient ( 0, 0 )\n                ( 1, 0 )\n                [ Paint.stop 0 (Color.rgb255 255 0 0)\n                , Paint.stop 1 (Color.rgb255 0 0 255)\n                ]\n            )\n        ]\n        { x = 0, y = 0, width = 100, height = 50 }\n\n\n# Paint Values\n\n@docs Paint\n\n\n## Solid Colors\n\n@docs none, solid, solidStr\n\n\n## Context Paint\n\n@docs contextFill, contextStroke\n\n\n## Gradients\n\n@docs linearGradient, linearGradientWithCoordinates\n@docs radialGradient, radialGradientWithCoordinates\n\n\n## Patterns\n\n@docs pattern, patternWithCoordinates\n\n\n## Gradient Stops\n\n@docs Stop, stop, stopWithOpacity, stopStr\n\n","unions":[],"aliases":[{"name":"Paint","comment":" Describes what a shape's fill or stroke is drawn with: a solid color,\na gradient, a repeating pattern, or nothing.\n","args":[],"type":"Evg.Internal.Paint"},{"name":"Stop","comment":" One pinned color in a gradient. A gradient is built from stops: positions\nalong the gradient line where you pin a color. Between stops, colors blend\nsmoothly.\n","args":[],"type":"Evg.Internal.Stop"}],"values":[{"name":"contextFill","comment":" Borrows the fill color of whichever shape this one is attached to. This\nmatters mostly inside markers (small symbols stamped onto the ends or corners\nof lines, like arrowheads). A marker painted this way automatically takes on\nthe fill color of each line it decorates, so one marker definition works for\nlines of any color.\n\n    -- A marker triangle that matches the fill\n    -- of the shape it decorates:\n    Evg.polygon [ Evg.fill Paint.contextFill ]\n        [ ( 0, 0 ), ( 10, 5 ), ( 0, 10 ) ]\n\n","type":"Evg.Paint.Paint"},{"name":"contextStroke","comment":" Borrows the stroke color (the color of the outline) of whichever shape\nthis one is attached to. Like `contextFill`, this is mostly useful inside\nmarkers: an arrowhead filled this way always matches the color of the line\nit sits on.\n\n    -- A marker arrowhead that matches\n    -- the line's stroke color:\n    Evg.polygon [ Evg.fill Paint.contextStroke ]\n        [ ( 0, 0 ), ( 10, 5 ), ( 0, 10 ) ]\n\n","type":"Evg.Paint.Paint"},{"name":"linearGradient","comment":" A gradient: colors that blend smoothly into one another along a straight\nline. You give the start point of the line, the end point, and a list of stops\n(positions along the line where you pin a color). Between stops, the colors\nblend smoothly.\n\nBoth points are measured against the shape being painted: `(0, 0)` is the\nshape's own top-left corner and `(1, 1)` its bottom-right, no matter where\nthe shape is or how big it is. That means the same gradient value can be\nreused on shapes of different sizes.\n\n    -- Yellow on the left fades to red on the right:\n    Paint.linearGradient ( 0, 0 )\n        ( 1, 0 )\n        [ Paint.stop 0 (Color.rgb255 255 255 0)\n        , Paint.stop 1 (Color.rgb255 255 0 0)\n        ]\n\n![linear gradient example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/linear-gradient-example.svg)\n\n    -- Fades from blue at the top-left corner\n    -- to magenta at the bottom-right:\n    Paint.linearGradient ( 0, 0 )\n        ( 1, 1 )\n        [ Paint.stop 0 (Color.rgb255 0 0 255)\n        , Paint.stop 1 (Color.rgb255 255 0 255)\n        ]\n\n![diagonal linear gradient example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/linear-gradient-diagonal-example.svg)\n\n","type":"( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> List.List Evg.Paint.Stop -> Evg.Paint.Paint"},{"name":"linearGradientWithCoordinates","comment":" Like `linearGradient`, but you choose how the coordinates are measured.\n\n`linearGradient` measures against the shape being painted (0 to 1 across its\nwidth and height). Use this function with `Evg.userSpace` when you want the\ngradient pinned to a fixed area of the picture instead, for example one\ngradient shared by several bars of a chart so the colors line up across all\nof them:\n\n    -- A gradient fixed to one area of the picture:\n    Paint.linearGradientWithCoordinates\n        (Evg.userSpace\n            { x = 0, y = 0, width = 400, height = 300 }\n        )\n        ( 0, 0 )\n        ( 400, 0 )\n        [ Paint.stop 0 (Color.rgb255 255 0 0)\n        , Paint.stop 1 (Color.rgb255 0 0 255)\n        ]\n\n","type":"Evg.CoordinateSpace -> ( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> List.List Evg.Paint.Stop -> Evg.Paint.Paint"},{"name":"none","comment":" No paint at all. That part of the shape is simply not drawn. Use this\nwhen you want only an outline (no fill) or only a fill (no outline).\n\n    -- An empty circle: a navy ring, nothing inside.\n    Evg.circle\n        [ Evg.fill Paint.none\n        , Evg.stroke (Paint.solid Color.darkBlue)\n        ]\n        { r = 40, center = ( 50, 50 ) }\n\n","type":"Evg.Paint.Paint"},{"name":"pattern","comment":" A pattern: a small tile of shapes repeated side by side, like wallpaper,\nto fill the shape it is painted onto. You give the size of one tile and the\nshapes to draw inside it. The tile size and the shapes inside it are measured\nin the same units you position shapes with elsewhere in the picture.\n\nThe first argument is a list of extra attributes for the tile. You can pass a\n`viewBox` to give the tile contents their own convenient coordinate system,\nor transforms to rotate or slant the whole pattern.\n\n    -- Polka dots: a 10 by 10 tile with one red dot,\n    -- repeated across the shape.\n    Paint.pattern [ Advanced.viewBox 0 0 10 10 ]\n        { width = 10, height = 10 }\n        [ Evg.rect [ Evg.fillStr \"white\" ]\n            { x = 0, y = 0, width = 10, height = 10 }\n        , Evg.circle [ Evg.fillStr \"red\" ]\n            { r = 3, center = ( 5, 5 ) }\n        ]\n\n![polka dot pattern example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/pattern-dots-example.svg)\n\n","type":"List.List (Evg.Attribute a Basics.Never) -> { width : Basics.Float, height : Basics.Float } -> List.List (Evg.Internal.Evg Basics.Never) -> Evg.Paint.Paint"},{"name":"patternWithCoordinates","comment":" Like `pattern`, but you choose how the tile is measured.\n\nWith `Evg.objectBoundingBox`, the tile size and the shapes inside it are\nfractions of the shape being filled (0 to 1). A tile that is `0.2` wide always\nfits five times across the shape, so the pattern grows and shrinks with the\nshape it fills.\n\nWith `Evg.userSpace`, the tile size and its contents use the same fixed units\nas the rest of the picture (the same behavior as `pattern`).\n\n    -- Checkerboard that scales with the element:\n    Paint.patternWithCoordinates []\n        (Evg.objectBoundingBox\n            { x = 0, y = 0, width = 0.2, height = 0.2 }\n        )\n        [ Evg.rect [ Evg.fillStr \"#eee\" ]\n            { x = 0, y = 0, width = 0.2, height = 0.2 }\n        , Evg.rect [ Evg.fillStr \"#333\" ]\n            { x = 0, y = 0, width = 0.1, height = 0.1 }\n        , Evg.rect [ Evg.fillStr \"#333\" ]\n            { x = 0.1\n            , y = 0.1\n            , width = 0.1\n            , height = 0.1\n            }\n        ]\n\n    -- Diagonal stripes:\n    Paint.patternWithCoordinates [ Transform.rotate 45 ]\n        (Evg.objectBoundingBox\n            { x = 0, y = 0, width = 0.1, height = 0.1 }\n        )\n        [ Evg.rect [ Evg.fillStr \"white\" ]\n            { x = 0, y = 0, width = 0.1, height = 0.1 }\n        , Evg.rect [ Evg.fillStr \"blue\" ]\n            { x = 0.05\n            , y = 0\n            , width = 0.05\n            , height = 0.1\n            }\n        ]\n\n","type":"List.List (Evg.Attribute a Basics.Never) -> Evg.Internal.CoordinateSpace -> List.List (Evg.Internal.Evg Basics.Never) -> Evg.Paint.Paint"},{"name":"radialGradient","comment":" A gradient where colors blend outward from a center point in circles,\nlike ripples on a pond. The first stop's color sits at the center and the\nlast stop's color is reached at the given radius.\n\nLike `linearGradient`, the center and radius are measured against the shape\nbeing painted: `(0.5, 0.5)` is the shape's middle and a radius of `0.5`\nreaches its edges.\n\n    -- White in the middle, black at the edges:\n    Paint.radialGradient ( 0.5, 0.5 )\n        0.5\n        [ Paint.stop 0 (Color.rgb255 255 255 255)\n        , Paint.stop 1 (Color.rgb255 0 0 0)\n        ]\n\n![radial gradient example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/radial-gradient-example.svg)\n\n","type":"( Basics.Float, Basics.Float ) -> Basics.Float -> List.List Evg.Paint.Stop -> Evg.Paint.Paint"},{"name":"radialGradientWithCoordinates","comment":" Like `radialGradient`, but you choose how the coordinates are measured.\n\n`radialGradient` measures against the shape being painted. Use this function\nwith `Evg.userSpace` to pin the gradient's center and radius to a fixed spot\nin the picture instead:\n\n    -- A glow fixed at a specific spot in the picture:\n    Paint.radialGradientWithCoordinates\n        (Evg.userSpace\n            { x = 0, y = 0, width = 200, height = 200 }\n        )\n        ( 100, 100 )\n        80\n        [ Paint.stop 0 (Color.rgb255 255 255 255)\n        , Paint.stop 1 (Color.rgb255 0 0 0)\n        ]\n\n","type":"Evg.CoordinateSpace -> ( Basics.Float, Basics.Float ) -> Basics.Float -> List.List Evg.Paint.Stop -> Evg.Paint.Paint"},{"name":"solid","comment":" A single, even color across the whole fill or stroke.\n\n    -- A solid orange:\n    Paint.solid (Color.rgb255 255 128 0)\n\n","type":"Color.Color -> Evg.Paint.Paint"},{"name":"solidStr","comment":" A solid color written as a CSS color string. Reach for this when the color\ncomes from your stylesheet rather than your Elm code, for example a CSS custom\nproperty or a CSS color function.\n\n    Paint.solidStr\n        \"light-dark(var(--foo), var(--baz, #ccc))\"\n\n","type":"String.String -> Evg.Paint.Paint"},{"name":"stop","comment":" Pins a color at a position along the gradient: `0.0` is the start of the\ngradient and `1.0` is the end.\n\n    -- Sky blue at the halfway point:\n    Paint.stop 0.5 (Color.rgb255 0 128 255)\n\n","type":"Basics.Float -> Color.Color -> Evg.Paint.Stop"},{"name":"stopStr","comment":" Pins a color written as a CSS color string, for when the color comes from\nyour stylesheet (a CSS custom property or color function) rather than your\nElm code.\n\n    Paint.stopStr 0.5 \"var(--accent)\"\n\n","type":"Basics.Float -> String.String -> Evg.Paint.Stop"},{"name":"stopWithOpacity","comment":" Pins a color that is also partially see-through. The last argument is the\nopacity: `1.0` is fully solid and `0.0` is fully invisible. A gradient ending\nin an invisible stop fades the shape out until whatever is behind it shows\nthrough completely.\n\n    -- The gradient's end point is fully see-through:\n    Paint.stopWithOpacity 1.0 (Color.rgb255 0 0 0) 0.0\n\n","type":"Basics.Float -> Color.Color -> Basics.Float -> Evg.Paint.Stop"}],"binops":[]},{"name":"Evg.Path","comment":" Draw arbitrary shapes out of straight lines and curves.\n\nA path is a shape drawn by moving an imaginary pen: you place it somewhere,\nthen draw straight lines and curves from point to point. Most shapes that\naren't simple rectangles or circles (icons, chart lines, arrows, country\noutlines) end up being paths.\n\nEvery point is a pair of `( x, y )` numbers measured from the top-left\ncorner of the drawing: x grows to the right, y grows downward.\n\nThis module offers two ways of describing the same shape:\n\n  - `Path` lists the pen movements one after another, much like you would\n    describe the shape out loud (\"start here, line to there, curve over to\n    there\"). Use it to construct paths.\n  - `Segment` describes the shape as a list of independent pieces, each\n    knowing its own start and end points. Use it for computations like\n    measuring a path or finding points along it.\n\nYou can convert freely between them with `toSegments` and `fromSegments`.\n\n\n# Path Commands\n\nPaths are built from a starting point and a sequence of drawing commands.\nUppercase constructors (`M`, `L`, `C`, and so on) use absolute coordinates:\n\"draw a line to the point (90, 90)\". Lowercase functions (`m`, `l`, `c`,\nand so on) use coordinates relative to wherever the pen currently is:\n\"draw a line 80 units to the right\".\n\n    import Evg.Path exposing (Path(..), PathSegment(..))\n\n\n    -- Absolute: a triangle with its tip at the top\n    triangle =\n        M ( 50, 10 ) [ L ( 90, 90 ), L ( 10, 90 ), Z ]\n\n    -- Relative: a square starting at (10, 10),\n    -- each side 80 units\n    square =\n        M ( 10, 10 )\n            [ l ( 80, 0 )\n            , l ( 0, 80 )\n            , l ( -80, 0 )\n            , Z\n            ]\n\n@docs Path, PathSegment\n\n\n## Relative Commands\n\nThese produce path segments with coordinates relative to the current point.\n\n@docs RelativeSegment\n@docs m, l, h, v, c, s, q, t, a\n\n\n## Utilities\n\n@docs close, endPoint, startPoint\n\n\n# Geometric Segments\n\nA `Segment` represents a single piece of a path with explicit start and end\npoints. This is more convenient for computations (measuring length, sampling\npoints, transforming) since you don't need to track the \"current point\" state.\n\n@docs Segment, toSegments, fromSegments\n\n\n## Measurement and Sampling\n\n@docs pathLength, interpolate\n\n\n# Rendering\n\n@docs toString\n\n","unions":[{"name":"Path","comment":" A single stroke of the pen: first lift the pen and put it down somewhere,\nthen draw a sequence of lines and curves from there.\n\n  - `M point segments` places the pen at an absolute position, then draws\n  - `MRelative offset segments` places the pen relative to wherever the\n    previous stroke ended, then draws\n\nPassing several `Path` values to `Evg.path` draws them all as one shape.\nSince the pen lifts between strokes, the pieces can be disconnected, and a\npiece drawn inside another one cuts a hole in it. That is how you draw a\ndonut: one stroke for the outer circle, another for the inner one.\n\n","args":[],"cases":[["M",["( Basics.Float, Basics.Float )","List.List Evg.Path.PathSegment"]],["MRelative",["( Basics.Float, Basics.Float )","List.List Evg.Path.PathSegment"]]]},{"name":"PathSegment","comment":" The individual pen movements, each using absolute coordinates. For every\none of these there is also a lowercase function (`l`, `h`, `c`, and so on)\nthat does the same thing with coordinates relative to the current pen position.\n\n  - `L point` draws a straight line to the point\n  - `H x` draws a horizontal line to the given x coordinate\n  - `V y` draws a vertical line to the given y coordinate\n  - `C cp1 cp2 end` draws a cubic curve; the two control points each pull\n    their end of the line toward themselves, so the curve can bend one way\n    and then the other, like an S\n  - `S cp2 end` continues a previous curve smoothly, so you only supply the\n    second control point\n  - `Q cp end` draws a quadratic curve, a simple bow bent toward one\n    control point\n  - `T end` continues a previous quadratic curve smoothly, needing no\n    control point at all\n  - `A rx ry rotation largeArc sweep end` draws an arc, a slice of an\n    ellipse outline, good for pie charts and rounded corners\n  - `Z` closes the shape with a straight line back to where the stroke began\n\nThe straight line commands look like this: `L` heads directly from the\ncurrent position to the point you give it.\n\n![a straight line from a start point to an end point](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-l.svg)\n\nFor details and pictures of each curve type, see the matching lowercase\nfunctions below.\n\n","args":[],"cases":[["L",["( Basics.Float, Basics.Float )"]],["H",["Basics.Float"]],["V",["Basics.Float"]],["C",["( Basics.Float, Basics.Float )","( Basics.Float, Basics.Float )","( Basics.Float, Basics.Float )"]],["S",["( Basics.Float, Basics.Float )","( Basics.Float, Basics.Float )"]],["Q",["( Basics.Float, Basics.Float )","( Basics.Float, Basics.Float )"]],["T",["( Basics.Float, Basics.Float )"]],["A",["Basics.Float","Basics.Float","Basics.Float","Basics.Bool","Basics.Bool","( Basics.Float, Basics.Float )"]],["Z",[]],["Rel",["Evg.Path.RelativeSegment"]]]},{"name":"RelativeSegment","comment":" A drawing command whose coordinates are measured from the current pen\nposition rather than from the top-left corner. You don't build these\ndirectly: the lowercase functions in this module ([`l`](#l), [`h`](#h),\n[`c`](#c), and so on) create them for you, already wrapped in a\n`PathSegment` via its `Rel` variant.\n","args":[],"cases":[]},{"name":"Segment","comment":" A single piece of a path with explicit start and end points. This\nrepresentation is more convenient for geometric computation, since you always\nknow where each piece starts and ends without tracking any pen state. It also\nhas only 4 constructors, which makes comprehensive case statements much\neasier to write.\n\n  - `Line` is a straight line between two points\n  - `Quadratic` is a curve pulled toward one control point\n  - `Cubic` is a curve pulled by two control points, one for each end\n  - `Arc` is a slice of an ellipse outline\n\n","args":[],"cases":[["Line",["{ from : ( Basics.Float, Basics.Float ), to : ( Basics.Float, Basics.Float ) }"]],["Quadratic",["{ from : ( Basics.Float, Basics.Float ), controlPoint : ( Basics.Float, Basics.Float ), to : ( Basics.Float, Basics.Float ) }"]],["Cubic",["{ from : ( Basics.Float, Basics.Float ), controlPoint1 : ( Basics.Float, Basics.Float ), controlPoint2 : ( Basics.Float, Basics.Float ), to : ( Basics.Float, Basics.Float ) }"]],["Arc",["{ from : ( Basics.Float, Basics.Float ), rx : Basics.Float, ry : Basics.Float, rotation : Basics.Float, largeArc : Basics.Bool, sweep : Basics.Bool, to : ( Basics.Float, Basics.Float ) }"]]]}],"aliases":[],"values":[{"name":"a","comment":" Draw an arc, a slice of an ellipse outline, from the current pen position\nto an end point. Arcs are what you reach for when drawing pie chart slices,\nrounded corners, or anything else that should look like part of a circle.\n\nYou describe the ellipse the arc is cut from (`rx` and `ry` are its\nhorizontal and vertical radii; make them equal for a circular arc, and\n`rotation` tilts the whole ellipse by that many degrees). Between any two\npoints there are four possible arcs of that ellipse: a long way round and a\nshort way round, on either side of the line between the points. Two flags\npick which one you get. `largeArc = True` chooses the longer route, and\n`sweep = True` makes the pen curve clockwise rather than counterclockwise.\n\nEvery panel in the picture uses the same start point, end point, and radii.\nOnly the two flags differ, and each combination picks out a different one of\nthe four arcs. The blue arc is the one selected; the pale arcs are the other\nthree possibilities:\n\n![the four arcs between the same two points, one per combination of the largeArc and sweep flags](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-a.svg)\n\nThe end point is an offset from the current pen position:\n\n    a 50 50 0 False True ( 100, 0 )\n\nThis draws the short clockwise half of a circle, bulging upward, ending\n100 units to the right.\n\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Bool -> Basics.Bool -> ( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"c","comment":" Draw a cubic curve, shaped by two invisible control points. The first\ncontrol point pulls the start of the line toward itself, the second pulls\nthe end. Because each end can be pulled in a different direction, a cubic\ncurve can bend one way and then the other, giving it an S capability that\nthe simpler quadratic curve lacks. This is the workhorse curve: reach for\nit when you need precise control over how a curve leaves one point and\narrives at another.\n\nIn the picture, the dashed lines connect each end of the curve to the\ncontrol point pulling on it:\n\n![a cubic curve arching between two points, with dashed lines to its two control points](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-c.svg)\n\nAll three points are offsets from the current pen position:\n\n    c ( 0, -50 ) ( 80, -50 ) ( 80, 0 )\n\nThis draws an arch that rises 50 units and lands 80 units to the right.\n\n","type":"( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"close","comment":" Close every stroke in the path by drawing a straight line from wherever\nit ends back to where it began, turning open lines into sealed outlines.\n","type":"List.List Evg.Path.Path -> List.List Evg.Path.Path"},{"name":"endPoint","comment":" The point where the pen finishes after drawing the whole path, in other\nwords the end of the final stroke. Handy when you want to continue drawing\nfrom where a path left off or attach something to its tip.\n","type":"List.List Evg.Path.Path -> ( Basics.Float, Basics.Float )"},{"name":"fromSegments","comment":" Convert geometric segments back into paths. Consecutive segments that\nshare endpoints become one continuous pen stroke. Wherever a segment starts\nsomewhere other than where the previous one ended, the pen is lifted and a\nnew stroke begins there.\n\n    fromSegments\n        [ Line { from = ( 10, 10 ), to = ( 90, 10 ) }\n        , Line { from = ( 90, 10 ), to = ( 90, 90 ) }\n        ]\n    --> [ M ( 10, 10 ) [ L ( 90, 10 ), L ( 90, 90 ) ] ]\n\n    -- A discontinuity creates a new subpath:\n    fromSegments\n        [ Line { from = ( 0, 0 ), to = ( 50, 0 ) }\n        , Line\n            { from = ( 100, 100 )\n            , to = ( 150, 100 )\n            }\n        ]\n    --> [ M ( 0, 0 ) [ L ( 50, 0 ) ]\n    --> , M ( 100, 100 ) [ L ( 150, 100 ) ]\n    --> ]\n\n","type":"List.List Evg.Path.Segment -> List.List Evg.Path.Path"},{"name":"h","comment":" Draw a horizontal line from the current pen position. Positive amounts\ngo right, negative ones go left. It is a convenient shorthand for `l` when\nyou know the line should be perfectly level.\n\nThe picture shows a horizontal line followed by a vertical one:\n\n![a horizontal line followed by a vertical line, forming a corner](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-h-v.svg)\n\n    h 100 -- 100 units right\n\n    h -50 -- 50 units left\n\n","type":"Basics.Float -> Evg.Path.PathSegment"},{"name":"interpolate","comment":" Find the point you would reach by tracing the path partway along its\nlength. The second argument says how far to go: 0.0 is the very start of the\npath, 1.0 is the very end, and 0.5 is the point exactly halfway along,\nmeasured by drawn distance. Useful for placing labels or markers along a\nline, or for animating something traveling along a path.\n\n    interpolate [ M ( 0, 0 ) [ L ( 100, 0 ) ] ] 0.5\n    --> ( 50, 0 )\n\n","type":"List.List Evg.Path.Path -> Basics.Float -> ( Basics.Float, Basics.Float )"},{"name":"l","comment":" Draw a straight line from the current pen position, offset by the given\namount. The first number moves right (negative moves left), the second moves\ndown (negative moves up).\n\n![a straight line from a start point to an end point](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-l.svg)\n\n    l ( 80, 0 ) -- 80 right\n\n    l ( 0, -40 ) -- 40 up\n\n","type":"( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"m","comment":" Lift the pen and put it down again at an offset from where the previous\nstroke ended, starting a new stroke there. Nothing is drawn by the move\nitself.\n\n    m ( 10, 20 ) [ l ( 50, 0 ), l ( 0, 50 ), Z ]\n\nThis starts a new triangle 10 units right and 20 units down from wherever\nthe previous stroke finished.\n\n","type":"( Basics.Float, Basics.Float ) -> List.List Evg.Path.PathSegment -> Evg.Path.Path"},{"name":"pathLength","comment":" The total length of a path, that is, how far the pen travels while\ndrawing it. Straight lines are measured exactly; curves are measured\napproximately by sampling points along them.\n\n    pathLength [ M ( 0, 0 ) [ L ( 100, 0 ) ] ] --> 100\n\n    -- a 3-4-5 triangle:\n    pathLength [ M ( 0, 0 ) [ L ( 30, 40 ) ] ] --> 50\n\n","type":"List.List Evg.Path.Path -> Basics.Float"},{"name":"q","comment":" Draw a quadratic curve, shaped by a single invisible control point. The\nline bows toward the control point without ever touching it, like a rope\nbeing tugged from one side. It always bends in just one direction, so it is\nthe simplest way to soften a line when you don't need the S shapes a cubic\ncurve can make.\n\nIn the picture, the dashed lines connect the ends of the curve to the\ncontrol point pulling on it:\n\n![a quadratic curve bowing toward a single control point above it](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-q.svg)\n\nBoth points are offsets from the current pen position:\n\n    q ( 40, -60 ) ( 80, 0 )\n\nThis draws a bow that arcs upward and lands 80 units to the right.\n\n","type":"( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"s","comment":" Continue a cubic curve smoothly. You give only the second control point\nand the end point; the first control point is computed automatically by\nmirroring the previous curve's last control point, which guarantees there is\nno visible kink where the two curves meet. Use it when chaining several\ncubic curves into one flowing line, such as a wave.\n\nIn the picture, a regular cubic curve (dark) is continued by a smooth one\n(blue); the mirrored control point is shown as a dashed circle:\n\n![a cubic curve continued smoothly by a second curve, with the mirrored control point shown dashed](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-s.svg)\n\nBoth points are offsets from the current pen position:\n\n    s ( 40, -30 ) ( 80, 0 )\n\n","type":"( Basics.Float, Basics.Float ) -> ( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"startPoint","comment":" The point where the pen is first put down, in other words the start of\nthe first stroke. A path whose first stroke uses the relative [`m`](#m)\nstarts relative to the origin, so its offset is its starting point.\n","type":"List.List Evg.Path.Path -> ( Basics.Float, Basics.Float )"},{"name":"t","comment":" Continue a quadratic curve smoothly. You give only the end point; the\ncontrol point is computed automatically by mirroring the previous curve's\ncontrol point, so the joined curves flow into each other without a kink.\nChaining `t` after a `q` is an easy way to draw a wavy line.\n\nIn the picture, a quadratic curve (dark) is continued by a smooth one\n(blue); the mirrored control point is shown as a dashed circle:\n\n![a quadratic curve continued smoothly by a second curve, with the mirrored control point shown dashed](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/path-t.svg)\n\nThe end point is an offset from the current pen position:\n\n    t ( 40, 0 )\n\n","type":"( Basics.Float, Basics.Float ) -> Evg.Path.PathSegment"},{"name":"toSegments","comment":" Convert paths into a list of geometric segments, resolving all the\nrelative movements so that each segment knows its own absolute start and end\npoints.\n\nThis is useful when you need to:\n\n  - Measure the length of a path\n  - Sample points along a path\n  - Transform individual segments\n  - Compute bounding boxes\n\nClosing commands (`Z`) become explicit straight `Line` segments back to the\nstroke's starting point, so a closed shape measures and samples like the\ncomplete outline you see on screen.\n\n","type":"List.List Evg.Path.Path -> List.List Evg.Path.Segment"},{"name":"toString","comment":" Render a single path to the compact text notation that SVG uses for\npath data (the `d` attribute), for example `\"M10 10L90 10Z\"`. You rarely need\nthis yourself, since `Evg.path` accepts `Path` values directly, but it is\nuseful for interoperating with other libraries or debugging. To render a\nlist of paths, use `List.map toString >> String.join \"\"`.\n","type":"Evg.Path.Path -> String.String"},{"name":"v","comment":" Draw a vertical line from the current pen position. Positive amounts go\ndown, negative ones go up. Like `h`, this is a shorthand for `l` when the\nline should be perfectly upright.\n\n    v 80 -- 80 units down\n\n    v -30 -- 30 units up\n\n","type":"Basics.Float -> Evg.Path.PathSegment"}],"binops":[]},{"name":"Evg.Performance","comment":" Tools for optimizing rendering performance.\n\nMost of the time you won't need these, since the default rendering is fast\nenough for typical use. Reach for this module when you have:\n\n  - A very large number of repeated shapes (hundreds or thousands)\n  - Complex shapes that are identical in structure (only position changes)\n  - Heavy computations producing shapes that rarely change\n\n\n# Lazy Evaluation\n\nOn every update Elm re-runs your view and works out what changed. `lazy`\nskips that work for a shape whose inputs haven't changed since last time: if\nthe arguments are the same values as before, the previous result is reused\nwithout re-rendering anything.\n\n@docs lazy, lazy2, lazy3\n\n\n# Reusable Definitions\n\nDraw a complex shape once, then stamp out cheap copies of it wherever you\nneed them.\n\n@docs asDef\n\n","unions":[],"aliases":[],"values":[{"name":"asDef","comment":" Turns a shape into a reusable definition. Returns a function that stamps\nout lightweight copies, working just like the shape constructors in `Evg`:\nit takes a list of attributes and then the position and size of the copy.\n\nThis is useful when you have the same complex shape repeated many times. The\nshape is drawn once as a hidden definition, and each visible copy is just a\ncheap reference to it, so the browser does the expensive work only once. The\ndefinition itself travels with the copies, so simply placing the stamped\nshapes in your scene is enough.\n\n    useIcon =\n        Evg.Performance.asDef myComplexIcon\n\n    scene =\n        Evg.svg []\n            { width = 200, height = 200 }\n            [ useIcon []\n                { x = 10\n                , y = 10\n                , width = 24\n                , height = 24\n                }\n            , useIcon [ Evg.opacity 0.5 ]\n                { x = 50\n                , y = 10\n                , width = 24\n                , height = 24\n                }\n            ]\n\nAttributes vary each copy individually: fade one out with `opacity`, listen\nfor clicks with an event handler, or move it with a transform.\n\nColors work by ordinary inheritance: `fill` and `stroke` set on a copy flow\ninto the parts of the original shape that left those unset, while parts\nthat picked explicit colors keep them. So if you design the original\nwithout colors, every stamp can be tinted differently; if you color the\noriginal fully, stamps always look identical.\n\n(There is also an explicit opt-in mechanism: parts of the original painted\nwith `Evg.Paint.contextFill` or `contextStroke` take their color from the\ncopy even alongside other explicit colors. Be aware that browser support\nfor context colors on copies is uneven; they are reliable for markers, less\nso here.)\n\n","type":"Evg.Evg msg -> List.List (Evg.Attribute { fill : Evg.Supported, stroke : Evg.Supported, opacity : Evg.Supported, filter : Evg.Supported, transform : Evg.Supported, events : Evg.Supported } msg) -> { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } -> Evg.Internal.Evg msg"},{"name":"lazy","comment":" Skips re-rendering the shape when the argument is unchanged since the\nlast update. Works like `Html.Lazy.lazy` but for `Evg` graphics, and comes\nwith the same caveats: both the function and the argument are compared by\nreference, so pass a top-level function (not a lambda) and a value straight\nout of your model rather than a record or list built fresh on every call.\n\nThe first argument is a name for this piece of the drawing, unique within\nyour whole scene. The library cannot look inside a lazy shape without\ndefeating its purpose, so the name stands in for the content when the\nlibrary needs to tell shapes apart (for example when a lazy shape is used\nas a clip stencil). Two different lazy shapes with the same name can get\nmixed up, so name them uniquely.\n\n    Evg.Performance.lazy \"sales-chart\"\n        viewExpensiveChart\n        model.chartData\n\n","type":"String.String -> (a -> Evg.Internal.Evg msg) -> a -> Evg.Internal.Evg msg"},{"name":"lazy2","comment":" Like [`lazy`](#lazy) but checks two arguments.\n","type":"String.String -> (a -> b -> Evg.Internal.Evg msg) -> a -> b -> Evg.Internal.Evg msg"},{"name":"lazy3","comment":" Like [`lazy`](#lazy) but checks three arguments.\n","type":"String.String -> (a -> b -> c -> Evg.Internal.Evg msg) -> a -> b -> c -> Evg.Internal.Evg msg"}],"binops":[]},{"name":"Evg.Text","comment":" Advanced text layout for when the basic `Evg.text` isn't enough.\n\nUse this module when you need:\n\n  - Mixed styling within a single line of text, such as one bold red word\n    in an otherwise plain sentence\n\n  - Text that bends to follow a curved line instead of sitting on a\n    straight one\n\n  - Fine control over spacing, boldness, decoration, and how the text sits\n    relative to the point you place it at\n\nHere is a sentence where just one word is red and bold:\n\n    import Evg\n    import Evg.Text as Text\n\n    Text.richText [ Evg.fontSize 16 ]\n        { x = 10, y = 50, anchor = Evg.Start }\n        [ Text.tspan [ Evg.fillStr \"black\" ] \"Hello, \"\n        , Text.tspan\n            [ Evg.fillStr \"red\"\n            , Text.fontWeight Text.Bold\n            ]\n            \"world\"\n        , Text.tspan [ Evg.fillStr \"black\" ] \"!\"\n        ]\n\nA note on positioning: text is placed at a single point. The `anchor` field\ndecides where the text sits relative to that point horizontally (`Start`\nputs the point at the left edge of the text, `Middle` centers the text on\nit, `End` puts the point at the right edge), and by default the point sits\non the baseline, the invisible line the letters rest on. `dominantBaseline`\nlets you change that vertical relationship.\n\n![the same point anchoring text three ways: extending right of it, centered on it, and extending left of it](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/text-anchors.svg)\n\n\n# Rich Text\n\n@docs Span, tspan\n@docs richText\n\n\n# Text on a Path\n\n@docs onPath\n\n\n# Text Attributes\n\n@docs textLength, LengthAdjust\n@docs dominantBaseline, Baseline\n@docs textDecoration, TextDecoration\n@docs letterSpacing, wordSpacing\n@docs writingMode, WritingMode\n@docs dx, dy\n@docs fontWeight, FontWeight\n@docs fontStyle, FontStyle\n\n","unions":[{"name":"Baseline","comment":" Where text sits vertically relative to the `y` coordinate you place it\nat. See `dominantBaseline` for what each option looks like.\n","args":[],"cases":[["Auto",[]],["Middle",[]],["Hanging",[]],["Central",[]],["TextTop",[]],["TextBottom",[]]]},{"name":"FontStyle","comment":" Whether the letters are upright or slanted.\n\n  - `StyleNormal` is upright text\n  - `Italic` uses the font's italic letterforms, which are usually slanted\n    and often more cursive\n  - `Oblique` simply slants the normal letterforms without changing their\n    shapes\n\n","args":[],"cases":[["StyleNormal",[]],["Italic",[]],["Oblique",[]]]},{"name":"FontWeight","comment":" How thick the strokes of the letters are.\n\n  - `Normal` is regular text\n  - `Bold` is heavy text\n  - `Bolder` is one step heavier than the surrounding text\n  - `Lighter` is one step lighter than the surrounding text\n  - `Weight n` picks an exact weight on the usual 100 to 900 scale, where\n    400 is normal and 700 is bold (the font must provide that weight for it\n    to show)\n\n","args":[],"cases":[["Normal",[]],["Bold",[]],["Bolder",[]],["Lighter",[]],["Weight",["Basics.Int"]]]},{"name":"LengthAdjust","comment":" How text is stretched or squeezed when `textLength` forces it to a\nspecific width.\n\n  - `Spacing` only changes the gaps between letters; the letters keep their\n    shape, so this looks better for small adjustments\n  - `SpacingAndGlyphs` stretches the letters themselves as well as the gaps,\n    which distorts the letterforms but distributes big changes more evenly\n\n","args":[],"cases":[["Spacing",[]],["SpacingAndGlyphs",[]]]},{"name":"Span","comment":" A run of text with its own styling, to be laid out as part of a\n`richText` block. Create these with `tspan`.\n","args":["msg"],"cases":[]},{"name":"TextDecoration","comment":" Lines drawn through or alongside text.\n\n  - `Underline` draws a line under the text\n  - `Overline` draws a line above the text\n  - `LineThrough` strikes the text out with a line through its middle\n  - `NoDecoration` removes any of the above\n\n","args":[],"cases":[["Underline",[]],["Overline",[]],["LineThrough",[]],["NoDecoration",[]]]},{"name":"WritingMode","comment":" The direction lines of text run.\n\n  - `HorizontalTB` is ordinary horizontal text, with lines stacking top to\n    bottom\n  - `VerticalRL` runs text top to bottom, with successive lines stacking\n    right to left, as in traditional Japanese layout\n  - `VerticalLR` runs text top to bottom, with successive lines stacking\n    left to right\n\n","args":[],"cases":[["HorizontalTB",[]],["VerticalRL",[]],["VerticalLR",[]]]}],"aliases":[],"values":[{"name":"dominantBaseline","comment":" Controls where text sits vertically relative to the `y` coordinate you\ngive it. By default the letters rest on top of that coordinate, like words\nsitting on a ruled line. This attribute moves that line.\n\n  - `Auto` is the default: letters rest on top of `y`, with descenders like\n    the tail of \"g\" dipping below\n  - `Middle` centers the text vertically on `y`, which is usually what you\n    want when labeling a point or centering text in a box\n  - `Hanging` hangs the text below `y`, so `y` marks roughly the top of the\n    letters\n  - `Central` also centers on `y`, but measures from the font's overall\n    height rather than the lowercase letters, so it can sit slightly\n    differently than `Middle`\n  - `TextTop` puts the very top of the font's tallest letters at `y`\n  - `TextBottom` puts the very bottom of the font's deepest descenders at `y`\n\nFor example:\n\n    Text.dominantBaseline Text.Hanging\n\nThis makes the text hang below the point you give instead of sitting on it.\n\n","type":"Evg.Text.Baseline -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"dx","comment":" Nudges text sideways from where it would otherwise be drawn. Positive\nvalues move it right, negative values move it left. Handy for fine-tuning a\nlabel's position without recomputing its `x` coordinate, or for offsetting\none span inside `richText`.\n\n    Text.dx 5\n\nThis shifts the text 5 units to the right.\n\n","type":"Basics.Float -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"dy","comment":" Nudges text up or down from where it would otherwise be drawn. Positive\nvalues move it down, negative values move it up. A common trick is to use\nthis on spans inside `richText` to create superscripts and subscripts.\n\n    Text.dy 10\n\nThis shifts the text 10 units down.\n\n","type":"Basics.Float -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"fontStyle","comment":" Controls whether the text is upright or slanted.\n\n    Text.fontStyle Text.Italic\n\nThis renders the text in slanted italic letters.\n\n","type":"Evg.Text.FontStyle -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"fontWeight","comment":" Controls how bold the text looks.\n\n    Text.fontWeight Text.Bold\n\n    Text.fontWeight (Text.Weight 600)\n\nThe second example produces a semi-bold weight, between normal and bold.\n\n","type":"Evg.Text.FontWeight -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"letterSpacing","comment":" Adjusts the space between individual letters. Positive values spread\nthe letters apart, negative values squeeze them closer together.\n\n    Text.letterSpacing 2\n\nThis adds 2 units of extra space between every pair of letters, giving the\ntext an airy, spaced-out look.\n\n","type":"Basics.Float -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"onPath","comment":" Makes text bend to follow a path instead of running in a straight line.\nApply this attribute to `Evg.text` or `Text.richText` and each letter is\nplaced and rotated so the whole line of text traces the path's shape, the\nway lettering follows the curve of a round badge or a wavy banner.\n\n![the words \"along a curve\" bending upward and back down over an arch](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/text-on-path.svg)\n\n    import Evg.Path exposing (Path(..), PathSegment(..))\n\n    Evg.text\n        [ Evg.fillStr \"black\"\n        , Text.onPath\n            [ M ( 10, 80 )\n                [ C ( 40, 10 ) ( 65, 10 ) ( 95, 80 ) ]\n            ]\n        ]\n        { x = 0, y = 0, anchor = Evg.Start }\n        \"Text along a curve\"\n\nThis draws the sentence climbing up and over an arch. The path itself stays\ninvisible; only the text shows. Text that is longer than the path gets cut\noff at the path's end.\n\n","type":"List.List Evg.Path.Path -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"richText","comment":" Renders several styled runs of text as one continuous line. Each run\ncan have its own color, size, and font, but they flow together as a single\npiece of text.\n\nThe position works like `Evg.text`: the text is placed at the point\n`( x, y )`, with `anchor` deciding whether that point is at the left edge\nof the text (`Start`), its center (`Middle`), or its right edge (`End`).\nThe point sits on the baseline, so the letters rest on top of the `y`\ncoordinate you give.\n\n    Text.richText [ Evg.fontSize 16 ]\n        { x = 10, y = 30, anchor = Evg.Start }\n        [ Text.tspan [ Evg.fillStr \"black\" ] \"Normal \"\n        , Text.tspan [ Evg.fillStr \"blue\" ] \"blue \"\n        , Text.tspan [ Evg.fillStr \"black\" ] \"normal\"\n        ]\n\nThis shows one line of text starting at (10, 30) with only its middle word\nin blue.\n\n","type":"List.List (Evg.Attribute { a | text : Evg.Supported } msg) -> { x : Basics.Float, y : Basics.Float, anchor : Evg.TextAnchor } -> List.List (Evg.Text.Span msg) -> Evg.Evg msg"},{"name":"textDecoration","comment":" Draws a decorative line on the text: underneath it, above it, or\nstriking through it.\n\n    Text.textDecoration Text.Underline\n\nThis underlines the text.\n\n","type":"Evg.Text.TextDecoration -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"textLength","comment":" Forces text to occupy exactly the given width, stretching or squeezing\nit as needed. Useful when text must line up with something of a fixed size,\nsuch as filling the full width of a button or column regardless of how many\nletters it contains. The second argument controls whether only the gaps\nbetween letters change or the letters themselves deform too.\n\n    Text.textLength 200 Text.SpacingAndGlyphs\n\nThis makes the text exactly 200 units wide, stretching both the letters and\nthe spaces between them.\n\n","type":"Basics.Float -> Evg.Text.LengthAdjust -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"tspan","comment":" Creates a styled run of text. Use within `richText` to give different\nparts of the same line their own color, size, weight, or font. The runs\nflow one after another as a single piece of text.\n\n    Text.tspan [ Evg.fillStr \"red\", Evg.fontSize 24 ]\n        \"important\"\n\nThis produces the word \"important\" in large red letters wherever it falls\nwithin the surrounding text.\n\n","type":"List.List (Evg.Attribute { a | text : Evg.Supported } msg) -> String.String -> Evg.Text.Span msg"},{"name":"wordSpacing","comment":" Adjusts the space between words, leaving the letters within each word\nuntouched. Positive values push the words apart, negative values pull them\ntogether.\n\n    Text.wordSpacing 5\n\nThis adds 5 units of extra space at every gap between words.\n\n","type":"Basics.Float -> Evg.Attribute { a | text : Evg.Supported } msg"},{"name":"writingMode","comment":" Controls whether text is written horizontally or vertically.\n\n    Text.writingMode Text.VerticalRL\n\nThis makes the text run from top to bottom, as in traditional Japanese\nlayout.\n\n","type":"Evg.Text.WritingMode -> Evg.Attribute { a | text : Evg.Supported } msg"}],"binops":[]},{"name":"Evg.Transform","comment":" Move, rotate, resize, and slant shapes.\n\nTransforms change where and how a shape is drawn without changing the\nnumbers that define it. You describe the shape once, then use transforms to\nplace it, spin it, or stretch it.\n\nYou can list several transforms on the same shape and they combine into one.\nThe transform listed last takes effect on the shape first. In the second\nexample below, the square is first rotated around the corner of the picture\nand then moved into place, which is the usual recipe for rotating a shape\n\"in place\" (though `rotateAround` does this in one step).\n\n    import Evg\n    import Evg.Transform as Transform\n\n    -- Move a square 50 units to the right:\n    Evg.rect [ Transform.translate 50 0 ]\n        { x = 0, y = 0, width = 40, height = 40 }\n\n    -- A square rotated 45 degrees, sitting at (50, 50):\n    Evg.rect\n        [ Transform.translate 50 50\n        , Transform.rotate 45\n        ]\n        { x = -20, y = -20, width = 40, height = 40 }\n\n@docs translate, rotate, rotateAround, scale, scaleUniform\n@docs skewX, skewY, matrix\n\n","unions":[],"aliases":[],"values":[{"name":"matrix","comment":" The escape hatch: applies an arbitrary 2D transformation given as six\nnumbers. `matrix a b c d e f` moves each point `(x, y)` of the shape to\n`(a*x + c*y + e, b*x + d*y + f)`. Every combination of moving, rotating,\nscaling, and slanting can be written this way.\n\nMost of the time you will not need this. The other functions in this module\ncover the common cases with friendlier names.\n\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"rotate","comment":" Rotates a shape clockwise by the given angle in degrees. The rotation\npivots around the top-left corner of the picture, the `(0, 0)` point, not\naround the shape's own center. A shape far from that corner will swing\naround it like the tip of a clock hand. If you want a shape to spin in\nplace, use `rotateAround` with the shape's center instead.\n\n    Transform.rotate 90 -- quarter turn clockwise\n\n![rotate example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/transform-rotate-example.svg)\n\nThe grey square is the original and the blue square has been rotated 30\ndegrees around the top-left corner of the picture.\n\n","type":"Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"rotateAround","comment":" Rotates a shape clockwise by the given angle in degrees, pivoting around\nthe point you give. Pass the shape's own center to spin it in place. This is\nusually what you want when \"rotating a shape\".\n\n    Transform.rotateAround 45 ( 50, 50 )\n\n![rotateAround example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/transform-rotate-around-example.svg)\n\nThe grey square is the original and the blue square has been rotated 45\ndegrees around its own center, so it stays put and just turns.\n\n","type":"Basics.Float -> ( Basics.Float, Basics.Float ) -> Evg.Internal.Attribute { a | transform : Evg.Internal.Supported } msg"},{"name":"scale","comment":" Stretches or squashes a shape, with separate factors for width and\nheight. A factor of `1.0` means no change, `2.0` doubles that dimension,\nand `0.5` halves it.\n\nDistances from the top-left corner of the picture are scaled too, so a shape\nthat does not touch that corner also moves as it grows or shrinks.\n\n    -- twice as wide, same height:\n    Transform.scale 2.0 1.0\n\n![scale example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/transform-scale-example.svg)\n\nThe grey square is the original and the blue rectangle is the same square\nstretched to twice its width.\n\n","type":"Basics.Float -> Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"scaleUniform","comment":" Grows or shrinks a shape by the same factor in both directions, keeping\nits proportions.\n\n    Transform.scaleUniform 0.5 -- shrink to half size\n\n","type":"Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"skewX","comment":" Slants a shape sideways by the given angle in degrees, like pushing a\ndeck of cards sideways so it leans. A square becomes a leaning\nparallelogram; its vertical edges tilt while its horizontal edges stay\nlevel. The further a point is from the top of the picture, the further it\nshifts sideways.\n\n    Transform.skewX 20\n\n![skewX example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/transform-skew-x-example.svg)\n\nThe grey square is the original and the blue parallelogram is the same\nsquare slanted 20 degrees to the side.\n\n","type":"Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"skewY","comment":" Slants a shape up or down by the given angle in degrees. This is the\nvertical partner of `skewX`: a square's horizontal edges tilt while its\nvertical edges stay upright, and the further a point is from the left of\nthe picture, the further it shifts down.\n\n    Transform.skewY 10\n\n","type":"Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"},{"name":"translate","comment":" Moves a shape sideways and down without changing its size or angle.\nPositive values move right and down, negative values move left and up.\n\n    -- move 100 right, 50 down:\n    Transform.translate 100 50\n\n![translate example](https://raw.githubusercontent.com/gampleman/evg/master/docs/images/transform-translate-example.svg)\n\nThe grey square is the original position and the blue square is the result.\n\n","type":"Basics.Float -> Basics.Float -> Evg.Attribute { a | transform : Evg.Supported } msg"}],"binops":[]}]